如何捕获无效的用户输入

时间:2019-02-01 06:10:35

标签: c++

我不理解Try,throw,catch语句,并且想知道当代码中的所有int应该为int时,为什么最好捕获一个char。这是为了防止人们愚蠢到当我要求最喜欢的电话号码时加一个“ a”。这是我尝试保护我的代码的示例,以防止有人在输入整数时输入字符:

int a, b;
std::cout << "Enter a Numerator: ";
std::cin >> a;
std::cout << "Enter a Denominator: ";
std::cin >> b;

2 个答案:

答案 0 :(得分:2)

如果您合并两个问题(thisthis)的两个答案,那么我在您问题的评论部分中提到了,您会得到的,

#include <iostream>

int main()
{
    int a, b;
    std::cout << "Enter a Numerator: ";
    std::cin >> a;
    std::cout << "Enter a Denominator: ";
    std::cin >> b;

    if (!std::cin.good())
    {
        throw std::invalid_argument( "received strings. Need integers" );
    }
}

如第一个链接的答案所述,您可以参考here以获得有关抛出哪些异常的更多信息。

正如第二个链接的答案所提到的,如果用户未输入期望的正确数据类型,“ cin将切换其故障位。将输入的数据类型更改为int并检查此故障位将使您验证用户输入。”

事后想到,最好也将分母检查为零,并在上面的代码示例中添加类似的内容。

if (b /*assuming b is denominator*/ == 0) {
        throw std::overflow_error("Divide by zero exception");
}

答案 1 :(得分:0)

要更精细地控制输入例程,您需要学习使用std::ios_base::iostate流状态goodbit, eofbit, badbit, and failbit。您可以直接使用std::basic_ios::rdstate检查状态,也可以使用方便的成员函数.good(), .eof(), .bad() and .fail(),请参阅std::basic_istream

虽然检查.good()会告诉您输入内容不错,但并不能帮助您从输入失败或错误情况或EOF中恢复。为此,您必须单独检查发生的错误情况。

根据我的评论并添加一些细节,您可以执行以下操作(其中您只对ab做同样的事情-您可以移动到一个函数或成员函数),例如

#include <iostream>
#include <limits>

int main (void) {

    int a, b;

    /* get input for a */
    while (1)       /* loop continually reading input */
    {
        std::cout << "\nenter an integer for a: ";
        if (! (std::cin >> a) ) {   /* check stream state */
            /* if eof() or bad() break read loop */
            if (std::cin.eof() || std::cin.bad()) {
                std::cerr << "(user canceled or unreconverable error)\n";
                goto unrecoverable;
            }
            else if (std::cin.fail()) {     /* if failbit */
                std::cerr << "error: invalid input.\n";
                std::cin.clear();           /* clear failbit */
                /* extract any characters that remain unread */
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                                '\n');
            }
        }
        else {  /* on succesful read, just output int and break loop */
            std::cout << "integer a: " << a << '\n';
            /* extract any characters that remain unread */
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                            '\n');
            break;
        }
    }

    /* same thing for b */
    while (1)       /* loop continually reading input */
    {
        std::cout << "\nenter an integer for b: ";
        if (! (std::cin >> b) ) {   /* check stream state */
            /* if eof() or bad() break read loop */
            if (std::cin.eof() || std::cin.bad()) {
                std::cerr << "(user canceled or unreconverable error)\n";
                break;
            }
            else if (std::cin.fail()) {     /* if failbit */
                std::cerr << "error: invalid input.\n";
                std::cin.clear();           /* clear failbit */
                /* extract any characters that remain unread */
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                                '\n');
            }
        }
        else {  /* on succesful read, just output int and break loop */
            std::cout << "integer b: " << b << '\n';
            /* extract any characters that remain unread */
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                            '\n');
            break;
        }
    }

    unrecoverable:;
}

请注意,将std::numeric_limits<std::streamsize>::max()std::cin.ignore配合使用,以清除stdin中剩余的任何令人反感的字符。 (基本上会提取最大的字符流大小,直到找到'\n'为止),因此下一次输入尝试不会尝试重新读取相同的错误字符并由于相同的原因而再次失败-通常导致如果输入是在循环内进行的,则为无限循环。

还请注意,无论用户取消goto还是a的输入,都使用旧的b允许程序正常退出。

这是一个输入例程,因此在编写它之后-尝试将其破坏。如果损坏,请修复。那是您可以捕获大多数极端情况的唯一方法,例如

使用/输出示例

$ ./bin/cin_validate_ab

enter an integer for a: no
error: invalid input.

enter an integer for a: OK
error: invalid input.

enter an integer for a: 5, I entered 5!
integer a: 5

enter an integer for b: again!
error: invalid input.

enter an integer for b: 6
integer b: 6

用户在Linux上使用 Ctrl + d 取消输入(在Windows上使用 Ctrl + z 取消输入)。

$ ./bin/cin_validate_ab

enter an integer for a: (user canceled or unreconverable error)

仔细研究一下,如果您有任何疑问,请告诉我。