Files

March 4 2002

files

working with files is a three-step process:

  1. open the file
  2. do stuff with the file [read or write]
  3. close the file

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);

exercises

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.