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

如何编写容错性更强的C++用户输入代码?排查现有错误处理

代码错误处理问题排查

原代码存在以下几处关键问题,会导致坏输入引发程序崩溃或逻辑异常:

  • 初始输入noOfInput无校验:若用户输入非整数(如字符串、小数),std::cin >> noOfInput会失败,noOfInput值未定义,后续循环会基于无效值执行,可能引发无限循环或非法内存访问。
  • 输入错误时循环计数器未回退:某一行输入无效时,程序仅提示重试但i仍会自增,导致本该重新输入的条目被跳过,最终收集的条目数量不足。
  • 字符串查找结果未做有效性检查:find_first_not_of、find等函数可能返回std::string::npos(未找到目标),原代码直接用该结果执行substr,会触发未定义行为(程序崩溃)。
  • 异常捕获范围不全:std::stoi和std::stod除了抛出std::logic_error子类,还会抛出std::out_of_range(数值超出类型范围),原代码未捕获该异常,会导致程序崩溃。
  • 错误输入后未重新获取输入:清理cin错误状态后直接进入下一次循环,未让用户重新输入当前条目的内容。
  • 未限制noOfInput的合理范围:若用户输入负数或极大值,会导致循环逻辑异常(负数时循环不执行,极大值时可能耗尽内存)。
代码优化方案

针对上述问题,从输入校验、错误恢复、边界检查等方面优化代码,提升容错性:

核心优化点

  • 校验初始输入的有效性,确保noOfInput是1到合理最大值之间的整数。
  • 输入错误时回退循环计数器,让程序重新处理当前条目。
  • 检查所有字符串查找结果,若返回npos则直接触发错误处理。
  • 扩大异常捕获范围,覆盖stoi/stod的所有异常类型。
  • 错误后重新获取输入,确保用户有机会修正输入。
  • 限制最大条目数,避免恶意输入耗尽系统资源。

优化后的代码

#include <iostream>
#include <string>
#include <vector>
#include <limits>
#include <stdexcept>

// 补充原代码缺失的itemInfo定义
struct itemInfo {
    int quantity;
    std::string name;
    double actualPrice;
};

int main()
{
    int noOfInput;
    const int MAX_ITEMS = 1000; // 限制最大条目数,避免恶意输入
    // 循环获取有效的产品数量
    while (true) {
        std::cout << "请输入产品数量(1-" << MAX_ITEMS << "):";
        if (std::cin >> noOfInput && noOfInput > 0 && noOfInput <= MAX_ITEMS) {
            break;
        } else {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "输入无效,请输入1到" << MAX_ITEMS << "之间的整数。\n";
        }
    }

    std::string line;
    std::vector<itemInfo> itemsVec;
    itemsVec.reserve(noOfInput); // 预分配内存,提升性能

    // 循环获取产品信息,仅在输入有效时递增计数器
    for (auto i = 0; i < noOfInput; ) {
        std::cout << "请输入第" << (i+1) << "个产品(格式:数量 名称 at 价格):";
        std::getline(std::cin >> std::ws, line);

        // 检查输入读取是否失败
        if (!std::cin) {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "输入读取失败,请重新输入。\n";
            continue;
        }

        try {
            itemInfo item;
            size_t start, stop;

            // 解析数量:检查空白处理和有效性
            start = line.find_first_not_of(" \t");
            if (start == std::string::npos) {
                throw std::invalid_argument("输入为空,缺少数量信息");
            }
            stop = line.find_first_of(" \t", start);
            if (stop == std::string::npos) {
                throw std::invalid_argument("缺少产品名称和价格信息");
            }
            item.quantity = std::stoi(line.substr(start, stop - start));
            if (item.quantity <= 0) {
                throw std::invalid_argument("数量必须是正整数");
            }

            // 解析名称:检查分隔符和空值
            start = line.find_first_not_of(" \t", stop + 1);
            if (start == std::string::npos) {
                throw std::invalid_argument("缺少产品名称");
            }
            stop = line.find(" at ", start);
            if (stop == std::string::npos) {
                throw std::invalid_argument("格式错误,未找到\" at \"分隔符");
            }
            item.name = line.substr(start, stop - start);
            if (item.name.empty()) {
                throw std::invalid_argument("产品名称不能为空");
            }

            // 解析价格:检查有效性和范围
            start = line.find_first_not_of(" \t", stop + 4);
            if (start == std::string::npos) {
                throw std::invalid_argument("缺少价格信息");
            }
            item.actualPrice = std::stod(line.substr(start));
            if (item.actualPrice <= 0) {
                throw std::invalid_argument("价格必须大于0");
            }

            // 所有校验通过,添加到容器并递增计数器
            itemsVec.push_back(item);
            i++;
        }
        catch (const std::exception& ex) {
            std::cout << "输入错误:" << ex.what() << ",请重新输入。\n";
        }
    }

    // 可选:输出已收集的产品信息用于验证
    std::cout << "\n已成功输入" << itemsVec.size() << "个产品:\n";
    for (const auto& item : itemsVec) {
        std::cout << item.quantity << " " << item.name << " at " << item.actualPrice << "\n";
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者Falcon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 12:21:31