使用fscanf直到EOF而不使用getc

时间:2015-04-11 20:51:16

标签: c eof scanf

我有一个由2个字节序列组成的文本文件,我必须将它存储在一个数组中。

我已宣布FILE *ptr

如何在不使用方法的情况下循环直到EOF:

while(c = getc() != EOF)
{
// do something 
}

我想实现(PSEUDOCODE)的一些东西:

while (ptr is not pointing to the end of the file)
{
fscanf(...)  // I will read in the bytes etc.
}

getc()方法对我来说效果不好,因为我一次只读取2个字节的块。

2 个答案:

答案 0 :(得分:0)

您可以使用fread一次读取多个字节。 fread返回它能够阅读的项目数。

例如,要读取2字节块,您可以使用:

while ((fread(target, 2, 1, ptr) == 1) {
    /* ... */
}

此处2是每个“项目”中的字节数,1是您希望在每次调用时读取的“项目”数。

通常,您不应使用feof()来控制何时终止输入循环。使用您正在使用的任何输入例程返回的值。不同的输入功能因其提供的信息而异;你必须阅读你正在使用的文档。

请注意,这会将行尾作为单个'\n'字符处理。你说你正在阅读一个文本文件;目前尚不清楚如何处理行结尾。如果文件具有奇数个字符,您还应该决定要执行的操作。

另一种选择是在循环中调用getc()两次,同时检查其结果。

答案 1 :(得分:0)

告诉您何时到达文件末尾的唯一方法是当您尝试读取它时,读取失败。 (是的,有一个feof()函数,但它只会在之后返回true ,你试图读取文件的末尾。)

这意味着,如果您要使用fscanf()来阅读您的输入,那么您需要检查fscanf()本身的返回值。

具体来说,fscanf()返回已成功读取的项目数,或EOF(如果输入在任何内容之前结束,则为负值,通常为-1)。因此,您的输入循环可能如下所示:

while (1) {
    /* ... */

    int n = fscanf(ptr, "...", ...);

    if (n == EOF && !ferror(ptr)) {
        /* we've reached the end of the input; stop the loop */
        break;
    } else if (n < items_requested) {
        if (ferror(ptr)) perror("Error reading input file");
        else fprintf(stderr, "Parse error or unexpected end of input!\n");
        exit(1);  /* or do whatever you want to handle the error */
    }

    /* ... */
}

尽管如此,也可能有其他选择。例如,如果您的输入结构为行(很多文本输入),you may be better off逐行读取输入fgets(),然后解析行,例如与sscanf()

另外,从技术上讲, 是一种使用ungetc()在输入中查找前一个字节的方法。也就是说,你可以做这样的事情:

int c;
while ((c = getc(ptr)) != EOF) {
    ungetc(c, ptr);
    /* ... now read and parse the input ... */
}

问题是这只会检查你在EOF之前可以读取一个多个字节;它没有,并且无法,实际检查您的fscanf()电话是否有足够的数据来匹配所有请求的项目。因此,您仍然需要检查fscanf()的返回值 - 如果您要这样做,您也可以将其用于EOF检测。