working with files is a three-step process:
we use the fopen command to do step 1,
fscanf, fprintf, and feof to do
step 2, and fclose to do step 3.
fopen
fopen is used like this:
FILE* read;
FILE* write;
read = fopen("readme.txt", "r");
write = fopen("writeme.txt", "w");
fopen takes two inputs, the name of the file you want to
open, and an indicator of whether you want to read or write the file
[use "r" for reading, and "w" for
writing. it's a common mistake to put these in single quotes instead
of double quotes].
fopen returns a FILE* pointer, which is
required as an input by all other file commands [which means you
should always save it in a variable [which we do above by saying
"read = ..."], because you're going to need it later].
if you want to read a file, and the file does not exist,
fopen returns NULL. if you want to write a file, and the
file does not exist, the file will be created for you.
fscanf
fscanf is used to read from files. it's just like
scanf, except that it requires one extra input, which is
the FILE* pointer that you got from
fopen. so, the commands below will read integers,
characters, and strings from the file:
int x; char c; char str[50]; fscanf(read, "%d", &x); fscanf(read, "%c", &c); fscanf(read, "%s", str);
fprintf
fprintf is used to write to files. it's just like
printf [bet you didn't see that one coming], except that
it also requires the FILE* pointer that you got from
fopen. so, if we want to write integers, characters, and
strings to a file, we do it like this:
fprintf(write, "%d", x); fprintf(write, "%c", c); fprintf(write, "%s", str);
feof
an interesting thing about files is that if you keep reading stuff
from a file, eventually you will get to the end [and, as you can
imagine, all kinds of weird stuff happens if you try to read past the
end of the file]. to avoid this, we have a very useful function called
feof that will tell us if we have reached the end of the
file.
feof returns something besides zero if have read
past the end of the file, and it returns zero if we are still
within the file [we might be at the end of the file]. since
anything besides zero is considered true, and zero is considered
false, we can think of feof as returning true or false.
don't forget that feof tells us whether we are past the end of the file. the book doesn't make this point very clear. here's an example of feof:
if(feof(read))
{
printf("done\n");
return;
}
important: program 8.1 in the book is so wrong it's actually kind of funny. here's what the program should look like:
/* not sstudio.h */
#include <stdio.h>
void main()
{
FILE* fdes;
int x;
fdes = fopen("test.dat", "r");
while(1)
{
/* fscanf needs to be within the while loop */
fscanf(fdes, "%d", &x);
/* need to check feof immediatly after fscanf to see if we
* just went past the end of the file */
if(feof(fdes))
return;
printf("Value is %d\n", x);
}
}
fclose
when you're done reading or writing to files, you use
fclose to tell the computer that you're done. this
command is very important, because sometimes your fprintf
commands won't actually write to the file until the file is closed. to
close files, we do this:
fclose(read); fclose(write);
write a program that displays the contents of a file on the screen [one character at a time]. ask the user for the name of the file to open. if the file does not exist, print an appropriate error message.
write a program that reads text [single characters] from the user, and
writes the text to a file. ask the user for the name of the file to
write to. stop when the user types in the character "#".
write a program that compares two files [one character at a time], and
prints "same" if they are exactly the same, and
"different" if they are different in any way. ask the
user for the names of both files. if either file does not exist, print
an appropriate error message.
write a program that outputs the number of words in a file. ask the user for the name of the file.
suppose we don't want people to be able to read our text files. we can do some encryption to make it harder for nosey people to read our stuff. the function below performs rot-13 "encryption" on a single character [it's not very secure at all, unfortunately, but it's relatively simple].
char rot13(char c)
{
if('A' <= c && c <= 'Z')
return(((c-'A'+13) % 26) + 'A');
else if('a' <= c && c <= 'z')
return(((c-'a'+13) % 26) + 'a');
else
return c;
}
write a program that reads a text file and produces another file that contains the rot-13 encrypted text. ask the user for the name of the text file, and the name of the file to write to. the cool thing about rot-13 is that the encrytor is also the decryptor... if you want to decrypt an encrypted text file, just run rot-13 on it again. bonus question: why is it called rot-13? hint: take a look at what the function is doing... and don't forget that the computer uses numbers to represent characters.