2013-05-23 20 views
10

Neue Version der typischen Frage, wie man von std::string zu LPCTSTR konvertiert. IchStd :: String zu LPCTSTR

aus verschiedenen SO Beiträge lesen gelernt, dass ich das tun sollte:

CreateDirectory(path.c_str(),NULL); 

Und immer noch der Compiler gibt Fehler, da cannot convert from const char * to LPCTSTR.

Ich habe versucht:

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

keine Fehler!

Immer noch das Verzeichnis (in der richtigen Stelle) erstellt wird genannt:

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

, die nicht genau das, was ich wollte, wie Sie sich vorstellen können ...

Also, was ich fehle? Ist das etwas mit UNICODE/ANSI? Wie kann ich das beheben?

+4

Die Lektion, um daraus zu lernen, ist nicht zu werfen. Blind zu werfen ist nur, dass du dem Compiler sagst, er soll den Mund halten. Versuchen Sie, den Compiler zu hören. –

+2

@DavidHeffernan Ich werde auf den allwissenden Master-Compiler hören! –

Antwort

7

Ihr Problem hier ist die Tatsache, dass LPCTSTR zu wchar_t* oder char* aufgelöst wird, abhängig davon, ob Ihr Build unterstützt Unicode (Unicode-Flag festgelegt oder nicht).

Um die char* Version explizit aufzurufen, rufen Sie CreateDirectoryA().

+0

Dies ist eine unvollständige Antwort.CreateDirectoryA setzt voraus, dass sich die Zeichenfolge in der aktuellen Codepage des Benutzers befindet. Viel Code verwendet std :: strings, um UTF-8 zu halten (oder, seltener, eine andere Kodierung), in diesem Fall sollten Sie die std :: string in eine UTF-16 WCHAR string konvertieren (und nicht typecast) und an diesen übergeben CreateDirectoryW. Begründung und Codebeispiele hier: http://utf8everywhere.org/ –

6

Versuchen Sie, diese Seite zu sehen: What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc. Wenn Sie MSVC verwenden, als Sie Unicode für Projekt festgelegt haben und LPCSTR ist „übersetzt“ zu const wchar_t *, die mit nicht kompatibel ist const char *

Auf diese Weise: (LPCTSTR)path.c_str() Sie zwei Zeichen von der ursprünglichen Zeichenfolge nehmen und erstellen von ihnen ein Unicode wchar_t Brief. So bekommen Sie "chinesische" Charaktere.

1

Verwenden Sie stattdessen CreateDirectoryA. CreateDirectory ist ein Makro, das je nach Build-Konfiguration entweder auf CreateDirectoryA oder CreateDirectoryW erweitert wird; Sie nehmen jeweils LPCSTR und LPCWSTR. Wenn Sie wissen, dass Sie eine LPCSTR haben (was c_str() Ihnen gibt), verwenden Sie die erste.

5

Sie kompilieren für Unicode, was bedeutet, dass CreateDirectory ein Alias ​​für CreateDirectoryW ist, die Wide-Character-Version. Der Text in Ihrem Programm wird jedoch mit ANSI codiert. Dies bedeutet, dass Ihr Programm die Internationalisierung nicht korrekt verarbeiten kann.

Der Compiler weist Sie darauf hin, dass zwischen der Textcodierung, die CreateDirectoryW erwartet, und der von Ihnen gelieferten Textcodierung ein Konflikt besteht. Es ist wahr, dass Sie CreateDirectoryA aufrufen können, um diese falsche Übereinstimmung zu beheben, aber das wird nur das Stammproblem verewigen, die Tatsache, dass Sie ANSI-Text in Ihrem Programm verwenden.

Also, die beste Lösung ist, den gesamten Text als Unicode zu kodieren. Beenden Sie die Verwendung von string und starten Sie die Verwendung von wstring.Sobald Sie path zu wstring dann

CreateDirectory(path.c_str(),NULL); 

korrekt ändern ist.

+0

Ja, aber ich werde es nur einmal im Programm verwenden, so dass der Wechsel von ANSI zu UNICODE momentan eine mühsame Arbeit ist, eine A in 1-Zeile zu schreiben Code ist einfach. Ihre Antwort ist wirklich interessant, das würde ich mir in Zukunft merken. –

4

Da diese Frage erscheint, wenn Sie versuchen, zu finden:

Hier ist ein Weg "(std :) String LPCTSTR" wie & Pass std::string als LPCTSTRwstring

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

WICHTIG zu konvertieren Hinweis von Adrian McCarthy:

