Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
53
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Chapter 13: C++ Streams

Section 13.1: String streams

std::ostringstream is a class whose objects look like an output stream (that is, you can write to them via operator<<), but actually store the writing results, and provide them in the form of a stream.

Consider the following short code:

#include <sstream> #include <string>

using namespace std;

int main()

{

ostringstream ss;

ss << "the answer to everything is " << 42; const string result = ss.str();

}

The line

ostringstream ss;

creates such an object. This object is first manipulated like a regular stream:

ss << "the answer to everything is " << 42;

Following that, though, the resulting stream can be obtained like this:

const string result = ss.str();

(the string result will be equal to "the answer to everything is 42").

This is mainly useful when we have a class for which stream serialization has been defined, and for which we want a string form. For example, suppose we have some class

class foo

{

// All sort of stuff here.

};

ostream &operator<<(ostream &os, const foo &f);

To get the string representation of a foo object,

foo f;

we could use

ostringstream ss; ss << f;

const string result = ss.str();

GoalKicker.com – C++ Notes for Professionals

65

Then result contains the string representation of the foo object.

Section 13.2: Printing collections with iostream

Basic printing

std::ostream_iterator allows to print contents of an STL container to any output stream without explicit loops. The second argument of std::ostream_iterator constructor sets the delimiter. For example, the following code:

std::vector<int> v = {1,2,3,4};

std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ! "));

will print

1 ! 2 ! 3 ! 4 !

Implicit type cast

std::ostream_iterator allows to cast container's content type implicitly. For example, let's tune std::cout to print floating-point values with 3 digits after decimal point:

std::cout << std::setprecision(3); std::fixed(std::cout);

and instantiate std::ostream_iterator with float, while the contained values remain int:

std::vector<int> v = {1,2,3,4};

std::copy(v.begin(), v.end(), std::ostream_iterator<float>(std::cout, " ! "));

so the code above yields

1.000 ! 2.000 ! 3.000 ! 4.000 !

despite std::vector holds ints.

Generation and transformation

std::generate, std::generate_n and std::transform functions provide a very powerful tool for on-the-fly data manipulation. For example, having a vector:

std::vector<int> v = {1,2,3,4,8,16};

we can easily print boolean value of "x is even" statement for each element:

std::boolalpha(std::cout); // print booleans alphabetically std::transform(v.begin(), v.end(), std::ostream_iterator<bool>(std::cout, " "), [](int val) {

return (val % 2) == 0;

});

or print the squared element:

std::transform(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "), [](int val) {

return val * val;

GoalKicker.com – C++ Notes for Professionals

66

});

Printing N space-delimited random numbers:

const int N = 10;

std::generate_n(std::ostream_iterator<int>(std::cout, " "), N, std::rand);

Arrays

As in the section about reading text files, almost all these considerations may be applied to native arrays. For example, let's print squared values from a native array:

int v[] = {1,2,3,4,8,16};

std::transform(v, std::end(v), std::ostream_iterator<int>(std::cout, " "), [](int val) {

return val * val;

});

GoalKicker.com – C++ Notes for Professionals

67