Can I ignore a line started with "#" while reading a file in C?

109 Views Asked by At

the following code is used to read a .pbm file

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;
}

and that's the file I'm reading:

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

but in some cases files can have commented lines, like this:

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

or even like this:

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

How can I ingore those lines? (Comments are always between the "P1" and the dimensions).

I tried using a buffer with the max line size (2047) in the following codes:

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;
        }
    }
2

There are 2 best solutions below

0
Duartinho Codes On BEST ANSWER

The following code solved my problem. Thanks to Chux for suggesting to use only fgets(), YuWea for the buffer size correction, and Jonathan Leffler for suggesting sscanf() and break.

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;
    }

    char buffer[2048];
    while (fgets(buffer, sizeof(buffer), arq) != NULL) {

        sscanf(buffer, "%s", tipo);
        printf("%s\n", tipo);

        // Ignore all commented lines and get dimensions
        while (fgets(buffer, sizeof(buffer), arq) != NULL) {
            if (buffer[0] != '#') {
                sscanf(buffer, "%d %d", col, lin);
                printf("%d %d\n", *lin, *col);
                break;
            }
        }

        int **mat = alocaMatrizImagem(*lin, *col);
        if (mat == NULL) {
            printf("\nErro ao alocar mat imagem - leArquivoImagem.\n");
            fclose(arq);
            return NULL;
        }

        int count = 0;
        for (int i = 0; i < *lin; i++) {
            fgets(buffer, sizeof(buffer), arq);
            char *ptr = buffer;
            for (int j = 0; j < *col; j++) {
                while (*ptr == ' ') ptr++;
                if (*ptr == '\n' || *ptr == '\0') {
                    j--;
                    continue;
                }
                mat[i][j] = strtol(ptr, &ptr, 10);
            }
        }

        fclose(arq);
        return mat;
    }

    fclose(arq);
    return NULL;
}
2
SmellyCat On

Once you have done those fgets calls, you need to check the buffer in case it's not a comment line. You do this with scanf rather than the fscanf that you would use if comments weren't supported.

char line[2047];
while (fgets(line, sizeof(line), arq) != NULL)
{
    char *hash = strchr(line, '#'); /* You might be able to combine this line into the if-statement. */
    if (hash != NULL)
        continue; /* comment line */
    
    sscanf(line, "%d %d", col, lin);
    printf("%d %d\n", *lin, *col);
    int **mat = ....