How to convert std::wstring to a TCHAR*? - c++

How to convert a std::wstring to a TCHAR*? std::wstring.c_str() does not work since it returns a wchar_t*.
How do I get from wchar_t* to TCHAR*, or from std::wstring to TCHAR*?

use this :
wstring str1(L"Hello world");
TCHAR * v1 = (wchar_t *)str1.c_str();

#include <atlconv.h>
TCHAR *dst = W2T(src.c_str());
Will do the right thing in ANSI or Unicode builds.

TCHAR* is defined to be wchar_t* if UNICODE is defined, otherwise it's char*. So your code might look something like this:
wchar_t* src;
TCHAR* result;
#ifdef UNICODE
result = src;
#else
//I think W2A is defined in atlbase.h, and it returns a stack-allocated var.
//If that's not OK, look at the documenation for wcstombs.
result = W2A(src);
#endif

in general this is not possible since wchar_t may not be the same size as TCHAR.
several solutions are already listed for converting between character sets. these can work if the character sets overlap for the range being converted.
I prefer to sidestep the issue entirely wherever possible and use a standard string that is defined on the TCHAR character set as follows:
typedef std::basic_string<TCHAR> tstring;
using this you now have a standard library compatible string that is also compatible with the windows TCHAR macro.

You can use:
wstring ws = L"Testing123";
string s(ws.begin(), ws.end());
// s.c_str() is what you're after

Assuming that you are operating on Windows.
If you are in Unicode build configuration, then TCHAR and wchar_t are the same thing. You might need a cast depending on whether you have /Z set for wchar_t is a type versus wchar_t is a typedef.
If you are in a multibyte build configuration, you need MultiByteToWideChar (and vica versa).

Related

Am I converting properly from "const char *" to "TCHAR*"?

I'm trying to pass a process name as a TCHAR to the following void:
void GetBaseAddressByName(DWORD pID, TCHAR *pN)
By doing it like this:
GetBaseAddressByName(aProcs[i], (TCHAR*)"Process.exe");
So my question is: is what I am doing correct? Because I have tried both TEXT("Process.exe") and _T("Process.exe") with my project's Character Set both on Multi-Bite and Unicode and it just tells me that
argument of type "const char*" is incompatible with parameter of type "TCHAR*"
The short answer is no. TCHAR maps to either char or wchar_t depending on your project's Unicode/Multi-byte setting. So, in general, a cast like that is either unnecessary or incorrect. The correct way, as you said, is to use either the TEXT or _T macro. The reason you're getting an error is that you're trying to pass a const character string to a function that expects a mutable character string. The safeset way to get around the error is to copy your constant string into a local TCHAR buffer and then pass that to GetBaseAddressByName.
It is better to have a TCHAR array first, then copy into it.
#include "atlstr.h"
char const * procName = "processName.exe";
TCHAR szName [128];
_tcscpy(szName, A2T(procName));
GetBaseAddressByName(aProcs[i], szName);
As suggested by #Remy Lebeau in the comments, procName can be defined as TCHAR const * procName = TEXT("processName.exe");.
(TCHAR*)"Process.exe" is not a valid type-cast. It will "work" when the project charset is set to ANSI/MBCS, but it will produce garbage if the charset is set to Unicode.
Using TEXT("Process.exe") is the correct way to make a string literal use TCHAR characters.
GetBaseAddressByName(aProcs[i], TEXT("Process.exe"));
However, you need to change your pN parameter to const TCHAR * (or LPCTSTR) instead:
void GetBaseAddressByName(DWORD pID, const TCHAR *pN);
void GetBaseAddressByName(DWORD pID, LPCTSTR pN);
A string literal is const data, and you cannot pass a pointer-to-const-data where a pointer-to-non-const-data is expected (without casting the const away with const_cast). That is why you were still getting errors when trying to use the TEXT()/_T() macros.
You need a L, like L"Process.exe". Unicode strings are specified with L"".
That said, there is no reason to use TCHAR. Use unicode all the time, if doing Windows work only.

C++ Combine 2 Tchar

