-1

Relatively new to C here. I have a program that reads in a "Dictionary" of words from a text file. Each word in the text file ends with a newline. I would like to dynamically allocate and store an array containing words of a certain length determined by the user. I am not sure that I completely understand how it works. My code doesn't seem to create this array and only stores the last string that it encounters.

It starts by counting the amount of words of the specified length, then stores that as the "rows" of the array.

My code so far:

int rows = 0, columns = letterAmount;
while(fgets(word, MAX_CHARS, dictionary)){
    if(strlen(word) == letterAmount + 2){
        rows++;
    }
}

char **wordList = malloc(rows * sizeof(char *));
for(i = 0; i < rows; i++){
    wordList[i] = (char *)malloc(columns + 1);
}

rewind(dictionary);

i = 0;
while(fgets(word, MAX_CHARS, dictionary) && i < rows){
    if(strlen(word) == letterAmount + 2){
        wordList[i] = word;
        i++;
    }
}

Any help is appreciated!

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • 1
    "My code doesn't seem to create this array and only stores the last string that it encounters." -- Questions seeking debugging help should generally provide a [mre] of the problem, which includes a function `main` and all `#include` directives. – Andreas Wenzel Mar 07 '22 at 23:42
  • See my recent answers: https://stackoverflow.com/questions/71313784/cs50-pset5-speller-optimisation/71316468#71316468 and https://stackoverflow.com/questions/71341850/how-would-i-be-able-to-read-every-word-in-a-line-with-an-unknown-length/71342538#71342538 for help with creating dictionaries and reading word lists of unknown length. – Craig Estey Mar 07 '22 at 23:45

1 Answers1

1

You allocate memory but then you leak that pointer by replacing it with a new pointer value. Presumably word is an array on the stack or similar.

// Stores a pointer
wordList[i] = (char *)malloc(columns + 1);

// Stores a new pointer (discards previous value)
wordList[i] = word;

So now, not only have you leaked a whole lot of memory by throwing away pointers, you have also changed every word to point to your word buffer. That's why you see the output contains only the last word repeated.

What you need to do instead is copy the string. Provided you know that the word is no longer than columns in length, you can do:

strcpy(wordList[i], word);

Note there's no obvious relationship between columns and MAX_CHARS so it's hard to advise further on the safety of your memory allocation. I do wonder why you allocate the strings up-front. Why not just allocate them as needed?

wordList[i] = malloc(strlen(word) + 1);
if (wordList[i] != NULL) {
    strcpy(wordList[i], word);
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Would your suggestion to allocate as needed just fit into the second while loop? – glwhitaker2 Mar 08 '22 at 00:10
  • Yes, that is what I was suggesting. Did you try it? – paddy Mar 08 '22 at 00:39
  • I did, I'm getting a seg fault. Likely my own lack of understanding. I should get rid of the part allocating up front, then initialize before the while loop without allocating memory, and use your suggestion within the second while loop? – glwhitaker2 Mar 08 '22 at 00:47
  • 1
    Attach a debugger and find where the problem happens. Or use a process of elimination to isolate the problem. Make sure `rows` is non-zero after the first loop. Make sure that you actually allocate the `wordList` array (the line just before your middle loop in original example). If the second read-loop completes, check the value `i` is what you expect (same as `rows`) -- acknowledging that if it's less then you'll have uninitialized values in your array. You cannot get debugging help without showing a complete program and some input. If you are completely stuck, post a new question. – paddy Mar 08 '22 at 01:03