Stringstream, String, and Char* Conversion Confusion

stringstream, string, and char* conversion confusion

stringstream.str() returns a temporary string object that's destroyed at the end of the full expression. If you get a pointer to a C string from that (stringstream.str().c_str()), it will point to a string which is deleted where the statement ends. That's why your code prints garbage.

You could copy that temporary string object to some other string object and take the C string from that one:

const std::string tmp = stringstream.str();
const char* cstr = tmp.c_str();

Note that I made the temporary string const, because any changes to it might cause it to re-allocate and thus render cstr invalid. It is therefor safer to not to store the result of the call to str() at all and use cstr only until the end of the full expression:

use_c_str( stringstream.str().c_str() );

Of course, the latter might not be easy and copying might be too expensive. What you can do instead is to bind the temporary to a const reference. This will extend its lifetime to the lifetime of the reference:

{
const std::string& tmp = stringstream.str();
const char* cstr = tmp.c_str();
}

IMO that's the best solution. Unfortunately it's not very well known.

C++ stringstream to char* conversion memory allocation

Did stringstream allocate memory for the extra characters in the char pointer?

No. Your code invokes undefined behavior.

Also want to know the correct way to copy data from stringstream to char* array, without exceeding the memory allocated for char*?

It is not a good idea to read into char*. Use std::string to read input from stream. But then if you still want to know for the sake of knowledge, use std::istream::read().

if ( sstream.read(tempStr, 5 ) )
{
//read succeeded
}

By the way, you can merge these two lines:

stringstream sstream;
sstream.str(stemp);

into one:

stringstream sstream(stemp);

or simply this:

stringstream sstream("helloworld"); //no need of stemp!

Hope that helps.

How to put stringstream contents into char instead string type?

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.

Pass contents of stringstream to function taking char* as argument

This looks like a typical case of someone not writing const-correct code and it having the knock-on effect. You have several choices:

  • If write_ppm is under your control, or the control of anyone you know, get them to make it const corrct

  • If it is not, and you can guarantee it never changes the filename then const_cast

  • If you cannot guarantee that, copy your string into a std::vector plus the null terminator and pass &vec[0] (where vec represents the name of your vector variable)

Stringstream weird behaviour

As we know now, + is a valid token for a double, so you need a way to skip to the next space-separated token instead of just getting rid of it. This function can do it for you:

template<class Ct>
std::basic_istream<Ct>& next_token(std::basic_istream<Ct>& is) {
is.clear();
std::ctype<Ct> const& ctype = std::use_facet<std::ctype<Ct>>(is.getloc());
if (ctype.is(ctype.space, is.peek())) {
return is >> std::ws;
}
Ct c;
while (is.get(c) && !ctype.is(ctype.space, c)) {
;
}
return is;
}

Then you can change your code to:

stringstream sso("12 + 1442 nana 7676");
double num = 0;
while (sso) {
if (!(sso >> num)) {
sso >> next_token;
} else {
cout << num << endl;
}
}

Output:

12
1442
7676

When turning a char with multiple characters into a string with stringstream, spaces dissapear

I cant understand how date_and_time is a char when it has multiple characters

It is not a single char, it is a char* pointer to a null-terminated array of chars.

when I want to get it to a string, it just stops when spaces come.

Because that is how operator>> works. It stops reading on whitespace or EOF, whichever occurs first.

I tried putting it with or without noskipws but to no avail.

noskipws before the first >> tells it not to skip leading whitespace. But your input string does not have any, so the noskipws is effectively a no-op in this situation. And it has no effect on the 2nd >> because the 1st one clears that flag from the stream after it is done reading.

If printing date_and_time is something like "Thu Jul 01 23:52:46 2021", when it turns to string it is just "Thu".

Because you are using >> to parse the string. This is normal behavior.

If you want the whole string, use std::getline() instead:

stringstream ss;
ss << date_and_time;
/* alternatively:
istringstream ss(date_and_time);
*/
getline(ss, date_and_time_string);

Or, since there is really no reason to use std::(i)stringstream at all in this situation, you can just assign date_and_time as-is directly to date_and_time_string:

date_and_time_string = date_and_time;


Related Topics



Leave a reply



Submit