1

我正在阅读一本关于 c 编程的书,但不理解显示的示例。或者更准确地说,我不明白为什么它会起作用,因为我认为它不应该。

代码很简单,它读取文本文件的内容并将其输出到输出区域。据我了解,我认为

 ch = fgetc(stream);

应该在while循环内,因为它一次只读取一个int?并且需要在当前 int 输出后读取下一个 int。好吧,事实证明这段代码确实可以正常工作,所以我希望有人可以向我解释我的谬误。谢谢!

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *stream;
    char filename[67];
    int ch;
    printf("Please enter the filename?\n");
    gets(filename);
    if((stream = fopen(filename, "r")) == NULL) {
        printf("Error opening the file\n");
        exit(1);
    }

    ch = fgetc(stream);
    while (!feof(stream)) {
        putchar(ch);
        ch = fgetc(stream);
    }

    fclose(stream);
}
4

8 回答 8

2

如果去掉fgetc外面while,像这样:

while (!feof(stream)) {
    putchar(ch);
    ch = fgetc(stream);
}

ch第一次putchar(ch)调用时将被取消初始化。

顺便说一句,不要使用gets,因为它可能会导致缓冲区溢出。使用fgetsgets_s代替。gets在 C11 中删除。

于 2013-07-15T08:22:27.350 回答
2

我认为您对 feof() 感到困惑:

文件:int feof ( FILE * stream );

检查是否设置了与流关联的文件结束指示符,如果设置,则返回一个不同于零的值。

指示符通常由尝试在文件结尾处或之后读取的流上的先前操作设置。

   ch = fgetc(stream);      <---"Read current symbol from file"
    while (!feof(stream)) { <---"Check EOF read/returned by last fgetc() call"
        putchar(ch);        <---"Output lasts read symbol, that was not EOF"
        ch = fgetc(stream); <---"Read next symbols from file"
    }
   <-- control reach here when EOF found   

一个更好的方法是编写你的循环,如:

while((ch = fgetc(stream))!= EOF){ <--" Read while EOF not found"
   putchar(ch);   <-- "inside loop print a symbol that is not EOF"
}

此外,请注意:int fgetc ( FILE * stream );

返回指定流的内部文件位置指示符当前指向的字符。然后内部文件位置指示器前进到下一个字符。

如果调用时流位于文件末尾,则函数返回 EOF并设置流的文件结尾指示符 (feof)。

如果发生读取错误,该函数返回 EOF并设置流的错误指示符 (ferror)。

于 2013-07-15T08:25:13.293 回答
2

您提供的代码有 'ch =fgetc(stream);' 在 While 循环之前以及 'ch = fgetc(stream);' 在循环体内。正如您正确陈述的那样,循环中的语句一次从流中检索一个是合乎逻辑的。

于 2013-07-15T08:29:38.127 回答
1

如您所见,它在内部和外部。外面的那个负责读取第一个字符(可能已经是文件的结尾,那么无论如何都不会输入while,也不会打印任何内容),然后它进入循环,放置字符并读取下一个字符。 . 只要读取的字符不是文件结尾,循环就会继续。

于 2013-07-15T08:21:08.837 回答
1

fgetc()读取一个char(byte)并返回那个字节,字节值的读取取决于读取指针在哪里可用。

一旦 fgetc() 成功读取一个字节,读取的文件指针将移动到下一个字节。因此,如果您读取文件,next byte它将成为输出,它将继续找到返回 EOF 的文件末尾。

于 2013-07-15T08:21:27.590 回答
1

这是因为 secondfgetc正在调用 upto while (!feof(stream))

于 2013-07-15T08:22:32.463 回答
1

实际上这部分在这里:

while (!feof(stream)) {
        putchar(ch);
        ch = fgetc(stream);
    }

非常不安全,您应该避免像那样检查 EOF(这里是为什么)。

您应该使用以下方式读取文件fgetc

int ch;
while ((ch = fgetc(stream)) != EOF) 
{
   printf("%c", ch)
}
于 2013-07-15T08:25:16.677 回答
1

这是非功能代码。文件中的最后一个字符永远不会输出。fgetc将读取最后一个字符,指针将位于文件末尾。因此,当检查while时,!feof将返回false,并且不会输出读取的字符。 feof不阻止文件结束后读取:因为空文件fgetc将在之前调用feof!除非在控制台处理中有一些好处,否则存在两个更好的选择: 使用 feof:

while (!feof(stream)) {
    ch=fgetc(stream);
    putchar(ch);
}

不使用feof- 因为在没有更多字符时fgetc返回:EOF

while ((ch=fgetc(stream))!=EOF) putchar(ch);
于 2013-07-15T08:46:39.910 回答