使用错误处理循环捕获用户输入 int 的最佳方法
The best way to capture user input int with error handling loop
在我的例子中,我必须确保用户输入是 1 或 2,或 3。
这是我的代码:
#include <iostream>
using namespace std;
void invalid_choice_prompt() {
string msg = "\nInvalid Command! Please try again.";
cout << msg << endl;
}
int ask_user_rps_check_input(int user_choice) {
if (user_choice == 1 || user_choice == 2 || user_choice == 3) return 1;
return 0;
}
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}
int main() {
ask_user_rps();
return 0;
}
当输入是整数时,代码能够处理这种情况,但是当输入是字符或字符串时,程序将陷入死循环。
有什么优雅的方法可以做到这一点吗?我找到了一些关于使用 cin.ignore
来忽略指定长度的 io 缓冲区的方法,但我认为这种方法不够灵活。我正在寻找更灵活的解决方案。
以字符形式输入
string user_choice;
cin >> user_choice;
检查输入是否有效if(user_choice=='1')
使用运算符 >>
从流中读取目标类型接受的字符数;其余的将保留在流中以供后续读取。如果输入有格式错误(例如,当需要整数时是前导字母字符),那么也会设置错误标志。这个错误标志可以用 cin.fail()
检查。它保持设置,直到它被明确清除。因此,如果您的代码是...
int user_choice;
cin >> user_choice;
然后如果您输入的不是数字,例如asdf
,然后 user_choice
有一个未定义的值,一个错误标志 cin.fail()
被(和 reamins)设置。因此任何后续读取也会失败。
要克服这个问题,您必须做三件事:
首先,检查错误标志。您可以通过在读取尝试后调用 cin.fail()
或检查表达式 (cin >> user_choice)
的 return 值来执行此操作,这与调用 cin.fail()
.[=23 相同=]
其次,如果出现错误,您需要使用cin.clear()
清除错误标志。否则,之后任何读取任何内容的尝试都将失败。
第三,如果要继续读取整数值,需要从流中取出无效字符。否则,你会一次又一次地把asdf
读入一个整数类型的变量,然后又一次又一次失败。您可以使用 cin.ignore(numeric_limits<streamsize>::max(),'\n');
从输入缓冲区中获取 EOF 或行尾之前的所有字符。
使用错误处理读取整数值的完整代码如下所示:
int readNumber() {
int result;
while (!(cin >> result)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Input is not a number." << std::endl;
}
return result;
}
我认为一个选项是将用户输入收集到一个字符串中,然后使用类似这样的 getline 将其移动到字符串流:
std::string input;
std::getline(std::cin, input);
//Now check if the input is correct. if it is, then:
std::stringstream stream;
stream << input;
int num;
stream >> num;
我不确定这是否是个好方法,但它确实有效。
最简单的解决方案之一是检查 cin 流故障,如下所示:
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if(cin.fail()) {
invalid_choice_prompt();
std::cin.clear();
std::cin.ignore(256,'\n');
continue;
}
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}
在我的例子中,我必须确保用户输入是 1 或 2,或 3。
这是我的代码:
#include <iostream>
using namespace std;
void invalid_choice_prompt() {
string msg = "\nInvalid Command! Please try again.";
cout << msg << endl;
}
int ask_user_rps_check_input(int user_choice) {
if (user_choice == 1 || user_choice == 2 || user_choice == 3) return 1;
return 0;
}
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}
int main() {
ask_user_rps();
return 0;
}
当输入是整数时,代码能够处理这种情况,但是当输入是字符或字符串时,程序将陷入死循环。
有什么优雅的方法可以做到这一点吗?我找到了一些关于使用 cin.ignore
来忽略指定长度的 io 缓冲区的方法,但我认为这种方法不够灵活。我正在寻找更灵活的解决方案。
以字符形式输入
string user_choice;
cin >> user_choice;
检查输入是否有效if(user_choice=='1')
使用运算符 >>
从流中读取目标类型接受的字符数;其余的将保留在流中以供后续读取。如果输入有格式错误(例如,当需要整数时是前导字母字符),那么也会设置错误标志。这个错误标志可以用 cin.fail()
检查。它保持设置,直到它被明确清除。因此,如果您的代码是...
int user_choice;
cin >> user_choice;
然后如果您输入的不是数字,例如asdf
,然后 user_choice
有一个未定义的值,一个错误标志 cin.fail()
被(和 reamins)设置。因此任何后续读取也会失败。
要克服这个问题,您必须做三件事:
首先,检查错误标志。您可以通过在读取尝试后调用 cin.fail()
或检查表达式 (cin >> user_choice)
的 return 值来执行此操作,这与调用 cin.fail()
.[=23 相同=]
其次,如果出现错误,您需要使用cin.clear()
清除错误标志。否则,之后任何读取任何内容的尝试都将失败。
第三,如果要继续读取整数值,需要从流中取出无效字符。否则,你会一次又一次地把asdf
读入一个整数类型的变量,然后又一次又一次失败。您可以使用 cin.ignore(numeric_limits<streamsize>::max(),'\n');
从输入缓冲区中获取 EOF 或行尾之前的所有字符。
使用错误处理读取整数值的完整代码如下所示:
int readNumber() {
int result;
while (!(cin >> result)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Input is not a number." << std::endl;
}
return result;
}
我认为一个选项是将用户输入收集到一个字符串中,然后使用类似这样的 getline 将其移动到字符串流:
std::string input;
std::getline(std::cin, input);
//Now check if the input is correct. if it is, then:
std::stringstream stream;
stream << input;
int num;
stream >> num;
我不确定这是否是个好方法,但它确实有效。
最简单的解决方案之一是检查 cin 流故障,如下所示:
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if(cin.fail()) {
invalid_choice_prompt();
std::cin.clear();
std::cin.ignore(256,'\n');
continue;
}
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}