调用std::stod触发std::invalid_argument异常:从文件读取双精度数值失败问题
调用std::stod触发std::invalid_argument异常:从文件读取双精度数值失败问题
我最近碰到一个特别诡异的问题:明明从文本文件里读取的数值字符串打印出来完全正常,但用std::stod转换成double时直接抛出了std::invalid_argument异常,程序直接崩溃了。
先给大家看看我的代码:
#include <iostream> #include <fstream> #include <sstream> int main() { std::ifstream file("data.txt"); std::string line, numStr; // 读取第一行 std::getline(file, line); // 提取行内第一个制表符分隔的数值 std::istringstream lineStream(line); std::getline(lineStream, numStr, '\t'); std::cout << "numStr= " << numStr << std::endl; // 输出看起来是正常的"numStr= 0.0014" double num = std::stod(numStr); // <-- 这里直接报错 }
我的data.txt里只有一行内容,两个数值用制表符分隔,内容是0.0014 0.9986。
运行代码后得到的输出是:
numStr= 0.0014 terminate called after throwing an instance of 'std::invalid_argument' what(): stod Aborted (core dumped)
更奇怪的是,打印出来的numStr看起来只有6个字符,但调用numStr.length()居然返回9,这明显不对!
折腾了半天调试后,我终于找到问题根源:这个文本文件的开头带有BOM(字节顺序标记)字符!这些字符是隐藏的,打印的时候看不到,但会被完整读取到字符串里,导致std::stod无法识别这是一个有效的浮点数格式,直接抛出了异常。
解决方法其实很简单:把文件重新保存为不带BOM的UTF-8格式(或者你需要的对应编码),再运行代码就完全正常了。
如果你的场景需要处理可能带BOM的文件,也可以在读取时手动跳过BOM:比如检查文件开头的字节,如果是UTF-8的BOM(0xEF, 0xBB, 0xBF),就先跳过这三个字节再读取后续内容。
备注:内容来源于stack exchange,提问作者Mathieu
相关产品推荐
相关产品推荐

