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

如何修复C++解析带引号CSV时的std::out_of_range异常?

解决读取带引号CSV时的std::out_of_range异常问题

你遇到的这个越界异常,核心原因是程序尝试解析空行或者超出字段范围的内容,而且getQuotedString函数没有处理"找不到引号"的边界情况,直接执行了非法的字符串截取操作。

具体触发场景

当getline读取到文件末尾的空行(比如文件最后多了一个换行符),currentLine会变成空字符串,但你的循环依然会进入处理逻辑,调用getQuotedString。此时index初始为0,line.find('"', 1)找不到任何引号,返回std::string::npos,但代码没有处理这个结果,继续执行substr(endIndex+1, ...)——空字符串长度为0,起始位置1显然超出范围,直接抛出std::out_of_range。

另外,原getQuotedString在处理最后一个字段后,盲目把index设置为index+2,如果是最后一个字段,后面没有逗号和引号,index会直接超出字符串长度,后续操作也会出问题。

修复方案

我分两步给你完善代码:

1. 完善getQuotedString的错误与边界处理

让函数能识别读取失败的情况,并且正确处理最后一个字段的后续位置:

bool getQuotedString( string& line, int& index, string& subString) {
    // 先检查当前索引是否已经超出字符串范围
    if (index >= line.size()) {
        subString.clear();
        return false;
    }

    // 确保从引号开始(如果当前位置不是引号,先找到下一个引号)
    if (line[index] != '"') {
        index = line.find('"', index);
        if (index == string::npos) {
            subString.clear();
            return false;
        }
    }

    // 找到当前引号对应的结束引号
    int endIndex = line.find('"', index + 1);
    if (endIndex == string::npos) {
        subString.clear();
        return false;
    }

    // 提取引号间的内容
    subString = line.substr(index + 1, endIndex - index - 1);
    cout << subString << endl;

    // 更新索引到下一个字段的起始位置:跳过结束引号,有逗号再跳逗号
    index = endIndex + 1;
    if (index < line.size() && line[index] == ',') {
        index++;
    }

    return true;
}

2. 在readFile中增加空行检查与读取结果校验

避免处理空行,并且确保只有所有字段都读取成功时,才计入有效条目:

void readFile( ifstream& inFile, vector<itemType>& item, int& itemNumber) {
    string currentLine;
    int indexDef = 0;
    while(getline(inFile, currentLine) && itemNumber < MAX_DB_SIZE){
        // 跳过空行,直接进入下一次循环
        if (currentLine.empty()) {
            continue;
        }

        indexDef = 0;
        bool allFieldsRead = true;
        // 逐个读取字段,只要有一个失败就标记为无效条目
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].NDBNumber);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].longName);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].dataSource);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].upc);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].manufacturer);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].dataModified);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].dataAvailable);
        allFieldsRead &= getQuotedString(currentLine, indexDef, item[itemNumber].ingredients);

        // 只有所有字段都读取成功,才增加计数
        if (allFieldsRead) {
            itemNumber++;
        }
    }
}

改进说明

  • 空行过滤:直接跳过无内容的空行,避免无效解析操作。
  • 错误校验:每个字段读取都检查返回值,确保vector中只存入完整的有效条目。
  • 边界处理:getQuotedString现在会检查索引是否越界,并且正确处理最后一个字段后没有逗号的情况,不会盲目设置索引位置。

这样修改后,程序就能稳定处理你的测试文件,不会再触发越界异常了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:25:16