鱼C论坛

 找回密码
 立即注册
查看: 896|回复: 2

[已解决]为什么用fwrite写入文件中,关闭程序重新打开读这个文件会不行

[复制链接]
发表于 2021-1-7 13:11:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
要写一个学生成绩管理系统,第一次运行没有问题,但第二次我想直接从上次登记的数据读取的时候就不行了。
有没有大佬帮忙解答一下


  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #define LEN sizeof(struct student)
  4. struct student
  5. {
  6.         int num;
  7.         char name[10];
  8.         int score;
  9.         struct student *next;
  10. };
  11. int n;  //统计学生人数

  12. int main()
  13. {
  14.         struct student *creat();
  15.         struct student *insert(struct student *head,struct student *stud);
  16.         struct student *del(struct student *head ,int num);
  17.         void print(struct student *head);
  18.         void search(struct student *head,int num);
  19.         void chucun(struct student *head);
  20.         void daochu(struct student *head);             //函数声明
  21.        
  22.         struct student *head,*stu;
  23.         int del_num,ser_num,i;
  24.         printf("\n\t学生管理系统1.0\n\n");
  25.         printf("--------------菜单--------------\n\n");
  26.         printf("\t1.登记学生信息\n");
  27.         printf("\t2.删除学生信息\n");
  28.         printf("\t3.增加学生信息\n");
  29.         printf("\t4.查找学生信息\n");
  30.         printf("\t5.浏览学生信息\n");
  31.         printf("\t6.储存到文件\n");
  32.         printf("\t7.从文件导出\n");
  33.         printf("\t8.退出系统\n");
  34.         printf("\n说明:学生信息输入0,表示输入结束\n\n");
  35.         printf("请选择:");
  36.         scanf("%d",&i);
  37.         while(i!=8)
  38.         {
  39.                 switch(i)
  40.                 {
  41.                         case 1: head=creat();break;
  42.                         case 2:
  43.                         {
  44.                                 printf("请输入要删除的学号:");
  45.                                 scanf("%d",&del_num);
  46.                                 while(del_num!=0)
  47.                                 {
  48.                                         head=del(head,del_num);
  49.                                         printf("请输入要删除的学号:");
  50.                                         scanf("%d",&del_num);
  51.                                 }
  52.                                 break;
  53.                         }
  54.                         case 3:
  55.                         {
  56.                                 printf("请输入要增加的学生的信息\n");
  57.                                 printf("请输入学号,姓名(用逗号隔开):");
  58.                                 stu=(struct student *)malloc(LEN);
  59.                                 scanf("%d,%s",&stu->num,&stu->name);
  60.                                 printf("请输入分数:");
  61.                                 scanf("%d",&stu->score);
  62.                                 while(stu->num!=0)
  63.                                 {
  64.                                         head=insert(head,stu);
  65.                                         printf("请输入要增加的学生的信息\n");
  66.                                         printf("请输入学号,姓名(用逗号隔开):");
  67.                                         stu=(struct student *)malloc(LEN);
  68.                                         scanf("%d,%s",&stu->num,&stu->name);
  69.                                         printf("请输入分数:");
  70.                                         scanf("%d",&stu->score);
  71.                                 }
  72.                                 break;
  73.                         }
  74.                         case 4:
  75.                         {
  76.                                 printf("请输入要查找学生的学号:");
  77.                                 scanf("%d",&ser_num);
  78.                                 search(head,ser_num);
  79.                                 break;
  80.                         }
  81.                         case 5: print(head);break;
  82.                         case 6: chucun(head);break;
  83.                         case 7: daochu(head);break;
  84.                         case 8: break;
  85.                         default : printf("请输入1-8之间的数字!!!\n");
  86.                 }
  87.                 printf("\n\t学生管理系统1.0\n\n");
  88.                 printf("--------------菜单--------------\n\n");
  89.                 printf("\t1.登记学生信息\n");
  90.                 printf("\t2.删除学生信息\n");
  91.                 printf("\t3.增加学生信息\n");
  92.                 printf("\t4.查找学生信息\n");
  93.                 printf("\t5.浏览学生信息\n");
  94.                 printf("\t6.储存到文件\n");
  95.                 printf("\t7.从文件导出\n");
  96.                 printf("\t8.退出系统\n");
  97.                 printf("\n说明:学生信息输入0,表示输入结束\n\n");
  98.                 printf("请选择:");
  99.                 scanf("%d",&i);
  100.         }
  101.         return 0;
  102. }

  103. struct student *creat()   //建立链表的函数
  104. {
  105.         struct student *head,*p1,*p2;
  106.         n=0;
  107.         p1=p2=(struct student *)malloc(LEN);
  108.         printf("请输入学号,姓名(用逗号隔开):");
  109.         scanf("%d,%s",&p1->num,&p1->name);
  110.         printf("请输入分数:");
  111.         scanf("%d",&p1->score);
  112.         head=NULL;
  113.         while(p1->num!=0)
  114.         {
  115.                 n=n+1;
  116.                 if(n==1) head=p1;
  117.                 else p2->next=p1;
  118.                 p2=p1;
  119.                 p1=(struct student *)malloc(LEN);
  120.                 printf("请输入学号,姓名(用逗号隔开):");
  121.                 scanf("%d,%s",&p1->num,&p1->name);
  122.                 printf("请输入分数:");
  123.                 scanf("%d",&p1->score);
  124.         }
  125.         p2->next=NULL;
  126.         return head;
  127. }

  128. struct student *insert(struct student *head,struct student *stud)  //插入结点的函数
  129. {
  130.         struct student *p0,*p1,*p2;
  131.         p1=head;
  132.         p0=stud;         //指向要插入的结点
  133.         if(head==NULL)   //如果为空链表
  134.         {
  135.                 head=p0;
  136.                 p0->next=NULL;
  137.         }
  138.         else
  139.         {
  140.                 while((p0->num>p1->num)&&(p1->next!=NULL))
  141.                 {
  142.                         p2=p1;
  143.                         p1=p1->next;
  144.                 }
  145.         }
  146.         if(p0->num<=p1->num)
  147.         {
  148.                 if(head==p1) head=p0;  //插入的是头结点
  149.                 else p2->next=p0;      //插入的是中间结点
  150.                 p0->next=p1;
  151.         }
  152.         else                      //插入的是尾结点
  153.         {
  154.                 p1->next=p0;
  155.                 p0->next=NULL;
  156.         }
  157.         n=n+1;
  158.         return(head);
  159. }

  160. struct student *del(struct student *head ,int num)  //删除结点的函数
  161. {
  162.         struct student *p1,*p2;
  163.         if(head==NULL)
  164.         {
  165.                 printf("\n该表是空表!\n");
  166.                 return(head);
  167.         }
  168.         p1=head;
  169.         while(num!=p1->num&&p1->next!=NULL)  //p1指向的不是所要找的结点且后面还有结点
  170.         {
  171.                 p2=p1;
  172.                 p1=p1->next;
  173.         }
  174.         if(num==p1->num)
  175.         {
  176.                 if(p1==head) head=p1->next;  //若p1指向的是首结点
  177.                 else p2->next=p1->next;
  178.                 printf("删除%d号学生成功!",num);
  179.                 n=n-1;
  180.         }
  181.         else
  182.                 printf("没有找到%d",num);
  183.         return(head);
  184. }

  185. void print(struct student *head)      //输出链表的函数
  186. {
  187.         struct student *p;
  188.         p=head;
  189.         printf("\n学生成绩为:\n");
  190.         printf("\t学号\t姓名\t成绩\n_______________________________________________________________\n");
  191.         if(head!=NULL)
  192.                 do
  193.                 {
  194.                         printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
  195.                         p=p->next;
  196.                 }while(p!=NULL);
  197.         printf("总共有%d名学生",n);
  198. }

  199. void search(struct student *head,int num)  //对链表的查询
  200. {
  201.         struct student *p;
  202.         if(head==NULL)
  203.                 printf("\n该表是空表!\n");
  204.         p=head;
  205.         if(p->num==num)
  206.         {
  207.                 printf("该学生信息为:\n\n");
  208.                 printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  209.         }
  210.         else
  211.         {
  212.                 while(p!=NULL)
  213.                 {
  214.                         p=p->next;
  215.                         if(p!=NULL&&p->num==num)
  216.                         {
  217.                                 break;
  218.                         }
  219.                 }
  220.                 if(p==NULL) printf("\t不存在该学号的学生!");
  221.                 else
  222.                 {
  223.                         printf("该学生信息为:\n\n");
  224.                         printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  225.                 }
  226.         }
  227. }

  228. void chucun(struct student *head)
  229. {
  230.         struct student *p;
  231.         FILE *fp;
  232.         p=head;
  233.         fp=fopen("stud.dat","w");
  234.         while(p!=NULL)
  235.         {
  236.                 if(fwrite(p,LEN,1,fp)!=1)
  237.                         printf("数据存储失败!");
  238.                 p=p->next;
  239.         }
  240.         fclose(fp);
  241. }

  242. void daochu(struct student *head)
  243. {
  244.         struct student *p;
  245.         FILE *fp;
  246.         p=head;
  247.         fp=fopen("stud.dat","w");
  248.         printf("\t学号\t姓名\t成绩\n_______________________________________________\n");
  249.         while(p!=NULL)
  250.         {
  251.                 fread(p,LEN,1,fp);
  252.                 printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
  253.                 p=p->next;
  254.         }
  255. }
