提问人:Mehdi Zayene 提问时间:3/19/2020 最后编辑:RobertS supports Monica CellioMehdi Zayene 更新时间:3/21/2020 访问量:577
fscanf - 如何知道EOF是否意味着文件结束或读取/另一个错误?
fscanf - How to know if EOF means end of file or reading/another error?
问:
我有一个关于 C 语言的 I/O 的问题,我怎样才能知道我的文件的讲座是否已经结束,或者数据是否无法读取(或有问题),因为在这两种情况下,fscanf 返回 EOF ?
答:
1赞
anastaciu
3/20/2020
#1
根据 fscanf()
返回值:
§ 7.21.6.2 - 16 - 如果在第一次转换(如果有)完成之前发生输入失败,则该函数将返回宏的值。否则,该函数将返回分配的输入项数,如果早期匹配失败,该数目可能少于提供的数量,甚至为零。
fscanf
EOF
EOF
是一个值为 的宏,它本身无法区分它发生的原因。-1
为了区分这一点,§ 7.21.6.2 - 19 建议将 feof
() 用于文件末尾,使用 ferror()
用于 I/O 错误:
示例 3要重复接受数量、计量单位和物料名称:
stdin
#include<stdio.h> /*...*/ int count; floatquant; charunits[21], item[21]; do { count = fscanf(stdin, "%f%20sof%20s", &quant, units, item); fscanf(stdin,"%*[^\n]"); } while(!feof(stdin) && !ferror(stdin));
在读取格式化输入时,我通常的方法是检查输入的值。对于 2 个整数的示例输入,您可以执行如下操作:
int a, b;
FILE* file;
//open file to read
while(fscanf(file, "%d %d", &a, &b) == 2){ //read each 2 integers in the file, stop when condition fails, i.e. there are nothing else to read or the read input is not an integer
//...handle inputs
}
这种读取是安全的,可以解决所有故障情况,因为它适用于错误的输入和“文件末尾”。
评论
0赞
Eric Postpischil
3/20/2020
这并不能回答如何区分文件末尾和 I/O 错误的问题。
1赞
anastaciu
3/20/2020
@EricPostpischil这个 DV 是完全不需要的,但我的回答通过奖励信息完全解决了这个问题。
0赞
Eric Postpischil
3/20/2020
OP 希望区分文件末尾和 I/O 错误。在这两种情况下,返回 .问题是要求一种方法来区分由于到达文件末尾而返回的和由于发生 I/O 错误(例如网络连接失败、文件已关闭、发生某些设备错误等)而返回的。此答案不包含任何提供该信息的内容。fscanf
EOF
EOF
EOF
2赞
chqrlie
3/20/2020
另一个不可见块引用的例子。C标准的引文曾经清晰而优雅地脱颖而出。支持推翻这一决定...看到 meta.stackoverflow.com/questions/394644/...
0赞
anastaciu
3/20/2020
@EricPostpischil,我考虑了你的批评者并认识到它的优点,我编辑了我的答案。
3赞
RobertS supports Monica Cellio
3/20/2020
#2
不要只依赖 的返回值,在调用 feof(
) 和 ferror() 之后,还要依赖 feof() 和 ferror()
的返回值:fscanf()
fscanf()
FILE* file;
if((file == fopen("file.txt","r")) == NULL)
{
fprintf(stderr, "File could not be opened!");
return EXIT_FAILURE;
}
char buf;
/******************************************************************************/
while(fscanf(file,"%c",buf) == 1) { // checks if an error was happen, else
// iterate to catching characters.
/* handling of read character */
}
if(ferror(file)) // checks if an I/O error occurred.
{
// I/O error handling
fprintf(stderr,"Input/Output error at reading file!");
clearerr(file);
// Further actions
}
else if(feof(file)) // checks if the end of the file is reached.
{
// end of file handling
fprintf(stderr,"Reached End of File!");
clearerr(file);
// Further actions
}
/******************************************************************************/
if(fclose(file) != 0)
{
fprintf(stderr, "File could not be closed properly!");
return EXIT_FAILURE;
}
评论
0赞
Mehdi Zayene
3/20/2020
非常感谢您的帮助!我仍然有一个问题,当我 se for ex 时: 然后我开始使用 feof 和 ferror 处理我的错误,它似乎工作得很好,但是当没有错误但输入文件不包含 X 元素时,我也想抛出一个错误,然后我尝试使用包含 X-1 元素的文件, 什么也没发生......所以我在这里的两个问题,如果我们扫描的元素多于文件中的可用元素,ferror 会启动错误吗?如果不是,为什么我的解决方案不起作用..:/if (fscanf("%d %d %d..", &a , &b ...) != X )
0赞
Mehdi Zayene
3/20/2020
你好!现已修复!在检查文件末尾之前,我必须储存 fscanf 在变量中返回的内容,以检查它是否在我的示例中小于 X!
0赞
RobertS supports Monica Cellio
3/20/2020
@MehdiZayene 您还可以在该案例之后使用另一个条件来显式处理成功分配第一个接收参数后发生的失败,例如: 因为所有其他条件都不匹配,这是唯一可能保留的问题。else if(feof(file){}
else if(feof(file){} else{ /* handle error if not all conversions could have been executed successfully */}
0赞
RobertS supports Monica Cellio
3/20/2020
@MehdiZayene我认为,如果在第一次分配之前没有到达文件的末尾并且分配成功,即使它已经到达文件末尾也不会返回。考虑这句话:“返回值 - 成功分配的接收参数数(如果在分配第一个接收参数之前发生匹配失败,则可能为零),或者如果在分配第一个接收参数之前发生输入失败,则为 EOF en.cppreference.com/w/c/io/fscanf。fscanf()
EOF
1赞
Mehdi Zayene
3/21/2020
当然!完成 :)
评论
feof
ferror