【问题标题】:Get only integers as input, code not working as expected仅获取整数作为输入,代码未按预期工作
【发布时间】:2018-11-26 01:56:09
【问题描述】:

我试图只允许输入整数

应该拒绝:

  • 5 小时
  • 3.4
  • 3.gh
  • 3.0
  • htr

应该接受:

  • -5
  • 0
  • 78

当前代码

int getIntInput() {
    int userInput;

    while (true) {
        std::cout << "> ";
        std::cin >> userInput;
        std::cout << std::flush;

        if (std::cin.fail()) {
            std::string cinBuffer;
            std::cin.clear();
            std::getline(std::cin, cinBuffer);
            continue;
        }
        break;
    }
    return userInput;
}

更新代码

问题:

  • 接受除“htr”(无数字)之外的所有拒绝

    int getIntInput() {
            std::string rawInput;
            int parsedinput;
    
            while (true) {
                std::cout << "> ";
                std::getline(std::cin, rawInput);
                std::cout << std::flush;
    
                try {
                    parsedinput = std::stoi(rawInput);
    
                } catch (std::invalid_argument & e) {
                    continue;
    
                } catch (std::out_of_range & e) {
                    continue;
                }
    
               break;
        }
        return parsedinput;
    }
    

完成的代码

  • 只接受带有可选参数的整数,这将允许 要接受或拒绝的负数。

    int getIntInput(bool allowNegatives = true) {
        bool validIntInput;
        std::string rawInput;
        int parsedinput;
    
        while (true) {
            validIntInput = true;
    
            // Grabs the entire input line
            std::cout << "> ";
            std::getline(std::cin, rawInput);
            std::cout << std::flush;
    
            for (int i = 0; i < rawInput.length(); i++) {
                // Checks to see if all digits are a number as well as to see if the number is a negative number
                if (!isdigit(rawInput[i]) && !(allowNegatives && i == 0 && rawInput[i] == '-')) {
                    validIntInput = false;
                    break;
                }
            }
    
            if (!validIntInput) {
                continue;
    
            } else {
                try {
                    // Try parse the string to an int
                    parsedinput = std::stoi(rawInput);
    
                    // Catch all possible exceptions, another input will be required
                } catch (...) {
                    continue;
                }
                // If the code reaches here then the string has been parsed to an int
                break;
            }
        }
        return  parsedinput;}
    

【问题讨论】:

  • 您有什么要求?我不知道你期望会发生什么。最好提供几个用户输入和预期结果的示例。
  • 只获取整数作为输入,如果输入了 4.5 等值,则不应接受该值,应输入另一个输入

标签: c++ input int cin


【解决方案1】:
template<class T>
T findInStreamLineWith(std::istream &input) {
    std::string line;
    while (std::getline(input, line)) {
        std::istringstream stream(line);
        T x;
        if (stream >> x >> std::ws && stream.eof()) {
            return x;
        }
        // reenter value
        // cout << "Enter value again: ";
    }
    throw std::invalid_argument("can't find value in stream");
}

…
auto x = findInStreamLineWith<int>(std::cin);

【讨论】:

【解决方案2】:

如果您不介意开销,我会使用 cin.getline() 从 cin 获取输入并将其保存到字符串中。然后遍历字符串并在每个字符上调用isdigit。您可以使用str.erase 函数丢弃不是数字的字符。

您需要为isdigit() #include cctype。

注意:根据字符串的长度,这将至少具有 O(N) 运行时间。

【讨论】:

    【解决方案3】:

    cin 在必须读取 int 时的工作方式是,它开始解析整数并在找到非 int 字符时停止,将解析的 int 存储在变量中。这就是为什么在浮点数上它会在点上停止,而在输入“5g”中它会在 g 上停止。

    如果您只需要整数输入,您可以改为 read the whole line,然后使用以下代码检查字符串中的每个字符是否都是数字:

    bool onlyNums = true;
    for (int i=0;i<rawInput.size();i++) {
        if (!isdigit(rawInput[i]))
            onlyNums = false;
    }
    
    if (!onlyNums)
        continue;
    

    (上述代码必须包含 ctype.h 库)

    【讨论】:

    • 那么为了以后的使用,我应该一直使用getline吗?
    • 取决于您的需求,cin 对于读取预期具有特定格式的令牌非常强大,但是由于您需要在此示例中验证整个输入行,因此最好阅读整个行并在之后处理它。
    • 你能看看我更新的答案吗?仍然有问题。
    • 是的,我的错,没有测试我建议你的实现。编辑了我的回复,现在应该可以了。无论如何,所有解析函数都必须遍历整个字符串来检查每个字符是否都是数字。
    • 所以我已经建立在你的两个答案的基础上,我所做的是过度杀伤还是可以接受的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    相关资源
    最近更新 更多