Page Top

概要 anchor.png

この章では配列についてお話します。
配列というのは、数学的には、数列やベクトルなんかが近い存在です。
たとえば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;
point[2] = 49;
:
:
point[9] = 91;

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

また、配列にはあらかじめ要素の数が定まっている静的配列と、定まっていない動的配列があります。
100人や1000人と、数が分かっている場合には前者を使用し、わからない場合には後者を使用します。

Page Top

今回のミソ anchor.png

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

#02 静的配列 anchor.png

Page Top

今回は… anchor.png

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

Page Top

今回のミソ anchor.png

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

サンプルコード anchor.png

filesample0802p.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
 
 
 
-
!
-
-
!
-
!
-
-
|
!
-
!
!
-
!
|
-
-
|
|
|
!
!
-
!
-
!
!
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] = to!(int)( 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;
}
+  Tango用はこちら
filesample0802t.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
 
 
 
-
!
-
-
!
-
!
-
-
|
|
|
!
-
!
!
-
!
|
-
-
|
|
|
!
!
-
!
-
!
!
import tango.io.Stdout;
import tango.io.Console;
import tango.text.convert.Integer;
 
// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    int[10] point;
    // 配列の中身すべてに対して処理を行う
    for (int i=0;i<10;i++)
    {
        // 点数入力を求めるメッセージ。
        // i+1なのは最初の人は0人目じゃなくて1人目だから。
        // ちなみに、改行しない場合は formatln ではなく、 format とします。
        // そのうえで、.flushを呼び出してやるときちんと出力されます。
        Stdout.format("{} 人目の点数を入力してください : ", i+1).flush;
        // point[i] として、添え字にアクセス。数値を入力
        point[i] = toInt( Cin.copyln() );
    }
    // 平均を出す
    int sum=0;
    for (int i=0;i<10;i++)
    {
        // すべての数値の足し算。
        // += という演算子は、
        // sum = sum + point[i]
        // とおなじ意味です。現在の値に対して加算。
        sum += point[i];
    }
    // 平均点の表示。整数で、端数切り捨て。
    Stdout.formatln("平均点は約 {} 点です", sum / 10);
    // 正常終了
    return 0;
}
Page Top

実行結果 anchor.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ 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 点です
Page Top

まとめ anchor.png

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

また、静的配列の変数を定義する際には、

int[10] a;

のようにしますが、D言語ではint[10]が型となります。 int10個の配列型ということです。
D言語では、配列は型を作ります。
つまり、

int[10][5] a;

とした場合、 ( (int型のデータ10個の配列) 型のデータ5個の配列 ) と言うことになります。 しかしながら、これだと人数があらかじめ決まっているのでコードの書き換えが必要ですね。
次回は静的配列に対して動的配列です。
動的配列では、人数が変更されてもより柔軟に対応することができます。

Page Top

#03 動的配列 anchor.png

Page Top

今回は… anchor.png

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

Page Top

今回のミソ anchor.png

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

サンプルコード anchor.png

filesample0803p.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
 
 
 
-
!
-
-
!
-
!
-
!
|
-
|
!
-
-
|
!
-
!
!
-
!
|
-
-
!
!
-
!
-
!
!
import std.stdio;
import std.conv;
import std.string;
 
// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    int[] point;
    // 何人分のテストの点数を使うかを訪ねる
    writef("何人分のテストの点数を使いますか : ");
    // テストの平均を出すのに使うテストの個数を指定
    point.length = to!(int)( chomp( readln() ) );
    
    // 配列の中身すべてに対して処理を行う
    // point.length はこの数値が何になっているかを調べることもできる。
    for(int i=0;i<point.length;i++)
    {
        // 点数入力を求めるメッセージ。
        // i+1なのは最初の人は0人目じゃなくて1人目だから。
        writef("%d 人目の点数を入力してください : ", i+1);
        // point[i] として、添え字にアクセス。数値を入力
        point[i] = to!(int)( chomp( readln() ) );
    }
    // 平均を出す
    int sum=0;
    for(int i=0;i<point.length;i++)
    {
        // すべての数値の足し算。
        sum += point[i];
    }
    // 平均点の表示。整数で、端数切り捨て。
    writefln("平均点は約 %d 点です", sum / point.length);
    // 正常終了
    return 0;
}
+  Tango用はこちら
filesample0803t.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
 
 
 
