如何在使用cin请求int时有效地模糊用户输入?

问题描述 投票:2回答:5

这是我在这里的第一篇文章,我是编程/ C ++的新手(实际上只是在这个兔子洞的几个星期内)。我在Microsoft Visual Studio 2017中有这个测试项目,我试图弄清楚如何在使用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();
    }
c++ visual-c++ cin
5个回答
1
投票

我建议您不要使用整数来存储“是”或“否”答案,而是使用字符串代替。通过这种方式,您可以使用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;
}

如果你必须使用整数,那么你应该看看thiscapturing characters without pressing enter


0
投票

最好的方法是不依赖于某些操作系统功能:

#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 << "!\n\n";
        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
投票

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

当然你也可以接受“y”或“n”而不是用户友好。


0
投票

作为答案状态之一,更容易将输入读入字符串然后评估该字符串。这是一个例子:

#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,并且要么成功退出,要么根据用户输入的内容提示用户。

如果我理解正确的话,这样的事情可以帮助你实现你想要的万无一失的用户输入。我建议您将代码调整为类似的代码而不是具有执行类似任务的多个函数。


0
投票

根据您的编译器,您可以使用像getch()这样的C代码,然后在进行检查之后再将其回显到屏幕上。然后你必须通过char获取代码char并显然组装你的字符串。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.