silent
silent

Reputation: 2924

Reading text into a buffer in c. (leaves out the last line of data when there is no newline on the textfile)

I'm trying to read lines on a text file into a buffer by giving a function a line number as a parameter. This function then copies the text contained on that particular line of the file into the variable retreiveString for use. The problem I'm having is that, if there is no 'empty newline' at the very end of the text file, the program doesn't copy the last entry into the buffer. What am I doing wrong?.

example of textfile that reads properly

line 0

line 1


example of textfile that doesnt read in the last line into the buffer (i.e line 1).

line 0

line 1

//test2
    #include <stdio.h> 
    #include <string.h>
    #define BUFFER_SIZE 80

    char read_in_buffer[BUFFER_SIZE];
    char retreivedString[BUFFER_SIZE];
    void getString(int lineNum);
    int maxDataNum = 0;
    bool endOfFileReached =  false;

    int main(void){
        printf("-Main-\n");


        getString(1);
        printf("retrieved:%s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
        printf("strlen: %d",strlen(retreivedString));
        /*
        getString(2);
        printf("retrieved: %s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
        getString(4);
        printf("retrieved: %s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
       */

       return 0;
    }

    void getString(int lineNum){
        FILE *fin=fopen("file1_Windows.txt","r");
        int line_number = 0;
        char *temp;


       if(fin==NULL){
           printf("cannot open file1_Windows.txt\n");
       }
       while (1){

            memset(read_in_buffer,0,sizeof(read_in_buffer));
            fgets(read_in_buffer,sizeof(read_in_buffer),fin); //change to segment size?

            if (!feof(fin)) {
                if (lineNum == line_number){
                    memset(retreivedString,0,sizeof(retreivedString));
                    strcpy(retreivedString,read_in_buffer);
                }
                //printf("current line %d:     ",line_number);
                //printf("%s",read_in_buffer);
                line_number++;

            }else {
                fclose(fin);
                printf("End-of-File reached. \n");
                maxDataNum = line_number;   
                printf("maxdata: %d\n",maxDataNum);

                if (lineNum == maxDataNum){
                    endOfFileReached =  true;
                }else if (lineNum > maxDataNum){
                    printf("file read error, you're reading further that data on file\n");
                }

                break;
            }

       }

    }

Upvotes: 2

Views: 1564

Answers (4)

cyber_raj
cyber_raj

Reputation: 1857

put the fgets() line inside if() condition. After all u want to read something from file only if EOF has not been set.

if (!feof(fin)) {
    line_number++;
    fgets(read_in_buffer,sizeof(read_in_buffer),fin);  
    ...
}

Upvotes: 0

dragon135
dragon135

Reputation: 1376

Here is what standard says about fgets:

Synopsis

char *fgets(char * restrict s, int n, FILE * restrict stream);

Description

The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.

Returns

The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.

So, here is what happens:

  1. When reading the last line, fgets returns read_in_buffer (not null pointer) because there are characters read and no read error occurs.
  2. Then the check feof(fin) returns true (because EOF already reached), that makes this code never executed: strcpy(retreivedString,read_in_buffer).

Conclusion:

  • retreivedString is never modified and because it is a global variable, it was initialized with 0 bits (equivalent as an empty string).

So if you print retreivedString, the output will be an empty string.

Upvotes: 3

Femi
Femi

Reputation: 64700

Do this. It returns if the fopen call fails and puts the fgets call in the while loop:

void getString(int lineNum){
        FILE *fin=fopen("file1_Windows.txt","r");
        int line_number = 0;
        char *temp;


       if(fin==NULL){
           printf("cannot open file1_Windows.txt\n");
           return;
       }
       memset(read_in_buffer,0,sizeof(read_in_buffer));
       while (fgets(read_in_buffer,sizeof(read_in_buffer),fin) != NULL){
            if (lineNum == line_number){
                memset(retreivedString,0,sizeof(retreivedString));
                strcpy(retreivedString,read_in_buffer);
            }
            //printf("current line %d:     ",line_number);
            //printf("%s",read_in_buffer);
            line_number++;
        memset(read_in_buffer,0,sizeof(read_in_buffer));
       }
       fclose(fin);
       printf("End-of-File reached. \n");
       maxDataNum = line_number;   
       printf("maxdata: %d\n",maxDataNum);
       if (lineNum == maxDataNum){
            endOfFileReached =  true;
       }else if (lineNum > maxDataNum){
            printf("file read error, you're reading further that data on file\n");
       }
    }

Upvotes: 3

jonsca
jonsca

Reputation: 10381

Rather than testing feof (see this thread for reasons not to) within the while loop, test to see if read_in_buffer is null, as once you've run out of lines to read, that pointer becomes null. You could even put your fgets as your if statement body:

if (fgets(read_in_buffer,sizeof(read_in_buffer),fin))
{

}

Upvotes: 2

Related Questions