how to convert char array to wchar_t array? - c++

char cmd[40];
driver = FuncGetDrive(driver);
sprintf_s(cmd, "%c:\\test.exe", driver);
I cannot use cmd in
sei.lpFile = cmad;
so,
how to convert char array to wchar_t array ?

Just use this:
static wchar_t* charToWChar(const char* text)
{
const size_t size = strlen(text) + 1;
wchar_t* wText = new wchar_t[size];
mbstowcs(wText, text, size);
return wText;
}
Don't forget to call delete [] wCharPtr on the return result when you're done, otherwise this is a memory leak waiting to happen if you keep calling this without clean-up. Or use a smart pointer like the below commenter suggests.
Or use standard strings, like as follows:
#include <cstdlib>
#include <cstring>
#include <string>
static std::wstring charToWString(const char* text)
{
const size_t size = std::strlen(text);
std::wstring wstr;
if (size > 0) {
wstr.resize(size);
std::mbstowcs(&wstr[0], text, size);
}
return wstr;
}

From MSDN:
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
using namespace System;
int main()
{
char *orig = "Hello, World!";
cout << orig << " (char *)" << endl;
// Convert to a wchar_t*
size_t origsize = strlen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;
}

From your example using swprintf_s would work
wchar_t wcmd[40];
driver = FuncGetDrive(driver);
swprintf_s(wcmd, "%C:\\test.exe", driver);
Note the C in %C has to be written with uppercase since driver is a normal char and not a wchar_t.
Passing your string to swprintf_s(wcmd,"%S",cmd) should also work

Related

Get temp path with file name

