cout << in2.rdbuf();
} ///:~
The first five lines copy the source code for this program into a file called iofile.outand 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 overwrites the existing text. Both writes are seen when the get pointer is moved back to the beginning with a seekg( ), and the file is displayed. Of course, the file is automatically saved and closed when out2goes out of scope and its destructor is called .
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 cinand coutto manipulate bytes in memory. On old computers, the memory was referred to as core, so this type of functionality is often called in-core formatting .
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 . As usual, there are class templates that fit into the iostreams hierarchy, as shown in the following figure: .

To read from a string using stream operations, you create an istringstreamobject initialized with the string. The following program shows how to use an istringstreamobject.
//: C04:Istring.cpp
// Input string streams
#include
#include // For fabs()
#include
#include // For epsilon()
#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::epsilon());
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 iwould get the value 1 because the input routine would stop at the decimal point. Then fwould 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 , represents the machine epsilon for double-precision numbers, which is the best tolerance you can expect comparisons of doubles to satisfy. [44] For more information on machine epsilon and floating-point computation in general, see Chuck’s article, “The Standard C Library, Part 3”, C/C++ Users Journal , March 1995, also available at www.freshsources.com/1995006a.htm.
As you may already have guessed, buf2doesn’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 Dateextractor 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");
testDate("8-10-2003");
testDate("08 - 10 - 2003");
testDate("A-10-2003");
testDate("08%10/2003");
} ///:~
Each string literal in main( )is passed by reference to testDate( ), which in turn wraps it in an istringstreamso we can test the stream extractor we wrote for Dateobjects. The function testDate( )also begins to test the inserter, operator<<( ) .
To create an output string stream to put data into, you just create an ostringstreamobject, which manages a dynamically sized character buffer to hold whatever you insert. To get the formatted result as a stringobject, you call the str( )member function. Here’s an example: .
//: C04:Ostring.cpp
// Illustrates ostringstream
#include
#include
#include
using namespace std;
int main() {
cout << "type an int, a float and a string: ";
int i;
float f;
cin >> i >> f;
cin >> ws; // Throw away white space
string stuff;
getline(cin, stuff); // Get rest of the line
ostringstream os;
os << "integer = " << i << endl;
os << "float = " << f << endl;
os << "string = " << stuff << endl;
string result = os.str();
cout << result << endl;
} ///:~
This is similar to the Istring.cppexample earlier that fetched an intand a float. A sample execution follows (the keyboard input is in bold type) .
type an int, a float and a string: 10 20.5 the end
integer = 10
float = 20.5
string = the end
You can see that, like the other output streams, you can use the ordinary formatting tools, such as the <<operator and endl, to send bytes to the ostringstream. The str( )function returns a new stringobject every time you call it so the underlying stringbufobject owned by the string stream is left undisturbed .
In the previous chapter, we presented a program, HTMLStripper.cpp, that removed all HTML tags and special codes from a text file. As promised, here is a more elegant version using string streams.
Читать дальше