C++使用stoi转换读取的文件行时抛出invalid_argument异常中止
C++ 数据集读取函数stoi转换异常修复
异常根因
报错libc++abi: terminating with uncaught exception of type std::invalid_argument: stoi: no conversion由两个逻辑错误共同导致:
- 读取逻辑和输入格式不匹配:当前代码每读取一行就直接调用
stoi转整数,但输入文件每4行对应1条骑手记录,内容依次为整数类型的号码布、字符串类型的姓名、浮点数类型的距离、字符串类型的时间。姓名、时间这类非纯数字内容传给stoi时,函数找不到可转换的数字序列,就会抛出无效参数异常。 - 流状态判断时机错误:
while (in)判断是在读取操作之前执行,当文件读到末尾时,getline会读取失败返回空字符串,后续代码依然会对空字符串调用stoi,同样会触发转换异常。
另外代码中定义的const int dataLength = 5没有实际使用,和实际每条记录占4行的输入格式也不匹配。
修复方法
- 调整循环判断逻辑:将
getline操作直接放在循环条件中,读取失败时直接退出循环,避免对无效读取的内容做转换。 - 对齐输入格式:每成功读取1条记录的第一行(号码布)后,按顺序读取后续3行内容,分别做对应类型的转换赋值,不要对非整数字段调用
stoi。 - 增加数组越界防护:传入结果数组的最大容量,避免数据量超出数组长度时发生内存越界写入。
修复后的完整代码如下:
void readDataset(ifstream &in, Results results[], int maxArrayLen, int &size) { size = 0; string line; // 读取成功且数组未满时持续处理 while (getline(in, line) && size < maxArrayLen) { // 读取号码布(整数) results[size].bibNumber = stoi(line); // 读取姓名(字符串) getline(in, line); results[size].name = line; // 读取距离(浮点数) getline(in, line); results[size].distance = stod(line); // 读取完赛时间(字符串) getline(in, line); results[size].time = line; // 单条记录处理完成,计数+1 size++; } in.close(); }
调用该函数时,需要额外传入results数组的实际最大长度作为maxArrayLen参数,防止数组越界。
内容的提问来源于stack exchange,提问作者Brandon A Bustamante
相关产品推荐
相关产品推荐

