使用std::istream::peek()总是安全的吗
Is it always safe to use std::istream::peek()?
我通常教学生处理文件输入的安全方法是:
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内部缓冲区限制(如此有效地导致加载新的缓冲区(,取消设置前一个字节(前一个缓冲区的最后一个(失败了。但我可能错了。所以这是我额外的怀疑:我错过了一些已知的东西,这些东西可能在标准或一些库实现中编码得很好。
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
将变得多余。
这是假设您希望循环在每次失败时都退出,遵循您的第一个代码示例,而不仅仅是在文件末尾。
相关文章:
- 通过网络、跨平台传递std::变体是否安全
- 在std::thread中,joinable()然后join()线程安全吗
- 使用std::istream::peek()总是安全的吗
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- std::memmove在同一对象之间是否始终安全
- 从其存储的回调中删除 std::函数是否安全
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 我可以对 std::array 使用自定义分配器来获取安全加密密钥吗?
- 安全回调提供程序(SFINAE,std::正向和过载解析)
- 如果迭代器没有因插入而无效,则使用std::find和C::insert()是线程安全的
- std::weak_ptr<T>::锁定线程安全吗?
- std::shared_ptr::unique(),复制和线程安全
- 通过std::shared_ptr使用Rcpp和RcppParallel的线程安全函数指针
- 附加类型安全的子类std::string
- 我们如何使std::uniform_int_distribution加密安全
- 线程安全 std::map:锁定整个映射和单个值
- 通过引用返回共享对象是否安全"std::lock_guard<mutex>"?
- 线程安全std::cout的死锁
- 线程安全std::vector push_back和reserve
- 安全std::tr1::shared_ptr使用