C++程序学习--cin.get()函数读取空行时的细节

在学习《C++ Primer Plus》第六版第17章P785页的程序时遇到一个小问题,这个问题困扰了我很久,直到我找到了一篇博文http://www.cnblogs.com/tonglingliangyong/p/3908463.html,该问题是:

请看下面这个代码:

#include 
#include 
using namespace std;

int main()
{
	char str[20];
	int  num;
	cout << "请输入:\n";
	cin.get(str, sizeof(str));
	cout << "str: " << str << endl;
	
	cout << "请输入一个数:";
	cin >> num;
	cout << "num = " << num << endl;
	
	return 0;
}

上述代码非常简单,但是存在一个Bug,就是如果我们在输入 str 的时候特意输入一个空行时,就会使num无法输入了,get()函数在读到空行的时候,会将换行符保留在输入队列,但同时会将cin的状态置为错误,并且如果此时代码中有while()循环时,cin的错误会一直持续,那样就会陷入死循环。我们可以用下面代码来捕获该错误:

#include 
#include 
using namespace std;

int main()
{
	char str[20];
	int  num;
	cout << "请输入:\n";
	cin.get(str, sizeof(str));
	
	if(cin.rdstate() == ios::goodbit)
	{
		cout << "输入一行正确.\n";
		cout << "str: " << str << endl;
	}
	
	if(cin.rdstate() == ios::failbit)
	{
		cout << "输入了空行、或者其他错误.\n";
		cin.clear();
		cin.sync();
	}
	
	cout << "请输入一个数:";
	cin >> num;
	cout << "num = " << num << endl;
	
	return 0;
}
如果此时我们依然输入对str输入空行时,就会执行到failbit的条件中,代码中加入了:

cin.clear();
cin.sync();
这两句代码很重要,cin.clear()主要将cin的状态清0,让我们可以继续输入,cin.sync()让流与其对应的数据源同步,这样流就可以丢弃掉之前没有处理的数据,如果不这样做,前面的没有处理掉的数据如果不能转换为需要的类型,那么流会一直处于错误状态。
所以在使用get()函数需要读取空行时应该加入上面两条重要代码,如果我们将上面get()函数换成getline()函数时,对于 空行的处理则没有这麽多细节,getline()函数遇到换行符时会将换行符丢弃掉,即在下次输入中,输入队列不会有换行符存在,也不会产生cin的错误状态。
同时,上面两条代码的细节地方:

#include 
using namespace std;
int main()
{
	int num1, num2;
	
	cout << "请输入一个数:";
	cin >> num1;
	cout << "num1 = " << num1 << endl;
	cin.clear();
	cin.sync();
	cin >> num2;
	cout << "num2 = " << num2 << endl;
	return 0;
}
我们特意输入abcd时,如果没有中间清空同步的两条代码,则后面的num2就不能再输入了...

 
  

你可能感兴趣的:(C++程序学习)