小言_互联网的博客

C语言学生信息管理系统终极版

396人阅读  评论(0)

本源码包含功能:输入、浏览全部信息、单个查找、添加、删除、修改、排序


思路:

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",&current->name);
	puts("please input age:");//age
	scanf("%3s",&current->age);
	puts("please input sex:");//sex
	scanf("%5s",&current->sex);
	puts("please input birthday:");//birthday
	scanf("%11s",&current->birthday);
	puts("please input address:");//address
	scanf("%19s",&current->address);
	puts("please input phone number:");//phone
	scanf("%11s",&current->phone);
	puts("please input emile:");//email
	scanf("%19s",&current->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",&current->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",&current->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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场