我正在尝试实现一个 C++ 类来读取 PGM 文件。我可以毫无问题地读取文件头(幻数、宽度、高度和最大值),但是当我尝试读取像素数据时,出现与使用
stoi
进行字符串转换相关的错误。
我现在得到的代码:
while(getline(file, line_pixels)) {
if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
std::stringstream ss(line_pixels);
std::string value;
while(getline(ss, value, ' ')) {
pixel p;
p.r = p.g = p.b = stoi(value) / this->max_value;
v.emplace_back(p);
}
}
}
错误上线:
p.r = p.g = p.b = stoi(value) / this->max_value;
程序在读取空格时出现问题(它应该跳过这些)。以下代码是可以编译以重现错误的程序:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
void read(std::string file_name);
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_one, line_two, line_three, line_pixels;
char magicNumber;
std::string width, height;
while(getline(file, line_one)) {
if(line_one.size() > 0 && line_one.at(0) != '#') {
magicNumber = line_one.at(1);
break;
}
}
while(getline(file, line_two)) {
if(line_two.size() > 0 && line_two.at(0) != '#') {
std::stringstream ss(line_two);
getline(ss, width, ' ');
getline(ss, height, ' ');
break;
}
}
while(getline(file, line_three)) {
if(line_three.size() > 0 && line_three.at(0) != '#') {
this->max_value = stoi(line_three);
break;
}
}
if(magicNumber == '2') {
std::vector<pixel> v;
while(getline(file, line_pixels)) {
if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
std::stringstream ss(line_pixels);
std::string value;
while(getline(ss, value, ' ')) {
pixel p;
p.r = p.g = p.b = stoi(value) / this->max_value;
v.emplace_back(p);
}
}
}
int h = stoi(height), w = stoi(width);
int index = 0;
for(int i=0; i<h; i++) {
std::vector<pixel> row;
for(int j=0; j<w; j++) row.push_back(v[index++]);
this->pixels.push_back(row);
}
}
}
};
int main(int argc, char ** argv) {
Image img;
img.read("lena.ascii.pgm");
return 0;
}
为了测试这个程序,我使用这个 pgm 图像。谁能告诉我这里出了什么问题吗?
这是跳过空格的修复方法(我只包含读取宽度和高度的块),例如:
while (getline(file, line_two)) {
if (line_two.size() > 0 && line_two.at(0) != '#') {
std::stringstream ss(line_two);
getline(ss, width, ' ');
while (ss.peek() == ' ') // skip spaces
ss.get();
getline(ss, height, ' ');
break;
}
}
然后要解决 stoi 问题,这又是因为实际值之间有多个空格,因此解析后的值为空,要解决此问题,您只需在将其传递给 stoi 之前检查是否为空字符串,如下所示:
while (getline(file, line_pixels)) {
if (line_pixels.size() > 0 && line_pixels.at(0) != '#') {
std::stringstream ss(line_pixels);
std::string value;
while (getline(ss, value, ' ')) {
if (value.size() > 0)
{
pixel p;
p.r = p.g = p.b = stoi(value) / this->max_value;
v.emplace_back(p);
}
}
}
}