Menangani Penyortiran di Aplikasi Anda

Beberapa aplikasi, seperti Microsoft Active Directory, Microsoft Exchange, dan Microsoft Access, mempertahankan database string lokal dan bahasa yang dapat diurutkan yang diindeks berdasarkan nama (string UTF-16), dan bobot pengurutan terkait.

Pengurutan biasanya intuitif untuk pengguna di lokal mereka sendiri. Namun, itu bisa tidak intuitif untuk pengembang aplikasi. Topik ini membahas pertimbangan untuk menangani pengurutan di aplikasi Anda. Pengurutan dapat berupa linguistik atau ordinal (non-linguistik).

Fungsi Pengurutan

Anda dapat menggunakan berbagai fungsi pengurutan dalam aplikasi Anda:

Biasanya fungsi pengurutan mengevaluasi karakter string menurut karakter. Namun, banyak bahasa memiliki elemen beberapa karakter, seperti pasangan dua karakter "CH" dalam bahasa Spanyol tradisional. CompareString dan CompareStringEx menggunakan pengidentifikasi atau nama lokal yang disediakan aplikasi untuk mengidentifikasi elemen beberapa karakter. Sebaliknya, lstrcmp, dan lstrcmpi menggunakan lokal pengguna.

Contoh lain adalah bahasa Vietnam, yang berisi banyak elemen dua karakter, seperti huruf besar yang valid, huruf besar, dan bentuk huruf kecil "GI", yang masing-masing adalah "GI, "Gi", dan "gi". Salah satu bentuk ini diperlakukan sebagai elemen pengurutan tunggal dan, jika casing diabaikan, dibandingkan sebagai sama. Namun, karena "gI" tidak valid sebagai elemen tunggal, CompareString, CompareStringEx, lstrcmp, dan lstrcmpi memperlakukan "gI" sebagai dua elemen terpisah.

Fungsi CompareString, CompareStringEx, lstrcmp, lstrcmpi, LCMapString, LCMapStringEx, FindNLSString, dan FindNLSStringEx semuanya default untuk menggunakan teknik "pengurutan kata". Untuk jenis jenis ini, semua tanda baca dan karakter non-alfanumerik lainnya, kecuali untuk tanda hubung dan apostrof, datang sebelum karakter alfanumerik apa pun. Tanda hubung dan apostrof diperlakukan secara berbeda dari karakter nonalfanumerik lainnya untuk memastikan bahwa kata-kata seperti "coop" dan "co-op" tetap bersama dalam daftar yang diurutkan.

Alih-alih pengurutan kata, aplikasi dapat meminta teknik "pengurutan string" dari fungsi pengurutan dengan menentukan bendera SORT_STRINGSORT. Pengurutan string memperlakukan tanda hubung dan apostrof sama seperti karakter nonalfanumerik lainnya. Posisi mereka dalam urutan pengurutan adalah sebelum karakter alfanumerik.

Tabel berikut membandingkan hasil pengurutan kata dengan hasil pengurutan string.

Pengurutan Word Pengurutan String
billet tagihan
Tagihan billet
tagihan Tagihan
Tidak tidak dapat
cant Tidak
tidak dapat cant
Con Co-op
Kandang Con
Co-op Kandang

 

Urutkan String Secara Linguistik

Fungsi CompareString dan CompareStringEx menguji kesetaraan linguistik. Aplikasi Anda harus menggunakan fungsi-fungsi ini dengan lokal yang benar untuk mengurutkan string secara linguistik.

Catatan

Untuk kompatibilitas dengan Unicode, aplikasi harus lebih memilih CompareStringEx atau compareString versi Unicode. Alasan lain untuk lebih memilih CompareStringEx adalah bahwa Microsoft bermigrasi ke penggunaan nama lokal alih-alih pengidentifikasi lokal untuk lokal baru, karena alasan interoperabilitas. Aplikasi apa pun yang hanya berjalan di Windows Vista dan yang lebih baru harus menggunakan CompareStringEx.

 

