鱼C论坛

 找回密码
 立即注册
查看: 4570|回复: 10

fprintf 和 fscanf 存读问题求高人指点

[复制链接]
发表于 2013-4-23 12:23:18 | 显示全部楼层 |阅读模式
5鱼币
这个代码一开始只要求输入员工,工号,名字,工资,只存储工号,工资。
没要求取出在进行操作的。后来一个朋友说加上一个在取出后删除的操作
结果就在用fscanf取出数据后发现悲催了。

求高人指点一下
rty.gif

下面是代码略长有问题的就最后一段
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<stdlib.h>

  4. #define ZJ sizeof(data)

  5. struct data
  6. {
  7.         int a;
  8.         char m[20];
  9.         int g;
  10.         struct data *e;
  11. };

  12. void main()
  13. {
  14.         struct data *lianbiao();
  15.         void baochun(struct data *p);
  16.         void puchu();

  17.         struct data *lb;

  18.         lb = lianbiao();
  19.         baochun(lb);
  20.         puchu();

  21. }

  22. struct data *lianbiao()      //建立链表
  23. {
  24.         struct data *p,*x,*y;
  25.        
  26.         printf("输入工人数据以工号‘0’结束\n");

  27.         p = x = y =(struct data *)malloc(ZJ);
  28.        
  29.         while(y->a)
  30.         {
  31.                 printf("输入工号 ");
  32.                 scanf("%d",&y->a);
  33.                 if(y->a != 0)
  34.                 {
  35.                         printf("输入名字 ");
  36.                         scanf("%s",&y->m);
  37.                         printf("输入工资 ");
  38.                         scanf("%d",&y->g);

  39.                         x = y;
  40.                         y = (struct data *)malloc(ZJ);
  41.                         x -> e = y;
  42.                 }
  43.                 else x -> e = NULL;
  44.         }
  45.         free(y);
  46.         return p;
  47. }  //

  48. void baochun(struct data *p)   //将建立的链表保存到文件 (只保存工号工资)
  49. {
  50.         char a[20];
  51.         FILE *fp;

  52.         printf("输入创建文件的目录和名字\n");
  53.         scanf("%s",a);

  54.         if((fp = fopen(a,"wb")) == NULL)
  55.         {
  56.                 printf("文件建立失败\n");
  57.                 exit(0);
  58.         }

  59.         printf("保存工号和工资\n");

  60.         while(p)
  61.         {
  62.                 fprintf(fp,"%d,%d",p->a,p->g);
  63.                 printf("%d,%d\n",p->a,p->g);
  64.                 p = p -> e;
  65.         }
  66.         free(p);
  67.         fclose(fp);
  68. }

  69. void puchu()  //取出工号工资进行删除操作
  70. {
  71.         char a[20];
  72.         FILE *fp;
  73.         struct data *p,*y,*x;

  74.         printf("输入读取文件的目录和名字\n");
  75.         scanf("%s",a);

  76.         if((fp = fopen(a,"rb+")) == NULL)
  77.         {
  78.                 printf("打开文件失败\n");
  79.                 exit(0);
  80.         }

  81.         p = y = x = (struct data *)malloc(ZJ);

  82.         while(feof(fp)==0)                         /*取出的数据是乱码,且可能无限循环*/
  83.         {
  84.                 fscanf(fp,"%d%d",&y->a,&y->g);
  85.                 printf("%d,%d\n",y->a,y->g);
  86.                 x = y;
  87.                 y = (struct data *)malloc(ZJ);
  88.                 x -> e = y;
  89.         }
  90.         x -> e = NULL;
  91.         free(y);
  92. }
复制代码

最佳答案

查看完整内容

