2013-05-16 15 views
5

Dでラインを範囲として読み取る方法は?Dで文字列を文字列で読み取る方法は?

Dに範囲があることは知っていますが、この概念を使用して文字列の各文字を単純に反復する方法は不思議です。私が後だものを表示するには

、移動中に同様のコードは次のとおりです。

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

http://ddili.org/ders/d.en/ranges.html – sigod

+0

@sigodは、確かに、アリの本をチェックしたはずです!それは間違いなくDのものを今読んでいるリソースへ行くことです。 –

答えて

12

これは、コード単位またはコードポイントを反復処理するかどうかによって異なります。あなたは、単に意味不明であろうプリント

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

最後の2つの文字と、次に、型推論とforeachを使用する場合にéであるため、言語自体の配列要素によってアレイを反復し、文字列は、コード単位の配列でありますコードポイントは2つのUTF-8コードユニットで構成され、個々のコードユニットが出力されます(charはUTF-8コードユニットなので)。一方、あなたは

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

をすれば、ランタイムは、コード・ポイントへのコード単位をデコードし、éは最後の文字として印刷されます。しかし、これはどれも実際には文字列で範囲として動作していません。 foreachは、入力範囲APIを使用せずにネイティブに配列を操作します。 ないそのコード単位の種類 - それはdcharの範囲などの文字列で動作

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

ようしかし、すべての文字列型のため、レンジAPIが見えます。これにより、 std.algorithm.filterなどの機能の問題が回避されます。これは意味をなさないため個々のコード単位で動作します。コードポイントの操作は100%正しいわけではありません。なぜなら、Unicodeはコードポイントと文字列とその他のコードを組み合わせることに関して非常に複雑になりますが、コードポイントでの操作は正しいことです。あなたがそれを必要とし、パフォーマンスヒットを支払う意思がある場合のための標準ライブラリへのグラフェムのサポート)。だから、文字列の範囲のAPIが dcharの範囲として、それらを操作したことは、はるかに正確である、とあなたが

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

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

+0

UFCSレベルで必要なRange関数を提供するstd.arrayをインポートした場合、文字列を繰り返し処理することは同じですか? – dav1d

+0

@ dav1d配列の 'foreach'は配列APIのみを使用します。配列の場合、範囲ベースの関数を明示的に使用する必要があります。実際、foreachとの矛盾と同様に、std.arrayがインポートされたかどうかは、バグが発生しやすいかどうかによって異なります。単にインポートを追加または削除するだけで、コードの動作が大幅に変更される可能性があります。それはやっていた。 –

+0

ええ、私は本当にコードを変更しないことを望んでいました。しかし一方では、UFCSは、opApply(ここで間違っている可能性があります)または範囲インターフェイスを実装していないオブジェクトを反復処理することができます。説明をありがとう。 – dav1d

1
foreach(ch; str) 
    do_something(ch); 

文字列がInputRangeです。 InputRangeは、3つのものを実装します。

  • 空です。それは空ですか?
  • フロント;私に次のアイテムを与えてください。
  • popFront;範囲を前進させます。さもなければ、フロントは同じものを返します。

foreachは範囲を扱う方法を「理解している」ので、「うまくいく」。

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

+0

はい、もちろん、うわー、私はこれを忘れることができるか分からない、それはすでに数回使用しているので、私はそれを知っている必要があります...昨夜の睡眠の不足を非難する:) –

+0

あなた、私は現時点では完全に明白ではない。 – 0b1100110

+2

ここで型の推論に注意してください。そのコードはコードポイントではなくコード単位を繰り返し処理するので、Unicodeを正しく操作することはできません。 –

関連する問題