コマンドの連携による問題解決とアニメーション

定数名と変数名の付け方について

C言語プログラムC言語プログラムにおいて,プログラム実行中に変化しない定数をソースプログラム中に直接書くとその数値の意味が分からなくなる(マジックナンバー)ので,それを避けて#define命令を使って「マクロ定義」としてプログラムの先頭部分に書いて置くのが良いことが,教科書4.2節に記載されています.この際,#define命令を使って定義する「定数」は全部大文字の名前とするのが慣習になっています.それにより,全部大文字だけの「名前」を見たときに「これは変数でなく#define命令を使った定数」と瞬時に判断出来るようになり,プログラムの理解を助ける効果があります.

良い定数の書き方例:
#define LIMIT 100

悪い定数の書き方例:
#define size 250   // sizeは変数なのか定数なのか見分け難い.

また,変数名は「英小文字で始まる名前」にする慣習もあり,これにより同様にソースプログラムを見た瞬間に「あ,これは変数だ」と理解しやすくなります.さらに,変数名や定数名はその意味(使い道,目的)が分かりやすいように,程々の長さを持つ英単語やローマ字書きを使うようにしましょう.

例えば,変数 limit なら「何かの限界を表す変数」というのが読み取れますが,l(エル)だと,line(線の何か)なのかlength(長さ)なのかleft(左)なのか,即座には分からなくなります.また,何か円を描くグラフィックスプログラムを作成しているなら,その円の中心座標を表す変数として x, y とするよりは centerX, centerYとした方がより分かりやすくなるでしょう.

但し,for文の実行制御につかう「カウンタ変数」については,習慣的に i とか j とか極めて短い変数名が使われる事が多いので,これについては例外的と思ってください.恐らく,配列要素番号に使われて頻繁に出てくる事が多くて,長い変数名だとかえってプログラムが見辛くなるためだと思います.

「今,プログラムを書いている自分にはバッチリ分かってるから,どんな変数名のつけ方でも問題ない」とか思ってませんか? そのソースプログラムを一週間放置した後に再度読み返してみてください.恐らく,「あれ?この変数は何の目的で使う変数だっけ?」と記憶があやふやになっているはずです.一ヶ月後には「全く覚えてない」状態になるでしょう.プログラミング業界では「一週間後の自分(の記憶)は他人(の記憶)」と言われるそうです.人間の記憶というのはそれほど「頼りにならない」ということです.

ちなみに,ソースプログラムを適切にインデントしたり改行したりして「美しい状態」になるように書きましょうと言われるのも,それによってプログラムの理解を助ける効果があると分かっているからです.心して「美しく見えるソースプログラム」を作成するようにしてください.

自作したC言語プログラムとUnixコマンドの連携

C言語プログラムでprintf()関数を使うと画面(正確にはターミナルウィンドウ内)へ文字メッセージが出力されることを既に学んだ.これは正確に言えば「コマンド入出力のリダイレクションとコマンドパイプライン」の学習内容にて学んだ「標準出力」へ文字データが出力されていることを意味している.

Unixでは,自作したプログラムも標準コマンドも標準入出力の取り扱いに区別が無いため,自作プログラムと一般のコマンドを組み合わせる事が容易に出来る.ここでは,自作プログラムとGNUPLOTを組み合わせて簡単な数学グラフのアニメーションを表示することを考える.

GNUPLOTは各種のグラフを描画処理するプログラムだが,グラフ描画の命令をキーボードから与える代わりに,事前に「テキストファイル」として命令内容を準備しておき,それをリダイレクション,或いは,パイプラインを用いて標準入力から読み取らせて動作させることが出来る.尚,CSE環境に導入されているGNUPLOTをそのように使う場合,コマンドとして以下の少し長めの絶対パス名で指示する.

/Applications/gnuplot.app/bin/gnuplot

例として,一次関数と二次関数のグラフを重ねて描画して,それをアニメーション表示するための命令を並べたテキストファイルを以下に用意してある.

このファイルをコピーして各自の適当な作業ディレクトリに配置し,以下の要領でGNUPLOTに読み取らせて動作させてみよ.

$ /Applications/gnuplot.app/bin/gnuplot < sample.plt
$ cat sample.plt |  /Applications/gnuplot.app/bin/gnuplot

この操作の考え方を図示すると以下のようになる..

このsample.pltにはGNUPLOTの命令が書き並べてあり,GNUPLOTは,これらの命令が標準入力より与えられれば,それを順番に実行して画面にグラフを描画してゆく.

この例では,少しずつ異なったグラフが連続して描画される結果,人間の視覚にはグラフが動いて見える.これがアニメーションの基本原理である.

尚,GNUPLOTのコマンド命令のうち,pauseコマンドは,そこで指定された秒数だけ一時停止するというコマンドであり,これによりアニメーションが目に留まるようにしている.もし,この一時停止が無ければ,GNUPLOTは全速力で全てのグラフを描画してしまって,あまりに速すぎて肉眼では見えない.

ここで,このテキストファイルと同じ内容を標準出力へ吐き出すC言語プログラムが

である.これを各自の作業ディレクトリにコピーして,コンパイル&実行してみよ.

$ gcc -o plot plot.c
$ ./plot

