feof, fgets and fread[ZT]
Prev: File Input and Output,
fopen and fclose
Next: rewind, fputc and fputs
Detecting the End of the File Using feof
Here’s a function you’ll be using in the future. You pass it a FILE pointer, and if you’ve reached the end of the file, feof returns 1, else it returns 0.
I’ll be using this function in the next section but in the meantime, There are a few more functions I’d like to cover…
Reading One Line at a Time Using fgets
Reading one character at a time can be a little inefficient, so we can use fgets to read 1 line at a time.
fgets takes three arguments. The first, has to be a char * – the name of a sized char array would work too. The second is an int – the maximum number of characters read per line.
The third and last, is a stream – a FILE * for example (try it with stdin and see what happens).
fgets returns NULL if the end of the file is reached, else it returns a char *.
You can’t use an !=EOF check here, as we’re not reading one character at a time (but you can use feof).
For this example, I made a file called numbers2.txt in Notepad:
111 222 333
444 555 666
777 888 999
Although it’s not obvious at first, I put tabs in the last line.
#include <stdio.h> int main() { char c[10]; <em>/* declare a char array */</em> FILE *file; <em>/* declare a FILE pointer */</em> file = fopen("numbers2.txt", "r"); <em>/* open a text file for reading */</em> if(file==NULL) { printf("Error: can't open file.n"); <em>/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */</em> return 1; } else { printf("File opened successfully. Contents:nn"); while(fgets(c, 10, file)!=NULL) { <em> /* keep looping until NULL pointer... */</em> printf("String: %s", c); <em> /* print the file one line at a time */</em> } printf("nnNow closing file...n"); fclose(file); return 0; } }
Output:
File opened successfully. Contents: |
The main area of focus is the while loop – notice how I performed the check for the return of a NULL pointer. Remember that passing in char * variable, c as the first argument assigns the line read into c, which is printed off by printf. I specified a maximum number of characters to be 10 – I knew the number of characters per line in my text file is more than this, but I wanted to show that fgets reads 10 characters at a time in this case.
Notice how fgets returns when the newline character is reached – this would explain why 444 and 777 follow the word "String". Also, the tab character, t, is treated as one character.
atoi Revisited
Notice how I’ve slipped in an extra lesson after the string section! I thought the atoi function would be especially useful when reading numerical data from an external text file.
So far, all the information extracted was returned as strings. If our text file contained numbers, we could use atoi to convert them into integer format for use in our program.
Now, fgets treats each line in your text file as a string (it stops reading when it finds a line break).
You could put each number on a separate line like this:
6
7
8
9
10
– I put this into a file called numbers3.txt so let’s get a program to add them up…
#include <stdio.h> #include <stdlib.h> <em>/* required for atoi */</em> int main() { char c[10]; int sum = 0; FILE *file; file = fopen("numbers3.txt", "r"); if(file==NULL) { printf("Error: can't open file.n"); return 1; } else { printf("File opened successfully.n"); while(fgets(c, 10, file)!=NULL) { sum += atoi(c); <em>/* convert string to int then add it to sum */</em> } printf("Now closing file...n"); fclose(file); printf("The sum of the numbers is: %dn", sum); return 0; } }
Output:
File opened successfully. |
So it looks like atoi has worked. Sometimes you can compile without including stdlib.h but your compiler may display a warning – MSVC++ did in my case.
Reading Large Amounts at a Time Using fread
The last reading function reads the entire text file.
fread takes four arguments:
The first is a char * – this could be an actual char pointer or a char array. There are differences between the two, as we’ll see later.
The second argument is the size of char, i.e. 1.
The third argument in the number of elements to read. This only has an effect if you passed a char array as opposed to a char pointer.
The last argument is the FILE pointer.
fread returns the number of characters read if you passed it a char array.
<font color="#0000ff">#include <stdio.h> int main() { FILE *file; char c[30]; <em>/* make sure it is large enough to hold all the data! */</em> char *d; int n; file = fopen("numbers.txt", "r"); if(file==NULL) { printf("Error: can't open file.n"); return 1; } else { printf("File opened successfully.n"); n = fread(c, 1, 10, file); </font><font color="#0000ff"><em>/* passing a char array, reading 10 characters */</em> c[n] = '