fc2ブログ

Dをつつく24-反復文2。お決まり手順は省略。

D言語の反復/繰り返し処理の記事はこれで最後ピヨ。
せっかちだけど、さっそくサンプルプログラムを見てね。

import std.stdio;

int main( char[][] ) {
    string[] array;
    array.length = 5;
    array[ 0 ] = "中博俊";
    array[ 1 ] = "じゃんぬねっと";
    array[ 2 ] = "夏椰";
    array[ 3 ] = "なおこ(・∀・)";
    array[ 4 ] = "まゆりん";
 
    writeln( "わんくま同盟の皆さんを番号順に", 
        array.length, "名表示します・・・" );
    foreach( int i, string str; array ) {
        writeln( i, "番", str, "さん" ); 
    }
    return 0;
}

D言語のforeach文はちょっと面白いピヨ。 VB.NETでは普通一つの要素を指定するんだけど、D言語の場合は インデックスと値の両方を指定できるピヨ。 ちょっと凄いよね。今回のサンプルプログラムでもこの機能が役立ったピヨ。 地味だけど結構便利だよね。
話しは変わるけど、実はこのサンプルプログラムforeach文以外の注目ポイントがあるんだ。 分かったかな?注目点はstringの文字列型ピヨ。 D言語では文字列はinvariant(char)[]の代わりにstring が用意されているピヨ。 いちいちこんなにもタイプするの面倒だから特別にstringが用意されているんだ。親切だよね。 でもstringはタイプ量を減らすだけの効果ではないんだ。 サンプルプログラムの代入文をよく見てごらん。"文字列".dupがないよね。これはinvariantキーワードが指定されているからなんだよ。 stringは実に便利だよね。
これからは、char[]よりもstringを使用しよう。
D言語にはまだ他にもforeach range 文という見慣れない文があるんだ。 今回はちょっと長いけど、がんばってforeach range文をつつこう。


鳥ゃーバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサ

import std.stdio;

int main( char[][] ) {
    string[] array;
    array.length = 5;
    array[ 0 ] = "中博俊";
    array[ 1 ] = "じゃんぬねっと";
    array[ 2 ] = "夏椰";
    array[ 3 ] = "なおこ(・∀・)";
    array[ 4 ] = "まゆりん";
 
    writeln( "わんくま同盟の皆さんを番号順に", 
        array.length, "名表示します・・・" );
    foreach( int i; 0..array.length ) {
        writeln( i, "番", array[ i ], "さん" ); 
    }
    return 0;
}

foreach文と違って foreach rang文は開始値と終了値が指定できるんだ。 だけどその代わり、 foreach rang文はインデックスと値を指定できないんだ。 何故なら、 foreach rang文の変数はカウンタ だからピヨ。何にでも長所と短所があるって事だね。
今回はお疲れ様でした。お終い。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく23-反復文1。前判定か後判定かそれが問題だ。

今回は毎度同じ前判定型のwhile文と 後判定型のdo/while文をさくっとつつこう。

import std.stdio;

int main( char[][] ) {
    int i = 100;
    
    while( i != 100 ) writeln( "前判定をクリアしたよ。" );
    do { writeln( "後判定だから表示されるよ。" ); } while( i != 100 );
    return 0;
}

このサンプルプログラムを実行すると「後判定だから表示されるよ。」しか表示されない。 何故ならば、変数iが100だからwhile文の条件判定を満たさないからなんだ。
この二つの文の使い分けは最低1回は実行したいか という点なんだ。必ず処理を1回はしたいのならばdo/while文を、 1回も実行しなくていい場合はwhile文を使うんだ。
今回は本当に言う事がないや。お終い。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく22-反復文。基本を忘れちゃらめぇ。

インドリィちゃん「for文が足りないぃぃ」
インドリ「えっ???!いきなり何?」
インドリィちゃん「for文が解説が足りないぃぃ」
インドリ「!そういえば書いて居なかったヨ。ごめん、ごめん。」
インドリィちゃん「さっさと詳解しなさい」
インドリ「紹介じゃなくて詳解?」
インドリィちゃん「他言語を習得した人用の記事だから当たり前でしょょ。」
インドリ「分ったよ。」


バサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサ


import std.stdio;