Cara lain pengujian untuk kesetaraan linguistik adalah dengan menggunakan lstrcmp atau lstrcmpi, yang selalu menggunakan pengurutan kata. Fungsi lstrcmpi memanggil CompareString dengan bendera NORM_IGNORECASE, sementara lstrcmp memanggilnya tanpa bendera tersebut. Untuk gambaran umum penggunaan fungsi pembungkus, lihat String.

Fungsi ini mengambil hasil yang sesuai secara linguistik untuk semua lokal. Ekspektasi pengguna untuk lokal yang berbeda dapat berbeda secara signifikan dalam perilaku pengurutan, seperti yang ditunjukkan dalam contoh berikut.

  • Banyak lokal menyamakan ligatur ae (æ) dengan huruf ae. Namun, Islandia (Islandia) menganggapnya sebagai huruf terpisah dan menempatkannya setelah Z dalam urutan penyortiran.
  • Cincin A (Å) biasanya diurutkan hanya dengan perbedaan diakritik dari A. Namun, Swedia (Swedia) menempatkan Cincin A setelah Z dalam urutan penyortiran.

Fungsi mencoba memverifikasi secara ketat bahwa titik kode yang ditentukan dalam standar Unicode secara kanonis sama dengan string titik kode yang setara. Misalnya, titik kode yang mewakili huruf kecil "u" dengan dieresis (ü) secara kanonis sama dengan huruf kecil "u" yang dikombinasikan dengan dieresis ( ̈). Namun, perhatikan bahwa kesetaraan kanonis tidak selalu dimungkinkan.

Karena hampir semua data yang dimasukkan menggunakan keyboard Windows dan editor metode input (IMEs) sesuai dengan normalisasi formulir C yang ditentukan dalam standar Unicode, mengonversi data masuk dari platform lain menggunakan fungsi normalisasi NLS Unicode memberikan hasil yang paling konsisten, terutama untuk lokal yang menggunakan skrip Tibet atau skrip Hangul untuk Hangul modern. Untuk informasi selengkapnya tentang dukungan normalisasi Unicode di Windows Vista dan yang lebih baru, lihat Menggunakan Normalisasi Unicode untuk Mewakili String.

Saat perbandingan string mengikuti preferensi bahasa pengguna, misalnya, saat mengurutkan item untuk kontrol ListView yang diurutkan, aplikasi dapat melakukan salah satu hal berikut ini:

  • Panggil lstrcmp atau lstrcmpi dengan lokal pengguna.
  • Panggil CompareString atau CompareStringEx untuk menentukan lokal untuk perbandingan, untuk meneruskan bendera tambahan, menyematkan karakter null, atau untuk meneruskan panjang eksplisit agar sesuai dengan bagian string.

Ketika hasil perbandingan harus konsisten terlepas dari lokal, misalnya, saat membandingkan data yang diambil dengan daftar yang telah ditentukan sebelumnya atau nilai internal, aplikasi harus menggunakan CompareString atau CompareStringEx dengan parameter Lokal diatur ke LOCALE_INVARIANT. Untuk CompareString, salah satu panggilan berikut akan cocok meskipun mystr adalah "INLAP". Dalam hal ini, panggilan sensitif lokal ke lstrcmpi akan gagal jika lokal saat ini adalah vietnam.

Pada Windows XP:

int iReturn = CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, mystr, -1, _T("InLap"), -1);

Pada sistem operasi sebelumnya:

DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
int iReturn = CompareString(lcid, NORM_IGNORECASE, mystr, -1, _T("InLap"), -1);

Urutkan String Secara Ordinal

Untuk pengurutan ordinal (non-linguistik), aplikasi Anda harus selalu menggunakan fungsi CompareStringOrdinal .

Catatan

Fungsi ini hanya tersedia untuk Windows Vista dan yang lebih baru.

 

