How do I use write with stringstream? - c++

I have a vector<char> of data which I want to write into std::stringstream.
I tried:
my_ss.write(vector.data(), vector.size());
...but it seems to put nothing into my_ss which I declared as follows:
std::stringstream my_ss( std::stringstream::binary);
Why write is not working (app does not crash and compiles with 0 errors, 0 warnings)?

For the "how do I do it" you can use a std::ostream_iterator:
std::copy(vector.begin(), vector.end(), std::ostream_iterator<char>(my_ss));
Complete example:
#include <iterator>
#include <sstream>
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<char> vector(60, 'a');
std::ostringstream my_ss;
std::copy(vector.begin(), vector.end(), std::ostream_iterator<char>(my_ss));
std::cout << my_ss.str() << std::endl;
}
You could also just use that to construct a string directly, without going via a stringstream at all:
std::string str(vector.begin(), vector.end()); // skip all of the copy and stringstream

Though you haven't given any code, it sounds like you probably just wrote:
std::stringstream my_ss (std::stringstream::binary);
If you wish to write to a stringstream you need to combine the flag std::stringstream::out in the constructor. If I'm right, then you would see things working fine if you changed this to:
std::stringstream my_ss (std::stringstream::out | std::stringstream::binary);
(Obviously if you wish to read from that stringstream you need to add std::stringstream::in)
UPDATE Now that you've given your code...yup, this is your specific problem. Note #awoodland's point about the fact that you can just construct a string from a vector of chars instead (if that's the only thing you were planning on doing with this stream.)

The default parameter for the mode of stringbuf in stringstream is out|in.
explicit basic_stringstream(ios_base::openmode _Mode =
ios_base::in | ios_base::out)
: _Mybase(&_Stringbuffer),
_Stringbuffer(_Mode)
{ // construct empty character buffer
}
You need to add stringstream::out if you pass something explicitly like stringstream:binary
Or just use std::ostringstream

Related

Partial copy of a stringstream

How can I copy three characters beginning with the second one of str1 to str2? This code doesn't work:
#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
int main()
{
std::stringstream str1("0123456789");
std::stringstream str2;
str1.seekg(1, str1.beg);
std::copy(std::istream_iterator<char>(str1), std::istream_iterator<char>(str1)+3, std::ostream_iterator<char>(str2));
std::cout << str2.str() << '\n';
}
The expected output is:
123
This is a dummy test, but I'd like to work with larger stringstreams and efficient methods.
There is another standard library algorithm called std::copy_n that will do what you want. It takes a begin iterator and the number of elements to copy. Your program works if you change the std::copy line to:
std::copy_n(std::istream_iterator<char>(str1), 3, std::ostream_iterator<char>(str2));
Demo on Compiler Explorer
An improvement might be to use std::next instead of the seekg() to advance the first iterator to the desired offset (Thanks to Armin Montigny). That would look like:
std::copy_n(std::next(std::istream_iterator<char>(str1)), 3, std::ostream_iterator<char>(str2));
Use substr() of std::string. To use the it for std::stringstream use str1.str()
Then assign it to str::string str2.
Step 1: Take the string our of the std::stringstream.
Step 2: Perform the operation on std::string.
Step 3: Assign the string to std::stringstream
Other way to get the part of stringstream:
char c[10] = {};
std::istringstream input("This is sample text."); // std::stringbuf makes its entire
// buffer available for unblocking read
input.readsome(c, 5); // reads 'This ' and stores in c[0] .. c[4]
input.readsome(c, 9); // reads 'is sample' and stores in c[0] .. c[8]

how can I convert istream * to string or just print it?

The below function part of connector/C++, it returns a istream*. if i just try and print it, it shows hex or a memory location because its a * type.
istream *stream = res->getBlob(1);
I tried to read & print it with this:
string s;
while (getline(*stream, s))
cout << s << endl;
But this crashes with access violation though. any other way i can print it or convert to string?
the value of stream before the getline:
stream 0x005f3e88 {_Chcount=26806164129143632 } std::basic_istream > *
so it seems that its valid to me. I think it would be null or 0 if it failed
You can extract and print a std::istream by using its stream buffer:
std::cout << in->rdbuf();
Of course, this will consume the input and you may not be able to get it again. If you want to keep the content, you could write it an std::ostringstream instead and print the content using the str() method. Alternatively, you can directly construct a std::string from a stream, too, e.g.:
std::string content{ std::istreambuf_iterator<char>(*in),
std::istreambuf_iterator<char>() };
BTW, when you printed your stream pointer, you actually used the output operator for void const*: it prints the address the pointer is referring to. In C++03 you could even restore a correspondingly printed pointer by reading a void* using an std::istream: as long as the pointed to object wasn't deleted, you could get a pointer back that way! In C++11 pointer hiding is prohibited, however, to support optional garbage collection which may or may not be added to the language in the future. The guarantee about non-hidden pointers also helps member debuggers, though.
You can use the std::getline function in the while loop to display the data in the istream. Here is an example that I ran and it worked correctly:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>
int main()
{
std::stringstream s1("This is a test string\nWith two lines");
std::istream s2(s1.rdbuf()); //just creates the istream to start with
std::string stt;
while(std::getline(s2,stt)) //can also have delimiter in getline
{
std::cout<<stt<<std::endl;
}
return 0;
}
Run it and it displays:
This is a test string
With two lines
I also tried this so that I was using pointer to the istream like you have:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>
int main()
{
std::stringstream s1("This is a test string\nWith three lines);
std::istream s2(s1.rdbuf()); //just creates istream to start with
std::istream *s3 = &s2; //and use a pointer to istream like code at top
std::string stt;
while(std::getline(*s3,stt,'\n'))
{
std::cout<<stt<<std::endl; //result.
}
return 0;
}
This code ran and gave the same result as I got without using the pointer. I was unable to reproduce your error. So the problem looks like the creation of your istream (e.g. istream *stream = res->getBlob(1);).

How to use basic_istream when you have a std::string

I have a function that uses basic_istream as an argument, and I have a std::string with the data I need to pass it. How do I do that?
You can put the string data into a stream:
std::string x;
std::stringstream ss(x); // put string into stream
function_taking_stream(ss);
A full working example showing how to parse a json string using boost property_tree:
#include <iostream>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
int main ()
{
std::string jsonString ("{ \"my key\": \"my value\" }");
ptree pt;
std::stringstream ss(jsonString);
read_json(ss, pt);
std::cout << pt.get<std::string>("my key") << std::endl;
return 0;
}
I have a function that uses basic_istream as an argument...
So I'm assuming you have a function that accepts a variable of a type specialized from the basic_istream template.
...and I have a std::string with the data I need to pass it.
So I'm assuming you want to feed this data into the istream argument.
How do I do that?
You don't. You can't feed output to an input stream!
I think the OP means he has a basic_istream<E> to read from and wants to read to a std::string, not to a std::basic_string<E>.
You should probably write to the basic_string first then convert that to a std::string. If you want to ensure the conversion is correct you probably want a proper UTF-8 to UTF-16 converter.
If you know you are dealing with only ASCII bytes you can do something like:
std::basic_string<E> strTemp;
is >> strTemp;
std::string str( strTemp.begin(), strTemp.end() );
If you have a basic_ostream<E> you can similarly first construct a basic_string<E> from your std::string and then write that to the stream.
You can "specialise" your template function so that if E happens to be char the conversion is quick. For that purpose you can input the two strings as non-const references and the specialised version could just "swap".

Read 1 line from istream to string stream without temporary variable in C++?

Is is possible to read one line from input stream and pass it to string stream without using temorary string variable in C++?
I currently do the reading like this (but I don't like the temporary variable line):
string line;
getline(in, line); // in is input stream
stringstream str;
str << line;
Like #Steve Townsend said above, it's probably not worth the effort, however if you wanted to do this (and you knew beforehand the number of lines involved), you could do something like:
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
template <typename _t, int _count>
struct ftor
{
ftor(istream& str) : _str(str), _c() {}
_t operator() ()
{
++_c;
if (_count > _c) return *(_str++); // need more
return *_str; // last one
}
istream_iterator<_t> _str;
int _c;
};
int main(void)
{
ostringstream sv;
generate_n(ostream_iterator<string>(sv, "\n"), 5, ftor<string, 5>(cin));
cout << sv.str();
return 0;
}
There is detailed info in the question below (per #Martin York) on reading direct from stream to stringstream. This is not a direct dup as you wish to handle the input line by line, but this approach will be hard to beat for efficiency. You can instantiate the individual lines using a character range once the raw data is in the stringstream.
How to read file content into istringstream?
To be honest, this may be a lot of work for a problem that's not really a huge perf concern anyway.

How to read and write a STL C++ string?

#include<string>
...
string in;
//How do I store a string from stdin to in?
//
//gets(in) - 16 cannot convert `std::string' to `char*' for argument `1' to
//char* gets (char*)'
//
//scanf("%s",in) also gives some weird error
Similarly, how do I write out in to stdout or to a file??
You are trying to mix C style I/O with C++ types. When using C++ you should use the std::cin and std::cout streams for console input and output.
#include <string>
#include <iostream>
...
std::string in;
std::string out("hello world");
std::cin >> in;
std::cout << out;
But when reading a string std::cin stops reading as soon as it encounters a space or new line. You may want to use std::getline to get a entire line of input from the console.
std::getline(std::cin, in);
You use the same methods with a file (when dealing with non binary data).
std::ofstream ofs("myfile.txt");
ofs << myString;
There are many way to read text from stdin into a std::string. The thing about std::strings though is that they grow as needed, which in turn means they reallocate. Internally a std::string has a pointer to a fixed-length buffer. When the buffer is full and you request to add one or more character onto it, the std::string object will create a new, larger buffer instead of the old one and move all the text to the new buffer.
All this to say that if you know the length of text you are about to read beforehand then you can improve performance by avoiding these reallocations.
#include <iostream>
#include <string>
#include <streambuf>
using namespace std;
// ...
// if you don't know the length of string ahead of time:
string in(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// if you do know the length of string:
in.reserve(TEXT_LENGTH);
in.assign(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// alternatively (include <algorithm> for this):
copy(istreambuf_iterator<char>(cin), istreambuf_iterator<char>(),
back_inserter(in));
All of the above will copy all text found in stdin, untill end-of-file. If you only want a single line, use std::getline():
#include <string>
#include <iostream>
// ...
string in;
while( getline(cin, in) ) {
// ...
}
If you want a single character, use std::istream::get():
#include <iostream>
// ...
char ch;
while( cin.get(ch) ) {
// ...
}
C++ strings must be read and written using >> and << operators and other C++ equivalents. However, if you want to use scanf as in C, you can always read a string the C++ way and use sscanf with it:
std::string s;
std::getline(cin, s);
sscanf(s.c_str(), "%i%i%c", ...);
The easiest way to output a string is with:
s = "string...";
cout << s;
But printf will work too:
[fixed printf]
printf("%s", s.c_str());
The method c_str() returns a pointer to a null-terminated ASCII string, which can be used by all standard C functions.