I want to get path to file like this > %ENV%/%FILE_NAME%.docx
But c++ doesn't make sense at all and nothing works..
I would use std::string but it's not compatible so I tried multiple ways of converting it to char[] or char* but none of them works and I'm also pretty sure this is unsafe..
My code so far (I know it's the worst code ever..)
char* appendCharToCharArray(char* array, char a)
{
size_t len = strlen(array);
char* ret = new char[len + 2];
strcpy(ret, array);
ret[len] = a;
ret[len + 1] = '\0';
return ret;
}
const char* getBaseName(std::string path)
{
std::string base_filename = path.substr(path.find_last_of("/\\") + 1);
std::string::size_type const p(base_filename.find_last_of('.'));
std::string file_without_extension = base_filename.substr(0, p);
return file_without_extension.c_str();
}
int main()
{
char szExeFileName[MAX_PATH];
GetModuleFileName(NULL, szExeFileName, MAX_PATH);
const char* file_name = getBaseName(std::string(szExeFileName));
char* new_file = getenv("temp");
new_file = appendCharToCharArray(new_file, '\\');
for (int i=0;i<sizeof(file_name)/sizeof(file_name[0]);i++)
{
new_file = appendCharToCharArray(new_file, file_name[i]);
}
new_file = appendCharToCharArray(new_file, '.');
new_file = appendCharToCharArray(new_file, 'd');
new_file = appendCharToCharArray(new_file, 'o');
new_file = appendCharToCharArray(new_file, 'c');
new_file = appendCharToCharArray(new_file, 'x');
std::cout << new_file << std::endl;
}
Using appendCharToCharArray() is just horribly inefficient in general, and also you are leaking lots of memory with the way you are using it. Just use std::string instead. And yes, you can use std::string in this code, it is perfectly "compatible" if you use it correctly.
getBaseName() is returning a char* pointer to the data of a local std::string variable that goes out of scope when the function exits, thus a dangling pointer is returned. Again, use std::string instead.
And, you should use the Win32 GetTempPath/2() function instead of getenv("temp").
Try something more like this:
#include <iostream>
#include <string>
std::string getBaseName(const std::string &path)
{
std::string base_filename = path.substr(path.find_last_of("/\\") + 1);
std::string::size_type const p(base_filename.find_last_of('.'));
std::string file_without_extension = base_filename.substr(0, p);
return file_without_extension;
}
int main()
{
char szExeFileName[MAX_PATH] = {};
GetModuleFileNameA(NULL, szExeFileName, MAX_PATH);
char szTempFolder[MAX_PATH] = {};
GetTempPathA(MAX_PATH, szTempFolder);
std::string new_file = std::string(szTempFolder) + getBaseName(szExeFileName) + ".docx";
std::cout << new_file << std::endl;
}
Online Demo
That being said, the Win32 Shell API has functions for manipulating path strings, eg:
#include <iostream>
#include <string>
#include <windows.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
int main()
{
char szExeFileName[MAX_PATH] = {};
GetModuleFileNameA(NULL, szExeFileName, MAX_PATH);
char szTempFolder[MAX_PATH] = {};
GetTempPathA(MAX_PATH, szTempFolder);
char new_file[MAX_PATH] = {};
PathCombineA(new_file, szTempFolder, PathFindFileNameA(szExeFileName));
PathRenameExtensionA(new_file, ".docx");
std::cout << new_file << std::endl;
}
Or, if you are using C++17 or later, consider using std::filesystem::path instead, eg:
#include <iostream>
#include <filesystem>
#include <windows.h>
namespace fs = std::filesystem;
int main()
{
char szExeFileName[MAX_PATH] = {};
GetModuleFileNameA(NULL, szExeFileName, MAX_PATH);
char szTempFolder[MAX_PATH] = {};
GetTempPathA(MAX_PATH, szTempFolder);
fs::path new_file = fs::path(szTempFolder) / fs::path(szExeFileName).stem();
new_file += ".docx";
// alternatively:
// fs::path new_file = fs::path(szTempFolder) / fs::path(szExeFileName).filename();
// new_file.replace_extension(".docx");
std::cout << new_file << std::endl;
}
Online Demo

how can I convert wstring to u16string?

I want to convert wstring to u16string in C++.
I can convert wstring to string, or reverse. But I don't know how convert to u16string.
u16string CTextConverter::convertWstring2U16(wstring str)
{
int iSize;
u16string szDest[256] = {};
memset(szDest, 0, 256);
iSize = WideCharToMultiByte(CP_UTF8, NULL, str.c_str(), -1, NULL, 0,0,0);
WideCharToMultiByte(CP_UTF8, NULL, str.c_str(), -1, szDest, iSize,0,0);
u16string s16 = szDest;
return s16;
}
Error in WideCharToMultiByte(CP_UTF8, NULL, str.c_str(), -1, szDest, iSize,0,0);'s szDest. Cause of u16string can't use with LPSTR.
How can I fix this code?
For a platform-independent solution see this answer.
If you need a solution only for the Windows platform, the following code will be sufficient:
std::wstring wstr( L"foo" );
std::u16string u16str( wstr.begin(), wstr.end() );
On the Windows platform, a std::wstring is interchangeable with std::u16string because sizeof(wstring::value_type) == sizeof(u16string::value_type) and both are UTF-16 (little endian) encoded.
wstring::value_type = wchar_t
u16string::value_type = char16_t
The only difference is that wchar_t is signed, whereas char16_t is unsigned. So you only have to do sign conversion, which can be performed by using the u16string constructor that takes an iterator pair as arguments. This constructor will implicitly convert wchar_t to char16_t.
Full example console application:
#include <windows.h>
#include <string>
int main()
{
static_assert( sizeof(std::wstring::value_type) == sizeof(std::u16string::value_type),
"std::wstring and std::u16string are expected to have the same character size" );
std::wstring wstr( L"foo" );
std::u16string u16str( wstr.begin(), wstr.end() );
// The u16string constructor performs an implicit conversion like:
wchar_t wch = L'A';
char16_t ch16 = wch;
// Need to reinterpret_cast because char16_t const* is not implicitly convertible
// to LPCWSTR (aka wchar_t const*).
::MessageBoxW( 0, reinterpret_cast<LPCWSTR>( u16str.c_str() ), L"test", 0 );
return 0;
}
Update
I had thought the standard version did not work, but in fact this was simply due to bugs in the Visual C++ and libstdc++ 3.4.21 runtime libraries. It does work with clang++ -std=c++14 -stdlib=libc++. Here is a version that tests whether the standard method works on your compiler:
#include <codecvt>
#include <cstdlib>
#include <cstring>
#include <cwctype>
#include <iostream>
#include <locale>
#include <clocale>
#include <vector>
using std::cout;
using std::endl;
using std::exit;
using std::memcmp;
using std::size_t;
using std::wcout;
#if _WIN32 || _WIN64
// Windows needs a little non-standard magic for this to work.
#include <io.h>
#include <fcntl.h>
#include <locale.h>
#endif
using std::size_t;
void init_locale(void)
// Does magic so that wcout can work.
{
#if _WIN32 || _WIN64
// Windows needs a little non-standard magic.
constexpr char cp_utf16le[] = ".1200";
setlocale( LC_ALL, cp_utf16le );
_setmode( _fileno(stdout), _O_U16TEXT );
#else
// The correct locale name may vary by OS, e.g., "en_US.utf8".
constexpr char locale_name[] = "";
std::locale::global(std::locale(locale_name));
std::wcout.imbue(std::locale());
#endif
}
int main(void)
{
constexpr char16_t msg_utf16[] = u"¡Hola, mundo! \U0001F600"; // Shouldn't assume endianness.
constexpr wchar_t msg_w[] = L"¡Hola, mundo! \U0001F600";
constexpr char32_t msg_utf32[] = U"¡Hola, mundo! \U0001F600";
constexpr char msg_utf8[] = u8"¡Hola, mundo! \U0001F600";
init_locale();
const std::codecvt_utf16<wchar_t, 0x1FFFF, std::little_endian> converter_w;
const size_t max_len = sizeof(msg_utf16);
std::vector<char> out(max_len);
std::mbstate_t state;
const wchar_t* from_w = nullptr;
char* to_next = nullptr;
converter_w.out( state, msg_w, msg_w+sizeof(msg_w)/sizeof(wchar_t), from_w, out.data(), out.data() + out.size(), to_next );
if (memcmp( msg_utf8, out.data(), sizeof(msg_utf8) ) == 0 ) {
wcout << L"std::codecvt_utf16<wchar_t> converts to UTF-8, not UTF-16!" << endl;
} else if ( memcmp( msg_utf16, out.data(), max_len ) != 0 ) {
wcout << L"std::codecvt_utf16<wchar_t> conversion not equal!" << endl;
} else {
wcout << L"std::codecvt_utf16<wchar_t> conversion is correct." << endl;
}
out.clear();
out.resize(max_len);
const std::codecvt_utf16<char32_t, 0x1FFFF, std::little_endian> converter_u32;
const char32_t* from_u32 = nullptr;
converter_u32.out( state, msg_utf32, msg_utf32+sizeof(msg_utf32)/sizeof(char32_t), from_u32, out.data(), out.data() + out.size(), to_next );
if ( memcmp( msg_utf16, out.data(), max_len ) != 0 ) {
wcout << L"std::codecvt_utf16<char32_t> conversion not equal!" << endl;
} else {
wcout << L"std::codecvt_utf16<char32_t> conversion is correct." << endl;
}
wcout << msg_w << endl;
return EXIT_SUCCESS;
}
Previous
A bit late to the game, but here’s a version that additionally checks whether wchar_t is 32-bits (as it is on Linux), and if so, performs surrogate-pair conversion. I recommend saving this source as UTF-8 with a BOM. Here is a link to it on ideone.
#include <cassert>
#include <cwctype>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <locale>
#include <string>
#if _WIN32 || _WIN64
// Windows needs a little non-standard magic for this to work.
#include <io.h>
#include <fcntl.h>
#include <locale.h>
#endif
using std::size_t;
void init_locale(void)
// Does magic so that wcout can work.
{
#if _WIN32 || _WIN64
// Windows needs a little non-standard magic.
constexpr char cp_utf16le[] = ".1200";
setlocale( LC_ALL, cp_utf16le );
_setmode( _fileno(stdout), _O_U16TEXT );
#else
// The correct locale name may vary by OS, e.g., "en_US.utf8".
constexpr char locale_name[] = "";
std::locale::global(std::locale(locale_name));
std::wcout.imbue(std::locale());
#endif
}
std::u16string make_u16string( const std::wstring& ws )
/* Creates a UTF-16 string from a wide-character string. Any wide characters
* outside the allowed range of UTF-16 are mapped to the sentinel value U+FFFD,
* per the Unicode documentation. (http://www.unicode.org/faq/private_use.html
* retrieved 12 March 2017.) Unpaired surrogates in ws are also converted to
* sentinel values. Noncharacters, however, are left intact. As a fallback,
* if wide characters are the same size as char16_t, this does a more trivial
* construction using that implicit conversion.
*/
{
/* We assume that, if this test passes, a wide-character string is already
* UTF-16, or at least converts to it implicitly without needing surrogate
* pairs.
*/
if ( sizeof(wchar_t) == sizeof(char16_t) ) {
return std::u16string( ws.begin(), ws.end() );
} else {
/* The conversion from UTF-32 to UTF-16 might possibly require surrogates.
* A surrogate pair suffices to represent all wide characters, because all
* characters outside the range will be mapped to the sentinel value
* U+FFFD. Add one character for the terminating NUL.
*/
const size_t max_len = 2 * ws.length() + 1;
// Our temporary UTF-16 string.
std::u16string result;
result.reserve(max_len);
for ( const wchar_t& wc : ws ) {
const std::wint_t chr = wc;
if ( chr < 0 || chr > 0x10FFFF || (chr >= 0xD800 && chr <= 0xDFFF) ) {
// Invalid code point. Replace with sentinel, per Unicode standard:
constexpr char16_t sentinel = u'\uFFFD';
result.push_back(sentinel);
} else if ( chr < 0x10000UL ) { // In the BMP.
result.push_back(static_cast<char16_t>(wc));
} else {
const char16_t leading = static_cast<char16_t>(
((chr-0x10000UL) / 0x400U) + 0xD800U );
const char16_t trailing = static_cast<char16_t>(
((chr-0x10000UL) % 0x400U) + 0xDC00U );
result.append({leading, trailing});
} // end if
} // end for
/* The returned string is shrunken to fit, which might not be the Right
* Thing if there is more to be added to the string.
*/
result.shrink_to_fit();
// We depend here on the compiler to optimize the move constructor.
return result;
} // end if
// Not reached.
}
int main(void)
{
static const std::wstring wtest(L"☪☮∈✡℩☯✝ \U0001F644");
static const std::u16string u16test(u"☪☮∈✡℩☯✝ \U0001F644");
const std::u16string converted = make_u16string(wtest);
init_locale();
std::wcout << L"sizeof(wchar_t) == " << sizeof(wchar_t) << L".\n";
for( size_t i = 0; i <= u16test.length(); ++i ) {
if ( u16test[i] != converted[i] ) {
std::wcout << std::hex << std::showbase
<< std::right << std::setfill(L'0')
<< std::setw(4) << (unsigned)converted[i] << L" ≠ "
<< std::setw(4) << (unsigned)u16test[i] << L" at "
<< i << L'.' << std::endl;
return EXIT_FAILURE;
} // end if
} // end for
std::wcout << wtest << std::endl;
return EXIT_SUCCESS;
}
Footnote
Since someone asked: The reason I suggest UTF-8 with BOM is that some compilers, including MSVC 2015, will assume a source file is encoded according to the current code page unless there is a BOM or you specify an encoding on the command line. No encoding works on all toolchains, unfortunately, but every tool I’ve used that’s modern enough to support C++14 also understands the BOM.
- To convert CString to std:wstring and string
string CString2string(CString str)
{
int bufLen = WideCharToMultiByte(CP_UTF8, 0, (LPCTSTR)str, -1, NULL, 0, NULL,NULL);
char *buf = new char[bufLen];
WideCharToMultiByte(CP_UTF8, 0, (LPCTSTR)str, -1, buf, bufLen, NULL, NULL);
string sRet(buf);
delete[] buf;
return sRet;
}
CString strFileName = "test.txt";
wstring wFileName(strFileName.GetBuffer());
strFileName.ReleaseBuffer();
string sFileName = CString2string(strFileName);
- To convert string to CString
CString string2CString(string s)
{
int bufLen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, NULL, 0);
WCHAR *buf = new WCHAR[bufLen];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, buf, bufLen);
CString strRet(buf);
delete[] buf;
return strRet;
}
string sFileName = "test.txt";
CString strFileName = string2CString(sFileName);

