读取PGM文件像素数据时stoi转换报错的问题排查
问题解决:PGM文件像素读取时stoi转换错误
问题根源
你当前用getline(ss, value, ' ')按单个空格分割像素值的方式存在缺陷:ASCII格式的PGM文件中,像素值之间可能存在多个连续空格、制表符甚至换行,这种分割方式会提取出空字符串,传给stoi时就会触发invalid_argument异常。
解决方案
直接利用std::stringstream的>>运算符,它会自动跳过所有空白字符(包括连续空格、制表符、换行),并且只读取有效的数字内容,无需手动处理空格分割,也避免了空字符串的问题。同时可以直接读取int类型,省去stoi的转换步骤。
修改后的核心代码片段
while(getline(file, line_pixels)) { if(line_pixels.size() > 0 && line_pixels.at(0) != '#') { std::stringstream ss(line_pixels); int pixel_val; while(ss >> pixel_val) { // 用>>自动跳过空白并读取数字 pixel p; p.r = p.g = p.b = static_cast<float>(pixel_val) / this->max_value; v.emplace_back(p); } } }
完整修正代码
#include <iostream> #include <fstream> #include <sstream> #include <vector> struct Pixel { float r, g, b; }; typedef struct Pixel pixel; class Image { private: int max_value; std::vector<std::vector<pixel>> pixels; public: void read(std::string file_name) { std::ifstream file(file_name); std::string line; char magicNumber; int width, height; // 直接用int存储,避免后续stoi转换 // 读取魔数 while(getline(file, line)) { if(line.size() > 0 && line.at(0) != '#') { magicNumber = line.at(1); break; } } // 读取宽高 while(getline(file, line)) { if(line.size() > 0 && line.at(0) != '#') { std::stringstream ss(line); ss >> width >> height; // 直接用>>读取两个整数 break; } } // 读取max_value while(getline(file, line)) { if(line.size() > 0 && line.at(0) != '#') { std::stringstream ss(line); ss >> this->max_value; // 同样用>>读取 break; } } if(magicNumber == '2') { std::vector<pixel> v; while(getline(file, line)) { if(line.size() > 0 && line.at(0) != '#') { std::stringstream ss(line); int pixel_val; while(ss >> pixel_val) { pixel p; // 注意转换为float再做除法,避免整数除法截断 p.r = p.g = p.b = static_cast<float>(pixel_val) / this->max_value; v.emplace_back(p); } } } // 构建二维像素数组 for(int i=0; i<height; i++) { std::vector<pixel> row; for(int j=0; j<width; j++) { row.push_back(v[i*width + j]); } this->pixels.push_back(row); } } } }; int main(int argc, char ** argv) { Image img; img.read("lena.ascii.pgm"); return 0; }
额外优化点
- 宽高直接用
int类型存储,避免后续多次stoi转换,提升效率并减少潜在错误。 - 像素值计算时显式转换为
float,避免整数除法导致的结果截断(比如128/255用整数除法会得到0,转换为float后才会得到正确的0.5左右的值)。 - 构建二维数组时用
i*width + j直接索引,比单独维护index变量更简洁可靠。
内容的提问来源于stack exchange,提问作者Kleber Mota
相关产品推荐
相关产品推荐

