On the other hand, an input-file stream can be connected to a file using the member function open, but the stream cin has no member function named open.. Every object of type ifstream is
Trang 1Display 12.7 Formatting Output (part 2 of 2)
44 cout << "End of program.\n";
45 return 0;
47 //Uses <iostream>, <fstream>, and <iomanip>:
48 void makeNeat(ifstream& messyFile, ofstream& neatFile,
49 int numberAfterDecimalpoint, int fieldWidth)
51 neatFile.setf(ios::fixed);
52 neatFile.setf(ios::showpoint);
53 neatFile.setf(ios::showpos);
54 neatFile.precision(numberAfterDecimalpoint);
55 cout.setf(ios::fixed);
56 cout.setf(ios::showpoint);
57 cout.setf(ios::showpos);
58 cout.precision(numberAfterDecimalpoint);
59 double next;
60 while (messyFile >> next)
61 {
62 cout << setw(fieldWidth) << next << endl;
63 neatFile << setw(fieldWidth) << next << endl;
64 }
setf and precision behave the same for a file output stream as they do for cout.
Satisfied if there is a next number to read
Works the same for file output streams as it does for cout
neat.txt
(After program is run) +10.37000
-9.89897 +2.31300 -8.95000 +15.00000 +7.33333 +92.87650 -123.75684
S CREEN O UTPUT
+10.37000 -9.89897 +2.31300 -8.95000 +15.00000 +7.33333 +92.87650 -123.75684 End of program.
rawdata.txt
(Not changed by program) 10.37 -9.89897 2.313 -8.950 15.0 7.33333 92.8765 -1.237568432e2
Trang 2EDITING A TEXT FILE
The program discussed here is a very simple example of text editing applied to files This program can be used to automatically generate C++ advertising material from existing C advertising mate-rial (in a rather simplistic way) The program takes its input from a file that contains advertising copy that says good things about C and writes similar advertising copy about C++ in another file The file that contains the C advertising copy is called cad.txt , and the new file that receives the C++ advertising copy is called cppad.txt The program is shown in Display 12.8 The program simply reads every character in the file cad.txt and copies the characters to the file
cppad.txt Every character is copied unchanged, except that when the uppercase letter ’C’ is read from the input file, the program writes the string "C++" to the output file This program assumes that whenever the letter ’C’ occurs in the input file, it names the C programming lan-guage; so this change is exactly what is needed to produce the updated advertising copy.
Notice that the line breaks are preserved when the program reads characters from the input file and writes the characters to the output file The newline character ’\n’ is treated just like any other character It is read from the input file with the member function get , and it is written to the output file using the insertion operator, << We must use the member function get to read the input (rather than the extraction operator, >> ) because we want to read whitespace.
Stream Hierarchies: A Preview of Inheritance One very useful way to organize classes is by means of the “derived from” relationship
When we say that one class is derived from another class we mean that the derived class
was obtained from the other class by adding features For example, the class of
input-file streams is derived from the class of all input streams by adding additional member
functions such as open and close The stream cin belongs to the class of all input
streams, but does not belong to the class of input-file streams because cin has no mem-ber functions named open and close This section introduces the notion of a derived class as a way to think about and organize the predefined stream classes (Chapter 14 shows how to use the idea of a derived class to define classes of your own.)
Both the predefined stream cin and an input-file stream are input streams So in some sense they are similar For example, you can use the extraction operator, >>, with either kind of stream On the other hand, an input-file stream can be connected to a file using the member function open, but the stream cin has no member function named open An input-file stream is a similar but different kind of stream than cin An input-file stream is
of type ifstream The object cin is an object of the class istream (spelled without the
’f’) The classes ifstream and istream are different but closely related types The class
ifstream is a derived class of the class istream Let’s see what that means
12.3
Trang 3Display 12.8 Editing a File of Text (part 1 of 2)
1 //Program to create a file called cplusad.txt that is identical to the file
2 //cad.txt except that all occurrences of ’C’ are replaced by "C++" Assumes
3 //that the uppercase letter ’C’ does not occur in cad.txt except as the
4 //name of the C programming language.
5 #include <fstream>
6 #include <iostream>
7 #include <cstdlib>
8 using std::ifstream;
9 using std::ofstream;
10 using std::cout;
11 void addPlusPlus(ifstream& inStream, ofstream& outStream);
12 //Precondition: inStream has been connected to an input file with open.
13 //outStream has been connected to an output file with open.
14 //Postcondition: The contents of the file connected to inStream have been
15 //copied into the file connected to outStream, but with each ’C’ replaced
16 //by "C++" (The files are not closed by this function.)
17 int main( )
19 ifstream fin;
20 ofstream fout;
21 cout << "Begin editing files.\n";
22 fin.open("cad.txt");
23 if (fin.fail( ))
24 {
25 cout << "Input file opening failed.\n";
26 exit(1);
27 }
28 fout.open("cppad.txt");
29 if (fout.fail( ))
30 {
31 cout << "Output file opening failed.\n";
32 exit(1);
33 }
34 addPlusPlus(fin, fout);
Trang 4Display 12.8 Editing a File of Text (part 2 of 2)
35 fin.close( );
36 fout.close( );
37 cout << "End of editing files.\n";
38 return 0;
40 void addPlusPlus(ifstream& inStream, ofstream& outStream)
42 char next;
43 inStream.get(next);
44 while (! inStream.eof( ))
45 {
46 if (next == ’C’)
47 outStream << "C++";
48 else
49 outStream << next;
50 inStream.get(next);
51 }
C is one of the world’s most modern programming languages There is no language as versatile as C, and C
is fun to use.
C++ is one of the world’s most modern programming languages There is no language as versatile as C++, and C++
is fun to use.
cad.txt
(Not changed by program)
cppad.txt
(After program is run)
Begin editing files.
End of editing files.
S CREEN O UTPUT
Trang 5When we say that some class D is a derived class of some other class B, it means
that class D has all the features of class B but it also has added features For example,
any stream of type istream (without the ’f’) can be used with the extraction operator,
>> The class ifstream (with the ’f’) is a derived class of the class istream, so an object
of type ifstream can be used with the extraction operator, >> An object of the class
ifstream has all the properties of an object of type istream In particular, an object of
the class ifstream is also an object of type istream
However, ifstream has added features so that you can do more with an object of
type ifstream than you can with an object that is only of type istream For example,
one added feature is that a stream of type ifstream can be used with the function open
The stream cin is only of type istream and not of type ifstream You cannot use cin
with the function open Notice that the relationship between the classes ifstream and
istream is not symmetric Every object of type ifstream is of type istream (a file input
stream is an input stream), but an object of type istream need not be of type ifstream
(the object cin is of type istream but not of type ifstream)
The idea of a derived class is really quite common An example from everyday life
may help to make the idea clearer The class of all convertibles, for instance, is a derived
class of the class of all automobiles Every convertible is an automobile, but a
convert-ible is not just an automobile A convertconvert-ible is a special kind of automobile with special
properties that other kinds of automobiles do not have If you have a convertible, you
can lower the top so that the car is open (You might say that a convertible has an
“open” function as an added feature.)
If D is a derived class of the class B, then every object of type D is also of type B A
convertible is also an automobile A file input stream (object of the class ifstream) is
also an input stream (also an object of the class istream) So, if we use istream as the
type for a function parameter, rather than using ifstream, then more objects can be
plugged in for the parameter Consider the following two function definitions, which
differ only in the type of the parameter (and the function name):
void twoSumVersion1(ifstream& sourceFile) //ifstream with an ’f’
{
int n1, n2;
sourceFile >> n1 >> n2;
cout << n1 << " + " << n2 << " = " << (n1 + n2) << endl;
}
and
void twoSumVersion2(istream& sourceFile) //istream without an ’f’
{
int n1, n2;
sourceFile >> n1 >> n2;
cout << n1 << " + " << n2 << " = " << (n1 + n2) << endl;
}
derived class
Trang 6With twoSumVersion1, the argument must be of type ifstream So if fileIn is a file input stream connected to a file, then
twoSumVersion1(fileIn);
is legal, but
twoSumVersion1(cin); //ILLEGAL
is not legal, because cin is not of type ifstream The object cin is only a stream and only of type istream; cin is not a file input stream
The function twoSumVersion2 is more versatile Both of the following are legal:
twoSumVersion2(fileIn);
twoSumVersion2(cin);
The moral is clear: Use istream, not ifstream, as a parameter type whenever you can When choosing a parameter type, use the most general type you can (To draw a real-life analogy: You might prefer to own a convertible, but you would not want a garage that could only hold a convertible What if you borrowed a sedan from a friend? You’d still want to be able to park the sedan in your garage.)
You cannot always use the parameter type istream instead of the parameter type
ifstream If you define a function with a parameter of type istream, then that param-eter can only use istream member functions In particular, it cannot use the functions
open and close If you cannot keep all calls to the member functions open and close
outside the function definition, then you must use a parameter of type ifstream
So far we have discussed two classes for input streams: istream and its derived class
ifstream The situation with output streams is similar Chapter 1 introduced the out-put streams cout and cerr, which are in the class ostream This chapter introduced the file output streams, which are in the class ofstream (with an ’f’) The class ostream is the class of all output streams The streams cout and cerr are of type ostream, but not
of type ofstream In contrast to cout or cerr, an output-file stream is declared to be of type ofstream The class ofstream of output-file streams is a derived class of the class
ostream For example, the following function writes the word "Hello" to the output stream given as its argument
void sayHello(ostream& anyOutStream) {
anyOutStream << "Hello";
}
The first of the following calls writes "Hello" to the screen; the second writes "Hello"
to the file with the external file name afile.txt
ofstream fout;
fout.open("afile.txt");
sayHello(cout);
sayHello(fout);
ostream and
ofstream
Trang 7Note that an output-file stream is of type ofstream and of type ostream Derived classes are often discussed using the metaphor of inheritance and family
relationships If class D is a derived class of class B, then class D is called a child of class
B and class B is called a parent of class D The derived class is said to inherit the
mem-ber functions of its parent class For example, every convertible inherits the fact that it has four wheels from the class of all automobiles, and every input-file stream inherits the extraction operator, >>, from the class of all input streams This is why the topic of
derived classes is often called inheritance
ANOTHER newLine FUNCTION
As an example of how you can make a stream function more versatile, consider the function new-Line that we defined in Display 9.2 That function works only for input from the keyboard, which
is input from the predefined stream cin The function newLine in Display 9.2 has no arguments
Below we have rewritten the function newLine so that it has a formal parameter of type istream
for the input stream:
//Uses <iostream>:
void newLine(istream& inStream) {
char symbol;
do
{
M AKING S TREAM P ARAMETERS V ERSATILE
If you want to define a function that takes an input stream as an argument and you want that argument to be cin in some cases and an input-file stream in other cases, then use a formal parameter of type istream (without an ’f’ ) However, an input-file stream, even if used as an argument of type istream , must still be declared to be of type ifstream (with an ’f’ ).
Similarly, if you want to define a function that takes an output stream as an argument and you want that argument to be cout in some cases and an output-file stream in other cases, then use a formal parameter of type ostream However, an output-file stream, even if used as an argument
of type ostream , must still be declared to be of type ofstream (with an ’f’ ) You cannot open
or close a stream parameter of type istream or ostream Open these objects before passing them to your function and close them after the function call.
The stream classes istream and ostream are defined in the iostream library and placed in the
std namespace One way to make them available to your code is the following:
#include <iostream>
using std::istream;
using std::ostream;
inheritance child parent
Trang 8inStream.get(symbol);
} while (symbol != ’\n’);
}
Now, suppose your program contains this new version of the function newLine If your program
is taking input from an input stream called fin (which is connected to an input file), the follow-ing will discard all the input left on the line currently befollow-ing read from the input file:
newLine(fin);
If your program is also reading some input from the keyboard, the following will discard the remainder of the input line that was typed in at the keyboard:
newLine(cin);
If your program has only the above rewritten version of newLine , which takes a stream argument such as fin or cin , you must always give the stream name, even if the stream name is cin But thanks to overloading, you can have both versions of the function newLine in the same program: the version with no arguments that is given in Display 9.2 and the version with one argument of type istream that we just defined In a program with both definitions of newLine , the following two calls are equivalent:
newLine(cin);
and
newLine( );
You do not really need two versions of the function newLine The version with one argument of type istream can serve all your needs However, many programmers find it convenient to have a version with no arguments for keyboard input, since keyboard input is used so frequently.
An alternative to having two overloaded versions of the newLine function is to use a default argument (as discussed in Chapter 4) In the following code, we have rewritten the newLine
function a third time:
//Uses <iostream>:
void newLine(istream& inStream = cin) {
char symbol;
do { inStream.get(symbol);
} while (symbol != '\n');
}
If we call this function as
newLine( );
using both
versions
of newLine
Trang 9Self-Test Exercises
the formal parameter takes the default argument cin If we call this as
newLine(fin);
the formal parameter takes the argument fin
An alternative to using this newLine function is to use the function ignore , which we discussed
in Chapter 9 The function ignore is a member of every input-file stream as well as a member of
cin
13 What is the type of the stream cin? What is the type of the stream cout?
14 Define a function called copyChar that takes one argument that is an input stream When
called, copyChar will read one character of input from the input stream given as its argu-ment and will write that character to the screen You should be able to call your function using either cin or an input-file stream as the argument to your function copyChar (If the argument is an input-file stream, then the stream is connected to a file before the function
is called, so copyChar will not open or close any files.) For example, the first of the follow-ing two calls to copyChar will copy a character from the file stuff.txt to the screen, and the second will copy a character from the keyboard to the screen:
ifstream fin;
fin.open("stuff.txt");
copyChar(fin);
copyChar(cin);
15 Define a function called copyLine that takes one argument that is an input stream When
called, copyLine reads one line of input from the input stream given as its argument and writes that line to the screen You should be able to call your function using either cin or
an input-file stream as the argument to your function copyLine (If the argument is an input-file stream, then the stream is connected to a file before the function is called, so
copyLine will not open or close any files.) For example, the first of the following two calls
to copyLine will copy a line from the file stuff.txt to the screen, and the second will copy a line from the keyboard to the screen:
ifstream fin;
fin.open("stuff.txt");
copyLine(fin);
copyLine(cin);
16 Define a function called sendLine that takes one argument that is an output stream
When called, sendLine reads one line of input from the keyboard and outputs the line to the output stream given as its argument You should be able to call your function using either cout or an output-file stream as the argument to your function sendLine (If the
ignore
Trang 10argument is an output-file stream, then the stream is connected to a file before the function
is called, so sendLine will not open or close any files.) For example, the first of the follow-ing calls to sendLine will copy a line from the keyboard to the file morestuf.txt, and the second will copy a line from the keyboard to the screen:
ofstream fout;
fout.open("morestuf.txt");
cout << "Enter 2 lines of input:\n";
sendLine(fout);
sendLine(cout);
17 Is the following statement true or false? If it is false, correct it In either event, explain it carefully
A function written using a parameter of class ifstream or ofstream can be called with
istream or ostream arguments, respectively
Random Access to Files
Any time, any where.
Common response to a challenge for a confrontation The streams for sequential access to files, which we discussed in the previous sections of this chapter, are the ones most often used for file access in C++ However, some appli-cations that require very rapid access to records in very large databases require some sort
of random access to particular parts of a file Such applications might best be done with specialized database software But perhaps you are given the job of writing such a pack-age in C++, or perhaps you are just curious about how such things are done in C++ C++ does provide for random access to files so that your program can both read from and write to random locations in a file This section gives a brief glimpse of this ran-dom access to files This is not a complete tutorial on ranran-dom access to files, but will let you know the name of the main stream class used and the important issues you will encounter
If you want to be able to both read and write to a file in C++, you use the stream class fstream that is defined in the <fstream> library The definition of fstream is placed in the std namespace
Details about opening a file and connecting it to a stream in the class fstream are basically the same as discussed for the classes ifstream and ofstream, except that
fstream has a second argument to open This second argument specifies whether the stream is used for input, output, or both input and output For example, a program that does both input and output to a file named "stuff" might start as follows:
12.4