整数输入 拒绝非整数输入并在C++中请求另一个输入

Integer input Rejecting non integer input and requesting another in C++?

本文关键字:输入 整数 另一个 C++ 请求 拒绝      更新时间:2023-10-16

这个函数在 while-loop 内的另一个函数中不断被调用,而 valid_office_num 为 false。问题是,如果输入以数字开头,但后跟其他无效字符(例如 5t),它会获取数字部分并接受它作为有效输入。我希望它考虑整个输入并拒绝它,以便它可以请求另一个输入。我以为我可以使用getline(),但是我不能使用cin.fail()。如何实现此行为?

我忘了说我对C++很陌生,到目前为止我只学到了基础知识。

(需要明确的是,期望的行为是拒绝包含数字以外的任何内容。这不是整数范围检查问题。如果它不是整数,则丢弃它并请求另一个)

//Function to read a valid office number, entered by user
int read_office_num()
{
    //Declaration of a local variable
    int office_num;
    //Read input
    cin >> office_num;
    //Check if input was valid
    if (cin.fail())
    {
        //Print error message
        cout << "nInvalid office number, it should only consist of digits!! Enter another:n";
        //Clear error flags
        cin.clear();
        //Ignore any whitespace left on input stream by cin
        cin.ignore(256, 'n');
    }
    else
    {
        //Office number entered is valid
        valid_office_num = true;
    }
    return office_num;
}

从我收集的信息来看,您希望将整行读取为数字并失败?

好吧,您可以使用 std::getline() ,但您必须遵循以下算法(我将把实现留给您.

  1. 使用 std::getline(cin, str) 读取一行,如果返回 true
  2. 使用 std::stoi(str, &pos) 转换为整数并获取最后一个整数的位置
  3. 如果pos != str.size()则整行不是整数(或者如果上面抛出异常),那么它不是一个有效的整数,否则返回值...

使用 std::getline() 将输入行作为std::string读取。

检查

字符串并检查它是否包含任何非数字字符。

如果字符串仅包含数字,请使用std::istringstream从字符串中读取整数。 否则报告失败,或采取任何其他需要的恢复操作(例如,丢弃整个字符串并返回以读取另一个字符串)。

您可以使用字符串流

int read_office_num()
{
    //Declaration of a local variable
    int office_num;
    string input = "";
    while (true) {
        getline(cin, input);
        stringstream myStream(input);
        if (myStream >> office_num)
            break;
        cout << "nInvalid office number, it should only consist of digits!! Enter another:n" << endl;
    }
    return office_num;
}

如果你想拒绝像123 xxx这样的输入,你可以添加一个额外的检查来验证收到的字符串是否确实是一个整数:

bool is_number(const string& s)
{
    string::const_iterator itr = s.begin();
    while (itr != s.end() && isdigit(*itr)) ++itr;
    return !s.empty() && itr == s.end();
}
int read_office_num()
{
    //Declaration of a local variable
    int office_num;
    string input = "";
    while (true) {
        getline(cin, input);
        stringstream myStream(input);
        if (is_number(input) && myStream >> office_num)
            break;
        cout << "nInvalid office number, it should only consist of digits!! Enter another:n" << endl;
    }
    return office_num;
}
您可能

应该只查看cin中剩余的输入字符数。你可以用in_avail

做到这一点

你的函数最终可能会有一个这样的主体:

//Declaration of a local variable
int office_num;
//Read input and check if input was valid
for (cin >> office_num; cin.rdbuf()->in_avail() > 1; cin >> office_num){
    //Print error message
    cout << "nInvalid office number, it should only consist of digits!! Enter another:n";
    //Ignore any whitespace left on input stream by cin
    cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
}
//Office number entered is valid
valid_office_num = true;
return office_num;

兴趣点:

  1. cin中始终至少有 1 个字符,否则cin将被标记为 bad 并且不好
  2. 如果以这种方式实现read_office_num则不需要valid_office_num,因为valid_office_num在返回之前将始终设置为true

嗯。我可能遗漏了一些东西,但为什么不阅读一行,修剪它,使用正则表达式来验证一个数字,然后利用strstream的设施,或者如果你必须的话,只是atoi?在所有现实中,我可能只是让用户摆脱无关的输入(但如果我确定我总是以交互方式运行,请丢弃它)。遵循座右铭"宽容你接受的东西"。

不过,"交互式"警告很重要。人们通常不能假设cin是一个终端。有人可能会变得自大,让你的程序在文本文件或管道上运行,然后它就会失败。一种健壮的方法将数据处理(可移植)与输入方式(可能是特定于机器的,因此也比通过控制台的 stdin/stdout 更强大和有用)分开。

以下是使用 Boost Lexical Cast 的方法:

#include <boost/lexical_cast.hpp>
#include <iostream>
#include <vector>
#include <string>
int read_office_num()
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;
    using namespace std;
    int office_num;
    while (true)
    {
        try
        {
            string input = cin.getline();
            office_num = lexical_cast<int>(*argv));
            break;
        }
        catch(const& bad_lexical_cast)
        {
            cout << "nInvalid office number, it should only consist of digits!! Enter another:n";
        }
    }
    return office_num;
}