在C程序中使用fscanf的奇怪行为

时间:2015-12-08 06:37:08

标签: c

我想在下面的代码片段中知道为什么fscanf在执行过程中抛出-1,因此我得不到所需的输出。

#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main(){
    FILE *fp=NULL;
    char fname[200], cmd[200];
    int i=0,j=0;
    system("ls /tmp/*.msg -1rt > /tmp/xyz.txt");
    fp=fopen("/tmp/xyz.txt","r+");
    if(fp!=NULL){
        i=fscanf(fp,"%s",fname);
        while(i!=EOF){
            sleep(2);
            printf("Filename is:'%s'\n",fname); 
            sprintf(cmd, "rm -rf %s; touch /tmp/a_%d_new.msg",fname,j++);
            system(cmd);
            memset(fname, 0, 200);
            memset(cmd,0, 200);
            system("ls /tmp/*.msg -rt1 > /tmp/xyz.txt");
            i=fscanf(fp,"%s",fname);// fscanf will return error after some iterations
            printf("The I Value is: '%d'\n",i);
        }
    }
    if(fp!=NULL)
        fclose(fp);
    return 0;
}

重现步骤:

  1. 创建/tmp/xyz.txt文件(无数据)
  2. &GT; xyz.txt(如果有任何数据则将其设为空)
  3. rm -rf * .msg
  4. 触摸a.msg b.msg c.msg d.msg e.msg f.msg
  5. 在这里,我期待从while循环中优雅地退出。在当前情况下,由于fscanf功能,它没有发生。

1 个答案:

答案 0 :(得分:1)

在我看来,我第二次做了更好的解释,所以这是我更好的解释:

FILE是一个包含EOF标志和缓冲区的有状态设备。如果在缓冲时,到达文件末尾,那么它可能在缓冲区中排队,并且缓冲区不会被更新,直到它耗尽为止。本质上发生的是文件的一部分副本在内存中创建,当您对该文件进行外部更改时,内存中的副本将变得不同步。

解决方案是以某种方式同步缓冲区。如果更改文件位置,则标准库别无选择,只能更新缓存版本并重置EOF标志。您有两种选择:

    如果您打算以rewind的方式使用<,那么
  • fgetpos是有道理的,因为您每次循环都会覆盖文件,因此您需要从头开始阅读文件。
  • fscanf,后跟fsetpos,后跟<<只有在您打算使用<而不是<<时才有意义,因为{{1}连接到文件的末尾,因此当fscanf失败时,您将能够在更新文件之后选择停止的地方。

在我的第一个回答中,我还提出了一个关于你选择的设计的问题。其中的要点是,无论您做出哪种选择,fscanf通常都不应产生EOF值,除非您的system调用之一无法创建文件。我想你已经根据我们下面的对话聚集了这个。不幸的是,我不能提出任何建议,除非你对你的计划应该解决的问题给出一个更广泛的概述......我只能说,while(i!=EOF)并没有做出很多建议。感。

话虽如此,C代码调用system是不寻常的(有点浪费,可能是错误和不安全的)...再次,我需要知道你的程序预期会出现什么问题。解决提出更好的建议。