Ludzie pragną czasami się rozstawać, żeby móc tęsknić, czekać i cieszyć się z powrotem.
The appropriate constructor isComment
ostrstream::ostrstream(char*, int, int = ios::out);
The first argument is the preallocated buffer where the characters will end up, the second is the size of the buffer, and the third is the mode. If the mode is left as the default, characters are formatted into the starting address of the buffer. If the mode is either ios::ate or ios::app (same effect), the character buffer is assumed to already contain a zero-terminated string, and any new characters are added starting at the zero terminator.Comment
The second constructor argument is the size of the array and is used by the object to ensure it doesn’t overwrite the end of the array. If you fill the array up and try to add more bytes, they won’t go in.Comment
An important thing to remember about ostrstreams is that the zero terminator you normally need at the end of a character array is not inserted for you. When you’re ready to zero-terminate the string, use the special manipulator ends.Comment
Once you’ve created an ostrstream you can insert anything you want, and it will magically end up formatted in the memory buffer. Here’s an example:Comment
//: C05:Ostring.cpp
// Output strstreams
#include <iostream>
#include <strstream>
using namespace std;
int main() {
const int sz = 100;
cout << "type an int, a float and a string:";
int i;
float f;
cin >> i >> f;
cin >> ws; // Throw away white space
char buf[sz];
cin.getline(buf, sz); // Get rest of the line
// (cin.rdbuf() would be awkward)
ostrstream os(buf, sz, ios::app);
os << endl;
os << "integer = " << i << endl;
os << "float = " << f << endl;
os << ends;
cout << buf;
cout << os.rdbuf(); // Same effect
cout << os.rdbuf(); // NOT the same effect
} ///:~
This is similar to the previous example in fetching the int and float. You might think the logical way to get the rest of the line is to use rdbuf( ); this works, but it’s awkward because all the input including newlines is collected until the user presses control-Z (control-D on Unix) to indicate the end of the input. The approach shown, using getline( ), gets the input until the user presses the carriage return. This input is fetched into buf, which is subsequently used to construct the ostrstream os. If the third argument ios::app weren’t supplied, the constructor would default to writing at the beginning of buf, overwriting the line that was just collected. However, the “append” flag causes it to put the rest of the formatted information at the end of the string.Comment
You can see that, like the other output streams, you can use the ordinary formatting tools for sending bytes to the ostrstream. The only difference is that you’re responsible for inserting the zero at the end with ends. Note that endl inserts a newline in the strstream, but no zero.Comment
Now the information is formatted in buf, and you can send it out directly with cout << buf. However, it’s also possible to send the information out with os.rdbuf( ). When you do this, the get pointer inside the streambuf is moved forward as the characters are output. For this reason, if you say cout << os.rdbuf( ) a second time, nothing happens – the get pointer is already at the end.Comment
Automatic storage allocation
Output strstreams (but not istrstreams) give you a second option for memory allocation: they can do it themselves. All you do is create an ostrstream with no constructor arguments:Comment
ostrstream a;
Now a takes care of all its own storage allocation on the heap. You can put as many bytes into a as you want, and if it runs out of storage, it will allocate more, moving the block of memory, if necessary.Comment
This is a very nice solution if you don’t know how much space you’ll need, because it’s completely flexible. And if you simply format data into the strstream and then hand its streambuf off to another iostream, things work perfectly:Comment
a << "hello, world. i = " << i << endl << ends;
cout << a.rdbuf();
This is the best of all possible solutions. But what happens if you want the physical address of the memory that a’s characters have been formatted into? It’s readily available – you simply call the str( ) member function:Comment
char* cp = a.str();
There’s a problem now. What if you want to put more characters into a? It would be OK if you knew a had already allocated enough storage for all the characters you want to give it, but that’s not true. Generally, a will run out of storage when you give it more characters, and ordinarily it would try to allocate more storage on the heap. This would usually require moving the block of memory. But the stream objects has just handed you the address of its memory block, so it can’t very well move that block, because you’re expecting it to be at a particular location.Comment
The way an ostrstream handles this problem is by “freezing” itself. As long as you don’t use str( ) to ask for the internal char*, you can add as many characters as you want to the ostrstream. It will allocate all the necessary storage from the heap, and when the object goes out of scope, that heap storage is automatically released.Comment