简体   繁体   中英

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.

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.

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM