#include <iostream>
intmain()
{
long ID;
std::cout<<"enter your ID: "<<std::endl;
std::cin>>ID;//oops, what if the user enters invalid data?
}
只要用户不输入非法变量,例如一个字符串或者字母和数字的组合,那么从程序设计的规则上来说,这个代码是没有什么问题的。
问题就在于,CIN虽然可以辨识非法的输入,可是它不并能将该错误反馈给程序,除非在每次输入操作完成后清楚地检查它的错误标记。更糟糕的是,如果不重置CIN,它将会中断另外的输入操作。
为了避免在每次输入操作后都要进行手工检查CIN状态的麻烦,我们可以绕开所有确认CIN的途径,将输入信息当作一个字符串来处理,然后人工确认这个数据串并检查其他任何的可能的错误。如果这个字符串是合法的,可把它转化成int或者其他的类型。
再来看看先前的例子,这次我们将把输入的信息储存为一个字符串,检查它,如果没有任何错误,把字符串定义为int。否则,我们将得到一个错误的信息,程序会提示用户再次输入ID。
#include <string>
#include <sstream>
#include <iostream>
#include <cctype> //for isdigit()
bool validate(const std::string &s);
int main()
{
std::stringstream stream; //for conversion
std::stringstring_id;
long ID=0;
std::cout<<"enter your ID: "<<std::endl;
std::cin>>string_id;
while(validate(string_id)!=true)
{
std::cout<< "invalid ID number; please try again: "<<std::endl;
std::cin>>string_id;
}
//we reach this part if the string is valid
stream<<string_id;
stream>>ID; //extract
}
Here is the implementation of validate():
bool validate(const std::string &s)
{
bool valid=true;
for(inti=0; i<s.size(); ++i)
if(!::isdigit(s[i]))
{
valid=false;
break;
}
return valid;
}
我们注意到,在前一个例子里,单单确认CIN的步骤就已经够麻烦了,因此,当我们在做第2个例子的时候,完全可以利用程序自身来检查潜在的错误。
不要担心类型的冲突:读入一个字符串和读入一个数字数据一样有效,因为在覆盖的作用下,CIN同样也能把输入信息当作字符。