ostringstream
sAn ostringstream
is useful when we need to build up our output a little at a time but do not want to print the output until later. For example, we might want to validate and reformat the phone numbers we read in the previous example. If all the numbers are valid, we want to print a new file containing the reformatted numbers. If a person has any invalid numbers, we won’t put them in the new file. Instead, we’ll write an error message containing the person’s name and a list of their invalid numbers.
Because we don’t want to include any data for a person with an invalid number, we can’t produce the output until we’ve seen and validated all their numbers. We can, however, “write” the output to an in-memory ostringstream
:
for (const auto &entry : people) { // for each entry in people
ostringstream formatted, badNums; // objects created on each loop
for (const auto &nums : entry.phones) { // for each number
if (!valid(nums)) {
badNums << " " << nums; // string in badNums
} else
// ''writes'' to formatted's string
formatted << " " << format(nums);
}
if (badNums.str().empty()) // there were no bad numbers
os << entry.name << " " // print the name
<< formatted.str() << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry.name
<< " invalid number(s) " << badNums.str() << endl;
}
In this program, we’ve assumed two functions, valid
and format
, that validate and reformat phone numbers, respectively. The interesting part of the program is the use of the string streams formatted
and badNums
. We use the normal output operator (<<
) to write to these objects. But, these “writes” are really string
manipulations. They add characters to the string
s inside formatted
and badNums
, respectively.