流的错误

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;
}
posted @ 2011-11-09 21:42  csqlwy  阅读(787)  评论(5编辑  收藏  举报