CompareStringOrdinal membandingkan dua string Unicode untuk menguji kesetaraan biner, dibandingkan dengan kesetaraan linguistik. Contoh string non-linguistik tersebut adalah nama file NTFS, variabel lingkungan, dan nama muteks, pipa bernama, atau mailslots. Kecuali untuk opsi ketidakpekaan huruf besar/kecil, fungsi ini mengacuhkan semua kesetaraan non-biner. Tidak seperti beberapa fungsi pengurutan lainnya, ia menguji semua titik kode untuk kesetaraan, termasuk yang tidak diberi bobot apa pun dalam skema pengurutan linguistik.

Semua pernyataan berikut berlaku untuk CompareStringOrdinal dalam perbandingan biner, tetapi tidak untuk CompareString, CompareStringEx, lstrcmp, atau lstrcmpi.

  • Urutan yang setara secara kanonis di Unicode, seperti LATIN SMALL LETTER A WITH RING ABOVE (U+00e5) dan LATIN SMALL LETTER A + COMBINING RING ABOVE (U+0061 U+030a), tidak sama meskipun tampak identik ("å").
  • String yang mirip secara kanonis di Unicode, seperti LATIN LETTER SMALL CAPITAL Y (U+028f) dan LATIN CAPITAL LETTER Y (U+0059), yang terlihat sangat mirip ("ʏ" dan "Y") dan hanya bervariasi oleh beberapa bobot kasus khusus dalam tabel linguistik, dianggap sebagai karakter yang sepenuhnya berbeda. Bahkan jika aplikasi mengatur bIgnoreCase ke TRUE, string ini dibandingkan sebagai berbeda.
  • Titik kode yang ditentukan tetapi tidak memiliki bobot pengurutan linguistik, seperti ZERO WIDTH JOINER (U+200d), diperlakukan sebagai memiliki bobot titik kode mereka.
  • Titik kode yang didefinisikan dalam versi Unicode yang lebih baru tetapi tidak memiliki bobot dalam tabel linguistik saat ini diperlakukan sebagai memiliki bobot titik kode mereka.
  • Poin kode yang tidak terdefinisi oleh Unicode diperlakukan sebagai memiliki bobot titik kode mereka.
  • Ketika aplikasi mengatur bIgnoreCase ke TRUE, kasus peta fungsi menggunakan tabel huruf besar sistem operasi, alih-alih informasi dalam tabel pengurutan linguistik. Dengan demikian pemetaan tidak bergantung pada lokal.

Untuk informasi selengkapnya tentang urutan yang setara secara kanonis di Unicode dan string yang sama secara kanonis di Unicode, lihat Menggunakan Normalisasi Unicode untuk Mewakili String.

Urutkan Titik Kode

Beberapa titik kode Unicode tidak memiliki bobot, misalnya, ZERO WIDTH NON JOINER, U+200c. Fungsi pengurutan sengaja mengevaluasi titik kode tanpa bobot yang setara karena tidak memiliki bobot dalam pengurutan. Pada Windows Vista dan yang lebih baru, aplikasi dapat mengurutkan titik kode ini dengan memanggil fungsi perbandingan string NLS, terutama CompareStringOrdinal, untuk evaluasi semua titik kode dalam arti harfiah biner, misalnya, dalam validasi kata sandi. Pada sistem operasi Vista pra-Windows, aplikasi harus menggunakan fungsi runtime C strcmp atau wcscmp.

Mengurutkan fungsi mengabaikan diakritik, seperti NON SPACING BREVE, U+0306, ketika aplikasi menentukan bendera hlink_NONSPACE. Demikian pula, fungsi-fungsi ini mengabaikan simbol, misalnya, EQUALS SIGN, U+003d , ketika bendera hlink_SYMBOLS ditentukan. Pada Windows Vista dan yang lebih baru, aplikasi memanggil CompareStringOrdinal untuk evaluasi diakritik dan titik kode simbol dalam arti harfiah biner. Pada sistem operasi Vista pra-Windows, aplikasi harus menggunakan strcmp atau wcscmp.

Beberapa titik kode, seperti 0xFFFF dan 0x058b, saat ini tidak ditetapkan di Unicode. Titik kode ini tidak menerima bobot apa pun dalam pengurutan, dan tidak boleh diteruskan ke fungsi pengurutan. Aplikasi harus menggunakan IsNLSDefinedString untuk mendeteksi titik kode non-Unicode dalam aliran data.

