输入各项信息
运用Insert函数排序并指向下一节点
申请下一结点的空间
完成循环,运用Display函数显示已输入的信息
返回头结点
4.5显示记录函数voidDisplay(structemployee*head)
这是一个不返回值的有参函数,形参为“链表头的指针”,负责对全部职工信息记录的输出显示。
算法:
先将p结点的指针指向第一个结点,用if函数判定第一个节点是否为空,不为空再用while循环依次输出p结点下的信息,直到p指针指向NULL为止。
N-S流程图如下:
建立p结点申请空间p=head,p指向第一个结点
头结点是否为空
是(if判定)否
没有数据可以显示!
p结点不为空
输出结点内各项信息
p指向下一结点
4.6查找记录函数voidQuery(structemployee*head)
这是一个不返回值的有参函数,形参为“链表头的指针”,实现按工号或姓名对某个职工进行查找,并显示所查找到的记录。
其内包含了两个子函数structemployee*Findnum(structemployee*head,intfindnum)和structemployee*Findname(structemployee*head,charfindname[])。
算法:
使用一个字符选择查找方式,根据选择调用函数。
工号查找函数structemployee*Findnum(structemployee*head,intfindnum)
这是一个有参函数,形参为“链表头的指针”,用来查找指定工号的职工信息,函数结束后,带回一个指向职工信息的指针。
算法:
将指针p指向工号,依次与寻找的工号进行对比,相等则返回指针p。
N-S流程图如下:
建立p结点申请空间p=head,p指向第一个结点
头结点是否为空
是(if判定)否
没有数据可以显示
p结点不为空
工号是否相等
是否
跳出循环
p指向下一结点
姓名查找函数structemployee*Findname(structemployee*head,charfindname[])
这是一个有参函数,形参为“链表头的指针”,用来查找指定工号的职工信息,函数结束后,带回一个指向职工信息的指针。
算法:
将指针p指向工号,依次与寻找的工号进行对比,相等则返回指针p。
N-S流程图如下:
建立p结点申请空间p=head,p指向第一个结点
头结点是否为空
是(if判定)否
没有数据可以显示
p结点不为空
姓名是否相等(调用strcmp函数)
是否
跳出循环
p指向下一结点
4.7删除记录函数structemployee*Delete(structemployee*head,intfindnum)
这是一个有参函数,形参为“链表头的指针”和“要删除信息的工号”,先输入要删除的职工记录的工号,找到后进行删除。
算法:
从p指向的第一个结点开始,检查该结点中的num值是否等于输入的要求删除的那个工号。
如果相等就将该结点删除,如不相等,就将p后移一个结点,再如此进行下去,直到遇到表尾为止。
N-S流程图如下:
是否head->num等于findnum)
是否
删除head结点
P指向head的下一结点
P不为NULL且p->num不等于findnum
P移向下一结点
否
是否p->num等于findnum
是
删除结点p
释放p指针返回head指针
4.8有序插入函数structemployee*Insert(structemployee*head,structemployee*p)与structemployee*Insertage(structemployee*head,structemployee*p)
这是一个有返回值的有参函数,形参为“链表头的指针”和一个指针p,返回一个指向链表头的指针head。
算法:
比较新插入的结点与其他结点中num(age)的值,找出结点的位置,进行插入。
N-S流程图如下:
头结点是否为空
是否
P结点为第一个结点
head=p
p->next=NULL
判断p的工号(年龄)是否小于head的工号(年龄)
是否
则p结点应该插入到head前面,所以p->next=head;
head=p
p1=head,判断p->num(age)是否大于p1->num(age)且p1的下一结点不为
p0=p1p1指向下一结点
继续循环
判断
是否
将p结点插入到p0与p1之间
判断p的工号(年龄)与p1的工号(年龄)
是否不等
否是
P插入到p1后面,NULL接到p后面
返回head指针
4.9保存数据到文件函数voidSave(structemployee*head)
这是一个不返回值的有参函数,形参为“链表头的指针”,可以把职工记录保存在电脑上指定的TXT文件中。
p=head
文件是否能打开
否是
输出出错信息
当p不为空
fprintf()函数将信息输入进文件
p=p->next,指针后移
关闭文件
4.10从文件读数据函数structemployee*Read(structemployee*head)
这是一个有返回值的有参函数,形参为“链表头的指针”,根据文件地址进行读取文件,最后返回头指针head。
N-S流程图如下:
定义指针变量p,文件指针fp
文件是否能打开
否是
输出出错信息
当文件未结束
选择排序方式
运用Insert函数建立链表
运用Insertage函数建立链表
fscanf()函数将信息从文件中输出
关闭文件
5.调试分析
(1)刚开始没有使用链表,程序运行后,因为没有在字符后面输入’\0’,结果运行后显示的是一堆乱码!
然后查阅了一些书籍,决定使用链表来完成,果然使用链表后,乱码就消失了。
(2)最初使用链表定义读取文件的函数时,运行之后读取不是很成功,显示一堆乱码,后来查阅资料才知道,是因为读取文件时,分配的字符串长度正好与文件长度相等,造成字符串末尾没有‘\0’,后来经过重新设计,顺利的解决了这个问题。
(3)最初设计时插入功能与排序功能是由两部分组成,后来查阅了书籍后发现两者可以合二为一,更加简洁,就将其学习后运用到了自己的编程中。
(4)刚开始界面设计的有点乱,后来经过许多次的修改,并且学习了清屏功能的用法,整个界面顿时清爽了很多。
(5)用两种排序最初是放在同一个函数中,造成排序重复,于是重新建立了一个新的函数用来排序,在读取文件时进行排序,然后系统终于可以运用两种排序方式。
6.总结
经过十几天的的C语言课程设计,感觉自己受益良多!
首先,链表本来课是上的很少的,掌握的并不是很熟练,但这个课程设计里面主要都是用链表,因为要达到这些的功能,使用链表更加方便,便于操作,但也不容易理解,所以在这方面我花了很多的时间看课本和上网查阅资料,也是自己对C语言了解的更透彻。
其次,在做课程设计的过程中,我也发现了平时很多没有注意到的问题,例如:
字符串后要添加’\0’才不会产生乱码,函数引用前要声明…….
更重要的是,这次课程设计虽然花了我不少时间,但这些时间很值得,我在这些时间里去学会了自己探索,自己学习,自己去建立一个简洁的操作界面。
在这写日子中我也懂得了,编程不仅需要程序好,而且运行界面还要给人以简洁明朗的感觉。
我相信这次的课程设计为我以后的专业课打下一个很好的基础。
代码:
#include
#include
#include
#include
#include
#defineLENsizeof(structemployee)
#defineDAT_FILENAME"D:
\\职工档案管理系统.txt"
structdate
{
intyear;
intmonth;
intday;
};
structemployee
{
intnum;
charName[12];
intage;
charsex;
charphone[15];
charaddress[40];
structdatebirthday;
chardegree[10];
charsalary[10];
structemployee*next;
};
voidMainmenu();
voidHelp();
voidDisplay(structemployee*head);
structemployee*Insertage(structemployee*head,structemployee*p);
structemployee*Findnum(structemployee*head,intfindID);
structemployee*Findname(structemployee*head,charfindname[]);
structemployee*Input(structemployee*head);
voidQuery(structemployee*head);
structemployee*Edit(structemployee*head);
structemployee*Insert(structemployee*head,structemployee*p);
voidSave(structemployee*head);
structemployee*Read(structemployee*head);
structemployee*Delete(structemployee*head,intfindID);
voidMainmenu()
{
printf("+###########################职工档案管理系统##########################+\n");
printf("+\t\t\t1--档案录入\t2--信息修改\t\t\t+\n");
printf("+\t\t\t3--内容查看\t4--保存文件\t\t\t+\n");
printf("+\t\t\t5--打开文件\t6--友情帮助\t\t\t+\n");
printf("+\t\t\t********0--安全退出********\t\t\t+\n");
printf("+\t\t\t如您第一次使用本程序请按“6”阅读帮助\t\t+\n");
printf("+#######################################################################+\n");
printf("\t\t请选择(0——7):
");
}
voidHelp()
{
printf("\n\t\t\t欢迎进入帮助系统!
\n\n");
printf("\t1.请按照主菜单提示选择所需执行功能的数字代号!
\n");
printf("\t2.所有文件请按照提示规范输入,请勿超出文字限制个数!
\n");
printf("\t3.刚开始执行程序时若需要文本文件里的数据请先进行打开文件!
\n");
printf("\t4.录入信息和修改信息以后,请切记需要保存!
\n");
printf("\t5.如您执行文件追加,则无需打开文件!
\n");
printf("\t6.遇到系统错误,请勿自行解决,如不需进行编辑,请及时退出系统!
\n");
printf("\t7.录入信息时请避免工号重复,否则录入失败!
\n");
printf("\t祝您使用愉快!
");
printf("\n");
}
voidDisplay(structemployee*head)
{
structemployee*p;
printf("\n工号\t姓名\t年龄\t性别\t电话\t\t地址\t出生年月学历工资\n");
p=(structemployee*)malloc(LEN);
p=head;
if(head!
=NULL)
while(p!
=NULL)
{
printf("%-d\t%-s\t%-d\t",p->num,p->Name,p->age);
printf("%-c\t%-s\t%-s\t",p->sex,p->phone,p->address);
printf("%-d%d%d",p->birthday.year,p->birthday.month,p->birthday.day);
printf("%-s",p->degree);
printf("%-s\n",p->salary);
p=p->next;
}
else
printf("没有数据\n");
}
structemployee*Findnum(structemployee*head,intfindnum)
{
structemployee*p;
p=(structemployee*)malloc(LEN);
p=head;
if(head!
=NULL)
while(p!
=NULL)
{
if(p->num==findnum)
break;
p=p->next;
}
else
printf("没有数据\n");
returnp;
}
structemployee*Findname(structemployee*head,charfindname[])
{
structemployee*p;
p=(structemployee*)malloc(LEN);
p=head;
if(head!
=NULL)
while(p!
=NULL)
{
if(strcmp(p->Name,findname)==0)
break;
p=p->next;
}
else
printf("没有数据\n");
returnp;
}
structemployee*Input(structemployee*head)
{
intn,i;
structemployee*p;
p=(structemployee*)malloc(LEN);
printf("\n请输入本次录入的职工人数");
scanf("%d",&n);
for(i=0;i{
system("cls");
printf("请输入第%d个职工的工号:
\t",i+1);
scanf("%d",&p->num);
printf("\t\t姓名:
\t");
scanf("%s",p->Name);
printf("\t\t年龄:
\t");
scanf("%d",&p->age);
printf("\t\t性别(男M、女W):
");
scanf("%s",&p->sex);
printf("\t\t电话:
\t");
scanf("%s",p->phone);
printf("\t\t地址:
\t");
scanf("%s",p->address);
printf("\t\t出生年月(年月日):
");
scanf("%d%d%d",&p->birthday.year,&p->birthday.month,&p->birthday.day);
printf("\t\t学历:
\t");
scanf("%s",p->degree);
printf("\t\t工资:
\t");
scanf("%s",p->salary);
head=Insert(head,p);
p=(structemployee*)malloc(LEN);
}
printf("\n输入后信息为:
\n");
Display(head);
return(head);
}
voidQuery(structemployee*head)
{
charselect;
intfindnum;
charfindname[12];
structemployee*p;
printf("请选择查询方式:
\n");
printf("1--按工号查询\n2--按姓名查询\n");
printf("请选择(1-2):
");
select=getche();
getch();
system("cls");
switch(select)
{
case'1':
printf("\n按工号查询\n请输入职工的工号");
scanf("%d",&findnum);
if((p=Findnum(head,findnum))!
=NULL)
{
printf("\n查找结果如下\n");
printf("\n工号\t姓名\t年龄\t性别\t电话\t\t地址\t出生年月学历工资\n");
printf("%d\t%s\t%d\t",p->num,p->Name,p->age);
printf("%c\t%s\t%s\t",p->sex,p->phone,p->address);
printf("%d%d%d",p->birthday.year,p->birthday.month,p->birthday.day);
printf("%s",p->degree);
printf("%s\n",p->salary);
}
else
printf("您输入的工号不存在!
\n");
break;
case'2':
printf("\n按姓名查询\n请输入职工的姓名:
");
scanf("%s",&findname);
if((p=Findname(head,findname))!
=NULL)
{
printf("\n查找结果如下\n");
printf("\n工号\t姓名\t年龄\t性别\t电话\t\t地址\t出生年月学历工资\n");
printf("%d\t%s\t%d\t",p->num,p->Name,p->age);
printf("%c\t%s\t%s\t",p->sex,p->phone,p->address);
printf("%d%d%d",p->birthday.year,p->birthday.month,p->birthday.day);
printf("%s",p->degree);
printf("%s\n",p->salary);
}
else
printf("您输入的姓名不存在\n");
break;
default:
printf("选择错误!
\n");
}
}
structemployee*Edit(structemployee*head)
{
intfindnum;
charselect;
structemployee*p;
printf("\n请输入职工的工号:
");
scanf("%d",&findnum);
if((p=Findnum(head,findnum))!
=NULL)
{
printf("请选择修改方式:
\n");
printf("1--修改信息\n2--删除信息\n");
printf("请选择(1---2):
");
select=