I'm trying to combine 2 tchar.
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
TCHAR* appdatapath ="C:\\Users\\"+username+"\\AppData";
But I get error error at appdatapath line. How can I combine 2 tchar? Thanks
Have a look at strcat and wcscat. You can't add char pointer with char array.
If you are on a windows machine, you can use _tcscat which will redirect to the right function to use depending on _UNICODE and _MBCS defines.
Might want to use the safe versions as well by appending _s to the function name.
As pointed in the comments, you can also use snprintf like so:
const size_t concatenated_size = 256;
char concatenated[concatenated_size];
snprintf(concatenated, concatenated_size, "C:\\Users\\%s\\AppData", username);
Since you have string literals before and after the runtime string, it is probably a better approach.
To answer the question in the title: you concatenate two TCHAR strings using the _tcscat function.
However, there are other issues in your code related to this: GetUserName expects a LPTSTR, i.e. a pointer to a buffer TCHAR characters. Furthermore, there's another TCHAR usage in
TCHAR* appdatapath ="C:\\Users\\"+username+"\\AppData";
The issue with this is that the type to which TCHAR expands changes depending on whether _UNICODE is defined. In particular, if you set it, TCHAR (eventually) expands to wchar and hence GetUserName expects a wchar_t* but you pass a char*. Another issue is that you cannot concatenate C arrays using the + operator.
I suggest to stop worrying about TCHAR in the first place and always just compile with _UNICODE defined - and use wchar throughout your code. Also, since you're using C++, just use std::wstring:
wchar username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserNameW(username, &username_len);
std::wstring appdatapath = L"C:\\Users\\";
appdatapath += username;
appdatapath += L"\\AppData";
Last but not least: your entire code can probably be replaced with a call to the SHGetSpecialFolderPath function - pass CSIDL_APPDATA to it to get the "AppData" path.
#include <tchar.h>
const size_t stringSize= 20;
TCHAR value[stringSize] = { 0 };
_tcscat_s(value, stringSize, TEXT("appendMe"));
MSDN: _tcscat_s

How do I get a substring of a LPCTSTR?

