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

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

Related

How to get rid of no "matching function call error" when iterating over a stream buffer?

I am trying to store binary data that should have the type of a std::complex< float > into a vector, through iterating over each element of the stream buffer. However I keep getting an error saying
no matching function for call to ‘std::istreambuf_iterator<std::complex<float> >::istreambuf_iterator(std::ifstream&)’
std::for_each(std::istreambuf_iterator<std::complex<float> >(i_f1),
I've tried searching for a solution but cannot find anything that would work. I am also trying to follow an example given in How to read entire stream into a std::vector? . Furthermore I'm compiling using g++ and -std=c++11.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cmath>
#include <boost/tuple/tuple.hpp>
#include <algorithm>
#include <iterator>
int main(){
//path to files
std::string data_path= "/$HOME/some_path/";
//file to be opened
std::string f_name1 = "ch1_d2.dat";
std::ifstream i_f1(data_path + f_name1, std::ios::binary);
if (!i_f1){
std::cout << "Error occurred reading file "<<f_name1 <<std::endl; std::cout << "Exiting" << std::endl;
return 0;
}
//Place buffer contents into vector
std::vector<std::complex<float> > data1;
std::for_each(std::istreambuf_iterator<std::complex<float> >(i_f1),
std::istreambuf_iterator<std::complex<float> >(),
[&data1](std::complex<float> vd){
data1.push_back(vd);
});
// Test to see if vector was read in correctly
for (auto i = data1.begin(); i != data1.end(); i++){
std::cout << *i << " ";
}
i_f1.close();
return 0;
}
I am quite lost at what I'm doing wrong, and am thus wondering why the
std::istreambuf_iterator()
does not accept the stream I am giving it as parameter?
Also the error message is confusing me as it seems to imply that I am calling the function in a wrong way, or a function that is non-existent.
Thanks
You want to read std::complex from i_f1 (which is a std::ifstream) using operator>> for std::complex, so you need a std::istream_iterator instead of std::istreambuf_iterator1:
std::for_each(std::istream_iterator<std::complex<float> >(i_f1),
std::istream_iterator<std::complex<float> >(),
[&data1](std::complex<float> vd){
data1.push_back(vd);
});
Your code can actually be simplified to:
std::vector<std::complex<float>> data1{
std::istream_iterator<std::complex<float>>(i_f1),
std::istream_iterator<std::complex<float>>()};
1 std::istreambuf_iterator is used to iterate character per character on, e.g., a std::basic_istream, not to iterate over it using overloads of operator>>.
You're probably using the wrong tool for the job.
You're trying to use a buffer iterator, which iterates over the constituent parts of a stream's buffer. But you're telling your computer that the buffer is one of complex<float>s … it isn't. An ifstream's buffer is of chars. Hence the constructor you're trying to use (one that takes an ifstream with a buffer of complex<float>) does not exist.
You can use an istream_iterator to perform a formatted iteration, i.e. to use the stream's magical powers (in this case, lexically interpreting input as complex<float>s) rather than directly accessing its underlying bytes.
You can read more on the previous question "the difference betwen istreambuf_iterator and istream_iterator".
The example you linked to does also go some way to explaining this.

How do I use write with stringstream?

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

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.