I'm new to windows programming, and what experience I have to-date has been with C#.
I've been asked to work on a project written by a colleague in C++. He's avoided using any of the .Net functionality as he doesn't like it. I'm trying to add in some debugging output, here is my code:
std::ostringstream strs;
strs << "Average value: " << dbl_sum / (double)_buffer.size() << " Buffer Size: " << _buffer.size();
std::string str = strs.str();
OutputDebugString((LPCTSTR)str.c_str());
However, when I run the program I'm seeing lines like this in the Debug window:
?????????????????????????????›?
My best guess is that it's something to do with my conversion to LPCTSTR, but I got that method from an answer to an old question on here.
Thanks to #Hans Passant I managed to fix this problem. I changed my code to:
std::ostringstream strs;
strs << "Average value: " << dbl_sum / (double)_buffer.size() << " Buffer Size: " << _buffer.size() << std::endl;
std::string str = strs.str();
OutputDebugStringA((LPCSTR)str.c_str());
I Guess your project's char set is UNICODE
when you take ASCII string and convert it to UNICODE you got Gibberish.
To resolve this you need to use wide string types instead of string or to change your program charset to Multi-bytes
You'll need to change these types:
string to wstring,
ostringstream to wostringstream,
"abc" to L"abc"
std::wostringstream strs;
strs << L"Average value: " << dbl_sum / (double)_buffer.size() << L" Buffer Size: " << _buffer.size();
std::wstring str = strs.str();
OutputDebugString(str.c_str());
Related
I know there are a ton questions on how to convert a std::string to a char* and through my research, I have adopted a few different options. However, the only one that seems to work for me is const_cast from the c_str() method.
So I am using that for now, but would like to know more information as to why the other methods do not work. What am I missing in my understanding as to why this isn't working as intended which seems to work for many others.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
char* test = "Hello World";
string testStr(test);
vector<char> testVec2(testStr.begin(), testStr.end());
// testVec2[0] = 'F';
char* test2 = reinterpret_cast<char*>(testVec2.data());
vector<char> testVec3(testStr.begin(), testStr.end());
// testVec3[0] = 'G';
char* test3 = &testVec3[0];
// The only one that works
char* test4 = const_cast<char*>(testStr.c_str());
cout << "char* test: " << test << " [" << strlen(test) << "]" << endl;
cout << "str test: " << testStr << " [" << testStr.length() << "]" << endl;
cout << "=== conv testing === " << endl;
cout << "char* test2: " << test2 << " [" << strlen(test2) << "]" << endl;
cout << "char* test3: " << test3 << " [" << strlen(test3) << "]" << endl;
cout << "char* test4: " << test4 << " [" << strlen(test4) << "]" << endl;
cin.get();
return 0;
}
I know the pitfalls of using const_cast but it works for my situation at the moment. I simply take the string from the user, pass it to a C API and do nothing else with it (no worries of it being modified).
Here is a sample of the output
https://imgur.com/a/2S1HD
So what am I doing wrong and is there a better way to do this?
UPDATE
Thanks to everyone for the extremely fast answers. It seems that my underlying confusion was the assumption of the null terminating character not being in the new buffer that I was assigning to the char* variable. Hence why my output was showing random characters after the string (that should have been my clue but it has been so long since I've done C/C++)
I also should have tagged this C++17 originally (since fixed) as that is what I am aiming for. I did not have that enabled in my console app in Visual Studio which made the solution by Passer By below work. That is the method I will use going forward.
Bottom line, changing my target to C++17 this works as expected
char* test = "Hello World";
string testStr(test);
vector<char> testVec2(testStr.begin(), testStr.end());
char* test2 = testStr.data();
vector<char> testVec2(testStr.begin(), testStr.end());
this will create the following vector:
vector<char> testVec2 = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
Anything jumps at you from that? It should. It doesn't contain the null terminator character. Any attempt to use testVec2.data() as a C string will result in Undefined Behavior because of this.
Although from C++11 std::string's underlying buffer has to contain the null terminator character, the begin - end range doesn't include it.
In C++17, the simplest way to fetch a char* from a std::string is simply
std::string str = "Why is this only available since C++17?";
some_c_function(str.data());
As to why other methods don't work, refer to bolov's answer
Since c++11 the best way to get a non-const char* from a std::string is to use this:
std::string s = "hello";
my_non_const_correct_c_function(&s[0]); // better than using const_cast
With a const_cast you can run into undefined behavior if you use it on a std::string that was not declared const.
Sorry for my English.
I need to convert double value to CString, because i need to do AfxMessageBox(double_value);
I find this:
std::ostringstream ost;
ost << double_value;
std::cout << "As string: " << ost.str() << std::endl;
//AfxMessageBox(ost.str()); - Does not work.
How i can do this?
AfxMessageBox expects a CString object, so format the double into a CString and pass that:
CString str;
str.Format("As string: %g", double);
AfxMessageBox(str);
Edit: If you want the value displayed as an integer (no value after decimal point) then use this instead:
str.Format("As string: %d", (int)double);
That's because ost.str() is not a CString, but rather a C++ string object. You need to convert that to CString: new CString(ost.str()).
Depending on your Unicode settings you need
std::ostringstream ost;
ost << std::setprecision(2) << double_value;
std::cout << "As string: " << ost.str() << std::endl;
AfxMessageBox(ost.str().c_str());
or
std::wostringstream ost;
ost << std::setprecision(2) << double_value;
std::wcout << L"As string: " << ost.str() << std::endl;
AfxMessageBox(ost.str().c_str());
This is needed because CString has a constructor for const char* or const wchar_t*. There is no constructor for std::string or std::wstring. You can also use the CString.Format which has the same not typesave problems like sprintf.
Be aware that double conversion is locale dependent. Decimal seperator will depend on your location.
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'