-
!
-
-
!
-
!
-
!
|
-
|
!
-
-
|
!
-
!
!
-
!
|
-
-
!
!
-
!
-
!
!
import tango.io.Stdout;
import tango.io.Console;
import tango.text.convert.Integer;
 
// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    int[] point;
    // 何人分のテストの点数を使うかを訪ねる
    Stdout.format("何人分のテストの点数を使いますか : ").flush;
    // テストの平均を出すのに使うテストの個数を指定
    point.length = toInt( Cin.copyln() );
    
    // 配列の中身すべてに対して処理を行う
    // point.length はこの数値が何になっているかを調べることもできる。
    for(int i=0;i<point.length;i++)
    {
        // 点数入力を求めるメッセージ。
        // i+1なのは最初の人は0人目じゃなくて1人目だから。
        Stdout.format("{} 人目の点数を入力してください : ", i+1).flush;
        // point[i] として、添え字にアクセス。数値を入力
        point[i] = toInt( Cin.copyln() );
    }
    // 平均を出す
    int sum=0;
    for(int i=0;i<point.length;i++)
    {
        // すべての数値の足し算。
        sum += point[i];
    }
    // 平均点の表示。整数で、端数切り捨て。
    Stdout.format("平均点は約 {} 点です", sum / point.length).flush;
    // 正常終了
    return 0;
}
Page Top

実行結果 anchor.png

1
2
3
4
5
6
7
8
$ dmd -run sample0803p.d
何人分のテストの点数を使いますか : 5
1 人目の点数を入力してください : 80
2 人目の点数を入力してください : 76
3 人目の点数を入力してください : 97
4 人目の点数を入力してください : 45
5 人目の点数を入力してください : 65
平均点は約 72 点です
Page Top

まとめ anchor.png

今回は動的配列について扱いました。
配列についてはもっといろいろなことができたりしますが、とりあえず基本的な使い方はこのような感じになります。
動的配列を使うと静的配列よりも自由度が増します。 ただし、自由度が増す分、気をつけて使用しないと非常に実行速度が遅くなってしまう危険性もはらんでいます。 どのような場合に実行速度が落ちるかというと、長さを何度も変えるような場合です。
長さを変えると、動的配列は新しい動的配列を定義し、今まで入っていた内容をコピーしようとします。 これは、イメージ的には次のコードのような感じになります。

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;
// 処理
// …

ちなみに、コピーは、配列の要素を増やすときで、連続したメモリが確保できない場合についてのみ行われます。
配列の要素数を減らす場合や、連続したメモリが確保できる場合(一度要素数を減らしたあとや、あらかじめ確保していた場合)は、コピーは行われません。
前述の2つのコードでは、前者のほうが効率が良い場合がある、ということになりますね。

このようなコピーによる時間はごく小さなものですが、あまりにも頻繁に行われる場合や、要素数が多い場合、決められた時間内に処理を終えないといけない場合(リアルタイム性のある場合)は、なるべくコピーの発生しないよう気を配るとよいでしょう。
筆者の遭遇した具体的な例としては、DirectXやOpenGL等を使った描写の際の点の配列の処理でコピーのための時間が問題になりました。

さて、今回は動的な配列として、プログラムの実行中に要素数を変えられる配列を説明しました。
次回は、添え字に、文字列など整数以外のものを利用できる連想配列というものについて説明いたします。
それではお次へどうぞ~

Page Top

#04 連想配列 anchor.png

Page Top

今回は… anchor.png

連想配列について取り扱います。ちょっと難しいので、飛ばしたい方は飛ばしても大丈夫ですよ。

連想配列というのは、添え字として、文字列など、数値以外の型を利用できる配列を言います。
他の呼び名としては、キーに対応する内容を取り出すという性質から辞書式配列とか、内部の処理から名前を取って、ハッシュとか呼ばれたりすることもあります。

サンプルコードでは、英和辞書のように、登録された単語から意味を引くプログラムを記述します。

Page Top