复制代码
最佳答案
2021-1-7 14:36:27
本帖最后由 jackz007 于 2021-1-7 15:24 编辑

       读取和保存链表的代码有些草率了,尤其是从文件中读取,不可以只是简单的从文件中整体读出整个链表,因为从文件中读取节点的 next 中保存的是当时下一个节点的内存地址,显然不能直接使用,必须是逐节点读出,然后,重新链接。
       以下代码重点修改了 main()、chucun()、daochu() 3 个函数
  1. #include <stdio.h>
  2. #include <malloc.h>

  3. #define LEN sizeof(struct student)

  4. struct student
  5. {
  6.         int num               ;
  7.         char name[10]         ;
  8.         int score             ;
  9.         struct student * next ;
  10. }                             ;

  11. int n;  //统计学生人数

  12. struct student *creat();
  13. struct student *insert(struct student *head,struct student *stud);
  14. struct student *del(struct student *head ,int num);
  15. void print(struct student *head);
  16. void search(struct student *head,int num);
  17. void chucun(struct student *head);
  18. void daochu(struct student **head);             //函数声明

  19. int main()
  20. {
  21.         struct student *head,*stu ;
  22.         int f , del_num , ser_num , i ;
  23.         for(f = 1 ; f ;) {
  24.                 printf("\n\t学生管理系统1.0\n\n");
  25.                 printf("--------------菜单--------------\n\n");
  26.                 printf("\t1.登记学生信息\n");
  27.                 printf("\t2.删除学生信息\n");
  28.                 printf("\t3.增加学生信息\n");
  29.                 printf("\t4.查找学生信息\n");
  30.                 printf("\t5.浏览学生信息\n");
  31.                 printf("\t6.储存到文件\n")  ;
  32.                 printf("\t7.从文件导出\n")  ;
  33.                 printf("\t8.退出系统\n")    ;
  34.                 printf("\n说明:学生信息输入0,表示输入结束\n\n");
  35.                 printf("请选择:")          ;
  36.                 fflush(stdin)               ;
  37.                 scanf("%d", & i)            ;
  38.                 if(i > 0 && i < 9) {
  39.                         switch(i) {
  40.                                 case 1: head=creat();break;
  41.                                 case 2:
  42.                                 printf("请输入要删除的学号:");
  43.                                 scanf("%d",&del_num);
  44.                                         while(del_num!=0) {
  45.                                                 head=del(head,del_num);
  46.                                                 printf("请输入要删除的学号:");
  47.                                                 scanf("%d",&del_num);
  48.                                         }
  49.                                         break;
  50.                                 case 3:
  51.                                         printf("请输入要增加的学生的信息\n");
  52.                                         printf("请输入学号,姓名(用逗号隔开):");
  53.                                         stu=(struct student *)malloc(LEN);
  54.                                         scanf("%d,%s",&stu->num,&stu->name);
  55.                                         printf("请输入分数:");
  56.                                         scanf("%d",&stu->score);
  57.                                         while(stu->num!=0) {
  58.                                                 head=insert(head,stu);
  59.                                                 printf("请输入要增加的学生的信息\n");
  60.                                                 printf("请输入学号,姓名(用逗号隔开):");
  61.                                                 stu=(struct student *)malloc(LEN);
  62.                                                 scanf("%d,%s",&stu->num,&stu->name);
  63.                                                 printf("请输入分数:");
  64.                                                 scanf("%d",&stu->score);
  65.                                         }
  66.                                         break;
  67.                                 case 4:
  68.                                         printf("请输入要查找学生的学号:");
  69.                                         scanf("%d",&ser_num);
  70.                                         search(head,ser_num);
  71.                                         break;
  72.                                 case 5: print(head);break;
  73.                                 case 6: chucun(head);break;
  74.                                 case 7: daochu(& head);break;
  75.                                 case 8: f = 0 ; break ;
  76.                         }
  77.                 } else {
  78.                         printf("\n")                         ;
  79.                         printf("请输入1-8之间的数字!!!\n");
  80.                         printf("\n")                         ;
  81.                 }
  82.         }
  83. }

  84. struct student *creat()   //建立链表的函数
  85. {
  86.         struct student *head,*p1,*p2;
  87.         n=0;
  88.         p1=p2=(struct student *)malloc(LEN);
  89.         printf("请输入学号,姓名(用逗号隔开):");
  90.         scanf("%d,%s",&p1->num,&p1->name);
  91.         printf("请输入分数:");
  92.         scanf("%d",&p1->score);
  93.         head=NULL;
  94.         while(p1->num!=0)
  95.         {
  96.                 n=n+1;
  97.                 if(n==1) head=p1;
  98.                 else p2->next=p1;
  99.                 p2=p1;
  100.                 p1=(struct student *)malloc(LEN);
  101.                 printf("请输入学号,姓名(用逗号隔开):");
  102.                 scanf("%d,%s",&p1->num,&p1->name);
  103.                 printf("请输入分数:");
  104.                 scanf("%d",&p1->score);
  105.         }
  106.         p2->next=NULL;
  107.         return head;
  108. }

  109. struct student *insert(struct student *head,struct student *stud)  //插入结点的函数
  110. {
  111.         struct student *p0,*p1,*p2;
  112.         p1=head;
  113.         p0=stud;         //指向要插入的结点
  114.         if(head==NULL)   //如果为空链表
  115.         {
  116.                 head=p0;
  117.                 p0->next=NULL;
  118.         }
  119.         else
  120.         {
  121.                 while((p0->num>p1->num)&&(p1->next!=NULL))
  122.                 {
  123.                         p2=p1;
  124.                         p1=p1->next;
  125.                 }
  126.         }
  127.         if(p0->num<=p1->num)
  128.         {
  129.                 if(head==p1) head=p0;  //插入的是头结点
  130.                 else p2->next=p0;      //插入的是中间结点
  131.                 p0->next=p1;
  132.         }
  133.         else                      //插入的是尾结点
  134.         {
  135.                 p1->next=p0;
  136.                 p0->next=NULL;
  137.         }
  138.         n=n+1;
  139.         return(head);
  140. }

  141. struct student *del(struct student *head ,int num)  //删除结点的函数
  142. {
  143.         struct student *p1,*p2;
  144.         if(head==NULL)
  145.         {
  146.                 printf("\n该表是空表!\n");
  147.                 return(head);
  148.         }
  149.         p1=head;
  150.         while(num!=p1->num&&p1->next!=NULL)  //p1指向的不是所要找的结点且后面还有结点
  151.         {
  152.                 p2=p1;
  153.                 p1=p1->next;
  154.         }
  155.         if(num==p1->num)
  156.         {
  157.                 if(p1==head) head=p1->next;  //若p1指向的是首结点
  158.                 else p2->next=p1->next;
  159.                 printf("删除%d号学生成功!",num);
  160.                 n=n-1;
  161.         }
  162.         else
  163.                 printf("没有找到%d",num);
  164.         return(head);
  165. }

  166. void print(struct student *head)      //输出链表的函数
  167. {
  168.         struct student *p;
  169.         p=head;
  170.         printf("\n学生成绩为:\n");
  171.         printf("\t学号\t姓名\t成绩\n_______________________________________________________________\n");
  172.         if(head!=NULL)
  173.                 do
  174.                 {
  175.                         printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
  176.                         p=p->next;
  177.                 }while(p!=NULL);
  178.         printf("总共有%d名学生",n);
  179. }

  180. void search(struct student *head,int num)  //对链表的查询
  181. {
  182.         struct student *p;
  183.         if(head==NULL)
  184.                 printf("\n该表是空表!\n");
  185.         p=head;
  186.         if(p->num==num)
  187.         {
  188.                 printf("该学生信息为:\n\n");
  189.                 printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  190.         }
  191.         else
  192.         {
  193.                 while(p!=NULL)
  194.                 {
  195.                         p=p->next;
  196.                         if(p!=NULL&&p->num==num)
  197.                         {
  198.                                 break;
  199.                         }
  200.                 }
  201.                 if(p==NULL) printf("\t不存在该学号的学生!");
  202.                 else
  203.                 {
  204.                         printf("该学生信息为:\n\n");
  205.                         printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  206.                 }
  207.         }
  208. }

  209. void chucun(struct student * head)
  210. {
  211.         FILE * fp                                                                  ;
  212.         char fn[] = "stu.dat"                                                      ;
  213.         if((fp = fopen(fn , "wb")) != NULL) {                                                 // 【关键】必须是为二进制写打开
  214.                 for(; head ; head = head -> next) {
  215.                         fwrite(head , sizeof(struct student) , 1 , fp)             ;
  216.                 }
  217.                 fclose(fp)                                                         ;
  218.         } else {
  219.                 fprintf(stderr , "\n")                                             ;
  220.                 fprintf(stderr , "无法创建记录文件 ["%s"] !\n" , fn)            ;
  221.                 fprintf(stderr , "\n")                                             ;
  222.         }
  223. }

  224. void daochu(struct student ** head)                                                           // 【关键】通过 head 反馈链表头节点,得用二级指针
  225. {
  226.         struct student * p , * q , stu                                             ;
  227.         FILE * fp                                                                  ;
  228.         char fn[] = "stu.dat"                                                      ;
  229.         * head = NULL                                                              ;          // 【关键】读取数据前,必须先将头节点地址置空
  230.         if((fp = fopen(fn , "rb")) != NULL) {                                                 // 【关键】必须是为二进制读打开
  231.                 fread(& stu , sizeof(struct student) , 1 , fp)                     ;
  232.                 while(! feof(fp)) {
  233.                         if((p = (struct student *) malloc(sizeof(struct student))) != NULL) { // 【关键】节点数据有效才分配内存
  234.                                 * p = stu                                          ;
  235.                                 p -> next = NULL                                   ;
  236.                                 if(* head) q -> next = p                           ;
  237.                                 else * head = p                                    ;
  238.                                 q = p                                              ;
  239.                                 fread(& stu , sizeof(struct student) , 1 , fp)     ;
  240.                         } else {
  241.                                 for(p = * head ; p ; p = q) {
  242.                                         q = p -> next                              ;
  243.                                         free(p)                                    ;
  244.                                 }
  245.                                 fprintf(stderr , "\n")                             ;
  246.                                 fprintf(stderr , "内存分配失败 !\n")               ;
  247.                                 fprintf(stderr , "\n")                             ;
  248.                         }
  249.                 }
  250.                 fclose(fp)                                                         ;
  251.                 if(* head) {
  252.                         printf("\t学号\t姓名\t成绩\n_______________________________________________\n");
  253.                         for(p = * head ; p ; p = p -> next) {
  254.                                 printf("\t%d\t%s\t%d\n",p->num,p->name,p->score)   ;
  255.                         }
  256.                 }
  257.         } else {
  258.                 fprintf(stderr , "\n")                                             ;
  259.                 fprintf(stderr , "记录文件 ["%s"] 不存在!\n" , fn)              ;
  260.                 fprintf(stderr , "\n")                                             ;
  261.         }
  262. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-1-7 14:36:27 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2021-1-7 15:24 编辑

       读取和保存链表的代码有些草率了,尤其是从文件中读取,不可以只是简单的从文件中整体读出整个链表,因为从文件中读取节点的 next 中保存的是当时下一个节点的内存地址,显然不能直接使用,必须是逐节点读出,然后,重新链接。
       以下代码重点修改了 main()、chucun()、daochu() 3 个函数
  1. #include <stdio.h>
  2. #include <malloc.h>

  3. #define LEN sizeof(struct student)

  4. struct student
  5. {
  6.         int num               ;
  7.         char name[10]         ;
  8.         int score             ;
  9.         struct student * next ;
  10. }                             ;

  11. int n;  //统计学生人数

  12. struct student *creat();
  13. struct student *insert(struct student *head,struct student *stud);
  14. struct student *del(struct student *head ,int num);
  15. void print(struct student *head);
  16. void search(struct student *head,int num);
  17. void chucun(struct student *head);
  18. void daochu(struct student **head);             //函数声明

  19. int main()
  20. {
  21.         struct student *head,*stu ;
  22.         int f , del_num , ser_num , i ;
  23.         for(f = 1 ; f ;) {
  24.                 printf("\n\t学生管理系统1.0\n\n");
  25.                 printf("--------------菜单--------------\n\n");
  26.                 printf("\t1.登记学生信息\n");
  27.                 printf("\t2.删除学生信息\n");
  28.                 printf("\t3.增加学生信息\n");
  29.                 printf("\t4.查找学生信息\n");
  30.                 printf("\t5.浏览学生信息\n");
  31.                 printf("\t6.储存到文件\n")  ;
  32.                 printf("\t7.从文件导出\n")  ;
  33.                 printf("\t8.退出系统\n")    ;
  34.                 printf("\n说明:学生信息输入0,表示输入结束\n\n");
  35.                 printf("请选择:")          ;
  36.                 fflush(stdin)               ;
  37.                 scanf("%d", & i)            ;
  38.                 if(i > 0 && i < 9) {
  39.                         switch(i) {
  40.                                 case 1: head=creat();break;
  41.                                 case 2:
  42.                                 printf("请输入要删除的学号:");
  43.                                 scanf("%d",&del_num);
  44.                                         while(del_num!=0) {
  45.                                                 head=del(head,del_num);
  46.                                                 printf("请输入要删除的学号:");
  47.                                                 scanf("%d",&del_num);
  48.                                         }
  49.                                         break;
  50.                                 case 3:
  51.                                         printf("请输入要增加的学生的信息\n");
  52.                                         printf("请输入学号,姓名(用逗号隔开):");
  53.                                         stu=(struct student *)malloc(LEN);
  54.                                         scanf("%d,%s",&stu->num,&stu->name);
  55.                                         printf("请输入分数:");
  56.                                         scanf("%d",&stu->score);
  57.                                         while(stu->num!=0) {
  58.                                                 head=insert(head,stu);
  59.                                                 printf("请输入要增加的学生的信息\n");
  60.                                                 printf("请输入学号,姓名(用逗号隔开):");
  61.                                                 stu=(struct student *)malloc(LEN);
  62.                                                 scanf("%d,%s",&stu->num,&stu->name);
  63.                                                 printf("请输入分数:");
  64.                                                 scanf("%d",&stu->score);
  65.                                         }
  66.                                         break;
  67.                                 case 4:
  68.                                         printf("请输入要查找学生的学号:");
  69.                                         scanf("%d",&ser_num);
  70.                                         search(head,ser_num);
  71.                                         break;
  72.                                 case 5: print(head);break;
  73.                                 case 6: chucun(head);break;
  74.                                 case 7: daochu(& head);break;
  75.                                 case 8: f = 0 ; break ;
  76.                         }
  77.                 } else {
  78.                         printf("\n")                         ;
  79.                         printf("请输入1-8之间的数字!!!\n");
  80.                         printf("\n")                         ;
  81.                 }
  82.         }
  83. }

  84. struct student *creat()   //建立链表的函数
  85. {
  86.         struct student *head,*p1,*p2;
  87.         n=0;
  88.         p1=p2=(struct student *)malloc(LEN);
  89.         printf("请输入学号,姓名(用逗号隔开):");
  90.         scanf("%d,%s",&p1->num,&p1->name);
  91.         printf("请输入分数:");
  92.         scanf("%d",&p1->score);
  93.         head=NULL;
  94.         while(p1->num!=0)
  95.         {
  96.                 n=n+1;
  97.                 if(n==1) head=p1;
  98.                 else p2->next=p1;
  99.                 p2=p1;
  100.                 p1=(struct student *)malloc(LEN);
  101.                 printf("请输入学号,姓名(用逗号隔开):");
  102.                 scanf("%d,%s",&p1->num,&p1->name);
  103.                 printf("请输入分数:");
  104.                 scanf("%d",&p1->score);
  105.         }
  106.         p2->next=NULL;
  107.         return head;
  108. }

  109. struct student *insert(struct student *head,struct student *stud)  //插入结点的函数
  110. {
  111.         struct student *p0,*p1,*p2;
  112.         p1=head;
  113.         p0=stud;         //指向要插入的结点
  114.         if(head==NULL)   //如果为空链表
  115.         {
  116.                 head=p0;
  117.                 p0->next=NULL;
  118.         }
  119.         else
  120.         {
  121.                 while((p0->num>p1->num)&&(p1->next!=NULL))
  122.                 {
  123.                         p2=p1;
  124.                         p1=p1->next;
  125.                 }
  126.         }
  127.         if(p0->num<=p1->num)
  128.         {
  129.                 if(head==p1) head=p0;  //插入的是头结点
  130.                 else p2->next=p0;      //插入的是中间结点
  131.                 p0->next=p1;
  132.         }
  133.         else                      //插入的是尾结点
  134.         {
  135.                 p1->next=p0;
  136.                 p0->next=NULL;
  137.         }
  138.         n=n+1;
  139.         return(head);
  140. }

  141. struct student *del(struct student *head ,int num)  //删除结点的函数
  142. {
  143.         struct student *p1,*p2;
  144.         if(head==NULL)
  145.         {
  146.                 printf("\n该表是空表!\n");
  147.                 return(head);
  148.         }
  149.         p1=head;
  150.         while(num!=p1->num&&p1->next!=NULL)  //p1指向的不是所要找的结点且后面还有结点
  151.         {
  152.                 p2=p1;
  153.                 p1=p1->next;
  154.         }
  155.         if(num==p1->num)
  156.         {
  157.                 if(p1==head) head=p1->next;  //若p1指向的是首结点
  158.                 else p2->next=p1->next;
  159.                 printf("删除%d号学生成功!",num);
  160.                 n=n-1;
  161.         }
  162.         else
  163.                 printf("没有找到%d",num);
  164.         return(head);
  165. }

  166. void print(struct student *head)      //输出链表的函数
  167. {
  168.         struct student *p;
  169.         p=head;
  170.         printf("\n学生成绩为:\n");
  171.         printf("\t学号\t姓名\t成绩\n_______________________________________________________________\n");
  172.         if(head!=NULL)
  173.                 do
  174.                 {
  175.                         printf("\t%d\t%s\t%d\n",p->num,p->name,p->score);
  176.                         p=p->next;
  177.                 }while(p!=NULL);
  178.         printf("总共有%d名学生",n);
  179. }

  180. void search(struct student *head,int num)  //对链表的查询
  181. {
  182.         struct student *p;
  183.         if(head==NULL)
  184.                 printf("\n该表是空表!\n");
  185.         p=head;
  186.         if(p->num==num)
  187.         {
  188.                 printf("该学生信息为:\n\n");
  189.                 printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  190.         }
  191.         else
  192.         {
  193.                 while(p!=NULL)
  194.                 {
  195.                         p=p->next;
  196.                         if(p!=NULL&&p->num==num)
  197.                         {
  198.                                 break;
  199.                         }
  200.                 }
  201.                 if(p==NULL) printf("\t不存在该学号的学生!");
  202.                 else
  203.                 {
  204.                         printf("该学生信息为:\n\n");
  205.                         printf("\t学号\t姓名\t成绩\n\t%d\t%s\n",p->num,p->name,p->score);
  206.                 }
  207.         }
  208. }

  209. void chucun(struct student * head)
  210. {
  211.         FILE * fp                                                                  ;
  212.         char fn[] = "stu.dat"                                                      ;
  213.         if((fp = fopen(fn , "wb")) != NULL) {                                                 // 【关键】必须是为二进制写打开
  214.                 for(; head ; head = head -> next) {
  215.                         fwrite(head , sizeof(struct student) , 1 , fp)             ;
  216.                 }
  217.                 fclose(fp)                                                         ;
  218.         } else {
  219.                 fprintf(stderr , "\n")                                             ;
  220.                 fprintf(stderr , "无法创建记录文件 ["%s"] !\n" , fn)            ;
  221.                 fprintf(stderr , "\n")                                             ;
  222.         }
  223. }

  224. void daochu(struct student ** head)                                                           // 【关键】通过 head 反馈链表头节点,得用二级指针
  225. {
  226.         struct student * p , * q , stu                                             ;
  227.         FILE * fp                                                                  ;
  228.         char fn[] = "stu.dat"                                                      ;
  229.         * head = NULL                                                              ;          // 【关键】读取数据前,必须先将头节点地址置空
  230.         if((fp = fopen(fn , "rb")) != NULL) {                                                 // 【关键】必须是为二进制读打开
  231.                 fread(& stu , sizeof(struct student) , 1 , fp)                     ;
  232.                 while(! feof(fp)) {
  233.                         if((p = (struct student *) malloc(sizeof(struct student))) != NULL) { // 【关键】节点数据有效才分配内存
  234.                                 * p = stu                                          ;
  235.                                 p -> next = NULL                                   ;
  236.                                 if(* head) q -> next = p                           ;
  237.                                 else * head = p                                    ;
  238.                                 q = p                                              ;
  239.                                 fread(& stu , sizeof(struct student) , 1 , fp)     ;
  240.                         } else {
  241.                                 for(p = * head ; p ; p = q) {
  242.                                         q = p -> next                              ;
  243.                                         free(p)                                    ;
  244.                                 }
  245.                                 fprintf(stderr , "\n")                             ;
  246.                                 fprintf(stderr , "内存分配失败 !\n")               ;
  247.                                 fprintf(stderr , "\n")                             ;
  248.                         }
  249.                 }
  250.                 fclose(fp)                                                         ;
  251.                 if(* head) {
  252.                         printf("\t学号\t姓名\t成绩\n_______________________________________________\n");
  253.                         for(p = * head ; p ; p = p -> next) {
  254.                                 printf("\t%d\t%s\t%d\n",p->num,p->name,p->score)   ;
  255.                         }
  256.                 }
  257.         } else {
  258.                 fprintf(stderr , "\n")                                             ;
  259.                 fprintf(stderr , "记录文件 ["%s"] 不存在!\n" , fn)              ;
  260.                 fprintf(stderr , "\n")                                             ;
  261.         }
  262. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-7 18:51:19 | 显示全部楼层
jackz007 发表于 2021-1-7 14:36
读取和保存链表的代码有些草率了,尤其是从文件中读取,不可以只是简单的从文件中整体读出整个链表 ...

感谢大佬
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-3 04:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表