Convert std::ostringstream into std::stringstream - c++

The next code returns an empty string in ss:
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss.basic_ios<char>::rdbuf(oss.rdbuf());
std::cout << ss.str() << "\n";
return 0;
}
How can I return from ss the text introduced in oss? I'm mainly interested in converting std::ostringstream into std::stringstream.

You could make use of the protected std::streambuf::swap member function that exchanges the contents of the stream buffer with those of another
To get access to it, you'll need a derived class:
#include <iostream>
#include <sstream>
struct swapper : std::streambuf {
using std::streambuf::streambuf;
void swap(std::streambuf& rhs) { // public proxy for protected swap
std::streambuf::swap(rhs);
}
};
// casting
void swapbuf(std::ostream& a, std::ostream& b) {
static_cast<swapper*>(a.rdbuf())->swap(*b.rdbuf());
}
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
swapbuf(oss, ss);
std::cout << "ss: " << ss.str() << "\n"; // prints Text
}

Following comments from #NathanOliver, I decided to convert std::ostringstream into std::stringstream by using str():
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss << oss.str();
std::cout << ss.str() << "\n";
return 0;
}

Related

Need help to understand where i am going wrong with strings

In c++ we have std::to_string which converts int/float/double to strings. So just to test my understanding of templates I tried the code below:
#include "iostream"
#include "sstream"
#include "string"
using std::cout;
template <typename T>
std::string getString(const T& data){
std::stringstream ss;
cout << '\n' << data << '\n';
ss << data;
std::string s;
ss >> s;
return s;
}
int main(int argc , char** argv){
cout << getString(1.0000011);
cout <<' '<<std::to_string(1.0000011);
return 0;
}
However, the output doesn't make sense, to_string gives me 1.0000011, whereas getString gets 1 and gives me 1. As I am using templates shouldn't getString get 1.0000011 as well and give me 1.0000011 too?
You can use std::setprecision in the <iomanip> header to set the precision that std::stringstream will use when formatting numeric data.
For example:
std::stringstream ss;
ss << std::setprecision(9) << data;
cout << ss.str();
Will print:
1.0000011
Here's a quick demo online: cpp.sh/9v7xf
As a side note, you don't have to create a string and output from the stringstream - you can replace the last 3 lines in getString() with:
return ss.str();
Numeric values are often truncated for appearance. You can supply the std::fixed manipulator from the iomanip standard header to avoid this issue.
#include "iomanip" // <- Add this header
#include "iostream"
#include "sstream"
#include "string"
using std::cout;
template <typename T>
std::string getString(const T& data)
{
std::stringstream ss;
cout << '\n' << data << '\n';
ss << std::fixed << data;
// ^^^^^^^^^^^^^ Add this
std::string s;
ss >> s;
return s;
}
int main(int argc, char** argv)
{
cout << getString(1.0000011);
cout << ' ' << std::to_string(1.0000011);
return 0;
}
<iomanip> needs included, and std::setprecision must be used when outputting float values to streams. Using your example, this looks like:
#include <iostream>
#include <iomanip> //include this.
#include <sstream>
#include <string>
template <typename T>
std::string getString(const T& data){
std::ostringstream ss;
ss << std::setprecision(8);
std::cout << std::setprecision(8);
std::cout << data << '\n';
ss << data;
return ss.str();
}
int main(int argc , char** argv){
std::cout << getString(1.0000011) << "\n";
std::cout << std::to_string(1.0000011) << std::endl;
return 0;
}
Which prints:
1.0000011
1.0000011
1.000001
Program ended with exit code: 0
Note how to_string alone truncates the floating point number!!! I suspect this is undesired behavior, but to_string cannot be manipulated directly, so...
If desired, you can fix this with the solution found here.
Otherwise, just use std:set_precision() when inserting into streams for precisely converted strings.

how to print Ascii code of a string in c++

I have a string and I want to print hex value of each parts ascii code.
for example if the string is "0200" the output will be 30323030 .
and here's my code:
string bit_pattern;
bit_pattern = "5678008180000000";
cout << hex << bit_pattern;
but it prints 5678008180000000 instead of 35363738303038313830303030303030
how do i fix it???
You can use the following
for (int i=0; i<bit_pattern.length(); i++)
cout << hex << (int)bit_pattern[i];
to print the ascii value (in hex format) char by char.
You're just sending the same std::string right to std::cout. Just sending the hex manipulator isn't going to magically convert all those chars.
I admit this is complete overkill, but I was bored:
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
class ascicodes
{
std::ostringstream ss;
public:
friend std::ostream& operator <<(std::ostream& os, const ascicodes& obj)
{
os << obj.ss.str();
return os;
}
ascicodes(const std::string& s)
{
ss << std::hex << std::setfill('0');
std::for_each(s.begin(), s.end(),
[this](char ch)
{
ss << std::setw(2) << static_cast<unsigned int>(ch);
});
}
};
int main()
{
std::string bit_pattern = "5678008180000000";
std::cout << ascicodes(bit_pattern) << std::endl;
std::cout << ascicodes("A completely different string") << std::endl;
return 0;
}
Output
35363738303038313830303030303030
4120636f6d706c6574656c7920646966666572656e7420737472696e67

