Condividi tramite


Gestione dell'ordinamento nelle applicazioni

Alcune applicazioni, ad esempio Microsoft Active Directory, Microsoft Exchange e Microsoft Access, mantengono un database ordinabile di stringhe locali e di lingua indicizzate per nome (stringa UTF-16) e i relativi pesi di ordinamento associati.

l'ordinamento è in genere intuitivo per gli utenti nel proprio contesto locale. Tuttavia, può essere non intuitivo per gli sviluppatori di applicazioni. Questo argomento illustra le considerazioni relative alla gestione dell'ordinamento nelle applicazioni. L'ordinamento può essere linguistico o ordinale (non linguistico).

Funzioni di ordinamento

È possibile usare un'ampia gamma di funzioni di ordinamento nelle applicazioni:

In genere le funzioni di ordinamento valutano i caratteri delle stringhe in base al carattere. Tuttavia, molte lingue hanno elementi a più caratteri, ad esempio la coppia di due caratteri "CH" in spagnolo tradizionale. CompareString e CompareStringEx usare l'identificatore o il nome delle impostazioni locali forniti dall'applicazione per identificare più elementi di caratteri. Al contrario, lstrcmpe lstrcmpi usano le impostazioni locali dell'utente.

Un altro esempio è il vietnamita, che contiene molti elementi a due caratteri, ad esempio le forme maiuscole, iniziali maiuscole e minuscole valide di "GI", che sono rispettivamente "GI", "Gi" e "gi". Una di queste forme viene considerata come un singolo elemento di ordinamento e, se le maiuscole e le minuscole vengono ignorate, viene considerata uguale. Tuttavia, poiché "gI" non è valido come singolo elemento, CompareString, CompareStringEx, lstrcmpe lstrcmpi considerare "gI" come due elementi separati.

Le funzioni CompareString, CompareStringEx, lstrcmp, lstrcmpi, LCMapString, LCMapStringEx, FindNLSStringe FindNLSStringEx per impostazione predefinita utilizzano una tecnica di ordinamento di parole. Per questo tipo di ordinamento, tutti i segni di punteggiatura e altri caratteri non alfanumerici, ad eccezione del trattino e dell'apostrofo, vengono prima di qualsiasi carattere alfanumerico. Il trattino e l'apostrofo vengono trattati in modo diverso dagli altri caratteri non alfanumerici per garantire che le parole come "coop" e "co-op" rimangano insieme in un elenco ordinato.

Anziché un ordinamento di parole, l'applicazione può richiedere una tecnica di ordinamento stringa dalle funzioni di ordinamento specificando il flag SORT_STRINGSORT. Un ordinamento di stringa tratta il trattino e l'apostrofo esattamente come qualsiasi altro carattere non alfanumerico. Le posizioni nella sequenza di ordinamento sono prima dei caratteri alfanumerici.

Nella tabella seguente vengono confrontati i risultati di un ordinamento di parole con i risultati di un ordinamento di stringa.

Classificazione di parole Ordinamento stringhe
biglietto di Bill
Bollette alloggio
di Bill Bollette
non può Non
non posso non può
Non non posso
con co-op
Coop con
co-op Coop

 

Ordinare le stringhe in modo linguistico

Le funzioni CompareString e CompareStringEx verificano l'uguaglianza linguistica. Le applicazioni devono usare queste funzioni con le impostazioni locali corrette per l'ordinamento delle stringhe in modo linguistico.

Nota

Per la compatibilità con Unicode, un'applicazione deve preferire CompareStringEx o la versione Unicode di CompareString. Un altro motivo per cui si preferisce CompareStringEx è che Microsoft sta eseguendo la migrazione verso l'uso dei nomi delle impostazioni locali anziché degli identificatori delle impostazioni locali per le nuove impostazioni locali, per motivi di interoperabilità. Qualsiasi applicazione eseguita solo in Windows Vista e versioni successive deve usare CompareStringEx.

 

Un altro modo per testare l'uguaglianza linguistica consiste nell'usare lstrcmp o lstrcmpi, che usano sempre un ordinamento di parole. La funzione lstrcmpi chiama CompareString con il flag NORM_IGNORECASE, mentre lstrcmp chiama senza tale flag. Per una panoramica dell'uso delle funzioni wrapper, vedere Strings.