fprintf(fp,"%d,%d",p->a,p->g); printf("%d,%d\n",p->a,p->g); 楼主 你的代码 假设 有数据 12 34 56 78 你这样写入文件 就会是 12,3456,78....... printf其实是 fprintf(stdout....) 你的printf 里面记得加\n fprintf就得加 \n fscanf(fp,"%d%d",&y->a,&y->g); printf("%d,%d\n",y->a,y->g); 你文件中的内容 两个数据中间用逗号分开了 那 ...
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-4-23 12:23:19 | 显示全部楼层
                fprintf(fp,"%d,%d",p->a,p->g);
                printf("%d,%d\n",p->a,p->g);
楼主 你的代码
假设 有数据
12 34
56 78
你这样写入文件 就会是
12,3456,78.......

printf其实是 fprintf(stdout....)
你的printf 里面记得加\n
fprintf就得加 \n

                fscanf(fp,"%d%d",&y->a,&y->g);
                printf("%d,%d\n",y->a,y->g);
你文件中的内容 两个数据中间用逗号分开了
那么 读取的时候 2个数据中间就得加逗号
fscanf(fp, "%d,%d"......)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-23 14:12:47 | 显示全部楼层
fscanf遇见空格就返回了。这里可以考虑用fread fseek 的方式。保存文件的时候 加一些特殊的间隔符号方便读取时候识别
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-23 14:13:51 | 显示全部楼层
另外,我还发现一个问题,就是你这个代码,开始输入0的时候就会崩溃,保护判断没有做
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-23 14:18:12 | 显示全部楼层
等下帮你整一下把。就当是复习,好久没搞c语言了。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-4-23 15:58:05 | 显示全部楼层

谢谢这个我还真悲催了一个下午
你指点一下果然ok
还有楼上的不提醒我,我都忘记了写代码要容错;
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-23 16:07:18 | 显示全部楼层
大哥,你的代码逻辑有点惨不忍睹,链表函数里面,逻辑有点混乱。那里我帮你小改一下,没有大改,另外,我把读写改成了fwrite和fwrite了。代码如下
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<stdlib.h>

  4. #define ZJ sizeof(data)

  5. struct data *lianbiao();
  6. void baochun(struct data *p);
  7. void puchu();


  8. struct data
  9. {
  10.         int a;
  11.         char m[20];
  12.         int g;
  13.         struct data *e;
  14. };



  15. struct data *lianbiao()      //建立链表
  16. {
  17.         struct data *p,*x,*y;

  18.         printf("输入工人数据以工号‘0’结束\n");

  19.         p = x = y =(struct data *)malloc(ZJ);

  20.         while(y->a)
  21.         {
  22.                 printf("输入工号 ");
  23.                 scanf("%d",&y->a);
  24.                 if(y->a != 0)
  25.                 {
  26.                         printf("输入名字 ");
  27.                         scanf("%s",&y->m);
  28.                         printf("输入工资 ");
  29.                         scanf("%d",&y->g);

  30.                         x = y;
  31.                         y = (struct data *)malloc(ZJ);
  32.                         x -> e = y;
  33.                 }
  34.                 else x -> e = NULL;
  35.         }
  36.         if (y == p)
  37.         {
  38.                 p = NULL;
  39.                 free(y);
  40.                 y = NULL;
  41.         }
  42.        
  43.        
  44.         return p;
  45. }  //

  46. void baochun(struct data *p)   //将建立的链表保存到文件 (只保存工号工资)
  47. {
  48.         if (!p)
  49.         {
  50.                 return;
  51.         }
  52.        
  53.         char a[20];
  54.         FILE *fp = NULL;

  55.         printf("输入创建文件的目录和名字\n");
  56.         scanf("%s",a);

  57.         if((fp = fopen(a,"wb")) == NULL)
  58.         {
  59.                 printf("文件建立失败\n");
  60.                 exit(0);
  61.         }

  62.         printf("保存工号和工资\n");

  63.         if (!p->a)
  64.         {
  65.                 free(p);
  66.                 fclose(fp);
  67.         }
  68.        
  69.         while(p)
  70.         {
  71.                 //fprintf(fp,"%d,%d",p->a,p->g);
  72.                 int nCount =  fwrite(&(p->a),sizeof(int),1,fp);
  73.                 nCount = fwrite(&(p->g),sizeof(int),1,fp);

  74.                
  75.                 printf("%d,%d\n",p->a,p->g);
  76.                 p = p -> e;
  77.         }
  78.         free(p);
  79.         fclose(fp);
  80. }

  81. void puchu()  //取出工号工资进行删除操作
  82. {
  83.         char a[20];
  84.         FILE *fp;
  85.         struct data *p,*y,*x;

  86.         printf("输入读取文件的目录和名字\n");
  87.         scanf("%s",a);

  88.         if((fp = fopen(a,"rb+")) == NULL)
  89.         {
  90.                 printf("打开文件失败\n");
  91.                 exit(0);
  92.         }

  93.         p = y = x = (struct data *)malloc(ZJ);

  94.         int nCount = fread(&(y->a),sizeof(int),1,fp);
  95.         nCount = fread(&(y->g),sizeof(int),1,fp);


  96.         while(!feof(fp))                         /*取出的数据是乱码,且可能无限循环*/
  97.         {
  98.                 //读完最后一个字符后,fp->flag仍然没有被置为_IOEOF,因而feof()仍然没有探测到文件结尾。直到再次调用fgetc()执行读操作,feof()才能探测到文件结尾。这样就多输出了一个
  99.                 printf("%d,%d\n",y->a,y->g);
  100.                 int nCount = fread(&(y->a),sizeof(int),1,fp);
  101.                 nCount = fread(&(y->g),sizeof(int),1,fp);

  102.                
  103.                 x = y;
  104.                 y = (struct data *)malloc(ZJ);
  105.                 x -> e = y;

  106.         }
  107.         x -> e = NULL;
  108.         free(y);
  109. }

  110. int main(int argc, _TCHAR* argv[])
  111. {
  112.         struct data *lb;

  113.         lb = lianbiao();
  114.         baochun(lb);
  115.         puchu();

  116.         while (1)
  117.         {
  118.                 int d = 0;
  119.                 scanf("%d",&d);

  120.                 if (1 == d)
  121.                 {
  122.                         break;
  123.                 }

  124.         }
  125.         return 0;
  126. }
