Sponsored Link
 
>>  Main > Programing > Primary > 0013

D言語入門 第13章 - その他の文法1

#01 - with文

今回は…

以前構造体を使用しましたね。
今回は、その構造体のメンバを一気にまとめて変更したい場合なんかに有効な文法 with 文を紹介します。
この文法はC言語には存在しません。
このキーワードが存在する言語としては、JavascriptをはじめとするECMAScript系の言語なんかが有名ですね。

今回のミソ

  • with(構造体の変数){ 処理 }
  • 上の処理のところでは、構造体の変数の名前を使用しなくてもその構造体の中身にアクセスできる

サンプルコード

import std.stdio;

// 構造体 MyStruct を定義
struct MyStruct
{
    // int型のメンバ変数aを定義
    int a;
    // int型のメンバ変数bを定義
    int b;
    // int型のメンバ変数cを定義
    int c;
    // int型のメンバ変数xを定義
    int x;
    // int型のメンバ変数yを定義
    int y;
    // int型のメンバ変数zを定義
    int z;
}

int main(char[][] args)
{
    // 構造体MyStruct型の変数 mystruct を宣言
    MyStruct mystruct;
    // mystructを初期化します
    with (mystruct)
    {
        // mystruct.a = 10; とおなじ
        a = 10;
        // mystruct.b = 20; とおなじ
        b = 20;
        // mystruct.c = 30; とおなじ
        c = 30;
        // mystruct.x = mystruct.a*4; とおなじ
        x = a*4;
        // mystruct.y = mystruct.b*5; とおなじ
        y = b*5;
        // mystruct.z = mystruct.c*6; とおなじ
        z = c*6;
    }
    // with文は初期化以外にも利用できます
    with (mystruct)
    {
        // writeln("a = %d", mystruct.a); とおなじ
        writefln("a = %d", a);
        // writeln("b = %d", mystruct.b); とおなじ
        writefln("b = %d", b);
        // writeln("c = %d", mystruct.c); とおなじ
        writefln("c = %d", c);
        // writeln("x = %d", mystruct.x); とおなじ
        writefln("x = %d", x);
        // writeln("y = %d", mystruct.y); とおなじ
        writefln("y = %d", y);
        // writeln("z = %d", mystruct.z); とおなじ
        writefln("z = %d", z);
    }
    return 0;
}

実行結果

a = 10
b = 20
c = 30
x = 40
y = 100
z = 180

まとめ

というわけで、with文。使いどころが難しいかもしれませんが、使えるところでは使えますよ。
具体的には、もっと先でやるclassのメソッドやプロパティと呼ばれるものにもアクセスできたりするので、オブジェクト指向向きの文法と言えます。
今のところは構造体をもっと使いやすくする方法という感じで覚えておくといいかもしれませんね。

#02 - switch文

今回は…

switch文を説明します。これは条件分岐の一種の文法です。なので、ifやelseを使用しても同じ挙動が期待できる場合が多いです。
ただ、switch文は、C言語にも存在する割とベーシックな文法です。いろいろなところで見るかと思いますので、一応触れておきます。
if文で十分に代用可能な文法ですが、もしかしたら最適化が計れて速度的に有利になることがあるかもしれません。あまり期待はできないけど。
特に、Windowsプログラミングにおけるウィンドウプロシージャの内部処理には頻繁に登場する文法です。
個人的にはswtich文の文法が若干気味悪く感じるのでifを使うことのほうが多いですが…

今回のミソ

  • switch(){ 分岐 } を使うと多条件分岐になる。
  • 分岐には case文とdefault文を使う
  • case :になった場合、そこへ飛ぶ。
  • が複数ある case : のどのにも当てはまらなかった場合、 default: へ飛ぶ。
  • 終わる場合は break を使う。
  • breakしないcase文はその次のcase文もつづけて実行する。
  • switch ()
    {
        case(値1):
            値1だったときの処理;
            break;
        case(値2):
            値2だったときの処理;
            break;
        default:
            デフォルトの処理;
    }
  • (上のような感じなのですが、わかりにくいと思うのでサンプルを見ましょう)

サンプルコード

import std.stdio;

// x の値によって処理の内容を振り分ける関数 Switching の定義
void Switching(int x)
{
    switch(x)
    {
        case(0):
            writefln("零の場合");
            break;
        case 1: // ()でくくらなくても大丈夫だけど…
            writefln("一の場合");
            break;
        case(2):
            writefln("二の場合。breakがないので次のも実行。");
        case(3):
            writefln("三の場合");
            break;
        default: // デフォルトの挙動はできる限りあったほうが良い。
            writefln("デフォルトの挙動");
    }
}

int main(char[][] args)
{
    // 零の場合
    Switching(0);
    // 一の場合
    Switching(1);
    // 二の場合。breakがないので次のも実行。
    // 三の場合
    Switching(2);
    // 三の場合
    Switching(3);
    // デフォルトの挙動
    Switching(4);
    return 0;
}

実行結果

零の場合
一の場合
二の場合。breakがないので次のも実行。
三の場合
三の場合
デフォルトの挙動

まとめ

switch文は使いどころが限られます。正直ifのほうが使いやすかったりもします。
ただ、何度も if(x == 1){ ... }else if(x == 2){ ... } といったように x == ... のような似たような条件を繰り返して使いたくない場合に使うといいと思います。
………ほかにswtichの有用性について知っている方がいたら教えてください>ここから

#03 - foreach文

今回は…

foreach文です。foreach文は繰り返し構文の一種です。
foreach文はC言語では使用できません。利用できる言語はWikipediaを見るといいでしょう
foreach文は配列などに関して、すべての要素に対して処理を行う場合に非常に便利な文です。
配列など、というのは他にも使えるものがあって、ある特定の条件を満たした構造体、クラス、連想配列にも使うことができるます。これらはのちの講座で解説します。

