È possibile scrivere una funzione di inversione di 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) di Dev-Days.

Sebbene "scrivere una funzione di inversione di stringa" stia codificando l'intervista 101 - Non sono sicuro che sia effettivamente possibile scrivere una funzione di inversione di stringa generale, certamente non una che funzioni 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) ecc.
C'è il codice 'applica l'accento al carattere successivo' (U + 0301) che Jon ha evidenziato. Quindi ci sono legature che possono essere visualizzate o meno o codificate come caratteri doppi.

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


No, prova a fermare il problema per qualcosa che è un passo in difficoltà ma più semplice da spiegare alla gente.
JB King,

Essendo una domanda non soggettiva e tecnica, mi permetto di dire che si adatterebbe meglio su StackOverflow (per favore non ripubblicarlo lì, verrà automatizzato se un numero sufficiente di persone vota per chiuderlo qui).
Péter Török,

1
Dipende dal linguaggio di programmazione. Ad esempio in Ruby è facile come "stressed".reverse: p
Marcelo,

Grande domanda filosofica. FWIW, StringBuilder di Java ottiene i surrogati giusti ma non combinatori
kdgregory,

2
"Invertire questa stringa in posizione utilizzando Java" è una buona domanda trabocchetto. :)
Scott C Wilson,

Risposte:


5

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

Il problema, come sottolinea Jon, è che l'inversione ha senso e si conforma alle regole del linguaggio e della cultura, ai caratteri e alla codifica. L'acqua diventa torbida più in profondità si va.

Se stai eseguendo qualsiasi tipo di manipolazione delle stringhe in C # usa la cultura Invariant durante la scrittura e la lettura, in questo modo puoi manipolarli in sicurezza. In caso contrario, prepararsi per l'errore di chiamata di supporto turco.

ToUpper () sembra così innocente, ma è un fallimento epico in attesa di accadere.


2
L'altra domanda è: a cosa serve mai chiunque usi l'inversione di stringa (oltre all'intervista Q)? Ne ho sempre avuto bisogno solo per la manipolazione del buffer di basso livello delle porte I / O - e anche allora quasi mai con le stringhe
Martin Beckett,

@Martin - Concordato. Forse per un programma di lingua inglese per trovare palidromi? Non credo di averlo usato oltre a risolvere una domanda del quiz.
Jon Raynor,

@Martin true. Penso che sia fatto solo ironicamente. :)
Scott C Wilson,

2

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


2
"Come potrebbe fallire con Unicode?" è una buona domanda di follow-up
Martin Beckett, il

Buono ma forse un po 'avanzato - dopo tutto, "invertire questa stringa sul posto" è una domanda di intervista entry level. Probabilmente non avresti chiesto a una persona esperta qualcosa di così semplice, a meno che forse non fossero molto timidi e non cercassi di scaldarli.
Scott C Wilson,

1

Come domanda di 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 personaggi potrebbero effettivamente rappresentare).

Allo stesso tempo, specialmente se stai intervistando una persona relativamente senior, potresti almeno sperare di ascoltare alcune domande sulla specifica e sulla forma esatta dell'input. Anche se li rimandi al semplice caso di scambiare solo elementi a 8 bit, sapere se pensano in termini più ampi di quello può essere prezioso.

Se hai a che fare con una vasta gamma di input, devi solo 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 una serie abbastanza specifica di trasformazioni in un ordine specifico. Questo ti consente di mantenere ogni parte della trasformazione abbastanza semplice da poterla tenere sotto controllo e avere una ragionevole possibilità di soddisfarla ai suoi requisiti.

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

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

Il passaggio successivo è facoltativo. È possibile normalizzare l'input in uno dei quattro moduli di normalizzazione Unicode. In questo caso, probabilmente vorrai applicare la trasformazione "NFKC": decomposizione di compatibilità seguita da composizione canonica. Questo (dove possibile) si convertirà combinando forme diacritiche (come l'U + 301 menzionata da Jon) in punti di codice singolo (ad esempio, una "A" con un "U + 301" verrebbe convertita in "capitale latina A con acuto" , U + 00C1).

Quindi attraversi 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 questo sarà in genere un indice dei caratteri effettivi nella stringa, come la posizione e la lunghezza di ciascuno.

Invertire l'ordine 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 con acuto" in due punti di codice: un "capitale latino A" e un "abbinamento acuto". Se l'input contenesse un U + 00C1 per iniziare, tuttavia, convertirà anche quello in due punti di codice.

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

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


Non avevo mai incontrato l'U + 301 prima che Jon lo tirasse su. Non riesco a capire perché sia ​​necessario in unicode con glifi per tutti i personaggi accentati - Immagino sia compatibilità all'indietro
Martin Beckett,

@Martin: In realtà esiste un discreto numero di combinazioni di segni diacritici (l'intera gamma da U + 0300 a U + 036F, sebbene da U + 0363 a U + 036F siano al massimo obsoleti). I personaggi precomposti sono forniti per alcune delle possibilità più comuni e combinano i segni diacritici per qualsiasi altra cosa necessaria.
Jerry Coffin, il

Troppa memoria aggiuntiva, normalizzazione e conversione. Basta iterare i caratteri e invertire l'ordine delle unità di codice costituenti sul posto. Quindi invertire l'ordine di tutte le unità di codice sul posto.
Deduplicatore,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.