C++ 使用std::istream::peek()是否总是安全的?
我通常教我的学生处理文件输入的安全方法是:C++ 使用std::istream::peek()是否总是安全的?,c++,istream,C++,Istream,我通常教我的学生处理文件输入的安全方法是: while (true) { // Try to read if (/* failure check */) { break; } // Use what you read } 这使我和许多人从古典主义和大多数错误中解脱出来: while (!is.eof()) { // Try to read // Use what you read } 但人们确实喜欢这种形式的循环,因此在学生代码
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
}
while(is.peek()!=EOF){/is.peek()!=EOF
告诉您输入流中是否还有字符,但它不会告诉您下次读取是否成功:
while (is.peek()!=EOF) {
int a;
is >> a;
// Still need to test `is` to verify that the read succeeded
}
是>>一个
可能会由于多种原因而失败,例如,输入可能实际上不是一个数字
因此,如果你可以这样做的话,这是没有意义的
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`
}
或者您的第一个示例,在这种情况下,循环中的是.peek()!=EOF
,将变得多余
这是假设您希望循环在每次失败时退出,遵循您的第一个代码示例,而不仅仅是在文件末尾。或for(int a;is>>a;)
好的,这是很清楚的。因此,如果我假设读取失败的唯一原因是到达文件末尾(一个非常强烈和慷慨的假设),这个想法是正确的,对吗?即使以后有人玩std::istream::unget()
?@CostantinoGrana你确定这是一个很好的假设吗?例如,如果输入的末尾有空格,那么peek()也可以
将不会返回EOF,尽管所有格式化读取都将失败。我不确定您对unget()
的想法,但我认为unget()
可能会更改peek()
将EOF返回为不返回EOF。@胡桃木不,我确信这不是一个好的假设。但是在考试期间,你有时会向学生保证文件格式正确,因此他们不需要做所有检查。大多数时候,我们处理的是二进制格式,这让你完全不用担心空白(因为数据都是有意义的。)我想到了unget()
的东西,因为我曾经观察到(我相信是在Windows上),通过查看4096缓冲区限制,取消设置上一个字节(上一个缓冲区的最后一个字节)失败。但我可能错了。这就是我的疑问:我遗漏了一些已知的东西。@CostantinoGrana您可能希望在您的问题中澄清这些问题,以便其他人可以添加答案。老实说,我认为我对streams库的内部结构了解不够,无法回答这个问题。您可能想看看第4个条件只是有点le更好。通常使用read函数本身控制读取总是更好的,例如while(std::cin>>var){/*handle var*/}
或while(getline(fp,str)){/*handle string*/}
等等。。。