5

Dの範囲として行を読み取る方法は?

Dに範囲があることは知っていますが、この概念を使用して文字列の各文字を単純に反復する方法を知りたいですか?

私が求めているものを示すために、Go の同様のコードは次のとおりです。

for _, someChar := range someString {
    // Do something
}
4

2 に答える 2

12

それは、コード単位またはコード ポイントのどちらを反復処理するかによって異なります。言語自体は配列要素ごとに配列を反復処理し、文字列はコード単位の配列であるため、単純にforeachwith 型推論を使用すると、

foreach(c; "La Verité")
    writeln(c);

éは2 つの UTF-8 コード単位で構成されるコード ポイントであり、個々のコード単位を出力しているため (は UTF-8 コード単位であるため) 、出力される最後の 2 文字は意味不明になりますchar。一方、そうする場合

foreach(dchar c; "La Verité")
    writeln(c);

次に、ランタイムはコード単位をコード ポイントにデコードしé、最後の文字として出力します。しかし、これは実際には文字列を範囲として操作していません。foreach入力範囲 API を使用しなくても、配列をネイティブに操作できます。ただし、すべての文字列型について、範囲 API は次のようになります。

@property bool empty();
@property dchar front();
void popFront();

コード単位タイプではなく、dchar範囲として文字列を操作します。これにより、個々のコード単位での操作などの関数の問題が回避されます。これはstd.algorithm.filter意味がないためです。Unicodeはコードポイントと書記素などの組み合わせに関して非常に複雑になるため、コードポイントの操作も100%正しいわけではありませんが、コードポイントの操作は正しいことにはるかに近いです(範囲を追加する作業が行われていると思います書記素のサポートが必要で、パフォーマンスへの影響を喜んで支払う場合のために、標準ライブラリへの書記素のサポート)。したがって、文字列の範囲 API を範囲として操作するdchar方がはるかに正確です。

foreach(c; filter!"true"("La Verité"))
    writeln(c);

を反復しdcharé正しく印刷します。もちろん、これらすべての欠点は、foreach文字列の場合はデフォルトでコード単位レベルで動作するのに対し、文字列の範囲 API はコード ポイントとして動作するため、配列操作と範囲ベースの操作を混在させる場合は注意が必要です。弦の上。これが、 と がランダム アクセス範囲と見なされない理由stringでもwstringあります。単なる双方向範囲です。コードポイントがさまざまな数のコードユニットで構成されている場合、コードポイントで O(1) でランダムアクセスを行うことはできません (一方、UTF-32 ではすべてのコードユニットがコードポイントであるため、 はランダムアクセス範囲です) dstring .

于 2013-05-16T17:25:37.670 に答える
1
foreach(ch; str)
    do_something(ch);

文字列はInputRange. Anは次のInputRange3 つのことを実装します。

  • 空の; 空ですか?
  • フロント; 次のアイテムをください。
  • popFront; そうでない場合、front は同じ値を返します。

foreach は、範囲を操作する方法を「理解」しているため、「うまく機能します」。

しかし、私は囲碁を話さないので、私たちが同じ言語を話しているかどうかは完全にはわかりません.

于 2013-05-16T14:57:49.230 に答える