int main( char[][] ) {
    //普通のfor文
    writeln( "普通のfor文を実行します。" );
    for(int i = 0; i < 10; i++) write( i );
    write( "\n" );

    //省略したfor文
    writeln( "nitializeとtest部分を省略したfot文を実行します。" );
    int x;
    for(;;x++) {
        if( x > 10 ) break;
        write( x );
    }
    write( "\n" );

    //コードが空のfor文
    writeln( "コードが空のfor文を実行します。暫らくとまったように見えますw" );
    for(int i = 0; i < 1_000_000_000; i++ )
    {
        //ブロックの開始と終了は省略できません。
    }

    return 0;
}

C言語の正統後継言語を目指しているD言語らしい仕様だよね。
えっ!2番目のfor文が何故変数xなのかって? それはねぇ、変数iにすると次のエラーになるからなんだ。
Error: shadowing declaration for.main.i is deprecated
さすが新しい言語だよね。バグの元となりやすい部分をエラーにしている んだ。案外こういったところにバグが生まれるから、これはいい考えだよね。
他にも反復文はあるけど、詳解したら長くなったので次回へ続くよ。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく21-コンストラクタ。静的コンストラクタ。後ろの少年だぁあーれ♪

今回はコンストラクタ をつつくピヨ。コンストラクタで確認するべきことは色々あるピヨ。

  • 宣言文
  • 実行順序
  • 親クラスのコンストラクタを呼び出す方法
  • 親クラスのコンストラクタが自動で呼び出されるか否か
  • 他のコンストラクタの呼び出し方法
  • 複数定義できるか否か


ボクの経験から言ってこれらのことを確認するプログラムを書くといいピヨ。 じゃあ早速コーディングしよう。


バサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサバサ


import std.stdio;

class Monster {
    this() { writeln( "モンスターペアレント参上!" ); }
}

class Child {
    this() { writeln( "子供が登校します。" );  }

    this( ubyte count) {
        this(); //他のコンストラクタを呼び出す
        for( ubyte i = 0; i < count; i++) writeln( "わーい" );
    }
}

int main( char[][] ) {
    Child c = new Child( 3 );
    return 0;
}

このプログラムを実行してみよう。次の様に表示されたはずピヨ。
モンスターペアレント参上!
子供が登校します。
わーい
わーい
わーい
どうやら 親クラスのコンストラクタは自動で呼び出される様だね。
じゃあ、どうしても呼び出したい時はどうするのかというと、 superを使うんだ。 サンプルプログラムのthis()の部分をsuper()に変えて実行してみよう
これで終わりと思った人も多いと思うけど、あと 静的コンストラクタ という機能があるピヨ。
早速コードを書いたピヨ。

import std.stdio;

class StaticFoo {
public:
    static int X = 10;
    static int Y = 10;
    //static Z = X * Y;
    static int Z;
    
    static this() { Z = X * Y; }
}

int main( char[][] ) {
    StaticFoo foo = new StaticFoo();
    writeln( "静的フィールドZの値=", foo.Z );
    return 0;
}

このサンプルコードで読み取れるけど、静的コンストラクタとは 静的フィールドを設定する為の機能だんだ。 静的フィールドは定数しか指定できないから、 計算が必要な静的フィールドの値を導出する場合は静的コンストラクタを使うんだ。
それを確かめたい人はコメントアウトされている部分の//記号を取って、 静的コンストラクタのコードともう1つのZフィールドのコードをを消してコンパイルしてみて。 そうすると・・・
staticconstrutor.d(7): Error: non-constant expression X * Y
と表示されるピヨ。これで納得いったよね♪
それじゃあすっきりしたところでお終い。またみてね♪

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく20-プロパティ。えっ!あったの?

前回の記事を読んで気になった人が居ると思う「プロパティは無いの?」ってね。 実はボクもマニュアルを見て驚いたピヨ。 だから、 Dをつつく1ーまずは学習環境を整えよう に書かれている参考ホームページを飛び回ってプロパティを探したんだ。
そしたら、やっぱりあったんだ。感覚としてはJavaに近い形でね。 Dマニュアルに書いてあるコーディング規則を読んだ時「Javaっぽい」と思ったけど、 D言語はやっぱりJavaに大きく影響を受けているね。
じゃあさっそくサンプルプログラムを見て♪見て♪見て♪

import std.stdio;

class Foo {
private:
   //フィールド
   int x, y, z;
public:
   //プロパティ
   int X() { return x; }
   void X( int value ) { x = value; }

   int Y() { return y; } //読み取り専用
   void Z( int value ) { z = value; } //書き込み専用

   //コンストラクタ
   this( int yvalue ) { y = yvalue; }
}