Catatan

Hasil IsNLSDefinedString mungkin bervariasi tergantung pada versi Unicode yang diteruskan jika karakter ditambahkan ke Unicode dalam versi yang lebih baru dan kemudian ditambahkan ke tabel pengurutan Windows. Untuk informasi selengkapnya, lihat Menggunakan Pengurutan Penerapan Versi.

 

Urutkan Digit sebagai Angka

Pada Windows 7 dan yang lebih baru, aplikasi dapat memanggil CompareString, CompareStringEx, LCMapString, atau LCMapStringEx menggunakan bendera SORT_DIGITSASNUMBERS. Bendera ini mendukung pengurutan yang memperlakukan digit sebagai angka, misalnya, pengurutan "2" sebelum "10".

Perhatikan bahwa penggunaan bendera ini tidak sesuai untuk digit heksadesimal seperti berikut ini.

01AF
1BCD
002A
12FA
AB1C
AB02
AB12

Dalam hal ini "angka" diurutkan secara berurutan, tetapi pengguna melihat daftar heksadesimal yang diurutkan dengan buruk.

String Peta

Aplikasi ini menggunakan fungsi LCMapString atau LCMapStringEx untuk memetakan string, jika LCMAP_SORTKEY tidak ditentukan. String yang dipetakan dihentikan null jika string sumber dihentikan null.

Saat mengubah antara huruf besar dan huruf kecil, fungsi tidak menjamin bahwa satu karakter akan memetakan ke satu karakter. Misalnya, bendera LCMAP_LOWERCASE dan LCMAP_UPPERCASE dapat memetakan German Sharp S ("ß") ke dirinya sendiri. Atau, bendera LCMAP_UPPERCASE dapat memetakan "ß" ke "SS" dan bendera LCMAP_LOWERCASE dapat memetakan "SS" ke "ß". Perilaku tergantung pada versi NLS.

Saat mengubah antara huruf besar dan huruf kecil, fungsi tidak sensitif terhadap konteks. Misalnya, sementara bendera LCMAP_UPPERCASE dengan benar memetakan sigma huruf kecil Yunani ("σ") dan sigma akhir huruf kecil Yunani ("ς") ke sigma huruf besar Yunani ("Σ"), bendera LCMAP_LOWERCASE selalu memetakan "Σ" ke "σ", tidak pernah "ς".

Secara default, fungsi memetakan huruf kecil "i" ke huruf besar "I", bahkan ketika parameter Lokal menentukan Turki atau Azerbaijani. Untuk mengambil alih perilaku ini untuk Turki atau Azerbaijani, aplikasi harus menentukan LCMAP_LINGUISTIC_CASING. Jika bendera ini ditentukan dengan lokal yang sesuai, "ı" (huruf kecil tanpa titik I) adalah bentuk huruf kecil "I" (huruf besar tanpa titik I) dan "i" (huruf kecil bertitik I) adalah bentuk huruf kecil dari "İ" (huruf besar bertitik I).

Jika bendera LCMAP_HIRAGANA ditentukan untuk memetakan karakter katakana ke karakter hiragana, dan LCMAP_FULLWIDTH tidak ditentukan, LCMapString atau LCMapStringEx hanya memetakan karakter lebar penuh ke hiragana. Dalam hal ini, setiap karakter katakana lebar setengah ditempatkan seperti dalam string tujuan, tanpa pemetaan ke hiragana. Aplikasi harus menentukan LCMAP_FULLWIDTH untuk memetakan karakter katakana lebar setengah ke hiragana. Alasan pembatasan ini adalah bahwa semua karakter hiragana adalah karakter lebar penuh.

Jika aplikasi perlu menghapus karakter dari string sumber, aplikasi dapat memanggil fungsi pemetaan dengan bendera NORM_IGNORESYMBOLS dan NORM_IGNORENONSPACE diatur, dan semua bendera lainnya dibersihkan. Jika aplikasi melakukan ini dengan string sumber yang tidak dihentikan null, fungsi dapat mengembalikan string kosong dan tidak mengembalikan kesalahan.

