Ist es möglich, eine verallgemeinerte String-Umkehrfunktion zu schreiben, die für alle Lokalisierungen und String-Typen funktioniert?


16

Ich habe mir gerade die Präsentation von Jon Skeet (mit Tony the Pony) von Dev-Days angesehen.

Obwohl "write a string reverse function" die Kodierung von Interview 101 ist - ich bin mir nicht sicher, ob es tatsächlich möglich ist, eine allgemeine Funktion zum Umkehren von Zeichenfolgen zu schreiben, die sicherlich nicht in allen Lokalisierungen und allen Zeichenfolgentypen funktioniert.

Abgesehen von der Erkennung, ob die Eingabezeichenfolge ASCII, UTF8, UTF16 (feste und variable Länge) usw. ist.
Es gibt den von Jon hervorgehobenen Code "Akzent auf nächstes Zeichen anwenden" (U + 0301). Dann gibt es Ligaturen, die möglicherweise angezeigt oder nicht angezeigt oder als Doppelzeichen codiert werden.

Scheint, dass "einen String umkehren" tatsächlich eine der schwierigeren Aufgaben der Informatik ist!


Nein, versuchen Sie es mit dem Stopp-Problem für etwas, das sich in Schwierigkeiten befindet, aber einfacher zu erklären ist.
JB King

Da es sich um eine unsubjektive, technische Frage handelt, würde ich sagen, dass dies besser zu StackOverflow passt (bitte posten Sie es dort nicht erneut, es wird automatisch migriert, wenn genügend Leute abstimmen, um es hier zu schließen).
Péter Török

1
Kommt auf die Programmiersprache an. Zum Beispiel in Ruby ist es so einfach wie "stressed".reverse: p
Marcelo

Große philosophische Frage. FWIW, bekommt Java StringBuilder Ersatz richtig, aber nicht Kombinierer
kdgregory

2
"Diese Zeichenfolge mit Java umkehren" ist eine gute Trickfrage. :)
Scott C Wilson

Antworten:


5

Ja. Wenn wir eine Zeichenkette erhalten, können wir jedes Zeichen definitiv umkehren.

Wie Jon betont, ist das Problem, dass die Umkehrung Sinn macht und sprachlichen und kulturellen Regeln, Zeichen und Kodierungen entspricht. Das Wasser wird mit zunehmender Tiefe trüb.

Wenn Sie in C # Zeichenfolgen manipulieren, verwenden Sie beim Schreiben und Lesen die invariante Kultur. Auf diese Weise können Sie diese sicher manipulieren. Bereiten Sie sich andernfalls auf das Scheitern des türkischen Supportanrufs vor.

ToUpper () sieht so unschuldig aus, aber es ist ein epischer Fehler, der darauf wartet, passiert zu werden.


2
Die andere Frage ist - wofür verwendet jemand jemals einen umgekehrten String (außer Interview Q)? Ich habe es immer nur für Low-Level-Buffer-Manipulation von I / O-Ports benötigt - und selbst dann fast nie wirklich mit Strings
Martin Beckett

@ Martin - Einverstanden. Vielleicht für ein englischsprachiges Programm, um Palidrome zu finden? Ich glaube nicht, dass ich es anders benutzt habe, als eine Quizfrage zu lösen.
Jon Raynor

@ Martin wahr. Ich denke, es ist nur ironisch gemacht. :)
Scott C Wilson

2

Wenn diese Frage gestellt wird, wird im Allgemeinen von US-ASCII ausgegangen. Es geht nicht darum, die Unicode-Kenntnisse einer Person zu testen (obwohl dies eine interessante Fortsetzung wäre), sondern zu prüfen, ob sie versteht, wie Zeiger funktionieren. Eine überraschend große Anzahl von Menschen kann diese Art von Zeigerarithmetik nicht ausführen.


2
"Wie würde das mit Unicode scheitern?" ist eine gute Anschlussfrage
Martin Beckett

Gut, aber vielleicht etwas weiter fortgeschritten - immerhin ist "Reverse this string in place" eine Einstiegsfrage. Sie würden einen erfahrenen Menschen wahrscheinlich nicht so etwas Einfaches fragen, es sei denn, er wäre sehr schüchtern und Sie wollten ihn aufwärmen.
Scott C Wilson

1

Als Interviewfrage wird in der Regel nur nach den technischen Details eines direkten Austauschs von 8-Bit-Elementen gefragt, um deren Reihenfolge umzukehren (unabhängig davon, für welche Zeichen diese möglicherweise tatsächlich stehen).

Gleichzeitig könnten Sie, insbesondere wenn Sie eine relativ hochrangige Person interviewen, auf einige Fragen zur Spezifikation und zur genauen Form der Eingabe hoffen. Selbst wenn Sie sie auf den einfachen Fall des Austauschs von 8-Bit-Elementen zurückführen, ist es möglicherweise wertvoll, zu wissen, ob sie allgemeiner denken oder nicht.

