You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的验证循环,甚至因缓冲区残留内容导致流程异常,看起来像是跳过了询问环节。

修复方案

要确保输入为纯数字,需读取整行输入并验证全部内容是否符合浮点数格式,具体步骤:

  1. 用std::getline读取整行输入,避免残留字符留在缓冲区;
  2. 使用std::istringstream将字符串转换为浮点数,并检查转换后是否无剩余字符;
  3. 仅当整行输入完全符合浮点数格式时,才通过验证。

修复后的代码:

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:35:27