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

C语言读取PBM文件时如何忽略以#开头的注释行?

问题:读取PBM文件时如何忽略注释行?

我用以下C语言代码读取.pbm格式文件:

int **leArquivoImagem(char *nomeImagem, char *tipo, int *lin, int *col)
{
    FILE *arq = fopen(nomeImagem, "r");
    if (arq == NULL)
    {
        printf("\nErro ao abrir arquivo - leArquivoImagem.\n");
        return NULL;
    }
    fscanf(arq, "%s", tipo);
    printf("%s\n", tipo);

    //line ignorer here

    fscanf(arq, "%d %d", col, lin);
    printf("%d %d\n", *lin, *col);
    int **mat = alocaMatrizImagem(*lin, *col);
    if (mat == NULL)
    {
        printf("\nErro ao alocar mat imagem - leArquivoImagem.\n");
        return NULL;
    }
    for (int i = 0; i < *lin; i++)
    {
        for (int j = 0; j < *col; j++)
        {
            fscanf(arq, "%d", &mat[i][j]);
        }
    }
    fclose(arq);
    return mat;
}

正常的PBM文件内容如下:

P1
5 3
0 0 1 0 1
0 0 1 1 0
1 1 0 0 0

但部分PBM文件会在P1标识与尺寸信息之间存在以#开头的注释行,例如:

P1
# comment here
5 3
0 0 1 0 1
0 0 1 1 0
1 1 0 0 0

或者:

P1
# comment here
# another comment to ignore
5 3
0 0 1 0 1
0 0 1 1 0
1 1 0 0 0

我尝试过以下几种代码实现忽略注释,但都失败了:

第一种:

char line[2047];
while (fgets(line, sizeof(line), arq) != NULL)
    {
        char *hash = strchr(line, '#');
        if (hash != NULL)
            *hash = '\0';
    }

第二种:

char buffer[2047];
while (fgets(buffer, 2047, arq) != NULL) {
    if (buffer[0] != '#') {
        break;
    }
}

第三种:

char line[2047];
while (fgets(line, sizeof(line), arq)) {
    if (line[0] == '#') {
        continue;
    }
}

请问如何正确实现忽略这些注释行的功能?


解决方案

你之前的代码失败原因:

  • 第一种和第三种代码会把文件读到末尾,后续的fscanf没有内容可读;
  • 第二种代码只跳过开头是#的行,但无法处理空行或行内带注释的情况,且跳出循环后没有从当前行解析尺寸。

正确的实现需要逐行处理,跳过注释内容,直到成功读取到尺寸信息,同时兼容行内注释(比如5 3 # width and height这种格式)。将原代码中//line ignorer here的位置替换为以下代码:

char line[2048];
int read_result;

// 循环读取,直到成功获取尺寸
while (1) {
    // 读取一行内容
    if (!fgets(line, sizeof(line), arq)) {
        printf("\nErro: Arquivo PBM inválido, faltam dados de dimensão.\n");
        fclose(arq);
        return NULL;
    }

    // 截断行内的注释(从#开始到行尾)
    char *hash_ptr = strchr(line, '#');
    if (hash_ptr != NULL) {
        *hash_ptr = '\0';
    }

    // 尝试从当前行解析宽和高
    read_result = sscanf(line, "%d %d", col, lin);
    if (read_result == 2) {
        // 成功读取到两个整数,退出循环
        break;
    }
    // 读取失败则继续循环,处理下一行
}

这段代码的逻辑:

  1. 逐行读取文件内容;
  2. 遇到#就截断该行后续内容,忽略注释;
  3. 尝试从处理后的行中解析两个整数(PBM的宽和高);
  4. 只有成功读取到两个整数时才退出循环,否则继续处理下一行,自动跳过纯注释行、空行。

这样就能正确处理各种带注释的PBM文件,同时兼容标准格式的文件。


内容的提问来源于stack exchange,提问作者Duartinho Codes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 21:44:50