1

I'm trying to read from a file which has words in which are separated by spaces, the words are read within a loop. They are read correctly within the loop and they can be printed as so but as soon as the loop ends I am only able to print the first character of each element. Here is the code:

char **storeWords(char **words){

    char* fileName = "words.txt";
    FILE* fp = fopen(fileName, "r");
    int i;
    for (i = 0; i < 2; i++){
        int j;
        for (j = 0; j < 20; j++){
            fscanf(fp, "%s", &words[i][j]);
            printf("%s", &words[i][j]); //prints correctly
        }
    }
    printf("%s", &words[0][0]); //prints first character of selected element
    fclose(fp);
    return **words;
}

int main(){
    char **words = (char**)malloc(6 * sizeof(char*));
    for (int i = 0; i < 6; i++){
        words[i] = (char*)malloc(20 * sizeof(char));
    }

   storeWords(words);

   system("pause");
   return 0;
}

I don't understand why this happens, it would be appreciated if this could be explained. Thanks.

4
  • 1
    fscanf(fp, "%s", &words[i][j]); overwrited each one shift. Commented Apr 14, 2015 at 21:47
  • what should be used instead? @BLUEPIXY Commented Apr 14, 2015 at 21:49
  • 2
    try for (i = 0; i < 2; i++){ fscanf(fp, "%19s", words[i]); printf("%s\n", words[i]); } Commented Apr 14, 2015 at 21:50
  • 1
    return **words; should be return words;. Doesn't your compiler complain on this line? Commented Apr 15, 2015 at 1:09

1 Answer 1

1

The problem is that you are allocating a 2D array of chars, not a 2D array of strings.

This is a pointer to a string, or a 1D array of chars:

char*

This is a pointer to a 1D array of strings, or a 2D array of chars:

char**

And this is a pointer to a 2D array of strings, or a 3D array of chars:

char***

You were trying to store a string to a char, and the only reason you didn't get a crash was because you allocated a [6][20] array but only iterated over 2x20 words, so there was room for overflow.

So, in your main function you need to allocate like this (note you don't need to cast the pointer returned from malloc):

char ***words = malloc(6 * sizeof(char**));
for (int i = 0; i < 6; i++){
    words[i] = malloc(20 * sizeof(char*));        
}

Change your function declaration to use the new type:

char ***storeWords(char ***words)

Then when you read in the words, use a temp char buffer and dynamically allocate enough space based on the word size:

for (j = 0; j < 20; j++){
    char word[100]; // max word size of 100 chars
    fscanf(fp, "%99s", word);
    words[i][j] = malloc(strlen(word) + 1);
    strcpy(words[i][j], word);
    printf("%s", words[i][j]); //prints correctly
}

Note that when you print out a word you don't need to use the ampersand, because words[i][j] now contains a char* not a char:

printf("%s", words[0][0]);
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, it works fine now. But could I ask, what is "%99s" is it to do with bytes? @samgak
It is similar to %s but specifies the maximum number of chars to read into the string, excluding the terminating null. It's to avoid overflowing the word[100] array.

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.