C++ try/catch程序无法触发第二个catch块问题求助
C++输入验证异常捕获问题修复
问题描述
编写了一个处理用户输入的try/catch程序,要求输入1-4的数字,需分别处理非数字输入(抛出std::invalid_argument)和超出范围输入(抛出std::out_of_range)。但测试超出范围输入时,总是触发std::invalid_argument的捕获逻辑,无法正确触发std::out_of_range的catch块。
原代码:
// C++ /*For context, choice is an integer from User input that is supposed to be a number 1-4.*/ void search() { int choice; std::cout << "Search by:\n1:Title\n2:Year\n3:Actor\n4:Rating\n"; try { std::cin >> choice; if(!isdigit(choice)) { throw std::invalid_argument("Please type a number. \n"); } if(choice >= 5 || choice <= 1) { throw out_of_range("Please input a number between 1 and 4"); } } catch(std::out_of_range const& e){ std::cout << e.what(); cin.clear(); } catch(std::invalid_argument const& e) { std::cout << e.what(); } }
错误原因分析
isdigit用法错误:isdigit用于判断字符的ASCII值是否为数字(比如字符'1'的ASCII码是49,isdigit(49)才会返回真),但这里choice是int类型,存储的是输入数字的数值(比如输入1时,choice是1),isdigit(1)判断的是ASCII码1对应的字符,不是数字,所以会错误触发std::invalid_argument。- 非数字输入处理逻辑缺失:当用户输入非数字时,
std::cin >> choice会执行失败,此时choice值未定义,且cin会进入错误状态,后续的范围判断逻辑完全混乱。 - 范围判断条件错误:
choice <= 1会把合法输入1也判定为超出范围,应该改为choice < 1。 out_of_range缺少命名空间前缀:未加std::前缀会导致编译错误(除非全局引入了std命名空间)。
修正后的代码
#include <iostream> #include <stdexcept> #include <limits> // 用于清除输入缓冲区 void search() { int choice; std::cout << "Search by:\n1:Title\n2:Year\n3:Actor\n4:Rating\n"; try { // 检查输入是否为有效整数 if (!(std::cin >> choice)) { // 清除cin的错误状态 std::cin.clear(); // 忽略缓冲区中剩余的无效输入,避免影响后续操作 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); throw std::invalid_argument("Please type a number.\n"); } // 检查输入范围是否在1-4之间 if (choice < 1 || choice > 4) { throw std::out_of_range("Please input a number between 1 and 4.\n"); } // 输入合法时的后续逻辑 std::cout << "Valid choice: " << choice << "\n"; } catch (const std::out_of_range& e) { std::cout << e.what(); } catch (const std::invalid_argument& e) { std::cout << e.what(); } } int main() { search(); return 0; }
修正要点说明
- 用
std::cin >> choice的返回值判断输入是否有效,替代错误的isdigit判断逻辑。 - 输入无效时,先清除cin错误状态并忽略缓冲区垃圾数据,避免影响后续输入操作。
- 修正范围判断条件,确保1-4为合法输入区间。
- 给
out_of_range添加std::前缀,符合标准库命名规范。
内容的提问来源于stack exchange,提问作者Kohaya3
相关产品推荐
相关产品推荐

