Search code examples
cmacoswhile-loopfgets

Unexpected behavior from "fgets" in a while loop


I'm trying to read a file line by line using fgets, but its not working. Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_SIZE 500
int main(int argc, char const *argv[])
{
    char *line;
    FILE *arq;


    //abre o arquivo para leitura
    if ((arq = fopen (argv[1], "r")) == NULL){
            printf ("erro ao abrir arquivo\n");
            exit (1);
    } 

    //aloca espaco para a linha
    if ((line = (char*) calloc (MAX_LINE_SIZE, sizeof(char))) == NULL){
            printf ("erro ao alocar memoria\n");
            exit (1);
    }

    //para cada linha
    while (fgets (line, MAX_LINE_SIZE, arq) != NULL){
            printf ("%s\n", line);
    }

    //desaloca a memoria
    free (line);

    //fecha o arquivo
    fclose (arq);

    return 0;
}

If my input file has the first line shorter than the size specified in the MAX_LINE_SIZE, in the same interaction, the fgets starts to overwrite the content of the first line with the content of the second line. For example, using MAX_LINE_SIZE = 14 with this input text:

AAAAAAA 
BBBBBBBBBB

I get this output:

Gabriels-MacBook-Air:Desktop Gabriel$ make
gcc teste.c;./a.out input.txt
BBBBBAA
BBBBB

I think the fgets method is recognizing the break line character, then, it moves the writing pointer to the beggining of the string and continues to read until the MAX_INE_SIZE is reached. But, why? Can somebody help me? Thanks!


Solution

  • The code compiled normally with a define of MAX_LINE_SIZE = 14. I tried several different ways of getting your output, and the only way that I could was to replace the space char in your input "AAAAAAA BBBBBBBBBB" with ^M. So you may want to look at your input file and see if you have a ^M in it. ^M is ASCII 13 which is a carriage return.

    Other than that, the code compiles on a FreeBSD machine using clang. And as someone mentioned, it is highly discouraged to cast the result of malloc, realloc, calloc, and other memory allocation functions. It is also not needed as void* is compatible with all pointer types.

    Additionally. I had to add the following lines to the top of the test program to get a compile with 1 warning:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_LINE_SIZE 14
    

    So your code does work, I believe the problem is in the input.