Ich glaube nicht, dass strings> 8-Bit-Zeichen akzeptiert werden. Ist es bereits in UTF-8 codiert?
Kennytm
3
Was ist Ihre Systemcodierung, die "おはよう"eine systemcodierte Zeichenfolge ergeben würde?
sbi
Ich glaube, MSVC wird das akzeptieren und eine Multibyte-Codierung vornehmen, vielleicht UTF-8.
Potatoswatter
1
@Potatoswatter: MSVC verwendet UTF-8 standardmäßig nicht für ALLES. Wenn Sie diese Zeichen eingeben, werden Sie gefragt, in welche Codierung die Datei konvertiert werden soll, und standardmäßig die Codepage 1252.
Mooing Duck
2
@ Samir: Wichtiger ist die Kodierung der Datei ? Können Sie diese Zeichenfolge an den Anfang der Datei verschieben und einen Hexdump dieses Teils anzeigen? Daran können wir es wahrscheinlich erkennen.
Mooing Duck
Antworten:
239
Angenommen, die Eingabezeichenfolge in Ihrem Beispiel (お は よ う) ist eine UTF-8-codierte Darstellung (was anscheinend nicht der Fall ist, aber nehmen wir an, dass dies der Erklärung dient :-)) einer Unicode-Zeichenfolge Wenn Sie dies interessieren, kann Ihr Problem allein mit der Standardbibliothek (C ++ 11 und neuer) vollständig gelöst werden.
Wie in den Kommentaren erwähnt und unter https://stackoverflow.com/a/17106065/6345 erläutert, kann es vorkommen, dass die Verwendung der Standardbibliothek zum Konvertieren zwischen UTF-8 und UTF-16 zu unerwarteten Unterschieden bei den Ergebnissen auf verschiedenen Plattformen führt . Beachten Sie für eine bessere Konvertierung std::codecvt_utf8die Beschreibung unter http://en.cppreference.com/w/cpp/locale/codecvt_utf8
Hinweis (neu) :
Da der codecvtHeader in C ++ 17 veraltet ist, wurden einige Bedenken hinsichtlich der in dieser Antwort vorgestellten Lösung geäußert. Allerdings fügte das C ++ Normenausschuss eine wichtige Aussage in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html sagen
Diese Bibliothekskomponente sollte nebenbei in Anhang D eingestellt werden, bis ein geeigneter Ersatz standardisiert ist.
In absehbarer Zeit ist die codecvtLösung in dieser Antwort sicher und tragbar.
Dies funktioniert nur, wenn alle Zeichen Einzelbyte sind, dh ASCII oder ISO-8859-1 . Alles, was mit mehreren Bytes zu tun hat, schlägt kläglich fehl, einschließlich UTF-8. Die Frage enthält eindeutig Mehrbytezeichen.
Mark Ransom
28
Diese Antwort ist eindeutig unzureichend und kopiert nur schmale Zeichen in breite Zeichen. In den anderen Antworten, insbesondere der von Johann Gerell, erfahren Sie, wie Sie von einer Multi-Byte- oder utf8-codierten Zeichenfolge zu einer utf16-Zeichenfolge wechseln.
DLRdave
10
Diese Antwort ist gefährlich und wird wahrscheinlich auf einem Nicht-ASCII-System brechen. dh ein arabischer Dateiname wird durch diesen Hack entstellt.
Stephen
9
Diese Antwort ist nützlich, wenn Sie die Nuance des Fragentextes ignorieren und sich auf den Fragentitel konzentrieren, der mich von Google hierher gebracht hat. Wie es ist, ist der Titel der Frage äußerst irreführend und sollte geändert werden, um die wahre Frage widerzuspiegeln
Anne Quinn
3
Dies funktioniert nur für 7-Bit-ASCII-Zeichen. Für latin1 funktioniert es nur, wenn char als vorzeichenlos konfiguriert ist. Wenn der Typ char signiert ist (was meistens der Fall ist), führen Zeichen> 127 zu falschen Ergebnissen.
Huyc
32
Ihre Frage ist nicht genau spezifiziert. Genau genommen ist dieses Beispiel ein Syntaxfehler. Es std::mbstowcsist jedoch wahrscheinlich das, wonach Sie suchen.
Es ist eine C-Bibliotheksfunktion und arbeitet mit Puffern, aber hier ist eine benutzerfreundliche Redewendung, mit freundlicher Genehmigung von TBohne (ehemals Mooing Duck):
std::wstring ws(s.size(), L' ');// Overestimate number of code points.
ws.resize(std::mbstowcs(&ws[0], s.c_str(), s.size()));// Shrink to fit.
@Samir: Sie müssen sicherstellen, dass die Laufzeitcodierung mit der Codierung zur Kompilierungszeit übereinstimmt. Möglicherweise müssen Sie setlocaleCompiler-Flags anpassen oder anpassen. Ich weiß es nicht, weil ich kein Windows verwende, aber deshalb ist es keine übliche Funktion. Betrachten Sie die andere Antwort, wenn möglich.
@WaffleSouffle Das ist veraltet. Seit 2011 sind zusammenhängende Implementierungen erforderlich, und Implementierungen haben solche Tricks lange vorher beendet.
Potatoswatter
1
und einige Umgebungen wie mingw haben immer noch keinen Codecvt-Header, so dass einige der "besseren" Lösungen früher nicht funktionieren, was bedeutet, dass dieses Problem auch ab Dezember 2014 noch keine guten Lösungen in mingw hat
Brian Jack
18
Nur Windows-API, vor der Implementierung von C ++ 11, falls jemand sie benötigt:
Sie können es optimieren. Es ist nicht erforderlich, die Zeichenfolge mit a doppelt zu kopieren vector. Reservieren Sie einfach die Zeichen in der Zeichenfolge wstring strW(charsNeeded + 1);und verwenden Sie sie dann als Puffer für die Konvertierung : &strW[0]. strW[charsNeeded] = 0;
Stellen Sie
1
@ c00000fd Soweit ich weiß, muss der interne Puffer std :: basic_string erst seit dem C ++ 11-Standard kontinuierlich sein. Mein Code ist vor C ++ 11, wie oben im Beitrag angegeben. Daher wäre der & strW [0] -Code nicht standardkonform und könnte zur Laufzeit legitim abstürzen.
Alex Che
13
Wenn Sie Windows / Visual Studio verwenden und eine Zeichenfolge in wstring konvertieren müssen, können Sie Folgendes verwenden:
#include<AtlBase.h>#include<atlconv.h>...
string s ="some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());
Gleiches Verfahren zum Konvertieren einer Zeichenfolge in eine Zeichenfolge (manchmal müssen Sie eine Codepage angeben ):
#include<AtlBase.h>#include<atlconv.h>...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());
// // using ATL
CA2W ca2w(str, CP_UTF8);// // or the standard way taken from the answer above#include<codecvt>#include<string>// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.from_bytes(str);}// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.to_bytes(str);}
Manchmal müssen Sie die Sicherheitswarnung # 4995 'deaktivieren. Ich kenne keine andere Problemumgehung (für mich passiert dies, wenn ich in VS2012 für Windows XP kompiliert habe).
Entschuldigung, ich bin kein englischer Muttersprachler. Bitte bearbeiten Sie nach Belieben.
lmiguelmh
Was ist mit dem Downvoter los? Was ist falsch an der Antwort?
lmiguelmh
Wahrscheinlich die Tatsache, dass es nicht portablen Code fördert.
Pavel Minaev
Ja, deshalb habe ich angegeben, dass dies nur in Windows / Visual Studio funktioniert. Aber zumindest ist diese Lösung richtig und nicht diese:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Zusätzlicher Hinweis: CA2W befindet sich unter dem Namespace von ATL. (ATL :: CA2W)
Val
12
Hier ist eine Möglichkeit string, wstringString-Konstanten zu kombinieren und zu mischen wstring. Verwenden Sie die wstringstreamKlasse.
Dies funktioniert NICHT für Mehrbyte-Zeichencodierungen. Dies ist nur eine blöde Methode, um die Typensicherheit wegzuwerfen und 7-Bit-Zeichen von std :: string in die unteren 7 Bits jedes Zeichens von std: wstring zu erweitern. Dies ist nur nützlich, wenn Sie über 7-Bit-ASCII-Zeichenfolgen verfügen und eine API aufrufen müssen, für die breite Zeichenfolgen erforderlich sind.
Die Antwort scheint interessant. Könnten Sie bitte etwas erklären: Funktioniert dies für Multi-Byte-Codierungen und warum / wie?
wh1t3cat1k
Codierungsschemata sind orthogonal zur Speicherklasse. stringspeichert 1-Byte-Zeichen und wstringspeichert 2-Byte-Zeichen. so etwas wie utf8 speichert Mulitbyte-Zeichen als eine Reihe von 1-Byte-Werten, dh in a string. Die Zeichenfolgenklassen helfen nicht bei der Codierung. Ich bin kein Experte für das Codieren von Klassen in C ++.
Mark Lakata
2
Gibt es einen Grund, warum dies nicht die beste Antwort ist, wenn man bedenkt, wie kurz und einfach es ist? Gibt es Fälle, die nicht abgedeckt sind?
Ryuu
@ MarkLakata, ich habe deine Antwort auf den ersten Kommentar gelesen, bin mir aber immer noch nicht sicher. Funktioniert es für Multi-Byte-Zeichen? Mit anderen Worten, ist es nicht anfällig für die gleiche Gefahr wie diese Antwort ?
März 2377
@ Marc.2377 Dies funktioniert NICHT für Mehrbyte-Zeichencodierungen. Dies ist nur eine blöde Art, die Typensicherheit wegzuwerfen und 7-Bit-Zeichen von std::stringin die unteren 7-Bits jedes Zeichens von zu erweitern std:wstring. Dies ist nur nützlich, wenn Sie über 7-Bit-ASCII-Zeichenfolgen verfügen und eine API aufrufen müssen, für die breite Zeichenfolgen erforderlich sind. Schauen Sie sich stackoverflow.com/a/8969776/3258851 an, wenn Sie etwas Anspruchsvolleres benötigen.
Weil dies nur funktioniert, wenn die Codierung Windows-1252 ist, das nicht einmal die Buchstaben in der Frage enthalten kann.
Mooing Duck
3
Dies ist die am wenigsten fehleranfällige Methode, wenn Sie wissen, dass Sie mit ASCII zu tun haben. Dies ist ein wichtiger Anwendungsfall beim Portieren von Apps auf neuere APIs.
Sid Sarasvati
Dies ist nicht der Weg. Wenn Sie Visual Studio verwenden, sollten Sie verwenden atlconv.h. Überprüfen Sie die anderen Antworten.
Diese Variante ist mein Favorit im wirklichen Leben. Es konvertiert die Eingabe, wenn sie UTF-8 gültig ist , in die entsprechende wstring. Wenn die Eingabe beschädigt ist, wstringwird die aus den einzelnen Bytes aufgebaut. Dies ist äußerst hilfreich, wenn Sie sich über die Qualität Ihrer Eingabedaten nicht sicher sein können.
Was ist mit all diesen Antworten, die den dynamischen Speicher auf unsichere Weise zuweisen und dann die Daten aus dem Puffer in die Zeichenfolge kopieren? Warum wird niemand den unsicheren Mittelsmann los?
Mooing Duck
hahakubile, kannst du bitte mit etwas ähnlichem für ws2s helfen?
Cristian
1
Basierend auf meinen eigenen Tests (unter Windows 8, vs2010) können mbstowcs tatsächlich die ursprüngliche Zeichenfolge beschädigen. Sie funktionieren nur mit der ANSI-Codepage. Wenn MultiByteToWideChar / WideCharToMultiByte auch eine Beschädigung von Zeichenfolgen verursachen kann, ersetzen sie jedoch Zeichen, die sie nicht kennen, durch '?' Fragezeichen, aber mbstowcs neigt dazu anzuhalten, wenn es auf ein unbekanntes Zeichen stößt und an dieser Stelle eine Zeichenfolge abschneidet. (Ich habe vietnamesische Schriftzeichen an finnischen Fenstern getestet).
Ziehen Sie daher die Multi * -Fenster-API-Funktion den analogen Ansi C-Funktionen vor.
Ich habe auch festgestellt, dass der kürzeste Weg zum Codieren von Zeichenfolgen von einer Codepage zur anderen darin besteht, nicht die API-Funktionsaufrufe MultiByteToWideChar / WideCharToMultiByte zu verwenden, sondern deren analoge ATL-Makros: W2A / A2W.
Die oben erwähnte analoge Funktion klingt also wie folgt:
Beachten Sie jedoch, dass diese Makros stark gestapelt sind - nicht für Schleifen oder rekursive Schleifen für dieselbe Funktion - nach Verwendung des W2A- oder A2W-Makros - besser so schnell wie möglich zurückgeben, damit der Stapel von der temporären Konvertierung befreit wird.
Diese Str2Wstr hat ein Problem mit der 0-Terminierung. Es ist nicht mehr möglich, die generierten Zeichenfolgen über "+" zu verketten (wie in Zeichenfolge s3 = s1 + s2). Ich werde bald eine Antwort veröffentlichen, um dieses Problem zu lösen. Müssen zuerst einige Tests auf Speicherlecks durchführen.
Das wird auch nicht funktionieren. Sie müssen diese Nicht-BMP-Zeichen in C-Escape-Sequenzen konvertieren.
Dave Van den Eynde
3
@ Dave: Es funktioniert, wenn Ihr Compiler Unicode in Quelldateien unterstützt, und alle im letzten Jahrzehnt (Visual Studio, GCC, ...)
Thomas Bonini
Hallo, unabhängig von der Standard-Systemcodierung (ich kann beispielsweise Arabisch als Standard-Systemcodierung verwenden), wie sollte die Codierung der Quellcodedatei für L "お は よ う" funktionieren? sollte es in UTF-16 sein, oder kann ich UTF-8 ohne Stückliste für die CPP-Dateicodierung haben?
Afriza N. Arief
2
@afriza: Es ist nicht wirklich wichtig, solange Ihre Kompilierung es unterstützt
Thomas Bonini
2
Es ist kein Fehler; Erweiterte Zeichen in einer "schmalen" Zeichenfolge werden definiert, um Multibyte-Sequenzen zuzuordnen. Der Compiler sollte es unterstützen, solange das Betriebssystem dies tut. Dies ist das Mindeste, was Sie fragen können.
Potatoswatter
-2
Verwenden Sie diesen Code, um Ihren String in wstring zu konvertieren
Beachten Sie, dass in der Frage Windows nicht erwähnt wird und diese Antwort nur für Windows gilt.
Johann Gerell
CP_ACPist mit Sicherheit das falsche Argument. Der Umgebungsstatus des ausführenden Threads wirkt sich plötzlich auf das Verhalten des Codes aus. Nicht ratsam. Geben Sie bei Ihrer Konvertierung eine feste Zeichenkodierung an. (Und erwägen Sie, Fehler zu behandeln.)
strings
> 8-Bit-Zeichen akzeptiert werden. Ist es bereits in UTF-8 codiert?"おはよう"
eine systemcodierte Zeichenfolge ergeben würde?Antworten:
Angenommen, die Eingabezeichenfolge in Ihrem Beispiel (お は よ う) ist eine UTF-8-codierte Darstellung (was anscheinend nicht der Fall ist, aber nehmen wir an, dass dies der Erklärung dient :-)) einer Unicode-Zeichenfolge Wenn Sie dies interessieren, kann Ihr Problem allein mit der Standardbibliothek (C ++ 11 und neuer) vollständig gelöst werden.
Die TL; DR-Version:
Längeres online kompilierbares und ausführbares Beispiel:
(Sie alle zeigen das gleiche Beispiel. Es gibt nur viele für Redundanz ...)
Anmerkung (alt) :
Wie in den Kommentaren erwähnt und unter https://stackoverflow.com/a/17106065/6345 erläutert, kann es vorkommen, dass die Verwendung der Standardbibliothek zum Konvertieren zwischen UTF-8 und UTF-16 zu unerwarteten Unterschieden bei den Ergebnissen auf verschiedenen Plattformen führt . Beachten Sie für eine bessere Konvertierung
std::codecvt_utf8
die Beschreibung unter http://en.cppreference.com/w/cpp/locale/codecvt_utf8Hinweis (neu) :
Da der
codecvt
Header in C ++ 17 veraltet ist, wurden einige Bedenken hinsichtlich der in dieser Antwort vorgestellten Lösung geäußert. Allerdings fügte das C ++ Normenausschuss eine wichtige Aussage in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html sagenIn absehbarer Zeit ist die
codecvt
Lösung in dieser Antwort sicher und tragbar.quelle
std::codecvt_utf8
für Anfänger<codecvt>
seit C ++ 17 veraltet ist.quelle
Ihre Frage ist nicht genau spezifiziert. Genau genommen ist dieses Beispiel ein Syntaxfehler. Es
std::mbstowcs
ist jedoch wahrscheinlich das, wonach Sie suchen.Es ist eine C-Bibliotheksfunktion und arbeitet mit Puffern, aber hier ist eine benutzerfreundliche Redewendung, mit freundlicher Genehmigung von TBohne (ehemals Mooing Duck):
quelle
setlocale
Compiler-Flags anpassen oder anpassen. Ich weiß es nicht, weil ich kein Windows verwende, aber deshalb ist es keine übliche Funktion. Betrachten Sie die andere Antwort, wenn möglich.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWNur Windows-API, vor der Implementierung von C ++ 11, falls jemand sie benötigt:
quelle
vector
. Reservieren Sie einfach die Zeichen in der Zeichenfolgewstring strW(charsNeeded + 1);
und verwenden Sie sie dann als Puffer für die Konvertierung :&strW[0]
.strW[charsNeeded] = 0;
Wenn Sie Windows / Visual Studio verwenden und eine Zeichenfolge in wstring konvertieren müssen, können Sie Folgendes verwenden:
Gleiches Verfahren zum Konvertieren einer Zeichenfolge in eine Zeichenfolge (manchmal müssen Sie eine Codepage angeben ):
Sie können eine Codepage und sogar UTF8 angeben (das ist ziemlich gut, wenn Sie mit JNI / Java arbeiten ). In dieser Antwort wird eine Standardmethode zum Konvertieren eines std :: wstring in utf8 std :: string gezeigt .
Wenn Sie mehr über Codepages erfahren möchten, gibt es einen interessanten Artikel über Joel über Software: Das absolute Minimum, das jeder Softwareentwickler unbedingt über Unicode und Zeichensätze wissen muss .
Diese CA2W-Makros (Convert Ansi to Wide = Unicode) sind Teil der ATL- und MFC-String-Konvertierungsmakros , einschließlich Beispielen.
Manchmal müssen Sie die Sicherheitswarnung # 4995 'deaktivieren. Ich kenne keine andere Problemumgehung (für mich passiert dies, wenn ich in VS2012 für Windows XP kompiliert habe).
Bearbeiten: Nun, laut diesem Artikel scheint der Artikel von Joel zu sein: "Während unterhaltsam, ist es ziemlich leicht auf tatsächlichen technischen Details". Artikel: Was jeder Programmierer unbedingt positiv über Codierung und Zeichensätze wissen muss, um mit Text arbeiten zu können .
quelle
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Hier ist eine Möglichkeit
string
,wstring
String-Konstanten zu kombinieren und zu mischenwstring
. Verwenden Sie diewstringstream
Klasse.Dies funktioniert NICHT für Mehrbyte-Zeichencodierungen. Dies ist nur eine blöde Methode, um die Typensicherheit wegzuwerfen und 7-Bit-Zeichen von std :: string in die unteren 7 Bits jedes Zeichens von std: wstring zu erweitern. Dies ist nur nützlich, wenn Sie über 7-Bit-ASCII-Zeichenfolgen verfügen und eine API aufrufen müssen, für die breite Zeichenfolgen erforderlich sind.
quelle
string
speichert 1-Byte-Zeichen undwstring
speichert 2-Byte-Zeichen. so etwas wie utf8 speichert Mulitbyte-Zeichen als eine Reihe von 1-Byte-Werten, dh in astring
. Die Zeichenfolgenklassen helfen nicht bei der Codierung. Ich bin kein Experte für das Codieren von Klassen in C ++.std::string
in die unteren 7-Bits jedes Zeichens von zu erweiternstd:wstring
. Dies ist nur nützlich, wenn Sie über 7-Bit-ASCII-Zeichenfolgen verfügen und eine API aufrufen müssen, für die breite Zeichenfolgen erforderlich sind. Schauen Sie sich stackoverflow.com/a/8969776/3258851 an, wenn Sie etwas Anspruchsvolleres benötigen.Von
char*
biswstring
:Von
string
biswstring
:Beachten Sie, dass dies nur gut funktioniert, wenn die zu konvertierende Zeichenfolge nur ASCII-Zeichen enthält.
quelle
atlconv.h
. Überprüfen Sie die anderen Antworten.mit Boost.Locale:
quelle
Diese Variante ist mein Favorit im wirklichen Leben. Es konvertiert die Eingabe, wenn sie UTF-8 gültig ist , in die entsprechende
wstring
. Wenn die Eingabe beschädigt ist,wstring
wird die aus den einzelnen Bytes aufgebaut. Dies ist äußerst hilfreich, wenn Sie sich über die Qualität Ihrer Eingabedaten nicht sicher sein können.quelle
Wenn Sie QT haben und faul sind, eine Funktion und Dinge zu implementieren, die Sie verwenden können
std :: string str; QString (str) .toStdWString ()
quelle
QString
, da derQString
Konstruktor aus irgendeinem Grund keine Zeichenfolge akzeptieren kann.Methode s2ws funktioniert gut. Hoffnung hilft.
quelle
Basierend auf meinen eigenen Tests (unter Windows 8, vs2010) können mbstowcs tatsächlich die ursprüngliche Zeichenfolge beschädigen. Sie funktionieren nur mit der ANSI-Codepage. Wenn MultiByteToWideChar / WideCharToMultiByte auch eine Beschädigung von Zeichenfolgen verursachen kann, ersetzen sie jedoch Zeichen, die sie nicht kennen, durch '?' Fragezeichen, aber mbstowcs neigt dazu anzuhalten, wenn es auf ein unbekanntes Zeichen stößt und an dieser Stelle eine Zeichenfolge abschneidet. (Ich habe vietnamesische Schriftzeichen an finnischen Fenstern getestet).
Ziehen Sie daher die Multi * -Fenster-API-Funktion den analogen Ansi C-Funktionen vor.
Ich habe auch festgestellt, dass der kürzeste Weg zum Codieren von Zeichenfolgen von einer Codepage zur anderen darin besteht, nicht die API-Funktionsaufrufe MultiByteToWideChar / WideCharToMultiByte zu verwenden, sondern deren analoge ATL-Makros: W2A / A2W.
Die oben erwähnte analoge Funktion klingt also wie folgt:
_acp wird im Makro USES_CONVERSION deklariert.
Oder auch eine Funktion, die ich oft vermisse, wenn ich alte Daten in neue konvertiere:
Beachten Sie jedoch, dass diese Makros stark gestapelt sind - nicht für Schleifen oder rekursive Schleifen für dieselbe Funktion - nach Verwendung des W2A- oder A2W-Makros - besser so schnell wie möglich zurückgeben, damit der Stapel von der temporären Konvertierung befreit wird.
quelle
String zu wstring
wstring zu String
quelle
string s = "おはよう";
ist ein Fehler.Sie sollten wstring direkt verwenden:
quelle
Verwenden Sie diesen Code, um Ihren String in wstring zu konvertieren
quelle
CP_ACP
ist mit Sicherheit das falsche Argument. Der Umgebungsstatus des ausführenden Threads wirkt sich plötzlich auf das Verhalten des Codes aus. Nicht ratsam. Geben Sie bei Ihrer Konvertierung eine feste Zeichenkodierung an. (Und erwägen Sie, Fehler zu behandeln.)