Printing out a stringstream using str() and rdbuf() - c++

When I have:
std::ostringstream oss("Hello");
Why does this work:
std::cout << oss.str();
but this doesn't print anything:
std::cout << oss.rdbuf();
Reading the definition of operator<<(std::ostream&, std::streambuf*) say that it will print characters from the buffer. Does oss.rdbuf() not contain anything?

This issue is related to the fact that here, oss is ostringstream object (ostringstream is output stream so its destination is to write to it and not to read from it) and to fact how streams manage its internal buffer.
You can change
std::ostringstream oss("Hello");
to
std::istringstream oss("Hello"); // or std::stringstream oss("Hello");
and it will work as expected. Alternatively use
std::cout << oss.rdbuf()->str(); // this will print a copy of all buffer content
Example:
#include <iostream>
#include <sstream>
int main() {
std::ostringstream oss("Hello");
std::istringstream oss2("Hello");
cout << oss.rdbuf()->str() << endl; // prints "Hello"
cout << oss2.rdbuf(); // prints "Hello"
return 0;
}

Objects of ostringstream class use a string buffer that contains a sequence of characters. This sequence of characters can be accessed directly as a string object, using member str. That explains first part.
std::ostringstream oss("Hello");
std::cout << oss.str(); // works
The rdbuf returns pointer to the associated streambuf object, which is charge of all input/output operations. Thus, you need to use str() again to print the contents as in:
std::cout << oss.rdbuf()->str();
instead of:
std::cout << oss.rdbuf();

Related

C++ << no operator found

string toString() {
std::stringstream punkte;
std::stringstream name;
std::cout << name << "hat" << punkte << "Punkte" << '\n'
return 0;
}
At this line of code. I'm receiving the error C++ << no operator found
I can't figure out what my mistake is. I have read and tried different solutions. But nothing works. Can somebody please help?
std::cout << name << "hat" << punkte << "Punkte" << '\n';
I also included this in my code:
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream, std::stringbuf
#include <fstream>
There is no overload of operator<<() that will format a std::stringstream to a std::ostream. There error does not lie.
You are trying to call operator "<<" with a stringstream parameter. In other words:
std::cout << name;
Is equivalent to:
std::cout.operator<<(name);
And that operator<<(const std::stringstream&) function doesn't exists.
I think that what you want to do is assign each stringstream their values and then print both, isn't?
string toString()
{
std::stringstream punkte;
std::stringstream name;
name << "hat";
punkte << "Punkte";
std::cout << name.str() << punkte.str() << std::endl;
return name.str();
}
Be careful with your return value, and remember that a std::stringstream is not a std::string. If you want to retrieve the std:string in the stream, you must call the str() method.

How can I convert the output from a ostream_iterator to a string?

I am implementing a toString method in C++ primarily using the ostream_iterator.
std::ostream_iterator<int> output(std::cout, " ");
After printing to the console, however, I wish to return the output of the ostream_iterator as a string. Is this direct conversion possible?
Yes, just replace cout with stringstream and you can create string from it.
std::stringstream ss; // #include <sstream>
std::ostream_iterator<int> output(ss, " ");
std::string s(ss.str());
Is this direct conversion possible?
I think, no, because ostream_iterator is used to send data to stream one way, so if the destination is std::cout you cannot use ostream_iterator to get data back.
But you can use some other destination, e.g. ostringstream object, and then use it for both output through cout and use again as you like.
Consider simple example:
std::stringstream buff;
std::ostream_iterator<int> output(buff, " ");
std::istringstream str("10 3 ABC 7 1");
// just copy only first integer values from str (stop on the first non-integer)
std::copy(std::istream_iterator<int>(str), std::istream_iterator<int>(), output);
// output as a string to std output
std::cout << buff.str() << std::endl;
// do something else
buff.seekp(0, std::ios::end);
std::cout << "String size is " << buff.tellp() << std::endl;
If you want a string-like object that uses the std::ostream interface rather than the STL container interface, that’s std::stringstream, or the deprecated std::strstream The closest thing to a generic wrapper that turns anything that can be serialized with cout << into a std::string would be to write to a std::stringstream and then read the data back out. This will end up making at least one expensive copy, however. Here’s an implementation:
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
using std::cout;
using std::endl;
using isit = std::istream_iterator<char>;
template <typename T> std::string to_string(const T& x)
// Must be able to print a T with std::ostream::operator<<.
{
std::stringstream buffer;
buffer << x;
const isit begin(buffer); // The start of the stream object.
static const isit end; // Default object is the end-of-stream iterator.
return std::string( begin, end );
}
int main(void)
{
const std::string output_string = to_string("Testing:") + " " +
to_string(1) + ", " + to_string(2ULL) + ", " + to_string(3.0) +
to_string('.');
cout << output_string << endl;
return EXIT_SUCCESS;
}
You can use a std::ostream_iterator<char> to write to a std::stringstream, rather than <<, and then a std::istream_iterator<char> as shown to copy from that to a string.
You can write data from a std::istream to a std::string with a std::istream_iterator. Sort of. The formatting can be wonky.
If you want to read data from a std::string using an iterator, its iterator type is std::string::iterator and an iterator to the front of the string is s.begin(), like other STL containers.
If you just have a bunch of data stored in memory that you want to send to both an output iterator and a string, you can use one of its other constructors.

