当cin的输入是'点'时,循环到无穷大

时间:2011-12-13 10:38:37

标签: c++ loops while-loop cin

我在使用cin方法获取变量时遇到问题。当输入是一个数字时没有问题,但是当它是一个像[。]这样的特殊字符时, whileloop循环到无限。 我做错了什么?

cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
    cin >> *race;
    while(*race<1||*race>3)
    {
    system("cls");
    cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
    cin >> *race;
    }

我搜索了答案,我应该冲洗缓冲区,但我不知道该怎么做。我是c ++的新手.Thanx

4 个答案:

答案 0 :(得分:2)

race成为一个字符,然后您就可以:

while (*race < '1' || *race > '3')

这可能就是你想要实现的目标。

说明:

当你cin >>进入int时,它会将给定的ASCII字符串转换为整数值。 .没有整数含义,因此未将其读入race并设置failbit - 进一步&gt;&gt; s为无操作,直到您清除它们为止。但是,如果您cin >>进入char并将其与其他char(实际上是他们的ASCII代码)进行比较,您就可以毫无困难地进行检查。

答案 1 :(得分:1)

除了接受的解决方案之外的其他解决方案是清除cin的failbit并忽略最后一个输入,如下所示:

cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
    // Clears the state of cin to be in good state
    cin.clear();
    // Ignores the last input read so that it's not read back again
    cin.ignore();
    system("cls");
    cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
    cin >> *race;
}

答案 2 :(得分:1)

此示例完全重现您的问题:

#include <iostream>

int main()
{
    int i = 5;
    while (i < 1 || i > 3)
    {
        std::cin >> i;
    }
}

这里发生了什么:当operator>>无法读取整数时(例如,当您键入一个点并按回车键时),无论您输入的是什么都会在流中停留,包括换行符。 因此,在while循环的下一次迭代中,下一个输入已经存在,并且因为它不是有效整数,所以循环永远不会中断。 您需要确保在operator>>失败时清空流并清除已设置的所有错误标志。

#include <iostream>
#include <limits>

int main()
{
    int i = 5;
    while (i < 1 || i > 3)
    {
        if (!(std::cin >> i))
        {
            // clear streams internal error flags
            std::cin.clear();
            // ignore what's left in the stream, up to first newline character
            // or the entire content, whichever comes first
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
}

答案 3 :(得分:1)

您的代码存在一些问题。首先是你没有 验证您的输入是否成功;正确的条件 while应该是:

while ( !cin || (*race < 1 || *race > 3) )

如上所述,如果输入失败(这就是你发生的事情 输入'.',假设race的类型为int*),然后*race 包含其先前的值,无论是什么。

第二个问题是如果你从cin收到错误,你就不会清除 它。一旦流处于错误状态,它就一直保持这种状态直到你 明确地说清楚它。如果cin失败,则需要执行:

cin.clear();

循环中的某个地方。

第三是如果cin失败,则不提取其中的字符 使它失败,因此在清除错误状态后,您需要 提取它。鉴于你构建对话框的方式,你可能 想要忽略所有事情,直到行尾:

cin.ignore( INT_MAX, '\n' );

即使cin未在循环中失败,您也可能希望这样做 (如果因*race < 1 || *race > 3条件而输入)或在 成功的例子。或者,您可能想转换到阅读线, 并确保该行仅包含该字符后面的空格 你对此感兴趣。

这个最后的解决方案是我将采用的解决方案,因为它处理得很好 以上所有问题。所以我的代码看起来像:

//  return -1 on error in input,
//  throw exception on (unexpected) end of file
int
getRace( std::istream& source )
{
    std::string line;
    if ( !std::getline( source, line ) ) {
        throw std::ios_base::failure( "Unexpected end of file" );
    }
    std::istringstream tmp( line );
    int results;
    return tmp >> results >> std::ws && tmp.get() == EOF
        ? results
        : -1;
}

//  ...
int race = -1;
while ( race < 0 ) {
    std::cout << "What is your race\n"
                 "1. Human\n"
                 "2. Troll\n"
                 "3.  Zombie\n" << std::flush;
    race = getRace( std::cout );
    if ( race < 0 ) {
        std::cout << "Wrong choice" << std::endl;
    }
}

请注意,通过输入一行,可以避免任何问题 重置格式错误,跳过错误输入或重新同步 出现错误。