【发布时间】:2015-12-04 12:48:30
【问题描述】:
所以我为一个 pgm 文件编写了一个 I/O。我的程序读取一个 pgm 并将它的数据写入一个新的 pgm 文件。 但不知何故,它只写了一半的数据,我花了几个小时寻找错误但找不到。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct {
int row;
int col;
int max_greyscale;
int **pixel_matrix;
} PGMData;
int **mem_alloc(int row, int col) {
int **ret;
ret = malloc(sizeof(int *) * row);
if (ret == NULL) {
perror("Error while allocating memory (NULL)");
exit(EXIT_FAILURE);
}
for (int i = 0; i < row; i++) {
ret[i] = malloc(sizeof(int) * col);
if (ret[i] == NULL) {
perror("Error while allocating memory (NULL)");
exit(EXIT_FAILURE);
}
}
return ret;
}
void destroy(int **pixel_matrix, int row) {
for (int i = 0; i < row; i++) {
free(pixel_matrix[i]);
}
free(pixel_matrix);
}
void ignoreComments(FILE *fp) {
int c;
char line[100];
while((c = fgetc(fp)) != EOF && isspace(c))
;
if (c == '#') {
fgets(line, sizeof(line), fp);
ignoreComments(fp);
} else {
fseek(fp, -1, SEEK_CUR);
}
}
PGMData* readFile(const char *filename, PGMData *data) {
FILE *fp;
char magic[3];
fp = fopen(filename, "r");
if (fp == NULL) {
perror("Error while reading file (NULL)");
exit(EXIT_FAILURE);
}
fgets(magic, sizeof(magic), fp);
ignoreComments(fp);
fscanf(fp, "%d", &data->col);
ignoreComments(fp);
fscanf(fp, "%d", &data->row);
ignoreComments(fp);
fscanf(fp, "%d", &data->max_greyscale);
fgetc(fp);
data->pixel_matrix = mem_alloc(data->row, data->col);
// read
for (int i = 0; i < data->row; i++) {
for (int j = 0; j < data->col; j++) {
data->pixel_matrix[i][j] = fgetc(fp);
}
}
fclose(fp);
return data;
}
void writeFile(const char *filename, const PGMData *data) {
FILE *fp;
fp = fopen(filename, "w");
if (fp == NULL) {
perror("Error while writing file (NULL)");
exit(EXIT_FAILURE);
}
fprintf(fp, "P2\n");
fprintf(fp, "%d %d\n", data->col, data->row);
fprintf(fp, "%d\n", data->max_greyscale);
for (int i = 0; i < data->row; i++) {
for (int j = 0; j < data->col; j++) {
fputc(data->pixel_matrix[i][j], fp);
}
}
fclose(fp);
destroy(data->pixel_matrix, data->row);
}
int main(int argc, char *argv[]) {
printf("P1\n");
const char * source_file = argv[1]; // source
const char * destin_file = argv[2]; // destination
PGMData pgm_pic;
PGMData * data = &pgm_pic;
data = readFile(source_file, data); // read source
writeFile(destin_file, data); // write to destination
return 0;
}
它给了我这个 PGM:
P2
# feep.ascii.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
这个输出:
P2
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0
【问题讨论】:
-
您能否检查源代码是否被正确读取,即在您的调试器中检查
data。这将缩小问题范围。 -
readFile中的行data->pixel_matrix[i][j] = fgetc(fp);似乎需要一个二进制格式的 PGM,每个像素一个字节(这对于幻数P5来说是正确的)。您是否在任何地方检查幻数以确保它是正确类型的 PGM 文件? -
哦是吗?我不必检查它,因为我只需要使用幻数 P2
-
但是 P2 格式将像素存储为从 0 到 255 的以空格分隔的 ASCII 十进制数字,如您的输入和输出中所示,而不是单字节二进制值。您需要使用
fscanf将每个像素值读取为十进制数,并使用fprintf将每个像素值打印为十进制数。 -
要获取行和列,使用单个
fscanf调用来读取这两个值,不要在它们之间调用ignoreComment。因为那里不能有任何评论。此外,您应该尝试自己实际调试程序。在调试器中逐行执行代码。