fscanf:如果不返回 EOF,是否可能出现错误或 EOF?
fscanf: is error or EOF possible without EOF returned?
我有一个C++程序,它读取一个文件,我希望该文件有一堆相同格式的记录。如果我遇到意外情况,我想停止阅读,无论这意味着格式错误的记录还是某些输入失败,我想区分这些不同的条件。
我已经看到了这个答案并查看了fscanf()
文档,我不确定fscanf()
是否可以在不返回 EOF 的情况下指示错误或 EOF。根据我对这两个链接的理解,即使fscanf()
返回 0 或更大的值,也可能发生错误或 EOF,因此无论fscanf()
返回什么值,我都必须调用ferror()
和feof()
。我似乎找不到 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 方面似乎略有不同。
如果不返回 EOF,是否可能出现错误或 EOF?
是的,它是。您还可以获得介于 0 和 3 之间的返回值。cplusplus.com 是出了名的草率。让我们来看看 cppreference.com 的页面。
返回值:成功分配的接收参数数(如果在分配第一个接收参数之前发生匹配失败,则可能为零),如果在分配第一个接收参数之前发生输入失败,则为 EOF。
有几种不同的方案。让我们将其分解为案例:
如果它已成功分配给第一个接收参数,那么您将获得一个正值,这是有保证的。假设它被分配给两个变量,然后命中 EOF。它将返回
2
,feof()
将返回 true。否则,如果它没有分配给第一个接收参数并得到匹配失败,它将返回
0
.什么是匹配失败?这时它匹配像%d
这样的说明符并且没有得到有效的整数。如果输入foobar
则%d
将无法匹配。或者,不太常见的是,当它正在寻找一个文字字符但没有看到它时。例如,如果您的格式字符串希望每个数字都括在括号 (
"[%d] [%d] [%d] [%d]"
) 中,那么如果输入不是以[
开头,它将返回0
。否则,如果它没有分配给第一个接收参数并得到 EOF 或读取错误,它将返回
EOF
。请注意,读取错误不同于匹配错误。读取错误是指操作系统返回尝试从磁盘读取的 I/O 错误。返回值
EOF
表示文件结束或 I/O 错误。如果你不在乎区别,你可以放弃你的循环并继续程序。但是,如果您想在ferror()
上打印错误消息并将feof()
视为成功,则检查ret
是不够的;您必须调用其中一个或两个函数。是否愿意,这取决于你。
假设我希望我的文件有一堆包含 4 个值的记录。下面的代码是否可以正确处理文件末尾和输入错误条件?
是的。对我来说看起来不错。
对于它的价值,我建议不要使用scanf()
和fscanf()
.它们很复杂,使得处理输入错误比必要的更加困难。这个问题是一个很好的示范。最好使用fgets()
读取整行并sscanf()
解析它。这样,如果有错误的输入,您就不会有部分行坐在那里干扰未来的读取。
我发现用例子解释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);
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何确定我已使用非编码文件到达 EOF?
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- "错误 C0000:语法错误,令牌"<EOF>"处出现意外$end,并且不确定
- fscanf:如果不返回 EOF,是否可能出现错误或 EOF?
- .EOF 在读取文件时导致 Seg 错误:FIXXED
- 输入文件读取错误的值,eof 控制循环不会结束
- 文件设置正确,但eof()和peek()意外地从新流返回了错误的值
- C++的 istream::eof() 的不一致是规范中的错误还是实现中的错误?
- ifstream::eof在if语句中时抛出类型错误
- 提升 asio、shared_from_this() 错误 R6010 和 async_read() eof
- 通过C++程序中EOF(CTRL+D)字符上的错误代码提供用户反馈
- 'Pre-mature EOF'和'Bad Character'错误
- 为什么我得到一个错误说eof不是fstream的类类型
- 在使用eof()的while循环中出现一个错误关闭