如何修复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
相关产品推荐
相关产品推荐

