从用户读取整数

3

我正在尝试从终端读取一个整数。这是我的代码:

int readNumber()
{
    int x;
    std::cin >> x;
    while(std::cin.fail())
    {
        std::cin.clear();
        std::cin.ignore();
        std::cout << "Bad entry. Enter a NUMBER: ";
        std::cin >> x;
    }
    return x;
}

每当我运行这段代码时,我会遇到以下问题:
Type in the number for the newsgroup that shall be deleted:
joöä
Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: 8

为什么会多次输出"bad entry"? 如果我去掉std::cin.clear();或者std::cin.ignore();,程序就会一直输出Enter a NUMBER: Bad entry. 有人可以解释一下这是为什么吗?

尝试在你的while循环中加入一个break语句,这应该可以解决你的问题。 - rockinfresh
我在 if(cin>>x) 语句中添加了一个 break,但没有起到作用。 - user2975699
@user2975699,简短的回答是你在每个字符上都失败了,并打印了每个失败的错误消息。 - merlin2011
@merlin2011,我也是这么认为的,但错误信息出现了6次,而不是4个字符。 - rockinfresh
@rockinfresh,我认为它可能是逐字节读取的,而且至少有两个字符不是ASCII码,因此它们可能每个占用两个字节。 - merlin2011
显示剩余2条评论
4个回答

3

这实际上是一个部分重复的问题,与旧问题相似,但表述不同,所以我会在这里简要回答。

  1. 如果没有这两行代码,你会得到无限的打印,因为需要使用cin.clear()来清除cin.fail()正在读取的错误标志。有关详细信息,请参见链接的问题。
  2. 即使有这些代码,为什么它仍然会打印多次?当你执行std::cin >> x;时,你的代码将读取输入中的第一个字符,并尝试将其解析为int。它会失败,然后在循环的下一次迭代中,它将尝试解析下一个字符并再次失败。对于每个失败(也就是你输入的每个字符),它都会打印Bad entry. Enter a NUMBER:。如果你输入一些较少字符的错误输入,你会明白我的意思。

有多种方法可以解决这个问题,但一个简单的解决方法是将整个输入读入一个字符串中,并尝试解析它,而不是直接使用cin读入一个int。这里是一些示例代码,需要使用各种编译器相关标志来编译C++11。我已经测试了你的输入并且它似乎达到了你想要的效果。

#include <iostream>
#include <string>
#include <stdexcept>

bool tryParse(std::string& input, int& output) {
    try{
        output = std::stoi(input);
    } catch (std::invalid_argument) {
        return false;
    }
    return true;
}
int main(){
    std::string input;
    int x;

    getline(std::cin, input);

    while (!tryParse(input, x))
    {
        std::cout << "Bad entry. Enter a NUMBER: ";
        getline(std::cin, input);
    }
    return x;
}

1

无论如何,尝试一下这个......由于我直接在stackoverflow中输入,可能会有编译错误。

int readNumber()
{
   int x=0; 
   while(true)
   {
        std::cin >> x;
        if(!std::cin.fail()){
            break;
        }
        else{
            std::cout << "Bad entry. Enter a NUMBER: " << std::endl;
            std::cin.clear();
            std::cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
        }
    }
 }

1
int main() {
    char* input;
    std::cin >> input;
    int x = std::atoi(input);
    while(x == 0 && strcmp(input, "0") != 0) {
        std::cout << "Bad entry. Enter a NUMBER: ";
        std::cin >> input;
        x = std::atoi(input);
    }
    return x;
}

请注意,当您有3个非整数字符时,它将重复3次,当您有5个时,它将重复5次。这是因为cin会尝试第一个字符,失败,尝试第二个字符,失败,以此类推,直到解析完所有输入字符。

0

cin.fail() 返回 true 如果最后一次的 cin 命令失败了,否则返回 false。

尝试使用这个替代方案:

    while(1)
    {
        std::cin >> x;
        if (!std::cin.fail()) break;
        std::cin.clear();
        std::cin.ignore(10000,'\n');
        std::cout << "Bad entry. Enter a NUMBER: ";
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接