姓名 王镇窑 学号 913104680120 班级 9131046801 任课教师 钱芸生 时间 2014.4 实验题目 工资管理 评定难易级别 A 实验报告成绩
一. 二. 三.
题目名称:工资管理 难度等级:A级 课程设计要求:
1. 用类的形式改写程序,将程序中工资数据用链表的形式存放,定义一个链表类,封装主要操作函数。
2. 显示,修改,删除数据项时大小写通用。 3. 工资数据按工资值的大小进行排序存放。
4. 修改、删除数据前增加提示信息,用户确认后才能进一步操作,否则操作取消。 5. 增加程序的文件输入输出功能,在执行程序中首先将工资数据从文件中读出再进行管理,在程序结束时能将工资数据保存在原文件中。 四.程序结构框图
功能示意图: 1.添加工资记录。 开始程序,打开文件,把文件中数据读出写入内存中。文件不存在,则提示。 4.根据姓名删除工资记录。 2.显示工资记 录。 3. 根据姓名查询工资记录。 主菜单 5.根据姓名修改工资记录。 按0结束程序,将修改后的链表数据从内存中存到文件里。退出程序。
返回主菜单 主函数具体流程: 开始程序 建立一个链表类对象 运行函数将文件中的数据写入内存中, 如果不存在文件输出提示 输出主菜单内容 从键盘提取字符 判断字符是不是0 调用链表类函数实现添 不是0 是 加工资记录的功能。 判断是不是1 不是1 调用链表类函数把整个 是 链表打印出来。 判断是不是2 调用链表类函数,不是2 键盘输入姓 名查找出相应的结点,并打印是 判断是不是3 出来。 不是3 调用链表类函数,键盘输入姓是 名查找出相应的结点,判断是不是4 修改上 一节点的next指针删除结点。 不是4 是 调用链表类函数,键盘输入姓判断是不是5 名查找出相应的结点,重新输 入工资,赋值给相应的数据类。 调用链表类函数将数据从 内存转存到文件中。 返回主菜单
是0
结束程序 五.程序设计思想
整个程序是我和吴龙生同学合作完成,我们先完成了主函数的编写,再把程序各个功能的实现交由类函数实现。一共有1.添加工资记录。2.显示工资记录。3.根据姓名查询工资记录。4.根据姓名删除工资记录。5.根据姓名修改工资记录,再加上从文件写入内存,从内存写入文件,七个主要功能函数,我们把这些函数分工编写,再整合整个程序。
用类改编程序,我们建立了一个数据类(用于存放姓名和工资),一个结点类(存放数据类指针和下一个结点的指针),一个链表类(存放链表的头指针和结点的个数,同时封装了对链表操作的所有函数)。虽然各个程序有不同的具体要求,但链表的操作大同小异,所不同的只是结点那部分的数据类型不同。所以根据这一特点,可以将链表定义成一个类,涉及结点数据的输入、输出、复制等。在结点中涉及较多的是具体数据的形式,所以将具体的数据形式定义成数据类型的指针,所有针对数据的操作都转换为对指针的操作,在数据类中再具体实现。这样,结点的操作也可以像链表一样通用。最后,再将数据具体形式定义成一个类,涉及数据的输入格式、输出形式、比较内容的大小等。那么,针对不同的数据管理,只要改动这部分就可以了。这样就实现程序的结构化了!
主函数,开始运行先建立一个链表类类对象,将文件中的数据读到内存中。然后再输出整个主菜单,键入相应的命令执行相应的链表类函数实现功能。最后再把修改后的链表中的数据写入文件中,退出。 六.程序重要功能的实现方法
1.添加工作记录,工资数据按工资值的大小进行排序存放。主菜单中添加工资记录的功能会先调用链表类Clist的成员函数voidAddRecord()。该函数会生成一个数据类成员和一个结点类成员,通过键盘输入员工的姓名和工资,并把数据赋值给数据类成员把数据类成员的指针赋给结点类成员,然后再调用Clist的成员函数voidinlist(CNode*node0),并把新生成的结点类指针传递过去,该函数会在原有链表中通过工资数据的比较,按工资大小顺序给该结点找到位置并插入到原有的链表中(如果链表不存在即运行该函数时头指针值为0,则该结点就赋值给链表类成员的头指针,作为链表中的唯一结点存在。)由于一开始每一个结点都是由小到大插入的,所以该链表最终工资数据一定是按工资值的大小进行排序存放的。
链表类的增加工资记录的函数: voidAddRecord() {CNode*pnode; CSalary*psal; charname0[20]; doublesalary0;
cout<<\"请输入姓名(按0结束):\"; cin>>name0;
while(strcmp(name0,\"0\")) {cout<<\"请输入工资:\"; cin>>salary0; cin.ignore(); psal=newCSalary;
psal->SetSalary(name0,salary0);
pnode=newCNode;
pnode->InputDate(psal); inlist(pnode);
cout<<\"请输入姓名(按0结束):\"; cin>>name0; }
cout< voidinlist(CNode*node0)//按照工资大小插入节点的类函数 {CNode*p0; if(phead==0) {phead=node0; n++; } else {CNode*p0,*p1; p0=phead; p1=phead->pnext; if(node0->pdata->getsalary()<=phead->pdata->getsalary()) {node0->pnext=phead; phead=node0; } else {for(inti=0;i<(n-1);i++) {if((node0->pdata->getsalary()>p0->pdata->getsalary())&&(node0->pdata->getsalary()<=p1->pdata->getsalary())) p0->pnext=node0,node0->pnext=p1; p0=p0->pnext,p1=p0->pnext; } if(node0->pdata->getsalary()>p0->pdata->getsalary()) p0->pnext=node0,node0->pnext=0; } n++; } } 2.显示工资记录。主菜单中显示工资的功能会先调用链表类Clist的成员函数voidShowList(),该函数会通过循环语句,调用每一个结点对应的结点类函数voidShowNode()函数,调用结点对应数据类成员的数据类函数voidshow()把员工的姓名和工资数据打印在显示屏上。 链表类的打印工资记录的函数 voidShowList()//打印工资记录的类函数 {CNode*p1; p1=phead; inti=0; for(;i 结点类的显示函数 voidShowNode(){pdata->show();} 数据类的显示函数 voidshow() {cout<<\"姓名:\"< 链表类的按照姓名查找工资记录的类函数: voidFindRecord()//按照姓名查找工资记录的类函数。 {cout<<\"请输入要查找的姓名\"< p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< intcompare(charaa[]) {chardd[20]; strcpy(dd,name); strlwr(dd); intbb=strcmp(aa,dd); if(bb==0) bb=1; else bb=0; returnbb; } 4.根据姓名查找并删除工资记录。主菜单中根据姓名查找并删除工资记录的功能是调用链表类中的函数void DeleteRecord()实现的。该函数在执行查询功能时与函数voidFindRecord()基本差不多也是大小写通用,但是为了方便删除结点,也是为了可以应付同名或者姓名大小写不同但是字母一样的情况出现(例如Mike,和mike),该函数建立了一个结点类的指针数组,每找到一个结点会把该结点的上一节点的指针保存在数组中(因为要更改上一结点的next指针,所以要保存上一指针),如果是头指针则把0赋给数组。接着把查询结果都打印出来,由用户选择要删除哪个用户数据。用户选择后会输出确认删除的语句,用户确认后开始删除。如果数组成员为0,则修改头指针为下一结点,如果是正常指针则修改该指针指向的next指针为下下个结点指针。 链表类中按照姓名查找并删除工资记录的函数 void DeleteRecord()//按照姓名查找并删除工资记录的类函数。 {cout<<\"请输入要查找的姓名\"< CNode *p1,*p0,*o[5]; p0=0; p1=phead; int i=0,ss=0; for(;i p0=p1; p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< cout<<\"确定要将员工\"< phead=phead->pnext; delete p5; n--; } else {CNode *p5; p5=o[kk]->pnext; p1=o[kk]->pnext->pnext; o[kk]->pnext=p1; n--; delete p5; } } else cout<<\"操作取消返回主菜单!\"< 链表类中按照姓名查找并修改工资记录的函数: void WriteRecord()//按照姓名查找并修改工资记录的类函数。 {cout<<\"请输入要查找的姓名\"< CNode *p1,*o[5],*p0; p1=phead; p0=0; int i=0,ss=0; for(;i p0=p1; p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< cout<<\"请输入修改后的工资:\"; cin>>mm; cout< { if(o[kk]==0) {CNode *p5; p5=phead; phead=phead->pnext; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } else if(o[kk]->pnext->pnext!=0) {CNode *p5; p5=o[kk]->pnext; p1=o[kk]->pnext->pnext; o[kk]->pnext=p1; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } else {CNode *p5; p5=o[kk]->pnext; o[kk]->pnext=0; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } } else cout<<\"操作取消返回主菜单!\"< 束时能将工资数据保存在原文件中。该部分的功能也是通过俩个链表类的函数void infire0()和void outfire0()实现的。在void infire0()函数中会先以二进制的模式打开文件,在把链表类的成员n(表示结点个数)写在(四个字节)文件的开头,再按照链表顺序把一个个结点对应的数据类的数据写入内存中,直到把n个结点写完。 内存写入文件的函数: void outfire0()//将内存中的链表内容转存到文件中的类函数 {ofstream outfire; outfire.open(\"aa.dat\ int bb; bb=n; outfire.write((char *)&bb,4); int k=0; CNode *p0; p0=phead; for(;k 而在函数void infire0()中对应着存储规则,会先以二进制的方式打开文档(如果文档不存在则打开失败并输出提示语句),再读取开头四个字节存入主函数中建立的链表类的n的地址,接着用一个循环语句执行一次循环语句就建立新的结点类和一个数据类成员,并把文档中接着的sizeof(CSalary)个字节读入到数据类中,把数据类的指针赋给结点类的成员pdata,修改pnxet,直至建立好n个结点,最终就利用文档中的数据建好了整个链表。 把文档中内容写入内存的函数: void infire0()//将文件中的数据读取出来到链表中 {ifstream infire; infire.open(\"aa.dat\ if(!infire) {cout<<\"未存在工资记录请添加记录\"< CSalary *p1; CNode *p0; p0=new CNode; int i=0; for(;i infire.read((char *)p1,sizeof(CSalary)); p0->pdata=p1; p0->pnext=new CNode; if(i==0) phead=p0; p0=p0->pnext; } p0->pnext=0; } } }; 七.总结 整个程序都是我们利用已学的C++知识,参考着源程序编写的,在编写过程中难免会有些东西不会,例如文件的输入和输出,为了解决这个问题恶补了一下这方面的知识。最后也成功地把这个问题解决了!源程序中也有些语句看不懂,翻翻书,在网上查查,学会了很多c++的知识!在编写这个程序中还学到了其他的东西,为了完成整个管理程序,我们把所有的功能的实现通通分解为一个个函数。把整个大的问题分解为小问题,一个个问题分工合作完成,最终完成了这个程序!能凭借自己的手完成这个程序,最后真的很有成就感,似乎明白了那些it男为什么面对着如此枯燥的代码还能津津有味的心境! 九.源程序代码 #include char name[20];//姓名 double salary;//工资 public: CSalary(void){strcpy(name,\"/0\");salary=0.0;} CSalary(char *p,double aa) {strcpy(name,p); salary=aa; } void SetSalary(char *p,double aa) {strcpy(name,p); salary=aa; } void SetSalary(double aa) { salary=aa; } double getsalary() {return salary; } char *getname() {return name; } int compare(char aa[]) {char dd[20]; strcpy(dd,name); strlwr(dd); int bb=strcmp(aa,dd); if(bb==0) bb=1; else bb=0; return bb; } void show() {cout<<\"姓名:\"< CNode(){pdata=0;pnext=0;} CNode(CNode &node) {pdata=node.pdata; pnext=node.pnext; } void InputDate(CSalary * pSal){pdata=pSal;} void ShowNode(){pdata->show();} CSalary *GetDate(){return pdata;} CNode *Getnext(){return pnext;} friend class Clist; }; class Clist //链表类 {protected: CNode *phead; int n; public: Clist(){phead=0;n=0;} ~Clist()//析构函数 {CNode *p1,*p2; CSalary *p3; p1=phead; p2=p1->pnext; p3=p1->pdata; for(int i=0;i<(n-1);i++) {delete p1,p3; p1=p2; p2=p1->pnext; p3=p1->pdata; } delete p1,p3; } void inlist(CNode *node0)//按照工资大小插入节点的类函数 { if(phead==0) {phead=node0; n++; } else {CNode *p0,*p1; p0=phead; p1=phead->pnext; if (node0->pdata->getsalary()<=phead->pdata->getsalary()) {node0->pnext=phead; phead=node0; } else {for(int i=0;i<(n-1);i++) {if((node0->pdata->getsalary()>p0->pdata->getsalary())&&(node0->pdata->getsalary()<=p1->pdata->getsalary())) p0->pnext=node0,node0->pnext=p1; p0=p0->pnext,p1=p0->pnext; } if(node0->pdata->getsalary()>p0->pdata->getsalary()) p0->pnext=node0,node0->pnext=0; } n++; } } void AddRecord()//增加工资记录的类函数 {CNode *pnode; CSalary *psal; char name0[20]; double salary0; cout<<\"请输入姓名(按0结束):\"; cin>>name0; while(strcmp(name0,\"0\")) {cout<<\"请输入工资:\"; cin>>salary0; cin.ignore();//缓冲 psal=new CSalary; psal->SetSalary(name0,salary0); pnode=new CNode; pnode->InputDate(psal); inlist(pnode); cout<<\"请输入姓名(按0结束):\"; cin>>name0; } cout< for(;i void FindRecord()//按照姓名查找工资记录的类函数。 {cout<<\"请输入要查找的姓名\"< CNode *p1; p1=phead; int i=0,ss=0; for(;i } p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< CNode *p1,*p0,*o[5]; p0=0; p1=phead; int i=0,ss=0; for(;i p0=p1; p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< if(ll==1) {if(o[kk]==0) {CNode *p5; p5=phead; phead=phead->pnext; delete p5; n--; } else {CNode *p5; p5=o[kk]->pnext; p1=o[kk]->pnext->pnext; o[kk]->pnext=p1; n--; delete p5; } } else cout<<\"操作取消返回主菜单!\"< CNode *p1,*o[5],*p0; p1=phead; p0=0; int i=0,ss=0; for(;i p0=p1; p1=p1->pnext; } if(ss==0) cout<<\"未查找到该员工数据!\"< cout<<\"请输入修改后的工资:\"; cin>>mm; cout< { if(o[kk]==0) {CNode *p5; p5=phead; phead=phead->pnext; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } else if(o[kk]->pnext->pnext!=0) {CNode *p5; p5=o[kk]->pnext; p1=o[kk]->pnext->pnext; o[kk]->pnext=p1; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } else {CNode *p5; p5=o[kk]->pnext; o[kk]->pnext=0; n--; CNode *pp; CSalary *ppp; pp=new CNode; ppp=new CSalary; pp->pdata=ppp; ppp->SetSalary(p5->pdata->getname(),mm); inlist(pp); delete p5; } } else cout<<\"操作取消返回主菜单!\"< void outfire0()//将内存中的链表内容转存到文件中的类函数 { ofstream outfire; outfire.open(\"aa.dat\ int bb; bb=n; outfire.write((char *)&bb,4); int k=0; CNode *p0; p0=phead; for(;k void infire0()//将文件中的数据读取出来到链表中 {ifstream infire; infire.open(\"aa.dat\ if(!infire) {cout<<\"未存在工资记录请添加记录\"< infire.read((char *)&bb,4); n=bb; CSalary *p1; CNode *p0; p0=new CNode; int i=0; for(;i infire.read((char *)p1,sizeof(CSalary)); p0->pdata=p1; p0->pnext=new CNode; if(i==0) phead=p0; p0=p0->pnext; } p0->pnext=0; } infire.close(); } }; void main() {cout<<\"欢迎进入工资管理系统!\"< {cout<<\"主菜单:\"< list.AddRecord();//利用类函数增加工资记录在(按照从小到大的顺序)相应位置 else if(a=='2') {list.ShowList(); char mm; cout<<\"按任意键和回车返回主菜单\"< }//利用类函数显示所有工资记录 else if(a=='3') {list.FindRecord();//利用类函数查询工资记录 char mm; cout<<\"按任意键和回车返回主菜单\"< else if(a=='4') list.DeleteRecord();//利用类函数删除工资记录 else if(a=='5') list.WriteRecord();//利用类函数修改工资记录 } list.outfire0();//调用类函数把信息保存在文件中 } 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务