ASCII Files as I/O


-Many programs IRW use files for I/O - much faster and fewer mistakes than human I/O

-Also useful for testing/validation - can quickly alter data file to test different functionality

-We will use files of ASCII characters, often called text files, in this section (There are other files of non-text data, computer-readable only, but we'll learn them next quarter.)

-Recall that for interactive I/O, we #included <iostream.h> so we could use the objects cin and cout

-cin is an object of the istream class (found in iostream.h library)

-cout is an object of the ostream class (found in iostream.h library)

-To use text files, must #include the <fstream.h> library, to use objects of the fstream class for our I/O operations

-Then, we must declare data objects, which are character string constants, to contain the actual filenames of the files the program will use (the names the files have on the disk)

-We must also open each file before using, and close each file when we are done.

EXAMPLE (recall from while loop section):

//read in (FROM A FILE) and (PRINT TO FILE) the average of a series of temperatures:

#include <iostream.h>		//contains ios and cerr definitions
#include <fstream.h>		//contains fstream definition
#include <stdlib.h>		//contains exit() definition (for errors)

int main(void) { const char InFileName[] = "temps.dat"; //hold name of input file OutFileName[] = "temps.out"; //hold name of output file ErrMsg[] = "\n*** main: unable to open file: "; fstream InStream, OutStream; //I/O streams for files int sum = count = 0; double temp; //open input file for reading: InStream.open(InFileName, ios::in);
//check to make sure file opened: if (InStream.fail()) { cerr << ErrMsg << InFileName << endl << endl; exit(-1); //stops program here! }
//if file OK, then proceed: InStream >> temp; // prime read 1st temp
//process file until end: while (!InStream.eof()) { sum += temp; count++; InStream >> temp; } //close input file: InStream.close();
//open output file: OutStream.open(OutFileName, ios::out); //print to output file: if (count) OutStream << sum/count << endl; else OutStream << "No temperatures entered. Average not computed.\n";
//close output file: OutStream.close(); return 0; }//end of program

In the above example, we #include 2 new libraries: fstream.h, stdlib.h, to be able to use objects defined within their classes

Specifically, fstream.h allows us to declare two data objects of the fstream class: InStream & Outstream

InStream connects program input to the designated input file, instead of the keyboard - note that all operations on the input file (opening, checking success of open, reading from and closing) use this variable (note especially: that reading from the file uses the >> operator, just like cin)

OutStream connects program output to the designated output file, instead of the monitor - note that all operations on the output file (opening, checking success of open, writing to and closing) use this variable (note especially: that reading from the file uses the << operator, just like cout)

We also declare 3 character string constant objects: InFileName[ ], OutFileName[ ] & ErrMsg[ ]

(don't worry about what the [ ]'s are for -- next quarter!)

These hold the strings specifying the 2 file names and an error message - they are constants, since they will not change thru the life of the program. If the names of either file changes, you can change the declaration at the top

Note that these string constants are only used in the file open statement, when attaching the particular stream to the actual file. All other references to the file use the variable data objects of the fstream class (in this case, InStream & OutStream)

Lastly, note that there is no significance to the identifers InStream, OutStream, InFileName[ ], OutFileName[ ], and ErrMsg[ ] - we declared them, so we can name them anything we want! (Just use meaningful names)

Let's look closer at the file handling in the example:

fstream objects: generally, declare an fstream object for each file the program will use, eg, InStream for input file stream and OutStream for output file stream

operations on fstream objects: all objects in C++ can have operations defined for use on them - fstream objects have many operations defined in the libraries, but we'll only look at 6:

Note, that to apply these member functions to the particular object, use the dot notation (a period) to connect the member function to the class object: ObjectName.MemberFunction( ) (you don't need to know exactly what's going on at this point! Just know how to use the functions described above, and that they are called member functions, and they're pre-defined for us. In later quarters, you'll define your own classes, objects and member functions!)

Note that we used these operators before, in a different way, with cin/cout, but now we're using the same operators on different operands. This is an example of what C++ calls operator overload. You'll see more of this in subsequent quarters.