web-dev-qa-db-ja.com

すべてのローカリゼーションと文字列型で機能する一般化された文字列逆関数を書くことは可能ですか?

Dev-Daysからの Jon Skeet(Tony the Ponyと)のプレゼンテーションを見ていました。

「文字列逆関数の記述」はコーディングインタビュー101ですが、一般的な文字列逆関数を実際に記述できるかどうかは確かではありません。

入力文字列がASCII、UTF8、UTF16(固定長および可変長)などであるかどうかの検出以外にも.
ジョンが強調した「次の文字にアクセントを付ける」(U + 0301)コードがあります。次に、表示または非表示、または二重文字としてエンコードされる合字があります。

「文字列を逆にする」は、実際にはコンピュータサイエンスの難しいタスクの1つであるようです。

16
Martin Beckett

はい。文字列を取得したら、確実に各文字を逆にすることができます。

Jonが指摘する問題は、反転が意味をなし、言語と文化の規則、文字、およびエンコーディングに準拠していることです。深く行くほど水は濁ります。

C#で任意のタイプの文字列操作を行う場合は、書き込みおよび読み取り時にインバリアントカルチャを使用すると、安全に操作できます。それ以外の場合は、トルコのサポートコールの失敗に備えます。

ToUpper()は実に無害に見えますが、発生するのを待っている壮大な失敗です。

5
Jon Raynor

一般に、この質問が行われるときは、US-ASCIIを想定しています。ポインタがどのように機能するかを理解しているかどうかを確認するために、Unicodeに関する個人の知識をテストすることはそれほど重要ではありません(これは興味深いフォローアップになるでしょう)。驚くほど多くの人がこの種のポインタ演算を行うことができません。

2
Scott C Wilson

インタビューの質問として、通常、8ビット項目のインプレーススワップを実行して順序を逆にする技術的なビットについて質問されます(実際にそれらが表す文字に関係なく)。

同時に、特に比較的年配の人にインタビューしている場合は、少なくとも仕様と入力の正確な形式についていくつかの質問を聞くことができます。 8ビットのアイテムを交換するだけの単純なケースにそれらを戻す場合でも、それらがより広い意味で考えるかどうかを知ることは価値があるかもしれません。

広範囲の入力を処理する必要がある場合は、ネットワークスタックのような「スタック」について考える必要があります。ソフトウェアはいくつかのレイヤーで構築する必要があり、各レイヤーはかなり特定の変換セットを特定の順序で適用します。これにより、変換の各部分をシンプルに保つことができるので、制御を維持でき、要件を満たすための妥当な機会を得ることができます。

少なくともある程度は実行可能であるとわかった1つの可能性について概説します。私はもっ​​と良いアイデアを持っている人がいるかもしれないことを認める最初の人です。少なくとも私には、これはブルートフォースエンジニアリングに少し似ていて、本当の優雅さはほとんどありません。

通常は、他の表現をUCS-4(別名UTF-32)に変換することから始めます。このため、一般には、自分でそれを理解しようとするよりも、ユーザーからの入力に依存することを好みます。場合によっては、特定のオクテットシーケンスがない特定のコード化スキームのルールに従っていることを確認できますが、まれに(あるとしても)特定のエンコードスキームに従っていることを確認してください。

次のステップはオプションです。入力を4つのUnicode正規化形式のいずれかに正規化できます。この場合、おそらく「NFKC」変換を適用したいと思います:互換性分解とそれに続く正規構成。これは(可能な場合)ダイアクリティカルな形式(ジョンが言及したU + 301など)を単一のコードポイントに変換します(たとえば、「U + 301」の付いた「A」は「アキュート付きラテン大文字A」に変換されます) 、U + 00C1)。

次に、すべての文字を最初から最後まで順番に調べ、文字列を実際の文字に分解します。また、発音区別符号を(まだ)組み合わせている場合は、それらを変更した文字で保持します。この結果は通常、文字列内の実際の文字のインデックス(各文字の位置や長さなど)になります。

通常は前のステップで作成したインデックスを使用して、これらの完全な文字の順序を逆にします。

次に、(再度、オプションで)NFD(正規分解)などの別のUnicode正規化プロセスを適用します。これにより、前述の「急性のラテンA」が2つのコードポイントに戻ります。「ラテンの大文字A」と「結合した急性」です。ただし、入力に最初からU + 00C1が含まれている場合は、thatも2つのコードポイントに変換されます。

次に、UCS-4コードポイントのシーケンスを目的のエンコーディング(UTF-8、UTF-16など)にエンコードします。

Unicodeの正規化手順により、文字列を格納するために必要なコードポイントの数が変更される可能性があるため、それらを含めると、元のストレージに適合する結果文字列を計画できなくなります。明らかに、結果として得られるコードポイントは、入力コードポイントにも直接対応しない場合があります。

1
Jerry Coffin