C++ TCHAR array to wstring not working in VS2010

I would like to convert a TCHAR array to a wstring.
TCHAR szFileName[MAX_PATH+1];
#ifdef _DEBUG
std::string str="m:\\compiled\\data.dat";
TCHAR *param=new TCHAR[str.size()+1];
szFileName[str.size()]=0;
std::copy(str.begin(),str.end(),szFileName);
#else
//Retrieve the path to the data.dat in the same dir as our data.dll is located
GetModuleFileName(_Module.m_hInst, szFileName, MAX_PATH+1);
StrCpy(PathFindFileName(szFileName), _T("data.dat"));
#endif
wstring sPath(T2W(szFileName));
I need to pass szFileName to a function that expects
const WCHAR *
For completeness I am stating the void that I need to pass szFileName to:
HRESULT CEngObj::MapFile( const WCHAR * pszTokenVal, // Value that contains file path
HANDLE * phMapping, // Pointer to file mapping handle
void ** ppvData ) // Pointer to the data
However, T2W does not work for me. The compiler says that "_lpa" is not defined, and I don't know where to go on from here. I have tried other conversion methods that I found stated on the net, but they did not work either.
There are functions like
mbstowcs_s()
that convert from char* to wchar_t*.
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
char *orig = "Hello, World!";
cout << orig << " (char *)" << endl;
// Convert to a wchar_t*
size_t origsize = strlen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;
Look here for an article and here for MSDN.
The definition of TCHAR differs depending on if certain preprocessor macros are defined or not. See e.g. this article for the possible combinations.
This means that TCHAR may already be a wchar_t.
You can use the _UNICODE macro to check if you need to convert the string. If you do, then you can use mbstowcs to do the conversion:
std::wstring str;
#ifdef _UNICODE
// No need to convert the string
str = your_tchar_string;
#else
// Need to convert the string
// First get the length needed
int length = mbstowcs(nullptr, your_tchar_string, 0);
// Allocate a temporary string
wchar_t* tmpstr = new wchar_t[length + 1];
// Do the actual conversion
mbstowcs(tmpstr, your_tchar_str, length + 1);
str = tmpstr;
// Free the temporary string
delete[] tmpstr;
#endif

