C++ string stream的EOF判定在不同编译运行环境下结果存在差异
问题根本原因
这个问题是C++输入流操作的经典错误导致的,核心在于错误使用while (!stream.eof())作为读取循环的判断条件,没有校验读取操作本身是否成功。
eof()标记的触发规则是:只有尝试读取操作失败、且失败原因是已经到达流末尾时,才会被置位,并非流刚好到达最后一个有效数据的位置时就自动置位。你当前的代码逻辑是先判断没到EOF就直接执行读取操作,再无条件把变量值存入vector,会出现以下错误流程:
- 读取完最后一个有效数值
1后,ss.eof()仍为false,会再次进入循环 - 本次
ss >> n操作因为没有有效数值可读取,执行失败,变量n的值会保留上一次读取的1 - 代码没有判断读取是否成功,直接把旧值
1存入vector,最终就出现了重复的最后一位
不同环境表现不同的原因
两个环境表现差异和文本文件的换行符格式有关:
- 你所用的训练数据大概率是Windows下生成的,行尾为Windows标准的
CRLF(\r\n)格式 - MinGW是Windows原生编译器,读取文本模式文件时会自动把
CRLF转换为LF,getline读取时会丢弃换行符,最终得到的line字符串末尾没有多余字符,该错误场景下部分编译实现刚好不会触发重复写入的问题,属于巧合的正常表现 - WSL是Linux环境,默认不会自动转换Windows格式的换行符,
getline读取到的行末尾会残留\r空白符,让流在读完最后一个数值后仍判断有剩余内容,更易触发这个错误逻辑的异常表现
修复方案
把读取操作直接放到循环判断条件中,利用输入流的重载布尔判定,只有读取成功时才进入循环处理:
unsigned n; while (ss >> n) { topology.push_back(n); }
这种写法会自动判断>>操作是否成功,读取失败(包括到达末尾)时直接跳出循环,完全避免上述问题。
内容的提问来源于stack exchange,提问作者Jayce444
相关产品推荐
相关产品推荐

