因为这是在学习了一段时间后才写的程序,一些知识都是前面学过的,所以我有关前面所学只是没有写的特别详细,只是把我在写的过程中被提醒或者被检查出来的错误写了上去。
该系统基于结构体与链表创建,有链表基本的增删查改,排序,查找,插入,文件的创建,保存,读取和一些小功能。
也同样优缺点:插入指定位置,能够插入到指定位置,但退不出循环,创建的临时指针并未释放,可能指向该电脑未知内存,萌新慎重copy,不建议copy全部代码。
有些代码粘贴过来原有层次分类没有粘贴上。
代码如下(示例):
#include
#include
#include
#include
typedef struct Worker{
int number;
char name[20];
char sex[2];
int year;
int month;
int day;
char degree[20];
struct Worker *next;
}WOR;
在结构体中定义数值域与指针域,数值域储存员工信息,指针域储存要连接的结构体地址,
代码如下(示例):
void menu();//菜单
void showall(WOR *head);//显示所有员工信息
void attend(WOR *head); //添加员工信息
void print(WOR *head);//查找某一员工信息
void save(WOR *head);//保存职工信息(只有值,用于文件读取)
void save1(WOR *head);//保存职工信息(有值对应的具体信息,用于用户查阅)
void delte(WOR *head);//删除职工信息
void change(WOR *head);//改变职工信息
void order(WOR *head);//对职工信息排序
void read(WOR *head);//读取职工信息
void insert(WOR *head);//插入职工信息
void save2(WOR *head);//保存职工信息(排序后的文件)
在调用函数中需要加个小程序:进入函数需要有直接退出功能,以便不进行任何修改便可以直接退出。
代码如下(示例):
在主函数中对头指针申请空间,后面所有函数定义void类型传入参数头指针,引用头指针时最好不要直接使用,定义一个指针为头指针再进行使用。
如果链表为空或者文件为空都要有一一对应错误提示
int main()
{
WOR *head;
head=(WOR*)malloc(sizeof(WOR));
head->next=NULL;
while(1){
menu();
char n[1000];
printf("请选择");
scanf("%s",n);
int a=strlen(n);
if(a>=2)
{
printf("你输入的什么东西,拉出去,糟蹋了\n");
system("pause");
continue;
}
switch(n[0])
{
case '1':
read(head);
system("pause");
showall(head);
system("pause");
break;
case '2':
attend(head);
save(head);
save1(head);
system("pause");
break;
case '3':
delte(head);
save(head);
save1(head);
system("pause");
break;
case '4':
change(head);
save(head);
save1(head);
system("pause");
break;
case '5':
read(head);
print(head);
system("pause");
break;
case '6':
system("cls");
order(head);
save2(head);
system("pause");
break;
case '7':
insert(head);
save(head);
save1(head);
system("pause");
break;
case '8':
printf("欢迎下次使用\n");
system("pause");
exit(1);
break;
default:printf("别瞎输,只能输1-8\n");system("pause");break;
}
}
return 0;
}
void menu()//制作菜单
{
system("cls");//清屏
printf(" 请规范输入操作,不要输入乱七八糟的的东西 \n");
printf("**************************************************\n");
printf("-------------欢迎来到喵喵嗷的管理系统-------------\n");
printf(" 1-查看当前所有的职工信息 \n");
printf(" 2-添加职工信息 \n");
printf(" 3-删除职工信息 \n");
printf(" 4-修改职工信息 \n");
printf(" 5-查看某一员工信息 \n");
printf(" 6-按职工号对职工排序 \n");
printf(" 7-插入职工信息 \n");
printf(" 8-退出 \n");
return;
}
注:只能输入具有该指令的数字,输入其他具有相对应的报错提示
注:因为我定义的是指字符数组输入,并且输入超过数组第一位就自动报出乱打错误
代码如下(示例):
添加解析:在主函数中定义的头指针进行调用,定义新的临时指针用头指针依次链接,这是头插法
在添加函数中根据结构体中的定义,对职工号要有查重操作,性别不能有除男女外其他,出生年月天都应该有他的限定,不能不符合常理,学位也要有对应的真是学位限制。
我没有对月份是30天还是31天的判断,以及是否是闰年对应2月天数限制,有精力和能力的人可以加以限制,完善代码。
void attend(WOR *head)//添加员工信息
{
int flag,i,a;
char n[20];
WOR *p=head;
WOR *s;//临时储存职工数据
printf("输入0退出,其他继续\n");
scanf("%s",n);
if(n[0]=='0')
return;
else
{
printf("请选择要添加职工信息的个数");
scanf("%d",&i);
if(i<=0)
return;
else
while(i)
{
s=(WOR*)malloc(sizeof(WOR));
tp:printf("请输入职工号");
scanf("%d",&s->number);
WOR *q=head->next;
while(q)
{
a=q->number;
if(s->number==a)
{
printf("该职工号已被使用,其选择其他喜欢的职工号");
goto tp;
}
q=q->next;
}
printf("请输入姓名:");
scanf("%s",s->name);
getchar();
printf("请输入性别: w/m ");
while(1)
{
scanf("%s",s->sex);
if(strcmp("w",s->sex)==0)
break;
if(strcmp("m",s->sex)==0)
break;
if(strcmp("W",s->sex)==0)
break;
if(strcmp("M",s->sex)==0)
break;
printf("不要创造新物种,请按要求输入");
}
printf("请输入出生年份:");
while(1)
{
scanf("%d",&s->year);
if(s->year<0)
{
printf("年份不能为负,请重新输入");
continue;
}
else if(s->year>=0&&s->year<1000)
{
printf("年份太小,请重新输入");
}
else
break;
}
printf("请输入出生月份:");
while(1)
{
scanf("%d",&s->month);
if(s->month<=0||s->month>12)
{
printf("不要创造新月份,请重新输入");
continue;
}
else
break;
}
printf("请输入出生天:");
while(1)
{
scanf("%d",&s->day);
if(s->day<=0||s->day>31)
{
printf("不要创造新天数,请重新输入");
continue;
}
else
break;
}
printf("请输入职工学位:\n");
printf("注意:学历有专科,本科,研究生,博士\n");
while(1)
{
scanf("%s",s->degree);
if(strcmp(s->degree,"专科")!=0&&strcmp(s->degree,"本科")!=0&&strcmp(s->degree,"研究生")!=0&&strcmp(s->degree,"博士")!=0)
{
printf("请按要求重新输入");
}
else
break;
}
printf("\n");
while(p->next)
p=p->next;
p->next=s;
p=s;
p->next=NULL;
i--;
}
printf("创建成功\n");
return ;
}
}
注:添加一次员工信息还需要能够完成下一次添加。
删除一个职工信息,让它的前一个指针直接连接到它的下一个指针,该指针脱离链表,再释放掉。
删除一个职工信息需要加个小程序:确定是否真的删除不想删除可以直接退出。
代码如下(示例):
void delte(WOR *head)//删除函数
{
WOR *q=head;
if(q->next==NULL)
{
printf("无员工信息,可选择添加员工信息以便吃掉\n");
}
else
{
WOR *p=q->next;
char a[20];
showall(head);
printf("请输入要吃掉职工的职工号");
int n;
scanf("%d",&n);
while(p){
if(n==p->number)
{
printf("职工号:%d\n",p->number);
printf("姓名:%s\n",p->name);
printf("性别:%s\n",p->sex);
printf("出生年份:%d\n",p->year);
printf("月份:%d\n",p->month);
printf("天:%d\n",p->day);
printf("学位:%s\n\n\n",p->degree);
printf("请选择是否继续修改,0吃掉,其他都不吃掉");
scanf("%s",a);
if(strcmp(a,"0")==0)
{
q->next=p->next;
free(p);
p=NULL;
printf("该员工信息已被吃掉");
return;
}
else
return;
}
printf("该员工信息已被吃掉");
q=p;
p=p->next;
}
}
}
查询所有职工信息:这是一个遍历链表并打印的过程,定义一个临时指针储存信息一一将信息输出出来。
查询某一员工信息:首先需要遍历链表找到员工信息,定义临时指针储存该员工信息再输出。
代码如下(示例):
void showall(WOR *head)//查询所有员工信息
{
char n[20];
printf("输入0退出,其他继续\n");
scanf("%s",n);
if(n[0]=='0')
return;
else
{
WOR *p;
p=head->next;
if(p==NULL)
{
printf("无员工信息,可选择添加员工信息以增大公司规模\n");
}
else
{
printf("员工信息\n");
while(p)
{
printf("职工号:%d\n",p->number);
printf("姓名:%s\n",p->name);
printf("性别:%s\n",p->sex);
printf("出生年份:%d\n",p->year);
printf("月份:%d\n",p->month);
printf("天:%d\n",p->day);
printf("学位:%s\n\n\n",p->degree);
p=p->next;
}
}
}
return;
}
void printf(WOR *head)//查询某一员工
{
char n[20];
printf("输入0退出,其他继续\n");
scanf("%s",n);
if(n[0]=='0')
return ;
else
{
WOR *q,*p;
q=head;
if(q->next==Null)
{
printf("无员工信息,可选择添加员工信息以增大公司规模\n");
}
else
{
int n;
printf("请选择 1.职工号查询 2.姓名查询");
scanf("%d",&n);
if(n==1)
{
printf("请输入职工号");
int a;
scanf("%d",&a);
p=head->next;
while(p)
{
if(a==p->number)
{
printf("职工姓名:%s\n",p->name);
printf("职工性别:%s\n",p->sex);
printf("职工出生年:%d\n",p->year);
printf("职工出生月:%d\n",p->month);
printf("职工出生日:%d\n",p->day);
printf("职工学位:%s\n",p->degree);
}
else if(a!=p->number)
{
printf("无职工信息,可选择添加增大公司规模\n");
return;
}
p=p->next;
}
}
else if(n==2)
{
printf("请输入姓名");
char b[20];
scanf("%s",b);
while(p)
{
if(strcmp(p->name,"b")==0)
{
printf("职工号:%d\n",p->number);
printf("职工性别:%s\n",p->sex);
printf("职工出生年:%d\n",p->year);
printf("职工出生月:%d\n",p->month);
printf("职工出生日:%d\n",p->day);
printf("职工学位:%s\n",p->degree);
return ;
}
else if(strcmp(b,p->name)!=0)
{
printf("无职工信息,可选择添加增大公司规模\n");
return;
}
p=p->next;
}
}
}
}
}
注:查询某一员工信息:建议多多添加几个方式查询。
修改员工信息只需要遍历链表找到职工信息,直接修改就行。
修改时要和添加相似有对各个信息的限制建议将那些小个程序直接写成函数,本代码就过于麻烦一个一个打,代码冗长。
代码如下(示例):
void change(WOR *head)//改变函数
{
WOR *q;
q=head;
if(q->next==NULL)
{
printf("无员工信息,可选择添加员工信息以增大公司规模\n");
}
showall(head);
int flag,a;
int j;
printf("请输入要修改的职工号");
scanf("%d",&j);
a=0;
while(q!=NULL)
{
if(q->number==j)
{
printf("职工号:%d\n",q->number);
printf("姓名:%s\n",q->name);
printf("性别:%s\n",q->sex);
printf("出生年份:%d\n",q->year);
printf("月份:%d\n",q->month);
printf("天:%d\n",q->day);
printf("学位:%s\n\n\n",q->degree);
printf("请选择修改职工信息:1.名字\n2.性别\n3.出生年\n4.出生月\n5.出生日\n6.学位\n7.修改全部");
scanf("%d",&flag);
system("cls");
if(flag==1)
{
printf("请重新输入职工姓名");
scanf("%s",q->name);
system("pause");
break;
}
else if(flag==2)
{
printf("请重新输入员工性别");
while(1)
{
scanf("%s",q->sex);
if(strcmp("w",q->sex)==0)
break;
if(strcmp("m",q->sex)==0)
break;
if(strcmp("W",q->sex)==0)
break;
if(strcmp("M",q->sex)==0)
break;
printf("不要创造新物种,请按要求输入");
system("pause");break;
}
}
else if(flag==3)
{
printf("请重新输入员工出生年份");
while(1)
{
scanf("%d",&q->year);
if(q->year<0)
{
printf("年份不能为负,请重新输入");
continue;
}
else if(q->year>=0&&q->year<1000)
{
printf("年份太小,请重新输入");
}
else
{
system("pause");
break;
}
}
}
else if(flag==4)
{
printf("请重新输入员工出生月份");
while(1)
{
scanf("%d",&q->month);
if(q->month<=0||q->month>12)
{
printf("不要创造新月份,请重新输入");
continue;
}
else
{
system("pause");
break;
}
}
}
else if(flag==5)
{
printf("请重新输入员工出生天数");
while(1)
{
scanf("%d",&q->day);
if(q->day<=0||q->day>31)
{
printf("不要创造新天数,请重新输入");
continue;
}
else
{
system("pause");
break;
}
}
}
else if(flag==6)
{
printf("请重新输入员工学位");
while(1)
{
scanf("%s",q->degree);
if(strcmp(q->degree,"专科")!=0&&strcmp(q->degree,"本科")!=0&&strcmp(q->degree,"研究生")!=0&&strcmp(q->degree,"博士")!=0)
{
printf("请按要求重新输入");
}
else
system("pause");
break;
}
}
else if(flag==7)
{
printf("请输入姓名:");
scanf("%s",q->name);
getchar();
printf("请输入性别: w/m ");
while(1)
{
scanf("%s",q->sex);
if(strcmp("w",q->sex)==0)
break;
if(strcmp("m",q->sex)==0)
break;
if(strcmp("W",q->sex)==0)
break;
if(strcmp("M",q->sex)==0)
break;
printf("不要创造新物种,请按要求输入");
}
printf("请输入出生年份:");
while(1)
{
scanf("%d",&q->year);
if(q->year<0)
{
printf("年份不能为负,请重新输入");
continue;
}
else if(q->year>=0&&q->year<1000)
{
printf("年份太小,请重新输入");
}
else
break;
}
printf("请输入出生月份:");
while(1)
{
scanf("%d",&q->month);
if(q->month<=0||q->month>12)
{
printf("不要创造新月份,请重新输入");
continue;
}
else
break;
}
printf("请输入出生天:");
while(1)
{
scanf("%d",&q->day);
if(q->day<=0||q->day>31)
{
printf("不要创造新天数,请重新输入");
continue;
}
else
break;
}
printf("请输入职工学位:\n");
printf("注意:学历有专科,本科,研究生,博士\n");
while(1)
{
scanf("%s",q->degree);
if(strcmp(q->degree,"专科")!=0&&strcmp(q->degree,"本科")!=0&&strcmp(q->degree,"研究生")!=0&&strcmp(q->degree,"博士")!=0)
{
printf("请按要求重新输入");
}
else
break;
}
}
else
{
printf("选择错误,请重新选择");
system("pause");continue;
}
a=1;
}
q=q->next;
}
if(a==0)
printf("该员工不存在\n");
return;
}
排序的过程不建议改变链表,可以使用冒泡排序,只交换数值域,不换指针域。
排序函数要有他自己对应的文件。
代码如下(示例):
void order(WOR *head)//对职工进行排序
{
char n[20];
printf("输入0退出,其他继续\n");
scanf("%s",n);
if(n[0]=='0')
return;
else
{
if(head->next==NULL)
{
printf("无员工信息,可选择添加员工信息以排序\n");
return;
}
WOR *p=head->next;
WOR *q;
q=p->next;
WOR *temp;
while(p!=NULL)
{
q=p->next;
while(q!=NULL)
{
if(p->number>q->number)
{
int number1;
char name1[20];
char sex1[2];
int year1;
int month1;
int day1;
char degree1[20];
number1=p->number;
p->number=q->number;
q->number=number1;
strcpy(name1,p->name);
strcpy(p->name,q->name);
strcpy(q->name,name1);
strcpy(sex1,p->sex);
strcpy(p->sex,q->sex);
strcpy(q->sex,sex1);
year1=p->year;
p->year=q->year;
q->year=year1;
day1=p->day;
p->day=q->day;
q->day=day1;
month1=p->month;
p-> month=q->month;
q->month=month1;
strcpy(degree1,p->degree);
strcpy(p->degree,q->degree);
strcpy(q->degree,degree1);
}
q=q->next;
}
p=p->next;
}
}
}
注:插入函数自己验证时,虽然能够插入到指定位置,但无法退出循环,使用者慎重。
定义一个临时指针储存要插入的员工信息,再将该指针插入指定的位置。
储存信息与添加一样也需要有一系列的判断,所以还是建议将限制写成函数
插入图解:
代码如下(示例):
void insert(WOR *head)
{
char n[20];
printf("输入0退出,其他继续\n");
scanf("%s",n);
if(n[0]=='0')
return;
else
{
int v;
WOR *p=head;
WOR *s=(WOR *)malloc(sizeof(WOR));
printf("请输入插入职工信息");
s=(WOR*)malloc(sizeof(WOR));
tp:printf("请输入职工号");
scanf("%d",&s->number);
WOR *q=head->next;
while(q)
{
v=q->number;
if(s->number==v)
{
printf("该职工号已被使用,其选择其他喜欢的职工号");
goto tp;
}
q=q->next;
}
printf("请输入姓名:");
scanf("%s",s->name);
getchar();
printf("请输入性别: w/m ");
while(1)
{
scanf("%s",s->sex);
if(strcmp("w",s->sex)==0)
break;
if(strcmp("m",s->sex)==0)
break;
if(strcmp("W",s->sex)==0)
break;
if(strcmp("M",s->sex)==0)
break;
printf("不要创造新物种,请按要求输入");
}
printf("请输入出生年份:");
while(1)
{
scanf("%d",&s->year);
if(s->year<0)
{
printf("年份不能为负,请重新输入");
continue;
}
else if(s->year>=0&&s->year<1000)
{
printf("年份太小,请重新输入");
}
else
break;
}
printf("请输入出生月份:");
while(1)
{
scanf("%d",&s->month);
if(s->month<=0||s->month>12)
{
printf("不要创造新月份,请重新输入");
continue;
}
else
break;
}
printf("请输入出生天:");
while(1)
{
scanf("%d",&s->day);
if(s->day<=0||s->day>31)
{
printf("不要创造新天数,请重新输入");
continue;
}
else
break;
}
printf("请输入职工学位:\n");
printf("注意:学历有专科,本科,研究生,博士\n");
while(1)
{
scanf("%s",s->degree);
if(strcmp(s->degree,"专科")!=0&&strcmp(s->degree,"本科")!=0&&strcmp(s->degree,"研究生")!=0&&strcmp(s->degree,"博士")!=0)
{
printf("请按要求重新输入");
}
else
break;
}
printf("请输入插入点位置");
int a,b;
int l=0;
scanf("%d",&a);
WOR *c;
WOR *d=head;
if(a<=0)
return ;
else
{
while(d)
{
b++;
if(a==b)
{
c==(WOR *)malloc(sizeof(WOR));
c->number=s->number;
strcpy(c->name,s->name);
strcpy(c->sex,s->sex);
c->year=s->year;
c->month=s->month;
c->day=s->day;
strcpy(c->degree,s->degree);
c->next=d->next;
d->next=c;
printf("添加成功");
l=1;
return;
}
d=d->next;
}
if(l==0)
printf("添加失败");
}
}
}
文件的保存需要定义文件指针,以及文件输入。
保存时建议保存两个文件,一个用来储存,以及文件内容调用,一个用来浏览观看。
排序函数的文件保存与之相似。
代码如下(示例):
void save(WOR* head)//保存文件函数
{
WOR* p;
FILE* fp;
if((fp=fopen("yyzhk.txt","w"))==NULL)
{
printf("文件打开失败\n");
}
else
{
p=head->next;
while(p!=NULL)
{
fprintf(fp,"%d %s %s %d %d %d %s\n",p->number,p->name,p->sex,p->year,p->month,p->day,p->degree);
p=p->next;
}
}
fclose(fp);
}
void save1(WOR *head)//保存显示函数
{
WOR* p;
FILE* fp;
if((fp=fopen("yyzhk1.txt","w"))==NULL)
{
printf("文件打开失败\n");
}
else
{
p=head->next;
while(p!=NULL)
{
fprintf(fp,"职工号:%d 姓名:%s 性别:%s 出生年:%d 出生月:%d 出生日:%d 学位:%s\n",p->number,p->name,p->sex,p->year,p->month,p->day,p->degree);
p=p->next;
}
}
fclose(fp);
}
在保存文件后,再次读取的时候需要将内容读到链表中,这时候需要写一个读取函数。
代码如下(示例):
void read(WOR *head)//读取函数
{
WOR* p ,*s;
FILE* fp;
if((fp=fopen("yyzhk.txt","r"))==NULL)
{
printf("文件打开失败\n");
return;
}
else{
printf("打开成功\n");
p=head;
while(!feof(fp))
{
s=(WOR*)malloc(sizeof(WOR));
fscanf(fp,"%d %s %s %d %d %d %s\n",&s->number,s->name,s->sex,&s->year,&s->month,&s->day,s->degree);
p->next=s;
p=s;
p->next=NULL;
}
}
printf("读取成功");
fclose(fp);
}
本系统以链表知识为主,把链表的增删查改理解之后,会发现其他功能与之其实都差不多。
如何遍历链表很重要,萌新把这些理解之后基本大作业就能够敲出来。
第一次写博客,自我感觉良好, 希望这篇文章能帮助需要的人。