This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I've been trying to append an integer to a string, and I've tried several solutions here, including:
std::stringstream ss;
ss << gvHours << "\'" << gvMinutes << "\"" << gvSeconds << ":" << gvTicks;
std::string output(ss.str());
return output.c_str();
and
std::stringstream ss;
std::string output = "";
ss << gvHours << "\'" << gvMinutes << "\"" << gvSeconds << ":" << gvTicks;
output = ss.str();
return output.c_str();
The first one gives me an empty string, and the second gives me an unreadable character that Notepad++ displays as "SOH" in a black box. Does anyone have any idea what I'm doing wrong?
Yes, this part
return output.c_str();
is broken.
When you take c_str() from a std::string, you are just getting a c-style pointer to the contents of that string. But you are not getting ownership of the data underlying that string. As soon as you return from the function, that stringstream and string are destroyed (as they are local variables) and the c_str() is a dangling pointer. So the whole thing is undefined behavior.
I fixed it. Here's the code I got that works:
std::stringstream ss;
std::string output;
ss << gvHours << "\'" << gvMinutes << "\"" << gvSeconds << ":" << gvTicks;
output = ss.str();
return output;
And in the function where it was needed:
fprintf(gvLog, ">: %s\n", timeString().c_str());
Related
I am trying to logg my events so i thought of using ostringstream to save the output and then send it to a function where i print the output on screen and on file fstream fileOut. It wont work, it just gives me random numbers and seem not to output all new outputs on the same file but just creates a new file everytime and deletes what was on it before. How do i do this?
where the print happens:
void Event::output(ostringstream* info) {
std::cout << info << std::endl;
fileOut << info << std::endl;
}
where the output happens:
ostringstream o;
if (time < SIM_TIME) {
if (status->tryAssemble(train)) {
Time ct;
ct.fromMinutes(time);
o << ct << " Train [" << train->getTrainNumber() << "] ";
Time t(0, DELAY_TIME);
o << "(ASSEMBLED) from " << train->getStart() << " " << train->getScheduledStartTime() <<
" (" << train->getStartTime() << ") to " << train->getDest() << " " << train->getScheduledDestTime() <<
" (" << train->getDestTime() << ") delay (" << train->getDelay() << ") speed=" << train->getScheduledSpeed() <<
" km/h is now assembled, arriving at the plateform at " << train->getStartTime() - t << endl << endl;
fileOut.open("testfile.txt", std::ios::out);
if (!fileOut.is_open())
exit(1); //could not open file
output(&o);
train->setStatus(ASSEMBLED);
time += ASSEMBLE_TIME;
Event *event = new ReadyEvent(simulation, status, time, train);
simulation->addEvent(event);
It wont work, it just gives me random numbers
You are passing the ostringstream to your function by pointer. There is no operator<< that takes an ostringstream* pointer as input and prints its string content. But there is an operator<< that takes a void* as input and prints the memory address that the pointer is pointing at. That is the "random numbers" you are seeing. ANY type of pointer can be assigned to a void* pointer.
You need to dereference the ostringstream* pointer to access the actual ostringstream object. Even so, there is still no operator<< that takes an ostringstream as input. However, ostringstream has a str() method that returns a std::string, and there is an operator<< for printing a std::string:
void Event::output(ostringstream* info) {
std::string s = info->str();
std::cout << s << std::endl;
fileOut << s << std::endl;
}
That being said, you should pass the ostringstream by const reference instead of by pointer, since the function does not allow a null ostringstream to be passed in, and it does not modify the ostringstream in any way:
void Event::output(const ostringstream &info) {
std::string s = info.str();
std::cout << s << std::endl;
fileOut << s << std::endl;
}
...
output(o);
seem not to output all new outputs on the same file but just creates a new file everytime and deletes what was on it before.
That is because you are not opening the file with either the app or ate flag 1, so it creates a new file each time, discarding the contents of any existing file. If you want to append to an existing file instead, you need to either:
use the ate flag to "seek to the end of stream immediately after open":
fileOut.open("testfile.txt", std::ios::out | std::ios::ate);
use the app flag to "seek to the end of stream before each write":
fileOut.open("testfile.txt", std::ios::out | std::ios::app);
1: if fileOut is a std::ofstream, you do not need to specify std::ios::out explicitly.
I am a newbie, writing a c++ code to open and read from multiple files and then dump part of the data into other files.
I want to generate file names in a for loop.
But I can't concatenate string(numbering of file) and string literal(a file extension). The same line of code works at the very beginning of the program, but not at the later part.
int main(int argc, char *argv[])
{
std::cout << std::string("9") + ".dat" << std::endl;
// many more lines
dump = 1;
if (dump == 1){
for (int ilevel=std::max(levelmin,lmin); ilevel < lmax + 1; ilevel++){
std::cout << std::string("9") + ".dat" << std::endl; // crashes here!
std::ofstream fout (std::string("9") + ".dat", std::ios::out | std::ios::binary);
std::cout << grid[ilevel].cube[0] << std::endl;
fout.write ((char*)&grid[ilevel].cube[0], grid[ilevel].cube.size() * sizeof(grid[ilevel].cube[0]));
fout.close();
}
}
...
}
If I put std::cout << std::string("9") + ".dat" << std::endl; at the beginning, it works and prints "9.dat".
but in the later loop, segmentation fault.
In between I call a function that uses stringstream to pad leading zeros to an integer. The function looks:
std::string int2str(const int n, const int m){
std::stringstream ss;
ss << std::setfill('0') << std::setw(m) << n;
std::string s2(ss.str());
ss.clear();
return s2;
}
I don't have a clear understanding about string and stringstream in c++.
But out of many things in my program, this function is the only thing I can think of being relevant. Other parts of codes does not deal with strings. It's mostly array manipulation code.
I've also tried std::string("9") + std::string(".dat")
but had no luck.
What is wrong?
Is there a specific reason why you're using std::string("9") rather than just "9"?
Where does the 9 come from? If its generated as part of a loop or a returned value from a function you can either place the variable itself to be concatenated, or the function that returns it, so:
std::cout << iFileNumber + ".dat" << std::endl;
or
std::cout << fileNumberGenerator() + ".dat" << std::endl;
For the hardcoded examples you've provided, I personally can't see the need for anything other than
std::cout << 9 + ".dat" << endl;
but that could easily just be lack of experience on my part.
For the sake of printing to the command line, its also worth nothing that this is equally acceptable syntax (assuming you're not already aware):
std::cout << 9 << ".dat" << endl;
Is it posible to use the TTF_Render_TextSolid controlled with one integer? I try to use stringstreams like this:
stringstream _minutes;
stringstream _seconds;
stringstream _miliseconds;
_minutes << minutes << ":";
_seconds << seconds << ":";
_miliseconds << miliseconds;
(the variable minutes, seconds and miliseconds was already scoped)
But when I compile this, compile well but then, I run and this says : core dumped. So the error is in the memory part. mmh what happens?
Doing something along the lines of:
stringstream ss;
ss << minutes << ":" << seconds << ":" << miliseconds;
const string str = ss.str();
SDL_Surface* surf = TTF_RenderText_Solid(textFont, str.c_str(), textColor);
Should work without a problem.
Do not store the const char* that comes out of it though! As soon as your str goes out of scope, your const char* won't be valid anymore.
I have an application in which I need to combine strings within a variable like so:
int int_arr[4];
int_arr[1] = 123;
int_arr[2] = 456;
int_arr[3] = 789;
int_arr[4] = 10;
std::string _string = "Text " + int_arr[1] + " Text " + int_arr[2] + " Text " + int_arr[3] + " Text " + int_arr[4];
It gives me the compile error
Error C2210: '+' Operator cannot add pointers" on the second string of the expression.
As far as I can tell I am combining string literals and integers, not pointers.
Is there another concatenation operator that I should be using? Or is the expression just completely wrong and should figure out another way to implement this?
BTW I am using Visual Studio 2010
Neither C nor C++ allow concatenation of const char * and int. Even C++'s std::string, doesn't concatenate integers. Use streams instead:
std::stringstream ss;
ss << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = ss.str();
You can do this in Java since it uses the toString() method automatically on each part.
If you want to do it the same way in C++, you'll have to explicitly convert those integer to strings in order for this to work.
Something like:
#include <iostream>
#include <sstream>
std::string intToStr (int i) {
std::ostringstream s;
s << i;
return s.str();
}
int main (void) {
int var = 7;
std::string s = "Var is '" + intToStr(var) + "'";
std::cout << s << std::endl;
return 0;
}
Of course, you can just use:
std::ostringstream os;
os << "Var is '" << var << "'";
std::string s = os.str();
which is a lot easier.
A string literal becomes a pointer in this context. Not a std::string. (Well, to be pedantically correct, string literals are character arrays, but the name of an array has an implicit conversion to a pointer. One predefined form of the + operator takes a pointer left-argument and an integral right argument, which is the best match, so the implicit conversion takes place here. No user-defined conversion can ever take precedence over this built-in conversion, according to the C++ overloading rules.).
You should study a good C++ book, we have a list here on SO.
A string literal is an expression returning a pointer const char*.
std::stringstream _string_stream;
_string_stream << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = _string_stream.str();
Hi below is my function:
string Employee::get_print(void) {
string out_string;
stringstream ss;
ss << e_id << " " << type << endl;
out_string = ss.str();
return out_string;
}
e_id and type are int and they contain values from the class Employee. But when I pass them into the stringstream they just clear the string when I try to out put it. But if I don't have a int in the ss << "Some text" << endl; this output fine. What am I doing wrong =S
//Edit
Ok;
This is the calling code:
tmp = cur->get_print();
Where tmp is a string and cur is an Employee Object.
This code...
stringstream out;
out << "Test " << e_id << " " << e_type;
return out.str();
Retruns "Test " and nothing else. If I take out "Test " << my returned string is ""
I'm using GCC 4.2 on Mac OS/X 10.6.2 if that makes any difference.
I too am unable to reproduce this error. As has been mentioned, don't include the endl, as this actually appends a \n and is supposed to flush the write buffer. For this use, it is completely unnecessary and may actually lead to undesirable results...However, the code in your edit/update works just fine for me.
int main(int argc, char* argv[])
{
int e_id = 5;
int e_type = 123456;
stringstream out;
out << "Test " << e_id << " " << e_type;
cout << out.str();
return 0;
}
Produces:
Test 5 123456
My suggestions would be to double check that e_id and e_type are really just native int.
For further testing, you may want to force a cast on the values to see if it helps as such:
out << "Test " << (int)e_id << " " << (int)e_type;
Since I'm unable to reproduce this error, I'm afraid I'm unable to help any further. But best of luck to you!
Ok I have no idea what is going on with stringstream I've tried using it in other parts of my code and it doesn't work with integers. Therefore, I have reverted to using the sprintf C function:
string Employee::get_print(void) {
char out[50];
sprintf(out, "%d %d", e_id, e_type);
string output = out;
return output;
}
This returns the string which is needed.
I have moved into Netbeans and I don't have this problem. So it is an issue with Xcode.
I think the endl is not needed. You only need to write endl if you want to write a newline on a file on on std::cout.
Since you write endl, your stringstream will contain a string with 2 lines of which the second is empty. This probably confuses you. Remove the endl to get only one line.
I've got exactly the same problem - GCC and stringstream returning nothing.
As I found out, the trick is that you have to put some text data before anything else into the stringstream.
This code...
stringstream ss(stringstream::out);
ss << 3.14159;
cout << "'" << ss.str() << "'" << endl;
gets you this result:
''
But if we put a single "" inside the stringstream first...
stringstream ss(stringstream::out);
ss << "" << 3.14159;
cout << "'" << ss.str() << "'" << endl;
the result is as expected:
'3.14159'