int main( char[][] ) {
    Foo f = new Foo( 100 );
    f.X = 10;
    writeln( "プロパティXの値=", f.X );
    writeln( "プロパティYの値=", f.Y );
    //エラー発生
    writeln( "プロパティZの値=", f.Z ); 
    f.Z = 123;
    return 0;
}

このコードをコンパイルしてみて。次のメッセージが表示されると思う。

property.d(24): function property.Foo.Z (int) does not match parameter types ()
property.d(24): Error: expected 1 arguments, not 0

このメッセージを読むとD言語がプロパティを認識している事と、 書き込み専用プロパティが正しく動作している事が分るピヨ。 D言語はプロパティの記述に柔軟さを持たしているんだね。 でも公式マニュアルのクラスにプロパティの説明が載っていないのはいただけないなぁ。 きっとドリィちゃんなら「親切心が足りないぃぃ」って言うぞ。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく19-クラス。何が出来るかな♪

いよいよD言語の解説記事もオブジェクト指向に突入するピヨ。他言語を知っている人にとって文法的な事を説明してもしかたが無いから、今回はD言語のクラスが持てるものを列挙するピヨ、

  • 基底クラス
  • インターフェイス
  • 動的フィールド
  • 静的フィールド
  • 静的関数
  • 仮想関数
  • コンストラクタ
  • デストラクタ
  • 静的コンストラクタ
  • 静的デストラクタ
  • 不変条件
  • 単体テスト
  • アロケータ
  • デアロケータ

幾つか見慣れないものあるよね。これはD言語の特徴となる要素でこれからつついていくよ。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく18ー共用体。皆で仲良くルームシェア。

おはピヨ。今回は共用体を楽習するぞ。 共用体というものを使った事が無い人が居ると思うからまずは説明するピヨ。 共用体というのは、同じ記憶空間を共用する構造のことだピヨ。
例えば、共用体にuintとushortのフィールドがあって、uintに0xAAAABBBBの値を代入したら、共用されているからushortのフィールドの値はBBBBになるんだ。
早速実験してみよう。

import std.stdio;

union Register {
public:
    ushort AX;
    uint EAX;
}

int main( char[][] ) {  
    Register reg;
    writeln( "共用体のサイズ", reg.sizeof );
    reg.EAX = 0x_AAAA;
    writef( "EAX=%x", reg.EAX, "\n" );
    writeln( "AX=", reg.AX );
    return 0;
}

このサンプルプログラムを実行してみよう。EAXフィールドの値が0xAAAAならば、AXフィールドの値も0xAAAAになるはずピヨッ。あれ?0が出たぞ?どうなっているんだ・・・
静的初期化じゃなければだめなのかなぁ?

import std.stdio;

union Register {
public:
    ushort AX;
    uint EAX;
}

int main( char[][] ) {  
    Register reg;
    writeln( "共用体のサイズ", reg.sizeof );
    reg.EAX = 0x_AAAA;
    writef( "EAX=%x", reg.EAX, "\n" );
    writeln( "AX=", reg.AX );
    reg.AX = 5;
    writef( "EAX=%x", reg.EAX, "\n" );
    writeln( "AX=", reg.AX );

    //静的初期化
    static Register reg1 = { EAX:0x0000AAAA };
    writef( "EAX=%x", reg1.EAX, "\n" );
    writeln( "AX=", reg1.AX );
    return 0;
}

あれぇ・・・やっぱり駄目だ。共有されていない。しかも構造体と同じ動きをするぞ・・・
もうこれはdmd2.014のバグとしか思えないピヨ。
この現象の解決法を知っている人はコメントで教えて下さい。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく17-構造体。初期化法がチャームポイント。

今回はD言語の構造体について一緒に楽習しよう。
D言語は構造体の初期化方法に 特徴があるからそれをつつくピヨ。


import std.stdio;

struct Foo { int A; int B; int C = 7;}

int main( char[][] ) {
    //動的初期化
    Foo f;
    writeln( "Foo構造体のAフィールドの初期値=", f.A );
    writeln( "Foo構造体のBフィールドの初期値=", f.B );
    writeln( "Foo構造体のCフィールドの初期値=", f.C );
    writeln( "" );

     //静的初期化
    static Foo g = { A:2, B:3 };
    writeln( "Foo構造体のAフィールドの初期値=", g.A );
    writeln( "Foo構造体のBフィールドの初期値=", g.B );
    writeln( "Foo構造体のCフィールドの初期値=", g.C );
    return 0;
}


