1. 错误状态位
流的错误状态位包含在类ios的enum成员中,用于报告在输入输出操作中的错误。
未 | 被 | 使 | 用 | hardfail | badbit | failbit | eofbit |
goodbit:没有错误,没有设置标志,值为0;
eofbit:到达文件末端;
failbit:操作失败(用户失败,过早的EOF);
badbit:不合法的操作(没有与之相关联的streambuf);
hardfail:不可修复的错误
2. ios中处理错误标志位的函数
int=eof( ) ---如果设置了EOF标志,则返回true
int=fail( )----如果设置了failbit、badbit、hardfail标志,则返回true
int=bad( )---如果设置了 badbit、hardfail标志,则返回true
int=good( )—如果所有事情都正确,没有设置任何标志,则返回true
clear(int=0)---如果没有参数,则清除所有错误标志;否则设置指定的标志,就和在clear(ios::failbit)中一样。
3.举例:
首先看一个简单的例子:
#include <iostream>
using namespace std;
int main()
{
int i;
while(true)
{
cout<<"Enter an integer: ";
//cin.unsetf(ios::skipws);
cin>>i;
if (cin.good())
{
cin.ignore(10,'\n');
break;
}
cin.clear();
cout<<"Incorrect input"<<endl;
cin.ignore(10,'\n');
}
cout<<"integer is "<<i<<endl;
return 0;
}
上面的程序检测的错误就是,如果键盘输入的不是数字(例如:使用nine代替9)。这将导致failbit位被设置。程序会清除,并且返回要求用户继续输入,知道cin.good为1.
注意:① 从输入流中读入数据时,额外的字符会引起问题。典型的错误就是完成输入后仍然有额外的字符残留在输入流中,这样就无意识的把这些残留的字符作为了下一步操作的输入,从而导致程序的错误。(经常出现的额外字符是换行符,有时也有其他字符)
这时我们需要istream的成员函数ignore(MAX,DELIM),它从输入流中读入并且抛弃知道MAX个字符,包括指定的分界符DELIM,如cin.ignore(10,'\n');导致cin读到10个字符,包括字符’\n’,然后从输入流中移除这些字符。
② 上面程序中被注释调的//cin.unsetf(ios::skipws);
我们假设一种情况:无输入的输入:当用户被提示输入数字是,他没有输入,只是简单的按了下回车键(可能用户认为这样就会输入0,哈)。
会出现什么情况呢,回车只会导致光标向下移动一行,但是流仍然在等待数字。
原因:空白符在输入数字时经常被忽略(跳过),例如制表符和’\n’。
解决:空白符可以有清除skipws标志来处理://cin.unsetf(ios::skipws);(有时候告诉输入流不忽略空白符是很重要的)
此时如果用户按回车而没有输入任何数字的话,failbit位将要被设置并且产生错误。
最后来看一个综合点的程序:
#include<iostream>
#include <string>
using namespace std;
bool isFeet(string);
class Distance
{
public:
Distance():feet(0),inches(0.0) {}
Distance(int f,float i):feet(f),inches(i) {}
void show()
{
cout<<feet<<"\'-"<<inches<<"\""<<endl;
}
void getdata();
private:
int feet;
float inches;
};
void Distance::getdata()
{
string instr;
while(true)
{
cout<<"Enter feet: ";
cin.unsetf(ios::skipws); //这里不忽略空字符,防止用户不输入直接回车
cin>>instr;
if (isFeet(instr))
{
cin.ignore(10,'\n');
feet=atoi(instr.c_str());
break;
}
cin.clear();
cin.ignore(10,'\n'); //由于上面不忽略空字符,如果运行到这一步,其实在输入流中
//还有'\n',所以如果没有这句,cin>>instr会因为空字符,
//而不需要用户输入任何东西就继续执行下面语句,导致程序
//无限循环下去,注意
cout<<"Feet must be an integer less than 1000\n";
}
while (true)
{
cout<<"Enter inches: ";
cin.unsetf(ios::skipws);
cin>>inches;
if (inches<0.0||inches>=12.0)
{
cout<<"Inches must be between 0.0 and 11.99 \n";
cin.clear(ios::failbit); //为了保证英寸正确,必须手动设置错误标志
}
if (cin.good())
{
cin.ignore(10,'\n');
break;
}
cin.clear();
cin.ignore(10,'\n');
cout<<"Incurrect inches input\n";
}
}
bool isFeet(string str)
{
int len=str.size();
if (len==0||len>5)
{
return false;
}
for (int j=0;j<len;j++)
{
if ((str[j]<'0'||str[j]>'9')&&str[j]!='-')
{
return false;
}
}
double n=atof(str.c_str());
if (n<-999.0||n>999.0)
{
return false;
}
return true;
}
int main()
{
Distance d;
d.getdata();
d.show();
return 0;
}