本源码包含功能:输入、浏览全部信息、单个查找、添加、删除、修改、排序
思路:
1.模块化设计是C语言的特点
2.防止特殊情况导致程序崩溃——空文件,所以重要函数都设有保护机制
3.UI方面实在无能为力,C语言知识就储备那一点,没办法
设计过程:
1.读写文件
分为只读(如查询、遍历等,不需要操作的)和只写(重写文件,把2中链表重新导到原文件中,覆盖原文件)两种,需要分情况选择。
为什么要分?主要是根据w,r,a的不同而决定的。
2.读数据
每次打开应用都用一个create()函数从文件里把数据读到一个链表中,之后只要对这个链表操作就可以了。
3.排序
由于每个结构体中的数据比较多,所以如果还是通过对值进行排序,其代码的运行效率显然会比较低,所以考虑直接对链表进行排序。
4.查询
想法:如果数据比较多,每次都遍历一遍显然会导致代码的低效率,所以排序显得格外必要。在排完序的前提下,利用fseek等函数+学号进行查询,效率会高很多。
但是,如果按名字查询,显然还是得遍历。除非再创建一个按名字排序的文件与链表。
最后实现:遍历法查询
5.添加
直接在链表中添加,再重写。
6.删除
直接在链表中删除,再重写。
7.修改
直接在链表中修改,再重写。
8.遍历
直接读取链表。
9.输入输出函数以及格式控制
输出函数printf需要注意控制格式,让输出的数据如表格一样好看。
输入函数可以把scanf分开写,每次输入前给个提示要输入什么。
输入字符串限制长度。
总的思想:把文件操作问题变成链表操作问题,这样,学生信息管理系统就显得格外简单,因为链表的相关操作函数我们已经写过了,只需把之前的函数稍微处理一下,就可以了。
问题:刚刚开始做实验时想把ui画好看一些,想加一个框,但这样的话就需要在每一次输入、输出、回车之后得调节一次光标位置,很复杂。
临时想到一个解决方法:自己这一个print、scan函数,把gotoxy()以及坐标控制也直接加到里面。当然,这样还是很复杂。
运行结果:
注意:
照搬源码可能会出错,原因是文件名可能不一致(文件路径不一致),这里需要自己根据个人电脑情况修改
源码(共330+行):
//本源码仅供参考学习,远水救不了近火,关键的还是要自己写呀。
//掌握在自己手中的才叫技术。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Student{
//学生信息包括:学号,姓名,年龄,性别,出生年月,地址,电话,E-mail。
int number;
char name[20];
char age[4];
char sex[6];
char birthday[12];
char address[20];
char phone[12];
char email[20];
struct Student *next;
}Student;
//辅助功能函数
void Refresh()//刷新界面
{
system("cls");//清空屏幕
printf( "\n"
"\t|================|\n"
"\t||录入学生信息:p||\n"
"\t||浏览学生信息:b||\n"
"\t||查询学生信息:f||\n"
"\t||修改学生信息:m||\n"
"\t||插入学生信息:i||\n"
"\t||删除学生信息:d||\n"
"\t||退出学生系统:e||\n"
"\t|================|\n"
"\n--------------------------------\n"
"你想做些什么吗?\n");
}
Student *Creat()//创建临时链表函数
{
Student *head=NULL,*pre=NULL,*current=NULL;
FILE *fp;
if(!(fp=fopen("file1","w"))){
//打开文件
puts("Cannot open this file!");
system("pause");
return head;
}
char ch=fgetc(fp);
rewind(fp);//此处很重要,如果丢失了就会出错 ,因为上一条语句后fp不是指向文件开头了
if(ch!=EOF){
//保护机制:判断文件是否为空,解决文件为空的情况
head=pre=current=(Student *)malloc(sizeof(Student));//创建链表
fread(current,sizeof(Student),1,fp);
while(current->next){
pre=current;
current=(Student *)malloc(sizeof(Student));
pre->next=current;
fread(current,sizeof(Student),1,fp);
}
}else{
puts("This list is empty.");//提示
system("pause");
}
fclose(fp);//关闭文件
Refresh();//刷新界面
return head;
}
void Write(Student *head){
//写入数据函数:把数据写入到磁盘中
FILE *fp;
if(!(fp=fopen("file1","w"))){
//打开并准备重写文件
puts("Cannot open this file!");
system("pause");
return;
}
while(head){
//写入数据
fwrite(head,sizeof(Student),1,fp);
head=head->next;
printf("*\n");
}
fclose(fp);
}
void Scan(Student *current)//输入数据 :输入数据
{
puts("please input name:");//name
scanf("%19s",¤t->name);
puts("please input age:");//age
scanf("%3s",¤t->age);
puts("please input sex:");//sex
scanf("%5s",¤t->sex);
puts("please input birthday:");//birthday
scanf("%11s",¤t->birthday);
puts("please input address:");//address
scanf("%19s",¤t->address);
puts("please input phone number:");//phone
scanf("%11s",¤t->phone);
puts("please input emile:");//email
scanf("%19s",¤t->email);
}
Student *Sort(Student *head)//排序函数
{
if(head){
//保护机制
Student *pre,*current,*next;
pre=current=head;
next=head->next;
int cnt=0;
while(head){
//算出一共有多少条数据
head=head->next;
cnt++;
}
head=current;
int i,j,flag;
for(i=cnt-1;i>0;i--){
//冒泡排序法
flag=1;
for(j=0;j<i;j++){
if(current->number>next->number){
current->next=next->next;
next->next=current;
if(j) pre->next=next;
else head=next;
}
current=current->next;
next=next->next;
if(j) pre=pre->next;
flag=0;
}
pre=current=head;
next=head->next;
if(flag) break;
}
}else{
puts("This list is empty.");//提示
system("pause");
}
return head;
}
//实用功能函数
Student *Input()//信息录入与保存函数p
{
puts("end with input number:0");//学号输0表示结束
Student *head=NULL,*pre=NULL,*current=NULL;
head=pre=current=(Student *)malloc(sizeof(Student));
puts("please input number:");
scanf("%d",¤t->number);
if(current->number) Scan(current);
else head=NULL;
while(current->number){
pre=current;
current=(Student *)malloc(sizeof(Student));
puts("please input number:");
scanf("%d",¤t->number);
if(!current->number){
puts("stop inputing");
break;
}
Scan(current);
pre->next=current;
}
pre->next=NULL;
char save;
save=getchar();//退出循环时最后还输了一个0保存在缓冲区,故需要一个字符用于消化
head=Sort(head);//排序
Refresh();
puts("do you want to save this?\nsave:y\tno:n");//是否保存输入数据至磁盘
save=getchar();
if(save=='y') Write(head);
return head;
}
Student *Delete(Student *head)//删除数据
{
if(head){
//保护机制 ,当文件夹为空(链表为空的时候)
int num,j=1;
puts("choose one you want to delete.");
scanf("%d",&num);
Student *pre=head,*current=head;
int cnt=1;
while(current->number!=num){
//寻找要删除的数据
cnt++;
pre=current;
current=current->next;
if(!current){
j=0;
break;
}
}
if(j){
//准备删除
if(cnt==1){
head=head->next;
free(pre);
}else{
pre->next=current->next;
free(current);
}
Write(head);
}else{
puts("this isn't exists.");//没找到
system("pause");
}
}else{
puts("This list is empty.");//空文件
system("pause");
}
return head;
}
Student *Insert(Student *head)//添加数据:按排序插入
{
Student *pre=head,*current=head;
Student *p=(Student*)malloc(sizeof(Student));
puts("please input number:");
scanf("%d",&p->number);
Scan(p);
if(head){
//保护机制 :防止文件夹为空
if( p->number <= head->number ){
p->next=head;
head=p;
}else{
current=current->next;
while(current){
if( p->number <= current->number ){
pre->next=p;
p->next=current;
break;
}else{
pre=current;
current=current->next;
}
}
if(!current){
pre->next=p;
p->next=NULL;
}
}
}else{
head=p;
head->next=NULL;
}
Write(head);
return head;//如果插入在第一个以前,则head变了,于是需要返回head
}
void Browse(Student *head){
//浏览函数:如果一条数据都没有?如何判断结尾?
//由于存储数据的时候把结构体里的指针也给存了加进去,
//所以可以直接用head->next是否为NULL判断
printf("%-10s %-12s %-10s %-10s %-10s %-10s %-11s %-15s\n",
"number","name","age","sex","birthday","address","phone","email");
if(head){
while(head){
printf("%-10d %-12s %-10s %-10s %-10s %-10s %-11s %-15s\n",
head->number,head->name,head->age,head->sex,head->birthday,head->address,head->phone,head->email);
head=head->next;
}
}else puts("This list is empty.");
system("pause");
}
Student *Find(Student *head)//查询函数
{
int k=1;
if(head){
//保护机制
printf("find by number:1\tfind by name:2\n");//选择根据名字还是根据学号查询
int judge;
scanf("%d",&judge);
printf("please input what you want to find:\n");
if(judge==1){
int num;
scanf("%d",&num);
while(head->number!=num){
if(!head->next){
puts("this isn't exist!\n");
k=0;
break;
}
head=head->next;
}
}else{
char name[20];
scanf("%19s",&name);
while(strcmp(name,head->name)){
if(!head->next){
puts("this isn't exist!\n");
k=0;
break;
}
head=head->next;
}
}
if(k) printf("%-10d %-12s %-10s %-10s %-10s %-10s %-11s %-15s\n",
head->number,head->name,head->age,head->sex,head->birthday,head->address,head->phone,head->email);
}else{
k=0;
puts("This list is empty.");
}
system("pause");
if(k) return head;//Modify中调用Find来找要修改的,故此处需要return
else return NULL;
}
Student *Modify(Student *headI)//修改信息
{
Student *head=Find(headI);//由于之前已经定义过find函数,故此处不需要再搜索,直接调用find函数即可
if(head){
//保护机制
puts("请重新输入数据:");
puts("please input number:");
scanf("%d",&head->number);
Scan(head);
head=Sort(headI);
Write(headI);
}
return headI;
}
//主函数
int main(){
Refresh();//初始化页面
Student *head=NULL;//创建临时链表
head=Creat();
char ch;
while(1){
ch=getchar();
switch(ch){
case 'p':head=Input();break;
case 'b':Browse(head);break;
case 'f':Find(head);break;
case 'm':head=Modify(head);break;
case 'i':head=Insert(head);break;
case 'd':head=Delete(head);break;
case 'e':exit(0);break;
}
Refresh();
}
return 0;
}
·
·
·
2020秋中国每羊大学期末C课程设计
转载:https://blog.csdn.net/weixin_50545743/article/details/112392957