28. Can My Programs Save Stuff on Disk?

With Sequential Files

image

None of the programs you’ve seen so far have been able to store data for very long. Think about this for a moment: If you defined an integer variable, put a 14 in it and then turned off the computer (believe me now and try it later), that variable would no longer have 14 in it! If you turned your computer back on and tried to find the value in the variable, you couldn’t find it—no way.

This chapter explains how to save data to your disk. Once the data is on your disk, it will be there until you change or erase it. Data on your disk is just like music on a tape. You can turn off the tape deck and the tape will hold the music until you change it. There is no good reason why a user should enter data, such as historical sales records, more than once.

Note

image

Files are critical to computer data programs. How useful would a word processor be without files?

Disk Files

Disks hold data in files. You already understand the concept of files if you’ve saved a C program to a disk file. Files can hold either programs or data, as shown in Figure 28.1. Your programs must be loaded from disk into memory before you can run them. You also must load data from the disk file into variables before you can work with the data. The variables also hold data before the data goes to a disk file.

Figure 28.1. Your program file can process data files.

image

There are two types of files: sequential-access and random-access. Their types determine how you can access them. If you work with a sequential-access file, you have to read or write the file in the order of the data. In a random-access file, you can jump around, reading and writing any place in the file.

Clue

image

A sequential file is like a cassette tape, and a random-access file is like a record or a CD. You have to play songs in sequence on a tape (or fast-forward through them in order), whereas you can skip around in the music on a record or a CD.

All disk files have names that conform to the same naming rules as program names. Before you can use a disk file, whether it be to create, read, or change the data in the file, you must open the file.

Clue

image

As with a filing cabinet, you can’t use a disk file without opening the file. Instead of pulling out a drawer, your computer attaches something called a file pointer to the file and makes sure that the disk is properly set up to hold the file you specify.

Opening a File

To open a file, you must use the fopen() function, whose description is included along with printf()’s in STDIO.H. Before seeing fopen(), you have to understand the concept of a file pointer.

Note

image

The concept of a file pointer is easy to understand. A regular pointer simply holds the address of data in a variable. A file pointer simply holds the disk location of the disk file you’re working with.

There is a special statement you must specify to define a file pointer. As with any variable, you can name file pointers anything you want. Suppose you want to open an employee file. Before the fopen(), you must define a file pointer variable. If you called the file pointer fptr, here is how you would define a file pointer:

FILE * fptr;  /* Defines a file pointer named fptr */

Warning

image

Most C programmers define their file pointers before main(). This makes the file pointer global, which is a fancy term meaning that the entire program can use the file. (Most other kinds of variables are local, not global.) Because part of the file pointer statement is in uppercase, FILE is defined someplace with #define. FILE is defined in STDIO.H, which is the primary reason you should include the STDIO.H header file when your program uses the disk for data.

Once you define a file pointer, you can connect that pointer to a file with fopen(). Once you specify fopen(), you can use the file throughout the rest of the program. Here is the way to open a file named C:EMPS.DAT. (If you don’t have a C: drive, change the C: in these examples to a different drive letter.)

image

For the rest of the program, you’ll access the EMPS.DAT file via the file pointer, not via the filename. Using a file pointer variable is easier and less error-prone than typing the filename and complete pathname to the file every time you must access the file.

Warning

image

Close your filing cabinet drawers when you’re done with your files or you’ll hit your head! Close all open files after you’re through with them or you could lose some data. fclose() is the opposite of fopen(). In its parentheses, fclose() requires a file pointer of the file you want to close.

Warning

image

If the file pointer equals 0, you’ll know that an error happened (such as a disk drive door being open). C returns a 0 from fclose() if an error occurs when you open a file. For example, if you attempt to open a file on a disk drive that doesn’t exist, fclose() returns an error.

The "w" (the second argument in the previous code’s fopen()) means write. The second argument of fopen() must be one of the string mode values found in Table 28.1.

Table 28.1. The basic fopen() mode strings.

image

Using Sequential Files

There are only three things you’ll ever do with a sequential file: create it, read it, and add to it (write to it). To write to a file, you can use fprintf(). fprintf() is easy because it’s just a printf() with a file pointer at the beginning of its parentheses. The following program creates a file and writes some data to it using fprintf():

image

If you were to run this program and look at the contents of the file named MYDATA.DAT (using the DOS TYPE command, a text editor, or the C program described next), you would see this:

image

Use fgets() to read the contents of the file. fgets() is nothing more than a gets() that you can direct to a disk file. fgets() reads lines from a file into character arrays (or allocated heap memory pointed to with a character pointer).

Clue

image

Think of the f at the beginning of fputs() and fgets() as standing for file. puts() and gets() go to the screen and keyboard respectively; fputs() and fgets() write and read their data from files.

Unlike gets(), fgets() requires that you specify a maximum length for the array you’re reading into. You might read past the end of the file (producing an error) if you’re not careful, so be sure to check for the location of the end of file.

fgets() reads one line at a time. If you specify more characters to read in the fgets() than actually reside on the file’s line you’re reading, fgets() will stop reading the line of data as long as the file’s lines end with a newline character. The previous program that created the MYDATA.DAT file always wrote at the end of each line so that subsequent fgets() functions would be able to read the file line-by-line.

The following program shows you how to read a file that contains string data and check for end-of-file (with the feof() function) along the way:

image

feof() returns a true condition if you just read the last line from the file. The feof() really isn’t needed in the previous program because we know exactly what the MYDATA.DAT contains (we just created the file in an earlier program). There are three lines in the file, and three fgets() would suffice. Nevertheless, you should generally use feof() when reading from disk files. You often don’t know exactly how much data the file contains because other people using other programs may have added data to the file.

Clue

image

There is also an fscanf() you can use to read individual numeric values from a data file if you wrote the values with a corresponding fprintf().

You can add to a file by opening the file in append mode and outputting data to it. The following program adds the line That's all! to the end of the MYDATA.DAT data file:

image

Here is what MYDATA.DAT now contains (notice the extra line):

image

Clue

image

To write to a printer instead of the screen, open the DOS printer device named LPT1: or LPT2: and use that device name as the first argument of fprintf().

Rewards

image

• Store long-term data in data files.

• Open a file with fopen() before you use the file.

• Always close a file with fclose() when you’re done.

Pitfalls

image

• Don’t read from a file without checking for feof(), because you might have previously read the last line in the file.

• Don’t use the filename once you open a file. Use the file pointer that you connected to the file with fopen().

• Don’t forget that the file pointer goes at the beginning of fprintf() and that fputs() requires a file pointer at the end of its argument list.

In Review

The goal of this chapter was to show you how to create, read, and write sequential files. Your C program must open a file before data can be written to, or read from, the file. When your program is done with a file, the program should close the file.

When reading from a file, you must check for the end-of-file condition to ensure that you don’t try to read past the end of the file. The feof() function is a built-in C function that you use to check for the end of the file.

Code Example

image

Code Analysis

This code describes a complete program that stores several messages in a sequential file. First the file pointer is defined, and then some data is stored in variables.

The file is then opened. If there was not an error during the open process, three messages are written to the disk before the file is closed.

This program is simple, yet it forms the beginning of a more complete database program you might want to write. Instead of assigning data to the variables directly, you might want to ask the user for the values and store the data entered by the user.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset