justik
justik

Reputation: 4265

C++ last character in file

I would like to get the last character in file using the following code

 FILE * f = fopen ( f_text, "r" );
 if (f )
 {
    if (fseek( f, -1, SEEK_END ) != 0 ) fclose (f);
    char last[1]; 
    fgets(last, 1, f );
    ...

but only "" is stored in variable last. Where is the bug?

Is there any problem with unicode files? Thanks for your help.

Upvotes: 2

Views: 8174

Answers (3)

octopusgrabbus
octopusgrabbus

Reputation: 10695

I made some changes to your code to print the last character. Here is test.c as a sample:

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

int main(int argc, char *argv[])
{

    FILE * f;
    char * f_text = "temp.txt";

    f = fopen ( f_text, "r" );
    if (f )
    {

        if (fseek( f, -2, SEEK_END ) == 0 ) 
        {
            char last[2] = {0}; 
            printf("Got here.\n");
            last[0] = fgetc( f );
            printf("%s\n", last);
        }
    }

    return 0;
}

and here is temp.txt displayed at the command line.

octopusgrabbus@steamboy:~/scratch$ cat temp.txt
This is a test.
octopusgrabbus@steamboy:~/scratch$ 

I changed your fseek to seek two from the end, so test would print the period. As another answer indicated, I used fgetc instead of fgets, because you were looking for an individual character, not a full string.

I also changed last to last[2] and initialized to zero, so I could treat the last character as a zero-terminated string for demo purposes.

Upvotes: 0

jxh
jxh

Reputation: 70472

The problem is that fgets will form a string. Since you only gave it one byte to work with, it can only return you an empty string, since it needs that byte to store the '\0'.

As James Kanze pointed out to me, you can only use fseek the way you want portably if you have opened the file in binary mode. Since the file is now in binary mode, it would be inappropriate to use fgets. So you would use fread instead.

FILE *f = fopen(f_text, "rb");
if (f == 0) throw 0;
try {
    if (fseek(f, -1, SEEK_END) != 0) throw 0;
    char last[1];
    if (fread(last, 1, 1, f) != 1) throw 0;
    //...
}
catch (...) {
    fclose(f);
    throw;
}
fclose(f);

Upvotes: 4

nav_jan
nav_jan

Reputation: 2553

Try using fgetc instead of fgets

Upvotes: 1

Related Questions