わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

尺取り虫プログラム〜結局,何がしたかったか

まずは,これまでのエントリを.

今,見直してみると,名称が不適切でした.「尺取り虫」になっていません.「蛇行」か「千鳥足」ですかね.あと,「経路」よりも「順路」のほうがよかったか.
さて,何をしたかったか.というと,これです.

ところでこれは,Cで書く場合,構造体を用いるとコーディングの見通しが良くなる典型例です

以下はこの「尺取り虫プログラム」の考察として,構造体を用いてコードにすることで,どのようなメリットがあるかを,述べることにします.
実用的なメリットの一つは,関数の引数に悩まなくなることです.
構造体宣言のあと,その構造体に作用する関数を定義するには,

戻り値の型 関数名(構造体 *引数)
{
}

とします.もちろん,他の引数が必要なら,追加していきます.
今回作った2つのプログラム,mainを除いて,自作関数はこの形になっています.
もし,構造体を用いなければ,一つ目(8月7日)のinchworm_moveは

void inchworm_move(int *x, int *y, int *step, int *dir)
{
}

のような引数になります*1.とはいえ,保守性を考えると,「x座標を格納する変数」と「そのポインタ」は,名前を区別しておくべきかもしれません.
上の構造体なし関数には,変数の数や名前のほかに,不便な点があります.二つ目(8月11日)には,方向を格納する変数がなくなっているので,「, int *dir」を取り除かないといけません.関数宣言部だけでなく,呼び出しのところもですし,関数プロトタイプを書いていたら,そこも怠ってはいけません.
「いけません」を連発しましたが,それだけ,構造体を使わないというのは,茨の道なのです.
なお,「(2次元)座標だから,構造体」ではない,というのは強調しておきたいと思います.構造体と関数の組み合わせは,座標処理に限らず有用です.
複数の値を持つ1個の実体に対して,さまざまな関数呼び出しをしたいのだけど,ある呼び出しでは,実体の中のあの情報,別の呼び出しでは,実体の中のこの情報,また別の呼び出しでは,実体の持つ情報全部,と,参照したり変更したりする情報が異なるような場合に,引数をこまごまと書くのではなく,構造体(通常はそのポインタ)を引数とすれば,引数に悩まされませんし,また関数プロトタイプを並べて見ると統一した「処理群」が出来上がるのです.
構造体を用いれば,向きの情報を増やそうが減らそうが,関数の宣言も呼び出しも,変更しなくてよいわけです.これを情報隠蔽と言います.「情報隠蔽」とだけ書くと,あまりいい響きではないのですが,プログラミングに限れば,読みやすく書きやすくする便利な手法なので,頭の片隅に入れておきたいものです.私自身は,「情報隠蔽」の概念を,オブジェクト指向プログラミングを通じて知りました.
これをもとに,メリットの2番目として,「戻り値の型 関数名(構造体 *引数)」の形で,構造体に作用させる関数の読み書きに慣れておけば,オブジェクト指向プログラミングの移行が容易になることが,指摘できます.
コード例は言語ごとに異なるので,提示することができず,概略の説明となりますが,クラス定義の中に,「戻り値の型 関数名(構造体 *引数)」の関数をコピーして,「構造体 *引数」をなくし,構造体のメンバのアクセスのところを,その言語に適した形にすればいいのです.逆すなわち,オブジェクト指向言語で書かれたコードを,Cに変換する必要に迫られたときにも,役立つでしょう.

*1:グローバル変数を使用するという方法も考えられますが,保守性が良くないのは,よく知られているとおりです.