学生离校情况管理系统 C语言(链表+文件)

        一次作业,学生离校情况管理系统,要求用链表和文件(整文件的时间占了八成QAQ)

        首先想记录一下一个要命细节。 没有加任何与文件有关的代码之前,窝突然想在Create()函数里加个是否连续输入的判断,但由于scanf的问题,出现了一系列玄幻结果:

        ·在打印“继续输入吗?继续请输入y或Y: ”之后,它为什么直接打印菜单???

        ·在显示菜单后输入y居然还能出现增添学生信息的提示词?!

        原来是输入y后会有回车,进入判断是否继续输入的while循环,于是退出了Init()函数,回到主函数打印菜单,而主函数里也因为scanf的问题,缓存区里保留着上一步操作里输入的选择 “1” ,所以在输入y后(实际上输入任何“字符”效果都一样,原因同本段末所述)我们就进入了增加学生信息的Create()环节,所以解决方法就有了在scanf前清空缓存,还有就是,一开始进主函数要是输入的是 “字符”,会发现它一直打印Error!..进入谜之死循环...这还得归功于scanf, 要是计划输入%d,而接收的却不是数字的话,缓存区就一直存着上一次的数值,一直.... 但你要是输入 非1~6 的“数字”,它就会“如你所料”的只打印一次Error!后打印菜单让你重新选择。

        于是乎就有了后面代码的改进:将scanf接收的整型改为字符型,并在其前清空缓存(在此万分感谢学长,救人一命啊~)

        接下来再谈文件(对我来说真是要命QAQ)。每次运行程序都要通过Init()函数,“r"是只读,要是还没有”student.txt"文件则打开失败,以“w+"形式创建一个新的文件,要是上次已创建,则“r"方式打开成功(不出意外的话),%*s的作用是跳过(即接收但不处理)文件中的提示语(“学生姓名:” “学生学号:”等)而把其后的信息赋给q->name等,一个循环创建好链表,计算学生人数ct.——初始化完成,记得文件不用时要fclose(fp)一下 ( >_<)

        最后在清空链表并退出前需要保存文件 ,也就是至关重要的write()函数了,先一个"w"方式,一开一关清空文件,再从头开始保存这次链表的内容,为什么要清空重写呢?干嘛不在新增的时候直接追加呢?一是为了保持学号从小到大的有序性(新插入的学生信息并不一定是以“追加”的形式挂在链表尾部啊),二是这样干挺省事的(bushi)。千万注意write()中fprintf里提示词与真实信息间的空格,因为%*s%s是以空格判断一条语句的。

(“w”模式:“只写”,若该文件存在则打开文件,并从头开始编辑,即原有内容会被删除;若该文件不存在则创建新文件)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int ct;
typedef struct student{
	char name[20],numb[20],data[20],traffic[20];
	struct student* next;
}Node,*Link;
Link head=(Link)malloc(sizeof(Node));

