LIsa
LIsa

Reputation: 163

C, values in array of pointers dissapear (pointers)

I seem to be losing the reference to my pointers here. I dont know why but I suspect its the pointer returned by fgets that messes this up. I was told a good way to read words from a file was to get the line then separate the words with strok, but how can I do this if my pointers inside words[i] keep dissapearing.

text

Natural Reader is
john make tame

Result Im getting.

array[0] = john
array[1] = e
array[2] =
array[3] = john
array[4] = make
array[5] = tame
int main(int argc, char *argv[]) {
   FILE *file = fopen(argv[1], "r");
   int ch;
   int count = 0;
   while ((ch = fgetc(file)) != EOF){
      if (ch == '\n' || ch == ' ')
         count++;
   }
   fseek(file, 0, SEEK_END);
   size_t size = ftell(file);
   fseek(file, 0, SEEK_SET);
   char** words = calloc(count, size * sizeof(char*) +1 );
   int i = 0;
   int x = 0;
   char ligne [250];

   while (fgets(ligne, 80, file)) {
      char* word;
      word = strtok(ligne, " ,.-\n");
      while (word != NULL) {
         for (i = 0; i < 3; i++) {
            words[x] = word;
            word = strtok(NULL, " ,.-\n");
            x++;
         }
      }
   }
   for (i = 0; i < count; ++i)
      if (words[i] != 0){
         printf("array[%d] = %s\n", i, words[i]);
      }
   free(words);
   fclose(file);
   return 0;
}

Upvotes: 0

Views: 47

Answers (2)

SGeorgiades
SGeorgiades

Reputation: 1821

You could also hanle this by using a unique ligne for each line read, so make it an array of strings like so:

char ligne[20][80]; // no need to make the string 250 since fgets limits it to 80

Then your while loop changes to:

int lno = 0;
while (fgets(ligne[lno], 80, file)) {
    char *word;
    word = strtok(ligne[lno], " ,.-\n");
    while (word != NULL) {
        words[x++] = word;
        word = strtok(NULL, " ,.-\n");
    }
    lno++;
}

Adjust the first subscript as needed for the maximum size of the file, or dynamically allocate the line buffer during each iteration if you don't want such a low limit. You could also use getline instead of fgets, if your implementation supports it; it can handle the allocation for, though you then need to free the blocks when you are done.

If you are processing real-world prose, you might want to include other delimiters in your list, like colon, semicolon, exclamation point, and question mark.

Upvotes: 1

AndersK
AndersK

Reputation: 36102

strtok does not allocate any memory, it returns a pointer to a delimited string in the buffer.

therefore you need to allocate memory for the result if you want to keep the word between loop iterations

e.g.

word = strdup(strtok(ligne, " ,.-\n"));

Upvotes: 1

Related Questions