2021/6/8
青岛理工大学(陈阳)
本次代码我写的十分繁琐,在这里说声抱歉。后期继续努力学习!
1. 综合利用面向对象的封装、继承、多态和文件流对象解决较为复杂的实际应用问题;
2. 体验多继承、动态多态等较为复杂的面向对象机制,提高学生学习的高阶性、挑战性和复杂度。
基于文件的小型公司人员信息管理系统的设计与实现
某小型公司主要有3类人员:经理、兼职技术人员、兼职销售员。这些人员分别具有以下属性。
经理:姓名、编号、固定工资、当月薪水、计算月薪、显示信息;
兼职技术人员:姓名、编号、工作小时、每小时工资额、当月薪水、计算月薪、显示信息;
兼职销售员:姓名、编号、销售额、销售额提成、当月薪水、计算月薪、显示信息。
销售经理:姓名、编号、固定工资、销售额、销售额提成、当月薪水、计算月薪、显示信息。
要求:
(1)人员编号基数为1000,每输入一个人员信息编号顺序加1;
(2)月薪计算办法是经理固定月薪8000元;兼职技术人员按100元/小时领取月薪;兼职销售员按当月销售额的4%提成;销售经理固定月薪5000元,销售提成为所管辖部门当月销售总额的0.5%。
(3)将成员函数displayStatus(显示信息)设置成虚函数。
(4)将void pay()(计算月薪)设置成纯虚函数。
(5)根据以上要求,设计一个基类Employee,然后派生出Technician(兼职技术人员)类、Manager(经理)类、Salesman(兼职销售员)类和Salesmanager(销售经理)类。
(6)每类人员的信息记录在“类名_info.txt”文件中,例如兼职技术人员的信息记录在
Technician_info.txt文件中。能够根据编号对每类人员的信息进行增加、查找、删除和修改。
编程提示:
由于销售经理既是经理又是销售人员,拥有两类人员的属性,因此同时继承Manager类和Salesman类。
由于Salesmanager类的两个基类又有公共基类Employee,为了避免二义性,将Employee类设计为虚基类。
代码如下:
#include<iostream>
#include<fstream> //文件流头文件
#include<string>
using namespace std;
int CountLines(char *filename);
void search(int num);
void look_name(int num);
void txt_delate();
void modify_name();
class Employee //人员基类
{
public:
Employee();
virtual void pay()=0; //纯虚函数,计算月薪
virtual void displayStatus(); //虚函数,展示信息
protected:
string Name;
int No;
static int Next_No;
int number;
};
int Employee::Next_No = 1000; //静态序号
Employee::Employee()
{
cout<<"请输入姓名:";
cin>>Name;
Next_No = Next_No + 1;
No = Next_No;
}
void Employee::displayStatus()
{
cout<<"姓名:"<<Name<<endl;
cout<<"号:"<<No<<endl;
}
class Manager:virtual public Employee //经理
{
public:
Manager();
virtual void pay();
virtual void displayStatus();
protected:
double Fixed_wage;
double Monthly_salary;
};
Manager::Manager()
{
int times;
int num = 0; //缓存数字
string No_after; //string缓存
ifstream in; //创建输入
in.open("info.txt",ios::in); //打开输入口
for(int i = 0;i < CountLines("info.txt");i ++) //每行每行查询
{
int product = 1000; //乘积,每次进入置位
getline(in,No_after); //将一行的数据存入No_after
times = No_after.length(); //获取string长度
for(int u = 0;u < times;u ++)
{
if(((int(No_after[u])) >= 48)&&((int(No_after[u])) <= 57))
{
num = num + ((int(No_after[u])-48)*product);
product = product / 10; //每次减少10倍
}
else if(No_after[u] == '/')
{
break; //退出循环
}
}
// num = ((int(No_after[5])-48)*1000)+((int(No_after[6])-48)*100)+((int(No_after[7])-48)*10)+((int(No_after[8])-48)*1); //类型转换,提取序号
No = num + 1; //赋值序号
num = 0; //执行一个循环后置一
}
in.close();
Fixed_wage=8000;
Monthly_salary=0;
}
void Manager:: pay()
{
Monthly_salary = Fixed_wage;
}
void Manager::displayStatus() //在显示电脑上时并且写入txt
{
ofstream out; //写入infol.txt
out.open("info.txt",ios::app);
out<<Name<<' '<<No<<'/'<<Monthly_salary<<' '<<endl;
out.close();
ofstream outc; //写入Manager.txt
outc.open("Manager.txt",ios::app); //Manager换行输入txt文档
outc<<Name<<' '<<No<<'/'<<Monthly_salary<<' '<<endl;
outc.close();
Employee::displayStatus();
cout<<"当月工资:"<<Monthly_salary<<"RMB"<<endl;
}
class Salesman:virtual public Employee //销售人员
{
public:
Salesman();
virtual void pay();
virtual void displayStatus();
protected:
double Sales_volume; //个人销售额
double Sales_commission; //销售额提成
double Salesman_Monthly_salary; //当月薪水
};
Salesman::Salesman()
{
int times;
int num = 0; //缓存数字
string No_after; //string缓存
ifstream in; //创建输入
in.open("info.txt",ios::in); //打开输入口,且为只读模式
for(int i = 0;i < CountLines("info.txt");i ++)
{
int product = 1000; //乘积,每次进入置位
getline(in,No_after); //将一行的数据存入No_after
times = No_after.length(); //获取string长度
for(int u = 0;u < times;u ++)
{
if(((int(No_after[u])) >= 48)&&((int(No_after[u])) <= 57))
{
num = num + ((int(No_after[u])-48)*product);
product = product / 10; //每次减少10倍
}
else if(No_after[u] == '/') //遇到这个标志位结束
{
break; //退出循环
}
}
No = num + 1; //赋值序号,可以实现程序下一次打开的序号赋值正确
num = 0; //执行一个循环后置一
}
in.close();
Sales_volume = 0;
Sales_commission = 0.04;
Salesman_Monthly_salary = 0;
}
void Salesman::pay()
{
cout<<"请输入本月你的销售额:";
cin>>Sales_volume;
Salesman_Monthly_salary = Sales_volume * Sales_commission;
}
void Salesman::displayStatus()
{
ofstream out; //写入infol.txt
out.open("info.txt",ios::app);
out<<Name<<' '<<No<<'/'<<Salesman_Monthly_salary<<' '<<endl;
out.close();
ofstream outc; //Salesman.txt
outc.open("Salesman.txt",ios::app); //Salesman换行输入txt文档
outc<<Name<<' '<<No<<'/'<<Salesman_Monthly_salary<<' '<<endl;
outc.close();
Employee::displayStatus();
cout<<"销售人员本月薪水:"<<Salesman_Monthly_salary<<"RMB"<<endl;
}
class Salesmanager: public Manager,public Salesman //销售经理
{
public:
Salesmanager();
void pay();
void displayStatus();
};
Salesmanager::Salesmanager()
{
Fixed_wage=5000;
Sales_commission=0.005;
}
void Salesmanager::pay()
{
cout<<"输入部门本月销售金额:";
cin>>Sales_volume;
Monthly_salary = Fixed_wage + Sales_volume * Sales_commission;
}
void Salesmanager::displayStatus()
{
ofstream out; //写入infol.txt
out.open("info.txt",ios::app);
out<<Name<<' '<<No<<'/'<<Monthly_salary<<' '<<Sales_volume<<endl;
out.close();
ofstream outc; //Salesmanager.txt
outc.open("Salesmanager.txt",ios::app); //Salesmanager换行输入txt文档
outc<<Name<<' '<<No<<'/'<<Monthly_salary<<' '<<Sales_volume<<endl;
outc.close();
Employee::displayStatus();
cout<<"销售经理工资:"<<Monthly_salary<<"RMB"<<endl;
}
class Technician:public Employee
{
private:
double Working_translation; //工作小时
double Hourly_work_amount; //小时工作金额
double Technician_Monthly_salary; //月工资
public:
Technician();
virtual void pay();
virtual void displayStatus();
};
Technician::Technician()
{
int times;
int num = 0; //缓存数字
string No_after; //string缓存
ifstream in; //创建输入
in.open("info.txt",ios::in); //打开输入口,且为只读模式
for(int i = 0;i < CountLines("info.txt");i ++)
{
int product = 1000; //乘积,每次进入置位
getline(in,No_after); //将一行的数据存入No_after
times = No_after.length(); //获取string长度
for(int u = 0;u < times;u ++)
{
if(((int(No_after[u])) >= 48)&&((int(No_after[u])) <= 57))
{
num = num + ((int(No_after[u])-48)*product);
product = product / 10;
}
else if(No_after[u] == '/') //遇到这个标志位结束,可进行自定义
{
break; //到达标志,退出循环
}
}
No = num + 1; //每次重新赋值序号
num = 0; //执行一个循环后置一
}
cout<<"请输入本月工作时间:";
cin>>Working_translation;
cout<<"请输入单位工作时间工资:";
cin>>Hourly_work_amount;
}
void Technician::pay()
{
Technician_Monthly_salary = Working_translation * Hourly_work_amount;
}
void Technician::displayStatus()
{
ofstream out; //写入infol.txt
out.open("info.txt",ios::app);
out<<Name<<' '<<No<<'/'<<Technician_Monthly_salary<<' '<<Working_translation<<endl;
out.close();
ofstream outc; //Technician.txt
outc.open("Technician.txt",ios::app); //Technician换行输入txt文档
outc<<Name<<' '<<No<<'/'<<Technician_Monthly_salary<<' '<<Working_translation<<endl;
outc.close();
Employee::displayStatus();
cout<<"兼职技术人员本月工资:"<<Technician_Monthly_salary<<endl;
cout<<Name<<endl;
}
int CountLines(char *filename) //返回行数
{
ifstream in;
int n=0;
string tmp;
in.open(filename,ios::in); //ios::in 表示以只读的方式读取文件
if(in.fail()) //文件打开失败:返回0
{
return 0;
}
else //文件存在
{
while(getline(in,tmp))
{
n++;
}
return n;
}
in.close();
}
void search(int num) //输入学号进行查询
{
string numb;
int number;
ifstream in;
in.open("info.txt",ios::in);
if(in.fail())
{
cout<<"打开文件info.txt失败!"<<endl;
}
else
{
while(getline(in,numb))
{
int multiple = 1000;
for(int i = 0;i < numb.length();i ++)
{
if(((int(numb[i])) >= 48)&&((int(numb[i])) <= 57))
{
number = number + ((int(numb[i])-48)*multiple);
multiple = multiple / 10;
}
else if(numb[i] == '/')
{
break;
}
if(num == number)
{
cout<<"查找到了!"<<endl;
look_name(num); //调用查找四表
}
number = 0;
}
}
}
in.close();
}
void look_name(int num) //找四个表,从中找出来
{
for(int i = 0;i < 4;i ++)
{
string txt_name;
string numb;
int number = 0;
if(i == 0)
{
txt_name = "Manager.txt";
}
else if(i == 1)
{
txt_name = "Salesman.txt";
}
else if(i == 2)
{
txt_name = "Salesmanager.txt";
}
else
{
txt_name = "Technician.txt";
}
ifstream ins;
ins.open(txt_name,ios::in);
if(ins.fail())
{
cout<<"打开文件"<<txt_name<<"失败!"<<endl;
}
else
{
while(getline(ins,numb))
{
int multiple = 1000;
for(int i = 0;i < numb.length();i ++)
{
if(((int(numb[i])) >= 48)&&((int(numb[i])) <= 57))
{
number = number + ((int(numb[i])-48)*multiple);
multiple = multiple / 10;
}
else if(numb[i] == '/')
{
break;
}
if(num == number)
{
cout<<"ta的名字是:";
for(int u = 0;u <numb.length();u ++)
{
if(((numb[u] >= 'a')&&(numb[u]) <= 'z')||(((numb[u]) >= 'A')&&((numb[u]) <= 'Z')))
{
cout << numb[u];
}
else if(numb[u] == ' ')
{
cout<<endl;
break;
}
}
}
}
number = 0;
}
}
ins.close();
}
}
void txt_delate() //删除代码
{
int cc;
string NAME_TXT;
int times_txt;
string numb;
string txt_nb;
int u;
int number;
int people_no;
cout<<"请输入你想要删除的员工号:";
cin>>people_no;
for(int z = 0;z < 5;z ++)
{
switch(z)
{
case 0:NAME_TXT = "info.txt";times_txt = CountLines("info.txt");break;
case 1:NAME_TXT = "Manager.txt";times_txt = CountLines("Manager.txt");break;
case 2:NAME_TXT = "Salesman.txt";times_txt = CountLines("Salesman.txt");break;
case 3:NAME_TXT = "Salesmanager.txt";times_txt = CountLines("Salesmanager.txt");break;
case 4:NAME_TXT = "Technician.txt";times_txt = CountLines("Technician.txt");break;
}
ifstream in;
in.open(NAME_TXT,ios::in);
ofstream out;
out.open(NAME_TXT,ios::app); //打开用于输出文件流
for(int i = 0;i < times_txt;i ++) //先查询写入备份文档
{
while(getline(in,numb))
{
int multiple = 1000;
number = 0;
for(u = 0;u < numb.length();u ++)
{
if(((int(numb[u])) >= 48)&&((int(numb[u])) <= 57))
{
number = number + ((int(numb[u])-48)*multiple);
multiple = multiple / 10;
}
else if(numb[u] == '/')
{
break;
}
}
if(people_no == number) //如果一样跳过写入
{
continue;
}
else //将不一样的写入backups.txt备用文档中
{
ofstream outs;
outs.open("backups.txt",ios::app);
outs<<numb<<endl;
outs.close();
}
}
}
in.close();
out.close();
switch(z) //删除循环,对应上面的
{
case 0:system("del info.txt");break;
case 1:system("del Manager.txt");break;
case 2:system("del Salesman.txt");break;
case 3:system("del Salesmanager.txt");break;
case 4:system("del Technician.txt");break;
}
cc = 0;
ifstream inmm; //创建in
inmm.open("backups.txt",ios::in); //打开与backups.txt的通道
ofstream outmm;
outmm.open(NAME_TXT,ios::app);
for(int t = 0;t < CountLines("backups.txt");t ++) //重新写入原文档,删除备份文档
{
getline(inmm,txt_nb); //获取每一行
outmm<<txt_nb<<endl; //写入原文档
}
inmm.close();
outmm.close();
system("del backups.txt"); //删除中间文件
}
}
void modify_name()
{
string Bei_fen;
string NAME_TXT;
string numb;
string new_name;
int times_txt; //存储行数
int NO_num; //存储序号
int number;
int u;
int u_best; //记录位置
cout<<"请问你要修改哪个序号的名字?";
cin>>NO_num;
for(int z = 0;z < 5;z ++)
{
switch(z)
{
case 0:NAME_TXT = "info.txt";times_txt = CountLines("info.txt");break;
case 1:NAME_TXT = "Manager.txt";times_txt = CountLines("Manager.txt");break;
case 2:NAME_TXT = "Salesman.txt";times_txt = CountLines("Salesman.txt");break;
case 3:NAME_TXT = "Salesmanager.txt";times_txt = CountLines("Salesmanager.txt");break;
case 4:NAME_TXT = "Technician.txt";times_txt = CountLines("Technician.txt");break;
}
ifstream in;
in.open(NAME_TXT,ios::in);
ofstream out;
out.open(NAME_TXT,ios::app);
ofstream outs;
outs.open("backups.txt",ios::app); //输出备份
ifstream ins; //备用文档
ins.open("backups.txt",ios::in); //读取备份
for(int i = 0;i < times_txt;i ++) //先查询写入备份文档
{
while(getline(in,numb))
{
int multiple = 1000;
number = 0;
for(u = 0;u < numb.length();u ++)
{
if(((int(numb[u])) >= 48)&&((int(numb[u])) <= 57))
{
number = number + ((int(numb[u])-48)*multiple);
multiple = multiple / 10;
}
else if(numb[u] == '/')
{
u_best = u + 1;
break;
}
}
if(NO_num == number)
{
cout<<"请输入新名字:";
cin>>new_name;
outs<<new_name<<" "<<NO_num<<'/';
for(int m = u_best;m < numb.length();m ++) //从'/'后继续输出,直到输出完
{
outs<<numb[m];
}
outs<<endl;
}
else //将不一样的写入backups.txt备用文档中
{
outs<<numb<<endl;
}
}
}
in.close();
out.close();
ins.close();
outs.close();
ins.open("backups.txt",ios::in);
outs.open("backups.txt",ios::app); //输出备份
switch(z) //删除循环,对应上面的
{
case 0:system("del info.txt");break;
case 1:system("del Manager.txt");break;
case 2:system("del Salesman.txt");break;
case 3:system("del Salesmanager.txt");break;
case 4:system("del Technician.txt");break;
}
in.open(NAME_TXT,ios::in);
out.open(NAME_TXT,ios::app);
for(int numbb = 0;numbb < CountLines("backups.txt");numbb ++)
{
getline(ins,Bei_fen); //将临时文档放入Bei_fen
out<<Bei_fen<<endl; //输出到文档
}
ins.close();
outs.close();
system("del backups.txt"); //每一行都获取完毕
in.close();
out.close();
}
}
int main()
{
int o;
int look;
cout<<"欢迎来到陈阳的代码世界!"<<endl;
cout<<"请问您要输入几个数据?";
cin>>o;
for(int i = 0;i < o;i ++)
{
int num;
Employee* P0;
cout<<"创建哪种类型的员工?"<<endl;
cout<<"1:经理"<<endl;
cout<<"2:兼职技术人员"<<endl;
cout<<"3:兼职销售员"<<endl;
cout<<"4:销售经理"<<endl;
cin>>num;
switch(num)
{
case 1:P0 = new Manager;break;
case 2:P0 = new Technician;break;
case 3:P0 = new Salesman;break;
case 4:P0 = new Salesmanager;break;
}
P0->pay();
P0->displayStatus();
}
cout<<"请问需要删除吗?0:是,1:否:"<<endl;
cin>>look;
switch(look)
{
case 0:txt_delate();break;
case 1:cout<<"成功取消删除!"<<endl;break;
}
cout<<"请问需要修改名字吗?0:是,1:否:"<<endl;
cin>>look;
switch(look)
{
case 0:modify_name();break;
case 1:cout<<"成功取消修改!"<<endl;break;
}
return 0;
}