数
据
结
构
大
作
业
作业题目:职工信息管理系统姓名:叶尔凯西·革命
学号:08080605227
班级:计算机07-(1)班指导教师:
日期:2010年6月13日
职工信息管理系统
(伊犁师范学院计算机科学系07-1班叶尔凯西) 摘要:本程序实现了一个职工管理系统中的常见功能, 包括建立职工信息, 输出职工信息以及根据职工号、部门号、职工的工资进行排序的功能, 还有对整个职工表的清空的功能.
关键词:职工管理;职工管理系统;数据排序;排序
1 有关程序设计的引言
随着信息技术的发展, 在更多的情况下人们借助计算机来交流和储存信息,确切地说是用计算机程序来管理当今的庞大的信息,提高了信息技术的发展. 在很多场合下计算机的这样管理程序的功能都派上了用场, 譬如就职工信息管理而言, 就得有个使用方便, 功能全面, 通俗易懂的管理程序是必备的. 从这一点出发, 本人设计出了一个计算机管理程序“职工管理系统”, 接下来就说明该程序的功能.
2 程序简介
该程序的功能可以从以下十个方面来说明:
1.输入:添加一个职工记录
2.输出:输出全部职工记录
3.按职工号排序:通过职工号指针将职工记录按职工号从小到大连接起来
4.按职工号输出:沿职工号指针输出全部职工记录
5.按部门号排序:通过部门号指针将职工记录按部门号从小到大连接起来
6.按部门号输出:沿部门号指针输出全部职工记录
7.按职工工资排序:通过职工工资指针将职工记录按职工工资从小到大连接起来
8.按职工工资输出:沿职工号指针输出全部职工记录
9.全清:删除职工文件中有的全部记录
10.存储退出:将单链表中的全部结点存储到职工文件中,然后退出程序运行过程3 实验仪器
每人1台安装有Turbo C 的普通学生电脑。
4 实验内容
利用静态链表来实现这一综合算法。
5 实验重点
掌握链表的常用操作。
6 程序功能及其实现详解
下面将详细介绍本程序的所有功能的实现方式即代码的含义, 在设计本程序时, 本人尽可能地用了质量好一点的算法, 因为本程序有以上10个功能, 显然应有实现相应功能的10个函数, 不过在设计时本人将输出部分统一到一个函数中来实现. 因为在面向过程的程序设计中包括面向对象的程序设计一般都没有一种职工类型的变量, 因此在一开始得建立一个结构体变量即所谓的职工类型, 此部分的代码如下:typedef struct node
{
int no,depno,salary; /*no为职工号,depno为部门号,salary为工资数*/
char name[maxsize]; /*职工姓名*/
struct node *pno,*pdepno,*psalary,*next; /*pno为职工号指针,pdepno为部门号指针,psalary 为工资数指针*/
}employee;
显然, 结构体中的成员包括职工姓名、职工号、部门号、职工工资、以及一些指向其它该类型结点的指针变量.
下面介绍实现第一个功能的代码:
employee *insert(employee *head)
{
employee *h;
if(head==NULL)
{
employee *s,*h1;
h1=malloc(sizeof(employee));
s=malloc(sizeof(employee));
clrscr();
printf("please input employee's name:");
scanf("%s",s->name);
printf("please input employee's number:");
scanf("%d",&s->no);
printf("please input department's number:");
scanf("%d",&s->depno);
printf("please input employee's wages:");
scanf("%d",&s->salary);
s->pno=NULL;
s->pdepno=NULL;
s->psalary=NULL;
s->next=NULL;
h1->pno=NULL;
h1->pdepno=NULL;
h1->psalary=NULL;
h1->next=s;
h=h1;
printf("all done!\n");
getch();
}
if(head!=NULL)
{
employee *s,*p,*h1;
h1=head;
p=h1->next;
s=malloc(sizeof(employee));
if(p->next!=NULL)
{
while(p->next!=NULL)
p=p->next;
clrscr();
printf("please input employee's name:");
scanf("%s",s->name);
printf("please input employee's number:");
scanf("%d",&s->no);
printf("please input department's number:");
scanf("%d",&s->depno);
printf("please input employee's wages:");
scanf("%d",&s->salary);
s->pno=NULL;
s->pdepno=NULL;
s->psalary=NULL;
s->next=NULL;
p->next=s;
h=h1;
printf("all done!\n");
getch();
}
if(p->next==NULL)
{
clrscr();
printf("please input employee's name:");
scanf("%s",s->name);
printf("please input employee's number:");
scanf("%d",&s->no);
printf("please input department's number:");
scanf("%d",&s->depno);
printf("please input employee's wages:");
scanf("%d",&s->salary);
s->pno=NULL;
s->pdepno=NULL;
s->psalary=NULL;
s->next=NULL;
p->next=s;
h=h1;
printf("all done!\n");
getch();
}
}
return(h);
}
本函数实现的功能是插入一个职工记录到职工表中, 为此我们还得把这个函数的返回类型设计成之前建立的结构体类型的指针函数, 而函数的参数是一个职工类型的头指针变量, 在main函数中也同时建立一个头指针变量, 且给它赋空值, 在调用该函数时就把空指针传给插入函数,当职工表为空即第一次插入一个职工记录时,很自然传给插入函数的头指针的值为空有此来判断是新建立一个结点还是在已有的结点后插入一个(连接)结点, 若头指针不为空, 即已有一个或多个结点在职工记录表中, 则只能插在最后一个节点之后. 当职工表中只有一个职工记录时, (即head->next->next==NULL时)插在第一个结点后面, 当职工表中的结点多于两个时就插在最后一个结点后面.
下面说明第二个功能的实现部分:
void output(employee *head)
{
employee *p;
if(head==NULL)
{
clrscr();
printf("The table is empty,please insert before!\n");
}
else
{
p=head->next;
if(p!=NULL)
{
clrscr();
printf("all information of employee\n\n");
printf("employee's name employee's number department's number employee's wages\n");
while(p!=NULL)
{
printf("\t%s\t\t%d\t\t\t%d\t\t %d\n",p->name,p->no,p->depno,p->salary);
p=p->next;
}
}
}
getch();
}
本函数的功能是实现职工记录表中的所有记录,若没有任何一个记录, 则输出一个提示语句来提醒使用者职工表为空, 若不为空则从第一号结点开始输出一直到最后一个结点(以表格形式输出).
下面分别介绍根据职工号、部门号以及职工工资来排序的函数:
employee *SortByEmployeeNumber(employee *head)
{
employee *p,*q,*s,*h,*temp;
temp=malloc(sizeof(employee));
h=head;
for(s=head->next; s!=NULL; s=s->next)
{
p=s;
for(q=s->next; q!=NULL; q=q->next)
if((p->no)>(q->no))
p=q;
}
if(p!=s)
{
temp->no=s->no;
temp->depno=s->depno;
temp->salary=s->salary;
strcpy(temp->name,s->name);
s->no=p->no;
s->depno=p->depno;
s->salary=p->salary;
strcpy(s->name,p->name);
p->no=temp->no;
p->depno=temp->depno;
p->salary=temp->salary;
strcpy(p->name,temp->name);
}
}
clrscr();
printf("all done!\n");
getch();
return(h);
}
employee *SortByDepartmentNumber(employee *head) {
employee *p,*q,*s,*h,*temp;
temp=malloc(sizeof(employee));
for(s=head->next; s!=NULL; s=s->next)
{
p=s;
for(q=s->next; q!=NULL; q=q->next)
{
if((p->depno)>(q->depno))
p=q;
}
if(p!=s)
{ t emp->no=s->no;
temp->depno=s->depno;
temp->salary=s->salary;
strcpy(temp->name,s->name);
s->no=p->no;
s->depno=p->depno;
s->salary=p->salary;
strcpy(s->name,p->name);
p->no=temp->no;
p->depno=temp->depno;
p->salary=temp->salary;
strcpy(p->name,temp->name);
}
}
clrscr();
printf("all done!\n");
getch();
return(h);
}
employee *SortByWages(employee *head)
{
employee *p,*q,*s,*h,*temp;
temp=malloc(sizeof(employee));
h=head;
for(s=head->next; s!=NULL; s=s->next)
{
p=s;
for(q=s->next; q!=NULL; q=q->next)
{
if((p->salary)>(q->salary))
p=q;
}
if(p!=s)
{
temp->no=s->no;
temp->depno=s->depno;
temp->salary=s->salary;
strcpy(temp->name,s->name);
s->no=p->no;
s->depno=p->depno;
s->salary=p->salary;
strcpy(s->name,p->name);
p->no=temp->no;
p->depno=temp->depno;
p->salary=temp->salary;
strcpy(p->name,temp->name);
}
}
clrscr();
printf("all done!\n");
getch();
return(h);
}
第一个就是根据职工号进行对职工表中的所有记录进行从小到大的排序, 不过在这里说明一点, 每一种排序都有相同的一点就是它们都是职工指针类型函数, 且参数也是职工类型的头指针. 在根据职工号来对职工记录表排序这个函数中采用的排序算法是直接选择排序法, 即整体上有两层循环,第一层负责一个职工类型的指针变量从一号结点开始到最后一个结点之间的循环, 其意义是把之前定义的职工类型的指针变量存放一号结点的地址, 而还有一个该类型的指针变量存放的是二号结点的地址, 然后比较职工号的大小, 然后把小的一个的地址存入第一个指针变量, 在程序中是p指针, 然后第二层循环起效一直到最后一个结点为止跟一号结点的职工号比较大小最终把最小的一个的结点的地址存入p指针, 然后该p指针的一切信息跟一号位置的结点的一切信息进行交换, 若p指针最终存放的是一号结点的地址, 则无需交换. 接着外层循环起效, 把二号结点的职工号跟三号结点开始(内外层循环的作用下两个指针往后移一步)比较, 重复上述操作, 一直到最后一个结点为止, 最终实现把职工记录表的信息按职工号从小到大的排序. 因为根据部门号排序和根据职工工资来进行排序是同样的结构, 所以在这里不进行详细说明, 整个函数中只有一条语句不一样, 那就是根据职工号、根据部门号以及根据职工工资来进行比较时p指针一直存放职工号最小的结点、部门号最小的结点或职工工资最小的结点地址.
下面讲述删除功能的实现:
employee *DeleteAllInformation()
{
employee *h;
h=NULL;
clrscr();
printf("all done!\n");
getch();
return(h);
}
该函数是利用职工类型的指针变量赋予空值, 然后返回给头指针, 从而让原来存
有职工记录的表置空.
本程序还有一个返回类型为空的函数, 即程序一开始所呈现出的画面. void show()
{
clrscr();
printf("*********************************************************************\n");
printf("\n");
printf("welcome to use manage employee's information micro syst em\n");
printf("\n");
printf(" a.insert a information of employee\n");
printf(" b.output.output all information of employee\n");
printf(" c.sort by employee's number\n");
printf(" d.output all information by employee's number\n");
printf(" e.sort by department's number\n");
printf(" f.output all information by department's number\n");
printf(" g.sort by employee's wages\n");
printf(" h.output all information by employee's wages\n");
printf(" i.delete all employee's information\n");
printf(" j.save\n");
printf(" 0.exit\n");
printf("*****************************************************************\n");
}
接着就是实现保存功能的函数,其代码如下:
void save(struct employee *head)
{
FILE *file;
employee *p;
if((file=fopen("d:\\职工记录表.txt","wb"))==NULL)
printf("can not open file\n");
fprintf(file,"\r\n"); /*将换行符号写入文件*/
fprintf(file,"employee's name employee's number department's number employee's wages\r\n");
for(p=head->next;p!=NULL;p=p->next)
{
fprintf(file,"\t%s\t\t%d\t\t\t%d\t\t %d\r\n",p->name,p->no,p->depno,p->salary); /*写入记录*/
fprintf(file,"\r\n"); /*将换行符号写入文件*/ }
fclose(file); /*关闭文件*/
clrscr();
printf("save done!\n");
getch();
}
下面说明整个程序的核心main函数, 因为任何一个程序都是从main函数开始进行的, 之所以因为如此, 所以必须说明main函数:
main()
{
char flag;
employee *head;
head=NULL;
show();
scanf("%c",&flag);
while(flag != '0')
{
switch(flag)
{
case 'a': head=insert(head);
show(); break;
case 'b': output(head);
show(); break;
case 'c': head=SortByEmployeeNumber(head);
show(); break;
case 'd': output(head);
show(); break;
case 'e': head=SortByDepartmentNumber(head);
show(); break;
case 'f': output(head);
show(); break;
case 'g': head=SortByWages(head);
show(); break;
case 'h': output(head);
show(); break;
case 'i': head=DeleteAllInformation();
show(); break;
case 'j': save(head);
show(); break;
}
scanf("%c",&flag);
}
}
显而易见, 在main函数中除了以上说过的职工类型的头指针变量外还有一些其他东西, 那就是来提供选择功能的switch case语句, 之所以本函数能进行不同的功能的选择就是因为main函数中的while循环中的switch case语句, 利用它选择不同的函数来实现不同的功能, 即本程序的十个功能.
7 程序运行过程详解
本程序包括输入一个职工记录,输出全部职工记录,根据职工号排序并输出,根据部门号排序并输出,根据职工工资排序并输出,清空职工记录表,保存职工记录表即生成txt文本文档和退出等功能,当我们运行程序是会出现如图1所示的窗口,其中可发现有以上说明的功能,根据旁边的小写英文字母来进行选择,方法是输入相应的
小写英文字母并回车就会进入相应的功能界面.
图1 程序一开始运行时的界面、即主界面
1.输入一个职工记录到职工记录表中
当在如图1所示的界面中的时候,即我们一开始运行程序的时候,要是想输入一个职工记录到职工记录表中去,则可以选择主界面中的第一个选项(输入a并回车),则会出现如图2所示的要求输入职工基本信息的窗口,上面的内容包括职工的姓名、职工的号码、部门的号码及职工工资的参数.
图2 输入一个职工的相关参数
可发现当我们输入完最后一个参数后按回车键则会出现全部参数输入完毕的提示信息以提示用户本次输入结束,在此界面中可再次敲一下回车键来返回到如图1所示
的主界面中,当我们返回到主界面以后若还想继续输入职工记录,可重复上述操作来进行职工记录的输入,不过这个时候这种操作应称作插入记录,显而易见选项1不仅可以输入职工记录且还可以插入职工记录到职工记录表中.我们假定已经有三个职工记录被输入进去,以便解释后部分排序的功能.
2.输出全部职工记录
当我们已经输入完毕一个或多个职工记录以后就可以进行输入操作了,方法是在如图1所示的主界面中选择选项二(输入b并回车),则可以看到之前输入的全部职工记录了,如图3所示.
图3 输出全部职工记录
可发现我们输入记录以表格形式输入到了窗口中,以便我们查阅.
值得一提的是如果职工记录表中什么记录都没有的前提下进行输出功能,因为记录表为空,自然不能输入任何记录给我们,这时会出现如图4所示的窗口,以提示用户现在职工记录表为空,为此必须先进性输入操作.
图4 当职工记录表为空的前提下进行输入功能
3.根据职工号对整个职工记录表进行排序并输出
当职工记录表中有两个或以上个记录时,我们可以根据职工号进行对整个职工记录表排序,方法是在如图1所示的主界面中选择选项三(输入c并回车),则会出现如图5所示的窗口以表示职工记录表以排序完毕.
图5 当我们对职工记录表进行排序完毕的时候出现的窗口要是想查看刚刚被排过序的职工记录表,则可以在此窗口中敲一下回车键以返回到主界面后,在主界面中选择第四选项(输入d并回车),则会出现如图6所示的窗口.
图6 根据职工号排序后所输出的窗口
跟之前输出的记录表相比较(图3和图6进行比较)发现职工记录表以职工的号码排序过了(升序).
4.根据部门号对整个职工记录表进行排序并输出
当在职工记录表中有两个或以上个记录时,我们还可以根据职工记录表中的职工参数的一项即部门号对整个职工记录表进行排序.方法是在如图1所示的主界面中选择选项五(输入e并回车),则会出现如图5所示的窗口,以表示根据部门号的排序已经完毕.要是想查看刚刚排序过的记录表,则在主界面中选择选项六(输入f并回车),这时会出现如图7所示的窗口.
图7 根据部门号排序后所输出的窗口
跟之前的记录表进行比较(图6和图7进行比较)可发现职工记录表已经根据部门
号排序过了.
5.根据职工工资对整个职工记录表进行排序并输出
当职工记录表中有两个或以上个记录时,我们还可以根据职工参数的一项,即职工工资对整个职工记录表排序,方法是在如图1所示的主界面中选择选项六(输入g 并回车),会出现如图5所示的界面. 若想查看已排序过的职工记录表,则在如图1所示的职工记录表中选择选项八(输入h并回车),会出现如图8所示的窗口.
图8 根据部门号排序后所输出的窗口
跟前一次的记录比较发现(图7跟图8进行比较),职工记录表中的记录已经根据职工的工资排序过了.
6.清空职工记录表
当我们想重新开始输入职工记录或者当前的记录无需而想重新开始输入记录的时候,就可以使用清空职工记录表这一功能.方法是程序主界面中选择选项九(输入i并回车),则会出现如图5所示的窗口,以表示职工记录表已经清空,在此界面中想返回到主界面则敲一次回车键即可,若这个时候(即职工记录表已为清空)选择选项二,输入全部职工记录,则会出现如图4所示的窗口,以提示我们职工记录表为空,为此我们必须先输入记录进去才行.
7.保存已有的记录即生成txt文本文档文件
本程序不仅可以实现输入、输出、排序(根据不同的项目)、删除等功能且还可以把已有的记录保存起来,以便使用. 实现保存功能的方法是,在如图1所示的主界面中我们选择选项十(输入j并回车),则会出现如图9所示的窗口,以提示我们保存成功.
图9 保存职工记录表成功(即已经生成了职工记录表)
保存成txt文本文档的文件的位置在运行该程序的微机中D驱动器根目录中,这一功能是在编写程序时已经规定好了,有关保存位置的代码如下:
if((file=fopen("d:\\职工记录表.txt","wb"))==NULL)
printf("can not open file\n");
可发现保存成txt文本文档的文件名也是在编写程序时定下来的.我们可以到D盘的根目录中去找一找“职工记录表.txt”的文件打开看,则会出现如图10所示的窗口.
图10 生成的txt文本文档
8.退出程序. 在如图1所示主界面中选择选项十一(输入0并回车),则会退出程序.