C++停车计费程序:数字加字母输入绕过验证导致程序异常求助
问题描述
测试C++停车计费程序时,输入验证逻辑存在以下问题:
- 输入以数字开头后跟字母(如
45Gge)时,验证会通过,程序直接结束,跳过询问是否继续的环节; - 输入以字母开头(如
gsdf)或字母数字混合且字母在前(如ggs52)时,验证失败的循环能正常工作。
需要明确数字加字母输入绕过验证的原因,并修复验证逻辑,确保所有非纯数字输入都被拦截。
原程序代码:
#include <iostream> #include <iomanip> #include <limits> int main() { float fee = 0.0; float hours = 0.0; float minFee = 2.50; char choice; std::cout << std::setprecision(2) << std::fixed; do { std::cout << "Enter parking hours: "; std::cin >> hours; while(std::cin.fail()) { std::cout << "\nIncorrect Input! Numbers Only.\nTry Again."; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); std::cout << "\n\nEnter parking hours: "; std::cin >> hours; } if(hours <= 3) { fee = minFee; } else if(hours > 3 && hours < 24) { fee = (((hours - 3) * 1) + minFee); } else { fee = 20.00; } std::cout << "\nTotal Cost: $" << fee; std::cout << "\n\nWould you like to pay another fee? (Y or N): "; std::cin >> choice; while(choice != 'y' && choice != 'n') { std::cout << "\nIncorrect Input! \"Y\" or \"N\" Only.\nTry Again."; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); std::cout << "\n\nWould you like to pay another fee? (Y or N): "; std::cin >> choice; } }while(choice == 'y'); std::cout << "\nThankyou for your payment." << std::endl; return 0; }
问题原因
C++中std::cin >> float的行为是从输入流中提取开头连续的有效数字字符:只要输入开头有合法数字(整数或小数),就会成功将数字部分赋值给变量,剩余的非数字字符会留在输入缓冲区中,不会触发std::cin.fail(),因此绕过了当前的验证逻辑。
后续读取choice时,缓冲区中残留的非数字字符会被直接读取,导致choice不符合y/n的要求,程序进入choice的验证循环,甚至因缓冲区残留内容导致流程异常,看起来像是跳过了询问环节。
修复方案
要确保输入为纯数字,需读取整行输入并验证全部内容是否符合浮点数格式,具体步骤:
- 用
std::getline读取整行输入,避免残留字符留在缓冲区; - 使用
std::istringstream将字符串转换为浮点数,并检查转换后是否无剩余字符; - 仅当整行输入完全符合浮点数格式时,才通过验证。
修复后的代码:
#include <iostream> #include <iomanip> #include <limits> #include <sstream> #include <string> int main() { float fee = 0.0; float hours = 0.0; float minFee = 2.50; char choice; std::cout << std::setprecision(2) << std::fixed; do { std::string input; bool validHours = false; while (!validHours) { std::cout << "Enter parking hours: "; std::getline(std::cin, input); std::istringstream iss(input); // 转换为浮点数且无剩余字符,才视为有效输入 if (iss >> hours && iss.eof()) { validHours = true; } else { std::cout << "\nIncorrect Input! Numbers Only.\nTry Again.\n\n"; } } if(hours <= 3) { fee = minFee; } else if(hours > 3 && hours < 24) { fee = (((hours - 3) * 1) + minFee); } else { fee = 20.00; } std::cout << "\nTotal Cost: $" << fee; bool validChoice = false; std::cout << "\n\nWould you like to pay another fee? (Y or N): "; while (!validChoice) { std::getline(std::cin, input); // 验证输入为单个Y/y或N/n字符 if (input.size() == 1 && (input[0] == 'y' || input[0] == 'n')) { choice = input[0]; validChoice = true; } else { std::cout << "\nIncorrect Input! \"Y\" or \"N\" Only.\nTry Again.\n\n"; std::cout << "Would you like to pay another fee? (Y or N): "; } } }while(choice == 'y'); std::cout << "\nThankyou for your payment." << std::endl; return 0; }
关键修改说明
- 使用
std::getline读取整行输入,确保捕获所有输入内容,彻底避免缓冲区残留问题; - 通过
std::istringstream结合iss.eof()验证输入是否为纯浮点数,无多余字符; - 同样用
getline处理choice输入,确保输入为单个合法字符,避免之前的输入残留干扰。
内容的提问来源于stack exchange,提问作者Another Channel
相关产品推荐
相关产品推荐