今回のミソ anchor.png

  • 添え字の部分に数値以外の型も利用できる配列を、連想配列という
  • 連想配列ではただの配列での添え字のことを、キー(key)と呼ぶ
  • 連想配列ではただの配列での要素のことを、(value)と呼ぶ
  • 連想配列は以下のようにして定義する
    値になる型名[キーになる型名] 連想配列の変数名;
  • 連想配列は以下のようにしてキーと値を関連付ける
    連想配列の変数名[キー] = 値;
  • 連想配列は以下のようにしてキーから値にアクセスする。
    連想配列の変数名[キー];
  • アクセスは関連付ける時のように = としない。この場合は意味が異なるので注意
  • キーから値にアクセスするときに、関連付けられていないキーでアクセスしようとするとエラーになる
  • キー in 連想配列の変数 で、連想配列にキーが関連付けられているかを確認できる
  • 連想配列の変数.keys で、キーの一覧を得ることができる
Page Top

サンプルコード anchor.png

filesample0804p.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 
 
 
-
!
-
-
!
-
|
!
-
-
!
-
!
-
!
-
-
|
!
|
-
!
|
|
-
|
!
!
|
-
-
|
!
!
|
-
-
!
-
!
-
|
!
-
|
-
|
!
|
-
!
!
|
-
-
|
!
!
!
!
|
-
!
|
-
|
|
|
|
|
!
|
|
-
|
!
|
-
!
-
-
|
|
!
!
|
-
!
!
import std.stdio;
import std.string;
 
// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    char[][char[]] dic;
    // ずっと俺のターン。
    // exitが入力されるまで辞書登録と辞書引きを繰り返す
    while (1)
    {
        // 登録するかどうかを訊ねる
        write("登録しますか?[y/n/exit] : ");
        // 返ってきた返事を command という変数に保存
        char[] command = chomp( readln() ).dup;
        // 入力を y と比較する
        if (command == "y")
        {
            // y と入力されたら単語を登録する
            // 登録する単語を入力させて
            write("単語を入力 : ");
            char[] key = chomp( readln() ).dup;
            // 続いて意味を入力させて value という変数に保存
            write("意味を入力 : ");
            char[] value = chomp( readln() ).dup;
            
            // このようにして、連想配列に key と内容を結びつけた
            // 新しい値を入力する
            dic[key] = value;
        }
        else if (command == "exit")
        {
            // exit と入力されたらプログラムを終了する
            // breakとして while (1) を抜ける
            break;
        }
        else
        {
            // y と exit 以外が入力されたら辞書を引いて表示する
            write("単語を入力 : ");
            // 入力されたものを key という変数に保存
            char[] key = chomp( readln() ).dup;
            // key in dic とすることで、連想配列内に要求された文字列が
            // 入っているか確認できる
            if ( key in dic )
            {
                
                // dic[key] として、 key に結びつけられた
                // 内容を取り出すことができる
                char[] value = dic[key];
                
                // 内容の表示
                writeln(value);
            }
            else
            {
                // もし見つからなかったら、その単語は登録されていないので、
                // その旨を表示します。
                writeln("単語が登録されていません");
            }
        }
    }
    writeln("プログラムを終了します。");
    // ついでなので、終了するときには登録された単語をすべて書き出します。
    writeln("----------今回登録された単語と意味は…----------");
    
    // char[][] は、文字列の動的配列です。
    // 文字列の動的配列の、 keys 変数を作って、
    // そこに、連想配列に登録されているすべてのキーを代入します
    // 連想配列のに登録されているすべてのキーを得るには、 .keys を使います
    // ただ、D2.0だとdic.keysから返される文字列はちょっとした処理を行わないと
    // char[][] に代入できません。以下参照。
    char[][] keys;
    keys.length = dic.keys.length;
    for (int i=0; i<dic.keys.length; i++)
    {
        keys[i] = dic.keys[i].dup;
    }
    
    // あとは得たキーの配列を使って、すべてのキーを for 文でまわしてやります
    for (int i=0; i<keys.length; i++)
    {
        // keys[i] はキーを、
        // dic[keys[i]] は、 dic から keys[i] をキーとして探して、
        // それに関連付けられた内容を示します。ちょっと複雑。
        writefln("%s:\n    %s", keys[i], dic[keys[i]]);
    }
    
    // 正常終了
    return 0;
}
+  Tango用はこちら
filesample0804t.d
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
 
 
-
!
-
-
!
-
|
!
-
-
!
-
!
-
!
-
-
|
!
|
-
!
|
|
-
|
!
!
|
-
-
|
!
!
|
-
-
!
-
!
-
|
!
-
|
-
|
!
|
-
!
!
|
-
-
|
!
!
!
!
|
-
!
|
-
|
|
|
!
|
-
!
-
-
|
|
!
!
|
-
!
!
import tango.io.Stdout;
import tango.io.Console;
 
