Daemeo
Daemeo

Reputation: 405

C memcpy Not Behaving as Expected

This question is tied to Making an Array to Hold Arrays of Character Arrays in C

Borrowing code from there, I have something that looks like this (credit to luser droog for the nice example code):

enum { BUFSZ = 50 };
enum { STRVSZ = 40 };
enum { STRVVSZ = 20 };
char buf[BUFSZ + 1];
char *strv[STRVSZ + 1];
char **strvv[STRVVSZ + 1];

int j;
int i;

while(1){
    fgets(buf, BUFSZ, infile);

    i = 0;
    strv[i] = strdup(buf);
    strv[i+1] = NULL;

    j = 0;
    strvv[j] = calloc(i+1, sizeof *strvv[j]); // assuming i is the count of elements 
    memcpy(strvv[j], strv, i * sizeof *strvv[j]);
    j++;
}

This might not run right out the door, but it illustrates something similar to what I'm running. Basically, the contents of strv needs to be stored in strvv after every iteration of the loop, and strv changes over time based on user input.

Using calloc and memcpy should have caused strvv to maintain copies of strv at each iteration of the loop independent of the values in strv. However, when I print out the contents of strvv, it prints out the same string for every entry, implying that the current approach is still moving pointers around and not making copies of strv in each strvv entry.

I'm not at all sure why this happens or how to fix it. memcpy should be making a byte level copy of what the pointers in strv point to =/.

Upvotes: 0

Views: 897

Answers (1)

luser droog
luser droog

Reputation: 19484

This is closer to what I was trying to suggest earlier.

enum { BUFSZ = 50 };
enum { STRVSZ = 40 };
enum { STRVVSZ = 20 };
char buf[BUFSZ + 1];
char *strv[STRVSZ + 1];
char **strvv[STRVVSZ + 1];

int j; // indexes strv slices in strvv
int i; // indexes strings (char *s) in strv

j = 0; // j is index into strvv

while(!feof(infile)) {

    i = 0; // i is index into strv
    while(i < STRVSZ){
        fgets(buf, BUFSZ, infile);
        if (strcmp(buf,"END")==0) break; // end of a set

        strv[i] = strdup(buf);
        strv[i+1] = NULL;
        i++;
    }  // i is count of strv

    // copy strv into strvv
    strvv[j] = calloc(i+1, sizeof *strvv[j]); // assuming i is the count of elements 
    memcpy(strvv[j], strv, (i+1) * sizeof *strvv[j]);  // i+1 to copy the NULL pointer
    j++; // index next element in strvv and a count of strvv

} // j is count of sets in strvv

It feels like a mess still.

Functions. It needs smaller, clearly defined functions. The variables here are all placeholders for something more meaningful.

Upvotes: 1

Related Questions