tl;dr
Verwenden Sie die Bibliothek der Intensivstation . Wenn Sie das nicht tun, wird Ihre Konvertierungsroutine in Fällen, von denen Sie wahrscheinlich nicht einmal wissen, dass sie existieren, unbemerkt abbrechen.
Zunächst müssen Sie eine Frage beantworten: Was ist die Kodierung Ihrer std::string
? Ist es ISO-8859-1? Oder vielleicht ISO-8859-8? Oder Windows Codepage 1252? Weiß das Programm, mit dem Sie Groß- in Kleinbuchstaben umwandeln wollen, das? (Oder scheitert sie kläglich bei Personen über 0x7f
?)
Wenn Sie UTF-8 verwenden ( die einzige vernünftige Wahl unter den 8-Bit-Kodierungen ) mit std::string
als Container, täuschen Sie sich bereits, wenn Sie glauben, dass Sie die Dinge noch unter Kontrolle haben. Sie speichern eine Multibyte-Zeichenfolge in einem Container, der das Multibyte-Konzept nicht kennt, und auch die meisten der Operationen, die Sie damit durchführen können, nicht! Selbst etwas so Einfaches wie .substr()
könnte zu ungültigen (Unter-)Zeichenketten führen, weil Sie in der Mitte einer Multibyte-Sequenz trennen.
Sobald Sie etwas versuchen wie std::toupper( 'ß' )
または std::tolower( '' )
en tout Kodierung, sind Sie in Schwierigkeiten. Denn 1), der Standard arbeitet immer nur mit einem Zeichen auf einmal, so dass es einfach nicht drehen kann ß
en SS
wie es richtig wäre. Und 2), der Standard arbeitet immer nur mit einem Zeichen zur gleichen Zeit, so dass er nicht entscheiden kann, ob in der Mitte eines Wortes steht (wobei wäre korrekt), oder am Ende ( ). Ein anderes Beispiel wäre std::tolower( 'I' )
was zu unterschiedlichen Ergebnissen führen sollte je nach Gebietsschema -- praktisch überall, wo man es erwarten würde i
aber in der Türkei (LATIN SMALL LETTER DOTLESS I) ist die richtige Antwort (was wiederum mehr als ein Byte in UTF-8-Kodierung ist).
Also, tout Groß-/Kleinschreibung, die jeweils ein Zeichen bearbeitet, oder noch schlimmer, eine Byte zu einer Zeit, ist absichtlich unterbrochen. Dazu gehören alle std::
Varianten, die zu diesem Zeitpunkt existieren.
Dann gibt es noch den Punkt, dass die Standardbibliothek, für das, was sie ist fähig ist, hängt davon ab, welche Lokalitäten unterstützt auf dem Rechner, auf dem Ihre Software läuft... und was tun Sie, wenn Ihr Zielgebietsschema zu den nicht unterstützten auf dem Rechner Ihres Kunden gehört?
Was Sie also sind realmente Wir suchen eine String-Klasse, die mit all dem richtig umgehen kann, und das ist ノット einer der std::basic_string<>
Varianten .
(C++11 Anmerkung: std::u16string
y std::u32string
son besser , aber immer noch nicht perfekt. C++20 gebracht std::u8string
aber diese spezifizieren lediglich die Kodierung . In vielerlei Hinsicht sind sie immer noch nicht mit den Unicode-Mechanismen vertraut, wie Normalisierung, Kollationierung, ...)
Während Boost siehe nett, API-mäßig ist Boost.Locale im Grunde ein Wrapper um INTENSIVSTATION . Wenn Boost ist zusammengestellt mit ICU-Unterstützung... wenn nicht, ist Boost.Locale auf die für die Standardbibliothek kompilierte Locale-Unterstützung beschränkt.
Und glauben Sie mir, unter Die Kompilierung von Boost mit ICU kann manchmal eine echte Qual sein. (Es gibt keine vorkompilierten Binärdateien für Windows, die ICU enthalten, also müssen Sie sie zusammen mit Ihrer Anwendung bereitstellen, und dass öffnet ein ganz neues Wespennest...)
Ich persönlich würde daher empfehlen, die volle Unicode-Unterstützung direkt aus erster Hand zu bekommen und die INTENSIVSTATION Bibliothek direkt:
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>
#include <iostream>
int main()
{
/* "Odysseus" */
char const * someString = u8"";
icu::UnicodeString someUString( someString, "UTF-8" );
// Setting the locale explicitly here for completeness.
// Usually you would use the user-specified system locale,
// which *does* make a difference (see vs. i above).
std::cout << someUString.toLower( "el_GR" ) << "\n";
std::cout << someUString.toUpper( "el_GR" ) << "\n";
return 0;
}
Kompilieren (in diesem Beispiel mit G++):
g++ -Wall example.cpp -licuuc -licuio
Dies ergibt:
Beachten Sie, dass die <-> Umwandlung in der Mitte des Wortes und die <-> Umwandlung am Ende des Wortes erfolgt. Keine <algorithm>
-basierte Lösung kann Ihnen das bieten.