LeonardoA
LeonardoA

Reputation: 3

Getc over-read a \n character


I'm having some problems with this little function that can read a file:

void ReadFile(char *name) {
FILE *fr;
int lenght, i;
fr = fopen(name, "r");  //Open the file reader
fseek(fr, 0, 2);        //Set the pointer at the EOF
lenght = ftell(fr);     //Read the ending position
printf("\nDEBUG lenght:%d\n", lenght);
fseek(fr, 0, 0);        //Return at the beginning of the file

printf("File read:\n\n");
for (i = 1; i <= lenght; i++) {
    printf("%c", getc(fr));
    fseek(fr, i, 0);
}
fclose(fr);
}

This is the file that it reads:

qwerty

asdfgh
zxcvbn

But this is the output of the program:

DEBUG lenght:24
File read:

qwerty



asdfgh

zxcvbn

It is basically reading an extra "\n" when there is one before.
Any ideas of why the code doesn't work?

Thanks

Upvotes: 0

Views: 344

Answers (2)

user3629249
user3629249

Reputation: 16540

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. properly checks for errors

and now, the proposed code:

#include <stdio.h>   // EOF, fopen(), getc(), putc() fclose() puts() perror()
#include <stdlib.h>  // exit(), EXIT_FAILURE

// prototype
void ReadFile(char *filename);


void ReadFile(char *filename)
{
    FILE *fp = fopen( filename, "r" );

    if( !fp )
    {
        perror( "fopen failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    puts("File read:\n");

    int ch;
    while( (ch = getc( fp )) != EOF )
    {
        putchar( ch );
    }

    fclose(fp);
}

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

If you open a file in text mode (as you do), then a call to fseek may only contain offset values that have been previously retrieved by an ftell function (cf, for example, cppreference/fseek):

If the stream is open in text mode, the only supported values for offset are zero (which works with any origin) and a value returned by an earlier call to ftell on a stream associated with the same file (which only works with origin of SEEK_SET).

In your for-loop, however, you are passing the value of i, which is not retrieved by ftell.

Besides that, your fseek in the loop is superflous, as fgetc moves the read pointer forward anyway. So for (i = 1; i <= lenght; i++) { printf("%c", getc(fr)); } should do the job.

Upvotes: 2

Related Questions