Le funzioni recuperano i risultati linguistici appropriati per tutte le impostazioni locali. Le aspettative degli utenti per impostazioni locali diverse possono differire in modo significativo nel comportamento di ordinamento, come illustrato negli esempi seguenti.

  • Molte lingue considerano la legatura ae (æ) equivalente alle lettere ae. Tuttavia, islandese (Islanda) lo considera una lettera separata e la inserisce dopo Z nella sequenza di ordinamento.
  • L'anello A (Å) ordina normalmente con semplicemente una differenza diacritica da A. Tuttavia, svedese (Svezia) posiziona l'anello A dopo Z nella sequenza di ordinamento.

Le funzioni tentano di verificare rigorosamente che i punti di codice definiti nello standard Unicode siano canonicamente uguali a una stringa di punti di codice equivalenti. Ad esempio, il punto di codice che rappresenta una "u" minuscola con dieresis (ü) è canonicamente uguale a un "u" minuscolo combinato con la dieresis ( ̈). Si noti, tuttavia, che l'equivalenza canonica non è sempre possibile.

Poiché quasi tutti i dati immessi usando le tastiere di Windows e gli editor di metodi di input (IMEs) sono conformi alla normalizzazione in forma C definita nello standard Unicode, convertire i dati in ingresso da altre piattaforme usando le funzioni di normalizzazione Unicode NLS fornisce risultati più coerenti, soprattutto per le località che usano lo script tibetano o lo script Hangul per Hangul moderno. Per altre informazioni sul supporto della normalizzazione Unicode in Windows Vista e versioni successive, vedere Uso della normalizzazione Unicode per rappresentare stringhe.

Quando il confronto tra stringhe segue la preferenza di lingua dell'utente, ad esempio, quando si ordinano elementi per un controllo ListView ordinato, l'applicazione può eseguire una delle operazioni seguenti:

  • Chiamare lstrcmp o lstrcmpi con le impostazioni locali dell'utente.
  • Chiamare CompareString o CompareStringEx per definire le impostazioni locali per il confronto, passare flag aggiuntivi, incorporare caratteri Null o passare lunghezze esplicite per trovare le corrispondenze tra le parti di una stringa.

Quando i risultati del confronto devono essere coerenti indipendentemente dalle impostazioni locali, ad esempio quando si confrontano i dati recuperati con un elenco predefinito o un valore interno, l'applicazione deve usare CompareString o CompareStringEx con il parametro delle impostazioni locali impostato su LOCALE_INVARIANT. Per CompareString, una delle chiamate seguenti corrisponderà anche se mystr è "INLAP". In questo caso, una chiamata sensibile alle impostazioni locali a lstrcmpi avrà esito negativo se le impostazioni locali correnti sono vietnamite.

In Windows XP:

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

Nei sistemi operativi precedenti:

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

Ordina stringhe in modo ordinale

Per l'ordinamento ordinale (non linguistico), le applicazioni devono usare sempre la funzioneCompareStringOrdinal.

Nota

Questa funzione è disponibile solo per Windows Vista e versioni successive.

 

CompareStringOrdinal confronta due stringhe di Unicode per verificare l'uguaglianza binaria, anziché l'uguaglianza linguistica. Esempi di stringhe non linguistiche sono nomi di file NTFS, variabili di ambiente e nomi di mutex, named pipe o mailslot. Ad eccezione dell'opzione di distinzione tra maiuscole e minuscole, questa funzione ignora tutte le equivalenze non binarie. A differenza di altre funzioni di ordinamento, testa tutti i punti di codice per verificarne l'uguaglianza, inclusi quelli che non hanno alcun peso negli schemi di ordinamento linguistico.

Tutte le dichiarazioni seguenti si applicano a CompareStringOrdinal nei confronti binari, ma non a CompareString, CompareStringEx, lstrcmpo lstrcmpi.

  • Sequenze equivalenti canoniche in Unicode, ad esempio LATIN SMALL LETTER A WITH RING ABOVE (U+00e5) e LATIN SMALL LETTER A + COMBINING RING ABOVE (U+0061 U+030a), non sono uguali anche se appaiono identici ("å").
  • Stringhe simili a livello canonico in Unicode, come LATIN LETTER SMALL CAPITAL Y (U+028f) e LATIN CAPITAL LETTER Y (U+0059), che sembrano molto simili ("ʏ" e "Y") e variano solo per alcuni pesi di maiuscole speciali nelle tabelle linguistiche, sono considerate caratteri completamente diversi. Anche se l'applicazione imposta bIgnoreCase su TRUE, queste stringhe risultano diverse.
  • I punti di codice che sono definiti ma non hanno peso di ordinamento linguistico, come ad esempio ZERO WIDTH JOINER (U+200d), vengono trattati come se avessero i loro pesi di punti di codice.
  • I punti codice definiti nelle versioni successive di Unicode che non hanno peso nelle attuali tabelle linguistiche sono trattati come se avessero il peso dei loro punti codice.
  • I punti di codice non definiti da Unicode vengono trattati come se avessero i loro pesi di codice.
  • Quando l'applicazione imposta bIgnoreCase su TRUE, la funzione mappa le maiuscole usando la tabella di maiuscolizzazione del sistema operativo anziché utilizzare le informazioni contenute nelle tabelle di ordinamento linguistico. Il mapping è quindi indipendente dalle impostazioni locali.

Per altre informazioni sulle sequenze canonicamente equivalenti in Unicode e sulle stringhe canonicamente simili in Unicode, vedere Uso della normalizzazione Unicode per rappresentare stringhe.

Ordina punti di codice

Alcuni punti di codice Unicode non hanno peso, ad esempio ZERO WIDTH NON JOINER, U+200c. Le funzioni di ordinamento valutano intenzionalmente i punti di codice senza peso come equivalenti perché non hanno peso nell'ordinamento. In Windows Vista e versioni successive, l'applicazione può ordinare questi punti di codice chiamando le funzioni di confronto delle stringhe NLS, in particolare CompareStringOrdinal, per la valutazione di tutti i punti di codice in un senso letterale, binario, ad esempio, nella convalida della password. Nei sistemi operativi pre-Windows Vista, l'applicazione deve usare la funzione di runtime C strcmp o wcscmp.

Le funzioni di ordinamento ignorano i segni diacritici, ad esempio NON SPACING BREVE, U+0306, quando l'applicazione specifica il flag hlink_NONSPACE. Analogamente, queste funzioni ignorano i simboli, ad esempio EQUALS SIGN, U+003d , quando viene specificato il flag hlink_SYMBOLS. In Windows Vista e versioni successive l'applicazione chiama CompareStringOrdinal per la valutazione dei segni diacritici e dei punti di codice dei simboli in un senso binario letterale. Nei sistemi operativi pre-Windows Vista l'applicazione deve usare strcmp o wcscmp.

Alcuni punti di codice, ad esempio 0xFFFF e 0x058b, non sono attualmente assegnati in Unicode. Questi punti di codice non ricevono alcun peso nell'ordinamento e non devono mai essere passati alle funzioni di ordinamento. L'applicazione deve usare IsNLSDefinedString per rilevare punti di codice non Unicode in un flusso di dati.

Nota

I risultati di IsNLSDefinedString possono variare a seconda della versione Unicode passata se un carattere viene aggiunto a Unicode in una versione successiva e successivamente viene aggiunto alle tabelle di ordinamento di Windows. Per altre informazioni, vedere Usare il controllo delle versioni di ordinamento.

 

Ordina cifre come numeri

In Windows 7 e versioni successive l'applicazione può chiamare CompareString, CompareStringEx, LCMapStringo LCMapStringEx usando il flag SORT_DIGITSASNUMBERS. Questo flag supporta l'ordinamento che considera le cifre come numeri, ad esempio l'ordinamento di "2" prima di "10".

Si noti che l'uso di questo flag non è appropriato per le cifre esadecimali, ad esempio le seguenti.

01AF
1BCD
002A
12FA
AB1C
AB02
AB12

In questo caso i "numeri" vengono ordinati in ordine, ma l'utente percepisce un elenco esadecimale ordinato in modo non corretto.

Mappa di stringhe

L'applicazione usa la funzioneLCMapStringo LCMapStringEx per eseguire il mapping delle stringhe, se non viene specificato LCMAP_SORTKEY. Una stringa mappata viene terminata con null se la stringa di origine è con terminazione Null.

Quando si trasforma tra maiuscole e minuscole, la funzione non garantisce che un singolo carattere venga mappato a un singolo carattere. Ad esempio, i flag LCMAP_LOWERCASE e LCMAP_UPPERCASE possono mappare il tedesco Sharp S ("ß") a se stesso. In alternativa, il flag LCMAP_UPPERCASE può mappare "ß" a "SS" e il flag LCMAP_LOWERCASE può mappare "SS" a "ß". Il comportamento dipende dalla versione NLS.

Quando si trasforma tra maiuscole e minuscole, la funzione non è sensibile al contesto. Ad esempio, mentre il flag LCMAP_UPPERCASE esegue correttamente il mapping di sigma minuscolo greco ("σ") e sigma minuscolo finale greco ("ς") al sigma maiuscolo greco ("Σ"), il flag LCMAP_LOWERCASE mappa sempre "Σ" a "σ", mai a "ς".

