cadence glorpon cadence glorpon - 21 days ago 12
C Question

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.

Answer

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.