concatenate stringstream in c++

36,849

Solution 1

Should be:

b << dest;
a << b.str();

stringstream::str returns the underlying string in the stringstream.

Solution 2

Or

a << b.rdbuf();

provided that get pointer is on the beginning of the stream to avoid allocating yet another std::string for content.

Solution 3

More generically across iostreams:

std::istream is1, is2; // eg. (i)stringstream
std::ostream os;       // eg. (o)stringstream

os << is1.rdbuf();
os << is2.rdbuf();
os << std::flush;

This works for filestreams, std::cin etc. as well as for stringstream

Solution 4

You don't need two instance of std::stringstream. One is enough for the purpose.

std::stringstream a;
a << source << dest;

std::string s = a.str(); //get the underlying string

Solution 5

The question was "how to concatenate STREAMS", the answers explained how to concatenate the contents of the streams. Here is a class which can be used to concatenate two istreams into one istream (file ConcatStreams.h):

class ConcatStreams
: public std::streambuf {
std::streambuf* sbuf1_;
std::streambuf* sbuf2_;
char*           buffer_;
int useBuf;
int bufSize;
public:
ConcatStreams(std::streambuf* sbuf1, std::streambuf* sbuf2)
    : bufSize(1024), sbuf1_(sbuf1), sbuf2_(sbuf2), buffer_(new char[bufSize]), useBuf(1) {
}
ConcatStreams(const ConcatStreams& orig);
virtual ~ConcatStreams() { delete[] this->buffer_; }
int underflow() {
    if (this->gptr() == this->egptr()) {
        // get data into buffer_, obtaining its input from
        // this->sbuf_; if necessary resize buffer
        // if no more characters are available, size == 0.
        std::streamsize size=0;
        if(useBuf==1) {
            size = this->sbuf1_->sgetn(this->buffer_, bufSize);
            if(!size) { useBuf++;}
        } 
        if(useBuf==2) {
            size = this->sbuf2_->sgetn(this->buffer_, bufSize);
            if(!size) { useBuf++;}
        }
        this->setg(this->buffer_, this->buffer_, this->buffer_ + size);
    }
    return this->gptr() == this->egptr()
         ? std::char_traits<char>::eof()
         : std::char_traits<char>::to_int_type(*this->gptr());
 }
};

To use it:

#include "ConcatStreams.h"
istringstream msgIn1("this is a stream.");
istringstream msgIn2("this is another stream.");
ConcatStreams cs(msgIn1.rdbuf(), msgIn2.rdbuf());
istream msgIn(&cs);
cout << "'" << msgIn.rdbuf() << "'" << endl;

Basically the class uses the streambuf's from the streams passed to it to create a new streambuf which first reads the first streambuf and then reads the second streambuf when finished with the first one.

Share:
36,849
Carlitos Overflow
Author by

Carlitos Overflow

Updated on August 29, 2020

Comments

  • Carlitos Overflow
    Carlitos Overflow over 3 years

    How can I concatenate two stringstreams?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include "types.h"    
    
    int main () {
        char dest[1020] = "you";
        char source[7] = "baby";
        stringstream a,b;
        a << source;
        b << dest;
        a << b; /*HERE NEED CONCATENATE*/
        cout << a << endl;
        cout << a.str() << endl;
        return 0;
    }
    

    The output is the following in both tries:

    0xbf8cfd20
    baby0xbf8cfddc
    

    The desired output is babyyou.

  • jli
    jli over 12 years
    Of course as mentioned you don't need 2 stringstreams in this case, however I assumed that the given example is a trivial version of some more complex use case.
  • Den-Jason
    Den-Jason over 6 years
    This will create a copy of b's string data; I think the questioner may be looking for a way to avoid doing that.
  • sehe
    sehe about 6 years
    This class is bugged (the initialization of bufSize comes after the use in constructing buffer_) and is generally unnecessarily low-level. Here's a c++17 version stackoverflow.com/a/49441066/85371