Конвертировать lptstr в char*
Кто-нибудь знает, как конвертировать тип LPTSTR
в char *
в С ++?
8 ответов
Зависит, если это Unicode или нет, он появляется. LPTSTR - это char*, если не Unicode, или w_char*, если это так.
Обсудить лучше здесь (принятый ответ стоит прочитать)
Вот много способов сделать это. Mtc или ATl CString, ATL макросы или Win32 API.
LPTSTR szString = _T("Testing");
char* pBuffer;
Вы можете использовать макросы ATL для преобразования:
USES_CONVERSION;
pBuffer = T2A(szString);
CString:
CStringA cstrText(szString);
или Win32 API WideCharToMultiByte
если UNICODE
определено.
Если для параметра "Настройка символов" вашего компилятора установлено значение "Набор символов Юникода", то LPTSTR будет интерпретироваться как wchar_t *. В этом случае требуется преобразование Unicode в многобайтовые символы.
(В Visual Studio параметр находится в разделе "Свойства проекта" \ "Свойства конфигурации"> "Общие" \ "Набор символов")
Пример кода ниже должен дать представление:
#include <windows.h>
/* string consisting of several Asian characters */
LPTSTR wcsString = L"\u9580\u961c\u9640\u963f\u963b\u9644";
//LPTSTR wcsString = L"OnlyAsciiCharacters";
char* encode(const wchar_t* wstr, unsigned int codePage)
{
int sizeNeeded = WideCharToMultiByte(codePage, 0, wstr, -1, NULL, 0, NULL, NULL);
char* encodedStr = new char[sizeNeeded];
WideCharToMultiByte(codePage, 0, wstr, -1, encodedStr, sizeNeeded, NULL, NULL);
return encodedStr;
}
wchar_t* decode(const char* encodedStr, unsigned int codePage)
{
int sizeNeeded = MultiByteToWideChar(codePage, 0, encodedStr, -1, NULL, 0);
wchar_t* decodedStr = new wchar_t[sizeNeeded ];
MultiByteToWideChar(codePage, 0, encodedStr, -1, decodedStr, sizeNeeded );
return decodedStr;
}
int main(int argc, char* argv[])
{
char* str = encode(wcsString, CP_UTF8); //UTF-8 encoding
wchar_t* wstr = decode(str, CP_UTF8);
//If the wcsString is UTF-8 encodable, then this comparison will result to true.
//(As i remember some of the Chinese dialects cannot be UTF-8 encoded
bool ok = memcmp(wstr, wcsString, sizeof(wchar_t) * wcslen(wcsString)) == 0;
delete str;
delete wstr;
str = encode(wcsString, 20127); //US-ASCII (7-bit) encoding
wstr = decode(str, 20127);
//If there were non-ascii characters existing on wcsString,
//we cannot return back, since some of the data is lost
ok = memcmp(wstr, wcsString, sizeof(wchar_t) * wcslen(wcsString)) == 0;
delete str;
delete wstr;
}
С другой стороны, если для параметра Character Character вашего компилятора установлено значение Multibyte, то LPTSTR будет интерпретироваться как char *.
В таком случае:
LPTSTR x = "test";
char* y;
y = x;
Также см:
Еще одно обсуждение о преобразовании wchar_t: как правильно использовать WideCharToMultiByte
Статья MSDN: http://msdn.microsoft.com/en-us/library/dd374130(v=vs.85).aspx
Допустимые идентификаторы кодовой страницы: http://msdn.microsoft.com/en-us/library/dd317756(v=vs.85).aspx
char * pCopy = NULL;
if (sizeof(TCHAR) == sizeof(char))
{
size_t size = strlen(pOriginal);
pCopy = new char[size + 1];
strcpy(pCopy, pOriginal);
}
else
{
size_t size = wcstombs(NULL, pOriginal, 0);
pCopy = new char[size + 1];
wcstombs(pCopy, pOriginal, size + 1);
}
Хорошо, давайте скажем, что вы должны использовать Unicode. И вы используете некоторые функции, такие как LookupAccountSid, которые требуются вашей программе для работы - но они возвращают LPTSTR для важной информации, которую вы ДОЛЖНЫ обрабатывать в виде строки (по какой-то причине - это программирование, такие вещи случаются)
Теперь, если вы используете многобайтовый код - это не будет проблемой. Но есть способ решить это. Это мой метод и по общему признанию неряшливый. Но, тем не менее, вы должны увидеть, как это работает.
const std::wstring &wstring = AcctName; // AcctName being my LPTSTR string
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstring[0], (int)wstring.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, & wstring[0], (int)wstring[0], &strTo[0], size_needed, NULL, NULL);
char* charUserName = new char[strTo.size() + 1];
// Set charUserName via copying
std::copy(strTo.begin(), strTo.end(), charUserName);
charUserName[strTo.size()] = '\0';
SetUPI(charUserName); // charUserName being my converted char * -
// You don't need this last part - but this is an example of passing to method
// that takes a string
Любые вопросы просто задавайте. Я понимаю, что это старый пост, но мне нравится постить людей в будущем, которые смотрят. (люди, как я)
Я надеюсь, что это кому-то поможет, потому что мне понадобилось время, чтобы понять, как это сделать.
Прежде всего, LPTSTR
имеет тип указателя, и это в основном эквивалентно TCHAR*
(при условии, что <tchar.h>
Включено). Обратите внимание, что размер TCHAR
варьируется в зависимости от типа кодировки символов. т.е. если определен юникод, TCHAR
равно wchar_t
в противном случае это char
,
Естественно, если вы конвертируете широкий символ в обычный char
, вы можете только сохранить LSB и можете потерять некоторые данные. Это было как-то раздражает меня. поэтому я написал следующий код. Его главное преимущество - преобразование без потери данных.
Кстати, если вы в порядке с потерей данных, то wcstombs
делает работу
#include <cstring>
#include <algorithm>
#include <tchar.h>
void lptstr2str(LPTSTR tch, char* &pch) // or (TCHAR* tch, char* &pch)
{
#ifndef UNICODE
std::memcpy(pch, tch, strlen(tch) + 1);
#else
size_t n =
sizeof(TCHAR) / sizeof(char)* wcsnlen(tch, std::string::npos);
pch = new char[n + 1];
std::memcpy(pch, tch, n + 1);
int len = n - std::count(pch, pch + n, NULL);
std::remove(pch, pch + n, NULL);
pch[len] = NULL;
#endif
}
Я пропустил несколько простых примеров, так что вот оно:
(для меня char* идентичен char[])
LPCTSTR myLPCTSTR = getLPCTSTR();
TCHAR myT[500];
wcscpy(myT,myLPCTSTR);
char myC[500];
sprintf(myC, "%S", myT);
Без сомнения, многие (например, мы, Unix, люди) с ужасом отшатнутся от безумного шутника Microserf doublespeak - "если ваш компилятор находится в режиме Unicode, используйте LPWSTR или вставьте перед ним"T_", но только если он статический строка, которая совпадает с буквой "L", или используйте T2A(), если используется ATL, но теперь она устарела, или используйте VARIANT, но не при связывании с COM/OLE"...).
"If (sizeof(TCHAR) == sizeof(char))", приведенный на этой странице, является логической попыткой найти хорошее решение, но оно не будет компилироваться - либо if-true не будет компилироваться, либо if-false не будет 'компилировать, в зависимости от ваших флагов компилятора (Aaargh!). Для переносимого решения с возможностью записи и забывания вам нужно прибегнуть к макросу UNICODE [со слишком общим именем]. Я предлагаю эту адаптацию предыдущего кода:
string mfc_to_zstring (CString &sref)
{
char nojoy[65536];
char *ptr, *psin = NULL;
string sot;
LPCTSTR p = sref;
#if UNICODE
if (sizeof(TCHAR) != sizeof(char))
{
size_t n = wcstombs(NULL, p, 0);
if (n > 65530)
{
psin = new char[n + 1];
wcstombs(psin, p, n + 1);
ptr = psin;
}
else
{
wcstombs(nojoy, p, n + 1);
ptr = nojoy;
}
sot = ptr;
if (psin != NULL)
delete psin;
}
else
{ std::cerr << "Aaargh! Microsoft horror.\n"; exit(1); }
#else
if (sizeof(TCHAR) == sizeof(char))
{
const char *ptr = p;
sot = ptr;
}
else
{ std::cerr << "Aaargh! You should never see this line\n"; exit(1); }
#endif
return sot;
}