how to convert const WCHAR * to const char *

CString output ;
const WCHAR* wc = L"Hellow World" ;
if( wc != NULL )
{
output.Append(wc);
}
printf( "output: %s\n",output.GetBuffer(0) );
you can also try this:
#include <comdef.h> // you will need this
const WCHAR* wc = L"Hello World" ;
_bstr_t b(wc);
const char* c = b;
printf("Output: %s\n", c);
_bstr_t implements following conversion operators, which I find quite handy:
operator const wchar_t*( ) const throw( );
operator wchar_t*( ) const throw( );
operator const char*( ) const;
operator char*( ) const;
EDIT: clarification with regard to answer comments: line const char* c = b; results in a narrow character copy of the string being created and managed by the _bstr_t instance which will release it once when it is destroyed. The operator just returns a pointer to this copy. Therefore, there is no need to copy this string. Besides, in the question, CString::GetBuffer returns LPTSTR (i.e. TCHAR*) and not LPCTSTR (i.e. const TCHAR*).
Another option is to use conversion macros:
USES_CONVERSION;
const WCHAR* wc = L"Hello World" ;
const char* c = W2A(wc);
The problem with this approach is that the memory for converted string is allocated on stack, so the length of the string is limited. However, this family of conversion macros allow you to select the code page which is to be used for the conversion, which is often needed if wide string contains non-ANSI characters.
You can use sprintf for this purpose:
const char output[256];
const WCHAR* wc = L"Hellow World" ;
sprintf(output, "%ws", wc );
My code for Linux
// Debian GNU/Linux 8 "Jessie" (amd64)
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
// Use wcstombs(3) to convert Unicode-string (wchar_t *) to UTF-8 (char *)
// http://man7.org/linux/man-pages/man3/wcstombs.3.html
int f(const wchar_t *wcs) {
setlocale(LC_ALL,"ru_RU.UTF-8");
printf("Sizeof wchar_t: %d\n", sizeof(wchar_t));
// on Windows, UTF-16 is internal Unicode encoding (UCS2 before WinXP)
// on Linux, UCS4 is internal Unicode encoding
for (int i = 0; wcs[i] > 0; i++) printf("%2d %08X\n",i,wcs[i]);
char s[256];
size_t len = wcstombs(s,wcs,sizeof(s));
if (len > 0) {
s[len] = '\0';
printf("mbs: %s\n",s);
for (int i = 0; i < len; i++)
printf("%2d %02X\n",i,(unsigned char)s[i]);
printf("Size of mbs, in bytes: %d\n",len);
return 0;
}
else return -1;
}
int main() {
f(L"Привет"); // 6 symbols
return 0;
}
How to build
#!/bin/sh
NAME=`basename $0 .sh`
CC=/usr/bin/g++-4.9
INCS="-I."
LIBS="-L."
$CC ${NAME}.c -o _${NAME} $INCS $LIBS
Output
$ ./_test
Sizeof wchar_t: 4
0 0000041F
1 00000440
2 00000438
3 00000432
4 00000435
5 00000442
mbs: Привет
0 D0
1 9F
2 D1
3 80
4 D0
5 B8
6 D0
7 B2
8 D0
9 B5
10 D1
11 82
Size of mbs, in bytes: 12
It's quite easy, because CString is just a typedef for CStringT, and you also have access to CStringA and CStringW (you should read the documentation about the differences).
CStringW myString = L"Hello World";
CString myConvertedString = myString;
You could do this, or you could do something cleaner:
std::wcout << L"output: " << output.GetString() << std::endl;
You can use the std::wcsrtombs function.
Here is a C++17 overload set for conversion:
#include <iostream> // not required for the conversion function
// required for conversion
#include <cuchar>
#include <cwchar>
#include <stdexcept>
#include <string>
#include <string_view> // for std::wstring_view overload
std::string to_string(wchar_t const* wcstr){
auto s = std::mbstate_t();
auto const target_char_count = std::wcsrtombs(nullptr, &wcstr, 0, &s);
if(target_char_count == static_cast<std::size_t>(-1)){
throw std::logic_error("Illegal byte sequence");
}
// +1 because std::string adds a null terminator which isn't part of size
auto str = std::string(target_char_count, '\0');
std::wcsrtombs(str.data(), &wcstr, str.size() + 1, &s);
return str;
}
std::string to_string(std::wstring const& wstr){
return to_string(wstr.c_str());
}
std::string to_string(std::wstring_view const& view){
// wstring because wstring_view is not required to be null-terminated!
return to_string(std::wstring(view));
}
int main(){
using namespace std::literals;
std::cout
<< to_string(L"wchar_t const*") << "\n"
<< to_string(L"std::wstring"s) << "\n"
<< to_string(L"std::wstring_view"sv) << "\n";
}
If you use Pre-C++17, you should urgently update your compiler! ;-)
If this is really not possible, here is a C++11 version:
#include <iostream> // not required for the conversion function
// required for conversion
#include <cwchar>
#include <stdexcept>
#include <string>
std::string to_string(wchar_t const* wcstr){
auto s = std::mbstate_t();
auto const target_char_count = std::wcsrtombs(nullptr, &wcstr, 0, &s);
if(target_char_count == static_cast<std::size_t>(-1)){
throw std::logic_error("Illegal byte sequence");
}
// +1 because std::string adds a null terminator which isn't part of size
auto str = std::string(target_char_count, '\0');
std::wcsrtombs(const_cast<char*>(str.data()), &wcstr, str.size() + 1, &s);
return str;
}
std::string to_string(std::wstring const& wstr){
return to_string(wstr.c_str());
}
int main(){
std::cout
<< to_string(L"wchar_t const*") << "\n"
<< to_string(std::wstring(L"std::wstring")) << "\n";
}
You can use sprintf for this purpose, as #l0pan mentions (but I used %ls instead of %ws):
char output[256];
const WCHAR* wc = L"Hello World" ;
sprintf(output, "%ws", wc ); // did not work for me (Windows, C++ Builder)
sprintf(output, "%ls", wc ); // works

