当涉及到基于一组指令创建程序时,我在设计伪代码,实现实际代码方面做得很好。我觉得我缺少的是检查用户的输入(它是否有效)。在我练习编程时,我创建了自己的方法来检查用户输入的有效性。但是代码很长,我觉得不够(我将解释原因)。我想知道是否有更好的方法来检查用户的输入。以及其他程序员如何实现他们的代码。
这是我验证用户输入的方式:
if(cin.fail()) {
cout << "Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
// I didn't know how to skip a line while in code
while(input < 0) {
cout << "Invalid Input" << endl;
cout << "Enter radius: " << endl;
cin >> input;
if(cin.fail()) {
cout << "Error: Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
}
当cin无法将值单独存储到变量中(第1 - 5行,第11 -15行)时退出的原因是,如果我将cin.fail()添加到while条件中并尝试输入一个字母,它将开始一个无限循环。我做了一些调查,我发现你必须先使用cin.sync(),然后再使用cin.clear()。但是我还是得到了无限循环
代码如下:
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 || cin.fail());
如果我做错了什么,看到更好的方法来验证用户的输入将非常有帮助。
我不建议使用std::cin,因为它在输入缓冲区中找到第一个空白实例后留下所有剩余的用户输入。这将产生问题,除非您使用cin.ignore()删除剩余的字符。通常认为使用getline()是更好的做法,它将获取所有字符直到换行符。如果您选择使用std::cin,则需要使用cin.ignore()来删除剩余的字符,并使用cin.clear()来重置cin的失败位,以便while条件在下一次通过循环时能够正常工作。
下面是我将如何解决这个问题。它使用getline()获取所有字符,并使用stringstream将字符串转换为int型。注意,您需要像使用cin一样清除stringstream的fail位,以确保当您在while条件中执行ss>> result时条件能够正确工作。std::cout << "Enter radius: ";
getline(std::cin, input);
std::stringstream ss(input);
while(!(ss >> result)) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
getline(std::cin, input);
ss.clear();
ss << input;
}
下面我还将包括一些使用std:cin解决问题的代码。尽管如此,我仍然推荐使用getline()。注意:std::numeric_limits::max()用于指定从输入缓冲区中删除多少字符。使用这个数字而不是您自己的任意数字是一种更好的做法,因为您无法确定用户将输入多少字符。Cin.ignore()将删除给定数字之前的所有字符,或者直到它到达作为其第二个参数提供的字符的实例,在本例中是newline ('n')。
std::cout << "Enter radius: ";
std::cin >> result;
while(std::cin.fail()) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
std::cin >> result;
}
输入验证的问题是一种简单的解析形式。
有语言类(在形式语言理论领域)来表达输入的复杂性。这些类被称为常规类、上下文无关类和图完备类。
你必须考虑你的程序可能接收到的所有输入,并决定你的程序是否应该接受它们。语言类帮助您决定需要哪种类型的输入验证。
如果语言是正则的(就像你的情况),你可以使用正则表达式来验证输入。
例如,与上下文无关的语言是数学公式。正则表达式不能计算括号的个数。因此,用正则表达式检查((a+b) * (c+d))
是否有正确数量的括号是不可能的。
到目前为止,这些都是关于你应该做什么的提示,当编程对你来说更自然的时候。
为了简单起见,我们将使用非常受限的正则表达式,比如手工解析。在伪代码中你真正想做的是:
do {
std::cout << "Please enter radius: ";
line = read_a_line_from(std::cin) // separated by 'n' the newline
if (false == really_read_a_line(line)) {
/* error handling for std::cin, dealing with i.e.: the fail bit */
break; /* exit the loop */
}
if (line == "exit") { // give the user an explicit exit, to quit gracefully
exit(SUCCESS); /* exit the program */
}
if (false == is_a_number(line)) {
/* we read something that isn't a number */
/* we should tell the user he should do as we asked */
continue; /* jump back to the beginning of the loop */
}
unsigned num = convert_number(line);
unsigned area = calculate_area(num); /* do something with your input */
} while (true);
exit(FAILURE);
这里的代码不太具体,目的是让您看到在某些地方可以做什么,仍然省略了实际的实现(供您练习)。请注意,检查一行是否实际上是数字的一种简单方法是转换。但是,并不是所有要解析的内容都应该同时检查有效性和处理。
参见Also(特别是示例):
http://en.cppreference.com/w/cpp/string/basic_string/getline http://en.cppreference.com/w/cpp/string/basic_string/stol如何检查是否给定c++字符串或字符*只包含数字?
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 && cin.fail());