问题描述
所以我必须以 PPM 格式读取此图像,然后将其写入另一个文件。 它可以工作,但是如果图像有评论,它就会停止工作。 如果图片是这样的:
P3
3 2
255
255 0 0
0 255 0
0 0 255
255 255 0
255 255 255
0 0 0
它有效,但如果图像是这样的:
P3
3 2
255
# "3 2" is the width and height of the image in pixels
# "255" is the maximum value for each color
# The part below is image data: RGB triplets
255 0 0 # red
0 255 0 # green
0 0 255 # blue
255 255 0 # yellow
255 255 255 # white
0 0 0 # black
它停止工作。 我真的不知道为什么,因为我已经编程为忽略评论。 我会在下面留下代码,也许有人可以帮忙。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols,rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
}imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
f = fopen(filename,"rb");
if(f == NULL) {
scanf("%c %c",&img.mnumber[0],&img.mnumber[1]);
scanf("%d %d",&img.cols,&img.rows);
scanf("%d",&img.maxcolor);
img.matrix = (pixel*) malloc(img.cols*img.rows*sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
scanf("%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
}
} else {
int i = 0;
while(i != 2)
{
img.mnumber[i] = getc(f);
//printf("%c\n",(char) img.mnumber[i]);
i++;
}
int c = getc(f);
while (c == '#') {
while (getc(f) != '\n') {
getc(f);
}
c = getc(f);
}
ungetc(c,f);
fscanf(f,"%d %d",&img.rows);
fscanf(f,"%d",&img.maxcolor);
img.matrix = (pixel*)malloc(img.cols * img.rows* sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
fscanf(f,"%u %u %u",&img.matrix[i].b);
}
fclose(f);
return img;
}
return img;
}
解决方法
我会把它写成这样:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols,rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
} imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
int i;
char buf[BUFSIZ];
if (filename == NULL) {
f = stdin;
} else {
f = fopen(filename,"r");
if (f == NULL) {
fprintf(stderr,"Can't open %s\n",filename);
exit(1);
}
}
if (fgets(buf,sizeof buf,f) == NULL) {
fprintf(stderr,"Can't read data\n");
exit(1);
}
for (i = 0; i < 2; i++) {
img.mnumber[i] = buf[i];
}
if (fgets(buf,"Can't read data\n");
exit(1);
}
sscanf(buf,"%d %d",&img.cols,&img.rows);
if (fgets(buf,"%d",&img.maxcolor);
img.matrix = malloc(img.cols * img.rows * sizeof(pixel));
if (img.matrix == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
i = 0;
while (fgets(buf,f) != NULL) {
if (buf[0] == '#') continue;
else {
sscanf(buf,"%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
i++;
}
} fclose(f);
return img;
}
- 按照建议,最好使用
fgets()
和sscanf()
而不是fscanf()
尤其是当我们需要处理不规则线条时。 - 您不必编写特定的代码来读取
stdin
文件名被省略。只需将文件指针f
分配给stdin
。 - 建议把函数名
read()
改成别的 因为它与现有的系统调用函数read(2)
冲突。