9

Every one know stringstream.str() need a string variable type to store the content of stringstream.str() into it .

I want to store the content of stringstream.str() into char variable or char array or pointer.

Is it possible to do that?

Please, write a simple example with your answer.

Lion King
  • 32,851
  • 25
  • 81
  • 143
  • 1
    I finally found what I think this is a dupe of: [C++ stringstream, string, and char* conversion confusion](http://stackoverflow.com/questions/1374468/c-stringstream-string-and-char-conversion-confusion). Voted to close. – sbi Jan 06 '12 at 23:05

4 Answers4

12

Why not just

std::string s = stringstream.str();
const char* p = s.c_str();

?

Edit: Note that you cannot freely give the p outside your function: its lifetime is bound to the lifetime of s, so you may want to copy it.

Edit 2: as @David suggests, copy above means copying of the content, not the pointer itself. There are several ways for that. You can either do it manually (legacy way "inherited" from C) -- this is done with the functions like std::strcpy. This way is quite complicated, since it involves manual resources management, which is usually discouraged, since it leads to a more complicated and error-prone code. Or you can use the smart pointers or containers: it can be either std::vector<char> or std::unique_ptr/std::shared_ptr.

I personally would go for the second way. See the discussion to this and @Oli's answer, it can be useful.

Vlad
  • 35,022
  • 6
  • 77
  • 199
  • @Oli: oh, indeed, just corrected. (BTW, why did you remove your answer?) – Vlad Jan 06 '12 at 22:59
  • @David : True, but then you need to explain that `free` must be used instead of `delete[]`, etc, etc. `unique_ptr<>` (or `boost::scoped_array<>` for C++03) plus `std::copy()` would be the proper suggestion IMO. – ildjarn Jan 06 '12 at 23:16
  • @ildjarn It's hard to know what the proper suggestion is without know what the OP is actually trying to do. – David Schwartz Jan 06 '12 at 23:40
  • @David: I assume he is studying the proper C++, so everything in our discussions helps. – Vlad Jan 06 '12 at 23:42
  • @David : True, but recommending interchanging C and C++ memory allocation schemes is rarely a good thing. `delete` vs. `delete[]` is confusing enough for most beginners; introducing `free()` as well just makes things worse. – ildjarn Jan 06 '12 at 23:43
  • If you want to return `p` from a function then the code will undergo two whole copies. That said, I don't know if there even exists an alternative approach. – Kröw Mar 10 '23 at 07:10
9

If you want to get the data into a char buffer, why not put it there immediately anyway? Here is a stream class which takes an array, determines its size, fills it with null characters (primarily to make sure the resulting string is null terminated), and then sets up an std::ostream to write to this buffer directly.

#include <iostream>
#include <algorithm>

struct membuf: public std::streambuf {
    template <size_t Size> membuf(char (&array)[Size]) {
        this->setp(array, array + Size - 1);
        std::fill_n(array, Size, 0);
    }
};

struct omemstream: virtual membuf, std::ostream {
    template <size_t Size> omemstream(char (&array)[Size]):
        membuf(array),
        std::ostream(this)
    {
    }
};

int main() {
    char   array[20];
    omemstream out(array);

    out << "hello, world";
    std::cout << "the buffer contains '" << array << "'\n";
}

Obviously, this stream buffer and stream would probably live in a suitable namespace and would be implemented in some header (there isn't much point in putting anything of it into a C++ file because all the function are templates needing to instantiated). You could also use the [deprecated] class std::ostrstream to do something similar but it is so easy to create a custom stream that it may not worth bothering.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 3
    While this answer is technically correct, it proposes a fixed-sized buffer in an answer for a newbie. IME that's a buffer overflow lurking, IYAM. – sbi Jan 07 '12 at 08:02
  • 1
    There is no danger for a buffer overflow: the buffer set up by membuf has the size specified and that is where the stream will stop writing to it. The real danger is that there is no terminating null character, either when the user forgets to use std::ends or when the buffer gets full. I mainly pointed it out as a solution avoiding an intermediate string. – Dietmar Kühl Jan 07 '12 at 14:34
  • I _know_ that this doesn't overflow. IME you rarely get a buffer overflow in newly written code. It's always years of maintenance and constant changes in existing code which lead to assumption not holding any longer. Using a fixed-size buffer is perfectly fine in a 20 LoC proof-of-concept/example piece of code. The problem I see is only with newbies using these examples as something to base their coding style on. Teaching C++, I have learned (the hard way) that I need to always write perfect code in examples, and that applies even to the code that I consider beside the point. – sbi Jan 07 '12 at 18:13
0

I figured it out. Using namespace std and replacing tstingstreamwith stringstream. Next step is: stringstream strstream; strstream.imbue(std::locale("C")); string str = strstream.str(); const char *sql= str .c_str(); Now you can execute sql statement.

sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);

Maybe it helps to somebody.

zokia
  • 63
  • 1
  • 8
0

You can do this if you want an actual copy of the string (vital if the stringstream object is going to go out of scope at some point):

const char *p = new char[ss.str().size()+1];
strcpy(p, ss.str().c_str());

...

delete [] p;

As discussed in comments below, you should be wary of doing it like this (manual memory management is error-prone, and very non-idiomatic C++). Why do you want a raw char array?

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Ugh. This shows a newbie to deal with manually allocated and deleted resources. A _very_ bad idea. `-1` from me. – sbi Jan 06 '12 at 23:02
  • 1
    @sbi: It's that, or a code snippet involving smart pointers and so on, which I think obscures the core concept here. (Anyway, the fact that the OP wants to deal with raw C arrays and pointers already means we're doing non-idiomatic C++...) – Oliver Charlesworth Jan 06 '12 at 23:03
  • 1
    IME nothing is harder for newbies than manual resource management. (You could use `std::vector` instead.) – sbi Jan 06 '12 at 23:05
  • I'm with @sbi, though I won't downvote -- smart pointers are the only _sensible_ answer at this point, especially for beginners. They may have followup questions asking what `unique_ptr<>` or whatever is, but that's better than encouraging use of raw memory management. – ildjarn Jan 06 '12 at 23:06
  • 1
    @sbi: The OP asked for "char variable or char array or pointer". – Oliver Charlesworth Jan 06 '12 at 23:06
  • I understood the implication to be that `vector` is interchangable with `char*` for the OP's purposes since `&v[0]` (or `v.data()` in C++11) is well-defined, just as would be `unique_ptr::get()`. – ildjarn Jan 06 '12 at 23:13
  • @ildjarn: That's absolutely true. But at that point, we might as well just copy `ss.str()` into a `std::string`. – Oliver Charlesworth Jan 06 '12 at 23:18
  • Which, not coincidentally, is exactly what the accepted answer does. ;-] In any case, your answer is obviously technically correct, I was just giving my vote for smart pointers. :-] – ildjarn Jan 06 '12 at 23:20
  • Yikes. By the time that `strcpy` is called the return value of `ss.str()` is no longer in scope and could have been destroyed, making the the value of `c_str` potentially invalid. – Yaur Dec 15 '15 at 17:56
  • @Yaur: Huh? The *lifetime* of `ss.str()` is until the end of the expression (i.e. including the call to `strcpy`). Maybe you're thinking of something like `const char *q = ss.str().c_str(); strcpy(p, q);`, which indeed would be UB. – Oliver Charlesworth Dec 16 '15 at 15:44
  • @OliverCharlesworth I'm not sure where I got that idea, since its been the way you describe for a very long time, but you are correct. – Yaur Feb 03 '16 at 18:31