c++ convert from LPCTSTR to const char *

I have this problem in MSVC2008 MFC. I´m using unicode. I have a function prototype:
MyFunction(const char *)
and I'm calling it:
MyfunFunction(LPCTSTR wChar).
error:Cannot Convert Parameter 1 From 'LPCTSTR' to 'const char *'
How to resolve it?
Since you're using MFC, you can easily let CString do an automatic conversion from char to TCHAR:
MyFunction(CString(wChar));
This works whether your original string is char or wchar_t based.
Edit: It seems my original answer was opposite of what you asked for. Easily fixed:
MyFunction(CStringA(wChar));
CStringA is a version of CString that specifically contains char characters, not TCHAR. There's also a CStringW which holds wchar_t.
LPCTSTR is a pointer to const TCHAR and TCHAR is WCHAR and WCHAR is most probably wchar_t. Make your function take const wchar_t* if you can, or manually create a const char* buffer, copy the contents, and pass that.
When UNICODE is defined for an MSVC project LPCTSTR is defined as const wchar_t *; simply changing the function signature will not work because whatever code within the function is using the input parameter expects a const char *.
I'd suggest you leave the function signature alone; instead call a conversion function such as WideCharToMultiByte to convert the string before calling your function. If your function is called several times and it is too tedious to add the conversion before every call, create an overload MyFunction(const wchar_t *wChar). This one can then perform the conversion and call the original version with the result.
This may not be totally on topic, but I wrote a couple of generic helper functions for my proposed wmain framework, so perhaps they're useful for someone.
Make sure to call std::setlocale(LC_CTYPE, ""); in your main() before doing any stringy stuff!
#include <string>
#include <vector>
#include <clocale>
#include <cassert>
std::string get_locale_string(const std::wstring & s)
{
const wchar_t * cs = s.c_str();
const size_t wn = wcsrtombs(NULL, &cs, 0, NULL);
if (wn == size_t(-1))
{
std::cout << "Error in wcsrtombs(): " << errno << std::endl;
return "";
}
std::vector<char> buf(wn + 1);
const size_t wn_again = wcsrtombs(&buf[0], &cs, wn + 1, NULL);
if (wn_again == size_t(-1))
{
std::cout << "Error in wcsrtombs(): " << errno << std::endl;
return "";
}
assert(cs == NULL); // successful conversion
return std::string(&buf[0], wn);
}
std::wstring get_wstring(const std::string & s)
{
const char * cs = s.c_str();
const size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);
if (wn == size_t(-1))
{
std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
return L"";
}
std::vector<wchar_t> buf(wn + 1);
const size_t wn_again = mbsrtowcs(&buf[0], &cs, wn + 1, NULL);
if (wn_again == size_t(-1))
{
std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
return L"";
}
assert(cs == NULL); // successful conversion
return std::wstring(&buf[0], wn);
}
You could provide "dummy" overloads:
inline std::string get_locale_string(const std::string & s) { return s; }
inline std::wstring get_wstring(const std::wstring & s) { return s; }
Now, if you have an LPCTSTR x, you can always call get_locale_string(x).c_str() to get a char-string.
If you're curious, here's the rest of the framework:
#include <vector>
std::vector<std::wstring> parse_args_from_char_to_wchar(int argc, char const * const argv[])
{
assert(argc > 0);
std::vector<std::wstring> args;
args.reserve(argc);
for (int i = 0; i < argc; ++i)
{
const std::wstring arg = get_wstring(argv[i]);
if (!arg.empty()) args.push_back(std::move(arg));
}
return args;
}
Now the main() -- your new entry point is always int wmain(const std::vector<std::wstring> args):
#ifdef WIN32
#include <windows.h>
extern "C" int main()
{
std::setlocale(LC_CTYPE, "");
int argc;
wchar_t * const * const argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
return wmain(std::vector<std::wstring>(argv, argv + argc));
}
#else // WIN32
extern "C" int main(int argc, char *argv[])
{
LOCALE = std::setlocale(LC_CTYPE, "");
if (LOCALE == NULL)
{
LOCALE = std::setlocale(LC_CTYPE, "en_US.utf8");
}
if (LOCALE == NULL)
{
std::cout << "Failed to set any reasonable locale; not parsing command line arguments." << std::endl;
return wmain(std::vector<std::wstring>());
}
std::cout << "Locale set to " << LOCALE << ". Your character type has "
<< 8 * sizeof(std::wstring::value_type) << " bits." << std::endl;
return wmain(parse_args_from_char_to_wchar(argc, argv));
}
#endif
In this example I convert a LPCTSTR to a const char pointer and a char pointer. For this conversion you need to include windows.h and atlstr.h, I hope to help you.
// Required inclusions
#include <windows.h>
#include <atlstr.h>
// Code
LPCTSTR fileName = L"test.txt";
CStringA stringA(fileName);
const char* constCharP = stringA;
char* charP = const_cast<char*>(constCharP);