简体   繁体   中英

fgets() doesn't continue until to the end of the file in the while loop

I need to read a file until its end, but it interrupts before the end. Here is my file;

8378749330196451143 7761927347639996843
3597172149842452783 2722311582032048570
6413963814675220040 151985128848019557
2797849130305409931 7006855242872793130
2312483514986641752 4723009976223322840
6299327914512777856 8560986736619134288
7840374864908954188 6413325942318176938
7120263339634576853 5721019237600873947
4064508404151769878 8332513917413808407
1131946326472490896 8768732125304950625
2593825059274639432 4898919688177170005
1152428805919273221 4955899780218674181
4762291655892416501 1286985264509566046
1098025338340897985 4952984927278789363
2524421559647997815 8843945302342585201

I am using this part of code for getting the lines;

file = fopen ( buffer, "r" );
    if ( file != NULL ){
            while ( fgets ( line, sizeof line, file ) != NULL ) {
                // Token will point to the part before the =.
                pairs[i].key = strdup(strtok(line, search));
                // Token will point to the part after the =.
                pairs[i].value = strdup(strtok(NULL, search));

                i++;
              }
    }

It works, but not till the end. After reading the part below while loop ends. What can be the reason for this? Every line end with a \\n symbol.

8378749330196451143 7761927347639996843
3597172149842452783 2722311582032048570
6413963814675220040 151985128848019557
2797849130305409931 7006855242872793130
2312483514986641752 4723009976223322840
6299327914512777856 8560986736619134288
7840374864908954188 6413325942318176938
7120263339634576853 572101923

Note: I got a screenshot from an editor that shows marks

在此处输入图片说明

EDIT 2

Your previous question on this topic indicates you are processing data from file 1000 lines at a time, for each of these 1000 lines you call strdup twice (once for each data field in the text line). You also said " I have a file which contains 2^32 key/value pairs ".

For each of these you call strdup twice, once for each data field. Now, strdup allocates memory to hold the string you want to be duplicated. With your massive quantity of data, that's an enormous amount of memory, and the program grinds to a halt through lack of it.

So I suggest that after processing each 1000 lines of input, you release the memory, something like this - please adapt to your needs, since you never show whole code.

for (i=0; i<1000; i++) {
    free(pairs[i].key);
    free(pairs[i].value);
}

It is essentially good practice to the check the return value of any library function that returns an error-hinting value. In the case of strdup that will tell you if you ran out of memory. In the case of strtok you'll know that a rogue line was in the file that you cannot interpret - perhaps an empty line at the end of the file terminated by newline .

Secondly, comments in that previous question reveal that char line [c]

is defined as 41 char because my every line can be maximum 41.

Now, there are 20 decimal digits max in a 64-bit unsigned int . Two of those plus a space make 41. What about the string terminator? And what about the newline that will usually be on the end of the input obtained by fgets ? I propose you change your definition of c (you never show it) to something like

#define c 50

as there is no reason to be tight with a single string length. When you call strdup , that will only allocate enough memory for the string length + terminator, so it's not a big waste of memory at all.

This is program which correctly reads the data from the file -

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

struct data{
    char *key;
    char *value;
}pairs[20];

int main(void) {
    FILE *fp; 
    int i=0;
    char line[255],search[2]=" ";
    char *token;
    fp=fopen("Results.txt","r");
    if(fp!=NULL){
       while(fgets(line,sizeof line,fp)!=NULL){            // read from file 
         pairs[i].key=NULL;                // setting to NULL 
         pairs[i].value=NULL;              // setting to NULL 
         token=strtok(line, search);
         if(token!=NULL){             // check its return 
              pairs[i].key = strdup(token);
           }
         token=strtok(NULL, search);
         if(token!=NULL){            // check its return             
             pairs[i].value = strdup(token);
         }            
         if(pairs[i].key!=NULL && pairs[i].value!=NULL)      //check return from strdup
              printf("%s %s\n",pairs[i].key,pairs[i].value);  //print values
           i++;
        }
    }
   for(int j=0;j<i;j++) {
      free( pairs[i].key);
      free( pairs[i].value);
   }
   fclose(fp);
}

I didn't know your declarations , so did accordingly .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM