|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
要写一个学生成绩管理系统,第一次运行没有问题,但第二次我想直接从上次登记的数据读取的时候就不行了。
有没有大佬帮忙解答一下
- #include <stdio.h>
- #include <malloc.h>
- #define LEN sizeof(struct student)
- struct student
- {
- int num;
- char name[10];
- int score;
- struct student *next;
- };
- int n; //统计学生人数
- int main()
- {
- struct student *creat();
- struct student *insert(struct student *head,struct student *stud);
- struct student *del(struct student *head ,int num);
- void print(struct student *head);
- void search(struct student *head,int num);
- void chucun(struct student *head);
- void daochu(struct student *head); //函数声明
-
- struct student *head,*stu;
- int del_num,ser_num,i;
- printf("\n\t学生管理系统1.0\n\n");
- printf("--------------菜单--------------\n\n");
- printf("\t1.登记学生信息\n");
- printf("\t2.删除学生信息\n");
- printf("\t3.增加学生信息\n");
- printf("\t4.查找学生信息\n");
- printf("\t5.浏览学生信息\n");
- printf("\t6.储存到文件\n");
- printf("\t7.从文件导出\n");
- printf("\t8.退出系统\n");
- printf("\n说明:学生信息输入0,表示输入结束\n\n");
- printf("请选择:");
- scanf("%d",&i);
- while(i!=8)
- {
- switch(i)
- {
- case 1: head=creat();break;
- case 2:
- {
- printf("请输入要删除的学号:");
- scanf("%d",&del_num);
- while(del_num!=0)
- {
- head=del(head,del_num);
- printf("请输入要删除的学号:");
- scanf("%d",&del_num);
- }
- break;
- }
- case 3:
- {
- printf("请输入要增加的学生的信息\n");
- printf("请输入学号,姓名(用逗号隔开):");
- stu=(struct student *)malloc(LEN);
- scanf("%d,%s",&stu->num,&stu->name);
- printf("请输入分数:");
- scanf("%d",&stu->score);
- while(stu->num!=0)
- {
- head=insert(head,stu);
- printf("请输入要增加的学生的信息\n");
- printf("请输入学号,姓名(用逗号隔开):");
- stu=(struct student *)malloc(LEN);
- scanf("%d,%s",&stu->num,&stu->name);
- printf("请输入分数:");
- scanf("%d",&stu->score);
- }
- break;
- }
- case 4:
- {
- printf("请输入要查找学生的学号:");
- scanf("%d",&ser_num);
- search(head,ser_num);
- break;
- }
- case 5: print(head);break;
- case 6: chucun(head);break;
- case 7: daochu(head);break;
- case 8: break;
- default : printf("请输入1-8之间的数字!!!\n");
- }
- printf("\n\t学生管理系统1.0\n\n");
- printf("--------------菜单--------------\n\n");
- printf("\t1.登记学生信息\n");
- printf("\t2.删除学生信息\n");
- printf("\t3.增加学生信息\n");
- printf("\t4.查找学生信息\n");
- printf("\t5.浏览学生信息\n");
- printf("\t6.储存到文件\n");
- printf("\t7.从文件导出\n");
- printf("\t8.退出系统\n");
- printf("\n说明:学生信息输入0,表示输入结束\n\n");
- printf("请选择:");
- scanf("%d",&i);
- }
- return 0;
- }
- struct student *creat() //建立链表的函数
- {
- struct student *head,*p1,*p2;
- n=0;
- p1=p2=(struct student *)malloc(LEN);
- printf("请输入学号,姓名(用逗号隔开):");
- scanf("%d,%s",&p1->num,&p1->name);
- printf("请输入分数:");
- scanf("%d",&p1->score);
- head=NULL;
- while(p1->num!=0)
- {
- n=n+1;
- if(n==1) head=p1;
- else p2->next=p1;
- p2=p1;
- p1=(struct student *)malloc(LEN);
- printf("请输入学号,姓名(用逗号隔开):");
- scanf("%d,%s",&p1->num,&p1->name);
- printf("请输入分数:");
- scanf("%d",&p1->score);
- }
- p2->next=NULL;
- return head;
- }
- struct student *insert(struct student *head,struct student *stud) //插入结点的函数
- {
- struct student *p0,*p1,*p2;
- p1=head;
- p0=stud; //指向要插入的结点
- if(head==NULL) //如果为空链表
- {
- head=p0;
- p0->next=NULL;
- }
- else
- {
- while((p0->num>p1->num)&&(p1->next!=NULL))
- {
- p2=p1;
- p1=p1->next;
- }
- }
- if(p0->num<=p1->num)
- {
- if(head==p1) head=p0; //插入的是头结点
- else p2->next=p0; //插入的是中间结点
- p0->next=p1;
- }
- else //插入的是尾结点
- {
- p1->next=p0;
- p0->next=NULL;
- }
- n=n+1;
- return(head);
- }
- struct student *del(struct student *head ,int num) //删除结点的函数
- {
- struct student *p1,*p2;
- if(head==NULL)
- {
- printf("\n该表是空表!\n");
- return(head);
- }
- p1=head;
- while(num!=p1->num&&p1->next!=NULL) //p1指向的不是所要找的结点且后面还有结点
- {
- p2=p1;
- p1=p1->next;
- }
- if(num==p1->num)
- {
- if(p1==head) head=p1->next; //若p1指向的是首结点
- else p2->next=p1->next;
- printf("删除%d号学生成功!",num);
- n=n-1;
- }
- else
- printf("没有找到%d",num);
- return(head);
- }
- void print(struct student *head) //输出链表的函数
- {
- struct student *p;
- p=head;
- printf("\n学生成绩为:\n");
- printf("\t学号\t姓名\t成绩\n_______________________________________________________________\n");
- if(head!=NULL)
- do
- {
- printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
- p=p->next;
- }while(p!=NULL);
- printf("总共有%d名学生",n);
- }
- void search(struct student *head,int num) //对链表的查询
- {
- struct student *p;
- if(head==NULL)
- printf("\n该表是空表!\n");
- p=head;
- if(p->num==num)
- {
- printf("该学生信息为:\n\n");
- printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
- }
- else
- {
- while(p!=NULL)
- {
- p=p->next;
- if(p!=NULL&&p->num==num)
- {
- break;
- }
- }
- if(p==NULL) printf("\t不存在该学号的学生!");
- else
- {
- printf("该学生信息为:\n\n");
- printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
- }
- }
- }
- void chucun(struct student *head)
- {
- struct student *p;
- FILE *fp;
- p=head;
- fp=fopen("stud.dat","w");
- while(p!=NULL)
- {
- if(fwrite(p,LEN,1,fp)!=1)
- printf("数据存储失败!");
- p=p->next;
- }
- fclose(fp);
- }
- void daochu(struct student *head)
- {
- struct student *p;
- FILE *fp;
- p=head;
- fp=fopen("stud.dat","w");
- printf("\t学号\t姓名\t成绩\n_______________________________________________\n");
- while(p!=NULL)
- {
- fread(p,LEN,1,fp);
- printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
- p=p->next;
- }
- }
复制代码
本帖最后由 jackz007 于 2021-1-7 15:24 编辑
读取和保存链表的代码有些草率了,尤其是从文件中读取,不可以只是简单的从文件中整体读出整个链表,因为从文件中读取节点的 next 中保存的是当时下一个节点的内存地址,显然不能直接使用,必须是逐节点读出,然后,重新链接。
以下代码重点修改了 main()、chucun()、daochu() 3 个函数
- #include <stdio.h>
- #include <malloc.h>
- #define LEN sizeof(struct student)
- struct student
- {
- int num ;
- char name[10] ;
- int score ;
- struct student * next ;
- } ;
- int n; //统计学生人数
- struct student *creat();
- struct student *insert(struct student *head,struct student *stud);
- struct student *del(struct student *head ,int num);
- void print(struct student *head);
- void search(struct student *head,int num);
- void chucun(struct student *head);
- void daochu(struct student **head); //函数声明
- int main()
- {
- struct student *head,*stu ;
- int f , del_num , ser_num , i ;
- for(f = 1 ; f ;) {
- printf("\n\t学生管理系统1.0\n\n");
- printf("--------------菜单--------------\n\n");
- printf("\t1.登记学生信息\n");
- printf("\t2.删除学生信息\n");
- printf("\t3.增加学生信息\n");
- printf("\t4.查找学生信息\n");
- printf("\t5.浏览学生信息\n");
- printf("\t6.储存到文件\n") ;
- printf("\t7.从文件导出\n") ;
- printf("\t8.退出系统\n") ;
- printf("\n说明:学生信息输入0,表示输入结束\n\n");
- printf("请选择:") ;
- fflush(stdin) ;
- scanf("%d", & i) ;
- if(i > 0 && i < 9) {
- switch(i) {
- case 1: head=creat();break;
- case 2:
- printf("请输入要删除的学号:");
- scanf("%d",&del_num);
- while(del_num!=0) {
- head=del(head,del_num);
- printf("请输入要删除的学号:");
- scanf("%d",&del_num);
- }
- break;
- case 3:
- printf("请输入要增加的学生的信息\n");
- printf("请输入学号,姓名(用逗号隔开):");
- stu=(struct student *)malloc(LEN);
- scanf("%d,%s",&stu->num,&stu->name);
- printf("请输入分数:");
- scanf("%d",&stu->score);
- while(stu->num!=0) {
- head=insert(head,stu);
- printf("请输入要增加的学生的信息\n");
- printf("请输入学号,姓名(用逗号隔开):");
- stu=(struct student *)malloc(LEN);
- scanf("%d,%s",&stu->num,&stu->name);
- printf("请输入分数:");
- scanf("%d",&stu->score);
- }
- break;
- case 4:
- printf("请输入要查找学生的学号:");
- scanf("%d",&ser_num);
- search(head,ser_num);
- break;
- case 5: print(head);break;
- case 6: chucun(head);break;
- case 7: daochu(& head);break;
- case 8: f = 0 ; break ;
- }
- } else {
- printf("\n") ;
- printf("请输入1-8之间的数字!!!\n");
- printf("\n") ;
- }
- }
- }
- struct student *creat() //建立链表的函数
- {
- struct student *head,*p1,*p2;
- n=0;
- p1=p2=(struct student *)malloc(LEN);
- printf("请输入学号,姓名(用逗号隔开):");
- scanf("%d,%s",&p1->num,&p1->name);
- printf("请输入分数:");
- scanf("%d",&p1->score);
- head=NULL;
- while(p1->num!=0)
- {
- n=n+1;
- if(n==1) head=p1;
- else p2->next=p1;
- p2=p1;
- p1=(struct student *)malloc(LEN);
- printf("请输入学号,姓名(用逗号隔开):");
- scanf("%d,%s",&p1->num,&p1->name);
- printf("请输入分数:");
- scanf("%d",&p1->score);
- }
- p2->next=NULL;
- return head;
- }
- struct student *insert(struct student *head,struct student *stud) //插入结点的函数
- {
- struct student *p0,*p1,*p2;
- p1=head;
- p0=stud; //指向要插入的结点
- if(head==NULL) //如果为空链表
- {
- head=p0;
- p0->next=NULL;
- }
- else
- {
- while((p0->num>p1->num)&&(p1->next!=NULL))
- {
- p2=p1;
- p1=p1->next;
- }
- }
- if(p0->num<=p1->num)
- {
- if(head==p1) head=p0; //插入的是头结点
- else p2->next=p0; //插入的是中间结点
- p0->next=p1;
- }
- else //插入的是尾结点
- {
- p1->next=p0;
- p0->next=NULL;
- }
- n=n+1;
- return(head);
- }
- struct student *del(struct student *head ,int num) //删除结点的函数
- {
- struct student *p1,*p2;
- if(head==NULL)
- {
- printf("\n该表是空表!\n");
- return(head);
- }
- p1=head;
- while(num!=p1->num&&p1->next!=NULL) //p1指向的不是所要找的结点且后面还有结点
- {
- p2=p1;
- p1=p1->next;
- }
- if(num==p1->num)
- {
- if(p1==head) head=p1->next; //若p1指向的是首结点
- else p2->next=p1->next;
- printf("删除%d号学生成功!",num);
- n=n-1;
- }
- else
- printf("没有找到%d",num);
- return(head);
- }
- void print(struct student *head) //输出链表的函数
- {
- struct student *p;
- p=head;
- printf("\n学生成绩为:\n");
- printf("\t学号\t姓名\t成绩\n_______________________________________________________________\n");
- if(head!=NULL)
- do
- {
- printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
- p=p->next;
- }while(p!=NULL);
- printf("总共有%d名学生",n);
- }
- void search(struct student *head,int num) //对链表的查询
- {
- struct student *p;
- if(head==NULL)
- printf("\n该表是空表!\n");
- p=head;
- if(p->num==num)
- {
- printf("该学生信息为:\n\n");
- printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
- }
- else
- {
- while(p!=NULL)
- {
- p=p->next;
- if(p!=NULL&&p->num==num)
- {
- break;
- }
- }
- if(p==NULL) printf("\t不存在该学号的学生!");
- else
- {
- printf("该学生信息为:\n\n");
- printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
- }
- }
- }
- void chucun(struct student * head)
- {
- FILE * fp ;
- char fn[] = "stu.dat" ;
- if((fp = fopen(fn , "wb")) != NULL) { // 【关键】必须是为二进制写打开
- for(; head ; head = head -> next) {
- fwrite(head , sizeof(struct student) , 1 , fp) ;
- }
- fclose(fp) ;
- } else {
- fprintf(stderr , "\n") ;
- fprintf(stderr , "无法创建记录文件 ["%s"] !\n" , fn) ;
- fprintf(stderr , "\n") ;
- }
- }
- void daochu(struct student ** head) // 【关键】通过 head 反馈链表头节点,得用二级指针
- {
- struct student * p , * q , stu ;
- FILE * fp ;
- char fn[] = "stu.dat" ;
- * head = NULL ; // 【关键】读取数据前,必须先将头节点地址置空
- if((fp = fopen(fn , "rb")) != NULL) { // 【关键】必须是为二进制读打开
- fread(& stu , sizeof(struct student) , 1 , fp) ;
- while(! feof(fp)) {
- if((p = (struct student *) malloc(sizeof(struct student))) != NULL) { // 【关键】节点数据有效才分配内存
- * p = stu ;
- p -> next = NULL ;
- if(* head) q -> next = p ;
- else * head = p ;
- q = p ;
- fread(& stu , sizeof(struct student) , 1 , fp) ;
- } else {
- for(p = * head ; p ; p = q) {
- q = p -> next ;
- free(p) ;
- }
- fprintf(stderr , "\n") ;
- fprintf(stderr , "内存分配失败 !\n") ;
- fprintf(stderr , "\n") ;
- }
- }
- fclose(fp) ;
- if(* head) {
- printf("\t学号\t姓名\t成绩\n_______________________________________________\n");
- for(p = * head ; p ; p = p -> next) {
- printf("\t%d\t%s\t%d\n",p->num,p->name,p->score) ;
- }
- }
- } else {
- fprintf(stderr , "\n") ;
- fprintf(stderr , "记录文件 ["%s"] 不存在!\n" , fn) ;
- fprintf(stderr , "\n") ;
- }
- }
复制代码
|
|