Как мне конвертировать из LPCTSTR в std :: string? - PullRequest
9 голосов
/ 01 апреля 2011

У меня есть LPCTSTR и я хочу вызвать функцию, которая принимает параметр std::string.

Какое преобразование мне нужно сделать?

Ответы [ 7 ]

16 голосов
/ 01 апреля 2011

Кончик айсберга

LPCTSTR может быть либо однобайтовой, либо многобайтовой строкой (зависит от того, определена ли константа UNICODE во время компиляции или нет), пока пользователи std::string(включая вашу функцию) обычно используют ее для хранения однобайтовой строки.

Вам потребуются два преобразования: одно для LPCSTR (не UNICODE build) и одно для LPCWSTR (UNICODE сборка).Первый прост:

std::string convert(LPCSTR str) {
    return std::string(str);
}

Второй требует, чтобы его входной параметр был сначала преобразован в другую кодировку с помощью WideCharToMultiByte.Не беспокойтесь по имени, результат может быть однобайтовой символьной строкой;это зависит от параметра CodePage.Вам придется использовать кодовую страницу для однобайтовой кодировки, например CP_ACP.

Обновление: WideCharToMultiByte пример

Имейте в виду, чтоточное преобразование в однобайтовую кодировку технически невозможно, если входная строка содержит символы, которых нет в кодовой странице целевой кодировки. Поскольку вы упоминаете, что это будет для функций файловой системы, если путь к файлу содержит такие символы, преобразование будетне будет на 100% точным, и последующие вызовы функций не будут выполнены.

std::string MBFromW(LPCWSTR pwsz, UINT cp) {
    int cch = WideCharToMultiByte(cp, 0, pwsz, -1, 0, 0, NULL, NULL);

    char* psz = new char[cch];

    WideCharToMultiByte(cp, 0, pwsz, -1, psz, cch, NULL, NULL);

    std::string st(psz);
    delete[] psz;

   return st;
}

Caveat emptor: Приведенный выше пример взят из некоторого кода, который я лежал без дела, и не соответствует качеству производственного уровня.Единственный очевидный недостаток заключается в том, что он не исключает исключений.Это также может убить всех милых пурпурных единорогов.Используйте его только как пример .

Полный ад кодирования

Голая правда в том, что std::string можно использовать для многобайтовых кодировок (таких как UTF8) просто отлично- вы даже можете использовать его для хранения строк с широким символом, так как это просто двоично-безопасный массив байтов в основе.

Проблема в том, что функции STL, которые применяются к std::string, ожидаютего содержимое должно быть в однобайтовой кодировке , и они не будут давать правильных результатов, если это не так.

По расширению мы не знаем, какую функцию выполняет ваша функцияпараметр std::string ожидает - он может ожидать строку, закодированную в UTF-8.Но «по соглашению», я предполагаю, что он также хочет однобайтовую строку в кодировке.

10 голосов
/ 01 апреля 2011

в одну строку:

std::string s = CT2A( lpctstr );
2 голосов
/ 01 апреля 2011

Из вашего комментария: «Функция, которую я вызываю, примет std :: string и будет использовать его в качестве имени файла при вызове std :: fstream :: open ()» *

.Функция действительно должна принимать tstring (определяется как typedef std::basic_string<TCHAR> tstring).Есть много файлов Windows, чье имя не может быть представлено без Unicode.Например, все файлы в \User\<myusername\My Documents\, если <myUserName> содержат не-ANSI символ (и вы действительно не хотите говорить своему пользователю, что у него плохое имя!)

Но как только выизменилось на tstring, это просто работает.Вы все еще получаете тот же std::fstream объект.

2 голосов
/ 01 апреля 2011

Прагматичный подход:

     LPCTSTR input;

     std::string s;

#ifdef UNICODE
     std::wstring w;
     w = input;
     s = std::string(w.begin(), w.end()); // magic here
#else
     s = input;
#endif

Смотрите другие ответы для отличных фонов!

1 голос
/ 01 апреля 2011

Этот фрагмент кода должен выполнять преобразование из LPWSTR в char * / std :: string

LPWSTR input = L"whatever";
int cSize = WideCharToMultiByte (CP_ACP, 0, input, wcslen(input), NULL, 0, NULL, NULL);
std::string output(static_cast<size_t>(cSize), '\0');
WideCharToMultiByte (CP_ACP, 0, input, wcslen(input),
                       reinterpret_cast<char*>(&output[0]), cSize, NULL, NULL);

и этот фрагмент должен выполнять преобразование однобайтовой std :: string в LPWSTR

std::string input = "whatever";
//computing wchar size:
int wSize = MultiByteToWideChar (CP_ACP, 0, (LPCSTR) input.c_str (), -1, 0, 0);

//allocating memory for wchar:
LPWSTR output = new WCHAR[wSize];

//conversion from string to LPWSTR:
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED , (LPCSTR) input.c_str (), -1, output, wSize);
1 голос
/ 01 апреля 2011

LPCTSTR - это определение Windows, которое читается как «длинный указатель на константную строку символьного типа». Я на самом деле не уверен, что означает T, но это связано с набором символов проекта.

Если ваш проект использует набор символов Unicode, этот тип является const wchar_t*, который использует два байта на символ. Если в вашем проекте используется многобайтовый набор символов, этот тип является const char*, который использует один байт на символ.

Скорее всего, набор символов вашего проекта - Unicode, поэтому LPCTSTR - это const wchar_t*. Поскольку std::string использует один байт на символ, он не может содержать эти два байта на символьную строку. std::wstring может, однако.

Если вам нужно преобразовать const wchar_t* в const char*, чтобы разрешить его присвоение строке, вы можете использовать такие функции, как wcstombs, чтобы сделать это. Если вы включаете ATL (в частности, atlconv.h) в свой проект, он предоставляет макросы для более легкой работы:

USES_CONVERSION;
const wchar_t* = L"Wide string";
std::string str = W2A(value);
0 голосов
/ 01 апреля 2011

Я не знаю, может ли это решение помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...