wstring to LPCWSTR not working with c_str() [duplicate] - c++

This question already has answers here:
Guaranteed lifetime of temporary in C++?
(6 answers)
Closed 8 years ago.
I am currently doing DirectX11 and trying to convert a UTF8 string into a LPCWSTR. I've written a utility function to aid me in the conversion:
// Convert an UTF8 string to a wide Unicode String
std::wstring WidenString(const std::string &string)
{
int size_needed = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), NULL, 0);
std::wstring wstring(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), &wstring[0], size_needed);
return wstring;
}
I've used the debugger to verify if it works. This is working:
Debugger says wndClassEx.lpszClassName = L"Hello"
std::wstring str = WidenString("Hello");
wndClassEx.lpszClassName = str.c_str();
This is not working:
Debugger says wndClassEx.lpszClassName = L"ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ..."
wndClassEx.lpszClassName = WidenString("Hello").c_str();
Can someone explain to me what is wrong with my code?

WidenString() returns a wstring by value. In the first snippet, wndClassEx.lpszClassName will point to a valid memory location as long as the variable str remains in scope i.e. it does not get destroyed.
In the second case the return value does go out of scope at the end of the expression (at the ;) and wndClassEx.lpszClassName then points to invalid memory.

Related

How to convert CString to byte [] array? [duplicate]

This question already has answers here:
conversion of Cstring to BYTE
(5 answers)
Closed 4 years ago.
I am trying to convert CString to byte [] array in Visual Studio MFC. Please see the code below.
CString str_text;
GetDlgItemText(IDC_KEY_TEXT, str_text);
BYTE A[] = "hi I love stackoverflow";
BYTE A[] = str_text;
Here, BYTE A [] is a byte array.
Regardless of CString and GetDlgItemText function, if I do only (1) my program does well.
But If you type CString(str_text)(2) instead of "hi I love stackoverflow" I have a error. That's error is "it couldn't convert CString to byte array".
I would like to convert CString to byte array. Please tell me where my mistake is.
Here is the proper way of doing this. I assume you deal with Unicode strings:
CStringW str = L"Hello World";
// convert to UTF-8
CStringA utf8 = CW2A(str, CP_UTF8);
CByteArray Bytes;
const size_t nBytes = sizeof(CStringA::XCHAR) * utf8.GetLength();
Bytes.SetSize( nBytes );
std::memcpy( Bytes.GetData(), static_cast<BYTE const*>utf8, nBytes );

Converting string to LPCTSTR

I encountered a problem during writting my code. I use a function which take as an argument object which type is LPCSTR. The object declaration looks like shown below:
LPCTSTR lpFileName;
Firstly, I used defined variable, which was futher assign to lpFileName like this:
#define COM_NR L"COM3"
lpFileName = COM_NR
Using this manner, I could easily pass lpFileName argument to the function. Anyway, i had to changed the way of defining my port number. Currently i read text from *.txt file and save it as string variable e.g "COM3" or "COM10". The main problem is to convert string to LPCSTR properly. I found good solution but finally it doesn't seem working properly. My code looks like this:
string temp;
\\code that fill temp\\
wstring ws;
ws.assign(temp.begin(),temp.end());
I thought that conversion went correctly, maybe it did and I don't get it because when i print few things it makes me to wonder why it doesn't work as i want:
cout temp_cstr(): COM3
cout LCOM3: 0x40e586
cout ws.c_str(): 0x8b49b2c
Why LCOM3 and ws.c_str() doesn't contain the same? When i pass lpFileName = ws.c_str() to my function, it works uncorretly. On the other hand, passing lpFileName = L"COM3" gives success.
I code using cpp, and IDE is QtCreator
Eventually, I managed with the pitfall using conversion-function s2ws() and doing few operations. I place my soultion here for people who will have similar troubles with converting string. In my first post i wrote that i needed to convert string to LPCTSTR and finally it turned out that argument in my function is not, LPCTSTR but LPCWSTR that is const wchar_t*.
So, soulution:
string = "COM3";
wstring stemp;
LPCWSTR result_port;
stemp = s2ws(port_nr);
result_port = stemp.c_str(); // now passing result_port to my function i am getting success
declaration of s2ws:
wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
Try to use wostringstream:
string temp;
\\code that fill temp\\
wostringstream ost;
ost << temp.c_str();
wstring ws = ost.str();
I have struggled with this for quite a while. After quite a bit of digging I found this works the best; you could try this.
std::string t = "xyz";
CA2T wt (t.c_str());

Unexpected results with wchar_t and c_str string conversion