Wenn Sie sich mit einer Vielzahl von Eingaben befassen müssen, müssen Sie in etwa an einen "Stapel" denken, ein bisschen wie an einen Netzwerkstapel. Sie müssen Ihre Software in mehreren Ebenen erstellen, von denen jede eine Reihe von Transformationen in einer bestimmten Reihenfolge ausführt. Auf diese Weise können Sie jeden Teil der Transformation so einfach halten, dass Sie sie unter Kontrolle halten und eine vernünftige Chance haben, dass sie den Anforderungen entspricht.

Ich werde eine Möglichkeit skizzieren, die ich zumindest als etwas praktikabel empfunden habe. Ich gebe als Erster zu, dass es vielleicht andere gibt, die bessere Ideen haben. Zumindest scheint mir das ein bisschen wie Brute-Force-Engineering, mit wenig wirklicher Eleganz.

Normalerweise möchten Sie zunächst eine andere Darstellung in UCS-4 (auch bekannt als UTF-32) konvertieren. In diesem Fall ziehen Sie es im Allgemeinen vor, sich auf die Eingaben des Benutzers zu verlassen, als dies selbst herauszufinden. In einigen Fällen können Sie sicher sein, dass eine bestimmte Folge von Oktetten nicht den Regeln eines bestimmten Codierungsschemas entspricht, Sie können jedoch selten (wenn überhaupt) sicher sein, dass sie einem bestimmten Codierungsschema entspricht.

Der nächste Schritt ist optional. Sie können die Eingabe in eines der vier Unicode-Normalisierungsformulare normalisieren. In diesem Fall möchten Sie wahrscheinlich die "NFKC" -Transformation anwenden: Kompatibilitätszerlegung, gefolgt von kanonischer Komposition. Dies wird (wo möglich) die Kombination diakritischer Formen (wie das von Jon erwähnte U + 301) in einzelne Codepunkte umwandeln (z. B. ein "A" mit einem "U + 301" würde in "lateinisches Kapital A mit Akut" umgewandelt werden. , U + 00C1).

Anschließend durchlaufen Sie alle Zeichen von Anfang bis Ende und teilen die Zeichenfolge in tatsächliche Zeichen auf. Wenn diakritische Zeichen (noch) kombiniert werden, behalten Sie sie mit den Zeichen bei, die sie ändern. Das Ergebnis ist in der Regel ein Index der tatsächlichen Zeichen in der Zeichenfolge, z. B. die Position und Länge der einzelnen Zeichen.

Sie kehren die Reihenfolge dieser vollständigen Zeichen um, indem Sie in der Regel den im vorherigen Schritt erstellten Index verwenden.

Anschließend wenden Sie (optional) einen anderen Unicode-Normalisierungsprozess an, z. B. NFD (Canonical Decomposition). Dadurch wird das oben erwähnte "Latin A mit Akut" wieder in zwei Codepunkte umgewandelt - ein "Latin Capital A" und ein "Combining Acute". Wenn Sie Ihre Eingabe mit einem U + 00C1 zu beginnen, jedoch enthält passiert ist , wäre es auch konvertieren , dass auch in zwei Codepunkte.

Anschließend codieren Sie die Sequenz der UCS-4-Codepunkte in die gewünschte Codierung (UTF-8, UTF-16 usw.).

Beachten Sie, dass die Unicode-Normalisierungsschritte die Anzahl der zum Speichern der Zeichenfolge erforderlichen Codepunkte ändern können / werden. Wenn Sie diese einbeziehen, können Sie die Ergebniszeichenfolge nicht mehr in den ursprünglichen Speicher einplanen. Offensichtlich entsprechen die resultierenden Codepunkte möglicherweise auch nicht direkt den Eingabecodepunkten.


Ich war nicht auf U + 301 gestoßen, bevor Jon es ansprach. Ich kann nicht verstehen, warum es in Unicode mit Glyphen für alle Zeichen mit Akzent benötigt wird - ich stelle mir vor, es ist abwärtskompatibel
Martin Beckett

@Martin: Es gibt tatsächlich eine ganze Reihe kombinierter diakritischer Zeichen (der gesamte Bereich von U + 0300 bis U + 036F, obwohl von U + 0363 bis U + 036F bestenfalls überholt). Vorkomponierte Zeichen werden für einige der gebräuchlichsten Möglichkeiten bereitgestellt und diakritische Zeichen für alles andere kombiniert.
Jerry Coffin

Zu viel zusätzlicher Speicher, Normalisierung und Konvertierung. Wiederholen Sie einfach die Zeichen und kehren Sie die Reihenfolge der vorhandenen Codeeinheiten um. Kehren Sie dann die Reihenfolge aller vorhandenen Codeeinheiten um.
Deduplizierer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.