Search code examples
cdynamicrealloccalloc

Allocation memory to char**


The program aims to get the first word and an array of remaining words. For example, if line = "a bb cc dd ee", then key should be a, keySet should be a pointer to an array of {bb,cc,dd,ee}.

I try to dynamically allocate memory to char** keySet, but keySet output always ee ee ee ee. It seems that keySet is not the pointer to the first element of array but point to the last element. What's the problem in my function?

void allocateKeySet(char* line){
    int count = 0;
    char* token = strtok(line, " ");
    char key[17];
    char tempKey[17];
    char** keySet;

    sscanf(strtok(NULL, " "), " %s", key);
    keySet = calloc(1, sizeof(char*));
    while((token = strtok(NULL, " ")) != NULL){
        sscanf(token, " %s", tempKey);
        keySet[count++] = tempKey;
        keySet = realloc(keySet, (count+2) * sizeof(char*));
    }

    printf("key: %s\n", key);
    printf("keySet: ");
    for(int i = 0; i < count - 1; i++){
        printf("%s ", keySet[i]);
    }
}

e.g. line:

"a bb cc dd ee"

expected output:

key: a
keySet: bb cc dd ee

My output:

key: a
keySet: ee ee ee ee

Solution

  • keySet[count++] = tempKey;: you probably want str(n)cpy, or strdup. Currently, tempKey gets reassigned everytime, and all keySet elements point to the same tempKey. Hence, after the last tempKey assignment, they all point to "ee". (Note that if you use strcpy, you'll need to assign memory for keySet[count++] first; strdup does the allocation and assignment in one go, but you'll have to test for NULL anyway afterwards.)

    Thus:

    while((token = strtok(NULL, " ")) != NULL){
            sscanf(token, " %s", tempKey);
            keySet[count] = strdup(tempKey);
            if (keySet[count] == NULL) {
                 perror("memory allocation failure");
            }
            count++;
            keySet = realloc(keySet, (count+2) * sizeof(char*));
        }
    

    If you can't use strdup, you can use the following lines instead of the strdup line:

    keySet[count] = malloc(strlen(tempKey)+1);
    // test for keySet[count] 1= NULL
    strcpy(keySet[count], tempKey)
    count++;
    

    as per this answer.

    Don't forget to free the individual keySet elements afterwards.