-2

I have a problem which says I have to read an unknown number of text lines from a file in an array of pointers and allocate memory at runtime.

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

int main()
{
    FILE *fp = fopen("file.txt","r");
    char *arrp[10];
    int i=1;

    while(!feof(fp))
    {
        arrp[i]=malloc(sizeof(char)*51);
        fgets(arrp[i],51,fp);
        i++;
    }

    return 0;
}
  • 6
    [`while(!feof(fp))` is always wrong](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). Always check the return value of `malloc()` against `NULL`. Is this on a specific operating system, or it has to be portable? – Iharob Al Asimi Jan 09 '16 at 14:19
  • In addition, why start i with 1 ? Then after you have fixed feof, are you sure that you have only at max 9 lines (or 10 if you start i with 0) and that each line has at max 50 characters including end of line ? – mikedu95 Jan 09 '16 at 14:39
  • 1
    looking for `realloc`? – BLUEPIXY Jan 09 '16 at 14:44
  • 1
    See [this](http://stackoverflow.com/a/34695651/841108) – Basile Starynkevitch Jan 09 '16 at 16:35

2 Answers2

2

I'd suggest counting the number of lines first.

int tmp;
int linecount = 0;
FILE *fp = fopen("file.txt","r");

while ((tmp=fgetc(fp))!=EOF) {
    if (tmp=='\n') 
         ++linecount;
}

rewind(fp); // resets the stream to beginning of file

From there, you can malloc the appropriate amount of array pointers (instead of initializing a fixed number).

 char** lines;
 lines = malloc(linecount * sizeof(char*));

and use fgets as normal to then read each line into lines[i]

Bill Harper
  • 379
  • 2
  • 10
0

First you would need to write a getline routine, which reads in a variable-length line. It will be allocated with malloc:

#define INITALLOC  16  /* #chars initally alloced */
#define STEP        8  /* #chars to realloc by */
int getline(char **dynline)
{
    int i, c;
    size_t nalloced;  /* #chars currently alloced */

    if ((*dynline = malloc(INITALLOC)) == NULL)
        return 0;
    nalloced = INITALLOC;
    for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
        /* buffer is full, request more mem */
        if (i == nalloced)
            if ((*dynline = realloc(*dynline, nalloced += STEP)) == NULL)
                return 0;
        /* store the newly read character */
        (*dynline)[i] = c;
    }
    /* zero terminate the string */
    (*dynline)[i] = '\0';

    if (c == EOF)
        return 0;  /* return 0 on EOF */
    return 1;
}

This function returns 0 on failure or EOF, and 1 on success. Now we can read the lines in our main function.

int main()
{
    char *line;

    while (getline(&line))
        printf("%s\n", line);

    /* free to avoid mem leak */
    free(line);
    return 0;
}

And do not use while(!feof(fp)), because this will always result in one extra read, because the EOF state is set only after you try to read, not before.

lost_in_the_source
  • 10,998
  • 9
  • 46
  • 75