【问题标题】:Function fscanf crash app after first use [closed]首次使用后功能 fscanf 崩溃应用程序[关闭]
【发布时间】:2017-01-17 21:35:30
【问题描述】:

如果我评论fprintf(pf,"1111"); exe 会崩溃,如果我保留它,我会得到 2/3/2011(只有第一条记录)。如果我尝试关闭文件,exe 也会崩溃。

fscanf 是否将行尾检测为文件尾并读取 null?

我也试过关闭(*pf),它仍然崩溃。

fprintf不应该在最终代码中使用,我不是故意使用它,但是当我使用它时,我观察到exe成功读取第一行

 Data* d;
fscanf(pf,"%d",&n);
d=calloc(n,sizeof(Data* ));
for(i=0;i<n;i++){
    if(fscanf(pf,"%d/%d/%d",&(d[i].zi),&(d[i].luna),&(d[i].an))!=3) break;
    printf("%d/%d/%d ",d[i].zi,d[i].luna,d[i].an);
       // fprintf(pf,"1111"); with this I observed that first data can be read

}
  fclose(pf);

输入

3
2/3/2011
2/2/2012
2/2/2016

【问题讨论】:

  • 听起来 pf 是 NULL。你查看fopen的返回码了吗?
  • d[i]的类型是什么? d的类型是什么?
  • 1) d=(Data*)calloc(n,sizeof(Data* )); --> d=calloc(n,sizeof(Data)); 2) for(i=1;i&lt;=n;i++){ --> for(i=0;i&lt;n;i++){ 3) 删除 fprintf(pf,"1111"); 4) fscanf(pf,"%d",&amp;n); 移动到d=calloc(n,sizeof(Data));之前
  • 在声明d=(Data*)calloc(n,sizeof(Data*))中,n是未定义的,更何况sizeof(Data)sizeof(Data*)可能是不同的。
  • @BLUEPIXY 谢谢,这就是答案,它起作用了。你能把它作为答案发布,因为我不能投票给 de cmets 吗? sizeof(Data) 我现在看到的是 12 而 sizeof(Data*) 是 4

标签: c file for-loop scanf fclose


【解决方案1】:

欢迎使用 C 编程。

在 C 中,循环是这样写的:

for( i = 0;  i < n;  i++ )

不是这样的:

for( i = 1;  i <= n;  i++ )

【讨论】:

  • 如果d被声明为struct something d[3],使用1..3会导致问题
  • 它仍然崩溃,我把它设为 1 因为我认为它可以做某事,但它不能
【解决方案2】:

除了在你的程序中指出的其他错误之外,崩溃的真正原因是:一旦你使用fprintf(),文件指针就指向了文件的末尾。因此,本质上您是在第二次调用中尝试在文件末尾使用fscanf,从而导致崩溃。要解决此问题,您可以在 fprintf 调用之后使用 rewind(),这会将文件指针回退到以前的位置。

fscanf(pf,"%d",&n);
for(i=1;i<=n;i++){
    if(fscanf(pf,"%d/%d/%d",&(d[i].zi),&(d[i].luna),&(d[i].an))!=3) break;
    printf("%d/%d/%d ",d[i].zi,d[i].luna,d[i].an);
        fprintf(pf,"1111");
    }
    rewind(fp);
}
  fclose(pf);

编辑:正如 cmets 中所指出的,这可能不是您想要的。更好的方法是跟踪到目前为止读取的字节,并在使用 fprintf 后使用 fseek 到达您想要的位置。

【讨论】:

  • 您发现错误是正确的,但我认为您的修复建议不会奏效。 OP 可能需要重新考虑他/她正在尝试做什么。从同一个文本文件中读取和同时写入在概念上是有缺陷的。
  • 添加 rewind() 将不起作用,因为 fscanf 调用将由于“1111”与说明符“%d/%d/&d”不匹配而失败。正如@Mike 所说,OP 需要重新考虑他想要做什么。
  • rewind 需要参数 pf,它会刷新文件,所以第二行和第三行永远不会被读取
  • 是的,这确实是一个有缺陷的想法。但如果他真的出于某种原因想要这样做,他的选择是rewindfseek 并跟踪字节。
  • 无论如何,读取和写入同一个文件都充满了潜在的问题。
【解决方案3】:

像这样修复:

#include <stdio.h>
#include <stdlib.h>

typedef struct data {
    int zi, luna, an;
} Data;

int main(void){
    FILE *pf = fopen("data.txt", "r");
    if(pf == NULL){
        perror("fopen");
        return -1;
    }
    Data *d;
    int n;
    fscanf(pf, "%d", &n);
    d = calloc(n, sizeof(Data));//sizeof(Data* ) should be sizeof(Data)
    if(d == NULL){
        perror("malloc");
        return -2;
    }
    for(int i = 0; i < n; i++){//i <= n occurs out ouf bounds, In C 0 origin
        if(fscanf(pf, "%d/%d/%d", &d[i].zi, &d[i].luna,&d[i].an)!=3) break;
        printf("%d/%d/%d ", d[i].zi, d[i].luna, d[i].an);
    }
    fclose(pf);
    free(d);
}

DEMO

【讨论】:

  • 再次感谢,fseek 是否有第二个解决方案?只是想知道...
  • @KingTsunamy fseek 不是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多