Back to page

− Links

 Print 

Backup diff of Articles​/D言語入門講座​/第08章 - 配列 (No. 1) :: D言語友の会

Backup diff of wiki:Articles/D言語入門講座/第08章 - 配列(No. 1)

  Next »[4]
1: 2010-02-21 (Sun) 11:22:54 SHOO[5] source[6]
With "vote" plugin. at 2012-05-03 (木) 18:34:01
Line 1: Line 1:
 +TITLE:配列について
 +#navi
 +* #01 配列とは [#l8536645]
 +** 概要 [#t59c5f7d]
 +この章では配列についてお話します。~
 +配列というのは、数学的には、数列やベクトルなんかが近い存在です。~
 +たとえば10人のテストの点数の平均点をとるとしましょう。~
 +その時、あなたは
 +#code(d,nomenu,nonumber,nooutline){{{
 +int point01 = 65;
 +int point02 = 72;
 +int point03 = 49;
 +:
 +:
 +int point10 = 91;
 +}}}
 +このように、たくさん変数を用意して、最後に
 +#code(d,nomenu,nonumber,nooutline){{{
 +int average = (point01+point02+point03+ ... +point10) / 10;
 +}}}
 +という感じで、平均をとりますか?
 +別に、10人とわかっている上に、10という数も小さい数なので、今回はこれでもいいでしょう。~
 +しかし、この数が、100人になったら、1000人になったらどうしましょうか?~
 +こんなこと、面倒臭くなってやっていられなくなるはずです。~
 +似たようなことの繰り返しなので、できればwhile文やfor文を使って、短く書いていきたいと思うかも知れません。~
 +でも、whileやforでは変数の名前を変えることはできません。このやり方だと繰り返しの構文は使えませんね。~
 +他にも、最初の段階で人数がわからない場合…そういう場合も困りますね。~
 +配列は、こんな問題を解決するのにとても有効な手段です。
 +
 +配列は、数学の数列のように、添え字を使うことでこれらの問題を解決します。
 +#code(d,nomenu,nonumber,nooutline){{{
 +point[0] = 65;
 +point[1] = 72;
 +point[2] = 49;
 +:
 +:
 +point[9] = 91;
 +}}}
 +配列では、添え字を使って表現されるものを、要素と言います。~
 +数列anを例にとると、a1とかa100とかのことですね。~
 +配列の添え字は0から始まります。最後の要素をさすための添え字は、要素数-1ということになります。
 +
 +また、配列にはあらかじめ要素の数が定まっている静的配列と、定まっていない動的配列があります。~
 +100人や1000人と、数が分かっている場合には前者を使用し、わからない場合には後者を使用します。
 +
 +** 今回のミソ [#l3549a2b]
 +- 配列は添え字でアクセスすることができる
 +- 配列は繰り返し構文と仲が良い
 +- 変数名[添え字(整数)] でアクセス。
 +- 添え字は0から始まる
 +
 +
 +* #02 静的配列 [#f8975eaa]
 +** 今回は… [#zf6e2c03]
 +今回は、あらかじめ最大の個数が分かっている場合の配列の話をします。~
 +コンパイルした段階で要素数が決まる配列のことを静的配列と言います。~
 +サンプルコードでは10人のテストの点数の平均点を出したいと思います。
 +
 +** 今回のミソ [#n333315a]
 +- 静的配列ははじめに要素数が決まる
 +- 静的配列の要素数はコンパイル時に決定されていなければならない。(プログラムが走ってからは変えることができない)
 +- 静的配列を定義するには以下のようにする
 +#code(d,nomenu,nonumber,nooutline){{{
 +要素の型[要素数] 変数名;
 +}}}
 +
 +** サンプルコード [#xa296b11]
 +#code(d,sample0802p.d);
 +#region(Tango用はこちら){{
 +#code(d,sample0802t.d);
 +}}
 +
 +
 +** 実行結果 [#da64d130]
 +#code(console){{{
 +$ dmd -run sample0802p.d
 +1 人目の点数を入力してください : 45
 +2 人目の点数を入力してください : 62
 +3 人目の点数を入力してください : 70
 +4 人目の点数を入力してください : 50
 +5 人目の点数を入力してください : 65
 +6 人目の点数を入力してください : 85
 +7 人目の点数を入力してください : 40
 +8 人目の点数を入力してください : 90
 +9 人目の点数を入力してください : 67
 +10 人目の点数を入力してください : 58
 +平均点は約 63 点です
 +}}}
 +
 +
 +** まとめ [#bb856f93]
 +今回は静的配列をやりました。~
 +これだと、入力なんかが繰り返し構文なんかでまとめて書けて楽ですね。~
 +100人に増えても、10だったところを100に変えればいいだけですね。 楽です。~
 +(実際はこの10とかも変数にするといいと思います。)
 +
 +また、静的配列の変数を定義する際には、
 +#code(d,nooutline,nonumber){{{
 +int[10] a;
 +}}}
 +のようにしますが、D言語ではint[10]が型となります。 int10個の配列型ということです。~
 +D言語では、配列は型を作ります。~
 +つまり、
 +#code(d,nooutline,nonumber){{{
 +int[10][5] a;
 +}}}
 +とした場合、 ( (int型のデータ10個の配列) 型のデータ5個の配列 ) と言うことになります。
 +しかしながら、これだと人数があらかじめ決まっているのでコードの書き換えが必要ですね。~
 +次回は静的配列に対して動的配列です。~
 +動的配列では、人数が変更されてもより柔軟に対応することができます。
 +
 +* #03 動的配列 [#aa6b3fac]
 +** 今回は… [#v5599bf4]
 +今回は動的配列について説明します。~
 +動的配列を用いることで静的配列と何が違うか。 それは、あらかじめ要素数が定まらない場合の配列を扱う際に適しています。~
 +たとえば、前回のテストの平均点をつけるプログラム。 テストの点数を調べる人数があらかじめ決まっていない場合に動的配列は有効です。
 +
 +** 今回のミソ [#s20c00fb]
 +- 動的配列は要素数を自由に決めることができる。
 +- 動的配列は使う前は要素数を指定しておく。
 +- 動的配列はコンパイル時に要素数は決定しない(プログラムが走っているときに指定してやる必要がある)
 +- 動的配列を定義するには以下のようにします。
 +#code(d,nomenu,nonumber,nooutline){{{
 +要素の型[] 変数名;
 +}}}
 +- 要素数を決定するには以下のようにします
 +#code(d,nomenu,nonumber,nooutline){{{
 +動的配列の変数.length = 要素数;
 +}}}
 +- 配列の変数.length の中身を見ることで、現在の要素数を取得可能
 +
 +** サンプルコード [#h2a800eb]
 +#code(d,sample0803p.d);
 +#region(Tango用はこちら){{
 +#code(d,sample0803t.d);
 +}}
 +
 +
 +** 実行結果 [#h962dbe2]
 +#code(console){{{
 +$ dmd -run sample0803p.d
 +何人分のテストの点数を使いますか : 5
 +1 人目の点数を入力してください : 80
 +2 人目の点数を入力してください : 76
 +3 人目の点数を入力してください : 97
 +4 人目の点数を入力してください : 45
 +5 人目の点数を入力してください : 65
 +平均点は約 72 点です
 +}}}
 +
 +
 +** まとめ [#db6fb5de]
 +今回は動的配列について扱いました。~
 +配列についてはもっといろいろなことができたりしますが、とりあえず基本的な使い方はこのような感じになります。~
 +動的配列を使うと静的配列よりも自由度が増します。 ただし、自由度が増す分、気をつけて使用しないと非常に実行速度が遅くなってしまう危険性もはらんでいます。 どのような場合に実行速度が落ちるかというと、長さを何度も変えるような場合です。~
 +長さを変えると、動的配列は新しい動的配列を定義し、今まで入っていた内容をコピーしようとします。 これは、イメージ的には次のコードのような感じになります。
 +#code(d,nomenu,nonumber,nooutline){{{
 +int[] point;
 +point.length = 100;
 +// 何かしらの処理
 +// 処理の途中で、要素数を100から1000に変える必要性が出た
 +point.length = 1000;
 +// 処理
 +// …
 +}}}
 +このコードは次のコードとおなじ意味を持っています。
 +#code(d,nomenu,nonumber,nooutline){{{
 +int[] point;
 +point.length = 100;
 +// 何かしらの処理
 +// 処理の途中で、要素数を100から1000に変える必要性が出た
 +// 新しい動的配列を定義
 +int[] newpoint;
 +// 新しい動的配列の要素数を1000にする。
 +newpoint.length = 1000;
 +// いままでのpointの中身をすべてnewpointに移す。
 +for(int i=0;i<point.length;i++)
 +{
 +    newpoint[i] = point[i];
 +}
 +// いままでのpointを新しい配列に置き換える
 +point = newpoint;
 +// 処理
 +// …
 +}}}
 +ちなみに、コピーは、配列の要素を増やすときで、連続したメモリが確保できない場合についてのみ行われます。~
 +配列の要素数を減らす場合や、連続したメモリが確保できる場合(一度要素数を減らしたあとや、あらかじめ確保していた場合)は、コピーは行われません。~
 +前述の2つのコードでは、前者のほうが効率が良い場合がある、ということになりますね。
 +
 +このようなコピーによる時間はごく小さなものですが、あまりにも頻繁に行われる場合や、要素数が多い場合、決められた時間内に処理を終えないといけない場合(リアルタイム性のある場合)は、なるべくコピーの発生しないよう気を配るとよいでしょう。~
 +筆者の遭遇した具体的な例としては、DirectXやOpenGL等を使った描写の際の点の配列の処理でコピーのための時間が問題になりました。
 +
 +さて、今回は動的な配列として、プログラムの実行中に要素数を変えられる配列を説明しました。~
 +次回は、添え字に、文字列など整数以外のものを利用できる''連想配列''というものについて説明いたします。~
 +それではお次へどうぞ~
 +
 +* #04 連想配列 [#de5acf84]
 +** 今回は… [#r49a6563]
 +連想配列について取り扱います。ちょっと難しいので、飛ばしたい方は飛ばしても大丈夫ですよ。
 +
 +連想配列というのは、添え字として、文字列など、数値以外の型を利用できる配列を言います。~
 +他の呼び名としては、キーに対応する内容を取り出すという性質から''辞書式配列''とか、内部の処理から名前を取って、''ハッシュ''とか呼ばれたりすることもあります。
 +
 +サンプルコードでは、英和辞書のように、登録された単語から意味を引くプログラムを記述します。
 +
 +** 今回のミソ [#mbea9df2]
 +- 添え字の部分に数値以外の型も利用できる配列を、連想配列という
 +- 連想配列ではただの配列での添え字のことを、''キー''(key)と呼ぶ
 +- 連想配列ではただの配列での要素のことを、''値''(value)と呼ぶ
 +- 連想配列は以下のようにして定義する
 +#code(d,nomenu,nonumber,nooutline){{{
 +値になる型名[キーになる型名] 連想配列の変数名;
 +}}}
 +- 連想配列は以下のようにしてキーと値を関連付ける
 +#code(d,nomenu,nonumber,nooutline){{{
 +連想配列の変数名[キー] = 値;
 +}}}
 +- 連想配列は以下のようにしてキーから値にアクセスする。
 +#code(d,nomenu,nonumber,nooutline){{{
 +連想配列の変数名[キー];
 +}}}
 +- アクセスは関連付ける時のように ''= '''値''''' としない。この場合は意味が異なるので注意
 +- キーから値にアクセスするときに、関連付けられていないキーでアクセスしようとするとエラーになる
 +- '''キー''' in '''連想配列の変数''' で、連想配列にキーが関連付けられているかを確認できる
 +- '''連想配列の変数'''.keys で、キーの一覧を得ることができる
 +
 +** サンプルコード [#n0da6d53]
 +#code(d,sample0804p.d);
 +#region(Tango用はこちら){{
 +#code(d,sample0804t.d);
 +}}
 +
 +** 実行結果 [#a5b0a114]
 +#code(console){{{
 +$ dmd -run sample0804p.d
 +登録しますか?[y/n/exit] : y
 +単語を入力 : さんま
 +意味を入力 : 魚の一種。秋に獲れる。おいしい。
 +登録しますか?[y/n/exit] : y
 +単語を入力 : ひまわり
 +意味を入力 : 夏に大きな花を咲かせる植物。種を食用にすることがある。
 +登録しますか?[y/n/exit] : y
 +単語を入力 : D言語
 +意味を入力 : プログラミング言語の一種。開発者のウォルター氏は皆に慕われている。
 +登録しますか?[y/n/exit] : n
 +単語を入力 : ひまわり
 +夏に大きな花を咲かせる植物。種を食用にすることがある。
 +登録しますか?[y/n/exit] : n
 +単語を入力 : D言語
 +プログラミング言語の一種。開発者のウォルター氏は皆に慕われている。
 +登録しますか?[y/n/exit] : n
 +単語を入力 : C言語
 +単語が登録されていません
 +登録しますか?[y/n/exit] : n
 +単語を入力 : さんま
 +魚の一種。秋に獲れる。おいしい。
 +登録しますか?[y/n/exit] : y
 +単語を入力 : C言語
 +意味を入力 : プログラミング言語の一種。
 +登録しますか?[y/n/exit] : n
 +単語を入力 : C言語
 +プログラミング言語の一種。
 +登録しますか?[y/n/exit] : exit
 +プログラムを終了します。
 +----------今回登録された単語と意味は…----------
 +ひまわり:
 +   夏に大きな花を咲かせる植物。種を食用にすることがある。
 +D言語:
 +   プログラミング言語の一種。開発者のウォルター氏は皆に慕われている。
 +さんま:
 +   魚の一種。秋に獲れる。おいしい。
 +C言語:
 +   プログラミング言語の一種。
 +}}}
 +
 +** まとめ [#oaaea19a]
 +サンプルコードがかなり複雑になってしまいましたね…~
 +大事なところをまとめましょう。
 +
 +- 8行目の、連想配列の変数の定義の部分
 +- 30行目の連想配列にキーと値を関連付ける部分
 +- 46行目の連想配列にキーが関連付けられているか確認する部分
 +- 51行目の連想配列で関連付けられた値にキーでアクセスする部分
 +
 +こんなところでしょうか。
 +
 +ちなみに、コンソールが面での日本語入力は、Windowsの場合、Alt+半角/全角キーでできるようになります。~
 +&color(gray){ただ、Phobosの場合日本語の表示がめちゃくちゃになってしまうので、英語でやった方がいいかもしれませんね。};
 +
 +豆知識として、今回は文字列と文字列を関連付ける連想配列を作りましたが、もちろんそれ以外の方もいろいろ作ることができます。~
 +#code(d,nomenu,nonumber,nooutline){{{
 +int[int] assoc;
 +}}}
 +等とすると、intとint型を結びつけて、動的配列のようにlengthで長さを指定しなくても…
 +#code(d,nomenu,nonumber,nooutline){{{
 +int[int] assoc;
 +assoc[10] = 10 * 10;
 +assoc[24] = 24 * 24;
 +assoc[1000000] = 1000000 * 1000000;
 +}}}
 +このように、ダイレクトに要素(値)を添え字(キー)と関連付けできてしまったりします。~
 +とはいえ、このようにした場合、配列よりもメモリも計算時間もかかってしまいますので、必要な時以外は普通の動的配列などで処理した方が良いでしょう。
 +
 +
 +* #summary - まとめ [#h90b9800]
 +** 第08章のミソ [#u05f3797]
 +- 配列は添え字でアクセスすることができる
 +- 配列は繰り返し構文と仲が良い
 +- 変数名[添え字(整数)] でアクセス。
 +- 添え字は0から始まる
 +- 静的配列ははじめに要素数が決まる
 +- 静的配列の要素数はコンパイル時に決定されていなければならない。(プログラムが走ってからは変えることができない)
 +- 静的配列を定義するには以下のようにする
 +- 動的配列は要素数を自由に決めることができる。
 +#code(d,nomenu,nonumber,nooutline){{{
 +要素の型[要素数] 変数名;
 +}}}
 +- 動的配列は使う前は要素数を指定しておく。
 +- 動的配列はコンパイル時に要素数は決定しない(プログラムが走っているときに指定してやる必要がある)
 +- 動的配列を定義するには以下のようにします。
 +#code(d,nomenu,nonumber,nooutline){{{
 +要素の型[] 変数名;
 +}}}
 +- 要素数を決定するには以下のようにします
 +#code(d,nomenu,nonumber,nooutline){{{
 +動的配列の変数.length = 要素数;
 +}}}
 +- 配列の変数.length の中身を見ることで、現在の要素数を取得可能
 +- 添え字の部分に数値以外の型も利用できる配列を、連想配列という
 +- 連想配列は以下のようにして定義する
 +#code(d,nomenu,nonumber,nooutline){{{
 +型名[型名] 変数名;
 +}}}
 +- 添え字の部分に数値以外の型も利用できる配列を、連想配列という
 +- 連想配列ではただの配列での添え字のことを、''キー''(key)と呼ぶ
 +- 連想配列ではただの配列での要素のことを、''値''(value)と呼ぶ
 +- 連想配列は以下のようにして定義する
 +#code(d,nomenu,nonumber,nooutline){{{
 +値になる型名[キーになる型名] 連想配列の変数名;
 +}}}
 +- 連想配列は以下のようにしてキーと値を関連付ける
 +#code(d,nomenu,nonumber,nooutline){{{
 +連想配列の変数名[キー] = 値;
 +}}}
 +- 連想配列は以下のようにしてキーから値にアクセスする。
 +#code(d,nomenu,nonumber,nooutline){{{
 +連想配列の変数名[キー];
 +}}}
 +- アクセスは関連付ける時のように ''= '''値''''' としない。この場合は意味が異なるので注意
 +- キーから値にアクセスするときに、関連付けられていないキーでアクセスしようとするとエラーになる
 +- '''キー''' in '''連想配列の変数''' で、連想配列にキーが関連付けられているかを確認できる
 +- '''連想配列の変数'''.keys で、キーの一覧を得ることができる
 +
 +** 宿題 [#o1ee9e4b]
 +~  数人のテストの採点結果を入力し、平均点、最高点、最低点、求め方を知っていたら不偏分散、標準偏差などを求めましょう。
 +~  実行結果は次のようになりますね。
 +#code(console){{{
 +何人分のテストの点数を使いますか : 5
 +1 人目の点数を入力してください : 80
 +2 人目の点数を入力してください : 76
 +3 人目の点数を入力してください : 97
 +4 人目の点数を入力してください : 45
 +5 人目の点数を入力してください : 65
 +平均点は約 72.6 点です
 +最高点は97点です
 +最低点は45点です
 +分散は370.3です
 +標準偏差は19.243181です
 +}}}
 +
 +** コメント [#t51d51e2]
 +今回は配列について説明しました。~
 +配列を知ると、forやwhileを使用してできることがぐんと広がります。~
 +今まで文字列というものを扱っていましたが、D言語では文字列についても「文字の配列」とみなすことができます。~
 +つまり、今までに知らず知らずのうちに使っていたわけですね。&br; ~ という演算子で文字列を連結させる、ということをやりましたが、これは普通の配列でも同じことが言えます。 ~ という演算子は2つの配列をつなぎ合わせるという演算子だったのです。 ただ、~ については、計算過程で動的配列の長さを変更する必要があります。 これについても動的配列と同じような注意が必要だ、ということですね。
 +
 +さて、次回は構造体について説明します。~
 +今回のプログラムではテストの点数についてやりましたね。~
 +しかし、このテストの内容は、誰がどの点数を取ったかという個人情報のようなことまでは扱っていません。~
 +誰がとった点数なのか、何の教科の点数なのか、そのようなことまで情報として取りたい場合には、複数の配列を使う、というよりも、構造体を使用するのが一般的です。~
 +そんな話を次章ではしていきます。
 +
 +そんなわけで、宿題できたら、あるいは予想ついたら次にいきましょう~
 +
 +#navi
 +
 +
 +* 投票とコメント [#r0ad26a4]
 +#vote(#lastvote:206a499f93f4a947869c09788c67c8b7,大変参考になった[1],参考になった,あまり参考にならなかった,まったく参考にならなかった,#notimestamp)
 +#pcomment
  Next »[4]