Reverse an ostringstream by line

ostringstream ss;
ss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << ss.str();
should print the following:
(1,2)
(1,3)
(1,4)
How could i reverse the output by line so that it prints:
(1,4)
(1,3)
(1,2)
You could use a custom std::streambuf which internally keeps a stack of std::strings and puts them together upon using a str() member. For example:
#include <iostream>
#include <numeric>
#include <streambuf>
#include <string>
#include <vector>
class stackbuf
: public std::streambuf
{
std::vector<std::string> d_lines;
int overflow(int c) {
if (c != std::char_traits<char>::eof()) {
this->d_lines.back().push_back(c);
if (c == '\n') {
this->d_lines.push_back(std::string());
}
}
return std::char_traits<char>::not_eof(c);
}
public:
stackbuf(): d_lines(1) {}
std::string str() const {
return std::accumulate(this->d_lines.rbegin(),
this->d_lines.rend(),
std::string());
}
};
int main()
{
stackbuf sbuf;
std::ostream out(&sbuf);
out << "(1, 2)\n(1, 3)\n(1, 4)\n";
std::cout << sbuf.str();
}
For a real-world application you should, obviously, set up a buffer in the stream buffer to improve the performance. You may also want to create a custom stream directly initializing the stream's stream buffer.
Using your original code with C++98:
ostringstream ss;
ss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << ss.str();
//assign a string to the contents of the ostringstream:
string rawlines = ss.str();
//now create an input stringstream with the value of the rawlines
istringstream iss(rawlines);
string temp;//just a temporary object used for storage
vector<string> lines;//this is where your lines will be held
//now iterate over the stream and store the contents into the vector `lines`:
while(getline(iss, temp)) {
lines.push_back(temp);
}
//now reverse the contents:
reverse(lines.begin(), lines.end());
//see what's inside:
for (vector<string>::const_iterator it = lines.begin(); it != lines.end(); ++it) {
cout << *it << endl;
}
This will print:
(1,4)
(1,3)
(1,2)
As desired
NOTE: This strips the newlines from the the original string.
And, this requires:
//for `getline`:
#include <cstdlib>
//for `reverse`:
#include <algorithm>
//for `string`:
#include <string>
//for `vector`:
#include <vector>
You can use reverse iterators:
std::ostringstream ss{ "(1,2)\n(1,3)\n(1,4)\n" };
std::string str = ss.str();
std::copy( str.rbegin(), str.rend(),
std::ostream_iterator<std::string>{std::cout, "\n"} );
This code will require:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <sstream>
and basic C++11 support.
This would be the classic way, best leveraging the standard C++ library.
#include <iostream>
#include <sstream>
#include <stack>
#include <string>
using namespace std;
int main(int argv, char* arv[])
{
ostringstream oss;
oss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << oss.str() << "----------\n";
// Reverse lines
// Fill an istringstream with buffer contents of the ostringstream
istringstream iss(oss.str());
stack<string> stk;
while (iss) {
string s;
if (!getline(iss, s)) break; // Read a line
s += '\n'; // Put back newline stripped by readline
stk.push(s); // Push line to stack
}
oss.clear(); // Clear state of the ostringstream
oss.str(""); // Clear contents of the ostringstream for reuse
while (!stk.empty()) {
string s;
s = stk.top(); // Get top of stack
oss << s; // Output it to the ostringstream
stk.pop(); // Pop and throw away top of stack
}
cout << oss.str();
return 0;
}

Convert a vector<char> to a string with a conversion