// メイン関数
int main(char[][] args)
{
    // int型の静的配列の変数定義。
    char[][char[]] dic;
    // ずっと俺のターン。
    // exitが入力されるまで辞書登録と辞書引きを繰り返す
    while (1)
    {
        // 登録するかどうかを訊ねる
        Stdout("登録しますか?[y/n/exit] : ").flush;
        // 返ってきた返事を command という変数に保存
        char[] command = Cin.copyln();
        // 入力を y と比較する
        if (command == "y")
        {
            // y と入力されたら単語を登録する
            // 登録する単語を入力させて
            Stdout("単語を入力 : ").flush;
            char[] key = Cin.copyln();
            // 続いて意味を入力させて value という変数に保存
            Stdout("意味を入力 : ").flush;
            char[] value = Cin.copyln();
            
            // このようにして、連想配列に key と内容を結びつけた
            // 新しい値を入力する
            dic[key] = value;
        }
        else if (command == "exit")
        {
            // exit と入力されたらプログラムを終了する
            // breakとして while (1) を抜ける
            break;
        }
        else
        {
            // y と exit 以外が入力されたら辞書を引いて表示する
            Stdout("単語を入力 : ").flush;
            // 入力されたものを key という変数に保存
            char[] key = Cin.copyln();
            // key in dic とすることで、連想配列内に要求された文字列が
            // 入っているか確認できる
            if ( key in dic )
            {
                
                // dic[key] として、 key に結びつけられた
                // 内容を取り出すことができる
                char[] value = dic[key];
                
                // 内容の表示
                Stdout(value).newline;
            }
            else
            {
                // もし見つからなかったら、その単語は登録されていないので、
                // その旨を表示します。
                Stdout("単語が登録されていません").newline;
            }
        }
    }
    Stdout("プログラムを終了します。").newline;
    // ついでなので、終了するときには登録された単語をすべて書き出します。
    Stdout("----------今回登録された単語と意味は…----------").newline;
    
    // char[][] は、文字列の動的配列です。
    // 文字列の動的配列の、 keys 変数を作って、
    // そこに、連想配列に登録されているすべてのキーを代入します
    // 連想配列のに登録されているすべてのキーを得るには、 .keyes を使います
    char[][] keys = dic.keys;
    
    // あとは得たキーの配列を使って、すべてのキーを for 文でまわしてやります
    for (int i=0; i<keys.length; i++)
    {
        // keys[i] はキーを、
        // dic[keys[i]] は、 dic から keys[i] をキーとして探して、
        // それに関連付けられた内容を示します。ちょっと複雑。
        Stdout.formatln("{}:\n    {}", keys[i], dic[keys[i]]);
    }
    
    // 正常終了
    return 0;
}
Page Top

実行結果 anchor.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ 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言語:
    プログラミング言語の一種。
Page Top

まとめ anchor.png

サンプルコードがかなり複雑になってしまいましたね…
大事なところをまとめましょう。

  • 8行目の、連想配列の変数の定義の部分
  • 30行目の連想配列にキーと値を関連付ける部分
  • 46行目の連想配列にキーが関連付けられているか確認する部分
  • 51行目の連想配列で関連付けられた値にキーでアクセスする部分

こんなところでしょうか。

ちなみに、コンソールが面での日本語入力は、Windowsの場合、Alt+半角/全角キーでできるようになります。
ただ、Phobosの場合日本語の表示がめちゃくちゃになってしまうので、英語でやった方がいいかもしれませんね。

豆知識として、今回は文字列と文字列を関連付ける連想配列を作りましたが、もちろんそれ以外の方もいろいろ作ることができます。

int[int] assoc;

等とすると、intとint型を結びつけて、動的配列のようにlengthで長さを指定しなくても…

int[int] assoc;
assoc[10] = 10 * 10;
assoc[24] = 24 * 24;
assoc[1000000] = 1000000 * 1000000;

このように、ダイレクトに要素(値)を添え字(キー)と関連付けできてしまったりします。
とはいえ、このようにした場合、配列よりもメモリも計算時間もかかってしまいますので、必要な時以外は普通の動的配列などで処理した方が良いでしょう。

Page Top

#summary - まとめ anchor.png

Page Top