Buat Tombol Sortir

Ketika aplikasi menentukan LCMAP_SORTKEY, LCMapString atau LCMapStringEx menghasilkan kunci pengurutan, array biner nilai byte. Kunci pengurutan bukan string benar dan nilainya mewakili perilaku pengurutan string sumber, tetapi bukan nilai tampilan yang bermakna.

Catatan

Fungsi ini mengabaikan kashida Arab selama pembuatan kunci pengurutan. Jika aplikasi memanggil fungsi untuk membuat kunci pengurutan untuk string yang berisi kashida Arab, fungsi tidak membuat nilai kunci pengurutan.

 

Kunci pengurutan dapat berisi jumlah byte ganjil. Bendera LCMAP_BYTEREV hanya membalikkan jumlah byte yang merata. Byte terakhir (posisi ganjil) di kunci pengurutan tidak dibalik. Jika byte 0x00 penghentian adalah byte yang diposisikan ganjil, byte tersebut tetap menjadi byte terakhir dalam kunci pengurutan. Jika penghentian 0x00 byte adalah byte yang diposisikan secara merata, itu bertukar posisi dengan byte yang mendahuluinya.

Saat menghasilkan kunci pengurutan, fungsi memperlakukan tanda hubung dan apostrof secara berbeda dari simbol tanda baca lainnya, sehingga kata-kata seperti "coop" dan "co-op" tetap bersama dalam daftar. Semua simbol tanda baca selain tanda hubung dan apostrof mengurutkan sebelum karakter alfanumerik. Aplikasi dapat mengubah perilaku ini dengan mengatur bendera SORT_STRINGSORT, seperti yang dijelaskan dalam Mengurutkan Fungsi.

Saat digunakan dalam memcmp, kunci sortir menghasilkan urutan yang sama seperti ketika string sumber digunakan dalam CompareString atau CompareStringEx. Fungsi memcmp harus digunakan alih-alih strcmp, karena kunci sortir dapat memiliki byte null yang disematkan.

Gunakan Penerapan Versi Pengurutan

Tabel pengurutan memiliki dua angka yang mengidentifikasi versinya: versi yang ditentukan dan versi NLS. Kedua angka tersebut adalah nilai DWORD, terdiri dari nilai utama dan nilai minor. Byte pertama dari nilai dicadangkan, dua byte berikutnya mewakili versi utama, dan byte terakhir mewakili versi minor. Dalam istilah heksadesimal, polanya adalah 0xRRMMMMmm, di mana R sama dengan Reserved, M sama dengan mayor, dan m sama dengan minor. Misalnya, versi utama 3 dengan versi minor 4 direpresentasikan sebagai 0x304.

Versi yang ditentukan mengidentifikasi repertoar titik kode dan sama untuk semua lokal. Kenaikan versi utama untuk menunjukkan perubahan pada titik kode yang ada. Kenaikan versi minor untuk menunjukkan bahwa titik kode telah ditambahkan, tetapi tidak ada titik kode yang sudah ada sebelumnya yang diubah.

Versi NLS khusus untuk pengidentifikasi lokal atau nama lokal, dan melacak perubahan pada bobot titik kode untuk lokal yang terpengaruh. Versi utama bertambah ketika bobot diubah untuk titik kode yang sudah dapat diurutkan. Versi minor bertambah ketika titik kode baru diberi bobot, tetapi semua bobot titik kode lain yang sebelumnya dapat diurutkan tetap tidak berubah.

Catatan

Untuk versi utama, satu atau beberapa titik kode diubah sehingga aplikasi harus mengindeks ulang semua data agar perbandingan valid. Untuk versi minor, tidak ada yang dipindahkan tetapi titik kode ditambahkan. Untuk jenis versi ini, aplikasi hanya harus mengindeks ulang string dengan nilai yang sebelumnya tidak dapat diurai.

 

Penting