このplot.cは,printf()関数で画面へ文字を表示する.すなわち,標準出力へ文字を出力している.従って,通常のUnixコマンドと同様に画面に出力されるはずの内容をリダイレクトして,テキストファイルに保存することが出来る.

以下のコマンドを実行してみよ.

$ ./plot > myplot.plt

上記のコマンド操作でプログラムの実行結果をリダイレクトしてファイル保存したmyplot.pltをEmacsで開いて内容を確認すると,sample.pltと全く同様の内容になっていることが分かる.従って,myplot.pltファイルは,同じようにGNUPLOTに読み込ませて処理させることが出来る.

$ /Applications/gnuplot.app/bin/gnuplot < myplot.plt
$ cat myplot.plt  |  /Applications/gnuplot.app/bin/gnuplot

ここで,次のコマンドを実行してみると,catコマンドは, myplot.plt の内容をそのまま標準出力へ吐き出している(つまり,画面表示)だけであることが判る.

$ cat myplot.plt 

ということは,plot.cプログラムが出す出力をリダイレクトして,一旦ファイルに保存しなくても,直接,GNUPLOTの標準入力へパイプラインで繋いで同じようにグラフを描画できそうに思える.実際,それは可能である.実行して確認してみよう.

$ ./plot  |  /Applications/gnuplot.app/bin/gnuplot

これから判るように,自作のC言語プログラムであっても,printf()関数を使ってGNUPLOTの描画命令を標準出力に出すように作成すれば,これをパイプラインで組み合わせてGNUPLOTのグラフ処理機能を活用できることが分かるだろう.これに対し,例えば,HandyGraphicライブラリを用いて,二次関数グラフを表示する部分まで全てのプログラムを自作することを想像してみれば,その作業は相当に難しいであろうことは容易に予想できるだろう.

UNIX を利用する場合,解決したい問題に対して,そのためのプログラムを全て自作するのではなく,既に用意されたコマンドを適材適所で上手に組み合わせることで,能率良く作業できないかと考えるべきである.UNIXの設計思想は,コンピュータを使い慣れたプロフェッショナルが,そのように能率良く作業が出来ることを目標に置いている.

プロが能率良く作業できるために,UNIXの操作はキーボードからコマンドを与えるCUI (Character-based User Interface)が主体となっているとも言える.MacOS Xでは,GUIでもCUIでも,それぞれの特徴を活かした操作が可能であるが,特にこのCUIを用いた高い操作性はMacOS Xの大きな特徴とも言えるので,是非とも修得して欲しい概念である.(ちなみに,このように既に用意されたコマンドを適切に組み合わせ,さらに,繰り返し処理や条件判断処理を含めた処理を組み立てる仕組みが「シェルスクリプト」と呼ばれる.余裕のある者は,少し勉強してみると良い.UNIXの強力な機能をさらに奥深く知ることが出来るだろう.)

提出課題その1

一次関数 y = 2x のグラフを直線 L とする. 二次関数 y = x^2 のグラフをX軸方向にa, Y軸方向にbだけ平行移動したグラフのうち,Lと接するものを放物線Pとする.aが-4から4まで刻み幅1で変化する時(a = -4, -3, ...., 3, 4),LとPのグラフの状態がどのように変化してゆくかをアニメーション表示するC言語プログラム parabora.c を作成せよ.尚,グラフ描画についてはGNUPLOTを組み合わせて用いるものとする.提出はmoodle学習支援システムによる.

ちなみに,数学幾何において変数aの値の変化に応じて何か図形の状態が変化するような状況を考えるとき,aを「媒介変数」と呼んだりする.

尚,アニメーションの実現にあたっては,以下のような形のfor文を考えれば実現出来る.(放物線Pの方程式より,Lと接するという条件を用いて,パラメータ変数bを消去した方程式を考えよう.実行例はこちらの動画を参照

int a; 
.......
for (a = -4; a <= 4; a++) {
    .....
}

レポ−ト名: program/semifinal1

提出期限:教員の指示による

HandyGraphicを用いた簡易CGアニメーション

アニメーションの原理は,少しづつ異なる絵を短い時間で切り替えることによって起きる錯覚に基づいている.HandyGraphicを用いても,同じようにアニメーションを実現することが出来る.

例えば以下のサンプルソースプログラムは,

円がウィンドウの左右両端でいつまでも跳ね返って往復運動しているように見えるアニメーションを表示するものである.

また,以下のサンプルソースプログラムは

円が描画ウィンドウの左から右に移動するアニメーションを表示した後に停止し,描画ウィンドウ上で何かキーを押すと終了するものである.

提出課題その2

以下のサンプルプログラム(但し,コンパイル済みの実行可能形式)では,

円が斜め45度に直線運動して,ウインドウ端に当たると光の反射のように反射し,一周すると一時停止した後,描画ウィンドウ上で何かキーを押すと終了するプログラムである.これと同じ動作をするC言語プログラム bound.c を作成してソースプログラムを提出せよ.但し,描画ウィンドウの大きさは上記例題のanim.cとanim2.cと同じ大きさで良い.

提出はmoodle学習支援システムによる.

レポ−ト名: program/semifinal2

提出期限:教員の指示による

基礎プログラミング演習Iの表紙ページへ戻る