如何在使用 cin 请求 int 时有效地使用户输入万无一失?

How do I efficiently foolproof user input while using cin to ask for an int?

本文关键字:用户 有效地 输入 万无一失 请求 cin int      更新时间:2023-10-16

这是我在这里的第一篇文章,我对编程/C++非常陌生(实际上只是进入这个兔子洞的几周(。我在Visual Studio 2017 Microsoft中进行了这个测试项目,我正在尝试弄清楚如何在使用cin时完全万无一失的用户输入。如果我要求一个 int,而我只想要一个 1 或一个 0,我希望某人绝对没有办法放入像 2 或 n 这样的东西,或者在错误和正确响应之间放置一个空格,比如"n 1"。目前,我已经到了这样的地步,我似乎可以创建一个不希望的结果的唯一方法是,如果我先输入一个正确的整数(0 或 1(,然后跟一个空格和任何其他字符,并且这种模式可以在初始正确的一个(0 a 42 f 9130(等之后跟随无限数量的空格和字符。除了使用更混乱的代码获得所需的结果之外,我想知道我是否只是缺少一些我还没有听说过的内置函数,这些功能可以使此过程更加高效。这是我为达到这一点而写的:

#include <iostream>
#include <string>
#include <climits>
using namespace std;
int trap;
int wrongNumber();
int numOnly() {
while (cin.fail())
{
// Using someone else's code for this while statement to figure out how to not take a char input when using an int
// Update: Turned this into a function to be called on whenever cin has a chance to fail because users don't listen.
cin.clear(); // clear input buffer to restore cin to a usable state
cin.ignore(INT_MAX, 'n'); // ignore last input
system("CLS");
cout << "----------------------------------" << endl;
cout << "|  You can only enter a number.  |" << endl;
cout << "| Would you like to pick a card? |" << endl;
cout << "|  Type 1 for yes or 0 for no!   |" << endl;
cout << "----------------------------------" << endl;
cin >> trap;
}
if (trap != 1 && trap != 0) {
system("CLS");
wrongNumber();
}
return trap;
}
int wrongNumber() {
// At least I made this fail-safe on my own!
while (trap != 1 && trap != 0) {
system("CLS");
cout << "----------------------------------" << endl;
cout << "|    That is not a 1 or a 0!     |" << endl;
cout << "| Would you like to pick a card? |" << endl;
cout << "|   Type 1 for yes or 0 for no!  |" << endl;
cout << "----------------------------------" << endl;
cin >> trap;
}
if (cin.fail()) {
system("CLS");
numOnly();
}
return trap;
}
int main() {
cout << "----------------------------------" << endl;
cout << "| Would you like to pick a card? |" << endl;
cout << "|   Type 1 for yes or 0 for no!  |" << endl;
cout << "----------------------------------" << endl;
cin >> trap;
while (cin.fail())
{
numOnly();
}
if (trap != 1 && trap != 0) {
wrongNumber();
}

我建议您不要使用整数来存储"是"或"否"答案,而是使用字符串。这样,您可以使用cin.fail()cin.ignore()cin.clear()为自己节省一些代码行:

int main() {
string trap;
cout << "----------------------------------" << endl;
cout << "| Would you like to pick a card? |" << endl;
cout << "|   Type 1 for yes or 0 for no!  |" << endl;
cout << "----------------------------------" << endl;
cin>>trap;
while (trap != "1" && trap != "0") { //You can make this while block into a function if you prefer
cout << "----------------------------------" << endl;
cout << "|    That is not a 1 or a 0!     |" << endl;
cout << "| Would you like to pick a card? |" << endl;
cout << "|   Type 1 for yes or 0 for no!  |" << endl;
cout << "----------------------------------" << endl;
cin>>trap;
}
return 0;
}

如果必须使用整数,则应查看此值并在不按 Enter 的情况下捕获字符。

最好的可以不依赖某些操作系统功能:

#include <iostream>
#include <limits> // std::numeric_limits
#include <cctype> // std::isspace
// function to read and discard whitespace except 'n' from a stream
std::istream& eat_whitespace(std::istream &is)
{
char ch;
// as long as the next character in the stream is a space and not a newline
while (std::isspace(ch = is.peek()) && ch != 'n') 
is.get(); // get and discard the character
return is;
}
int read_range_strict(std::istream &is, int min, int max)
{
int value;
// as long as
while (!(is >> value >> eat_whitespace) // extraction of an int fails
|| is.peek() != 'n' // or the next character in the stream is not a newline *)
|| value < min || max < value // or the value is not within the specified range
) {
std::cerr << "Please enter a number between " << min << " and " << max << "!nn";
is.clear(); // clear flags
// discard everything that might be left in the stream
is.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
}
return value;
}
int main()
{
int value;
do {
value = read_range_strict(std::cin, 0, 1);
} while (true); // only for demo
}

*( 我们试图使用eat_whitespace建立。因此,如果溪流中还剩下任何不是n的东西,我们会在数字之后得到一些垃圾。

由于唯一有效的值是 0 和 1,因此您无需将输入读取为 int。只需将其读取为字符串,修剪任何空格并将字符串与"0"或"1"进行比较。

当然,您也可以只接受"y"或"n",这会更加用户友好。

正如其中一个答案状态,更容易将输入读入字符串,然后计算该字符串。下面是一个示例:

#include <iostream>
#include <string>
int main() {
std::string trap;
std::cout << "Enter 1 or 0" << std::endl;
std::getline(std::cin, trap); // fetch user input, save into trap
while (std::cin.fail() || (trap != "1" && trap != "0")) {
std::cout << "That was not a 1 or 0; try again" << std::endl;
std::getline(std::cin, trap);
}
return 0;
}

此代码读取所有用户输入,确定它是 1 还是 0,然后成功退出或根据用户输入的内容提示用户。

如果我理解正确,这样的事情可能会帮助您在万无一失的用户输入方面实现您想要的东西。我建议你调整你的代码,以适应类似的东西,而不是让几个函数执行类似的任务。

根据您的编译器,您可以使用 get ch(( 等 C 代码,并在完成检查后将其回显到屏幕上。 然后,您必须逐个字符获取代码字符,并且显然可以组装字符串。

https://www.c-lang.thiyagaraaj.com/archive/c-blog/use-of-getch-getche-and-getchar-in-c

免责声明:并非所有C++编译器都支持此功能。 这是 C 代码,而不是C++代码。