cadence glorpon
cadence glorpon

Reputation: 39

Trouble dynamically allocating memory for string array

I am trying to write a function that reads a text file and copies each line of the text file into a line of an array that is passed into the function.

void read_lines(FILE* fp, char*** lines, int* num_lines) {  
    int i = 0, line_count = 0;
    char line[256], c;

    fscanf(fp, "%c", &c);
    while(!feof(fp)){
        if(c == '\n') {
            ++line_count;
        }
        printf("%c", c);
        fscanf(fp, "%c", &c);
    }

    rewind(fp);
    *num_lines = line_count;

    lines = (char***)malloc(line_count * sizeof(char**));
    while (fgets(line, sizeof(line), fp) != NULL) {
        lines[i] = (char**)malloc(strlen(line) * sizeof(char*));
            strcpy(*lines[i], line);
        }
        ++i;
    }
}

The initial part scans for newlines so that I know how much to allocate to lines initially. I am not sure where I am going wrong.

Additionally, if anybody has any resources that could help me to better understand how to dynamically allocate space, that would be greatly appreciated.

Upvotes: 0

Views: 148

Answers (2)

chux
chux

Reputation: 153508

Code is making various mistakes including the key ones detailed by @Ari0nhh

The other is the counting the '\n' can fail to get the correct number of lines vs. fgets() in 3 ways:

  1. Line exceeds 256.

  2. More than INT_MAX lines.

  3. Last line does not end with a '\n'.

Suggest instead use the same loop to count "lines"

unsigned long long line_count = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
    line_count++;
}

rewind(fp);

.... 

assert(line_count <= SIZE_MAX/sizeof *(*lines));
*lines = malloc(sizeof *(*lines) * line_count);

Upvotes: 1

Ari0nhh
Ari0nhh

Reputation: 5920

You should understand how the pointers work. After that, dynamical memory allocation task would be pretty trivial. Right now your code is completely wrong:

//here you assign to the argument. While this is technically allowed 
//it is most certainly not what you have intended
lines = (char***)malloc(line_count * sizeof(char**));
while (fgets(line, sizeof(line), fp) != NULL) {
        //sizeof(char*) <> sizeof(char).  Also you need a space for the trailing \0 
        lines[i] = (char**)malloc(strlen(line) * sizeof(char*));
        //[] precedes * so it is copying the string somewhere you not intend to
        strcpy(*lines[i], line);
    }
    ++i;
}

Correct version should be:

*lines = malloc(line_count * sizeof(char*));
while (fgets(line, sizeof(line), fp) != NULL) {
    (*lines)[i] = malloc((strlen(line) + 1) * sizeof(char));
    strcpy((*lines)[i], line);
    }
    ++i;
}

Note, that you need to use (*lines)[i] construct, because [] operator precedes * (dereference) operator.

Upvotes: 2

Related Questions