std::cin 与 ctrl+z 配合使用时遇到的问题

来源:互联网 发布:origin图片导出数据 编辑:程序博客网 时间:2024/04/30 12:51

《C++ Primer》第四版第一章1.4.4节,早早的教了我们如何利用cin读入未知数目的输入。

关键在于利用失败的cin>>返回0,一种触发失败的方式就是主动输入文件结束符,而Windows系统下输入文件结束符的方式,是按Ctrl + Z。


于是,实际使用中我碰到这样一个问题,请看以下代码:

#include <iostream>#include <vector>using std::cin;using std::cout;using std::endl;using std::vector;int main(){    vector<int> src;    cout<<"请输入整形数组:";    int temp;    while (cin>>temp)    {        src.push_back(temp);    }                               int target;    cout<<"请输入需查找数:";    cin>>target;}

这是一个二分查找程序的一部分,意图就不多解释了,可完整运行。

但是,你会发现运行结果有些意外,第二个cin>>target似乎完全不起作用,一旦ctrl+z结束第一个循环后,程序就直接结束了。


在网上搜索一些资料或者翻翻书,我们会发现,cin是维持着一系列状态标识位的,倘若发生错误,则状态位需要重置,否则无法继续正常使用。

所以,我们在第二个cin>>target前加一句:cin.clear()。

这样问题似乎就解决了。


请注意,问题才刚刚开始。

ctrl+z的输入方式也有讲究,前面说的没问题的情况,是假设你按正常次序输入了数组和结束符(例:1 空格 2 空格 3 空格 Enter Ctrl+Z Enter)。

要是输入(1 空格 2 空格 3 空格 Ctrl+Z Enter),会发生什么情况呢?你会发现之前的问题又出现了,cin>>target再次被无视!


网上关于此问题似乎有一些文章作出了解释:cin中Ctrl+Z无法结束的问题

很遗憾,它给出的现象及解释我都不认为和我遇到的问题相符。


于是我写了以下测试代码,来查看各时期cin的状态位。

#include <iostream>#include <vector>using std::cin;using std::cout;using std::endl;using std::vector;int main(){    vector<int> src;    cout<<"请输入整形数组:";    int temp;    while (cin>>temp)    {        src.push_back(temp);    }       cout<<"good: "<<cin.good()<<endl;    cout<<"eof: "<<cin.eof()<<endl;    cout<<"fail: "<<cin.fail()<<endl;    cout<<"bad: "<<cin.bad()<<endl;    cin.clear();    cout<<"good: "<<cin.good()<<endl;    cout<<"eof: "<<cin.eof()<<endl;    cout<<"fail: "<<cin.fail()<<endl;    cout<<"bad: "<<cin.bad()<<endl;    int target;    cout<<"请输入需查找数:";    cin>>target;}

这时候,正常输入数组,Enter,然后输入ctrl+z,再Enter,现象先是eof和fail被置1,然后重置状态后,一切正常。

假如ctrl+z粘连输入,就会发现eof并未被置1,仅fail=1,状态位的确被重置了,但cin就是无法继续正常使用。


这时候,我想了下,是不是ctrl+z作为非正常输入无法被解析产生fail,然后它一直停留在cin的数据缓冲区,持续产生fail?

于是我搜了下清cin缓冲区的方法,于是问题搞定了。

代码就不贴了,自己在cin.clear()后加上cin.sync()。


很让我困惑的是,假如不是我眼花的话,无论《C++ Primer》,还是《C++标准程序库自修教程与参考手册》,都完全没提及sync()清缓冲区这个重要的函数。蛋疼。

0 0
原创粉丝点击