#ifndef _TEST #define _TEST #include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h> #define LEN sizeof(struct Student) struct Student //学生信息的结构体声明 { unsigned int num; //记录学号,且不存在负数学号; char grade[10]; //记录年级 char name[20]; //记录姓名 char chinese[20]; //记录出生年月 char math[10]; //记录性别 char Endlish[20]; //记录政治面貌 char chose[20]; //记录联络电话 struct Student *next; //指向下一个结构体的指针 }; //******************对各功能函数的声明*************************** void show(); //显示函数的声明 struct Student *input(); //新建学生信息的函数声明 struct Student *insert(struct Student *head,struct Student *stu); //插入学生信息的函数声明 struct Student *del(struct Student *head); //删除学生信息的函数声明 void alter(struct Student *head); //修改学生信息的函数声明 void search(struct Student *head,unsigned int num); //查询学生信息的函数声明 void output(struct Student *head); //保存学生信息的函数声明 #endif #include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h> extern struct Student *head = NULL; extern unsigned int kg = 0; void show(){ int n,z = 1,k = 0; char cho; do{ //***********显示提示信息********** printf(" 学生信息管理系统 \n"); printf(" \n"); printf(" 1.新建学生信息 2.插入学生信息 \n"); //显示序号1的功能 printf(" \n"); //显示序号2的功能 printf(" 3.删除学生信息 4.修改学生信息 \n"); //显示序号3的功能 printf(" \n"); //显示序号4的功能 printf(" 5.查询学生信息 6.保存学生信息 \n"); //显示序号5的功能 printf(" \n"); //显示序号6的功能 printf(" 0.退出系统 \n"); //显示序号0的功能 printf(" \n"); //******************************** printf(" 请输入功能序号: "); //提示用户输入 while(!scanf("%d",&n)){ //接受用户输入的功能序号,并且进行排错 printf(" 输入序号有误,请重新输入: "); fflush(stdin); //清空输入缓冲区,通常是为了确保不影响后面的数据读取 } printf("\n"); //输出回车 while((n < 0 || n > 6)) //对用户输入不能实现的功能序号进行处理 { printf(" 抱歉,没有此功能,请重新输入功能序号: "); //提示用户所输入的功能序号系统不能进行处理 fflush(stdin); while(!scanf("%d",&n)) //接收用户重新输入的功能序号 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } printf("\n"); //输出回车 } switch(n) //对用户信息进行功能函数的调用 { case 0: { printf(" "); if (k == 1){ //对于没有对数据进行存盘的情况进行对用户提示以确认是否退出 printf("数据未保存,是否退出? Y.是 N.否 请选择: "); fflush(stdin); cho = getchar(); if (cho == 'y' || cho == 'Y') { z = 0; printf(" "); } else if (cho == 'n' || cho == 'N'){ } else { printf(" 无效输入\n "); system("pause"); } } else { z = 0; } break; } case 1: { head = input(); k = 1; system("pause"); break; } case 2: { head = insert(head,NULL); k = 1; printf(" 成功插入学生信息\n "); system("pause"); break; } case 3: { head = del(head); k = 1; printf(" "); system("pause"); break; } case 4: { alter(head); break; } case 5: { if (head == NULL) k = 1; search(head,0); printf(" "); system("pause"); break; } case 6: { k = 0; output(head); break; } } }while(z == 1); } struct Student *input() { struct Student *p1,*p2; //尾插法 unsigned m,n,i; FILE *read; char filename[20]; head = NULL; printf (" 请输入学生人数: "); while (!scanf("%u",&n)) //接收录入学生信息的人数,并对输入有误的进行排除 { printf(" 输入有误,请重新输入学生人数: "); fflush(stdin); } if (n == 0) //对录入人数为0的情况进行处理 { printf(" 学生个数为0人,建立失败\n "); return (head); } head = p2 = p1 = (struct Student *) malloc (LEN); //开辟内存,用于生成链表 printf(" 学生个数为:%u个,请按照以下顺序输入\n",n); //对学生总数的提示,并且提示每个学生信息的输入顺序 printf(" 学号、年级、姓名、语文成绩、数学成绩、英语成绩、选修课成绩\n"); //每个学生信息的输入顺序 for(i = 0; i < n; i++) { printf(" 请输入第%u个学生信息!\n",i+1); //提示接下来要输入第几个学生的信息 printf(" "); //格式调整,输出三个空格 fflush(stdin); while(!scanf("%d %s %s %s %s %s %s",&p2->num,p2->grade,p2->name,p2->chinese,p2->math,p2->Endlish,p2->chose)) { printf(" 输入有误,请重新输入该学生信息\n "); fflush(stdin); } if (n == 1) //对录入人数为1时的情况进行处理 { p2->next = NULL; } else //对录入人数大于1的情况进行录入,并在录入时进行排序,每录入一位学生信息就开辟一个内存空间,用于下一个学生的录入 { head = insert(head,p2); p2 = (struct Student *) malloc (LEN); } } printf(" 成功录入学生信息,并且学生信息已经按学号从小到大排列\n"); printf(" 学生信息如下: \n"); search(head,1); //以表格的形式显示所录入的学生信息 printf(" "); return head; //返回*head指针的地址 } struct Student *insert(struct Student *head,struct Student *stu) //插入学生信息功能函数定义 { struct Student *p1,*p2; if (stu == NULL) //对于传入插入学生信息为空时要求用户输入插入的学生信息 { printf(" 请按照学号、年级、姓名、语文成绩、数学成绩、英语成绩、选修课成绩的顺序输入\n "); //每个学生信息的输入顺序 stu = (struct Student *) malloc (LEN); while(!scanf("%d %s %s %s %s %s %s %s",&stu->num,stu->grade,stu->name,stu->chinese,stu->math,stu->Endlish,stu->chose)) { printf(" 输入信息有误,请重新输入\n"); fflush(stdin); } } if (head == NULL){ //对于链表为空的情况的处理 head = stu; head->next = NULL; } else //在链表中插入学生信息 { p1 = p2 = head; while(stu->num > p2->num && p1->next != NULL) //查找适合位置的前一个学生 { p2 = p1; p1 = p1->next; } if (p2 == p1) //插入的学生正好为链表头的情况 { if (stu->num < p2->num) //插入在表头前 { head = stu; stu->next = p2; } else //插入在表头后 { p2->next = stu; stu->next = NULL; } } else //插入的学生在链表中的情况 { if (stu->num < p1->num) //插入到p1指向的学生前 { p2->next = stu; stu->next= p1; } else //插入到p1指向的学生后 { p1->next = stu; stu->next = NULL; } } } kg = 1; return(head); } struct Student *del(struct Student *head) //删除学生信息的功能函数定义 { unsigned int num,k; struct Student *p1,*p2; if (head == NULL) //对空链表删除的情况处理 { printf(" 没有学生信息,结束删除\n"); return(head); } printf(" 请输入要删除的学生学号: "); //求用户输入要删除的学生学号 while(!scanf("%u",&num)) //接收学生序号并进行排错处理 { printf(" 输入有误,请重新输入学生序号: "); fflush(stdin); } do { p1 = p2 = head; while(num != p1->num && p1->next != NULL) //查找删除位置的前一个学生 { p2 =p1; p1= p1->next; } if (num == p1->num) //对满足要求的学生进行删除 { if (num == p1->num) { if (p1->next == NULL && p1 == head) //对只有一个节点的链表进行删除 { free(p1); head = NULL; } else if (p1->next == NULL) //删除链表尾节点 { free(p1); p2->next = NULL; } else if (head == p1) //删除表头节点 { head = p1->next; free(p1); } else //删除表中节点 { p2->next = p1->next; free(p1); } } printf(" 成功删除学生信息\n"); //提示删除成功信息 } else //找不到要删除的学生时的提示 { printf(" 找不到该同学信息\n"); fflush(stdin); } if (head == NULL) //对空链表删除时的处理 { printf(" 没有学生信息,结束删除\n"); return(head); } else //提示用户删除后是否继续 { printf("**********1.继续删除学生信息\n"); printf("**********2.结束删除\n"); printf("***************请选择: "); while(!scanf("%u",&k)) //接收用户选择 { printf(" 输入有误,请重新输入选择的序号: "); fflush(stdin); } if (k == 1) //选择继续 { printf(" 请输入要删除的学生学号: "); while(!scanf("%u",&num)) { printf(" 输入有误,请重新输入学生学号: "); fflush(stdin); } } else if (k != 2) //对于不是选择2的继续循环提示 { k = 1; } } }while(k == 1); return(head); //返回表头地址 } void search(struct Student *head,unsigned int num) //查询函数的定义 { unsigned int cho,t = 0; struct Student *p1; if (head == NULL) //对查询空链表时的操作 { printf(" 没有学生信息,结束查询\n"); return; } p1 = head; if (num == 0){ //当传入实参 num = 0 需要接受用户需要的查询方式(个别或者全部),不等于0则可以直接查询个别学生信息 printf("***********1.查询个别学生信息\n"); printf("***********2.查询全部学生信息\n"); printf("*****************请选择: "); while(!scanf("%u",&cho)) //对错误输入数据的处理 { printf(" 输入有误,请重新输入序号: "); fflush(stdin); } while(cho != 1 && cho != 2) //处理不能处理的功能序号 { printf(" 抱歉!此项中没有此功能,请重新输入功能序号: "); //提示不能处理的信息,并要求用户重新输入功能序号 while(!scanf("%u",&cho)) //接收用户重新输入的功能序号 { printf(" 输入序号有误,请重新输入序号: "); fflush(stdin); } printf("\n"); //输出回车 } } else { cho = 1; //设置直接查询个别学生的开关 } if (kg == 1){ //kg(全局变量)为全部学生查询的开关 kg = 1 打开开关由下面直接进行全部学生查询 kg = 0 关闭开关 cho = 2; } switch(cho) //查询类别分支 { case 1: //查询个别学生 { do { p1 = head; if (num == 0 || t == 1) { printf(" 请输入需要查询的学生学号: "); while(!scanf("%u",&num)) { printf(" 输入有误,请重新输入: "); fflush(stdin); } t = 1; //打开开关,该开关为查询完毕后 num不能作为该分支的条件(因为以下的操作会改变num的值)而建立的,并且能够实现当传入num不等于0时,以下询问用户是否继续的分支就不用执行了 } else { cho = 2; //如果传入的实参num不等于0 则该 DO WHILE 循环只做一次 } while(p1->num != num) //查找查询学生学号 { if (p1->next == NULL) break; p1 = p1->next; } if (p1->num == num){ //查找成功一表格方式输出该学生信息 //***********************表格头部设计************************ printf("********┃学号┃年级┃姓名 ┃语文成绩 ┃数学成绩 ┃英语成绩 ┃选修课成绩|********\n"); printf("********┃%-4d┃%-4s┃%-7s┃%-9s┃%-8s| %-9s| %-9s|********\n",p1->num,p1->grade,p1->name,p1->chinese,p1->math,p1->Endlish,p1->chose); //********************************************************** //***********************表格头部设计*********************** //********************************************************* } else //查找不成功,提示用户找不到该学生 { printf(" 找不到该学生\n"); } if (t == 1) //如果传入的num=0,则此分支有效,询问用户是否继续查询 { printf(" 1.继续查询\n"); printf(" 2.结束查询\n"); printf(" 请选择: "); while(!scanf("%u",&cho)) //对输入序号查错,利用cho = 2时的情况跳出 DO WHILE 循环 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } } }while (cho == 1); break; } case 2: //查询全部信息 { //***********************表格头部设计************************ printf("********┃学号┃年级┃ 姓名 ┃ 语文成绩 ┃数学成绩 ┃英语成绩 ┃选修课成绩|********\n"); //********************************************************** //****************表格主体设计以及数据输出****************** while(p1 != NULL) { //intf(" ┣━━╋━━╋━━━━╋━━━━╋━━╋━━━━╋━━━━━━╋━━━━━━━━━━━━━━━━━━━┫\n"); printf(" ********┃%-4d┃%-4s┃%-8s┃%-8s┃%-8s┃%-8s┃%-8s|********\n",p1->num,p1->grade,p1->name,p1->chinese,p1->math,p1->Endlish,p1->chose); p1 = p1->next; } //********************************************************** //***********************表格头部设计*********************** //********************************************************** break; } } if (kg == 1) kg = 0; //关闭查询全部学生的开关,以便下一次使用 } void alter(struct Student *head){ //修改学生信息的功能函数定义 struct Student *p1,*p2; unsigned int num,cho,k,l=0; if (head == NULL) //对空链表的处理 { printf(" 没有学生信息,结束修改\n "); system("pause"); return; } printf(" 请输入需要修改的学生学号: "); while(!scanf("%u",&num)) //接受用户输入的学号并且进行查错 { printf(" 输入学号有误,请重新输入: "); fflush(stdin); } do { p2 = p1 = head; while(p1->num != num) //查找学生学号 { if (p1->next == NULL) break; p2 = p1; p1 = p1->next; } if (p1->num == num) //查找成功 { printf(" 已找到该学生,该学生的信息为: \n"); search(head,num); l = 0; do { if (l == 0) //开关,当第一次循环时 l=0 执行 IF 语句 printf(" 选择修改的内容\n"); else printf(" 序号输入错误,请重新选择\n"); l = 1; //打开开关,以在以下操作用户输入序号超出范围时控制上面的分支语句,进而可以更好地向用户提示信息 printf(" 1.学号\n"); printf(" 2.年级\n"); printf(" 3.姓名\n"); printf(" 4.语文成绩\n"); printf(" 5.数学成绩\n"); printf(" 6.英语成绩\n"); printf(" 7.选修课成绩\n"); printf(" 8.全部\n"); printf(" 请选择序号: "); fflush(stdin); while(!scanf("%u",&cho)) //接受序号并查错 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } }while(cho > 8 || cho < 1); switch(cho) //对序号进行多分支处理 { case 1: { printf(" 请输入该学生改正的学号信息: "); while(!scanf("%u",&p1->num)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 2: { printf(" 请输入该学生改正的年级信息: "); while(!scanf("%s",p1->grade)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 3: { printf(" 请输入该学生改正的姓名信息: "); while(!scanf("%s",p1->name)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 4: { printf(" 请输入该学生改正的语文成绩信息: "); while(!scanf("%s",p1->chinese)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 5: { printf(" 请输入该学生改正的数学成绩信息: "); while(!scanf("%s",p1->math)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 6: { printf(" 请输入该学生改正的英语成绩信息: "); while(!scanf("%s",p1->Endlish)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 7: { printf(" 请输入该学生改正的选修课成绩信息: "); while(!scanf("%s",p1->chose)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 8: { printf(" 请输入该学生全部要改正的信息: "); while(!scanf("%u %s %s %s %s %s %s %s",&p1->num,p1->grade,p1->name,p1->chinese,p1->math,p2->Endlish,p2->chose)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } } if (cho == 1 || cho == 8) //对修改过学号的学生进行重新排序 { if (p1 == head) //当该学生在链表头时,删除链表头节点 { head = head->next; } else if (p1->next == NULL) //当该学生在链表尾时,删除链表尾节点 { p2->next = NULL; } else //当该学生在链表中时,删除该学生对应的节点 { p2->next = p1->next; } head = insert(head,p1); //利用插入学生信息功能函数,进行该学生的重新排序 } printf(" 修改成功,该学生改正后的信息为: \n"); search(head,p1->num); //显示以下修改后的学生信息 //询问用户是否继续 printf(" 1.继续修改其他学生信息\n"); printf(" 2.退出修改\n"); printf(" 请选择: "); while(!scanf("%u",&k)) //接受用户输入的序号,并进行排错 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } if (k == 1) //接受下一次修改的学生学号 { printf(" 请输入需要修改的学生学号: "); while(!scanf("%u",&num)) { printf(" 输入修改信息有误,请重新输入: "); fflush(stdin); } } else if (k != 2) //排错 { printf(" 输入有误,请重新输入\n"); } } else //查找不到学生时要求用户进行重新输入学生序号 { k = 1; printf(" 找不到该学生信息,请重新输入需要修改的学生学号: "); fflush(stdin); while(!scanf("%u",&num)); //接受用户重新输入的学号并进行排错 { printf(" 输入修改信息有误,请重新输入: "); fflush(stdin); } } }while(k == 1); printf(" "); system("pause"); } void output(struct Student *head) //保存学生信息到txt文件功能函数 { FILE *write; char filename[20]; struct Student *p1,*p2; unsigned int cho,n; if (head == NULL) //对空链表进行处理 { printf(" 没有学生信息,保存失败\n "); system("pause"); return; } p1 = p2 = head; printf(" 请输入保存的文件名(如save): "); while(!scanf("%s",filename)) //接受文件名,并进行排错(几乎不会出现错误的现象,慎重而设) { printf(" 输入的文件名有误,请重新输入:"); fflush(stdin); } strcat(filename,".txt"); //链接后缀名 write = fopen(filename,"w"); //以写入方式打开文件 //询问用户用哪种方式保存 printf(" 1.以表格形式保存(不可重新录入)\n"); printf(" 请按1进行确认 : "); while(!scanf("%u",&cho)) //接受用户输入的序号并进行排错 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } while(cho < 1 || cho > 1) //对超出范围的序号进行排错 { printf(" 输入序号有误,请重新输入: "); while(!scanf("%u",&cho)) { printf(" 输入序号有误,请重新输入: "); //对输入错误的序号进行排错 fflush(stdin); } } if (cho == 1) { //以表格形式保存 //***********************表格头部设计************************ fprintf(write,"********┃学号┃年级┃ 姓名 ┃ 语文成绩 ┃数学成绩 ┃英语成绩 ┃选修课成绩|********\n"); //********************************************************** //****************表格主体设计以及数据输出****************** while(p1 != NULL){ fprintf(write,"********┃%-4d┃%-4s┃%-7s┃%-8s┃%-8s┃%-8s┃%-8s|********\n",p1->num,p1->grade,p1->name,p1->chinese,p1->math,p2->Endlish,p2->chose); p1 = p1->next; } } fclose(write); printf(" 保存成功\n "); system("pause"); } #include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h> int main() { show(); //调用显示功能函数 return 0; }