Versi utama telah diubah dalam Windows 8. Data yang dibuat di bawah versi Windows yang lebih lama harus diindeks ulang.

 

Versi yang ditentukan dan NLS berlaku untuk titik kode yang dapat diurutkan yang diambil menggunakan fungsi LCMapString atau LCMapStringEx dengan bendera LCMAP_SORTKEY, dan juga digunakan oleh fungsi CompareString, CompareStringEx, FindNLSString, dan FindNLSStringEx . Jika satu atau beberapa titik kode dalam string tidak dapat diurutkan, maka fungsi IsNLSDefinedString mengembalikan FALSE ketika string tersebut diteruskan ke dalamnya sebagai parameter.

Aplikasi ini dapat memanggil GetNLSVersion atau GetNLSVersionEx untuk mengambil versi yang ditentukan dan versi NLS untuk tabel pengurutan.

Mengindeks Database

Untuk alasan performa, aplikasi harus mengikuti prosedur ini saat mengindeks database.

Untuk mengindeks database dengan benar

  1. Untuk setiap fungsi, simpan versi NLS, kunci pengurutan versi tersebut, dan indikasi pengurutan untuk setiap string yang diindeks.
  2. Saat versi minor berangsur-angsur, indeks ulang string yang sebelumnya tidak dapat diurai. String yang terpengaruh dalam pembaruan ini harus terbatas pada string yang sebelumnya telah dikembalikan oleh IsNLSDefinedStringFALSE.
  3. Saat versi utama bertambah, indeks ulang semua string karena bobot yang diperbarui dapat mengubah perilaku string apa pun. Rilis versi utama sangat jarang.

Masalah pengindeksan database dapat muncul karena alasan berikut:

  • Sistem operasi yang lebih baru dapat menentukan titik kode yang tidak terdefinisi untuk sistem operasi sebelumnya, sehingga mengubah pengurutan.
  • Titik kode dapat memiliki bobot pengurutan yang berbeda dalam sistem operasi yang berbeda, karena koreksi dalam dukungan bahasa.

Untuk meminimalkan kebutuhan untuk mengindeks ulang database dalam keadaan ini, aplikasi dapat menggunakan IsNLSDefinedString untuk membedakan yang ditentukan dari string yang tidak terdefinisi sehingga aplikasi dapat menolak string dengan titik kode yang tidak terdefinisi. Penggunaan GetNLSVersion atau GetNLSVersionEx memungkinkan aplikasi menentukan apakah perubahan NLS memengaruhi lokal yang digunakan untuk tabel indeks tertentu. Jika perubahan tidak berpengaruh pada lokal, aplikasi tidak perlu mengindeks ulang tabel.

Contoh

Tabel berikut mengilustrasikan efek bendera tertentu yang digunakan dengan fungsi pengurutan. Dalam setiap kasus, pemilihan bendera menentukan apakah dua karakter yang berbeda dianggap sama untuk tujuan pengurutan.

Karakter 1 Karakter 2 Default NORM_IGNOREWIDTH NORM_IGNOREKANA NORM_IGNOREWIDTH| NORMIGNOREKANA
"あ"
U+3042 HIRAGANA LETTER A
"ガ"
U+30A2 KATAKANA LETTER A
Tidak sama Tidak sama Equal Equal
"オ"
U+FF75 HALFWIDTH KATAKANA LETTER O
"オ"
U+30AA KATAKANA LETTER O
Tidak sama Equal Tidak sama Equal
"B"
U+FF22 FULLWIDTH LATIN CAPITAL LETTER B
"B"
U+0042 HURUF LATIN KAPITAL B
Tidak sama Equal Tidak sama Equal

 

Menggunakan Dukungan Bahasa Nasional

Penyortiran

Mengambil dan Mengatur Informasi Lokal

Menggunakan Normalisasi Unicode untuk Mewakili String

Pertimbangan Keamanan: Fitur Internasional

CompareString

CompareStringEx

CompareStringOrdinal

FindNLSString

FindNLSStringEx

LCMapString

LCMapStringEx