Reputation: 29
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_
Upvotes: 0
Views: 80
Reputation: 46960
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;
}
Upvotes: 1