65,013
社区成员
发帖
与我相关
我的任务
分享
cin的总结
近日浏览CSDN,发现经常会有关于cin的问题
参考文献:
http://blog.csdn.net/daineng/archive/2008/04/05/2252730.aspx
http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
http://hi.baidu.com/bdruiruili/blog/item/5966d9958a6eb20c7bf4801f.html
http://www.cplusplus.com/reference/iostream/istream/
建议看看:Tips and Tricks for Using C++ I/O (input/output)
在cin>><int/float/double>时 如果我们输入一个字符,就会导致刷屏的结果。这是因为非数字字符无法被cin接收而一直停留在输入缓冲区,从而导致下一次cin时直接从缓冲区中读取数据,但是字符无法读取,导致死循环。
那么怎么解决呢?
第一、 在cin>><int/float/double>后加cin.ignore(); cin.clear();
第二、 在cin>><int/float/double >后加fflush(stdin); (需要#include <cstdio>) cin.clear()
cin.clear()可以清除输入错误后的相应流状态,而ignore和fflush都是起到刷新输入缓冲区的作用(输入的字母留在了缓冲区,cin不能读取,如果不刷新,之后cin还是首先读到字母,导致死循环),从而是cin可以重新接收新的数据。
fflush刷新缓冲区相信大家都不陌生了,这里就不多说了,那么ignore()方法是怎样操作的呢?
以下参考C++ Reference:
ignore()方法原型是:
istream& ignore ( streamsize n = 1, int delim = EOF );功能:它从输入序列提取字符并且丢弃它们,ignore方法直到丢弃的字符数达到 n 或者丢弃的字符是 delim 时(注意,delim 也会一起被丢弃),终止函数。
参数:
n 丢弃的最大字符数, 它是 streamsize.整数类型
delim 界限符
返回值:
函数返回 *this
流状态有三种:
1) stream:: badbit
系统级的故障,如无法恢复的读写错误,流通常无法继续使用。
2) stream::failbit
可恢复的流错误,如在希望获得数值型的数据时输入了字符,
3) stream::eofbit
文件结束,同时还会设置failbit标志
流有三个函数来测试以上各个流状态:即bad(), fail()和eof(),另外流状态是否正常可以用good()来测试;流的状态字可以由rdstate()读出;另外还有两个操作用于改变流的状态:clear()和setstate(),但它们的操作结果不怎么符合我们的直觉。(注:C++ Reference中的解释是:Sets a new value for the error control state.)
setstate必须有个一个表示流状态的参数,操作结果将使指定的状态位置位(set),其他的状态位不变,无法作reset操作。clear用于设置流的状态为参数指定的状态字,它实际上是个set操作,而不是reset,它的参数有一个默认的值为goodbit,这实际是个0,等价于clear(0); 不带参数调用时就是clear状态,带参数时,并不是我们想象中的reset参数指定的位,而是将整个状态字设置成参数指定的那样。
具体的请看basic_ios.h中的代码:
/* g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) */
void clear(iostate __state = goodbit);
void setstate(iostate __state)
{this->clear(this->rdstate() | __state;}
以一个例子作为参考:(C++ Primer里面的一个例子)
#include <stdexcept>
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int ival;
while(cin>>ival, !cin.eof())
{
if(cin.bad())
throw runtime_error("IO stream corrupted");
if(cin.fail())
{
cout << "rdstate()函数的返回值: " << cin.rdstate() << endl;
cout << "三个标记位返回的返回值: " << cin.fail() << cin.bad() << cin.eof() << endl;
cout << "goodbit标记位的返回值: " << cin.good() << endl;
//cin.clear(istream::failbit); // 这样不行
//cin.clear(istream::failbit ^ cin.rdstate()); // 可以
//cin.ignore();
cin.clear();
fflush(stdin);
cerr <<"bad data, try again:"<<endl;
//system("PAUSE");
continue;
}
cout <<ival <<endl;
}
system("PAUSE");
return 0;
}
上面的例子修正了C++ Primer书上的例子
用了2种方法清除输入错误:
cin.clear();
fflush(stdin);
和
cin.ignore();
cin.clear();
其中,cin.clear()可以替换为:cin.clear(istream::failbit ^ cin.rdstate());
也许大家对cin.rdstate()不太熟悉,简要说明一下:
它的原型是:iostate rdstate ( ) const;它的功能是返回流的当前内部错误标志,他的返回值是eofbit、failbit、badbit和goodbit的任意组合。
如果有任何错误,请指正!
#include <iostream>
using namespace std;
int main()
{
int a;
cin>>a;
cout<<cin.rdstate()<<endl;
if(cin.rdstate() == ios::goodbit)
{
cout<<"输入数据的类型正确,无错误!"<<endl;
}
if(cin.rdstate() == ios_base::failbit)
{
cout<<"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl;
}
system("pause");
}
#include <iostream>
using namespace std;
int main()
{
int a;
while(1)
{
cin>>a;
if(!cin) //条件可改写为cin.fail()
{
cout<<"输入有错!请重新输入"<<endl;
cin.clear();
cin.sync(); //清空流
}
else
{
cout<<a;
break;
}
}
system("pause");
}