第08章のミソ anchor.png

  • 配列は添え字でアクセスすることができる
  • 配列は繰り返し構文と仲が良い
  • 変数名[添え字(整数)] でアクセス。
  • 添え字は0から始まる
  • 静的配列ははじめに要素数が決まる
  • 静的配列の要素数はコンパイル時に決定されていなければならない。(プログラムが走ってからは変えることができない)
  • 静的配列を定義するには以下のようにする
  • 動的配列は要素数を自由に決めることができる。
    要素の型[要素数] 変数名;
  • 動的配列は使う前は要素数を指定しておく。
  • 動的配列はコンパイル時に要素数は決定しない(プログラムが走っているときに指定してやる必要がある)
  • 動的配列を定義するには以下のようにします。
    要素の型[] 変数名;
  • 要素数を決定するには以下のようにします
    動的配列の変数.length = 要素数;
  • 配列の変数.length の中身を見ることで、現在の要素数を取得可能
  • 添え字の部分に数値以外の型も利用できる配列を、連想配列という
  • 連想配列は以下のようにして定義する
    型名[型名] 変数名;
  • 添え字の部分に数値以外の型も利用できる配列を、連想配列という
  • 連想配列ではただの配列での添え字のことを、キー(key)と呼ぶ
  • 連想配列ではただの配列での要素のことを、(value)と呼ぶ
  • 連想配列は以下のようにして定義する
    値になる型名[キーになる型名] 連想配列の変数名;
  • 連想配列は以下のようにしてキーと値を関連付ける
    連想配列の変数名[キー] = 値;
  • 連想配列は以下のようにしてキーから値にアクセスする。
    連想配列の変数名[キー];
  • アクセスは関連付ける時のように = としない。この場合は意味が異なるので注意
  • キーから値にアクセスするときに、関連付けられていないキーでアクセスしようとするとエラーになる
  • キー in 連想配列の変数 で、連想配列にキーが関連付けられているかを確認できる
  • 連想配列の変数.keys で、キーの一覧を得ることができる
Page Top

宿題 anchor.png

数人のテストの採点結果を入力し、平均点、最高点、最低点、求め方を知っていたら不偏分散、標準偏差などを求めましょう。

実行結果は次のようになりますね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
何人分のテストの点数を使いますか : 5
1 人目の点数を入力してください : 80
2 人目の点数を入力してください : 76
3 人目の点数を入力してください : 97
4 人目の点数を入力してください : 45
5 人目の点数を入力してください : 65
平均点は約 72.6 点です
最高点は97点です
最低点は45点です
分散は370.3です
標準偏差は19.243181です
Page Top

コメント anchor.png

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

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

そんなわけで、宿題できたら、あるいは予想ついたら次にいきましょう~


Page Top

投票とコメント anchor.png

Choices Vote
大変参考になった1  
参考になった0  
あまり参考にならなかった0  
まったく参考にならなかった0  

Show recent 10 comments. Go to the comment page.

  • 動的配列は動的配列は、と2重になってます -- ゲストEdit 2009-12-14 (月) 12:13:10
  • 報告ありがとうございます。直しておきました -- SHOOEdit 2009-12-15 (火) 01:14:19
  • 宿題の項目ですが、分散と標準偏差の実行結果が間違っていませんか?分散の計算の最後が5ではなく4で割られているようです。 -- ゲストEdit 2010-02-02 (火) 14:07:51
  • 分散は標本分散(5人がテストを受けたすべての人数と考える)か、不偏分散(5人はテストを受けた一部の人と考える)かで計算方法が異なります。今回の宿題の解答としましては、不偏分散で求めました。記述が足りず、申し訳ありませんでした。 -- SHOOEdit 2010-02-02 (火) 14:46:46
  • sample0804p.d ですが、上手くコンパイルが通りませんでした。 dic[key.idup] = value; とするか、 dic[to!string(key)] = value; とすることで通りました。 dmd のバージョンはは v2.069.2 です。 -- ゲストEdit 2016-01-12 (火) 21:41:51
Name:

Front page   Freeze Diff Backup Copy Rename ReloadPrint View   New Page Page list Search Recent changes   Help   RSS of recent changes (RSS 1.0) RSS of recent changes (RSS 2.0) RSS of recent changes (RSS Atom) Powered by xpWiki
Counter: 3329, today: 1, yesterday: 0
Princeps date: 2010-02-21 (Sun) 11:22:54
Last-modified: 2016-01-12 (Tue) 21:41:52 (JST) (1753d) by ゲスト
メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu