cin

我们谈谈cin.clear的作用,第一次看到这东西,很多人以为就是清空cin里面的数据流,而实际上却与此相差很远,首先我们看看以下代码:

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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" ); 
}


我们定义要输入到的变量是整型,但如果我们输入了英文字母或者汉字,那就会发生错误,cin里有个方法能检测这个错误,就是cin.rdstate(); 当cin.rdstate()返回0(即ios::goodbit)时表示无错误,可以继续输入或者操作,若返回4则发生非致命错误即ios::failbit,则不能继续输入或操作.而cin.clear则可以控制我们此时cin里对这个问题的一个标识.语发如下: cin.clear(标识符); 标识符号为:

goodbit 无错误 
Eofbit 已到达文件尾 
failbit 非致命的输入/输出错误,可挽回 
badbit 致命的输入/输出错误,无法挽回 若在输入输出类里.需要加ios::标识符号 
通过cin.clear,我们能确认它的内部标识符,如果输入错误则能重新输入.结合真正的清空数据流方法cin.sync(),请看下例:

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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" ); 
}


上面的cin.clear()默认参数为0,即无错误,正常操作.当我们输入英文字母'k'时,它的状态标识改为fail,即错误,用cout对用户输出信息,再用cin.clear让错误标识改回为0,让我们可以继续输入,再清空流数据继续输入.如果我们没有了cin.clear,则会进入死循环,其过程为我们输入了英文字母,它的状态标识便为fail,当运行到条件判断时,便总是回到错误的条件表示里,并且我们再也没办法输入,因为错误的表示关闭了cin,所以会进入死循环.

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的任意组合。
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值