一、设计题目
1.设计目的
全面系统的学习面向对象程序设计的基本概念、基本语法和编程方法。正确理解掌握C++面向对象程序设计的基本特性:类、对象、继承与派生、多态、虚函数、模板、流类库等。遵循软件过程的各个环节进行系统分析、设计、实现、集成、测试。了解当前常用的软件开发工具,要求熟练掌握基于类的程序设计,培养解决实际问题的能力。
2.题目背景:人事管理系统
程序应采用面向对象的程序设计方法,程序应提供人员信息的输入、删除、查找、修改等基本功能,并且能够按部门进行各项分类统计,对各部门进行排序和筛选等操作。
在本程序中,人事管理系统将人员分为两个部门,每个部门均有添加员工、删除员工、修改员工信息、按照工资多少排序输出、按照工资多少筛选员工、按编号查找员工、写入和读取文件的功能。设置人事部为基类,员工信息有编号、姓名、工资;销售部为派生类,员工信息除了编号、姓名、工资,还加入了新的信息:奖金。因此在主函数下选择部门时,应用了虚函数,体现了多态性;在每步改动人员信息之后均会写入进文件,在打开程序时会自动读取文件。
二、需求分析
1.功能结构图
2.设计流程图
(1)添加员工 Add_member()
首先输入要添加的员工人数n(若n超出了可添加的范围,则返回重新输入),进入for循环,在总数total之后(total初值默认为0)循环n次,依次添加n个员工的编号、姓名、工资(销售部还包括奖金),每次total的值增加1。在输入编号时,通过for循环首先遍历已存在的total个员工的编号,若存在编号与刚刚录入的编号相等,则提示已有该编号,返回重新输入。
每次输入某员工信息完成后,文件指针从开头移动total个员工信息单位的长度,将信息写入到文件尾。
(2)删除员工 Delete_member()
输入要删除的员工的编号,通过for循环遍历total个员工的数据,若第i 个员工与其编号相等,则将该员工数据删除(删除方法:使用for循环,从i开始,用第i+1个员工的数据覆盖掉第i个员工的数据,以此类推,之后的员工数据都往前移动一位),total的值减去1;若遍历后没有找到该编号,则输出无此员工。
利用ios::out方式打开文件,即打开后清空数据。在删除该员工数据后,通过for循环重新从头开始写入每个员工的数据。
(3)修改员工信息 Change_member()
输入要修改的员工的编号,通过for循环遍历total个员工的数据,若第i 个员工与其编号相等,则首先输出该员工信息做参考,之后重新输入该员工数据;若遍历后没有找到该编号,则输出无此员工。
重新输入第i个员工的数据后,将文件指针从开头移动i个员工信息单位的长度,将修改后的该员工信息写入文件。
(4)按工资排序输出 Sort_by_wage()
通过for循环,将员工数据复制进新的结构体数组,用冒泡排序(从第total个员工开始,将其与前一个员工的工资进行比较,若大于则相互交换;total轮循环后,工资数最大的员工在第一个;再比较当前的第total个员工与total-1个员工,total-1轮循环后,工资数第二的员工在第二个……以此类推)按照工资(销售部是工资+奖金)的值的大小排序完成,最后用for循环从新的数组中输出排序好的员工信息。
(5)按工资筛选员工 Screen_by_wage()
定义统计人数的变量k,k初始化为0;输入筛选的起始点a和终止点b(若输入的b比a要小,返回重新输入),用for循环遍历total个员工数据,若员工工资的值在a ~ b范围内,输出该员工的数据,k+1;如果循环结束后k=0,即没有任何员工的工资的值在a ~ b范围内,则输出无该工资区间的员工。
(6)按编号查找员工 LookUp_by_number()
定义统计人数的变量k,k初始化为0;输入要查找的员工的编号,用for循环遍历total个员工的数据,若找到与其相等的编号,则输出该员工信息,k+1,终止循环;若遍历结束后k=0,即没有找到该编号,则输出无此员工。
完整代码
//2019-2020学年第一学期 面向对象程序设计综合实训(C++)
#include
#include
#include
#include
using namespace std;
struct Member//员工信息
{
char number[20];//员工编号
char name[20];//员工姓名
double wage;//工资
};
class Base//人事部
{
protected:
Member member[20];//员工信息
int total;//总人数
public:
Base(){total=0;}
virtual void Add_member();//添加员工
virtual void Delete_member();//删除员工
virtual void Change_member();//修改员工信息
virtual void Sort_by_wage(); //按工资排序
virtual void Screen_by_wage(); //按工资筛选
virtual void LookUp_by_number(); //按编号查找
void Outfile_Base();//写入文件
void Infile_Base();//读取文件
};
class Department1:public Base //销售部
{
private:
double bonus[20];//奖金
public:
Department1(){total=0;}
void Add_member();//添加员工
void Delete_member();//删除员工
void Change_member();//修改员工信息
void Sort_by_wage();//按工资+奖金排序
void Screen_by_wage();//按工资+奖金筛选
void LookUp_by_number(); //按编号查找
void Outfile_Department();//写入文件
void Infile_Department();//读取文件
};
void Base::Add_member()
{
int n,i,j,w;
w=total;
cout<<"请输入将要添加的员工人数:";
leap11:
cin>>n;
if(n>20-total)
{
cout<<"添加人数超出可记录范围(20个),请重新输入:";
goto leap11;
}
fstream iofile("information_base.dat",ios::in|ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=w;i<w+n;i++)
{
cout<<"请输入员工编号:";
leap12:
cin>>member[i].number;
for(j=0;j<w;j++)
{
if(strcmp(member[i].number,member[j].number)==0)
{
cout<<"已有该编号员工!请重新输入:";
goto leap12;
}
}
cout<<"请输入员工姓名:";
cin>>member[i].name;
cout<<"请输入该员工工资:";
cin>>member[i].wage;
iofile.seekp(i*sizeof(member[i]),ios::beg);
iofile.write((char*)&member[i],sizeof(member[i]));
cout<<"文件写入成功!"<<endl;
iofile.close();
total++;
}
cout<<"添加完成!"<<endl;
}
void Base::Delete_member()
{
int i,j,w,k=0;
w=total;
char n[20];
cout<<"请输入将要删除的员工的编号:";
cin>>n;
fstream iofile("information_base.dat",ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=0;i<w;i++)
{
if(strcmp(n,member[i].number)==0)
{
for(j=i+1;j<w;j++)
{
member[j-1]=member[j];
}
total--;
k++;
break;
}
}
iofile.seekp(i*sizeof(member[i]),ios::beg);
for(j=0;j<w-1;j++)
{
iofile.write((char*)&member[j],sizeof(member[j]));
}
cout<<"文件写入成功!"<<endl;
iofile.close();
if(k==0) cout<<"无此编号员工!";
else cout<<"删除完成!"<<endl;
}
void Base::Change_member()
{
int i,t,k=0;
t=total;
char n[20];
cout<<"请输入将要修改的员工的编号:";
cin>>n;
fstream iofile("information_base.dat",ios::in|ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=0;i<t;i++)
{
if(strcmp(n,member[i].number)==0)
{
cout<<"当前员工姓名:"<<member[i].name<<" 工资:"<<member[i].wage<<endl;
cout<<"请输入修改后员工姓名:";
cin>>member[i].name;
cout<<"请输入修改后该员工工资:";
cin>>member[i].wage;
iofile.seekp(i*sizeof(member[i]),ios::beg);
iofile.write((char*)&member[i],sizeof(member[i]));
cout<<"文件写入成功!"<<endl;
iofile.close();
k++;
break;
}
}
if(k==0) cout<<"无此编号员工!";
else cout<<"修改完成!"<<endl;
}
void Base::Sort_by_wage()
{
int i,j;
Member t;
Member mem2[20];
for(i=0;i<total;i++) mem2[i]=member[i];
for(i=0;i<total;i++)
{
for(j=total-1;j>i;j--)
{
if(mem2[j].wage<mem2[j-1].wage)
{t=mem2[j];mem2[j]=mem2[j-1];mem2[j-1]=t;}
}
}
cout<<"***************************************************************"<<endl;
for(i=total-1;i>=0;i--)
{
cout<<"员工编号:"<<mem2[i].number<<setw(15)<<"员工姓名:"<<mem2[i].name
<<setw(15)<<"工资:"<<mem2[i].wage<<endl;
}
cout<<"***************************************************************"<<endl;
}
void Base::Screen_by_wage()
{
int i,k=0;
double a,b;
cout<<"请输入工资区域起始点(最小值):";
cin>>a;
cout<<"请输入工资区域截止点(最大值):";
leap51:
cin>>b;
if(b<a)
{
cout<<"输入有误,请输入比起始点大的数字:";
goto leap51;
}
cout<<"***************************************************************"<<endl;
for(i=0;i<total;i++)
{
if(member[i].wage>=a&&member[i].wage<=b)
{
k++;
cout<<"员工编号:"<<member[i].number<<setw(15)<<"员工姓名:"<<member[i].name
<<setw(15)<<"工资:"<<member[i].wage<<endl;
}
}
if(k==0) cout<<"无该工资区间的员工!"<<endl;
cout<<"***************************************************************"<<endl;
}
void Base::LookUp_by_number()
{
int i,k=0;
char n[20];
cout<<"请输入将要查找的员工的编号:";
cin>>n;
for(i=0;i<total;i++)
{
if(strcmp(n,member[i].number)==0)
{
k++;
cout<<"当前员工姓名:"<<member[i].name<<" 工资:"<<member[i].wage<<endl;
break;
}
}
if(k==0) cout<<"无此编号的员工!"<<endl;
}
void Base::Outfile_Base()
{
ofstream outfile("information_base.dat",ios::binary);
if(!outfile) cerr<<"文件写入错误,请重试!"<<endl;
else
{
for(int i=0;i<total;i++)
{
outfile.write((char*)&member[i],sizeof(member[i]));
}
outfile.close();
cout<<"文件写入成功!"<<endl;
}
}
void Base::Infile_Base()
{
int i=0;
ifstream infile("information_base.dat",ios::binary);
if(!infile) cerr<<"文件读取错误,请重试!"<<endl;
else
{
while(infile.peek()!=EOF)
{
infile.read((char*)&member[i],sizeof(member[i]));
i++;
total++;
}
infile.close();
cout<<"文件读取成功!当前人事部有"<<total<<"个员工的数据,";
}
}
void Department1::Add_member()
{
int n,i,j,w;
w=total;
cout<<"请输入将要添加的员工人数:";
leap13:
cin>>n;
if(n>20-total)
{
cout<<"添加人数超出可记录范围(20个),请重新输入:";
goto leap13;
}
fstream iofile("information_department.dat",ios::in|ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=w;i<w+n;i++)
{
cout<<"请输入员工编号:";
leap14:
cin>>member[i].number;
for(j=0;j<w;j++)
{
if(strcmp(member[i].number,member[j].number)==0)
{
cout<<"已有该编号员工!请重新输入:";
goto leap14;
}
}
cout<<"请输入员工姓名:";
cin>>member[i].name;
cout<<"请输入该员工工资:";
cin>>member[i].wage;
cout<<"请输入该员工奖金:";
cin>>bonus[i];
iofile.seekp(i*(sizeof(member[i])+sizeof(bonus[i])),ios::beg);
iofile.write((char*)&member[i],sizeof(member[i]));
iofile.write((char*)&bonus[i],sizeof(bonus[i]));
cout<<"文件写入成功!"<<endl;
iofile.close();
total++;
}
cout<<"添加完成!"<<endl;
}
void Department1::Delete_member()
{
int i,j,w,k=0;
w=total;
char n[20];
cout<<"请输入将要删除的员工的编号:";
cin>>n;
fstream iofile("information_department.dat",ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=0;i<w;i++)
{
if(strcmp(n,member[i].number)==0)
{
for(j=i+1;j<w;j++)
{
member[j-1]=member[j];
bonus[j-1]=bonus[j];
}
total--;
k++;
break;
}
}
iofile.seekp(i*(sizeof(member[i])+sizeof(bonus[i])),ios::beg);
for(j=0;j<w-1;j++)
{
iofile.write((char*)&member[j],sizeof(member[j]));
iofile.write((char*)&bonus[j],sizeof(bonus[j]));
}
cout<<"文件写入成功!"<<endl;
iofile.close();
if(k==0) cout<<"无此编号员工!";
else cout<<"删除完成!"<<endl;
}
void Department1::Change_member()
{
int i,k=0;
char n[20];
cout<<"请输入将要修改的员工的编号:";
cin>>n;
fstream iofile("information_department.dat",ios::in|ios::out|ios::binary);
if(!iofile) cerr<<"文件打开失败!"<<endl;
for(i=0;i<total;i++)
{
if(strcmp(n,member[i].number)==0)
{
cout<<"当前员工姓名:"<<member[i].name<<" 工资:"<<member[i].wage<<" 奖金:"<<bonus[i]<<endl;
cout<<"请输入修改后员工姓名:";
cin>>member[i].name;
cout<<"请输入修改后该员工工资:";
cin>>member[i].wage;
cout<<"请输入修改后该员工奖金:";
cin>>bonus[i];
iofile.seekp(i*(sizeof(member[i])+sizeof(bonus[i])),ios::beg);
iofile.write((char*)&member[i],sizeof(member[i]));
iofile.write((char*)&bonus[i],sizeof(bonus[i]));
cout<<"文件写入成功!"<<endl;
k++;
break;
}
}
if(k==0) cout<<"无此编号员工!";
else cout<<"修改完成!"<<endl;
}
void Department1::Sort_by_wage()
{
int i,j;
Member t1;
Member mem2[20];
double t2;
double bou2[20];
for(i=0;i<total;i++)
{
mem2[i]=member[i];
bou2[i]=bonus[i];
}
for(i=0;i<total;i++)
{
for(j=total-1;j>i;j--)
{
if(mem2[j].wage+bou2[j]<mem2[j-1].wage+bou2[j-1])
{
t1=mem2[j];mem2[j]=mem2[j-1];mem2[j-1]=t1;
t2=bou2[j];bou2[j]=bou2[j-1];bou2[j-1]=t2;
}
}
}
cout<<"***************************************************************"<<endl;
for(i=total-1;i>=0;i--)
{
cout<<"员工编号:"<<mem2[i].number<<setw(15)<<"员工姓名:"<<mem2[i].name
<<setw(15)<<"工资:"<<mem2[i].wage<<setw(15)<<"奖金:"<<bou2[i]<<endl;
}
cout<<"***************************************************************"<<endl;
}
void Department1::Screen_by_wage()
{
int i,k=0;
double a,b;
cout<<"请输入工资+奖金区域起始点(最小值):";
cin>>a;
cout<<"请输入工资+奖金区域截止点(最大值):";
leap52:
cin>>b;
if(b<a)
{
cout<<"输入有误,请输入比起始点大的数字:";
goto leap52;
}
cout<<"***************************************************************"<<endl;
for(i=0;i<total;i++)
{
if(member[i].wage+bonus[i]>a&&member[i].wage+bonus[i]<b)
{
k++;
cout<<"员工编号:"<<member[i].number<<setw(15)<<"员工姓名:"<<member[i].name
<<setw(15)<<"工资:"<<member[i].wage<<setw(15)<<"奖金:"<<bonus[i]<<endl;
}
}
if(k==0) cout<<"无该工资+奖金区间的员工!"<<endl;
cout<<"***************************************************************"<<endl;
}
void Department1::LookUp_by_number()
{
int i,k=0;
char n[20];
cout<<"请输入将要查找的员工的编号:";
cin>>n;
for(i=0;i<total;i++)
{
if(strcmp(n,member[i].number)==0)
{
k++;
cout<<"当前员工姓名:"<<member[i].name<<" 工资:"<<member[i].wage<<" 奖金:"<<bonus[i]<<endl;
break;
}
}
if(k==0) cout<<"无此编号的员工!"<<endl;
}
void Department1::Outfile_Department()
{
ofstream outfile("information_department.dat",ios::binary);
if(!outfile) cerr<<"文件写入错误,请重试!"<<endl;
else
{
for(int i=0;i<total;i++)
{
outfile.write((char*)&member[i],sizeof(member[i]));
outfile.write((char*)&bonus[i],sizeof(bonus[i]));
}
outfile.close();
cout<<"文件写入成功!"<<endl<<endl;
}
}
void Department1::Infile_Department()
{
int i=0;
ifstream infile("information_department.dat",ios::binary);
if(!infile) cerr<<"文件读取错误,请重试!"<<endl;
else
{
while(infile.peek()!=EOF)
{
infile.read((char*)&member[i],sizeof(member[i]));
infile.read((char*)&bonus[i],sizeof(bonus[i]));
i++;
total++;
}
infile.close();
cout<<"销售部有"<<total<<"个员工的数据。"<<endl<<endl;
}
}
void main1(Base &bas,Department1 &dep1)//添加员工
{
int choose1;
Base *pt=&bas;
cout<<"请选择即将添加员工的所在部门序号(1.人事部 2.销售部):";
leap1:
cin>>choose1;
if(choose1<1||choose1>2)
{
cout<<"请输入1或2:";
goto leap1;
}
else
switch(choose1)
{
case 1:pt->Add_member();break;
case 2:pt=&dep1;pt->Add_member();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap1;
}
}
void main2(Base &bas,Department1 &dep1)//删除员工
{
int choose2;
Base *pt=&bas;
cout<<"请选择即将删除员工的所在部门序号(1.人事部 2.销售部):";
leap2:
cin>>choose2;
if(choose2<1||choose2>2)
{
cout<<"请输入1或2:";
goto leap2;
}
else
switch(choose2)
{
case 1:pt->Delete_member();break;
case 2:pt=&dep1;pt->Delete_member();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap2;
}
}
void main3(Base &bas,Department1 &dep1)//修改员工信息
{
int choose3;
Base *pt=&bas;
cout<<"请选择即将修改员工的所在部门序号(1.人事部 2.销售部):";
leap3:
cin>>choose3;
if(choose3<1||choose3>2)
{
cout<<"请输入1或2:";
goto leap3;
}
else
switch(choose3)
{
case 1:pt->Change_member();break;
case 2:pt=&dep1;pt->Change_member();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap3;
}
}
void main4(Base &bas,Department1 &dep1)//按工资排序输出
{
int choose4;
Base *pt=&bas;
cout<<"请选择即将输出的所在部门序号(1.人事部 2.销售部):";
leap4:
cin>>choose4;
if(choose4<1||choose4>2)
{
cout<<"请输入1或2:";
goto leap4;
}
else
switch(choose4)
{
case 1:pt->Sort_by_wage();break;
case 2:pt=&dep1;pt->Sort_by_wage();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap4;
}
}
void main5(Base &bas,Department1 &dep1)//按工资筛选员工
{
int choose5;
Base *pt=&bas;
cout<<"请选择即将筛选的所在部门序号(1.人事部 2.销售部):";
leap5:
cin>>choose5;
if(choose5<1||choose5>2)
{
cout<<"请输入1或2:";
goto leap5;
}
else
switch(choose5)
{
case 1:pt->Screen_by_wage();break;
case 2:pt=&dep1;pt->Screen_by_wage();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap5;
}
}
void main6(Base &bas,Department1 &dep1)//按编号查找员工
{
int choose6;
Base *pt=&bas;
cout<<"请选择即将查找的员工所在部门序号(1.人事部 2.销售部):";
leap6:
cin>>choose6;
if(choose6<1||choose6>2)
{
cout<<"请输入1或2:";
goto leap6;
}
else
switch(choose6)
{
case 1:pt->LookUp_by_number();break;
case 2:pt=&dep1;pt->LookUp_by_number();break;
default:cout<<"输入有误,请重新输入:"<<endl;goto leap6;
}
}
int main()
{
int choose;
Base bas;
Department1 dep1;
bas.Infile_Base();
dep1.Infile_Department();
while(1)
{
cout<<" "<<endl;
cout<<" 人事管理系统 "<<endl;
cout<<"***************************************************************"<<endl;
cout<<"* *"<<endl;
cout<<"* 1.添加员工 2.删除员工 *"<<endl;
cout<<"* *"<<endl;
cout<<"* 3.修改员工信息 4.按工资排序输出 *"<<endl;
cout<<"* *"<<endl;
cout<<"* 5.按工资筛选员工 6.按编号查找员工 *"<<endl;
cout<<"* *"<<endl;
cout<<"* 7.写入文件 0.退出程序 *"<<endl;
cout<<"* *"<<endl;
cout<<"***************************************************************"<<endl;
cout<<" 请选择:";
leap0:
cin>>choose;
if(choose<0||choose>7)
{
cout<<"请输入0-7的数字:";
goto leap0;
}
else
switch(choose)
{
case 1:main1(bas,dep1);break;
case 2:main2(bas,dep1);break;
case 3:main3(bas,dep1);break;
case 4:main4(bas,dep1);break;
case 5:main5(bas,dep1);break;
case 6:main6(bas,dep1);break;
case 7:bas.Outfile_Base();dep1.Outfile_Department();break;
case 0:exit(0);
default:cout<<"输入有误,请重新输入:"<<endl;goto leap0;
}
}
return 0;
}
遗留及待优化问题
1.结构体Member(员工信息)中数据项仅有编号、姓名、工资3种。
2.派生类只有一个,可录入信息的部门只有两个,无法更好地体现出多态性。
3.增加的员工录入文件时,文件指针直接指向文件尾会更高效。
4.无法将基类和派生类(两个部门所有员工)的信息进行比较,共同排序,只能单独对每个部门进行比较和排序。
仅作留档。