C++逻辑运算符组合多条件实现输入校验失效问题
C++ 输入校验合并写法失效问题
问题相关原代码
#include <iostream> int main(int, char **) { using namespace std; int days; cout<<"How many days did you work this month? "; cin>>days; while(!(cin>>days) || (days<1) || (days>31)){ if(!(cin>>days)){ cout<<"Number of days should be... well, a number. Please re-enter: "; cin.clear(); cin.ignore(100,'\n'); } else if(days<1 || days>31){ cout<<"Number of days should be between 1 and 31. Please re-enter:"; cin>>days; } } return 0; }
预期实现逻辑
- 类型校验:用户输入非整数内容时,清空输入流错误状态、跳过非法输入内容,提示重新输入,避免程序死循环
- 范围校验:输入的整数需落在合法工作天数区间内(需求提及预期区间为130,原代码写为131可按需调整),不满足区间要求时提示重新输入
- 实际现象:类型校验功能正常,但输入任何数字都不会触发范围校验,无对应提示输出。拆分两个独立循环分别做两类校验时功能正常,合并到同一个while循环后失效。
错误根因
代码对cin >> days的冗余重复调用是核心问题,整个输入读取流程完全错位:
- 打印初始输入提示后,第一次调用
cin>>days读取用户输入,但读取到的值没有做任何校验,直接进入while循环判断逻辑 - while循环的判断条件中第二次调用
cin>>days,会阻塞等待用户输入新值,第一次读取到的输入直接被丢弃,根本没有进入校验流程 - 进入循环体后,类型错误分支、范围错误分支中又分别第三次、第四次调用
cin>>days读取输入,进一步打乱输入流读取顺序:用户输入的合法值会被这些多余的读取操作直接吞掉,永远无法触发范围校验逻辑,最终表现为输入数字后无任何对应响应。
修正方案
将输入读取动作统一收拢到循环判断处,每次循环仅做一次读取:先判断读取是否成功(即输入类型是否为整数),类型合法后再判断取值范围,不要在条件判断、分支逻辑中重复编写读取输入的代码。
修正后可正常运行的代码如下:
#include <iostream> #include <limits> int main(int, char **) { using namespace std; int days; cout << "How many days did you work this month? "; // 仅在循环条件处做单次读取,移除所有冗余的cin>>days调用 while (!(cin >> days) || days < 1 || days > 31) { if (cin.fail()) { // 输入类型不匹配 cout << "Number of days should be... well, a number. Please re-enter: "; cin.clear(); // 跳过当前行所有剩余非法字符,替代原代码写死100长度的不严谨写法 cin.ignore(numeric_limits<streamsize>::max(), '\n'); } else { // 类型匹配但取值超出范围 cout << "Number of days should be between 1 and 31. Please re-enter: "; } } // 此处可添加校验通过后的业务逻辑 return 0; }
若实际需求的合法区间为1~30,只需将判断条件中的
days > 31修改为days > 30,同时同步修改范围提示的文案即可。
内容的提问来源于stack exchange,提问作者Celephais Hyde
相关产品推荐
相关产品推荐

