【问题标题】:pgm-file I/O gives me half of datapgm-file I/O 给了我一半的数据
【发布时间】: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-&gt;pixel_matrix[i][j] = fgetc(fp); 似乎需要一个二进制格式的 PGM,每个像素一个字节(这对于幻数 P5 来说是正确的)。您是否在任何地方检查幻数以确保它是正确类型的 PGM 文件?
  • 哦是吗?我不必检查它,因为我只需要使用幻数 P2
  • 但是 P2 格式将像素存储为从 0 到 255 的以空格分隔的 ASCII 十进制数字,如您的输入和输出中所示,而不是单字节二进制值。您需要使用fscanf 将每个像素值读取为十进制数,并使用fprintf 将每个像素值打印为十进制数。
  • 要获取行和列,使用单个fscanf 调用来读取这两个值,不要在它们之间调用ignoreComment。因为那里不能有任何评论。此外,您应该尝试自己实际调试程序。在调试器中逐行执行代码。

标签: c io pgm


【解决方案1】:

但是 P2 格式将像素存储为从 0 到 255 的以空格分隔的 ASCII 十进制数字,如您的输入和输出中所示,而不是作为单字节二进制值。您需要使用fscanf 将每个像素值读取为十进制数,并使用fprintf 将每个像素值打印为十进制数。 ——伊恩·阿博特

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多