博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++中cin对象的clear方法和sync方法的暧昧关系

Posted on 2011-05-24 19:56  单鱼游弋  阅读(3804)  评论(0编辑  收藏  举报

话说刚才写求最大公约数的代码时,为了提高可靠性,加入了IO错误判断,可测试结果让人不解,先看修改前的部分代码:

int a = 0, b = 0;
cout
<< "Please input two number to computing they GCD: ";


while (!(cin >> a >> b))
{
cin.clear();
// 将流中的所有状态值都重设为有效值
cout << "Input Error !" << endl;
cout
<< "Input againt: " << endl;
}

// gcd 即 Greatest Common Divisor,最大公约数.
cout << "The GCD is " << gcd(a, b) << endl;

按理(从《C++ Primer》看来的)说,输入错误时,进入了循环体,接着调用 clear 方法重设状态值,然后 cin 流对象就处于正常状态了,我们就可以重新输入两个数值以求最大公约数了。可事实是,进入循环体后,再也出不来了,一个劲儿地循环。

我调试呀调试,发现问题可能出在 clear 方法上,可是《C++ Primer》也是这么用的呀!好吧,这是我的错,我得先检讨一下再继续往下讲。为了赶进度,我在很短的时间里把《C++ Primer》看了一遍,可这只是粗略看一遍,书上的代码基本上就没有上机实践过,我错了,原谅我吧。

经过一番百度,发现原来是把 clear 的老情人 sync 给丢了。俗话说的好,男女搭配,干活不累。没了 sync,clear 自然就整天魂不守舍地徘徊不前,等待梦中情人的出现。好了,有请 sync 先生出场:

while (!(cin >> a >> b))
{
cin.sync();     // 清除输入缓冲区中的数据流,功能与 fflush(stdin) 相同.
cin.clear();    // 将流中的所有状态值都重设为有效值.
cout << "Input Error !" << endl;
cout
<< "Input againt: " << endl;
}

 恭喜 clear 女士脱离光棍行列,终于可以让我们继续输入数值了。

分析一下,当我们输入了错误的数值后,cin 对象处于错误状态,代码进入循环体,接着我们调用 clear 方法重设了 cin 对象的状态。此时,cin 对象已经处于正确状态了,但是有一点需要注意,这些状态只是用来告诉别人,我 cin 已经没有问题了。当然啦,神经病自己都会说自己没病,有病不是说句话就能好的,有病还得治。打从 cin 里塞进了垃圾数据之后,这些垃圾就没清除掉。所以得让 sync 把垃圾数据给清除掉,清除之后才可以再放有用的东西。OK,垃圾也清除了,状态也正常了,活可以继续干了。

PS: 想不想知道 clear 为什么是女性?