2011-01-27 10 views
3

私はDを学んでいます。テキストファイルを1行ずつ読み込んで、各行を別々の単語に分け、すべてを標準出力に出力する簡単なプログラムがあります。Dの文字の3D配列の問題D

import std.stdio; 
import std.string; 

void main(string args[]) 
{ 
    char[][][] lines; 
    auto input = File(args[1], "r"); 
    foreach(line; input.byLine()) 
    { 
     auto words = split(strip(line)); 
     lines ~= words; 
    } 

    foreach(line; lines) 
    { 
     writeln(line); 
    } 
} 

wordsを作成するコードが機能します。単語が割り当てられるたびにwritelnと呼ぶだけで、私は必要な出力を得ることができます。しかし、wordslinesに追加してlinesを出力すると、奇妙なことが起こります。 linesにはソースファイルの各行のエントリがありますが、各行は最後に読み込まれた行の破損したバージョンです。例えば、ファイルの最後の行は次のように見える場合:

END START  * End of routine 

が、私はこのようなものな出力を得る:

[  , END, ST, *, End , f rout, ne, ,  , e other] 
[  , END, ST, *, End of, rout, ne,  , , e othe] 
[ , END, STAR, *, End of, rout, ne.,   
e] 
[ , END, START , *, End of, rout, ne.,   
e] 
[END , STAR] 
[  , END, START  , *, End , f , out, ne. ] 
[END, START, *, End, of ro, tine. , , , 
] 
[END, STA, *, o, r, ut] 
[ , END , S, *, End, o, r, utine., , , , 
, o] 
[END, START , *, of routi, e., ] 

任意のアイデアを私が間違ってやっていますか?

答えて

8

あなたの主な問題は、署名欄が同じバッファを使用していることで、あなたはそれを複製する必要があり、それはあなたのデータを上書きしないように

auto words = split(strip(line).dup); 

より適切なストレージクラスには、[]の代わりに文字列である場合を除き実際の文字を変更するつもりです。しかし、はchar []になるので、v 2.0ではコンパイラエラーが発生します。これは単なる不変の文字列として複製することに過ぎません。あなたのプログラムは、これに

import std.stdio; 
import std.string; 

void main(string[] args) 
{ 
    string[][] lines; 
    auto input = File(args[1], "r"); 
    foreach(line; input.byLine()) 
    { 
     auto words = split(strip(line).idup); 
     lines ~= words; 
    } 

    foreach(line; lines) 
    { 
     writeln(line); 
    } 
} 
+0

なぜ 'char [] [] []'を使うとコンパイルが失敗するのですか?確かにそれは醜いですが、まだ動作するはずです。私は 'split(strip(line))'が返す 'char [] []'と 'string []'との間で変換に多くのトラブルを抱えていたので、これを使い始めました。どのような場合でも、ソリューションは機能します。ありがとうございました。 – Max

+0

@Max、申し訳ありませんが、あなたは正しいです。私はあなたがchar []を追加していると思っていました。私は私の答えを更新します。 –

5

答えのようになります

auto words = split(strip(line).idup); 

この方法は2つある。

最初に述べたように、byLineは内部バッファ(速度用)を使用します。これは後続のループ反復で上書きされます。

次に、wordsの操作を見てください。 split(strip(line))strip配列(これは参照)の開始と終了を変更するだけで、splitは配列を同じ基礎データを参照するより小さなサブ配列に分割します。どちらもありません破壊的;したがって、再割り当てする必要はありません。このため、最後のstring[] wordsは、次の繰り返しで上書きされる元のバッファを指しています。

解決策は、auto words = split(strip(line).dup);と書くことで、ループスコープからエスケープしたい場合は、データを確実にコピーすることです。 wordsのデュプリングはではなくとなります。これは配列自体ではなく、配列の配列を複製するためです。

また、string[] argsを使用する必要があります。 Cのような構文は、従来の理由でのみサポートされており、使用することはお勧めしません。

+0

実際のところ、文字列は単にD1のchar []とD2のimmutable(char)[]の別名です。読みやすく、読み書きが容易なので、immutable(char)[]よりもお勧めです。もちろん、 'auto'もそれを助けます。しかし、D2に可変文字列が必要な場合は、char []を使用する必要があります。 –

+0

いいえ、私は 'string args []'を意味しません。 '[]'をパラメータの後ろに置く。 Btw、あなたは、あなたの '[i] dup'を' strip'の後ろに置き、十五ビットのメモリを節約したいかもしれません。 – FeepingCreature

関連する問題