tl; Dr.
ICU kitaplığını kullanın . Bunu yapmazsanız, dönüşüm rutininiz muhtemelen varlığınızın farkında bile olmadığınız durumlarda sessizce bozulur.
Nedir: Önce bir soruya cevap vermek zorunda kodlama , aramalarınızdan std::string
? ISO-8859-1 mi? Ya da belki ISO-8859-8? Veya Windows Codepage 1252? Büyük harfe küçük harfe dönüştürmek için ne kullandığınızı biliyor musunuz? (Yoksa karakterler bittiğinde perişan bir şekilde başarısız oluyor 0x7f
mu?)
std::string
Kapsayıcı olarak UTF-8 (8 bit kodlamalar arasında tek aklı başında seçim) kullanıyorsanız , zaten bir şeyleri kontrol ettiğinizi düşünmeye kendinizi aldatırsınız, çünkü bir kapta çok baytlı bir karakter dizisi saklıyorsunuz bu çokbaytlı kavramın farkında değil. .substr()
Bir saatli bomba gibi basit bir şey bile . (Çünkü çok baytlı bir dizinin bölünmesi geçersiz (alt) bir dizeyle sonuçlanacaktır.)
Eğer böyle bir şey deneyin ve en kısa sürede std::toupper( 'ß' )
de, herhangi bir kodlama, derin belada. (Çünkü bu "doğru" sadece burada gerekli değil, sadece bir sonuç karakteri verebilen standart kütüphane ile yapmak mümkün değildir "SS"
.) [1] Yerel ayara bağlı olarakstd::tolower( 'I' )
farklı sonuçlar vermesi gereken başka bir örnek olacaktır . Almanya'da doğru olur; Türkiye'de (LATIN KÜÇÜK MEKTUP DOTLESS I) beklenen sonuçtur (yine UTF-8 kodlamasında birden fazla bayttır). Yine başka bir örnek, Yunan Sigma , büyük harf , küçük harf ... bir kelimenin sonu hariç .'i'
'ı'
'∑'
'σ'
'ς'
Bu nedenle, bir seferde bir karakter üzerinde veya daha da kötüsü, bir seferde bir bayt üzerinde çalışan herhangi bir vaka dönüşümü tasarım tarafından kırılır.
Sonra standart kütüphanenin, yapabileceği şey için , yazılımınızın çalıştığı makinede hangi yerel ayarların desteklendiğine bağlı olduğu nokta var ... ve değilse ne yaparsınız?
Peki edilmektedir gerçekten aradığınız doğru bütün bunlarla başa çıkabilen bir dize sınıftır, ve olmasıdır değil herhangi birinin std::basic_string<>
varyantları .
(C ++ 11 not: std::u16string
ve std::u32string
daha iyi , ama yine de mükemmel değil. C ++ 20 getirdi std::u8string
, ancak bunların hepsi kodlama belirtmek olduğunu. Diğer birçok açıdan hala Unicode mekaniği, hala normalleştirme, harmanlama, gibi cahil kalır .. .)
Boost iken görünüyor akıllıca bir güzel, API, Boost.Locale temelde etrafında sarıcı YBÜ . Eğer Boost edilir derlenmiş yoğun bakım desteği ile Değilse ..., Boost.Locale standart kütüphane için derlenmiş yerel destek ile sınırlıdır.
Ve inan bana, ICU ile derlemek için Boost yapmak bazen gerçek bir acı olabilir. (Windows için önceden derlenmiş ikili dosyalar yoktur, bu nedenle bunları uygulamanızla birlikte sağlamanız gerekir ve bu da yepyeni bir solucan kutusu açar ...)
Şahsen tam at ağzından tam Unicode desteği almanızı ve doğrudan YBÜ kütüphanesini kullanmanızı tavsiye ederim :
#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;
}
Derleme (bu örnekte G ++ ile):
g++ -Wall example.cpp -licuuc -licuio
Bu şunları verir:
ὀδυσσεύς
Kelimenin ortasındaki Σ <-> σ dönüşümünün ve kelimenin sonundaki Σ <-> ς dönüşümüne dikkat edin. Hiçbir <algorithm>
tabanlı çözüm size bunu veremez.
[1] 2017 yılında Alman Ortografya Konseyi "ẞ" U + 1E9E LATIN SERMAYE MEKTUBU SHARP S'nin pasaportlarda (adların büyük harfle yazıldığı yerlerde) belirsizliği önlemek için bir seçenek olarak resmi olarak kullanılabileceğine karar verdi. ). Komite kararıyla geçersiz kılınan güzel go-to örneğim ...