C++大作业——公司员工信息管理系统
文章目录
- 1.系统概述
- 2. 系统环境
- 1.1 软件环境
- 1.2 硬件环境
- 3. 设计内容
- 3.1 系统流程
- 3.2功能模块及详细说明
- 3.2.1设计框架
- 3.2.2定义宏数据
- 3.2.3类的应用
- 3.2.4链表
- 3.2.5二进制文件
- 4.测试内容
- 5.源代码
1.系统概述
使用C++面向对象程序设计设计一个简易的公司员工信息管理系统,其中用到了:类的使用、数组、循环体、函数的调用、封装等内容。系统需要定义职工(Employee)类,其中包括工号、姓名、性别、电话、所在科室和工资等信息。实现如下基本功能:
(1)设计菜单实现功能选择;
(2)添加功能:输入人员信息,并保存到文件中;
(3)删除功能:输入人员编号实现删除,并保存到文件中;
(4)修改功能:输入人员编号及其他相关信息,实现修改并保存到文件中;
(5)查询功能:能够根据姓名精确查询人员信息;
(6)统计功能:根据科室分别统计每个科室员工的平均工资并输出结果;
2. 系统环境
1.1 软件环境
操作系统为Windows 10,工作软件为:Dev-c++ 5.11
1.2 硬件环境
系统类型: 64 位操作系统, 基于 x64 的处理器
3. 设计内容
3.1 系统流程
问题分析:
系统要求实现如下功能:
(1)系统后台
1.原有数据:利用二进制文件存储公司员工信息管理系统的原始数据,存储员工信息。
2.修改信息:在原有数据的基础上,有客户信息需要修改,需要二进制文件的读写操作进行存储和读取数据文件内的信息,并通过链表修改实现文件信息修改。
(2)系统前台
-
添加加职工信息
-
删除职工信息
-
修改职工信息
-
按姓名查询职工信息
-
按科室查询职工信息
-
按科室统计职工平均工资程序模块流程
-
查看文件中现有职工信息
-
退出职工信息管理系统
3.2功能模块及详细说明
功能结构图
3.2.1设计框架
利用循环语句及switch语句实现功能模块多次执行,代码如下:
void show() { int n; while (1) { menu_show(); cin >> n; switch (n) { case (0) : { exit(1); //退出职工工资管理系统 } case (1): { AddEmployee();//增加职工信息函数 break; } case (2): { DeleteEmployee();//删除职工信息函数 break; } case (3):{ UpdateEmployee();//修改职工信息函数 break; } case(4) :{ reseachStudentByName();// 按姓名查询职工信息函数 break; } case(5):{ reseachStudentByOffice();//按科室查询职工信息函数 break; } case (6) : { add();//按科室统计职工平均工资函数 break; } case(7):{ ap();//显示文件信息函数 break; } } } }设计主菜单
3.2.2定义宏数据
员工信息、各科室信息都是由多个基础的数据类型共同组成,因此,使用类进行封装存储。类中的基础数据类型包括浮点型、整形、字符数组。在条件允许的情况下,应多使用new、delete函数以节省空间。
//定义全局变量,每个函数都要使用此链表
Employee *head=NULL,*p1=NULL,*p2=NULL;//head
记录头,p1记录当前,p2开辟
此处的链表记录了员工信息数据,在每个函数里面都要调用,因此定义为全局变量。
3.2.3类的应用
源代码中包含了俩个类,一个是Employee类,用于记录员工的工号、姓名、性别、电话、所在科室和工资,还有一个是office类,用于记录某一科室的名字、人数、成员总工资。
它们实现的功能如下:
Employee类
数据成员
private: int id; //记录工号 char name[10]; //记录名字 char sex[5]; //记录性别 char number[12]; //记录电话号码 char office[20]; //科室 double wage; //记录工资 public: Employee *next; //链表节点
公有成员函数
Employee() {} //无参构造函数 Employee(int id,char na[],char sex[],char num[],char of[],double wa); //有参构造函数 friend istream &operator>>(istream &cin,Employee &x);//重载运算符">>" 函数 void SaveInfo(); //输出信息函数 char* get_name();//获取名字函数 int get_id();//获取工号函数 char* get_office();//获取科室函数 double get_wage();//获取工资函数类图
office类
数据成员
private: double sum=0;//记录总工资 int count=0;//记录该科室人数 char off[20]; //记录该科室名称 public: office *next; //链表节点
成员函数
office() //无参构造函数 {strcpy(off," ");} office(double s,char o[]);//有参构造函数 void display();//输出信息函数 char* get_off(); //获得科室名字函数 void add(double s);//新增该科室成员数据函数类图
**注:**1.以上各个类中的字符数组均不能换成string类,在存入二进制文件时,string型数据存入的是指针,二进制文件是不能存储指针的
3.2.4链表
链表每一个节点都是由数据域和指针域构成的,每一个指针域指向下一个节点,每个节点的数据域存储相应的数据,最后一个节点的指针域指向NULL,即空,表示链表结束。访问单链表中任何一个元素都必须通过头结点层层往下遍历,因此头节点是链表中最重要的节点,没有头节点就无法访问整个链表。这也是链表和顺序表最大的不同。
相较于数组,链表则可以动态改变长度,加之指针的方式使得其遍历速度极为高效。
源代码中多处使用到了链表,涉及到链表的初始化、信息修改、增删节点以及遍历链表读取链表信息。源代码中以head指针记录表头,p1指针记录链表尾节点位置,p2指针用于开辟空间,始终保证p1的下一个节点为空指针。
初始化链表及添加节点:
表头head用于记录第一个数据地址,p2开辟空间,然后利用p1将它们链接起来。
当只有一个数据时,3个指针指向同一块地址。实现对员工信息的添加,即在链表的尾节点再接入一个节点,存储新增数据。具体步骤如下,利用循环先从表头开始遍历当前链表,直至尾节点为空指针,p1指针指向当前节点
具体实现代码如下(以添加成员信息功能为例):
if(head) while(p->next) {p=p->next;} //获取尾节点 ,经删除函数后,p1会变化,此处重新获取 p1=p; while(i p2=new Employee(); p2-next=NULL; cout head=p1=p2; } else { p1-next=p2;} p1=p2; p1-next=NULL; i++; cout if(strcmp(p-get_name(),na)==0) { cout cout if(p-next-get_id()==id) { Employee *pp=new Employee(); pp=p-next; p-next=pp-next; delete pp; flag=1; cout cout cout p2=new Employee(); it.read((char*)p2,sizeof(Employee)); if(i==1) { head=p1=p2; } else { p1-next=p2; } p1=p2; p1-next=NULL; i++; } it.close(); cout o.write((char *)p,sizeof(Employee)); p=p-next; } o.close(); p2=new Employee(); it.read((char*)p2,sizeof(Employee)); if(i==1) { head=p1=p2; } else { p1-next=p2; } p1=p2; p1-next=NULL; i++; } it.close(); Employee *p=head; //遍历链表代码 if(head) while(p) { p-SaveInfo(); p=p-next; } else cout private: int id; //记录工号 char name[10]; //记录名字 char sex[5]; //记录性别 char number[12]; //记录电话号码 char office[20]; //科室 double wage; //记录工资 public: Employee *next; //链表节点 Employee() //无参构造 {} Employee(int id,char na[],char sex[],char num[],char of[],double wa); friend istream &operator(istream &cin,Employee &x);//重载运算符"" void SaveInfo(); //输出信息 char* get_name();//获取名字 int get_id();//获取工号 char* get_office();//获取科室 double get_wage();//获取工资 }; class office{ private: double sum=0;//记录总工资 int count=0;//记录该科室人数 char off[20]; //记录该科室名称 public: office *next; office() //无参构造初始化 {strcpy(off," ");} office(double s,char o[]);//有参构造初始化 void display();//输出信息 char* get_off(); //获得科室名字 void add(double s);//新增该科室成员数据 }; Employee::Employee(int id,char na[],char se[],char num[],char of[],double wa) //有参构造函数 { strcpy(name,na); strcpy(sex,se); strcpy(number,num); strcpy(office,of); this-id=id; this-wage=wa; } istream &operator(istream &in,Employee &x)//重载运算符"" { //cout cout return name; } char* Employee::get_office(){ return office; } int Employee::get_id(){ return id; } double Employee::get_wage(){ return wage; } office::office(double s,char o[]){ sum+=s; count++; strcpy(off,o); } void office::display(){ cout return off; } void office::add(double s){ sum+=s; count++; } void menu_show(){ cout ofstream o; o.open("员工信息.dat",ios::out); if(!o) {cout o.write((char *)p,sizeof(Employee)); p=p-next; } o.close(); } void ap() //将文件信息读入链表 { ifstream it; it.open("员工信息.dat",ios::in); if(!it) { cout p2=new Employee(); it.read((char*)p2,sizeof(Employee)); if(i==1) { head=p1=p2; } else { p1-next=p2; } p1=p2; p1-next=NULL; i++; } //p1-next=NULL; 加上会运行错误 //head-SaveInfo(); it.close(); Employee *p=head; //遍历链表代码 if(head) while(p) { p-SaveInfo(); p=p-next; } else cout//1.增加职工信息函数 coutp=p-next;} //获取尾节点 ,经删除函数后,p1会变化,此处重新获取 p1=p; while(i p2=new Employee(); p2-next=NULL; cout head=p1=p2; } else { p1-next=p2;} p1=p2; p1-next=NULL; i++; cout if(!head){ cout cout cout if(p-next-get_id()==id) { Employee *pp=new Employee(); pp=p-next; p-next=pp-next; delete pp; flag=1; cout cout cout if(strcmp(p-next-get_name(),na)==0) { Employee *pp=new Employee(); pp=p-next; p-next=pp-next; delete pp; flag=1; cout if(!head){ cout cout if(strcmp(p-get_name(),na)==0) { cout cout if(p-get_id()==*id) { coutif(!head){ cout if(strcmp(p-get_name(),na)==0) { cout if(!head){ cout if(strcmp(p-get_office(),of)==0) {if(*flag==0) cout if(!head){ cout int f=0;//作为标记 for( p_=head_;p_;p_=p_-next) //遍历链表head_ {if(strcmp(p_-get_off(),p-get_office())==0) { p_-add(p-get_wage()); //添加 f=1; break; } } if(f==0) //新增,存入链表head_ { p2_=new office(p-get_wage(),p-get_office()); if(i==1) { head_=p1_=p2_; } else { p1_-next=p2_; } p1_=p2_; p1_-next=NULL; i++; } p=p-next; } p_=head_; //遍历链表代码 while(p_) { p_-display(); p_=p_-next; } } void show() { int n; while (1) { menu_show(); cin n; switch (n) { case (0) : { exit(1); //退出职工工资管理系统 } case (1): { AddEmployee();//增加职工信息函数 break; } case (2): { DeleteEmployee();//删除职工信息函数 break; } case (3):{ UpdateEmployee();//修改职工信息函数 break; } case(4) :{ reseachStudentByName();// 按姓名查询职工信息函数 break; } case(5):{ reseachStudentByOffice();//按科室查询职工信息函数 break; } case (6) : { add();//按科室统计职工平均工资函数 break; } case(7):{ ap();//显示文件信息函数 break; } } } } int main(){ //getdate(); ofstream ot; ot.open("员工信息.dat",ios::out|ios::app);//1.文件不存在时创建文件2.存在时不覆盖原内容 if(!ot) { cout cout p2=new Employee(); it.read((char*)p2,sizeof(Employee)); if(i==1) { head=p1=p2; } else { p1-next=p2; } p1=p2; p1-next=NULL; i++; } //head-SaveInfo(); it.close(); show(); } -







