C++ 而带有try-catch的循环在输入错误时失败

C++ 而带有try-catch的循环在输入错误时失败,c++,try-catch,iostream,while-loop,C++,Try Catch,Iostream,While Loop,我似乎不明白为什么在得到非int输入后会陷入循环。我试过cin.flush(),它似乎不存在,cin.clear(),它似乎应该可以工作,甚至在阅读了其他人关于它工作的帖子后,我试过了cin.sync(),但似乎没有多大意义。还尝试了cin.bad() 非常感谢你的帮助 请输入第一个数字:f 对不起,我不认为这是一个数字 请输入第一个号码:对不起, 我不认为这是一个数字 请输入第一个号码:对不起, 我不认为这是一个数字 请输入第一个号码:对不起, 我不认为这是一个数字 请输入第一个号码:对不起,

我似乎不明白为什么在得到非int输入后会陷入循环。我试过cin.flush(),它似乎不存在,cin.clear(),它似乎应该可以工作,甚至在阅读了其他人关于它工作的帖子后,我试过了cin.sync(),但似乎没有多大意义。还尝试了cin.bad()

非常感谢你的帮助

请输入第一个数字:f 对不起,我不认为这是一个数字

请输入第一个号码:对不起, 我不认为这是一个数字

请输入第一个号码:对不起, 我不认为这是一个数字

请输入第一个号码:对不起, 我不认为这是一个数字

请输入第一个号码:对不起, 我不认为这是一个数字?对不起, 你不会再有机会了。按 任何继续的钥匙

#包括
使用名称空间std;
int main(){
整数输入;
int=1;
int结果;
同时(试图进入;
if(cin.fail())
抛出“对不起,我不认为这是一个数字?”;
如果(条目<0)
抛出“对不起,没有负数。试试别的?”;
不能进入;
cin.clear();
cin.get();
}
捕获(字符*错误){
法庭(5)

cout为什么要对异常执行此操作?您不会在输入时终止程序,因此不应该抛出异常


只需打印出您的错误消息并尝试再次读取。

看起来您最好使用
iostream
的本机异常。使用

cin.exceptions( ios::failbit );

try {
   …
} catch( ios_base::failure & ) {
  cin.clear();
  …
}

永远不要抛出非源于
std::exception
的对象,尤其是像
char*

这样的本机类型。在这种情况下,如果用户给出无效输入,您应该仔细考虑该怎么办。通常在这种情况下,最好的解决方案是从输入中读取一行并将其丢弃

尝试将
cin.clear()
std::cin.ignore(std::numeric\u limits::max(),'\n');
放在catch子句中。
cin.clear()
清除cin.ignore()中的故障状态,而
cin.ignore()
丢弃输入缓冲区中等待的其余行


(是的,您可能应该重新考虑异常的使用)。

异常应该用于处理异常、意外的情况。来自用户的错误输入既不是意外的,也不是例外的——这或多或少是正常现象。就我个人而言,我倾向于完全忽略最糟糕的输入(当无法阻止时)。当(而且只有当)他们反复输入一些不可用的东西时,才值得向他们指出。因此,我倾向于编写如下代码:

char ch;
int attempts = 0;

std::cout << "Please enter the first number: ";
do { 
    cin >> ch;
    attempts++;
    if (attempts > 5)
        std::cerr << "The only allowable inputs are '0' through '9'\n";            
} while (cin.good() && !isdigit(ch));
int first_number = ch - '0';
charch;
int=0;
std::cout>ch;
尝试++;
如果(尝试次数>5次)
std::cerr处理基于行的输入验证的最直接(但通常不是最简单也不是最快)的方法是始终一行一行地读取它。这种方法在任何情况下都不会在缓冲区中留下额外的空白(如换行符),并且丢弃错误的输入也是相当自动的

// Infinite loop for retrying until successful
while (true) {
    // Ask the user something
    std::cout << prompt;
    // Read the answer (one full line)
    std::string line;
    if (!std::getline(std::cin, line))
      throw std::runtime_error("End of input while expecting a value");
    // Put the line read into iss for further parsing
    std::istringstream iss(line);
    int val;
    // Read val from iss and verify that reading was successful and
    // that all input was consumed
    if (iss >> val && iss.get() == EOF) return val;
    std::cout << "Invalid input, try again!\n";
}
//无限循环,用于重试直至成功
while(true){
//询问用户一些问题
std::cout>val&&iss.get()==EOF)返回val;

std::cout我的问题是阻止对cin>>号的字符输入

此错误导致出现“无限”循环,显示我的提示cout fi_game_sec;cin.clear();}//(2) catch(…)//超出范围) { fi_game_sec=-1;
除非您特别想发出信号,以免它在错误处理中被捕获(C++0x建议的线程API的中断支持使用此技巧中断线程)-1.进行建议的更改不会解决当前的问题,这与引发的异常类型无关,也与异常是由流手动还是自动引发无关。@Rob:但我在示例代码中解决了当前的问题……不,您没有。调用
clear
重置错误状态,但缓冲区中仍存在错误输入。读取字符是读取数字(可能不止一个数字)的一种非常糟糕的方式。@Tronic:当然,这就是为什么我说您可能要读取整行并尝试转换。然而,这样做的原因是(至少在正常情况下)用户可以输入的任何内容都将被成功读入字符,因此它们不会停留在输入缓冲区中,从而导致OP询问的问题。-1.忽略手头的问题,这就是代码“在获得非int输入后陷入循环”的原因立即打印错误并使用
continue
将产生相同的结果。正如其他人所说,您的异常使用是不合适的。将
throw
替换为“std::cerr可能与我的一个类中的问题的解决方案重复。谢谢!:)(是的,我在源代码中添加了指向您的评论的链接)
// Infinite loop for retrying until successful
while (true) {
    // Ask the user something
    std::cout << prompt;
    // Read the answer (one full line)
    std::string line;
    if (!std::getline(std::cin, line))
      throw std::runtime_error("End of input while expecting a value");
    // Put the line read into iss for further parsing
    std::istringstream iss(line);
    int val;
    // Read val from iss and verify that reading was successful and
    // that all input was consumed
    if (iss >> val && iss.get() == EOF) return val;
    std::cout << "Invalid input, try again!\n";
}
template <typename Val> void input(std::string const& prompt, Val& val) {
    // (the above code goes here, slightly adjusted)
}

int main() {
    int w;
    double l;
    input("Enter weight in kg: ", w);
    input("Enter length in m: ", l);
    std::cout << "BMI: " << w / (l * l) << std::endl;
}
double fi_trap_d()    // function to return a valid range double catching errors  
{  
  double fi_game_sec;  
//-------------------------------------------  
   do  
   {  
    fi_game_sec = -1;  
    cout << fi_game_sec_c;  

        //------------------------------  
    cin.ignore();  // (1)
        //------------------------------  

    try  
    {  cin >> fi_game_sec;  cin.clear(); }  // (2)
        catch (...)  //out_of_range)  
      {  
        fi_game_sec = -1;  
        cout << " Dis am an error!\n";  
                     // just loop back as we asked for a number  
      }  
    } while (fi_game_sec < 1);  
//-------------------------------------------  
  return fi_game_sec;  
}