请高手剖析下IO

chenshimia 2011-05-14 12:28:23
#include <iostream>
#include <string>

using namespace std;
int main()
{
int ival;
while( cin >> ival, !cin.eof())
{
if(cin.bad())
throw runtime_error("IO stream corrupted");
if(cin.fail())
{
cerr << "bad data,try again\n";
cin.clear(istream::failbit);
continue;
}
cout<<ival<<endl;
}
return 0;
}

为什么当cin.bad()执行时,循环就变成了死循环了。
这是c++ primer 中的一道例题
...全文
118 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenshimia 2011-05-14
  • 打赏
  • 举报
回复
谢谢各位高手,我涨见识了!
qq120848369 2011-05-14
  • 打赏
  • 举报
回复
你输入2.2就知道问题了,这个代码无法正确处理错误输入,因为错误数据不会从缓冲区中取走,
所以导致一直重复读取'.'造成了死循环。

#include <iostream>
#include <string>

using namespace std;
int main()
{
int ival;
while( cin >> ival, !cin.eof())
{
if(cin.bad())
throw runtime_error("IO stream corrupted");

if(cin.fail())
{
cerr << "bad data,try again\n";

cin.clear(); //这样
cin.ignore(1); //并且掠过这个非法字节

continue;
}
cout<<ival<<endl;
}
return 0;
}


另外,直接调用clear即可,错误可能不仅仅是failbit。
jilonglv 2011-05-14
  • 打赏
  • 举报
回复
int ival;
while(true)
{
if(!( cin >> ival))
//读入失败,则返回0
{
if(cin.bad())
throw runtime_error("IO stream corrupted");
if(cin.fail())
{
cerr << "bad data,try again\n";
cin.clear();//首先你要将状态为清空
while(cin.peek()!='\n')//peek()是探测下一个字符是否为空,如果不是,将缓冲区的内容忽略掉
cin.ignore();
continue;
}
}
else
cout<<ival<<endl;

}

已成功编译通过,并执行成功。。。。。

楼主那个很容易误导,分读入成功和失败两种情况!
读入失败的话,则判断是哪种失败!
pcliuguangtao 2011-05-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 fukang258369 的回复:]

你是这样:C/C++ code
if(cin.fail())
{
cerr << "bad data,try again\n";
cin.clear(istream::failbit);
continue;
}



查了一下应该这样那个写:C/C++ code
if(cin.fail())
{
cerr << "bad data,try again\n"……
[/Quote]
很明显,当你输入“2.2”的时候,进行cin>>ival;
但是ival是int类型的,这样ival实际上的值为2;这样就把“.2”给留在cin流的stringbuf里面了,同时进行while循环,又cin>>ival同样无法赋给int型的ival,虽然if(cin.fail())可以捕获这个错误,但是这时候的流错误标记没有去掉,所以无法继续从流中extract抽取数据,产生死循环。
要去掉“.2”很简单可以直接使用一个
char temp;
cin>>temp吃掉“.”就可以,或者使用cin.ignore(1)
可以参看:
http://www.cplusplus.com/reference/iostream/istream/
pcliuguangtao 2011-05-14
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qq120848369 的回复:]

C/C++ code
你输入2.2就知道问题了,这个代码无法正确处理错误输入,因为错误数据不会从缓冲区中取走,
所以导致一直重复读取'.'造成了死循环。

C/C++ code
#include <iostream>
#include <string>

using namespace std;
int main()
{
int ival;
while( cin >> iv……
[/Quote]

正解,顶一下
liutengfeigo 2011-05-14
  • 打赏
  • 举报
回复
<<标准C++输入输出流与本地化>>
木有看过.
chenshimia 2011-05-14
  • 打赏
  • 举报
回复
本人愚钝,依旧不明白
fukang258369 2011-05-14
  • 打赏
  • 举报
回复
你是这样:
if(cin.fail())
{
cerr << "bad data,try again\n";
cin.clear(istream::failbit);
continue;
}


查了一下应该这样那个写:
if(cin.fail())
{
cerr << "bad data,try again\n";
cin.clear(istream::goodbit);//istream::goodbit可以省略,,默认就是goodbt...
cin.ignore(1);//为什么要这一句,我也不是很清楚。等高手吧。或者再查查。
continue;
}
qq120848369 2011-05-14
  • 打赏
  • 举报
回复
远离VC6,谢谢。
飞天御剑流 2011-05-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 chenshimia 的回复:]
等高手ing
[/Quote]

建议你看一本书<<标准C++输入输出流与本地化>>
chenshimia 2011-05-14
  • 打赏
  • 举报
回复
等高手ing
chenshimia 2011-05-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 yfkiss 的回复:]
首先,我们看下:
cin >> ival, !cin.eof()
这是一个逗号操作符,一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式;整个表达式的结果是逗号右边表达式的值。

cin是STL库提供的一个iostream实例
cin.eof():
Return Value
true if eofbit stream's state flag is set (wh……
[/Quote]
问题是,当输入合法的时候就可以再输入,为什么不合法的时候就不能再输入呢?
chenshimia 2011-05-14
  • 打赏
  • 举报
回复
输入ctrl+z 两次才跳出循环,不知道为什么。

想问下2L 的高手,为什么要cin.ignore(1); //并且掠过这个非法字节
要怎么样才能使数据从缓冲区中取走?


yfk 2011-05-14
  • 打赏
  • 举报
回复
首先,我们看下:
cin >> ival, !cin.eof()
这是一个逗号操作符,一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式;整个表达式的结果是逗号右边表达式的值。

cin是STL库提供的一个iostream实例
cin.eof():
Return Value
true if eofbit stream's state flag is set (which signals that the End-of-File has been reached).
false otherwise.

cin.bad()
Return Value
true if badbit stream's state flag is set.
false otherwise.

循环变成了死循环,这个和cin.bad()没有关系,只是因为一直是有效输入,cin.eof()返回true,所以循环一直继续。

LZ尝试输入ctrl+z
观察程序

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