Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
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 <cassert>
#include <cmath> // For fabs()
#include <iostream>
#include <limits> // For epsilon()
#include <sstream>
#include <string>
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<double>::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( ) or 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 <limits>, represents the machine epsilon for double-precision numbers, which is the
best tolerance you can expect comparisons of doubles to satisfy.
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 <iostream>
#include <sstream>
#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 << "\"" << endl;
}
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 istringstream
so we can test the stream extractor we wrote for Date objects.
The function testDate( ) also begins to test the inserter, operator<<( ).
Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |