Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I read lines from bottom up using C?

Tags:

c

file-read

I need to read numbers which are listed in a file from bottom up. How can I do that using C?

The file is like:

4.32
5.32
1.234
0.123
9.3
6.56
8.77

For example, I want to read the last three numbers. They have to be float type.

8.77
6.56
9.3

PS.: Actually I need a solution which is playing with the file pointer position using fseek, etc.

like image 363
Erol Guzoğlu Avatar asked Apr 26 '15 22:04

Erol Guzoğlu


2 Answers

It's important to understand that no modern operating system tracks the position of line breaks within a file. (VMS could, and I'm pretty sure so could some IBM mainframe operating systems, but you're probably not using any of those.) So it's not possible to seek to a line boundary. It is also not possible to read byte-by-byte in reverse order.

Therefore, the simplest way to read the last three numbers in the file, in reverse, is to read the entire file in forward order, keeping the most recently seen three numbers in a buffer. When you hit EOF, just process that buffer backward.

A more efficient, but significantly more complicated, technique is to guess a position close to but before the last three numbers in the file; seek to that position, then discard characters till you hit a line break; and use the technique in the previous paragraph from that point. If you guessed wrong and the buffer winds up with fewer than three numbers in it, guess again.

And a third approach would be to use fseek (with SEEK_END) and fread to read the last 1024 or so bytes of the file, set a pointer to the end of the block, and parse it backward. This would be quite efficient, but would have even more headache-inducing corner cases to get right than the previous suggestion. (What exactly do you do if the last three lines of the file, collectively, are more than 1024 bytes long?)

FYI, the correct way to read floating-point numbers in C is to use fgets and strtod. DO NOT use either atof or scanf for this; atof doesn't tell you about syntax errors, and scanf triggers undefined behavior on overflow.

P.S. If you have the shell utility tac (which is a GNUism), the easiest option of all would be to write your program to process the first three numbers on standard input, and then invoke it as tac < input.file | ./a.out. Skimming the code leads me to believe that tac implements my "third approach", with some additional cleverness.

like image 117
zwol Avatar answered Nov 15 '22 12:11

zwol


Well, the obvious way is to read them all, put them into an array and then get the last three.

like image 6
Joshua Byer Avatar answered Nov 15 '22 13:11

Joshua Byer