关于C++的cin异常的处理方式与中文输入吞字现象的关联与解决方案
一、问题现象:在处理完cin异常后,中文字符串输入出现异常
如果程序经历过这样的cin异常处理手段,那么后续的中文字符串输入将会出现异常:
cin.clear();
setbuf(stdin,NULL);
问题1:cin的异常与处理
在C++中,cin的操作需要数据类型匹配才能正常执行,当你试图将字母赋值给一个整型数时就会导致cin异常,比如下面的代码:
#include<iostream>
using namespace std;
int main(){
int a = 0;
cout << "请输入数字1:";
while(true){
cin >> a;
if ( a == 1 ){
break;
}
cout << "你没有输入1,请重新输入吧:";
}
return 0;
}
①输入字母后的运行结果
②一般的解决方案:向代码中插入这两段来清除cin异常
cin.clear(); //清除cin异常状态
setbuf(stdin,NULL); //清除缓冲区数据
#include <iostream>
using namespace std;
int main() {
int a = 0;
cout << "请输入数字1:";
while (true) {
cin >> a;
if(!cin){//获取cin异常
cin.clear();//清除cin异常状态
setbuf(stdin,NULL);//清除缓冲区数据
}
else if (a == 1) {
break;
}
cout << "你没有输入数字1,请重试:";
}
return 0;
}
③最终效果图
问题2:中文输入出现异常
在使用上述方案解决cin异常后,我们如果继续在代码里添加输入中文的过程,会发现中文输入出问题了:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int a = 0;
string b = "0";
cout << "请输入数字1:";
while (true) {
cin >> a;
if(!cin){
cin.clear();//清除cin异常状态
setbuf(stdin,NULL);//清除缓冲区数据
}
else if (a == 1) {
break;
}
cout << "你没有输入数字1,请重试:";
}
cout << "请输入中文“我爱编程”:";
while (true) {
cin >> b;
if(b == "我爱编程"){
break;
}
cout << "你输入的是“" << b << "”,不是“我爱编程”,请重新输入:";
}
return 0;
}
①使用了setbuf(stdin,NULL);后的运行结果:
②该现象的规律
1.只对含有中文字符的输入有影响
2.输入的文本中每个中文后的第一个字符都会被吞
3.被吞的字符如果是中文,则该中文字符后的第一个字符不会被吞
二、上述问题的解决:中文输入问题与cin异常的问题同时解决的方案
解决方法:setbuf(stdin,NULL);
把setbuf(stdin,NULL);替换成这个:
rewind(stdin); //清理cin缓冲区防止cin错误导致死循环
最终代码及效果图
①代码
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int a = 0;
string b = "0";
cout << "请输入数字1:";
while (true) {
cin >> a;
if(!cin){
cin.clear();//清除cin异常状态
rewind(stdin);//清除缓冲区数据
}
else if (a == 1) {
break;
}
cout << "你没有输入数字1,请重试:";
}
cout << "请输入中文“我爱编程”:";
while (true) {
cin >> b;
if(b == "我爱编程"){
break;
}
cout << "你输入的是“" << b << "”,不是“我爱编程”,请重新输入:";
}
return 0;
}
②效果图
三、总结
1.对于大部分C++控制台程序而言,使用setbuf(stdin,NULL);完全足以应对cin异常
2.对于少部分涉及有中文字符串操作的程序而言,使用rewind(stdin);可以保证中文字符输入不出问题
3.总而言之,rewind(stdin);适用范围更广,推荐使用
4.原问题出处链接(本人付费悬赏问题的解答)