I'd like to convert a vector<char> to a std::string and do a conversion one the way.
I'm almost there, but the result of the code below is a vector<string>, while I'd like to have one string (a concatenation of all the string parts in the vector).
See my code example for details.
string ConvertHexToAscii(const char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return oss.str();
}
vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
vector<string> resultVec;
std::transform(readBuffer.begin(), readBuffer.end()
, back_inserter(resultVec)
, ConvertHexToAscii);
// resultVec[0] = "1C";
// resultVec[1] = "09";
The result I need is a string containing "1C09". How to achieve that with std::transform?
You were almost there; this works:
std::stringstream sstr;
std::transform(
input.begin(), input.end(),
std::ostream_iterator<std::string>(sstr, ""),
ConvertHexToAscii);
But unfortunately this instantiates quite a lot of string streams, which is inefficient. Ideally, the ConvertHexToAscii (misnamed, by the way! C++ doesn’t know about encodings) function would directly use the underlying stream.
#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <numeric>
std::string ConvertHexToAscii(std::string acc, char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return acc + oss.str();
}
int main() {
std::vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
std::cout << std::accumulate(readBuffer.begin(), readBuffer.end()
, std::string(), ConvertHexToAscii) << std::endl;
return 0;
}
create your own back_insert_iterator (look at the code in your stl lib, it's fairly simple) for string types of which operator = is defined as
template< class string_type, class value_type >
class back_insert_iterator
{
public:
back_insert_iterator< _string_type >& operator = ( const value_type& val )
{
container->append( val )
return *this;
}
};
You can do this with a function output iterator:
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <boost/function_output_iterator.hpp>
std::string ConvertHexToAscii(const char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return oss.str();
}
int main() {
std::vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
std::string temp;
std::transform(readBuffer.begin(), readBuffer.end()
, boost::make_function_output_iterator([&temp](const std::string& r) {temp.append(r);})
, ConvertHexToAscii);
std::cout << temp << std::endl;
}
I used a lambda to call the append() function on the result string, but if you don't have that available it's fairly easy to use boost::bind or just write an old fashioned functor to do that for you.
With boost::bind the function output iterator gets created as:
boost::make_function_output_iterator(boost::bind(static_cast<std::string& (std::string::*)(const std::string&)>(&std::string::append), &temp, _1))
instead. It's slightly clunky because you need to pick the right overload for std::string::append.
Whereas perreal's idea of using an accumulation isn't that bad, it may be more performant to operate on the stream directly instead of creating so many temporary strings (though move semantics may help with that):
std::ostringstream os;
std::string temp = std::accumulate(
readBuffer.begin(), readBuffer.end(), std::ref(os),
[](std::ostream &os, const char input)
-> std::reference_wrapper<std::ostream> {
return os << std::hex << std::setw(2)
<< std::setfill('0')
<< static_cast<int>(input);
}).str();
EDIT: But Ok, that's maybe a bit oversophistication here, a simple foreach would have done, too (even if not as semantically clean as an accumulation):
std::ostringstream os;
std::for_each(readBuffer.begin(), readBuffer.end(),
[&os](const char input) mutable {
os << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<int>(input);
});
std::string temp = os.str();
But anything might be better than creating a whole bunch of temporary strings.

What's the equivalent of cout for output to strings?

I should know this already but... printf is to sprintf as cout is to ____? Please give an example.
It sounds like you are looking for std::ostringstream.
Of course C++ streams don't use format-specifiers like C's printf()-type functions; they use manipulators.
Example, as requested:
#include <sstream>
#include <iomanip>
#include <cassert>
std::string stringify(double x, size_t precision)
{
std::ostringstream o;
o << std::fixed << std::setprecision(precision) << x;
return o.str();
}
int main()
{
assert(stringify(42.0, 6) == "42.000000");
return 0;
}
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
ostringstream s;
s.precision(3);
s << "pi = " << fixed << 3.141592;
cout << s.str() << endl;
return 0;
}
Output:
pi = 3.142
Here's an example:
#include <sstream>
int main()
{
std::stringstream sout;
sout << "Hello " << 10 << "\n";
const std::string s = sout.str();
std::cout << s;
return 0;
}
If you want to clear the stream for reuse, you can do
sout.str(std::string());
Also look at the Boost Format library.
std::ostringstream
You can use this to create something like the Boost lexical cast:
#include <sstream>
#include <string>
template <typename T>
std::string ToString( const T & t ) {
std::ostringstream os;
os << t;
return os.str();
}
In use:
string is = ToString( 42 ); // is contains "42"
string fs = ToString( 1.23 ) ; // fs contains something approximating "1.23"
You have a little misunderstanding for the concept of cout. cout is a stream and the operator << is defined for any stream. So, you just need another stream that writes to string in order to output your data. You can use a standard stream like std::ostringstream or define your own one.
So your analogy is not very precise, since cout is not a function like printf and sprintf