流的错误
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; }