tl; dr
Gunakan perpustakaan ICU . Jika tidak, rutin konversi Anda akan membungkam kasus yang mungkin tidak Anda sadari bahkan ada.
Pertama, Anda harus menjawab pertanyaan: Apa pengkodean Anda std::string
? Apakah ISO-8859-1? Atau mungkin ISO-8859-8? Atau Windows Codepage 1252? Apakah apa pun yang Anda gunakan untuk mengonversi huruf besar ke kecil tahu itu? (Atau apakah itu gagal total untuk karakter 0x7f
?)
Jika Anda menggunakan UTF-8 (satu-satunya pilihan yang waras di antara penyandian 8-bit) dengan std::string
sebagai wadah, Anda sudah menipu diri sendiri untuk percaya bahwa Anda masih mengendalikan hal-hal, karena Anda menyimpan urutan karakter multibyte dalam wadah yang tidak menyadari konsep multibyte. Bahkan sesuatu yang sederhana seperti .substr()
bom waktu. (Karena pemisahan urutan multibyte akan menghasilkan string (sub-) yang tidak valid.)
Dan begitu Anda mencoba sesuatu seperti std::toupper( 'ß' )
, dalam pengkodean apa pun , Anda berada dalam masalah besar. (Karena sama sekali tidak mungkin untuk melakukan ini "benar" dengan perpustakaan standar, yang hanya dapat memberikan satu karakter hasil, bukan yang "SS"
diperlukan di sini.) [1] Contoh lain adalah std::tolower( 'I' )
, yang akan menghasilkan hasil yang berbeda tergantung pada lokal . Di Jerman, 'i'
akan benar; di Turki, 'ı'
(LATIN KECIL SURAT DOTLESS I) adalah hasil yang diharapkan (yang, sekali lagi, lebih dari satu byte dalam pengkodean UTF-8). Contoh lain adalah Sigma Yunani , huruf besar '∑'
, huruf kecil 'σ'
... kecuali pada akhir kata, di mana itu 'ς'
.
Jadi, konversi kasus apa pun yang berfungsi pada karakter pada satu waktu, atau lebih buruk, byte pada suatu waktu, rusak oleh desain.
Lalu ada titik bahwa perpustakaan standar, untuk apa yang mampu dilakukannya, tergantung pada daerah mana yang didukung pada mesin perangkat lunak Anda menjalankan ... dan apa yang Anda lakukan jika tidak?
Jadi yang benar - benar Anda cari adalah kelas string yang mampu menangani semua ini dengan benar, dan itu bukanstd::basic_string<>
varian apa pun .
(C ++ 11 catatan: std::u16string
dan std::u32string
yang lebih baik ., Tapi masih tidak sempurna C ++ 20 dibawa std::u8string
, tapi semua do ini adalah menentukan encoding Dalam banyak hal lain mereka masih tetap bodoh mekanika Unicode, seperti normalisasi, pemeriksaan, ... .)
Sementara Boost terlihat bagus, API bijak, Boost.Locale pada dasarnya adalah pembungkus di sekitar ICU . Jika Boost dikompilasi dengan dukungan ICU ... jika tidak, Boost.Locale terbatas pada dukungan lokal yang dikompilasi untuk pustaka standar.
Dan percayalah, mendapatkan Boost untuk dikompilasi dengan ICU terkadang bisa sangat menyakitkan. (Tidak ada binari yang dikompilasi sebelumnya untuk Windows, jadi Anda harus menyediakannya bersama dengan aplikasi Anda, dan itu membuka kaleng cacing yang sama sekali baru ...)
Jadi secara pribadi saya akan merekomendasikan mendapatkan dukungan Unicode penuh langsung dari mulut kuda dan menggunakan perpustakaan ICU langsung:
#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;
}
Kompilasi (dengan G ++ dalam contoh ini):
g++ -Wall example.cpp -licuuc -licuio
Ini memberi:
ὀδυσσεύς
Perhatikan bahwa konversi Σ <-> σ di tengah kata, dan konversi Σ <-> ς di akhir kata. Tidak ada <algorithm>
solusi berbasis yang bisa memberi Anda itu.
[1] Pada tahun 2017, Dewan untuk Orthografi Jerman memutuskan bahwa "ẞ" U + 1E9E LATIN MODAL SURAT SHARP S dapat digunakan secara resmi, sebagai opsi di samping konversi "SS" tradisional untuk menghindari ambiguitas misalnya dalam paspor (di mana nama ditulis dengan huruf besar ). Contoh masuk saya yang indah, dibuat usang oleh keputusan komite ...