You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:05:23