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 achar
when it has multiple characters
It is not a single char
, it is a char*
pointer to a null-terminated array of char
s.
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
Non-Blocking Worker - Interrupt File Copy
Macro For Dllexport/Dllimport Switch
Standard Library Sort and User Defined Types
When Passing an Array to a Function in C++, Why Won't Sizeof() Work the Same as in the Main Function
Why Does Call-By-Value Example Not Modify Input Parameter
What Is the Worst Real-World Macros/Pre-Processor Abuse You'Ve Ever Come Across
What Techniques Can Be Used to Speed Up C++ Compilation Times
How Many and Which Are the Uses of "Const" in C++
C/C++ Include Header File Order
Compelling Examples of Custom C++ Allocators
Why Do We Not Have a Virtual Constructor in C++
Using Scanf() in C++ Programs Is Faster Than Using Cin
Smart Pointers: Who Owns the Object
View Array in Visual Studio Debugger
Confused When Boost::Asio::Io_Service Run Method Blocks/Unblocks