C++大作业——公司员工信息管理系统

我还没秃头~ 2024-07-08 15:35:02 阅读 93

文章目录

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++面向对象程序设计设计一个简易的公司员工信息管理系统,其中用到了:类的使用、数组、循环体、函数的调用、封装等内容。系统需要定义职工(<code>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语句实现功能模块多次执行,代码如下:

<code>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函数以节省空间。

//定义全局变量,每个函数都要使用此链表

<code>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();//获取工资函数

类图

<code>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指针指向当前节点

具体实现代码如下(以添加成员信息功能为例):

<code>if(head)

while(p->next)

{ p=p->next;} //获取尾节点 ,经删除函数后,p1会变化,此处重新获取

p1=p;

while(i<=n){

p2=new Employee();

p2->next=NULL;

cout<<"请依次第"<<i<<"个输入工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

cin>>*p2;

if(!head)//头指针为空

{

head=p1=p2;

}

else

{

p1->next=p2;}

p1=p2;

p1->next=NULL;

i++;

cout<<"添加信息成功!"<<endl;

};

修改链表信息:

由于链表存的都是地址,因此,只需要遍历链表找到需要更改的节点处进行修改指针指向内容即可,实现代码如下(以修改员工信息功能为例):

Employee *p=head; //遍历链表代码

while(p)

{

if(strcmp(p->get_name(),na)==0)

{

cout<<"请依次输入修改后的工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

cin>>*(p) ;

cout<<"修改信息成功!"<<endl;

break;

}

p=p->next;

}

删除链表信息:

删除链表信息的方法为,将此节点的下一个节点与上一个节点连接,然后将此节点释放,即可完成信息删除。此处要注意表头信息。

上述过程如下图:

实现代码如下:(以删除员工信息为例)

<code>if(head->get_id()==id)//头链表时

{ cout<<"删除信息成功!"<<endl;

flag=1;

head=head->next;}

while(p->next)

{

if(p->next->get_id()==id)

{

Employee *pp=new Employee();

pp=p->next;

p->next=pp->next;

delete pp;

flag=1;

cout<<"删除信息成功!"<<endl;

break; //删完之后退出

}

p=p->next;

}

3.2.5二进制文件

该系统中建立了一个二进制文件“员工信息.dat”。引用二进制文件,头文件是不可少的,其次,c++中的利用文件流进行读写文件,因此使用时需要定义文件流对象,每次以二进制方式打开文件并检查是否成功打开。

1.读写文件方法

利用二进制文件读写函数read和write俩大函数,由于次俩函数存储类型为(char*),因此,“员工信息.dat”存储员工的信息,通过将类数据Employee类型进行强制转换为字符数组型读写相应二进制文件。

实现代码如下:

Employee a1(1 ,"李你好", "男", "155", "精神科", 300);

ot.write((char*)&a1,sizeof(Employee));

it.read((char*)&a1,sizeof(Employee));

2.读写文件运用

在此系统中,为了将修改后的信息永久存入文件中,且在内存中修改并永久保存,使用了链表结合二进制文件进行读写。即先将文件信息读入链表,通过链表进行信息增删修改后,再将链表信息以覆盖方式写入文件实现永久储存信息。

上述过程如下图:

首先,如果文件不存在,我们就利用系统自动创建一个“员工信息.dat”文件,如果文件存在,则将原有文件信息读入链表,且确保原有文件数据不被删除

实现代码如下:

<code>ofstream ot;

ot.open("员工信息.dat",ios::out|ios::app);//1.文件不存在时创建文件2.存在时不覆盖原内容

if(!ot)

{

cout<<"员工信息文件打开失败!"<<endl;

exit(1);

}

ot.close();

ifstream it;

it.open("员工信息.dat",ios::in);

if(!it)

{

cout<<"员工信息文件打开失败!"<<endl;

exit(1);

}

it.seekg(0,ios::end);

int filelen,i=1;

filelen=it.tellg();

it.seekg(0,ios::beg);

while(it.tellg()!=filelen)

{

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();

在将信息读入链表后,通过对链表修改数据后再存入文件,具体链表修改参照上文。将链表信息写入文件的实现代码如下:

ofstream o;

o.open("员工信息.dat",ios::out);

if(!o)

{ cout<<"员工信息文件打开失败!"<<endl;

return;}

Employee *p=head;

while(p)

{

o.write((char *)p,sizeof(Employee));

p=p->next;

}

o.close();

3.读文件信息并输出

将文件的信息读入链表,并遍历链表输出文件里面的信息。

实现代码如下:(以输出文件信息功能为例)

while(it.tellg()!=filelen)

{

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<<"暂无信息!"<<endl;

4.测试内容

主页面

添加职工信息功能

添加3个员工信息如下:

1 张三 男 10010 联通 3050

2 李四 男 10086 移动 4500

3 王五 男 10010 联通 3800

输出此时文件信息

按姓名查询职工信息

以张三名字进行查询

按科室查询职工信息

此处查询联通科室

按科室统计职工平均工资

自动统计并输出所有科室平均工资信息

修改信息

以张三的名字进行修改信息,此处示例仅改变了工资

修改前张三工资为3050,修改后为4000

以张三的工号进行修改信息,此处示例仅改变了工资

张三的工资由4000改至10000

删除信息

以张三名字进行删除张三信息

删除后,文件信息输出中张三的信息不存在了

此处以工号删除王五信息(工号为3)

删除后,文件信息输出时王五的信息不存在

检验文件信息

经过上述操作后,文件中仅剩李四的信息,查看<code>员工信息.dat文件

通过工号删除文件中李四的信息

再次查询文件中的个人信息

查看<code>员工信息.dat文件

退出系统

输入数字0,自动退出系统,文件信息自动存储

5.源代码

<code>#include<iostream>

#include<cstring>

#include<fstream>//新增了office类、重载运算符、查看文件信息函数 、根据名字删除信息

#include<iomanip>

using namespace std;

class Employee;

//定义全局变量,每个函数都要使用此链表

Employee *head=NULL,*p1=NULL,*p2=NULL;//head记录头,p1记录当前,p2开辟

class 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();//获取工资

};

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<<"请依次输入工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

in>>x.id>>x.name>>x.sex>>x.number>>x.office>>x.wage;

return in;

}

void Employee::SaveInfo(){

cout<<"员工姓名:"<<setw(10)<<left<<name<<"性别:"<<setw(10)<<sex<<"工号:"<<setw(5)<<id<<endl;

cout<<"所在科室:"<<setw(10)<<office<<"工资:"<<setw(10)<<wage<<"电话号码:"<<setw(15)<<number<<endl;

}

char* Employee::get_name(){

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<<off<<"科室的平均工资为:"<<sum/count<<endl;

}

char* office::get_off(){

return off;

}

void office::add(double s){

sum+=s;

count++;

}

void menu_show(){

cout << "***********************************************************" << endl;

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 << " *** 0.退出职工信息管理系统 *** " << endl;

cout << " *********************************** " << endl;

cout << "请输入一个数字选择功能: ";

}

void ad() //将链表数据存入文件

{

ofstream o;

o.open("员工信息.dat",ios::out);

if(!o)

{ cout<<"员工信息文件打开失败!"<<endl;

return;}

Employee *p=head;

while(p)

{

o.write((char *)p,sizeof(Employee));

p=p->next;

}

o.close();

}

void ap() //将文件信息读入链表

{

ifstream it;

it.open("员工信息.dat",ios::in);

if(!it)

{

cout<<"员工信息文件打开失败!"<<endl;

exit(1);

}

it.seekg(0,ios::end);

int filelen,i=1;

filelen=it.tellg();

it.seekg(0,ios::beg);

while(it.tellg()!=filelen)

{

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<<"暂无信息!"<<endl;

}

void AddEmployee() { //1.增加职工信息函数

cout<<"请输入您要添加的职工数量:"<<endl;

int n,i=1;

cin>>n;

Employee *p=head; //遍历链表代码

if(head)

while(p->next)

{ p=p->next;} //获取尾节点 ,经删除函数后,p1会变化,此处重新获取

p1=p;

while(i<=n){

p2=new Employee();

p2->next=NULL;

cout<<"请依次第"<<i<<"个输入工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

cin>>*p2;

if(!head)//头指针为空

{

head=p1=p2;

}

else

{

p1->next=p2;}

p1=p2;

p1->next=NULL;

i++;

cout<<"添加信息成功!"<<endl;

};

ad();//刷新文件

// head->next->SaveInfo();

//p1->SaveInfo();

// p2->SaveInfo();

}

void DeleteEmployee() //2.删除员工信息

{

if(!head){

cout<<"没有可供删除的人员信息! 请先添加人员信息!"<<endl;

return;

}

cout<<"输入名字删除输入0,输入工号删除输入1:"<<endl;

int choice;

cin>>choice;

if(choice==1)

{

cout<<"请输入您要删除的员工工号:"<<endl;

int id,flag=0;

cin>>id;

Employee *p=head; //遍历链表代码

if(head->get_id()==id)//头链表时

{ cout<<"删除信息成功!"<<endl;

flag=1;

head=head->next;}

while(p->next)

{

if(p->next->get_id()==id)

{

Employee *pp=new Employee();

pp=p->next;

p->next=pp->next;

delete pp;

flag=1;

cout<<"删除信息成功!"<<endl;

break; //删完之后退出

}

p=p->next;

}

if(flag==0) cout<<"文件中不包含此人信息!"<<endl;

}else if(choice==0){

cout<<"请输入您要删除的员工姓名:"<<endl;

char *na=new char[10];

cin>>na;

int flag=0;

Employee *p=head; //遍历链表代码

if(strcmp(head->get_name(),na)==0)//头链表时

{ cout<<"删除信息成功!"<<endl;

flag=1;

head=head->next;}

while(p->next)

{

if(strcmp(p->next->get_name(),na)==0)

{

Employee *pp=new Employee();

pp=p->next;

p->next=pp->next;

delete pp;

flag=1;

cout<<"删除信息成功!"<<endl;

break; //删完之后退出

}

p=p->next;

}

if(flag==0) cout<<"文件中不包含此人信息!"<<endl;

delete []na;

}

//if(!head->next) head->next=p1; //**当只有表头时,链接起来

ad();//刷新文件

}

void UpdateEmployee()///修改职工信息函数

{

if(!head){

cout<<"没有可供修改的人员信息! 请先添加人员信息!"<<endl;

return;

}

cout<<"输入名字修改输入0,输入工号修改输入1:"<<endl;

int choice;

cin>>choice;

if(choice==0)

{

cout<<"请输入要修改的人名字:"<<endl;

char *na=new char[10];

cin>>na;

Employee *p=head; //遍历链表代码

while(p)

{

if(strcmp(p->get_name(),na)==0)

{

cout<<"请依次输入修改后的工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

cin>>*(p) ;

cout<<"修改信息成功!"<<endl;

break;

}

p=p->next;

}

if(!p) cout<<"未查询到修改人信息!"<<endl;

delete []na;

}

else if(choice==1){

cout<<"请输入要修改的人工号:"<<endl;

int *id=new int;

cin>>*id;

Employee *p=head; //遍历链表代码

while(p)

{

if(p->get_id()==*id)

{

cout<<"请依次输入修改后的工号、名字、性别、电话号码、所在科室 、工资:"<<endl;

cin>>*(p) ;

cout<<"修改信息成功!"<<endl;

break;

}

p=p->next;

}

if(!p) cout<<"未查询到修改人信息!"<<endl;

delete id;

}

//

ad();//刷新文件

}

void reseachStudentByName()//4.按姓名查询职工信息函数

{ if(!head){

cout<<"查询失败! 请先添加人员信息!"<<endl;

return;

}

cout<<"请输入要查询的人名字:"<<endl;

char *na=new char[10];

cin>>na;

Employee *p=head; //遍历链表代码

while(p)

{

if(strcmp(p->get_name(),na)==0)

{

cout<<na<<"的个人信息如下:"<<endl;

p->SaveInfo();

break;

}

p=p->next;

}

if(!p) cout<<"未查询到此人信息!"<<endl;

delete []na;

}

void reseachStudentByOffice()//按科室查询职工信息函数

{ if(!head){

cout<<"查询失败! 请先添加人员信息!"<<endl;

return;

}

cout<<"请输入要查询的科室名字:"<<endl;

char *of=new char[10];

cin>>of;

Employee *p=head; //遍历链表代码

int *flag=new int(0);

while(p)

{

if(strcmp(p->get_office(),of)==0)

{ if(*flag==0) cout<<"所查询的科室职工如下:"<<endl;

p->SaveInfo();

(*flag)++;

}

p=p->next;

}

if(!(*flag)) cout<<"未查询到该科室人员信息!"<<endl;

delete []of;

delete flag;

}

void add()//按科室统计职工平均工资函数

{

if(!head){

cout<<"统计失败! 请先添加人员信息!"<<endl;

return;

}

office *head_=NULL,*p1_=NULL,*p2_=NULL;//前三者同之前

Employee *p=head; //遍历链表代码

office *p_;

int i=1;

while(p)

{

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<<"员工信息文件打开失败!"<<endl;

exit(1);

}

//ot.write((char*)&a1,sizeof(Employee));

ot.close();

ifstream it;

it.open("员工信息.dat",ios::in);

if(!it)

{

cout<<"员工信息文件打开失败!"<<endl;

exit(1);

}

it.seekg(0,ios::end);

int filelen,i=1;

filelen=it.tellg();

it.seekg(0,ios::beg);

while(it.tellg()!=filelen)

{

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();

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。