引言:
经过在网络上的广泛搜索和比较,我了解了一款基于C/C++的公司职工管理系统软件,这款软件在基本功能方面表现相当完善,能够满足日常的使用需求。然而,在实际使用过程中,我也发现它存在一些问题和不足,所以我决定对该软件进行二次开发。
原始代码:
点击查看代码
**main.cpp**
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
#include "EmployeeManager.h"
int main() {
EmployeeManager manager;
int choice;
while (true) {
manager.show_menu();
cin >> choice;
switch (choice) {
case 1:
manager.AddEmployee();
break;
case 2:
manager.DeleteEmployee();
break;
case 3:
manager.UpdateEmployee();
break;
case 4:
manager.reseachStudentByName();
break;
case 5:
manager.reseachStudentByOffice();
break;
case 6:
manager.avgsalary();
break;
case 7:
manager.exitsystem();
default:
cout << "输入有误,请重新选择" << endl;
break;
}
system("pause");
system("cls");
}
return 0;
}
**EmployeeManager.h**
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
#include "Employee.h"
#define EMPLOYEEFILE "employee.txt"
class EmployeeManager {
private:
Employee* employees; // 存储所有职工信息的数组
int count; // 记录当前职工数
int capacity; // 数组容量(最大职工数)
public:
EmployeeManager();
~EmployeeManager();
void show_menu();//菜单
void AddEmployee();// 添加职工信息
void DeleteEmployee(); // 删除职工信息
void UpdateEmployee(); // 修改职工信息
void reseachStudentByName();// 按姓名查询职工信息
void reseachStudentByOffice();// 按科室查询职工信息
void avgsalary();// 统计平均工资
void SaveInfo();// 保存职工信息到文件
void expand(); // 扩容(double)
void loadFromFile(); // 从文件中加载职工信息
void exitsystem();
};
**EmployeeManager.cpp**
#include "EmployeeManager.h"
EmployeeManager::EmployeeManager() {
employees = new Employee[10]; // 初始数组长度为10
count = 0;
capacity = 10;
loadFromFile();
}
EmployeeManager::~EmployeeManager() {
delete[] employees; // 释放内存
}
void EmployeeManager::show_menu(){
cout << "*****欢迎使用公司职工管理系统*****"<<endl;
cout << "* 请选择需要进行的操作: *" << endl;
cout << "* 1.添加职工信息 *" << endl;
cout << "* 2.删除职工信息 *" << endl;
cout << "* 3.修改职工信息 *" << endl;
cout << "* 4.按姓名查询职工信息 *" << endl;
cout << "* 5.按科室查询职工信息 *" << endl;
cout << "* 6.按科室统计平均工资 *" << endl;
cout << "* 7.退出系统 *" << endl;
cout << "**********************************" << endl;
}
void EmployeeManager::AddEmployee() {
if (count == capacity) {
expand(); // 扩容后添加
}
int id_;
string name_, sex_, phone_, office_;
float salary_;
cout << "请输入新员工信息:" << endl;
cout << "工号:";
cin >> id_;
while (cin.fail()) { // 输入错误处理
cin.clear();
cin.ignore();
cout << "请输入工号:" << endl;
cin >> id_;
}
for (int i = 0; i < count; i++) {// 检查工号是否已存在
if (employees[i].id == id_) {
cout << "工号已存在,请重新输入:" << endl;
cin >> id_;
i = -1; // 重新循环开始检查
}
}
cout << "请输入姓名:";
cin >> name_;
cout << "请输入性别:";
cin >> sex_;
cout << "请输入电话:";
cin >> phone_;
cout << "请输入科室(其中包含 办公室,技术部,市场部,财务部,人事部):";
cin >> office_;
cout << "请输入工资:";
cin >> salary_;
while (cin.fail()) { // 输入错误处理
cin.clear();
cin.ignore();
cout << "请输入正确的工资:" << endl;
cin >> salary_;
}
employees[count] = Employee(id_, name_, sex_, phone_, office_, salary_);
count++;
SaveInfo();
cout << "添加成功!" << endl;
}
void EmployeeManager::DeleteEmployee() {
if (count == 0) {
cout << "目前系统内没有员工信息" << endl;
return;
}
int id_;
cout << "请输入要删除的员工工号:" << endl;
cin >> id_;
for (int i = 0; i < count; i++) { // 遍历数组查找
if (employees[i].id == id_) {
for (int j = i; j < count - 1; j++) { // 删除并移动数组
employees[j] = employees[j + 1];
}
count--;
SaveInfo();
cout << "删除成功!" << endl;
return;
}
}
cout << "未找到该员工信息" << endl;
}
void EmployeeManager::UpdateEmployee() {
if (count == 0) {
cout << "目前系统内没有员工信息" << endl;
return;
}
int id_;
cout << "请输入要修改的员工工号:" << endl;
cin >> id_;
for (int i = 0; i < count; i++) { // 遍历数组查找
if (employees[i].id == id_) {
string name_, sex_, phone_, office_;
float salary_;
cout << "请输入修改后的姓名(原名字:"<<employees[i].name<<"):";
cin >> name_;
cout << "请输入修改后的性别(原性别:"<<employees[i].sex<<"):";
cin >> sex_;
cout << "请输入修改后的电话(原电话:"<<employees[i].phone<<"):";
cin >> phone_;
cout << "请输入修改后的科室(原科室:"<<employees[i].office<<"):";
cin >> office_;
cout << "请输入修改后的工资(原工资:"<<employees[i].salary<<"):";
cin >> salary_;
while (cin.fail()) { // 输入错误处理
cin.clear();
cin.ignore();
cout << "请输入正确的工资:" << endl;
cin >> salary_;
}
employees[i].name = name_;
employees[i].sex = sex_;
employees[i].phone = phone_;
employees[i].office = office_;
employees[i].salary = salary_;
SaveInfo();
cout << "修改成功!" << endl;
return;
}
}
cout << "未找到该员工信息" << endl;
}
void EmployeeManager::reseachStudentByName() {
if (count == 0) {
cout << "目前系统内没有员工信息" << endl;
return;
}
string name_;
cout << "请输入要查找的员工姓名:" << endl;
cin >> name_;
bool found = false;
for (int i = 0; i < count; i++) { // 遍历数组查找
if (employees[i].name == name_) {
employees[i].show_data();
found = true;
}
}
if (!found) {
cout << "未找到该员工信息" << endl;
}
}
void EmployeeManager::reseachStudentByOffice() {
if (count == 0) {
cout << "目前系统内没有员工信息" << endl;
return;
}
string office_;
cout << "请输入要查找的员工科室:" << endl;
cin >> office_;
bool found = false;
for (int i = 0; i < count; i++) {
if (employees[i].office == office_) {
employees[i].show_data();
found = true;
}
}
if (!found) {
cout << "未找到该科室的员工信息" << endl;
}
}
void EmployeeManager::avgsalary() {
if (count == 0) {
cout << "目前系统内没有员工信息" << endl;
return;
}
string offices[] = { "办公室", "人事部","技术部", "财务部" , "市场部"};
float salaries[] = {0, 0, 0, 0, 0};
int counts[] = { 0, 0, 0, 0, 0 };
for(int i = 0;i<count;i++){
for(int j = 0;j<5;j++){
if(employees[i].get_office() == offices[j]){
salaries[j] += employees[i].get_salary();
counts[j]++;
}
}
}
cout << "统计结果如下:" << endl;
cout << left << setw(15) <<"科室名称"<< setw(15)<<"总人数"<< setw(15)<<"平均工资" << endl;
for (int i = 0; i < 5; i++) {
if (counts[i] == 0) continue;
float avgsalary = salaries[i] / counts[i];
cout <<left << setw(15)<< offices[i] <<setw(15)<<counts[i]<<setw(15)<< avgsalary << endl;
}
}
void EmployeeManager::expand() {
capacity *= 2;
Employee* newArray = new Employee[capacity];
for (int i = 0; i < count; i++) {
newArray[i] = employees[i];
}
delete[] employees;
employees = newArray;
}
void EmployeeManager::loadFromFile() {
ifstream ifs;
ifs.open(EMPLOYEEFILE, ios::in);
if (!ifs) {
return;
}
int id_;
string name_, sex_, phone_, office_;
float salary_;
while (ifs >> id_ >> name_ >> sex_ >> phone_ >> office_ >> salary_) { // 从文件中读取职工信息
employees[count] = Employee(id_, name_, sex_, phone_, office_, salary_);
count++;
}
ifs.close();
}
void EmployeeManager::SaveInfo() {
ofstream ofs;
ofs.open(EMPLOYEEFILE, ios::out);
for (int i = 0; i < count; i++) { // 将职工信息写入文件
ofs << employees[i].id << " " << employees[i].name << " " << employees[i].sex << " " << employees[i].phone << " " << employees[i].office << " " << employees[i].salary << endl;
}
ofs.close();
}
void EmployeeManager::exitsystem(){
exit(0);
}
**employee.h**
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
class Employee {
public:
int id; // 工号
string name; // 姓名
string sex; // 性别
string phone; // 电话
string office; // 所在科室
float salary; // 工资
Employee();
Employee(int id_, string name_, string sex_, string phone_, string office_, float salary_);
void show_data();
string get_office();
float get_salary();
};
**Employee.cpp**
#include "Employee.h"
Employee::Employee(){
id = 0;
name = "";
sex = "";
phone = "";
office = "";
salary = 0;
}
Employee::Employee(int id_, string name_, string sex_, string phone_, string office_, float salary_){
id = id_;
name = name_;
sex = sex_;
phone = phone_;
office = office_;
salary = salary_;
}
void Employee::show_data(){
cout << "工号:" << id << "\t姓名:" << name << "\t性别:" << sex << "\t电话:" << phone << "\t科室:" << office << "\t工资:" << salary << endl;
}
string Employee::get_office(){
return office;
}
float Employee::get_salary(){
return salary;
}
程序主页面
以下是我对该软件的二次开发:
1.添加一个登录密码的界面。
原因:考虑到这款软件作为一个公司职工管理系统,其安全性是至关重要的。为了确保只有授权人员能够访问和操作职工信息,我计划为其增加一个登录密码界面。这样一来,没有相应权限的人员将无法进入系统,从而有效防止了信息泄露和误操作的风险。通过这一改进,我们不仅能够提升系统的安全性,还能为公司职工信息提供更加可靠的保障。
该密码验证我是用MD5加盐加密进行验证,输入的密码进行加密后和正确的密码的密文进行匹对。
md5加密代码
点击查看代码
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
using namespace std;
#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
const char str16[] = "0123456789abcdef";
const unsigned int T[] = {
0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
0x6b901122,0xfd987193,0xa679438e,0x49b40821,
0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 };
const unsigned int s[] = { 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21};
class MD5 {
private:
unsigned int tempA, tempB, tempC, tempD, strlength;
public:
string rightPass = "2ee2e1729baf76c0f6e81a7d04a0f435";
MD5() {
tempA = A;
tempB = B;
tempC = C;
tempD = D;
strlength = 0;
}
// F函数
unsigned int F(unsigned int b, unsigned int c, unsigned int d) {
return (b & c) | ((~b) & d);
}
// G函数
unsigned int G(unsigned int b, unsigned int c, unsigned int d) {
return (b & d) | (c & (~d));
}
// H函数
unsigned int H(unsigned int b, unsigned int c, unsigned int d) {
return b ^ c ^ d;
}
// I函数
unsigned int I(unsigned int b, unsigned int c, unsigned int d) {
return c ^ (b | (~d));
}
// 移位操作函数
unsigned int shift(unsigned int a, unsigned int n) {
return (a << n) | (a >> (32 - n));
}
// 编码函数
string encode(string src) {
vector<unsigned int> rec = padding(src);
for(unsigned int i = 0; i < strlength/16; i++) {
unsigned int num[16];
for(int j = 0; j < 16; j++) {
num[j] = rec[i*16+j];
}
iterateFunc(num, 16);
}
return format(tempA) + format(tempB) + format(tempC) + format(tempD);
}
// 循环压缩
void iterateFunc(unsigned int* X, int size = 16) {
unsigned int a = tempA,
b = tempB,
c = tempC,
d = tempD,
rec = 0,
g, k;
for(int i = 0; i < 64; i++) {
if(i < 16) {
// F迭代
g = F(b, c, d);
k = i;
}
else if(i < 32) {
// G迭代
g = G(b, c, d);
k = (1 + 5*i) % 16;
}
else if(i < 48) {
// H迭代
g = H(b, c, d);
k = (5 + 3*i) % 16;
}
else {
// I迭代
g = I(b, c, d);
k = (7*i) % 16;
}
rec = d;
d = c;
c = b;
b = b + shift(a + g + X[k] + T[i], s[i]);
a = rec;
}
tempA += a;
tempB += b;
tempC += c;
tempD += d;
}
// 填充字符串
vector<unsigned int> padding(string src) {
// 以512位,64个字节为一组
unsigned int num = ((src.length() + 8) / 64) + 1;
vector<unsigned int> rec(num*16);
strlength = num*16;
for(unsigned int i = 0; i < src.length(); i++){
// 一个unsigned int对应4个字节,保存4个字符信息
rec[i>>2] |= (int)(src[i]) << ((i % 4) * 8);
}
// 补充1000...000
rec[src.length() >> 2] |= (0x80 << ((src.length() % 4)*8));
// 填充原文长度
rec[rec.size()-2] = (src.length() << 3);
return rec;
}
// 整理输出
string format(unsigned int num) {
string res = "";
unsigned int base = 1 << 8;
for(int i = 0; i < 4; i++) {
string tmp = "";
unsigned int b = (num >> (i * 8)) % base & 0xff;
for(int j = 0; j < 2; j++) {
tmp = str16[b%16] + tmp;
b /= 16;
}
res += tmp;
}
return res;
}
};
修改后main.cpp代码
点击查看代码
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <string.h>
using namespace std;
#include "EmployeeManager.h"
#include "function.h"
int main() {
while(true){
cout<<"请输入管理员密码:"<<endl;
MD5 jiami;
string enterPass;
cin >> enterPass;
string enterPass1 = jiami.encode(jiami.encode(enterPass)+enterPass);
if(enterPass1 == jiami.rightPass){
cout<<"密码正确"<<endl;
system("pause");
system("cls");
EmployeeManager manager;
int choice;
while (true) {
manager.show_menu();
cin >> choice;
switch (choice) {
case 1:
manager.AddEmployee();
break;
case 2:
manager.DeleteEmployee();
break;
case 3:
manager.UpdateEmployee();
break;
case 4:
manager.reseachStudentByName();
break;
case 5:
manager.reseachStudentByOffice();
break;
case 6:
manager.avgsalary();
break;
case 7:
manager.exitsystem();
default:
cout << "输入有误,请重新选择" << endl;
break;
}
system("pause");
system("cls");
}
}
else{
cout<< "密码错误,请重新输入"<<endl;
system("pause");
system("cls");
}
}
return 0;
}
**2. **对用户输入信息检验是否有效。
原代码 cout << "请输入姓名:"; cin >> name_; cout << "请输入性别:"; cin >> sex_; cout << "请输入电话:"; cin >> phone_; cout << "请输入科室(其中包含 办公室,技术部,市场部,财务部,人事部):"; cin >> office_;
均没有检验数据是否正确,这难免造成小错误或者记录数据不正确
修改后代码
点击查看代码
// 输入姓名
do {
cout << "请输入姓名:";
cin >> name_;
if (name_.empty()) {
cout << "姓名不能为空,请重新输入!" << endl;
}
} while (name_.empty());
// 输入性别
do {
cout << "请输入性别:";
cin >> sex_;
if (sex_ != "男" && sex_ != "女") {
cout << "性别必须为'男'或'女',请重新输入!" << endl;
}
} while (sex_ != "男" && sex_ != "女");
// 输入电话
do {
cout << "请输入电话:";
cin >> phone_;
if(phone_.size() != 11){
cout<<"手机号输入不正确"<<endl;
}
// 这里可以根据电话号码的规则进行更复杂的检验,例如检查是否只包含数字
if (phone_.empty()) {
cout << "电话不能为空,请重新输入!" << endl;
}
} while (phone_.empty()||phone_.size() != 11);
// 输入科室
string validOffices[] = {"办公室", "技术部", "市场部", "财务部", "人事部"};
bool isValidOffice = false;
do {
cout << "请输入科室(其中包含 办公室,技术部,市场部,财务部,人事部):";
cin >> office_;
for (int i=0;i<5;i++) {
if (office_ == validOffices[i]) {
isValidOffice = true;
break;
}
}
if (!isValidOffice) {
cout << "科室输入无效,请输入:办公室,技术部,市场部,财务部,人事部中的一个!" << endl;
}
} while (!isValidOffice);
运行结果
其他问题
该软件在可视化和数据存储方面存在明显不足。目前,整个系统主要依赖菜单形式进行展示,并且数据被不安全地存储在txt文件中。最初,我计划使用Java GUI和MySQL数据库来提升管理员体验和数据安全性,但由于技术和时间上的限制,二次开发工作未能顺利继续。若条件允许,我将不遗余力地继续推进该软件的二次开发,以优化用户界面和数据存储方式,确保软件的稳定性和安全性。
二次开发心得
经过对公司职工管理系统软件的二次开发实践,我深刻体会到,模块化设计和详尽的代码注释对于软件后期的维护、扩展以及性能提升具有决定性的作用。同时,我也意识到,无论是对外还是对内使用的软件,用户输入的安全性都是不容忽视的。为了防止输入渗透,我们必须严格限制输入的范围,并采取有效措施确保数据存储的安全。在满足软件功能需求的基础上,我们还应致力于持续优化用户界面,提升可视化布局和美化程度,以提供更加友好、直观的用户体验。
二次开发流程图