How do I convert a TCHAR
array to std::string
(not to std::basic_string
)?
TCHAR
is just a typedef that, depending on your compilation configuration, either defaults to char
or wchar_t
.
Standard Template Library supports both ASCII (with std::string
) and wide character sets (with std::wstring
). All you need to do is to typedef String as either std::string or std::wstring depending on your compilation configuration. To maintain flexibility you can use the following code:
#ifndef UNICODE
typedef std::string String;
#else
typedef std::wstring String;
#endif
Now you may use String
in your code and let the compiler handle the nasty parts. String will now have constructors that lets you convert TCHAR
to std::string
or std::wstring
.
typedef std::wcout std_tcout
and std_tstring
etc? I can't... get myself to facade a standard like that. Then again, I used to do it for graphics operations all the time. Why not std::basic_string<TCHAR>
for the first half of the typedef of string is there a discernible difference? –
Ashaashamed std::wstring
and std::string
, assuming UTF-8, but there are other scenarios. Considering this is VS, I'd just try to stick to W2A()
and A2W()
in most cases though. –
Ashaashamed My answer is late, I'll admit that, but with the answers of 'Alok Save' and some research I've found a good way! (Note: I didn't test this version a lot, so it might not work in every case, but from what I tested it should):
TCHAR t = SomeFunctionReturningTCHAR();
std::string str;
#ifndef UNICODE
str = t;
#else
std::wstring wStr = t;
str = std::string(wStr.begin(), wStr.end());
#endif
std::cout << str << std::endl; //<-- should work!
TCHAR type is char
or wchar_t
, depending on your project settings.
#ifdef UNICODE
// TCHAR type is wchar_t
#else
// TCHAR type is char
#endif
So if you must use std::string
instead of std::wstring
, you should use a converter function. I may use wcstombs
or WideCharToMultiByte
.
TCHAR * text;
#ifdef UNICODE
/*/
// Simple C
const size_t size = ( wcslen(text) + 1 ) * sizeof(wchar_t);
wcstombs(&buffer[0], text, size);
std::vector<char> buffer(size);
/*/
// Windows API (I would use this)
std::vector<char> buffer;
int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
if (size > 0) {
buffer.resize(size);
WideCharToMultiByte(CP_UTF8, 0, text, -1, static_cast<BYTE*>(&buffer[0]), buffer.size(), NULL, NULL);
}
else {
// Error handling
}
//*/
std::string string(&buffer[0]);
#else
std::string string(text);
#endif
TCHAR is either char or wchar_t, so a
typedef basic_string<TCHAR> tstring;
is one way of doing it.
The other is to skip char
altogether and just use std::wstring
.
Simple!
std::string tcharToChar(TCHAR* buffer)
{
char *charBuffer = NULL;
std::string returnValue;
int lengthOfbuffer = lstrlenW(buffer);
if(buffer!=NULL)
{
charBuffer = (char*)calloc(lengthOfbuffer+1,sizeof(char));
}
else
{
return NULL;
}
for (int index = 0;
index < lengthOfbuffer;
index++)
{
char *singleCharacter = (char*)calloc(2,sizeof(char));
singleCharacter[0] = (char)buffer[index];
singleCharacter[1] = '\0';
strcat(charBuffer, singleCharacter);
free(singleCharacter );
}
strcat(charBuffer, "\0");
returnValue.append(charBuffer);
free(charBuffer);
return returnValue;
}
std::string
instead? Edit : You also leak a ton of tiny buffers with singleCharacter
. This solution is not acceptable as-is. There is no need to dynamically allocate for singleCharacter
and I don't see the need for strcat
to write a string character-by-character. –
Vanessa strcat
or singleCharacter
, you can just push the last character to the position index
of charBuffer
. You also don't need to allocate for charBufffer
because std::string
already has a character buffer you can use. Manual memory management has fallen heavily out of favor in modern C++ and should generally not be part of recommended solutions unless absolutely necessary. –
Vanessa calloc
, malloc
, etc. are C memory allocation functions and are not as easy to use in C++. They do not start the lifetime of objects. new
should be used instead, but even then new
is also discouraged. std::vector
and std::make_unique
should replace the vast majority of manual memory management. –
Vanessa Quick and dirty solution :
TCHAR str[256] = {};
// put something in str...
// convert to string
std::string strtmp(&str[0], &str[255]);
std::cout << strtmp << std::endl;
std::string
with a length of 255 characters, even when the string contains a null terminator. std::string
can contain nulls, specifically if you use the range based constructor like in this case. –
Vanessa © 2022 - 2024 — McMap. All rights reserved.