Sponsored Link
 
>>  Main > Programing > Primary > 0008

D言語入門 第08章 - 配列

#01 - 配列とは

概要

この章では配列についてお話します。
配列というのは、数学的には、数列やベクトルなんかが近い存在です。
たとえば10人のテストの点数の平均点をとるとしましょう。
その時、あなたは int point01 = 65;
int point02 = 72;
int point03 = 49;
:
:
int point10 = 91;
このように、たくさん変数を用意して、最後に int average = (point01+point02+point03+ ... +point10) / 10; という感じで、平均をとりますか?
別に、10人とわかっている上に、10という数も小さい数なので、今回はこれでもいいでしょう。
しかし、この数が、100人になったら、1000人になったらどうしましょうか?
こんなこと、面倒臭くなってやっていられなくなるはずです。
似たようなことの繰り返しなので、できればwhile文やfor文を使って、短く書いていきたいと思うかも知れません。
でも、whileやforでは変数の名前を変えることはできません。このやり方だと繰り返しの構文は使えませんね。
他にも、最初の段階で人数がわからない場合…そういう場合も困りますね。
配列は、こんな問題を解決するのにとても有効な手段です。

配列は、数学の数列のように、添え字を使うことでこれらの問題を解決します。
point[0] = 65;
point[1] = 72;
:
:

配列では、添え字を使って表現されるものを、要素と言います。
数列anを例にとると、a1とかa100とかのことですね。
配列の添え字は0から始まります。最後の要素をさすための添え字は、要素数-1ということになります。

また、配列にはあらかじめ要素の数が定まっている静的配列と、定まっていない動的配列があります。
100人や1000人と、数が分かっている場合には前者を使用し、わからない場合には後者を使用します。
これについては詳しくは静的配列は2回動的配列は3回で説明しますね。

今回のミソ

  • 配列は添え字でアクセスすることができる
  • 配列は繰り返し構文と仲が良い
  • 変数名[添え字(整数)] でアクセス。

#02 - 静的配列

今回は…

今回は、あらかじめ最大の個数が分かっている場合の配列の話をします。
コンパイルした段階で要素数が決まる配列のことを静的配列と言います。
サンプルコードでは10人のテストの点数の平均点を出したいと思います。

今回のミソ

  • 静的配列ははじめに要素数が決まる
  • 静的配列の要素数はコンパイル時に決定されていなければならない。(プログラムが走ってからは変えることができない)
  • 要素の型[要素数] 変数名; で静的配列を定義

サンプルコード

import std.stdio;
import std.conv;
import std.string;

// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    int[10] point;
    // 配列の中身すべてに対して処理を行う
    for (int i=0;i<10;i++)
    {
        // 点数入力を求めるメッセージ。
        // i+1なのは最初の人は0人目じゃなくて1人目だから。
        writef("%d 人目の点数を入力してください : ", i+1);
        // point[i] として、添え字にアクセス。数値を入力
        point[i] = toInt( chomp( readln() ) );
    }
    // 平均を出す
    int sum=0;
    for (int i=0;i<10;i++)
    {
        // すべての数値の足し算。
        // += という演算子は、
        // sum = sum + point[i]
        // とおなじ意味です。現在の値に対して加算。
        sum += point[i];
    }
    // 平均点の表示。整数で、端数切り捨て。
    writefln("平均点は約 %d 点です", sum / 10);
    // 正常終了
    return 0;
}

実行結果

1 人目の点数を入力してください : 54
2 人目の点数を入力してください : 65
3 人目の点数を入力してください : 47
4 人目の点数を入力してください : 68
5 人目の点数を入力してください : 75
6 人目の点数を入力してください : 85
7 人目の点数を入力してください : 45
8 人目の点数を入力してください : 91
9 人目の点数を入力してください : 57
10 人目の点数を入力してください : 76
平均点は約 66 点です

まとめ

今回は静的配列をやりました。
これだと、入力なんかが繰り返し構文なんかでまとめて書けて楽ですね。
100人に増えても、10だったところを100に変えればいいだけですね。 楽です。
(実際はこの10とかも変数にするといいと思います。)

しかしながら、これだと人数があらかじめ決まっているのでコードの書き換えが必要ですね。
次回は静的配列に対して動的配列です。
動的配列では、人数が変更されても柔軟に対応することができます。

#03 - 動的配列

今回は…

今回は動的配列について説明します。
動的配列を用いることで静的配列と何が違うか。 それは、あらかじめ要素数が定まらない場合の配列を扱う際に適しています。
たとえば、前回のテストの平均点をつけるプログラム。 テストの点数を調べる人数があらかじめ決まっていない場合に動的配列は有効です。

今回のミソ

  • 動的配列は要素数を自由に決めることができる。
  • 使う前は要素数を指定しておく。
  • コンパイル時に要素数は決定しない(プログラムが走っているときに指定してやる必要がある)
  • 要素の型[] 変数名; で動的配列を定義
  • 動的配列の変数.length = 要素数; で要素数を決定
  • 配列の変数.length の中身を見ることで、現在の要素数を取得可能

サンプルコード

