我正在读一本关于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);
}
答案 0 :(得分:2)
我认为你因为feof()而感到困惑:
Doc:int feof ( FILE * stream );
检查与流关联的文件结束指示符是否为 set,返回一个不等于零的值。
此指标通常由流上的先前操作设置 尝试在文件结尾处读取或超过文件结尾。
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)。
答案 1 :(得分:1)
如你所见,它在内部和外部。外面的一个负责读取第一个字符(可能已经是文件的结尾,然后无论如何都不输入而没有打印),然后它进入循环,放置字符并读取下一个字符。只要读取的字符不是文件的结尾,循环就会继续。
答案 2 :(得分:1)
fgetc()
读取char(byte)
并返回该字节,字节值的读取取决于读指针的可用位置。
一旦fgetc()成功读取一个字节,读取文件指针就会移动到下一个字节。如果你读取文件,next byte
将是输出,它将继续向上找到文件的末尾它返回EOF。
答案 3 :(得分:1)
如果移除fgetc
外while
,请执行以下操作:
while (!feof(stream)) {
putchar(ch);
ch = fgetc(stream);
}
第一次调用ch
时, putchar(ch)
将被取消初始化。
顺便说一句,不要使用gets
,因为它可能会导致缓冲区溢出。请改用fgets
或gets_s
。在C11中删除了gets
。
答案 4 :(得分:1)
这是因为第二个fgetc
正在调用while (!feof(stream))
。
答案 5 :(得分:1)
实际上这部分在这里:
while (!feof(stream)) {
putchar(ch);
ch = fgetc(stream);
}
非常不安全,你应该避免像那样检查EOF(here为什么)。
使用fgetc
阅读文件的方式如下:
int ch;
while ((ch = fgetc(stream)) != EOF)
{
printf("%c", ch)
}
答案 6 :(得分:1)
您提供的代码有'ch = fgetc(stream);'在While循环之前也是 'ch = fgetc(stream);'在循环体内。 顺便说一下,循环中的语句在正确表示时一次从流中检索ch。
答案 7 :(得分: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);