0

Following is my code, I want to use pointer to pointer to store strings.

char **BlankWords(char word[]){
    // take word 'lad' as an example
    // length of it is 3
    // fill in blank: _ad, l_d, la_, _lad, l_ad, la_d, lad_
    // 3 + 4 = 7
    // which means, length of 'lad' + (length of 'lad') + 1
    int strLength = strlen(word);
    char **blank_words = malloc(sizeof(char*) * (2 * strLength + 1));
    assert(blank_words != NULL);
    int i, j, k;
    for (i = 0; i < strLength; i++){
        // allocate memory for each length of the word
        blank_words[i] = calloc(MAX_WORD_LENGTH, sizeof(char));
        assert(blank_words[i] != NULL);
        char temp[MAX_WORD_LENGTH];
        strcpy(temp, word);
        temp[strLength] = '\0';
        temp[i] = '_';
        blank_words[i] = temp;
       // printf("%s\n", blank_words[0]);
    }
    for (j = strLength; j < (2 * strLength + 1); j++){
        // allocate memory for each length of the word
        blank_words[j] = calloc(MAX_WORD_LENGTH, sizeof(char));
        assert(blank_words[j] != NULL);
        char temp[MAX_WORD_LENGTH];
        strcpy(temp, word);
        temp[(strlen(temp) + 1)] = '\0';
        for (k = (strLength - 1); k >= (j - strLength); k--){
            if (k >= 0){
                temp[k + 1] = temp[k];  // in order to insert '_' to the word, then the other letter move back one
            }
        }
        temp[j - strLength] = '_';   // insert '_' to the word
        blank_words[j] = temp;
    }
    return blank_words;
}

Following is the output, each row was overwritten after each loop, but in my opinion, each row cannot be overwritten, and may store a unique string.

blank_words[0]: lab_
blank_words[1]: lab_
blank_words[2]: lab_
blank_words[3]: lab_
blank_words[4]: lab_
blank_words[5]: lab_
blank_words[6]: lab_

I don't know why the previous data gets overwritten after each loop. In my opinion, the output should be:

blank_words[0]: _ab
blank_words[1]: l_b
blank_words[2]: la_
blank_words[3]: _lab
blank_words[4]: l_ab
blank_words[5]: la_b
blank_words[6]: lab_
4
  • 2
    char temp[MAX_WORD_LENGTH]; blank_words[i] = temp; That results in Undefined Behaviour. temp is a local variable within the scope of the for loop. Which means the variable is invalid outside the loop and using a reference to it outside the loop is UB. One option is blank_words[i] = strdup(temp);. That allocates dynamic memory so don't forget to free it when done. Commented Apr 2, 2022 at 23:59
  • Well, there is another question, where should I use free? Commented Apr 3, 2022 at 0:09
  • 2
    Your example could do with 1) being more concise, shorter, to the point; and 2) being complete, as in, we could copy & paste & compile it and get the same output as you. Without having to add anything. Commented Apr 3, 2022 at 0:11
  • 2
    Your code is incomplete so I can't tell you precisely where to call free. The caller of this function would free the memory when it no longer needs the array and its contents. Commented Apr 3, 2022 at 0:12

1 Answer 1

1

As others have said, a local buffer disappears when its scope closes. Since the char** array points to buffers of that sort, the result is undefined behavior. You'll need to allocate the result strings with malloc.

Another tip: You can build the second set of strings by just moving the underscore rather than creating each from scratch. This is simpler:

#include <stdlib.h>
#include <string.h>
#include <assert.h>

void *safe_malloc(size_t n) {
  void *r = malloc(n);
  assert(r);
  return r;
}

char *stralloc(char *s) {
  return strcpy(safe_malloc((strlen(s) + 1) * sizeof(char)), s);
}

char **variations(char *s) {
  int len = strlen(s), rp = 0;
  char **r = safe_malloc((2 * len + 1) * sizeof *r);;
  char buf[len + 2];
  strcpy(buf, s); // Copy in case s is a read-only literal.
  for (int i = 0; i < len; ++i) {
    char t = buf[i];               // Remember the i'th char.
    buf[i] = '_';                  // Overwrite with _.
    r[rp++] = stralloc(buf);       // Capture a copy.
    buf[i] = t;                    // Replace original char.
  }
  buf[0] = '_';                    // Make the 1st char _.
  strcpy(buf + 1, s);              // Copy the rest after.
  r[rp++] = stralloc(buf);         // Capture a copy.
  for (int i = 0; i < len; ++i) {
    buf[i] = buf[i + 1];           // Overwrite _ with following char.
    buf[i + 1] = '_';              // Move the _ up one position.
    r[rp++] = stralloc(buf);       // Capture a copy.
  }
  return r;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.