如何处理错误的数据类型输入

Posted

技术标签:

【中文标题】如何处理错误的数据类型输入【英文标题】:How to handle wrong data type input 【发布时间】:2012-05-08 03:44:39 【问题描述】:

在 C++ 中,如何处理错误的输入?就像,如果程序要求输入一个整数,当你输入一个字符时,它应该能够做一些事情,然后循环重复输入,但是当你输入一个整数时,循环进入无限期,反之亦然。

【问题讨论】:

【参考方案1】:

程序进入无限循环的原因是因为std::cin的错误输入标志是由于输入失败而设置的。要做的是清除该标志并丢弃输入缓冲区中的错误输入。

//executes loop if the input fails (e.g., no characters were read)
while (std::cout << "Enter a number" && !(std::cin >> num)) 
    std::cin.clear(); //clear bad input flag
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input
    std::cout << "Invalid input; please re-enter.\n";

请参阅the C++ FAQ 了解此内容以及其他示例,包括在条件中添加最小值和/或最大值。

另一种方法是将输入作为字符串获取并使用std::stoi 或其他允许检查转换的方法将其转换为整数。

【讨论】:

在问这里之前我已经做了一些研究。我看到他们把 cin.ignore(1000, '\n');这是做什么的?还有 !(cin >> num) 返回一个布尔值?我不知道 @Marvin, cin.ignore (1000, '\n') 忽略/丢弃输入缓冲区中的字符,直到丢弃 1000 个字符或遇到换行符,以先到者为准。这是摆脱线的好方法。您将在 parashift 示例中看到,它们使用流的最大大小而不是 1000 来说明最大长度的行。我使用cin.sync(),因为这样做时,我想与用户处于平等地位(还没有阅读下一行),所以我放弃了所有内容。最后,cin 有一个operator void *,所以它不能转换为布尔值。 @Marvin, cin &gt;&gt; num 如果用户键入失败,则在预期 int 时说“a”。它提供了一个转换运算符以允许将其隐式转换为void *。如果cin 处于错误状态,它将返回NULL。如果没有,它将返回对象。然后可以将其转换为布尔值:如果不是 NULL,则为 true,如果为 NULL,则为 false。然后循环可以使用它来评估它需要的布尔表达式。 @VaisakMohan,那也可以;这是完成最后一段的一种方法。但是,请注意是否要在一行上计算多个输入。如果您读取一行有效输入,转换它的第一部分,然后折腾其他部分,那将是一种耻辱。 getline 最适合实际的基于行的输入,而不是基于令牌的输入。您还必须注意空格,在您的转换中可能会以不同的方式处理。除此之外,逐行阅读意味着您必须进行转换错误检查(减去从流中丢弃错误输入),而不仅仅是后者。 另外,对于getline,在使用之前,您必须小心不要在流中留下杂散的换行符。如果使用getline,一般建议全押而不是尝试将其与基于令牌的输入混合匹配。【参考方案2】:

测试输入以查看它是否是您的程序所期望的。如果不是,请提醒用户他们提供的输入是不可接受的。

【讨论】:

【参考方案3】:

你可以通过 ASCII 值来检查,如果 ascii 值在 65 到 90 或 97 到 122 之间是字符。

【讨论】:

你怎么知道系统正在使用ASCII?【参考方案4】:

票数最高的答案很好地涵盖了解决方案。

除了那个答案,这可能有助于更好地可视化正在发生的事情:

int main()

    int input = 1;//set to 1 for illustrative purposes
    bool cinState = false;
    string test = "\0";
    while(input != -1)//enter -1 to exit
        cout << "Please input (a) character(s): ";//input a character here as a test
        cin >> input; //attempting to input a character to an int variable will cause cin to fail
        cout << "input: " << input << endl;//input has changed from 1 to 0
        cinState = cin;//cin is in bad state, returns false
        cout << "cinState: " << cinState << endl;
        cin.clear();//bad state flag cleared
        cinState = cin;//cin now returns true and will input to a variable
        cout << "cinState: " << cinState << endl;
        cout << "Please enter character(s): ";
        cin >> test;//remaining text in buffer is dumped here. cin will not pause if there is any text left in the buffer.
        cout << "test: " << test << endl;
    
    return 0;    

将缓冲区中的文本转储到变量中并不是特别有用,但它有助于可视化为什么需要cin.ignore()

我还注意到输入变量的更改,因为如果您在条件中使用输入变量进行 while 循环或 switch 语句,它可能会陷入死锁,或者它可能满足您之前的条件'不期望,这可能更容易调试。

【讨论】:

以上是关于如何处理错误的数据类型输入的主要内容,如果未能解决你的问题,请参考以下文章

如何处理重复条目的错误?

我如何处理有关输入的字符串大小超过字符数组的设定大小的错误?

如何处理未捕获的错误:对象作为 React 子错误无效

在flask中提交数据时如何处理错误

如何处理有关输入的字符串大小超出字符数组设置大小的错误?

处理 Mongoose 验证错误——在哪里以及如何处理?