How do I get a substring of a LPCTSTR?
LPCSTR is just fancy name for char *, it doesn't have methods.
If you use std::string you could use the find and substr methods to extract the first and second part of the string.
Edit: As noted by Christoph, the type of TCHAR differs depending on if UNICODE is defined or not. If UNICODE is defined (check with #ifdef UNICODE, do a Google search on preprocessor to learn more about things like #define and #ifdef) you need to use std::wstring instead of std::string.
Edit 2: An easier solution than checking if you need to use std::string or std::wstring all the time, is to follow the advice of Konrad Rudolph and create a new typedef similar to std::string and std::wstring. Something like this:
typedef std::basic_string<TCHAR> tstring;
And then use that string type internally.
As an alternative, as LPCTSTR is a TCHAR*, then you can "substring" quite easily using _tcschr...depending on what your use case is.
TCHAR* exepath = getTheFullPathToThisProcess();
TCHAR* extension = _tcschr(exepath,'.'); //extension is a valid c-string containing '.exe'
//where is the last "\"?
TCHAR* slash = _tcsrchr(exepath,'\\');
*slash = 0;//exepath is now shortened to the path pre the filename of this process.
Might be easier for you if you are comfortable in c-string land.
EDIT : Forgot that LPCTSTR is a const! You would need to do a _stprintf(copy,"%s",exepath) in that case... so may not be worth it. But will leave this here as an alternative anyway.
Make use of the fact that string is actually a template itself.
typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;
Then use
tstring str( _T("Hello world" ) );
tstring sub = str.substr(6, 3 );
Unfortunately there is no tcout unless you #define it somewhere:
#ifdef _UNICODE
#define tcout wcout
#else
#define tcout cout
#endif
Now I can print my string
tcout << sub << static_cast<TCHAR>('\n');
Note that in general code like this gets very messy, and will often lead to enormous bloat.
use _tcsstr() to find a substring in a LPCTSTR
an LPCSTR is either a pointer to an ANSI string ('char') or a unicode string ('wchar')
you don't need to do any conversion to stl:string etc.
just call the appropriate flavor of strstr() which is what _tcsstr() does
This is to convert into std::string -
LPCTSTR astring ="A random string";
std::string temp = astring;
Then use basic_string::find to get position of substrings separator ("-" was before your editing) and basic_string::erase to erase string after this position.
Consult with MSDN for samples: basic_string Members
LPCTSTR is Microsoft specific type and stands for Long Pointer to Constant T (Unicode) STRing. In other words, it is const TCHAR* where TCHAR is generic character (defined in WinNT.h):
#ifdef UNICODE
typedef WCHAR TCHAR
#else
typedef char TCHAR
#endif
where WCHAR is:
typedef wchar_t WCHAR
So, LPCTSTR is pointer and you cannot do much with string it represents unless you want to play with pointers, count bytes and search for zero-termination character. It is better to use some of string abstractions (classes), like MFC or ATL CString, or STL string - std::string which is better as you don't depend on MFC/ATL but just standard C++ library. One catch is that STL has string based on narrow- and wide- characters: std::string and std::wstring. As your code is written for UNICODE, you can do something like this:
#include <string>
#ifdef UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif
int main()
{
// ANSI "te-st" or L"te-st" if UNICODE
TCHAR pszStr[] = TEXT("te-st");
// const char* or const wchar_t* if UNICODE
LPCTSTR pStr = pszStr;
tstring str(pStr);
tstring sub1 = str.substr(str.find(TEXT("-")) + 1);
tstring sub2 = str.substr(0, str.length() - sub1.length() - 1);
// sub1 contains "st" (L"st" if UNICODE) and sub2 contains "te" (L"te" if UNICODE)
return 0;
}
You must copy the string, you can't have a pointer to existing buffer, with null terminator where you need it, without changing the buffer, which you can't because it's const (the C in LPCTSTR).
If you're using MFC, you could also construct a CString and use that to get the second half.
LPCTSTR both = "first-second";
CString bothStr(both);
CString second_half = bothStr.Right(bothStr.GetLength() -
(bothStr.Find("-") + 1));

Making TCHAR* compatible with char*

So a quick question how do I make TCHAR* (or wchar_t as its a macro) work with char*?
I am using the unicode character set.
The code that is the problem is:
TCHAR* D3DDevTypeToString(D3DDEVTYPE devType) {
switch (devType) {
case D3DDEVTYPE_HAL:
return TEXT("D3DDEVTYPE_HAL");
case D3DDEVTYPE_SW:
return TEXT("D3DDEVTYPE_SW");
case D3DDEVTYPE_REF:
return TEXT("D3DDEVTYPE_REF");
default:
return TEXT("Unknown devType");
}
}
The obvious solution is to change TCHAR* to char* but I would like to keep it as TCHAR* if possible.
Thanks.
And yes I am using the unicode character set.
Then you cannot make TCHAR compatible with char. Because if you're using UCS, then TCHAR is wchar_t. The type char is not related in any way to wchar_t. You could do some work to convert the string (using e.g. WideCharToMultiByte), but then you'd lose Unicode support.
TCHAR could be wchar_t or char, depeding upon whether the macro UNICODE is defined or not.
If the macro UNICODE is defined, then TCHAR means wchar_t. In this case, you cannot use TCHAR in place of, or with, char. It's dangerous!
If it's not defined, then TCHAR means char. In this case, you can use TCHAR in place of, or with, char. After all, they're same now.
Write a converter from UTF-16 to UTF-8 (or use the win32 API function if that's what it does). Make it generic so it can work on char*, wchar_t*, std::string, and std::wstring. Write a templated function string_cast and let the second parameter be figured out by the compiler. Override string_cast for the different combinations you will be using. Convert between TCHAR* to std::string with string_cast and then it doesn't matter how TCHAR is defined (assuming you overrode for both char and wchar_t.

How to convert tchar pointer to char pointer

I want to conver a tchar* to char * is this possible . if yes how to do it. I use unicode setting
A TCHAR is either a plain char or a wchar_t depending on your project's settings. If it's the latter, you would need to use WideCharToMultiByte with appropriate code page parameter.
You can't convert the pointer, you need to allocate a new string that is "char" instead of "wchar_t"
the most elegant way to do this is with the ATL conversion macros because it will hide all the allocation and called to the functions mentioned in the other comments
example
#include <atlbase.h>
#include <atlconv.h>
void YourFunction()
{
TCHAR wszHelloTchar = _T("Hello!\n");
USES_CONVERSION; // a macro required once before using T2A() and other ATL macros
// printf require a char*
// T2A converts (if necessary) the TCHAR string to char
printf( T2A( wszHelloTchar ) );
}
I find wcstombs works great for doing this sort of thing,