プログラムの初心者が突き当たる壁はどこにあるのか、 自己流プログラマの多くは限界を感じて真のプログラマにはなれないのだ。 入門書などを読んで、練習用の短いプログラムを作ることは誰にでも出来る。 木片を削って小さなおもちゃを作るのに小学生が難渋することはない。 しかし、同じ木材を使って家を作るとなると道具は揃っていても家は完成しないのだ。 プログラム作成においても同様のことに突き当たる。なぜそうなるのか、 ここに素人とプロの建築家の間で仕事に対する考えの違い出てくる。 大工さんは家を作ろうとするのでなく、柱1本、棚板1枚、床板1枚など、 家を構成している部品一つずつを作る作業をするのだ。それらを組み立ててゆくことで大きな家が完成する。 小さな部品を一つずつ作る仕事に分解する作業、これが家の建築の場合では「設計図」というものだ。 では、設計図を作成することは素人にできるか?ここにプロへの壁が存在する。 コンピュータプログラム作成でも同様のことが言える。
プログラム練習用の小さなプログラムが作れるようになったのに、実用的な大きなプログラムを作れない。 スケールが大きくなるときに、どのように対処すればよいのか、ここに「構造化」という視点が重要になる。 「大きなものも小さなものの組み合わせ」で出来ている。 だから、対処の仕方さえ心得れば、大きなものを作り上げることに、それほど困難は生じないはずなのだ。 大きな仕事を小さな仕事に分解し、小さな仕事の集まりとして組み合わせる。 この作業が「プログラムの構造化」なのだ。全体を見通して、作業内容を分解する。 作業内容をバラバラにするのではなく、共通作業で処理可能な部分の切り出し、 作業の時系列による作業群の分離など、構造化への目の付け所は多い。 この構造化が適切であれば、プログラム作成作業において飛躍的な効率アップ、 プログラムの不良(バグ)の発見、修正など多くの効用が浮かんでくるのだ。
数学に「素数」という用語がある。素数とは1とその数以外では割り切れない整数のことだ。 5は素数、8は素数でないのはすぐ分かるが、1231は素数だろうか?素数でないのだろうか? では、任意の整数を入力し、それが素数かどうかを確かめるプログラムを作ってみることにしよう。 プログラムの構造を考えると、次のようになるだろう。
以上の3つの大きな部分に分かれるが、それぞれの部分はもっと小さな部分から構成されているのだ。。
最初の項目1の「入力を受ける部分」を更に細部まで分解してみよう。次のようになるだろう。
項目3の「整数かどうかを判定する部分」がなぜ必要なのだろうか?
整数の変わりにABCと入れてみればすぐに分かります。エラーが出てプログラム処理が止まるからです。
それを許すなら無くてもいいのですが、手抜きと言われても仕方ありません。
ここまで分解すると、項目3の整数かどうかを判定する部分以外は素人でもプログラムが作れるようになりました。
構造化をはかる上では、整数かどうかを判定する部分パックした形にしましょう。
BASIC言語で記述してみると、項目1、2の部分は次のようになります。
1000 | PRINT "素数判定してほしい整数を入れてください→ "; | ' 項目1 |
1010 | INPUT S$ | ' 項目2(文字変数 S$ に文字列として入力) |
C言語で記述してみると、項目1、2の部分は次のようになります。
char s[10]; | /* 変数宣言 */ |
printf"素数判定してほしい整数を入れてください→ "; | /* 項目1 */ |
gets(s); | /* 項目2(文字変数 S$ に文字列として入力)*/ |
PASCALで記述してみると、項目1、2の部分は次のようになります。
var s: string; | { 変数宣言 } |
write('素数判定してほしい整数を入れてください→ '); | { 項目1 } |
readln(s); | { 項目2(文字変数 s に文字列として入力)} |
入力処理部分の項目1、2はプログラム・コード1行のレベルに分解できたのでプログラム記述コードは容易だ。 しかし、項目3の「整数かどうかを判定する」部分はまだ、分解できていない。
入力された文字列が整数を表すかどうかの判定はどのようにすればよいのだろうか。 入力された文字列が数字だけを含んでいることだ(小学生でも分かることだから説明は要らないだろう)。 受け取った文字列が数字だけであることを判定処理を記述する部分を更に分解してみよう。
文字列から文字を取り出す操作を行う関数はどのプログラミング言語にも備わっている。
これを使えば任意の文字列から1文字を切り出すことができる。
繰り返しの作業なので、プログラムの実行繰り返しの記述のテクニックが必要となる。
BASICでは、[FOR、NEXT]、[WHILE、WEND]などの制御文が使える。
PACALでは、[for next]、[repeat until]、[while do]などがある。
言語の仕様書を読めばどのようなプログラム制御関係の記述が使えるか、
どの言語も必ず備わっている機能なのだが、各言語間に微妙な差異が見られるので注意が必要だ。
文字列を数値に変換するのは10進数の仕組みを知っておれば簡単だ。 その手順を示してみよう。
本当にそのような処理で出来るのでしょうか?試してみよう。入力された文字が「1234」だとしましょう。
入力された「1234」が数値 1234 に見事に変換されたでしょう。 実際のコンピュータでは直接数値しているわけではありません。キーボードのキーを押されただけですから、 文字を受け取っているだけなのです。これを数値に直し計算処理に使っているのです。
素数の判定は「1と自分自身のみで割り切れる自然数」というルールを確かめればよい。 1と自分自身で割り切れるのは当たり前だから、2 から 自分自身の数値-1 で割り切れるかどうかを判定すればよい。 その手順としては次のような手順が考えられる。
上の処理には無駄な部分がたくさん入っているので改良が必要だが、簡単にするためにはこれで済ますことにする。
PASCALで実際に記述して見ました。使用したものコンパイラははDelphi6というフリーソフトです。 必要な人は、この Borland サイト からダウンロードできます。 Windowsで動くソフトですので、GUIでのアップリケーションになるので、そのための少し複雑な手続きが必要です。 まだまだプログラムとして改善すべき点がたくさん残っています。
procedure TForm1.Button1Click(Sender: TObject);
const
numberstr='0123456789';
var
s,c,sol: string;
f: boolean;
i,n,p: integer;
begin
{{文字列入力処理}
s:=Edit1.text; {入力欄から入力された文字列を取り出す}
{{整数判定処理}
n:=0; f:=true; {初期値設定}
for i:=1 to length(s) do begin
c:=copy(s,i,1); {1文字取り出す}
p:=pos(c,numberstr); {'0123456789'の何番目にあるか、無ければ 0 を返す}
if ( p > 0 ) then begin f:=false; break; end; {無ければ処理をやめる}
n:=n*10+p-1; {数値に加算}
end;
if f then label3.Caption:='入力OK' else label3.Caption:='入力に誤りあり'; {入力チェック結果表示}
str(n,s); Edit1.Text:=''; Edit1.Text:=s; {変換した数値を表示}
{素数判定処理}
if f then begin {入力チェックでエラーが無ければ次の処理をする}
for i:=2 to n-1 do begin {自分より小さな数値全てで割り算してみる}
if ( n mod i )=0 then begin f:=False; str(i,sol); break; end; {余りが無ければ割り切れた}
end;
if f then label3.Caption:='素数だ!' else label3.Caption:=sol+'で割り切れる'; {結果を表示}
end;
end;
実際に動かして見たい人は ダウンロード して使ってみてください。まだまだ改善する部分が残っているが、 このコーナーの趣旨にはないのでこれ以上の手を加えないものとします。 管理人(志)
このページは2003/12/28に作成されました。