C++中的整数验证

nfzehxib  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(102)

我在这里有点困惑。为什么代码在输入字母时给予我一个无限循环?

do
{
    if (cin.fail())
    {
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cin.clear();
    }
    cout << "Please Enter a Number: ";
    cin >> N;
} while (cin.fail());
x6yk4ghg

x6yk4ghg1#

失败后,必须在输入或忽略输入流中的任何字符之前清除std::cin
如果std::cin处于失败状态,则不能输入或忽略任何字符。调用std::cin.clear()将重置输入流的failbit(沿着其eofbitbadbit),之后std::cin不再处于失败状态。只有这样,对std::cin.ignore的调用才会有任何效果。
在本例中,您需要颠倒对std::cin.ignorestd::cin.clear的调用顺序:

do
{
    if (cin.fail())
    {
        cin.clear();  // MUST CALL CLEAR BEFORE CALLING IGNORE.
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    cout << "Please Enter a Number: ";
    cin >> N;
} while (cin.fail());

在输入后而不是之前测试cin.fail()

在下面的评论中,@雷米勒博为在从cin获取输入之后而不是之前测试cin.fail()提供了一个很好的案例。

for (;;)
{
    std::cout << "Please Enter a Number: ";
    if (std::cin >> N)
        break;
    std::cout << "Invalid entry. Please reenter.\n\n";
    std::cin.clear();
    std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

这更接近我自己编写代码的方式。
然而,如果有一个 * 前提条件 *,cin.fail()返回false,在进入这个循环之前隐式或显式地建立,那么这个“改进”的效果是“没有任何改变”。OP的代码和这个版本的行为都是一样的。
这就是为什么我在评论中说,我对OP的编码方式很满意,如果这是他想要的方式的话。

使用函数进行控制台输入

在我自己的工作中,我使用了@Some programmer dude在上面的评论中描述的技术:“把整行读成一串。尝试将字符串转换为整数。如果无效或超出范围,请重试。把它放在一个单独的函数中也是一个好主意。”
此外,我允许用户通过在空白行上按Enter键来取消输入操作。否则,我会一直循环,直到用户正确。
我有以下函数模板的三个重载,这取决于需要什么范围检查选项。
1.不收支票
1.检查min
1.检查minmax
在任何时候,我都不能调用cin.clearcin.ignore。如果std::getline失败,则抛出std::runtime_error
函数tbx::console::get_number在输入成功时返回true,在用户取消时返回false。输入的数字通过参数n返回。requires子句中的type_traits确保NumType是以下之一:

  1. charsigned charunsigned char
    1.签名或未签名:shortintlonglong long
  2. floatdoublelong double
    此声明用于检查minmax的重载。
namespace tbx::console
{
    template< typename NumType >
        requires tbx::is_char_short_int_long_v<NumType>
            || std::is_floating_point_v<NumType>
    bool get_number(
        NumType& n
        , NumType const min
        , NumType const max
        , std::string const& prompt = "Enter value (press Enter to cancel): "
        , std::string const& reenter_prompt = "Invalid entry. Please reenter."
        , std::istream& ist = std::cin
        , std::ostream& ost = std::cout);
}

相关问题