0

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
Jennifer Q
  • 257
  • 3
  • 12
  • 1
    `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.) –  Apr 11 '16 at 00:28
  • you mean: `strdup(keySet[count++], tempKey )`? – Jennifer Q Apr 11 '16 at 00:30
  • Almost: `keySet[count++] = strdup(tempKey)`. Do test for `keySet[count-1] != NULL` afterwards (unlikely, but the proper thing to do). –  Apr 11 '16 at 00:31

1 Answers1

1

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.

Community
  • 1
  • 1
  • If I want to use `strcpy`, how can I assign memory for `keySet[count++]`? Something like `keySet[count++] = char[strlen(tempKey)]`? Cuz `strdup` seems not in standard C library and I can't use it in my homework... – Jennifer Q Apr 11 '16 at 00:39
  • What OS are you using. `strdup` is a POSIX.1-2001 standard, and is around in most C libraries. –  Apr 11 '16 at 00:43
  • And some discussion on why it's not the C standard otherwise: http://stackoverflow.com/questions/32944390/what-is-the-rationale-for-not-including-strdup-in-the-c-standard –  Apr 11 '16 at 00:45
  • We can only use the libraries provided. And thank you! `strcpy` works – Jennifer Q Apr 11 '16 at 00:51