我有一个C ++程序,该程序从一个文件中读取,我希望它有一堆格式相同的记录。如果遇到意外情况(表示记录格式错误或某些输入失败),我想停止阅读,我想区分这些不同的情况。
我已经看过this answer并看了fscanf()
documentation,但不确定fscanf()
是否可以指示错误或EOF而不会返回EOF。根据我对这两个链接的理解,即使fscanf()
返回0或更大的值,也可能会发生错误或发生EOF,因此无论如何,我都必须调用ferror()
和feof()
值fscanf()
返回。我似乎找不到EOF的返回值对调用者有什么用。
说我希望我的文件中有一堆带有4个值的记录。下面的代码能正确处理文件结尾和输入错误的情况吗?
int ret;
int field1;
int field2;
int field3;
int field4;
while ((ret = fscanf(pFile, "%d %d %d %d", &field1, &field2, &field3,
&field4)) == 4) {
// do whatever with fields
}
if (ferror(fp)) {
// some input error occurred
} else if (feof(fp)) {
// end of file occurred
} else {
assert(ret != EOF);
// encountered record that didn't match expected format
}
更新:因此,我将添加cppreference中的文档,因为它在描述什么条件不再导致EOF返回方面似乎略有不同。
答案 0 :(得分:3)
如果没有返回EOF,是否可能发生错误或EOF?
是的。您也可能会得到0到3之间的返回值。cplusplus.com有点草率。让我们来看一下cppreference.com's page。
返回值:成功分配的接收参数的数量(如果在分配第一个接收参数之前发生匹配失败,则为零);如果在分配第一个接收参数之前发生输入失败,则为EOF。 / em>
有两种不同的情况。让我们将其分解为几种情况:
如果已成功将其分配给第一个接收参数,那么您将获得肯定的值。假设它已分配给两个变量,然后达到EOF。它将返回2
,而feof()
将返回true。
否则,如果未将其分配给第一个接收参数并获得匹配失败,则它将返回0
。什么是匹配失败?那是当它与%d
之类的说明符匹配并且没有得到有效的整数时。如果输入为foobar
,则%d
将不匹配。
或更不常见的是,它正在寻找文字字符而看不到它。例如,如果您的格式字符串希望每个数字都用括号("[%d] [%d] [%d] [%d]"
括起来,那么如果输入的内容不是以0
开头,它将返回[
。
否则,如果未将其分配给第一个接收参数,并且得到EOF或读取错误,它将返回EOF
。请注意, read 错误与 matching 错误不同。读取错误是指操作系统返回尝试从磁盘读取的I / O错误。
返回值EOF
表示文件结束或I / O错误。如果您不关心区别,则可以放弃循环并继续执行该程序。但是,如果您想在ferror()
上打印错误消息并将feof()
视为成功,则检查ret
是不够的;您必须调用这些功能之一或全部。是否执行此操作取决于您。
说我希望我的文件中有一堆带有4个值的记录。下面的代码能正确处理文件结尾和输入错误的情况吗?
是的。对我来说很好。
出于价值考虑,建议不要使用scanf()
和fscanf()
。它们很复杂,使处理输入错误的难度大大超出了必要。这个问题是一个很好的示范。最好使用fgets()
读取整行,然后使用sscanf()
进行解析。这样一来,如果输入的内容不好,您就不会在将来的阅读工作中碰到部分麻烦了。
答案 1 :(得分:0)
我发现更容易用示例解释fscanf
函数系列的返回值。
// The string contains valid data given the format specifier.
// Expect ret to be 1.
int ret = sscanf("10", "%d", &n);
// The string contains data but not what the user expects to see.
// Expect ret to be 0.
int ret = sscanf("abcd", "%d", &n);
// The string contains no data .
// Expect ret to be EOF.
int ret = sscanf("", "%d", &n);
在所有这些情况下,如果您有前导空格,则可以期待相同的行为。
// Expect ret to be 1.
int ret = sscanf(" 10", "%d", &n);
// Expect ret to be 0.
int ret = sscanf(" abcd", "%d", &n);
// Expect ret to be EOF.
int ret = sscanf(" ", "%d", &n);