流(stream)是一个传送和格式化固定宽度字符的对象。包括输入流、输出流和同时实现两种功能的输入/输出流。其中,用istream及其派生类表示输入流,用ostream及其子类表示输出流,用iostream及其子类表示输入输出流。

1 输入流与cin

cin是输入流istream类的对象,它是一个全局变量。cin通过提取符(extractor)“>>”从流中获取信息。

2 错误处理

2.1 流状态位

ios_base类中声明了所有流类共有的内容,不依赖于流所处理的字符类型。其中,定义了4个标志位来测试流的状态,badbit、eofbit、failbit和goodbit。其中,badbit位表示了在流缓冲区中发生了致命性错误,流将不能继续使用;eofbit位表示输入结束,例如按下了Ctrl-Z;failbit位表示I/O操作由于非法数据而失败,流可以继续使用;goodbit位表示一切正常,没有错误发生,也没有发生输入结束。

2.2 流状态函数

通过good()、eof()、fail()和bad()等成员函数获取流状态。这些函数的返回值是boolean类型,分别对应goodbit、eofbit、failbit和badbit标志位的。可以通过调用以上的成员函数,根据其返回的布尔值来测试发生了什么情况,返回的布尔值表示相应的流状态。

当除goodbit之外的其它3个标志位没有被设置时,流类的成员函数good()返回真。如果eofbit被设置则函数eof()返回真,表明程序试图从已经到达末尾的流(通常是文件流)中读取数据。如果设置了failbit和badbit标志位中的任意一个,则函数fail()返回真,只有设置了badbit标志位,函数bad()才返回真。

2.3 清空标志位

一旦设置了流状态中的任何一个标志位,这些标志位将保持不变。可以通过调用clear()函数来清空标志位。如:

 

cin.clear();

 

2.4 编程验证

 

在控制台程序中,有如下代码

 

int i;
cin >> i;
bool good = cin.good();
bool bad = cin.bad();
bool fail = cin.fail();
bool eof = cin.eof();

程序运行后,在控制台中输入整数5,此时good的值是true,而其它三个值是false。输入Ctrl-Z,此时good和bad的值是false,fail和eof的值是true。如果输入一个字符,如’a’,此时good、bad和eof的值是false,而fail的值是true。

 

3 编程实践

在CSDN论坛上有朋友问到这样一个问题:

 

int i;
while(1)
{
   cin >> i;
   cout << i << endl;
}

运行以上代码时,输入正确格式(整数)时,程序可以正确运行。当输入不正确的格式时,如输入字符’a’,此时程序不报错,但是会一直输出i的最后一次正确值。也就是说,当输入错误格式时

 

 

cin >> i;

此代码不起作用了。

 

3.1 问题分析

从“2错误处理”中分析可知,当输入不正确格式的数时,cin的failbit位将会被设置,导致cin的提取符失效。

3.2 问题解决

使用“2.3 清空标志位”中提到的clear()函数,清空failbit位。之后调用ignore()函数跳过流中格式不正确的数据。

 

cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

其中,ignore()函数的第一个参数表示要跳过的字符的数目,第二个参数指定了遇到哪个字符时,ignore()函数退出。

 

numeric_limits是一个模板类,该类用于描述内置数字类型的数学属性,streamsize是流大小的单位,max()函数是numeric_limits类的成员函数,该函数的作用是返回指定类型(streamsize类型)的最大值。第二行代码的含义是,当输入流中的数据出现错误时,跳过该流,此时流的状态为good()。

3.3 修改后的代码

修改后的代码如下所示

 

int i;
while (1)
{
cout << "请输入一个整数:" << endl;
cin >> i;
while(cin.fail())
{
cout << "输入格式错误,请重新输入!" << endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "请输入一个整数:" << endl;
cin >> i;
}
cout << i << endl;
}

此时,当输入不正确格式的数据时,程序会显示错误提示信息,并且可以重新输入。