int main() {
ifstream in("Iofile.cpp");
assure(in, "Iofile.cpp");
ofstream out("Iofile.out");
assure(out, "Iofile.out");
out << in.rdbuf(); // Copy file
in.close();
out.close();
// Open for reading and writing:
ifstream in2("Iofile.out", ios::in | ios::out);
assure(in2, "Iofile.out");
ostream out2(in2.rdbuf());
cout << in2.rdbuf(); // Print whole file
out2 << "Where does this end up?";
out2.seekp(0, ios::beg);
out2 << "And what about this?";
in2.seekg(0, ios::beg);
cout << in2.rdbuf();
} ///:~
The first five lines copy the source code for this program into a file called iofile.out and then close the files. This gives us a safe text file to play with. Then the aforementioned technique is used to create two objects that read and write to the same file. In cout << in2.rdbuf( ), you can see the "get" pointer is initialized to the beginning of the file. The "put" pointer, however, is set to the end of the file because "Where does this end up?" appears appended to the file. However, if the put pointer is moved to the beginning with a seekp( ), all the inserted text
String iostreams
A string stream works directly with memory instead of a file or standard output. It allows you to use the same reading and formatting functions that you use with cin and cout to manipulate bytes in memory. On old computers, the memory was referred to as
The class names for string streams echo those for file streams. If you want to create a string stream to extract characters from, you create an istringstream. If you want to put characters into a string stream, you create an ostringstream. All declarations for string stream are in the standard header
Input string streams
To read from a string using stream operations, you create an istringstream object initialized with the string. The following program shows how to use an istringstream object.
//: C04:Istring.cpp
// Input string streams
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
istringstream s("47 1.414 This is a test");
int i;
double f;
s >> i >> f; // Whitespace-delimited input
assert(i == 47);
double relerr = (fabs(f) - 1.414) / 1.414;
assert(relerr <= numeric_limits
string buf2;
s >> buf2;
assert(buf2 == "This");
cout << s.rdbuf(); // " is a test"
} ///:~
You can see that this is a more flexible and general approach to transforming character strings to typed values than the standard C library functions such as atof( ), atoi( ), even though the latter may be more efficient for single conversions.
In the expression s >> i >> f, the first number is extracted into i, and the second into f. This isn’t "the first whitespace-delimited set of characters" because it depends on the data type it’s being extracted into. For example, if the string were instead, "1.414 47 This is a test," then i would get the value 1 because the input routine would stop at the decimal point. Then f would get 0.414. This could be useful if you want to break a floating-point number into a whole number and a fraction part. Otherwise it would seem to be an error. The second assert( ) calculates the relative error between what we read and what we expected; it’s always better to do this than to compare floating-point numbers for equality. The constant returned by epsilon( ), defined in
As you may already have guessed, buf2 doesn’t get the rest of the string, just the next white-space-delimited word. In general, it’s best to use the extractor in iostreams when you know the exact sequence of data in the input stream and you’re converting to some type other than a character string. However, if you want to extract the rest of the string all at once and send it to another iostream, you can use rdbuf( ) as shown.
To test the Date extractor at the beginning of this chapter, we used an input string stream with the following test program:
//: C04:DateIOTest.cpp
//{L} ../C02/Date
#include
#include
#include "../C02/Date.h"
using namespace std;
void testDate(const string& s) {
istringstream os(s);
Date d;
os >> d;
if (os)
cout << d << endl;
else
cout << "input error with \"" << s << "\"\n";
}
int main() {
testDate("08-10-2003");