这个系统也是我大一时候写的....
当时没有学过界面编程,没有学过数据库....
所以存储方式也存储在文件中....
而数据结构的选择,一开始是使用数组保存在内存.....
最后改写成链表,存储在磁盘文件中....
代码编写过程也是通过搜索引擎搜索到一些资料,然后自己根据自己需要的一些选项一步一步实现的。
实现了核心功能后就开始实现对输入数据的检测....
这样一个小型系统,可谓是麻雀虽小,五脏六腑俱全吖。
在构思和编写这个系统中,自己也学到了不少的东西....
其中的过程直到现在还记忆犹新。
以下就附上代码....编译器使用VC++6.0....
#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 born[20]; //记录出生年月 char sex[10]; //记录性别 char poli[20]; //记录政治面貌 char phone[20]; //记录联络电话 char addr[100]; //记录家庭住址 struct Student *next; //指向下一个结构体的指针 }; struct Student *head = NULL; unsigned int kg = 0; //******************对各功能函数的声明*************************** 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); //保存学生信息的函数声明 //*************************************************************** void show() { int n,z = 1,k = 0; char cho; do { //***********显示提示信息********** printf(" ********************************************学生信息管理系统********************************************\n"); printf(" * *\n"); printf(" * 1.新建学生信息 *\n"); //显示序号1的功能 printf(" * 2.插入学生信息 *\n"); //显示序号2的功能 printf(" * 3.删除学生信息 *\n"); //显示序号3的功能 printf(" * 4.修改学生信息 *\n"); //显示序号4的功能 printf(" * 5.查询学生信息 *\n"); //显示序号5的功能 printf(" * 6.保存学生信息 *\n"); //显示序号6的功能 printf(" * 0.退出系统 *\n"); //显示序号0的功能 printf(" * *\n"); printf(" ********************************************************************************************************\n"); printf(" * *\n"); printf(" * 作者:梁铮豪 制作时间:2011.3 制作用途:嘉应学院计算机协会寒假作业(学生信息管理系统) *\n"); //显示关于作者、制作时间以及制作用途的信息 printf(" * *\n"); 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(" 请选择录入方式:\n"); printf(" 1.从当前窗口录入\n"); printf(" 2.从已有的文件(txt文件)录入\n"); printf(" 请选择: "); while(!scanf("%u",&m)) //排除输入错误的情况 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } while(m < 1 || m > 2) //排除输入错误的情况 { printf(" 请重新选择选择录入方式:\n"); printf(" 1.从当前界面录入\n"); printf(" 2.从已有文件(txt文件)录入\n"); printf(" 请选择: "); fflush(stdin); while(!scanf("%d",&m)) { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } printf("\n"); } if (m == 1) //当前窗口录入 { 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 %s",&p2->num,p2->grade,p2->name,p2->born,p2->sex,p2->poli,p2->phone,p2->addr)) { printf(" 输入有误,请重新输入该学生信息\n "); fflush(stdin); } if (n == 1) //对录入人数为1时的情况进行处理 { p2->next = NULL; } else //对录入人数大于1的情况进行录入,并在录入时进行排序,每录入一位学生信息就开辟一个内存空间,用于下一个学生的录入 { head = insert(head,p2); p2 = (struct Student *) malloc (LEN); } } } else //对文件录入的处理 { printf(" 请输入文件名(如student): "); while(!scanf("%s",filename)) //接收用户输入的文件名,并对其进行排错 { printf(" 输入文件名有误,请重新输入: "); fflush(stdin); } strcat(filename,".txt"); //合并后缀名 while((read = fopen(filename,"r")) == NULL) //如果该文件成功打开就进行学生信息的录入,否则继续要求用户输入文件名 { printf(" 未找到此文件,请重新输入文件名: "); scanf("%s",filename); strcat(filename,".txt"); } if (!fscanf(read,"%u",&n)) //接收从文件中录入的学生人数并进行排错 { printf(" 文件数据有错,结束录入\n "); fclose(read); fflush(stdin); return head; } p2 = p1 = (struct Student *) malloc (LEN); //开辟内存空间,创建链表 for(i = 0; i < n; i++) //循环录入每一个学生的信息 { if(!fscanf(read,"%d %s %s %s %s %s %s %s",&p2->num,p2->grade,p2->name,p2->born,p2->sex,p2->poli,p2->phone,p2->addr)) //当遇到数据有误,释放内存空间,返回NULL { fclose(read); p2 = head; p1 = p2->next; do //释放链表空间 { free(p2); p2 = p1; if (p1 != NULL) p1 = p1->next; else break; }while(p2 != NULL); printf(" 数据有误,结束录入\n "); return NULL; //返回NULL } if (n == 1) //对录入人数为1的情况进行处理 { p2->next = NULL; } else //对录入人数大于1的情况进行录入,并在录入时进行排序,开辟内存空间用于下一个学生信息的录入 { head = insert(head,p2); p2 = (struct Student *) malloc (LEN); } } fclose(read); //关闭文件 } 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->born,stu->sex,stu->poli,stu->phone,stu->addr)) { 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(" ┃学号┃年级┃ 姓名 ┃出生年月┃性别┃政治面貌┃ 联络电话 ┃ 家庭住址 ┃\n"); //********************************************************** //****************表格主体设计以及数据输出****************** printf(" ┣━━╋━━╋━━━━╋━━━━╋━━╋━━━━╋━━━━━━╋━━━━━━━━━━━━━━━━━━━┫\n"); printf(" ┃%-4d┃%-4s┃%-8s┃%-8s┃%-4s┃%-8s┃%-12s┃%-38s┃\n",p1->num,p1->grade,p1->name,p1->born,p1->sex,p1->poli,p1->phone,p1->addr); //********************************************************** //***********************表格头部设计*********************** printf(" ┗━━┻━━┻━━━━┻━━━━┻━━┻━━━━┻━━━━━━┻━━━━━━━━━━━━━━━━━━━┛\n"); //********************************************************* } 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"); printf(" ┃学号┃年级┃ 姓名 ┃出生年月┃性别┃政治面貌┃ 联络电话 ┃ 家庭住址 ┃\n"); //********************************************************** //****************表格主体设计以及数据输出****************** while(p1 != NULL) { printf(" ┣━━╋━━╋━━━━╋━━━━╋━━╋━━━━╋━━━━━━╋━━━━━━━━━━━━━━━━━━━┫\n"); printf(" ┃%-4d┃%-4s┃%-8s┃%-8s┃%-4s┃%-8s┃%-12s┃%-38s┃\n",p1->num,p1->grade,p1->name,p1->born,p1->sex,p1->poli,p1->phone,p1->addr); p1 = p1->next; } //********************************************************** //***********************表格头部设计*********************** printf(" ┗━━┻━━┻━━━━┻━━━━┻━━┻━━━━┻━━━━━━┻━━━━━━━━━━━━━━━━━━━┛\n"); //********************************************************** 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(" 9.全部\n"); printf(" 请选择序号: "); fflush(stdin); while(!scanf("%u",&cho)) //接受序号并查错 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } }while(cho > 9 || 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->born)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 5: { printf(" 请输入该学生改正的性别信息: "); while(!scanf("%s",p1->sex)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 6: { printf(" 请输入该学生改正的政治面貌信息: "); while(!scanf("%s",p1->poli)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 7: { printf(" 请输入该学生改正的联络电话信息: "); while(!scanf("%s",p1->phone)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 8: { printf(" 请输入该学生改正的家庭住址信息: "); while(!scanf("%s",p1->addr)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } case 9: { printf(" 请输入该学生全部要改正的信息: "); while(!scanf("%u %s %s %s %s %s %s %s",&p1->num,p1->grade,p1->name,p1->born,p1->sex,p1->poli,p1->phone,p1->addr)) { printf(" 输入改正信息有误,请重新输入: "); fflush(stdin); } break; } } if (cho == 1 || cho == 9) //对修改过学号的学生进行重新排序 { 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(" 2.以输入形式保存(可重新录入)\n"); printf(" 请选择: "); while(!scanf("%u",&cho)) //接受用户输入的序号并进行排错 { printf(" 输入序号有误,请重新输入: "); fflush(stdin); } while(cho < 1 || cho > 2) //对超出范围的序号进行排错 { printf(" 输入序号有误,请重新输入: "); while(!scanf("%u",&cho)) { printf(" 输入序号有误,请重新输入: "); //对输入错误的序号进行排错 fflush(stdin); } } if (cho == 1) //以表格形式保存 { //***********************表格头部设计************************ fprintf(write," ┏━━┳━━┳━━━━┳━━━━┳━━┳━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n"); fprintf(write," ┃学号┃年级┃ 姓名 ┃出生年月┃性别┃政治面貌┃ 联络电话 ┃ 家庭住址 ┃\n"); //********************************************************** //****************表格主体设计以及数据输出****************** while(p1 != NULL) { fprintf(write," ┣━━╋━━╋━━━━╋━━━━╋━━╋━━━━╋━━━━━━╋━━━━━━━━━━━━━━━━━━━┫\n"); fprintf(write," ┃%-4d┃%-4s┃%-8s┃%-8s┃%-4s┃%-8s┃%-12s┃%-38s┃\n",p1->num,p1->grade,p1->name,p1->born,p1->sex,p1->poli,p1->phone,p1->addr); p1 = p1->next; } //********************************************************** //***********************表格头部设计*********************** fprintf(write," ┗━━┻━━┻━━━━┻━━━━┻━━┻━━━━┻━━━━━━┻━━━━━━━━━━━━━━━━━━━┛\n"); //********************************************************** } else //以输入的格式保存 { n = 0; fprintf(write," \n"); //为输出学生人数留位置 while(p1 != NULL) { fprintf(write,"%u %s %s %s %s %s %s %s\n",p1->num,p1->grade,p1->name,p1->born,p1->sex,p1->poli,p1->phone,p1->addr); p1 = p1->next; n++; //每向文件输出一位学生信息n就累加1 } fseek(write,0,SEEK_SET); //移到文件头部 fprintf(write,"%u",n); //写入学生个数 } fclose(write); printf(" 保存成功\n "); system("pause"); } void main() { show(); //调用显示功能函数 }