我通常教我的学生处理文件输入的安全方法是:

while (true) {
    // Try to read
    if (/* failure check */) {
        break;
    }
    // Use what you read
}

这使我和许多人免于经典和大部分时间错误:

while (!is.eof()) {
    // Try to read
    // Use what you read
}

但是人们真的很喜欢这种形式的循环,因此在学生代码中看到这种形式变得很常见:

while (is.peek()!=EOF) { // <-- I know this is not C++ style, but this is how it is usually written
    // Try to read
    // Use what you read
}

现在的问题是:这段代码有问题吗? 是否存在某些情况无法完全按预期工作的极端情况? 好的,这是两个问题。

编辑其他详细信息:在考试期间,您有时会向学生保证文件的格式正确,因此他们无需进行所有检查,只需验证是否有更多数据。 大多数时候我们处理二进制格式,这让你完全不用担心空格(因为数据都是有意义的)。

虽然接受的答案是完全清楚和正确的,但我仍然希望有人尝试评论peek()unget()的联合行为。

我想到了unget()东西,因为我曾经观察到(我相信它是在 Windows 上)通过查看 4096 内部缓冲区限制(如此有效地导致加载新缓冲区),取消获取前一个字节(最后一个前一个缓冲区)失败。 但我可能是错的。 所以这是我的另一个疑问:我错过了一些已知的东西,它可能在标准或某些库实现中得到了很好的编码。

#1楼 票数:8 已采纳

is.peek()!=EOF告诉您输入流中是否还有字符,但它不会告诉您下一次读取是否会成功:

while (is.peek()!=EOF) {
    int a;
    is >> a;
    // Still need to test `is` to verify that the read succeeded
}

is >> a可能由于多种原因而失败,例如输入实际上可能不是数字。

所以如果你可以这样做,这没有意义

int a;
while (is >> a) { // reads until failure of any kind
    // use `a`
}

或者,也许更好:

for (int a; is >> a;) { // reads until failure of any kind
    // use `a`
}

或者您的第一个示例,在这种情况下, is.peek()!=EOF将变得多余。

这是假设您希望循环在每次失败时退出,遵循您的第一个代码示例,而不仅仅是在文件结束时。

  ask by Costantino Grana translate from so

未解决问题?本站智能推荐:

2回复

不应该istream::peek()总是返回你刚刚putback()?

直观地说,从C ++规范来看,它看起来好像istream::putback( c )应该总是安排输入缓冲区,以便下一次调用istream::peek()应该读取字符c 。 这不正确吗? 我问,因为随Xcode 4.6发布的最新版本的libc ++似乎并未在所有情况下强制执行此行为 - 特别是
1回复

如何正确使用std::istream

我要执行以下操作: 编译器抱怨: 我需要做些什么才能使这项工作? [编辑] 请注意: operator>>给出格式化的输出-它丢失空白字符(制表符,换行符等)。 要访问所有字符,您需要使用get() 。
2回复

使用std::istream运行功能

我正在尝试在函数中输入一个值,如下所示: 当我尝试运行它时: 我收到一个错误:.. \\ working.cpp:17:14:错误:类型'int'.. \\ working.cpp类型的表达式对'std :: istream&{aka std :: basic_istream&}'引用的
3回复

使用std::unique_ptr和std::istream吗?

我正在用c ++编写程序,可以从文件(作为命令行arg传递给它),std :: cin或std :: istringstream接收输入。 它工作正常,并使用std :: istream *管理。 有人告诉我,这很糟糕,处理原始指针,所以我决定将其包装在std :: unique_ptr(即
1回复

使用istream::peek()将下一个值与当前值进行比较

当下一个值为50时,为什么我的peek()条件没有返回FALSE? 当我的代码从文件中读入40并比较50是否小于40时,它返回TRUE。这显然是错误的,并按照子文件中数字的显示顺序创建了一个错误。 我输入了一个临时int告诉我fin_dataFile.peek()返回了什么,我一直保持3
1回复

我如何使用std::istream读取bool值

我正在尝试读取不同格式的csv和json。 一次布尔值由字符串“ 1”或“ 0”给出,另一次布尔值由字符串“ true”或“ false”给出。 现在,我使用统一的模板函数将该字符串转换为bool。 但是std :: istream无法同时读取两种bool格式。 如果设置了标志std :
1回复

如何使用libjpeg从std::istream中读取JPEG?

libjpeg可以从FILE*或缓冲区读取JPEG数据。 我的数据来自std::istream 。 我可以将整个std::istream读入缓冲区以与libjpeg一起使用,但如果可能的话,我宁愿直接从std::istream读取libjpeg。 如何才能做到这一点?
1回复

istream::peek好奇行为wrt。EOF

我刚刚在C ++中遇到了一个奇怪的情况。 我正在做类似的事情: 现在我很好奇为什么peek设置了eof位; 我觉得这很不直观。 它应该只是偷看实际上没有消耗任何东西,并且不应该更改流状态。 另外,为什么后来unget却不起作用? 当good()为false或类似的东西时,该标准是否