void Init(Link h){            //打开文件,创建链表
	Link p = h;
	FILE *fp;
	if(!(fp = fopen("student.txt","r"))) fp = fopen("student.txt","w+");
	fscanf(fp,"%*s");
	while(!feof(fp)){
		Link q = (Link)malloc(sizeof(Node));
		q->next = NULL;
		fscanf(fp,"%s",q->name);
		fscanf(fp, "%*s%s", q->numb);
		fscanf(fp, "%*s%s", q->data);
		fscanf(fp, "%*s%s", q->traffic);
		fscanf(fp,"%*s");
		p->next = q;
		p = q;
		ct++;
	}
	fclose(fp);
	printf("文件打开或创建成功!\n");
}	
void Create(){
	char flag = 'y';
	Link tail,pNew,p,q;	
	while((flag == 'y'||flag == 'Y')){
		pNew=(Link)malloc(sizeof(Node));
		printf("请输入学生姓名:");scanf("%s",pNew->name);
		printf("学号:") ;scanf("%s",pNew->numb);
		printf("离校日期:");scanf("%s",pNew->data);
		printf("交通工具:");scanf("%s",pNew->traffic); 
		ct++;
		if(ct==1){
			head->next=pNew;
			pNew->next=NULL;
		}
		else{
			p=head,q=head->next;
			while(q != NULL){
				if(strcmp(pNew->numb,q->numb)<0)break;    //插入时就使其有序,学号从小到大
				p = q, q = q->next;
			}	
			pNew->next=q;
			p->next=pNew;
		}
		printf("继续输入吗?继续请输入y或Y:");
		while((flag=getchar())!=EOF&&flag!='\n');       //清空缓存(因为scanf的问题...)
		scanf("%c",&flag);
	}
	return;	
}
void Delete(){
	char cl[20];
	int flag = 1;
	printf("请输入要删除学生的学号:\n");
	scanf("%s",cl);
	Link p, q;
	p=head,q=head->next;
	while(q != NULL){
		if(strcmp(q->numb, cl) == 0){
		p->next = q->next;
		q = q->next;
		printf("删除成功!\n");
		flag = 0, ct--;
	}
	else
		p = q, q = q->next;
	}
	if(flag)printf("查无此学号!\n");
}
void PrintMenu(){
	printf("*****************菜单*******************\n"
	       "*1.增加学生信息    2.删除学生信息      *\n"
		   "*3.修改学生信息    4.显示全部学生信息  *\n"
		   "*5.查询学生信息    6.保存并退出程序    *\n"
		   "****************************************\n" 
	);
	printf("\nPlease enter number 1~6\n");
}
void Change(){
	int c = 0, flag = 1;
	char tp[20],modif[30];
	printf("##注意## 学号不可修改!\n"
		   "选择:0.退出修改    1.修改姓名\n      2.修改离校日期  3.修改交通工具\n "); 
	printf("请输入您要修改的学生的学号:\n");
	scanf("%s",tp);
	Link p, q;
	p = head, q = head->next;
	while(q != NULL){
		if(strcmp(q->numb, tp) == 0){
			flag = 0;break;
		}
		else
			p = q, q = q->next;
	}
	if(flag)printf("查无此号!\n");
	else{
		while(1){
			printf("请选择序号(0~3):\n");
			scanf("%d",&c);
			if(!c)break; 
			switch(c){
				case 1:printf("请输入替换内容(10字内):\n");scanf("%s",q->name);break;
				case 2:printf("请输入替换内容(10字内):\n");scanf("%s",q->data);break;
				case 3:printf("请输入替换内容(10字内):\n");scanf("%s",q->traffic);break;
				default:printf("输入非法!\n");
			}
			printf("修改成功!\n");
		}
	}
}
void Display(){
	Link tp;
		int index = 1;
		printf("\n-------The list has %d members------\n\n",ct);
		tp = head->next;
		while(tp != NULL){
			printf("***The NO%d member:\n",index);
			printf("   姓名: %s\n   学号:%s\n   离校日期:%s\n   交通工具:%s\n",tp->name,tp->numb,tp->data,tp->traffic);
			tp = tp->next;
			index++;
		}
}
void Find(){
	Link p,q;
	p = head, q = head->next; 
	char tp[20];
	int flag = 1;
	printf("请输入要查找到学生学号:\n");
	scanf("%s",tp);
	while(q != NULL){
		if(strcmp(q->numb, tp) == 0){
			printf("您要查找的学生信息如下:\n");
			printf("姓名: %s\n学号:%s\n离校日期:%s\n交通工具:%s\n",q->name,q->numb,q->data,q->traffic);
			flag = 0; break;
		}
		else
			p = q, q = q->next;
	}
	if(flag) printf("未查找到!\n");
}

void write(){
	Link q = head->next;
	FILE *fp = fopen("student.txt","w");
	fclose(fp);
	while(q){
		fp = fopen("student.txt","a+");
		fprintf(fp, "学生姓名: %-10s 学生学号: %-10s 离校日期: %-10s 交通工具: %-10s", q->name, q->numb, q->data, q->traffic);
		fprintf(fp,"\n");
		q = q->next; 
	}
	printf("保存成功!\n");
}
void Clear(){
	write();
	Link p;
	while(head != NULL){
		p = head;
		head = head->next;
		free(p);
	}
	free(head);
}
int main(){
	char ch;             //同样是为了解决scanf的问题,这里不用int, 用字符
	Init(head);
	while(1){
		PrintMenu();
		scanf("%c",&ch);
		switch(ch){
			case '1':Create();  break;
			case '2':Delete();  break;
			case '3':Change();  break;
			case '4':Display(); break;
			case '5':Find();    break;
			case '6':Clear();   return 0;
			default:printf("Error!\n");
		}
		while((ch=getchar())!=EOF&&ch!='\n');            //清空缓存
	}
	return 0;
}

        结尾:这个短小的学生信息管理系统远比不上其他同学的“大作业”(人家还有模糊搜索...) ,但我希望它能对看到的小伙伴有所帮助(我为文件抓狂良久qwq)  这种只在头和尾增加有关文件的一小段代码,应该比较好接受,不用做太大修改。

        希望大家看到错误能不吝指出,thanks! ~~ >_<

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值