Based on this answer to a related question, I tried to write a method that converts a standard string to a wide string, which I can then convert into a wchar_t*.
Why aren't the two different ways of creating the wchar_t* equivalent? (I've shown the values that my debugger gives me).
TEST_METHOD(TestingAssertsWithGetWideString)
{
std::wstring wString1 = GetWideString("me");
const wchar_t* wchar1 = wString1.c_str(); // wchar1 = "me"
const wchar_t* wchar2 = GetWideString("me").c_str(); // wchar2 = "ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ#" (Why?!)
}
where GetWideString is defined as follows:
inline const std::wstring GetWideString(const std::string &str)
{
std::wstring wstr;
wstr.assign(str.begin(), str.end());
return wstr;
};
Note: the following doesn't work either.
const wchar_t* wchar2 = GetWChar("me");
const wchar_t *GetWChar(const std::string &str)
{
std::wstring wstr;
wstr.assign(str.begin(), str.end());
return wstr.c_str();
};
Each time you call GetWideString(), you are creating a new std::wstring, which has a newly allocated memory buffer. You are comparing pointers to different memory blocks (assuming Assert::AreEqual() is simply comparing the pointers themselves and not the contents of the memory blocks that are being pointed at).
Update: const wchar_t* wchar2 = GetWideString("me").c_str(); does not work because GetWideString() returns a temporary std::wstring that goes out of scope and gets freed as soon as the statement is finished. Thus you are obtaining a pointer to a temporary memory block, and then leaving that pointer dangling when that memory gets freed before you can use the pointer for anything.
Also, const wchar_t* wchar2 = GetWChar("me"); should not compile. GetWChar() returns a std::wstring, which does not implement an implicit conversion to wchar_t*. You have to use the c_str() method to get a wchar_t* from a std::wstring.
Because the two pointers aren't equal. A wchar_t * is not a String, so you get the generic AreEqual.
std::wstring contains of wide characters of type wchar_t. std::string contains characters of type char. For special characters stored within std::string a multi-byte encoding is being used, i.e. some characters are represented by 2 characters within such a string. Converting between these thus can not be easy as calling a simple assign.
To convert between "wide" strings and multi-byte strings, you can use following helpers (Windows only):
// multi byte to wide char:
std::wstring s2ws(const std::string& str)
{
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
// wide char to multi byte:
std::string ws2s(const std::wstring& wstr)
{
int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0);
return strTo;
}

C++ Unicode Issue

I'm having a bit of trouble with handling unicode conversions.
The following code outputs this into my text file.
HELLO??O
std::string test = "HELLO";
std::string output;
int len = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)test.c_str(), -1, NULL, 0, NULL, NULL);
char *buf = new char[len];
int len2 = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)test.c_str(), -1, buf, len, NULL, NULL);
output = buf;
std::wofstream outfile5("C:\\temp\\log11.txt");
outfile5 << test.c_str();
outfile5 << output.c_str();
outfile5.close();
But as you can see, output is just a unicode conversion from the test variable. How is this possible?
Check if the LEN is correct after first measuring call. In general, you should not cast test.c_str() to LPCWSTR. The 'test' as is 'char'-string not 'wchar_t'-wstring. You may cast it to LPCSTR - note the 'W' missing. The WinAPI has distinction between that. You really should be using wstring if you want to keep widechars in it.. Yeah, after re-reading your code, the test should be a wstring, then you can cast it to LPCWSTR safely.
after reading this
Microsoft wstring reference
I changed
std::string test = "HELLO";
to
std::wstring test = L"HELLO";
And the string was outputted correctly and I got
HELLOHELLO

How to insert variables values in the registry with C++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Char array gives error when initializing
I want to insert an environment variable in the windows registry, so i tied the following C++ code :
string appDataPath = getenv("appdata");
HKEY hkey;
char value[] = appDataPath.c_str();
RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\Currentversion\\Run", 0, KEY_SET_VALUE, &hkey);
RegSetValueEx (hkey, "MyProgram", 0, REG_SZ, (LPBYTE) value, strlen(value) + 1);
RegCloseKey(hkey);
The codeblock debug output tell me : error: initializer fails to determine size of 'value'
I think it's because the compilator need to know the size of my variable before compiling, however i don't know how to fix that...
Thanks !
c_str() returns a const char*, not a char[]. Change
char value[] = appDataPath.c_str();
to
const char* value = appDataPath.c_str();
The compiler is giving the error because an array variable requires a length - which is not being provided.
Use
const char * value = appDataPath.c_str();
(Read the < string > reference to find the return type of c_str(), it will tell you that it is indeed const char *.)
Regarding your question of how to concatenate two strings:
Do that with C++ strings rather than with char *s and convert them later:
string newstring = appDataPath;
newstring.append("some text");
const char * value = newstring.c_str();