ostringstream breaks cout? - c++

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.

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.

can't get file to output correctly

i am writing this very simple program that ouputes hello world using files. keep in mind i want the hello and world to be on separate lines.
here is the following code:
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
return 0;
}
however, whenever i run the following program, it only prints "hello".
any help will be greatly appreciated, and PLEASE give an example using fstream, not ofstream or ifstream (I am trying to learn how fstream works, however am finding a little trouble).
my compiler is the latest VS.
getine function only read one line per one time, so you should call getline until the end of file. The code be below can help you.
#include <iostream>
#include <fstream>`
#include <string>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
while(std::getline(someOtherFile, content))
{
std::cout << content << std::endl;
}
return 0;
}
You have 2 lines of code:
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
They put 2 lines of strings into file.dat:
// file.dat
hello
world
The function "getline()" gets only 1 line from the file. And the "seekg" function sets the read position to the first line of the file: which contains "hello".
If you want to read to the end of the file: then replace:
std::getline(someOtherFile, content);
std::cout << content << std::endl;
with:
while (!someOtherFile.eof())
{
std::getline(someOtherFile, content);
std::cout << content << std::endl;
}
Or use a counter variable if you just want specific lines.
By the way, I am just assuming that you meant to put the variable "content" where "name" is.
std::getline only get one line of text from the specific file. As http://www.cplusplus.com/reference/string/string/getline/?kw=getline says:
istream& getline (istream& is, string& str);
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).
Add another getline(..) and cout statement after the first set of getline and cout. you will get the world as output.
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
std::getline(someOtherFile, content);
std::cout << content << std::endl;
getline gets only one line in a file. To get next line, you need to call again.
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
someFile.close();
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello ";
someOtherFile << "world" << std::endl;
someOtherFile.close();
someOtherFile.seekg(0, ios::beg);
std::getline(someFile1, content);
std::cout << content << std::endl;
someFile1.close();
return 0;
}
This will print your desired answer

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();
}

Printing out a stringstream using str() and rdbuf()

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();

handle empty string case extracting a string from std::istream

Using the following code to extract a string from a std::istream :
#include <sstream>
#include <iostream>
void parse(std::istream & is, std::string & out)
{
is >> out;
}
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out("__INIT__");
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
parse(is, out);
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
}
}
With a non-empty string the output looks like :
$./a.out "TEST"
good:1 fail:0 eof:0 in_avail:4 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:TEST
With an empty string the output looks like :
$./a.out ""
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:1 eof:1 in_avail:0 value:__INIT__
Instead of this, I would expect :
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:
The operator>> does not extract an empty string. The result is the same with an empty string or and no data.
Any suggestion to handle this situation will be appreciated.
If you're using your parse function exclusively for extraction, you can simply make it out to be a check for an empty buffer. If there is, simply clear the string:
void parse(std::istream& is, std::string& out)
{
if (is.eof() || is.peek() == std::char_traits<char>::eof())
{
out.clear();
return;
}
is >> out;
}
There is no difference between an empty value and no value.
That's just your assumption, and it's not really true.
If you attempt to extract a string, it is expected that there are characters to extract. Before characters are available, it is impossible to perform any extraction, let alone one that results in extraction to a particular object.
This is entirely expected behaviour.
I guess your confusion stems from your prior check for argc > 1, but although the shell pretended ./myProgram "" had some argument, as far as your stream is concerned there is nothing in that argument.
If you wish to make your own handling for it, simply stick an if condition on is.fail() after the read.
#include <sstream>
#include <iostream>
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out;
is >> out;
if (is.fail()) {
std::cout << "Well, you gave me an argument, but it was empty, biatch!\n";
}
}
}
Don't bother checking is.eof(); it'll be set when you reached the end of input whether it contained any characters or not.