复制代码
建议把头指针和其他的指针区分开来。单独写createHead 和addNode函数
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-4-23 16:44:08 | 显示全部楼层
熊文杰 发表于 2013-4-23 16:07
大哥,你的代码逻辑有点惨不忍睹,链表函数里面,逻辑有点混乱。那里我帮你小改一下,没有大改,另外,我把 ...

学习了果然高手,求教,求升级。求入门进阶教程
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-23 19:02:33 | 显示全部楼层
vfcv 发表于 2013-4-23 16:44
学习了果然高手,求教,求升级。求入门进阶教程

fscanf,和fprintf不建议用,效率不高,写的时候将2进制转换成ascii,读的时候又要讲ascii转换成2进制,效率很低的,常规做法是用fread和fwrite fseek配合进行读写。代码如果需要优化的话,单独写链表文件,不要写一起。不知道小甲鱼的零基础c语言里面是怎么说的,没看他的c语言教程。学习c语言的话,写个栈的例子,链表的例子感觉就差不多了。如果觉得还不够 可以写一些数据结构,比如复杂点的红黑树。这些东西如果能用c熟练的编写 就没什么问题了。c语言的书 我没看几本 一本谭浩强的入门c程序设计,一本c陷阱与缺陷 一本数据结构。然后再就是c++ primer 第三版。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-24 14:41:39 | 显示全部楼层
学习了{:1_1:}{:1_1:}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-4-24 15:07:04 | 显示全部楼层
熊文杰 发表于 2013-4-23 19:02
fscanf,和fprintf不建议用,效率不高,写的时候将2进制转换成ascii,读的时候又要讲ascii转换成2进制,效 ...

这个看具体情况了
效率未必是第一考虑

这里 如果需要写出来的文件
能直接打开查看内容 那么
用fscanf fprintf 是一个不错的选择
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-1 18:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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