import std.stdio;
import std.conv;
import std.string;

// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    int[] point;
    // 何人分のテストの点数を使うかを訪ねる
    writef("何人分のテストの点数を使いますか : ");
    // テストの平均を出すのに使うテストの個数を指定
    point.length = toInt( chomp( readln() ) );
    
    // 配列の中身すべてに対して処理を行う
    // point.length はこの数値が何になっているかを調べることもできる。
    for(int i=0;i<point.length;i++)
    {
        // 点数入力を求めるメッセージ。
        // i+1なのは最初の人は0人目じゃなくて1人目だから。
        writef("%d 人目の点数を入力してください : ", i+1);
        // point[i] として、添え字にアクセス。数値を入力
        point[i] = toInt( chomp( readln() ) );
    }
    // 平均を出す
    int sum=0;
    for(int i=0;i<point.length;i++)
    {
        // すべての数値の足し算。
        sum += point[i];
    }
    // 平均点の表示。整数で、端数切り捨て。
    writefln("平均点は約 %d 点です", sum / point.length);
    // 正常終了
    return 0;
}

実行結果

何人分のテストの点数を使いますか : 5
1 人目の点数を入力してください : 80
2 人目の点数を入力してください : 76
3 人目の点数を入力してください : 97
4 人目の点数を入力してください : 45
5 人目の点数を入力してください : 65
平均点は約 72 点です

まとめ

今回は動的配列について扱いました。
配列についてはもっといろいろなことができたりしますが、とりあえず基本的な使い方はこのような感じになります。
動的配列を使うと静的配列よりも自由度が増します。 ただし、自由度が増す分、気をつけて使用しないと非常に実行速度が遅くなってしまう危険性もはらんでいます。 どのような場合に実行速度が落ちるかというと、長さを何度も変えるような場合です。
長さを変えると、動的配列は新しい動的配列を定義し、今まで入っていた内容をコピーしようとします。 これは、イメージ的には次のコードのような感じになります。
int[] point;
point.length = 100;
// 何かしらの処理
// 処理の途中で、要素数を100から1000に変える必要性が出た
point.length = 1000;
// 処理
// …
このコードは次のコードとおなじ意味を持っています。 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;
// 処理
// …
……実際にはもうちょっとましだとは思いますが、これに近いものがあると考えていいと思います。
このようなコピーしなければならない状況が大量に発生すると、さすがに動作が遅くなる可能性があります。
こうならないように注意して動的配列を扱ってください。

#summary - まとめ

第08章のミソ

  • 配列は添え字でアクセスすることができる
  • 配列は繰り返し構文と仲が良い
  • 変数名[添え字(整数)] でアクセス。
  • 静的配列ははじめに要素数が決まる
  • 静的配列の要素数はコンパイル時に決定されていなければならない。(プログラムが走ってからは変えることができない)
  • 要素の型[要素数] 変数名; で静的配列を定義
  • 動的配列は要素数を自由に決めることができる。
  • 使う前は要素数を指定しておく。
  • コンパイル時に要素数は決定しない(プログラムが走っているときに指定してやる必要がある)
  • 要素の型[] 変数名; で動的配列を定義
  • 動的配列の変数.length = 要素数; で要素数を決定
  • 配列の変数.length の中身を見ることで、現在の要素数を取得可能

宿題

数人のテストの採点結果を入力し、平均点、最高点、最低点、求め方を知っていたら分散、標準偏差などを求めましょう。
実行結果は次のようになりますね。
何人分のテストの点数を使いますか : 5
1 人目の点数を入力してください : 80
2 人目の点数を入力してください : 76
3 人目の点数を入力してください : 97
4 人目の点数を入力してください : 45
5 人目の点数を入力してください : 65
平均点は約 72.6 点です
最高点は97点です
最低点は45点です
分散は370.3です
標準偏差は19.243181です

コメント

今回は配列について説明しました。
配列を知ると、forやwhileを使用してできることがぐんと広がります。
今まで文字列というものを扱っていましたが、D言語では文字列についても「文字の配列」とみなすことができます。
つまり、今までに知らず知らずのうちに使っていたわけですね。
~ という演算子で文字列を連結させる、ということをやりましたが、これは普通の配列でも同じことが言えます。 ~ という演算子は2つの配列をつなぎ合わせるという演算子だったのです。 ただ、~ については、計算過程で動的配列の長さを変更する必要があります。 これについても動的配列と同じような注意が必要だ、ということですね。

さて、次回は構造体について説明します。
今回のプログラムではテストの点数についてやりましたね。
しかし、このテストの内容は、誰がどの点数を取ったかという個人情報のようなことまでは扱っていません。
誰がとった点数なのか、何の教科の点数なのか、そのようなことまで情報として取りたい場合には、複数の配列を使う、というよりも、構造体を使用するのが一般的です。
そんな話を次章ではしていきます。
そんなわけで、宿題できたら、あるいは予想ついたら次にいきましょう~

ページトップ / 目次 / 次へ
Copyright©SHOO All rights reserved. / LastModified : 2007/12/12(水)[05:55:21]