C++的标准输入

来源:互联网 发布:淘宝客服外包怎么运营 编辑:程序博客网 时间:2024/06/05 02:34

从一个简单的问题谈起

昨天做题的时候,遇到一个输入是这样的

3 4aaaa aaaa aaaabbbbbbb bbbbccc cccccccc^D

第一行输入一个整数n,表示接下来句子的数量,和另外一个整数(这里没有作用,只是用来说明下面的一个情况),接下来就是n个句子,每个句子以回车结束。
我的想法是

int ij;cin >> i >> j;while(i--){ string s; getline(cin, s);}

可是,结果是我第一次调用getline返回的是“”(空字符串)。这是为什么呢?

原因是cin有它的缓冲区,当我们在标准输入输入回车之后,会将我们的输入放到它的缓冲区,然后cin就开始在缓冲区读。 cin的>>操作符,默认是以空格,制表符作为分隔符的。

当我们输入 3 4换行之后,输入缓冲区读到的内容是3 4\n,cin >> 操作符将3 4读取之后赋给i,j,缓冲区里面剩下\n,下一个getline来读的时候就返回空字符串了。

一个解决方法,用cin.get()吸收掉缓冲区的\n字符。

int ij;cin >> i >> j;cin.get();while(i--){ string s; getline(cin, s);}

其实,我之前一直认为cin >> 操作符是以空格,制表符,回车作为分隔符的,对于代码cin >> i >>j;,我曾经这么输入。

23

这样i,j读到的也是2,3,所以我就以为cin >> 也可以以回车作为分隔符。今天我查资料才发现,cin >> j的时候,缓冲区里面是有\n3的,只是它为j赋值的时候忽略掉\n而已。

cin的状态

在找这个问题的原因的时候我发现一个更有意思的事情。

cin.clear()

int a;char  b;int ret = 0;cout << "input a:" << endl;cin >> a;cout << "a:" << a << endl;cout << "input b:" << endl;cin >> b;cout << "b:" << b << endl;

这行代码如果输入的不是数字而是字符的话,会导致一个死循环,因为第一次赋值给a的时候,赋值失败了,cin就会给自己设一个状态iostate state = badbit这就会导致cin不能正常工作,cin >> b也不能正常工作了。
下面是我的输入:

➜  stl git:(master) ✗ g++ input.cpp -o input➜  stl git:(master) ✗ ./inputinput a:asdfa:0input b:b:

这里我给a赋了个字符,然后cin >> b就直接返回了,没有再给机会输入b,也没有办法让b正确赋值。

int a;char  b;int ret = 0;cout << "input a:" << endl;cin >> a;cout << "a:" << a << endl;cin.clear();  //加了这一句cout << "input b:" << endl;cin >> b;cout << "b:" << b << endl;

在cin错误之后,将状态设置回iostate state = goodbit,这样我的b就能从缓冲区读取我之前的输入。我的输入

➜  stl git:(master) ✗ g++ input.cpp -o input➜  stl git:(master) ✗ ./inputinput a:asdfa:0input b:b:a      

cin.ignore() and cin.sync()

网上有人说这两个语句都是用来清空输入缓冲区,也就是说回到我第一个谈到的问题,我输入数字之后回车,\n存放在输入缓冲区的最开始,那我就可以通过这两个语句来将输入缓冲区清空,然后再读取其他输入。

cin.ignore()是丢弃输入缓冲区的一个字符,istream& ignore (streamsize n = 1, int delim = EOF);,还可以丢弃n个字符,或抛弃到以delim结尾字符。 这是推荐使用的清空缓冲区的方法。

cin.sync()这个的实际功能依赖于具体实现,我在g++中使用这个函数没有作用,后来在下面这篇文章看到原因。
这篇文章讲到了cin.sync()具体功能依赖于实现, VC++将cin.sync()实现为清空现有缓冲区,而g++什么都不做。

0 0
原创粉丝点击