Converting Std: :Wsting to Char* with Wcstombs_S
I Have Input Strings That Contain Only Digits (Just the Plain Latin Ones, 0-9, So for Example "0123"), Stored as Std: :Wstring, and I Need Each as a Char*...
I have input strings that contain only digits (just the plain Latin ones, 0-9, so for example "0123"), stored as std::wstring, and I need each as a char*. What's the best way for me to do this? This is my initial approach:
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, sizeof(outputString), inputW, input.length());
}
EDIT: The code below works. Thanks all!
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1; // +1 for null terminator
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, outputSize, inputW, input.length());
}
3 Answers
You are not allocating enough memory for your buffer:
char * outputString = new char[input.length()];
Should be
char * outputString = new char[input.length() + 1];
because of terminating NUL-character.
Oh, and also, as per pm100's comment: sizeof(outputString) is giving you the size of the pointer. You should use input.length() + 1, as that is the size of the buffer.
There are a couple of errors in your code. First, you're not allocating enough space in your destination buffer for the NULL character. You must allocate at least input.length() + 1 chars for the function to succeed.
Second, you're not passing in the correct size of the output buffer to the function. sizeof(outputString) returns the size of outputString itself, a char *, and not the number of bytes pointed to by that pointer.
So your function should look like this:
void CoverageTileManager::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1;
outputString = new char[outputSize];
size_t charsConverted = 0;
wcstombs_s(&charsConverted, outputString, outputSize, input.c_str(), input.length());
// TODO verify charsConverted = outputSize
}
In C++ I would never use pure pointers: use vector if a char array needed in heap! Do you want to copy the source string? If not, const reference should be used for input. wcstombs_s is used only in Windows, so why doesn't use simply WideCharToMultiByte? Was the conversion success? Return value.
bool CoverageTileManager::convertWStringToCharPtr(const std::wstring& input, std::vector<char>& outputString )
{
if ( input.empty() ) {
return false;
}
int size = WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),NULL,0,NULL,NULL);
if ( size <= 0 ) {
return false;
}
outputString.resize(size+1);
if ( WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),&outputString[0],size,NULL,NULL) <= 0 ) {
outputString.clear();
return false;
}
outputString[size] = '\0';
return true;
}
Use vector to external C++ lib:
extern void call( const char*, size_t);
std::vector<char> buffer;
std::wstring input;
...
if ( convertWStringToCharPtr(input,buffer) ) {
call(&buffer[0],buffer.size());
}