How can I obtain the length of a const stringstream's buffer without copying or seeking?

I have a const std::stringstream and a desire to find out how many bytes there are in its underlying string buffer.
I cannot seekg to the end, tellg then seekg to the start again, because none of these operations are available constly.
I do not want to get the str().size() because str() returns a copy and this may not be a trivial amount of data.
Do I have any good options?
(The stream itself is presented to me as const, only because it is a member of another type, and I receive a const reference to an object of that type. The stream represents the contents of a "document", its encapsulating object represents a CGI response and I am trying to generate an accurate Content-Length HTTP header line from within operator<<(std::ostream&, const cgi_response&).)
I've never been very comfortable with stream buffers, but this seems to work for me:
#include <iostream>
#include <sstream>
std::stringstream::pos_type size_of_stream(const std::stringstream& ss)
{
std::streambuf* buf = ss.rdbuf();
// Get the current position so we can restore it later
std::stringstream::pos_type original = buf->pubseekoff(0, ss.cur, ss.out);
// Seek to end and get the position
std::stringstream::pos_type end = buf->pubseekoff(0, ss.end, ss.out);
// Restore the position
buf->pubseekpos(original, ss.out);
return end;
}
int main()
{
std::stringstream ss;
ss << "Hello";
ss << ' ';
ss << "World";
ss << 42;
std::cout << size_of_stream(ss) << std::endl;
// Make sure the output string is still the same
ss << "\nnew line";
std::cout << ss.str() << std::endl;
std::string str;
ss >> str;
std::cout << str << std::endl;
}
The key is that rdbuf() is const but returns a non-const buffer, which can then be used to seek.
If you want to know the remaining available input size:
#include <iostream>
#include <sstream>
std::size_t input_available(const std::stringstream& s)
{
std::streambuf* buf = s.rdbuf();
std::streampos pos = buf->pubseekoff(0, std::ios_base::cur, std::ios_base::in);
std::streampos end = buf->pubseekoff(0, std::ios_base::end, std::ios_base::in);
buf->pubseekpos(pos, std::ios_base::in);
return end - pos;
}
int main()
{
std::stringstream stream;
// Output
std::cout << input_available(stream) << std::endl; // 0
stream << "123 ";
std::cout << input_available(stream) << std::endl; // 4
stream << "567";
std::cout << input_available(stream) << std::endl; // 7
// Input
std::string s;
stream >> s;
std::cout << input_available(stream) << std::endl; // 4
stream >> s;
std::cout << input_available(stream) << std::endl; // 0
}
This is similar to #Cornstalks solution, but positions the input sequence correctly.
This should work :))
#include <iostream>
#include <sstream>
#include <boost/move/move.hpp>
int main()
{
const std::stringstream ss("hello");
std::cout << boost::move(ss).str().size();
}

How do you prepend to std::stringstream?

std::stringstream ss;
int number = 0x12345678;
ss << std::hex << number;
cout << ss.str();
This will produce 12345678
I want to make it as 0x12345678. How can I prepend 0x in front of ss.str()?
The probably simplest way to do this is to change the formatting of the stringstream ss: Make it automatically prepend the number base with std::showbase:
#include <sstream>
#include <iostream>
int main()
{
std::stringstream ss;
int number = 0x12345678;
ss << std::showbase << std::hex << number; // prepends the 0x automagically
std::cout << ss.rdbuf(); // empties ss
}
Note that I changed the output from cout << ss.str() to cout << ss.rdbuf(). This modifies the stream ss (it is empty afterwards), but requires no copy as in the OP's example.
Once you've put the number into the stringstream, there's no simple way I know of to prepend the 0x in this stringstream. You could then however print it before printing the contents of the stream to cout:
std::cout << "0x" << ss.rdbuf();

ostringstream breaks cout?

I want to output the content of a ostringstream to some other stream (for example std::cout). I know that I can use std::ostringstream::str() but I assume it has an overhead on copying the stream contents to a string and then further to the other stream. I found that I could use std::ostringstream::rdbuf() (Comment suggesting that has 25 votes). But it breaks std::cout as is shown in the output of the test program below. Am I doing something wrong?
#include <iostream>
#include <sstream>
int main(int argc, char const *argv[])
{
std::ostringstream ss;
ss << "some data" << std::endl;
std::cerr << std::cout << std::endl;
std::cout << "start" << std::endl;
std::cout << ss.str();
std::cout << ss.rdbuf();
std::cout << "end" << std::endl;
std::cerr << std::cout << std::endl;
return 0;
}
Results in:
0x6013b8
start
some data
0
Your problem is that the rdbuf() buffer for an ostringstream is, as you might expect from the name, write only (the ostringstream returns the string through the str() method). You can't read the data back out of it through the buffer pointer.
Change your ostringstream to stringstream and it should work fine.