Search code examples
cdynamicmallocrealloc

fgets + dynamic malloc/realloc with a .txt as stdin


i'm trying to read lines of a file. txt, but without knowing the size of each lines...First I used the getline instruction (and works fine), but my teacher does not let me use that instruction, he says I can only use the fgets statement with malloc and realloc...

This is an input example, with variable line sizes:

[9.3,1.2,87.9]
[1.0,1.0]
[0.0,0.0,1.0]

As shown, each line defines a different vector with no size limit

Someone could help me implement this method?

Thank you very much.

NOTE: I forgot to mention, to compile the program I use these commands:

g++ -Wall-Wextra-Werror-pedantic main.c-o metbasicos.c metintermedios.c eda.exe

./eda.exe <eda.txt

Solution

  • I would say do something similar to this

        while(fgets(buf, LEN, stdin)){
                z = strtok(buf, ",");
                *(*(matrix + i)) = atof(z);
                for(j = 1; j < col; ++j){
                        z = strtok(NULL, ",");
                        *(*(matrix + i) + j) = atof(z);
                }
                ++i;
        }
    

    The only extra thing you would have to take care of is making sure that you strip the brackets off of the first and last element.

    Of course, if you don't know the size of the final array, you might need something like this:

        struct data_t {
                int nval;               /* current number of values in array */
                int max;                /* allocated number of vlaues */
                char **words;           /* the data array */
        };
    
        enum {INIT = 1, GROW = 2};
    
        ...
        while (fgets(buf, LEN, stdin)) {
                if (data->words == NULL)
                        data->words = malloc(sizeof(char *));
                else if (data->nval > data->max) {
                        data->words = realloc(data->words, GROW * data->max *sizeof(char *));
                        data->max = GROW * data->max;
                }
                z = strtok(buf, "\n");
                *(data->words + i) = malloc(sizeof(char) * (strlen(z) + 1));
                strcpy(*(data->words + i), z);
                i++;
                data->nval++;           
        }
        data->nval--;
    

    If you combine both of those while loops into a single one, you should be all set. The first one reads in floats, the second one is good for dynamically allocating space on the fly.