どう感じた?ボクは静的初期化にD言語の工夫を感じたピヨ。
静的構造体は
{ フィールド名:(コロン記号) }
と書いて初期値を設定するんだ。便利そうな構文だね。
そろそろ、D言語らしさが出てきたようだね♪
期待させておいて申し訳ないのだけど、構造体についてはひとまずお終い。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく16-シフト演算。スイ~スイ~。

さて、今回はD言語のシフト演算を確認しよう。他の言語を経験している人は面倒なだけと思うだろうけど、意外とチェックするポイントがあるピヨ。
まぁ、気楽にこのコードを実行してみて。


import std.stdio;

int main( char[][] ) {
    int value = -8;
    writeln(value, "を1ビット右シフトすると「", value >> 1, "」になった");
    value = -8;
    writeln(value, "を1ビット左シフトすると「", value << 1, "」になった。");

    //オーバーフローした場合をチェック
    value = 2;
    writeln(value, "を32ビット左シフトすると「", value << 32, "」になった。");
    value = 2;
    writeln(value, "を32ビット右シフトすると「", value >> 32, "」になった。");
    return 0;
}


このコードを見ればボクがチェックするべきだと言った理由が分ると思う。 シフト演算を普通に使っている時は言語ごとの差異は記号ぐらいしかないけど、 オーバーフローした時の挙動は言語ごとに違うピヨ。 注意してね。
ところでこのコードの実行結果はどうだった?
オーバーフローで例外が発生しないと思わなかったでしょ?
多言語を扱う場合はこういった盲点を事前にチェックしておこう。
ドリィちゃん「なに偉そうな事言っているのよ。それ私が貴方に言った事でしょょw」
う、うん。まぁね。ええと・・・。と、とにかく、これ以上ドリィちゃんに何か言われる前に終わり。

テーマ : プログラミング
ジャンル : コンピュータ

Dをつつく15-論理演算。バイナリの必須アイテム。

今回は論理演算に関する確認ピヨ。「Cとどうせ同じだろ?」と思う人もいるだろうけど油断大敵。 多言語を学習するとたまに混乱するから確認だけしておいてメモしておこう。 そうした地道な積み重ねが技術者としての力を生むんだ。
という事でコードを見てね。


import std.stdio;

int main( char[][] ) {
    bool x;
    bool y;

    //Or演算
    x = true;
    y = false;
    writeln( "x = ", x, "y = ", y, "のOr演算の結果は?\t", x | y );
    x = false;
    y = false;
    writeln( "x = ", x, "y = ", y, "のOr演算の結果は?\t", x | y );
    x = true;
    y = true;
    writeln( "x = ", x, "y = ", y, "のOr演算の結果は?\t", x | y );
    writeln( "" );

    //And演算
    x = true;
    y = false;
    writeln( "x = ", x, "y = ", y, "のAnd演算の結果は?\t", x & y );
    x = false;
    y = false;
    writeln( "x = ", x, "y = ", y, "のAnd演算の結果は?\t", x & y );
    x = true;
    y = true;
    writeln( "x = ", x, "y = ", y, "のAnd演算の結果は?\t", x & y );
    writeln( "" );

    //Xor演算
    x = true;
    y = false;
    writeln( "x = ", x, "y = ", y, "のXor演算の結果は?\t", x ^ y );
    x = false;
    y = false;
    writeln( "x = ", x, "y = ", y, "のXor演算の結果は?\t", x ^ y );
    x = true;
    y = true;
    writeln( "x = ", x, "y = ", y, "のXor演算の結果は?\t", x ^ y );
    writeln( "" );
    
    return 0;
}


これで確認OKピヨ。でもこれだけじゃ面白くないから1つ面白い事を教えるピヨ。
このプログラムの文字列以外のところに 全角スペースを使ってみて。 どう?珍しいエラーが出たでしょう。
これは何かというと。文字コードに関するトラブルなんだ。 Dコンパイラのソースを見たところ、 0x3eで始まるUNICODE文字はスキャナでANSI文字列と見なされて その結果、Lexerのscanメソッドの
if (isprint(c)) 
error("unsupported char '%c'", c); 
else 
error("unsupported char 0x%02x", c); 
p++; 
continue; 
} 

の部分でエラーを出力されるピヨッ。 その理由はANSIでは<にあたるからなんだ。 なお、UNICODE-8では先頭バイト00-7FはANSIの制御文字に当たるんだよ。
だから 全角スペースを使用したら絶対に駄目。 でもこれはパーサーのプログラムミスだと思うピヨね。 パーサーがちゃんと全角スペースを取り除いていればこの部分へ到達する事は無い筈。 もしかしたらそうしない理由があるのかもしれないけどね。

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター