È possibile scrivere una funzione di inversione della stringa generalizzata che funzioni per tutte le localizzazioni e i tipi di stringa?

16

Stavo solo guardando la presentazione di Jon Skeet (con Tony the Pony) da Dev-Days.

Anche se "scrivere una funzione di inversione delle stringhe" è un'intervista di codifica 101 - Non sono sicuro che sia effettivamente possibile scrivere una funzione di inversione generale delle stringhe, certamente non quella che funziona in tutte le localizzazioni e tutti i tipi di stringa.

Oltre a rilevare se la stringa di input è ascii, UTF8, UTF16 (lunghezza fissa e variabile)
C'è il codice "applica accento al prossimo carattere" (U + 0301) che Jon ha evidenziato. Poi ci sono legature che possono o non possono essere visualizzate, o codificate come caratteri doppi.

Sembra che "invertire una stringa" sia in realtà uno dei compiti più difficili dell'informatica!

    
posta Martin Beckett 26.07.2011 - 19:28
fonte

3 risposte

5

Sì. Se otteniamo una stringa possiamo invertire definitivamente ogni carattere.

Il problema, come sottolinea Jon, è che l'inversione ha senso e si conforma alle regole linguistiche e culturali, ai caratteri e alla codifica. L'acqua diventa torbida più a fondo vai.

Se stai facendo qualsiasi tipo di manipolazione delle stringhe in C #, usa la cultura Invariant quando scrivi e leggi, in questo modo puoi manipolarli in sicurezza. Altrimenti, prepararsi per il fallimento della chiamata di assistenza turca.

ToUpper () sembra così innocente, ma è un fallimento epico che aspetta di succedere.

    
risposta data 26.07.2011 - 20:09
fonte
2

In generale, quando viene posta questa domanda, si presuppone che US-ASCII. Il punto non è tanto quello di testare la conoscenza della persona di Unicode (anche se questo sarebbe un seguito interessante), per vedere se capiscono come funzionano i puntatori. Un numero sorprendente di persone non può fare questo tipo di aritmetica puntatore.

    
risposta data 26.07.2011 - 20:03
fonte
1

Come domanda dell'intervista, di solito viene chiesto solo i bit tecnici di fare uno scambio sul posto di elementi a 8 bit per invertire il loro ordine (indipendentemente da quali caratteri potrebbero effettivamente rappresentare).

Allo stesso tempo, specialmente se stai intervistando una persona relativamente anziana, potresti almeno sperare di sentire alcune domande sulla specifica e sulla forma esatta dell'input. Anche se li rimandi al semplice caso di scambiare semplicemente articoli a 8 bit, sapere se pensano in termini più ampi di quello che potrebbe essere prezioso.

Se hai a che fare con una vasta gamma di input, devi semplicemente pensare in termini di "stack", un po 'come uno stack di rete. Devi costruire il tuo software in un numero di livelli, ognuno dei quali applica un insieme di trasformazioni abbastanza specifico in un ordine specifico. Ciò ti consente di mantenere ogni parte della trasformazione abbastanza semplice da poterla tenere sotto controllo e avere una ragionevole possibilità di soddisfare i suoi requisiti.

Illustrerò una possibilità che ho trovato almeno in qualche modo realizzabile. Sono il primo ad ammettere che potrebbero esserci altri che hanno idee migliori. Almeno per me, questo mi sembra un po 'come l'ingegneria a forza bruta, con poca vera eleganza.

Normalmente si desidera iniziare convertendo qualsiasi altra rappresentazione in UCS-4 (alias UTF-32). Per questo, generalmente preferisce affidarsi all'input dell'utente piuttosto che tentare di capirlo da solo. In alcuni casi, puoi essere sicuro che una particolare sequenza di ottetti non segua le regole di un particolare schema di codifica, ma puoi raramente (se mai) essere sicuro che segua un particolare schema di codifica.

Il prossimo passo è facoltativo. È possibile normalizzare l'input in uno dei quattro moduli di normalizzazione Unicode. In questo caso, probabilmente vorresti applicare la trasformazione "NFKC": decomposizione della compatibilità seguita dalla composizione canonica. Questo (dove possibile) converte combinando forme diacritiche (come l'U + 301 che Jon menziona) in punti di codice singolo (ad esempio, una "A" con un "U + 301" verrebbe convertita in "Capitale latina A con acuto" , U + 00C1).

Passi quindi attraverso tutti i personaggi dall'inizio alla fine, spezzando la stringa in caratteri reali e se ci sono (ancora) combinando segni diacritici, mantenendoli con i caratteri che modificano. Il risultato di ciò sarà in genere un indice dei caratteri effettivi nella stringa, ad esempio la posizione e la lunghezza di ciascuno.

È l'ordine inverso di quei caratteri completi, in genere utilizzando l'indice creato nel passaggio precedente.

Quindi (di nuovo, facoltativamente) si applica un altro processo di normalizzazione Unicode, come NFD (decomposizione canonica). Ciò trasformerà il suddetto "latino A acuto" in due punti di codice: una "capitale latina A" e una "combinazione acuta". Se all'inizio il tuo input contiene un U + 00C1, tuttavia converte anche quello in due code point.

Quindi codifica la sequenza di punti codice UCS-4 nella codifica desiderata (UTF-8, UTF-16, ecc.)

Si noti che i passaggi di normalizzazione Unicode possono / cambieranno il numero di punti di codice necessari per memorizzare la stringa, quindi se li si include, non è più possibile pianificare l'adattamento della stringa di risultati nella memoria originale. Ovviamente, i punti codice risultanti potrebbero non corrispondere direttamente ai punti del codice di input.

    
risposta data 26.07.2011 - 20:50
fonte

Leggi altre domande sui tag