std:: строка в LPCTSTR

новая версия типичного вопроса о том, как конвертировать из std::string to LPCTSTR.

чтение из разных сообщений SO я узнал, что я должен сделать это:

CreateDirectory(path.c_str(),NULL);

и все же компилятор дает ошибку, потому что cannot convert from const char * to LPCTSTR.

пробовал:

CreateDirectory((LPCTSTR)path.c_str(),NULL);

нет ошибки!

еще каталог созданный (в правильном месте) называется:

D:something㩄ぜ弲久䅓余屓䱆彄湡敤屲䵉ⴱ㠶ⴰⵃㅇ㉜洰就䥄牃獥汵獴촀췍췍췍췍췍췍췍﷽ﺫﻮﻮ

это не совсем то, что я хотел, как вы можете догадка...

так что я упускаю? Это связано с UNICODE / ANSI? Как я могу это решить?

7 ответов


ваша проблема здесь в том, что LPCTSTR разрешить wchar_t* или char* на основе того, поддерживает ли ваша сборка unicode (набор флагов unicode или нет).

для явного вызова char* версия, вызов CreateDirectoryA().


как этот вопрос появляется, когда вы пытаетесь найти"(std::) string to LPCTSTR"

вот способ, как конвертировать & pass std::string as LPCTSTR используя wstring

string path_str = "Yay!"; //your string containing path
wstring path_wstr( path_str.begin(), path_str.end() );
//then this should work:
CreateDirectory(path_wstr.c_str(),NULL);

важное примечание by Адриан Маккарти:

это нормально, если исходная строка ASCII или если это ANSI и текущая кодовая страница-Windows-1252 (что очень похоже на Latin-1). Если источник является UTF-8 или другая кодовая страница, то это просто скрывает проблема.


попробуйте посмотреть на эту страницу:что является файле TCHAR-тип данных wchar-LPSTR-LPWSTR-LPCTSTR-и т. д.. Если вы используете MSVC, возможно, вы установили Unicode для project и LPCSTR это "переводится"const wchar_t *, который не совместим с const char *

при этом: (LPCTSTR)path.c_str() вы берете два символа из исходной строки и создаете из них одну букву unicode wchar_t. Таким образом, вы получаете" китайские " символы.


вы компилируете для Unicode, что означает, что CreateDirectory псевдоним CreateDirectoryW, широкая версия символов. Однако текст в вашей программе кодируется с помощью ANSI. Это означает, что ваша программа не может обрабатывать интернационализацию должным образом.

компилятор говорит вам, что существует несоответствие между кодировку текста, что CreateDirectoryW ожидает и кодировку текста, которую вы предоставляете. Это правда, что вы могли бы назвать CreateDirectoryA чтобы решить эту ошибку, но это только собирается увековечить корневую проблему, тот факт, что вы используете текст ANSI в своей программе.

Итак, лучшее решение - начать кодировать весь текст как Unicode. Прекратите использовать string и начать использовать wstring. Как только вы измените path to wstring затем

CreateDirectory(path.c_str(),NULL);

является правильным.


использовать . CreateDirectory макрос либо CreateDirectoryA или CreateDirectoryW в зависимости от конфигурации сборки; они принимают соответственно LPCSTR и LPCWSTR. Если вы знаете, что у вас LPCSTR (что и есть c_str() дает вам), используйте первый.


другие объяснения правильно:

CreateDirectory, как и многие API окон, на самом деле является макросом, который расширяется до "ANSI" или "широкой" версии в зависимости от того,UNICODE определяется. Версии ANSI эффективно преобразует однобайтовые строки символов в двухбайтовых знаков и затем делегаты широкий буквенная версия.

однако предложения по вызову CreateDirectoryA напрямую имеют некоторые недостатки:

в преобразования, выполняемые API "ANSI", предполагают, что исходная строка закодирована на текущей кодовой странице пользователя. В простых случаях, это скорее всего правда. Но во многих реальных кодах это не так. Таким образом, вы можете оказаться с неправильным типом преобразования, что приводит к ошибкам, которые вы найдете гораздо позже. По крайней мере, плохая типография приводит к ошибкам, которые вы найдете сразу.

лучшим решением является использование широких строк (std::wstring) и вызов CreateDirectoryW. Нет преобразования, чтобы пойти не так. Нет требуются типовые списки.

для многих баз кода переписывать все, чтобы использовать широкие строки, нецелесообразно. Оказывается, есть веские причины делать прямо противоположное и продолжать использовать std:: strings но стандартизировать их удерживайте UTF-8 текст. Затем, когда вам нужно вызвать API Windows, вы конвертируете (не typecast) в UTF-16 и вызываете широкую версию API напрямую. Это дает вам полную верность за счет выполнения нескольких преобразований и некоторых временный буфер. Поскольку эти типы вызовов редко находятся в горячих точках, стоимость обычно не является большой проблемой.

в Windows для преобразования между UTF-8 и UTF-16 можно вызвать MultiByteToWideChar / WideCharToMultiByte с кодовой страницей CP_UTF8.


Я боролся с этим долгое время. После совсем немного копания я нашел, что это работает лучше всего; вы можете попробовать следующее:

std::string t = "xyz";
CA2T wt (t.c_str());