Dies ist in Ordnung, wenn die Quellzeichenfolge ASCII oder ANSI ist und die aktuelle Codepage Windows-1252 ist (was sehr ähnlich zu Latin-1 ist). Wenn die Quelle UTF-8 oder eine andere Codepage ist, wird nur das Problem ausgeblendet.

+0

Dies ist in Ordnung, wenn die Quellzeichenfolge ASCII ist oder wenn es ANSI _and_ ist, ist die aktuelle Codepage Windows-1252 (die Latin-1 sehr ähnlich ist). Wenn die Quelle UTF-8 oder eine andere Codepage ist, wird dadurch das Problem einfach ausgeblendet. –

+0

Sie beginnen mit einem Pfad in einer std :: string mit einer _unknown encoding_. Das Codebeispiel in Ihrer Antwort kopiert die Byte-Dateien aus dieser Zeichenfolge in die wchar_t-Werte in einem Std :: Wstring. CreateDirectoryW erwartet, dass das wstring UTF-16 ist. Wenn die Quellzeichenfolge ASCII oder Windows-1252 ist, funktioniert Ihr Vorschlag (in fast allen Fällen). Wenn sich die Quellzeichenfolge jedoch in einer anderen Codierung wie UTF-8 oder Windows-1250 befindet, enthält das wstring Unsinn. Damit es in allen Fällen funktioniert, müssen Sie die Quellcodierung kennen, die von der Quelle in die wstring konvertiert (nicht kopiert) wird. –

+0

Nein, das meine ich nicht. Das passiert nicht. Angenommen, die Quellzeichenfolge enthält einen griechischen Großbuchstaben Beta, der als UTF-8 kodiert ist. Die Quellzeichenfolge ist also "0xCE 0x92". Die Art und Weise, wie Sie den breiten String konstruieren, wird '0x00CE 0x0092' enthalten, was ein lateinischer Großbuchstabe I mit Zirkumflex ist, gefolgt von einem privaten Zeichen. Das liegt daran, dass Sie eine Kopie anstelle einer Konvertierung erstellt haben. In meiner Antwort wird erklärt, wie die Konvertierung durchgeführt werden kann (dazu muss die Quellencodierung bekannt sein), und es gibt eine Verknüpfung zu einer Seite mit aktuellen Codebeispielen. –

1

Die anderen Erklärungen sind richtig:

Create, wie viele der Fenster APIs, ist eigentlich ein Makro, das in Abhängigkeit davon, zu einem „ANSI“ oder „Wide“ Version erweitert ob UNICODE definiert ist. Die ANSI-Version konvertiert die Einzelbytezeichenfolge effektiv in eine breite Zeichenfolge und delegiert dann an die breite Zeichenfolgenversion.

jedoch auf den Vorschläge nennen CreateDirectoryA direkt mit einigen Nachteilen kommen:

Die Umwandlungen von dem „ANSI“ APIs getan davon aus, dass die Quellzeichenfolge in dem aktuellen Codepage des Benutzers verschlüsselt ist. In einfachen Fällen ist dies wahrscheinlich richtig. Aber in vielen realen Code ist es nicht. So können Sie mit der falschen Art der Konvertierung enden, die zu Fehlern führt, die Sie viel später finden werden. Zumindest die schlechte Typumwandlung führt zu Fehlern, die Sie sofort finden.

Eine bessere Lösung ist die Verwendung von Wide Strings (Std :: Wstring) und CreateDirectoryW aufrufen. Keine Konvertierung, um falsch zu gehen. Keine Typumwandlungen erforderlich.

Für viele Codebasen ist es nicht praktisch, alles neu zu schreiben, um breite Strings zu verwenden. Es stellt sich heraus, dass es gute Gründe gibt, genau das Gegenteil zu tun und weiterhin std :: strings zu verwenden, aber zu standardisieren, sie hold UTF-8 text zu haben. Wenn Sie dann eine Windows-API aufrufen müssen, konvertieren Sie (nicht Typcast) in UTF-16 und rufen Sie direkt die Wide-Version der API auf. Dadurch erhalten Sie volle Klangtreue auf Kosten einiger Conversions und temporärer Puffer. Da diese Arten von Anrufen selten in Hot Spots sind, sind die Kosten in der Regel keine große Sache.

Unter Windows können Sie zum Konvertieren zwischen UTF-8 und UTF-16 MultiByteToWideChar/WideCharToMultiByte mit der auf CP_UTF8 eingestellten Codepage aufrufen.

0

Ich habe schon eine ganze Weile damit zu kämpfen. Nach einigem Graben fand ich das am besten; Sie könnten folgendes versuchen:

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