Search code examples
cdynamic-memory-allocationfile-handlingdynamic-arrays

how to store words from a file to a dynamic array of strings?


I'm trying to store data from a file (words line by line) maximum length is 16

when I run the code it only stores the last word on the file and prints it (number of all the words in the file) times.

if the file contains 10 words and the last word is test, the output is test 10 times

when I tried while loop to scan the file I got garbage data

here is my code

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



int main()
{
    FILE *file;

    file = fopen("words.txt", "r");

    char word[20];
    int words_count=0; // count the words in the file

    while (fscanf(file, "%s", word) != EOF)
    {
        words_count++;
    }

    printf("%d", words_count); // i get the right number of words in the file at this step


    char **list_of_words = malloc (words_count * sizeof(char *)); //allocate memory to store enough pointers to charecters

    int length;

    for (int i=0; i<words_count; i++)
        {
            fscanf(file, "%s", word);
            length = strlen(word);
            word[length+1] = '\0';
            list_of_words[i] = malloc (length+1 * sizeof(char)); //allocate memory for each word 
            list_of_words[i] = word;  //I used strcpy(), but I got the same output 
        }



    for (int i=0; i<words_count; i++)
    {
        printf("%s\n", list_of_words[i]); //print the words 
    }


    fclose(file);
}

Solution

  • There are several issues:

    • once you have read the file you're at the end of the file. If you want to read the file again, you need to move the file pointe rto the start of the file again.
    • you definitely need to use strcpy here, list_of_words[i] = word is pointless, you want to copy the string, not overwrite the previously allocated pointer with a pointer to a local variable (try it and see what happens).
    • length+1 * sizeof(char) is wrong, you intended (length + 1) * sizeof(char). However by chance both expressions give the same result. so this doesn't cause a bug in this particular case. But anyway length+1 is enough because sizeof(char) is 1 by definition.
    • word[lengt+1] = '\0' is useless because after fscanf word[length+1] is 0 by definition. But it doesn't cause a bug.
      ...
      fseek(file, SEEK_SET, 0);               // rewind the file so you can read it 
                                              // again
      for (int i = 0; i < words_count; i++)
      {
        fscanf(file, "%s", word);
        length = strlen(word);
    //    word[length + 1] = '\0';            // remove this, it's useless
        list_of_words[i] = malloc(length + 1); // remove the sizeof(char)  which is 1 by definition
        strcpy(list_of_words[i], word);       // use strcpy
      }
      ...