Per impostazione predefinita, la funzione mappa la "i" minuscola alla "I" maiuscola, anche quando il parametro Locale specifica turco o azerbaigiano. Per eseguire l'override di questo comportamento per turco o azero, l'applicazione deve specificare LCMAP_LINGUISTIC_CASING. Se questo flag viene specificato con le impostazioni locali appropriate, "ı" (i minuscolo senza punto) è la forma minuscola di "I" (I maiuscolo senza punto) e "i" (i minuscolo con punto) è la forma minuscola di "İ" (I maiuscolo con punto).

Se il flag LCMAP_HIRAGANA viene specificato per eseguire il mapping dei caratteri katakana ai caratteri hiragana e non viene specificato LCMAP_FULLWIDTH, LCMapString o LCMapStringEx esegue il mapping dei caratteri a larghezza intera solo a hiragana. In questo caso, qualsiasi carattere katakana a larghezza ridotta viene inserito come nella stringa di destinazione, senza mappatura a hiragana. L'applicazione deve specificare LCMAP_FULLWIDTH per eseguire il mapping dei caratteri katakana a metà larghezza in hiragana. Il motivo di questa restrizione è che tutti i caratteri hiragana sono caratteri a larghezza intera.

Se l'applicazione deve rimuovere caratteri dalla stringa di origine, può chiamare la funzione di mapping con i flag NORM_IGNORESYMBOLS e NORM_IGNORENONSPACE impostati e tutti gli altri flag cancellati. Se l'applicazione esegue questa operazione con una stringa di origine non con terminazione Null, è possibile che la funzione restituisca una stringa vuota e non restituisca un errore.

Creare chiavi di ordinamento

Quando l'applicazione specifica LCMAP_SORTKEY, LCMapString o LCMapStringEx genera una chiave di ordinamento, una matrice binaria di valori di byte. La chiave di ordinamento non è una stringa vera e i relativi valori rappresentano il comportamento di ordinamento della stringa di origine, ma non sono valori di visualizzazione significativi.

Nota

La funzione ignora la kashida araba durante la generazione di una chiave di ordinamento. Se un'applicazione chiama la funzione per creare una chiave di ordinamento per una stringa contenente un kashida arabo, la funzione non crea alcun valore di chiave di ordinamento.

 

La chiave di ordinamento può contenere un numero dispari di byte. Il flag 'LCMAP_BYTEREV' inverte solo un numero pari di byte. L'ultimo byte (in posizione dispari) nella chiave di ordinamento non viene invertito. Se il byte di terminazione 0x00 è in posizione dispari, rimane l'ultimo byte nella chiave di ordinamento. Se il byte di terminazione 0x00 è in posizione pari, scambia posizione con il byte che lo precede.

Quando si genera la chiave di ordinamento, la funzione tratta il trattino e l'apostrofo in modo diverso da altri simboli di punteggiatura, in modo che le parole come "coop" e "co-op" rimangano insieme in un elenco. Tutti i simboli di punteggiatura diversi dal trattino e dall'apostrofo ordinano prima dei caratteri alfanumerici. L'applicazione può modificare questo comportamento impostando il flag SORT_STRINGSORT, come descritto in Funzioni di ordinamento.

Se usato in memcmp, la chiave di ordinamento produce lo stesso ordine di quando la stringa di origine viene usata in CompareString o CompareStringEx. La funzione memcmp deve essere usata invece di strcmp, perché la chiave di ordinamento può avere byte Null incorporati.

Usare il controllo delle versioni di ordinamento

Una tabella di ordinamento include due numeri che ne identificano la versione: la versione definita e la versione NLS. Entrambi i numeri sono valori DWORD, composti da un valore principale e da un valore secondario. Il primo byte di un valore è riservato, i due byte successivi rappresentano la versione principale e l'ultimo byte rappresenta la versione secondaria. In termini esadecimali, il modello è 0xRRMMMMmm, dove R è uguale a Reserved, M uguale a major e m è minore. Ad esempio, una versione principale di 3 con una versione secondaria di 4 è rappresentata come 0x304.

La versione definita identifica il repertorio dei punti di codice ed è la stessa per tutte le impostazioni locali. L'incremento della versione principale indica modifiche ai punti di codice esistenti. L'incremento di versione secondaria indica che sono stati aggiunti punti di codice, ma che non sono stati modificati quelli esistenti.

La versione NLS è specifica per un identificatore locale o per un nome locale e monitora le modifiche ai pesi dei punti di codice per il locale interessato. La versione principale viene incrementata quando vengono modificati i pesi per i punti di codice già ordinabili. La versione secondaria aumenta quando vengono assegnati nuovi punti di codice, ma tutti gli altri pesi dei punti di codice ordinabili in precedenza rimangono invariati.

Nota

Per una versione principale, uno o più punti di codice vengono modificati in modo che l'applicazione debba ri-indicizzare tutti i dati affinché i confronti siano validi. Per una versione secondaria, non viene spostato alcun elemento, ma vengono aggiunti punti di codice. Per questo tipo di versione, l'applicazione deve ri-indicizzare le stringhe con valori precedentemente non ordinabili.

 

Importante

La versione principale è stata modificata in Windows 8. I dati creati nelle versioni precedenti di Windows devono essere ri indicizzati.

 

Entrambe le versioni, quella definita e quella NLS, si applicano ai punti di codice ordinabili recuperati usando la funzione LCMapString o la funzione LCMapStringEx con il flag LCMAP_SORTKEY, e utilizzati anche dalle funzioni CompareString, CompareStringEx, FindNLSStringe le funzioni FindNLSStringEx. Se uno o più punti di codice in una stringa non sono ordinabili, la funzione IsNLSDefinedString restituisce FALSE quando tale stringa viene passata come parametro.

L'applicazione può chiamare GetNLSVersion o GetNLSVersionEx per recuperare sia la versione definita che la versione NLS per una tabella di ordinamento.

Indicizzare il database

Per motivi di prestazioni, l'applicazione deve seguire questa procedura durante l'indicizzazione del database.

Per indicizzare correttamente il database

  1. Per ogni funzione, archiviare la versione NLS, le chiavi di ordinamento di tale versione e un'indicazione di ordinabilità per ogni stringa indicizzata.
  2. Quando la versione secondaria viene incrementata, reindicizzare le stringhe precedentemente non ordinate. Le stringhe interessate in questo aggiornamento devono essere limitate a quelle per cui IsNLSDefinedString ha precedentemente restituito FALSE.
  3. Quando la versione principale viene incrementata, ri-indicizzare tutte le stringhe perché i pesi aggiornati potrebbero modificare il comportamento di qualsiasi stringa. Le versioni principali sono molto rare.

I problemi di indicizzazione del database possono verificarsi per i motivi seguenti:

  • Un sistema operativo successivo può definire punti di codice non definiti per un sistema operativo precedente, modificando così l'ordinamento.
  • I punti di codice possono avere pesi di ordinamento diversi in sistemi operativi diversi, a causa delle correzioni nel supporto del linguaggio.

Per ridurre al minimo la necessità di reindicizzare il database in queste circostanze, l'applicazione può usare IsNLSDefinedString per distinguere le stringhe definite da stringhe non definite in modo che l'applicazione possa rifiutare stringhe con punti di codice non definiti. L'uso di GetNLSVersion o GetNLSVersionEx consente all'applicazione di determinare se una modifica NLS influisce sulle impostazioni locali usate per una tabella di indice specifica. Se la modifica non ha alcun effetto sulle impostazioni locali, l'applicazione non deve reindicizzare nuovamente la tabella.

Esempi

Nella tabella seguente vengono illustrati gli effetti di determinati flag usati con le funzioni di ordinamento. In ogni caso, la selezione dei flag determina se due caratteri diversi vengono considerati uguali a scopo di ordinamento.

Carattere 1 Carattere 2 Predefinito NORM_IGNOREWIDTH NORM_IGNOREKANA NORM_IGNOREWIDTH| NORMIGNOREKANA
"あ"
U+3042 HIRAGANA LETTERA A
"ガ"
U+30A2 KATAKANA LETTERA A
Ineguale Ineguale Uguale Uguale
"オ"
U+FF75 LETTERA KATAKANA A MEZZA LARGHEZZA O
"オ"
U+30AA LETTERA O KATAKANA
Ineguale Uguale Ineguale Uguale
"B"
U+FF22 FULLWIDTH LETTERA LATINO MAIUSCOLA B
"B"
U+0042 LETTERA MAIUSCOLA LATINA B
Ineguale Uguale Ineguale Uguale

 

Utilizzo del supporto per la lingua nazionale

Ordinamento

Recupero e impostazione delle informazioni locali

uso della normalizzazione Unicode per rappresentare le stringhe

Considerazioni sulla Sicurezza: Funzionalità Internazionali

CompareString

CompareStringEx

CompareStringOrdinal

FindNLSString

FindNLSStringEx

LCMapString

LCMapStringEx