今回のミソ

  • foreach(val;list){ ... }
  • vallistの中のデータが一つずつ入る
  • foreach文を使うと、breakするかすべての要素をめぐるまでループする
  • valは型名などを使ってもよいが、使わなくても勝手に推測してくれる
  • foreach(ref val;list){ ... } とすると、リストの要素の変更が可能

サンプルコード

import std.stdio;

int main(char[][] args)
{
    // 配列の変数 list を定義して初期化しておく
    int[5] list;
    list[0] = 4;
    list[1] = 3;
    list[2] = 2;
    list[3] = 5;
    list[4] = 7;
    // すべての要素を表示します
    foreach (val; list)
    {
        writefln(val);
    }
    // ref をつけると要素の変更ができます。
    foreach (ref val; list)
    {
        // すべての要素を8にする
        val = 8;
    }
    // i には添え字が入ります。
    foreach (i,ref val; list)
    {
        val = i + val + list[ (i+4) % list.length ];
    }
    // すべての要素を表示します
    // 変更された内容を確認してください。
    foreach (val; list)
    {
        writefln(val);
    }
    return 0;
}

実行結果

4
3
2
5
7
16
25
35
46
58

まとめ

さてforeachもswitch同様forやwhile文で同じものが記述できます。
では、いったい何がいいのか。
まず、その一つとして、このような配列をすべて廻るようなものでは添え字が配列に対して大きすぎる値を入力することが少なくなります。バグの原因を減らせます。
ほかにも、簡単な記述が可能ということや、限定された使い方であるため最大の効率化が期待できたりもします。(これもやはりあまり期待できませんが。)
D言語では、人によってはfor文以上に使うことが多くなるかもしれませんね。

#04 - goto文

今回は…

goto文についてお話します。
この構文はまずほとんど使うことはないと思います。
なので軽めに。

goto文は古くはアセンブリの時代から非常に愛されてきた文です。
forやwhileなどの繰り返し文にも代用として使えますし、switch文の代用にもすることができる、非常に強力な文です(笑)。

ちなみに、なんでほとんど使わないかというと、プログラムが煩雑になりやすいからです。
あちこちにジャンプして、流れがつかみにくいプログラム、それを、スパゲッティプログラムと言います。
そんなコードを書かないように注意しましょう。

今回のミソ

  • LABEL: としてラベルを定義
  • ラベルの定義は";"(セミコロン)じゃなく":"(コロン)なので注意。
  • goto LABEL; としてラベルにジャンプする
  • gotoを使うとプログラムコードが煩雑になりやすいため、使いどころを考えなければならない

サンプルコード

import std.stdio;

// 注意!この goto の使用例は非常に悪い使用例です。
// 流れが無駄に複雑になっています。
// このように、goto文は下手に使うとすぐに、
// ごちゃごちゃした読みにくい、保守のしにくい、汚い、臭い、しょっぱい
// コードになってしまいます。
// 用法と容量を正しく守った上、ご使用ください。

int main(char[][] args)
{
    
    // この後出てくるラベル5にジャンプ
    goto L_LABEL5;
    
    // ラベルを定義
L_LABEL1:
    writefln("L_LABEL1");
    
    // ラベル3にジャンプ
    goto L_LABEL3;
    
L_LABEL2:
    writefln("L_LABEL2");
    goto L_LABEL1;
L_LABEL3:
    writefln("L_LABEL3");
    goto L_END;
L_LABEL4:
    writefln("L_LABEL4");
    goto L_LABEL2;
L_LABEL5:
    writefln("L_LABEL5");
    goto L_LABEL4;
L_END:
    writefln("L_END");
    return 0;
}

実行結果

L_LABEL5
L_LABEL4
L_LABEL2
L_LABEL1
L_LABEL3
L_END

まとめ

サンプルコードではgoto単体として使っていましたが、ふつうはif文などと組み合わせて使用します。
もし値が1ならLABEL1にジャンプする…と。このように使うのですが、これはswitchでできますし、関数なんかにまとめたほうがよっぽど読みやすいコードになります。
できる限りgoto文をなくすようにしましょう。

#summary - まとめ

第13章のミソ

  • with(構造体の変数){ 処理 }
  • 上の処理のところでは、構造体の変数の名前を使用しなくてもその構造体の中身にアクセスできる
  • switch(){ 分岐 } を使うと多条件分岐になる。
  • 分岐には case文とdefault文を使う
  • case :になった場合、そこへ飛ぶ。
  • が複数ある case : のどのにも当てはまらなかった場合、 default: へ飛ぶ。
  • 終わる場合は break を使う。
  • breakしないcase文はその次のcase文もつづけて実行する。
  • switch()
    {
        case(値1):
            値1だったときの処理;
            break;
        case(値2):
            値2だったときの処理;
            break;
        default:
            デフォルトの処理;
    }
  • foreach(val;list){ ... }
  • vallistの中のデータが一つずつ入る
  • foreach文を使うと、breakするかすべての要素をめぐるまでループする
  • valは型名などを使ってもよいが、使わなくても勝手に推測してくれる
  • foreach(ref val;list){ ... } とすると、リストの要素の変更が可能

宿題

この章で紹介したサンプルコードをすべてwith,switch,foreach,for,while文を使わずに期待される動作を全く同じになるように記述してみてください。

コメント

今回の宿題はつまり、繰返しや分岐を使わないで、どのようにプログラムが流れているかを確認するためのものです。
goto文を使って再現してみるのもいいかもしれません。あまり役には立たないと思うけど。 そんなわけで、宿題できたら、あるいは予想ついたら次にいきましょう~

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