Converting TCHAR to string in C++ - c++

I'm trying to convert a TCHAR to a string as in:
std::string mypath;
TCHAR path[MAX_PATH];
GetModuleFileName( NULL, path, MAX_PATH );
I need to set mypath to that of path. I did a simple loop and concatenated path[index] to mypath and this works but I don't like this way.
I'm new to C++ but have done plenty of C#. I've seen examples of the GetModuleFileName that passes in a "char" but it doesn't like it. It needs the TCHAR or a LPWSTR.

TCHAR is a macro defined as a char or wchar depending on what you have your character set defined to. The default after 2008 is have the character set to unicode. this code works if you change your character set.
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR* bob ="hi";
string s = bob;
}
Right click on the project settings and chage the folowing
if You want to use TCHAR as a Unicode character set use wstring

When I really need to do it I use the following:
TCHAR infoBuf[32767];
GetWindowsDirectory(infoBuf, 32767);
And then I convert it to a wstring which can be converted to a standard std::string:
wstring test(&infoBuf[0]); //convert to wstring
string test2(test.begin(), test.end()); //and convert to string.

If you want the path in chars, you should call GetModuleFilenameA. That function takes LPSTR instead of LPTSTR.
Note that almost all Win32 functions that take or return strings have two version, one ending in A (ANSI?) and the other ending in W (wide).

You can also convert from _TCHAR* to char* using wcstombs or wcstombs_s function
http://msdn.microsoft.com/en-us/library/5d7tc9zw%28v=vs.80%29.aspx

Hi this is a late answer but I have an idea.
{wstring test = User;
std::wcout << test << std::endl;
string test2(test.begin(), test.end());
std::cout << test2 << std::endl;}
User is in this example the username as a TCHAR.
Now I can use the name as a string or wstring.
This is the easiest way to convert the TCHAR to a string.

Related

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

Converting string to wchar_t (wide character) C++ [duplicate]

Is there any method?
My computer is AMD64.
::std::string str;
BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
When I used:
loadU(&str);
the VS2005 compiler says:
Error 7 error C2664:: cannot convert parameter 1 from 'std::string *__w64 ' to 'const wchar_t *'
How can I do it?
First convert it to std::wstring:
std::wstring widestr = std::wstring(str.begin(), str.end());
Then get the C string:
const wchar_t* widecstr = widestr.c_str();
This only works for ASCII strings, but it will not work if the underlying string is UTF-8 encoded. Using a conversion routine like MultiByteToWideChar() ensures that this scenario is handled properly.
If you have a std::wstring object, you can call c_str() on it to get a wchar_t*:
std::wstring name( L"Steve Nash" );
const wchar_t* szName = name.c_str();
Since you are operating on a narrow string, however, you would first need to widen it. There are various options here; one is to use Windows' built-in MultiByteToWideChar routine. That will give you an LPWSTR, which is equivalent to wchar_t*.
You can use the ATL text conversion macros to convert a narrow (char) string to a wide (wchar_t) one. For example, to convert a std::string:
#include <atlconv.h>
...
std::string str = "Hello, world!";
CA2W pszWide(str.c_str());
loadU(pszWide);
You can also specify a code page, so if your std::string contains UTF-8 chars you can use:
CA2W pszWide(str.c_str(), CP_UTF8);
Very useful but Windows only.
If you are on Linux/Unix have a look at mbstowcs() and wcstombs() defined in GNU C (from ISO C 90).
mbs stand for "Multi Bytes String" and is basically the usual zero terminated C string.
wcs stand for Wide Char String and is an array of wchar_t.
For more background details on wide chars have a look at glibc documentation here.
Need to pass a wchar_t string to a function and first be able to create the string from a literal string concantenated with an integer variable.
The original string looks like this, where 4 is the physical drive number, but I want that to be changeable to match whatever drive number I want to pass to the function
auto TargetDrive = L"\\\\.\\PhysicalDrive4";
The following works
int a = 4;
std::string stddrivestring = "\\\\.\\PhysicalDrive" + to_string(a);
std::wstring widedrivestring = std::wstring(stddrivestring.begin(), stddrivestring.end());
const wchar_t* TargetDrive = widedrivestring.c_str();

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));

How can I substring a TCHAR

I have a TCHAR and value as below:
TCHAR szDestPathRoot[MAX_PATH]="String This";
Now I want the 1st three character from TCHAR , like below:
szDestPathRoot.substring(0,2);
How can I do this.
TCHAR[] is a simple null-terminated array (rather than a C++ class). As a result, there's no ".substring()" method.
TCHAR[] (by definition) can either be a wide character string (Unicode) or a simple char string (ASCII). This means there are wcs and str equivalents for each string function (wcslen() vs strlen(), etc etc). And an agnostic, compile-time TCHAR equivalent that can be either/or.
The TCHAR equivalent of strncpy() is tcsncpy().
Final caveat: to declare a TCHARliteral, it's best to use the _T() macro, as shown in the following snippet:
TCHAR szDestPathRoot[MAX_PATH] = _T("String This");
TCHAR szStrNew[4];
_tcsncpy (str_new, szTestPathRoot, 3);
You may find these links to be of interest:
http://msdn.microsoft.com/en-us/library/xdsywd25%28VS.71%29.aspx
http://www.i18nguy.com/unicode/c-unicode.html
http://msdn.microsoft.com/en-us/library/5dae5d43(VS.80).aspx (for using the secure _tcsncpy_s)
TCHAR szDestPathRoot[MAX_PATH]="String This";
TCHAR substringValue[4] = {0};
memcpy(substringValue, szDestPathRoot, sizeof(TCHAR) * 3);
As you have tagged your question with "C++" you can use the string classes of the std library:
std::wstring strDestPathRoot( _T("String This") );
strDestPathRoot.substr( 0, 2 );
This is somewhat ugly but if you know for sure that:
The string holds at least 4 TCHAR (3 chars plus the terminating NUL)
The content of the string can be modified (which is the case in your example).
You don't have to keep the original string intact
You could just put a terminating NUL at the 4th position to make the string 3 char long.
szDestPathRoot[3] = _T('\0');
Note that this operation is destructive to the original string
You should really be using a string class in C++ code though.

I want to convert std::string into a const wchar_t *

Is there any method?
My computer is AMD64.
::std::string str;
BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
When I used:
loadU(&str);
the VS2005 compiler says:
Error 7 error C2664:: cannot convert parameter 1 from 'std::string *__w64 ' to 'const wchar_t *'
How can I do it?
First convert it to std::wstring:
std::wstring widestr = std::wstring(str.begin(), str.end());
Then get the C string:
const wchar_t* widecstr = widestr.c_str();
This only works for ASCII strings, but it will not work if the underlying string is UTF-8 encoded. Using a conversion routine like MultiByteToWideChar() ensures that this scenario is handled properly.
If you have a std::wstring object, you can call c_str() on it to get a wchar_t*:
std::wstring name( L"Steve Nash" );
const wchar_t* szName = name.c_str();
Since you are operating on a narrow string, however, you would first need to widen it. There are various options here; one is to use Windows' built-in MultiByteToWideChar routine. That will give you an LPWSTR, which is equivalent to wchar_t*.
You can use the ATL text conversion macros to convert a narrow (char) string to a wide (wchar_t) one. For example, to convert a std::string:
#include <atlconv.h>
...
std::string str = "Hello, world!";
CA2W pszWide(str.c_str());
loadU(pszWide);
You can also specify a code page, so if your std::string contains UTF-8 chars you can use:
CA2W pszWide(str.c_str(), CP_UTF8);
Very useful but Windows only.
If you are on Linux/Unix have a look at mbstowcs() and wcstombs() defined in GNU C (from ISO C 90).
mbs stand for "Multi Bytes String" and is basically the usual zero terminated C string.
wcs stand for Wide Char String and is an array of wchar_t.
For more background details on wide chars have a look at glibc documentation here.
Need to pass a wchar_t string to a function and first be able to create the string from a literal string concantenated with an integer variable.
The original string looks like this, where 4 is the physical drive number, but I want that to be changeable to match whatever drive number I want to pass to the function
auto TargetDrive = L"\\\\.\\PhysicalDrive4";
The following works
int a = 4;
std::string stddrivestring = "\\\\.\\PhysicalDrive" + to_string(a);
std::wstring widedrivestring = std::wstring(stddrivestring.begin(), stddrivestring.end());
const wchar_t* TargetDrive = widedrivestring.c_str();