if文を用いた条件分岐とscanf関数による変数へのデータ読み込み

ソースプログラムにおけるインデントについて

既に,幾つかのC言語プログラム課題について,ソースプログラムの提出を課しましたが,残念な事に,インデント(字下げ)を適切に行っていないものが散見されます.

Emacsを使っていれば,ソースプログラム支援機能としてTABキー押下による自動インデントが行われる筈(こちらのページを参照)なので,この支援機能を上手に使うようにしましょう.

ちなみに,適切なインデントがなされているかどうかも,課題に対する評価基準の一つになっていますので注意してください.

scanf関数による変数へのデータ読み込み

scanf関数を用いると,キ−ボ−ドからタイプ入力した数値を変数へ代入することができる.これを用いた例が

として置いてある.

練習

上記のソースプログラムは教科書pp.41,例題3.2のソースプログラムである.このプログラムについてキーボード入力する数値を色々変えながら何度か実行して結果を確認し,そのプログラムの意味を確認してみよ.

提出課題その1

3つのint型変数,first_num, second_num, third_numにそれぞれ整数をキーボードから読み込み,それらの積を計算して結果を画面表示するプログラム(ファイル名compute.c)を作成せよ.プログラムが正しく動くことが確認できたら,そのプログラムを用いて,10000×10000×10000を計算させてみよ.また,実際に実行する前に結果を予想しておき,その予想と実際に実行した結果とそれに対する考察(どうしてそのような結果が出たのか?)せよ.

課題提出要領

今回の提出課題その1に対して作成したソースプログラムcompute.c,及び,実行結果とその考察を別のテキストファイル(ファイル名study.txt)として作成し,それらをzipアーカイブとして一つに固めたものを提出せよ.提出するアーカイブファイルのファイル名は「ユーザ名.zip」という名前とする.ユーザ名の部分は各自のログインIDで置き換えて考えること.

提出先は学習支援システムmoodleとする.また,ソースプログラムの先頭にはコメント部分として各自の氏名と学生証番号を記入しておくこと.

レポート名:program/compute

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

zipアーカイブの作成方法

例としてユーザ名がg0123456の場合を想定する.

まず,g0123456というディレクトリを適当な作業フォルダに作成し,そこに提出すべきファイルを配置する.

配置できたら,そのフォルダをControlキーを押しながらマウスでプレスすると表示されるメニューから「......を圧縮」を選ぶ.この例の場合は「g0123456を圧縮」を選ぶことになる.

これによりフォルダと中身のファイルが一つに圧縮されたzipアーカイブ(g0123456.zip)が圧縮対象フォルダが入っている同じフォルダに作成される(NetBoot環境では,場合によりデスクトップに作成される事がある).

if文を用いた条件分岐

if文は,ある論理条件に対して,条件を満たすか満たさないかを判断して,その結果に応じてプログラムの処理を切り替える場合に用いる.

その構文は次の通り.

if (条件式)
	条件を満足したときに実行したい文;

また,条件が満足された場合に実行したい文が複数ある場合(複文と呼ぶ)は次のように{ }で囲む.

if (条件式) {
	条件を満足したときに実行したい文1;
	条件を満足したときに実行したい文2;
	条件を満足したときに実行したい文3;
}

この条件式は実は単なる計算式や関数呼びだしでも構わない.計算の結果が「0であれば真」「0以外であれば偽」と解釈されるが,非常に技巧的プログラミングとなるので,今の段階では計算式をif文の条件には使わないようにすること.

また,非常に陥りやすい間違いとして,等価条件をx == yとすべきところをx = yとしてしまうことがある.これはC言語の文法上は間違いではないため,コンパイル時に発見されずにまるで何の問題もないかのように動いてしまうことがあるので注意のこと.

さらに条件式を満たす場合と満たさない場合に実行したい文が変わる場合には,次のif-else文を用いる.

if (条件式)
	条件を満足したときに実行したい文;
else
	条件を満足しないときに実行したい文;

条件を満足するとき,及び,満足しないときに実行したい文が複数ある時は,{ }で囲む.

if (条件式) {
	条件を満足したときに実行したい文1;
	条件を満足したときに実行したい文2;
	条件を満足したときに実行したい文3;
}
else {
	条件を満足しないときに実行したい文1;
	条件を満足しないときに実行したい文2;
	条件を満足しないときに実行したい文3;
}

練習問題

一つの整数をキーボード入力すると,その入力された整数が偶数か奇数かを画面表示するプログラム(ファイル名oddOrEven.c)を作成せよ.(教科書例3.3, 3.4を参考,偶数か奇数かは2で割り算した余りを計算してみて,それが0か1かで判断できる.)

プログラムを理解出来るようになるコツ: 
ソースプログラム上に並んだ文は基本的に上から下へ順に処理が進みますが,if文などが現れると次に処理される文の箇所が変わります.この時,プログラム実行処理の流れを見失うと理解できなくなります.
プログラムの流れを見失わないためには,プログラムが教科書など紙に印刷されている場合には,コンピュータが実行してゆくはずの箇所(行)を指や鉛筆でしっかり押さえながら,落ち着いて考えるようにしましょう.
また,プログラムをテキストエディタで編集している時に実行処理の流れを見失わないためには,指の代わりにカーソルを置く,或いは,マウスポインタでドラッグして選択して反転表示させながら,一行づつじっくりと考えると良いでしょう.

if-else文による3分岐

教科書pp. 50,51にif-else文にて条件により3つに場合分けする例が出てくる.実はif-else文はあくまでも2分岐のための構文であって,3分岐は「見掛けに過ぎない」ことに注意しておこう.

3分岐のif-else文は次のような構造に見えるが,

if (条件1) {
	条件1を満足した時に実行したい文1;
	条件1を満足した時に実行したい文2;
	条件1を満足した時に実行したい文3;
}
else if (条件2) {
	条件1を満足しないが条件2を満足した時に実行したい文1;
	条件1を満足しないが条件2を満足した時に実行したい文2;
	条件1を満足しないが条件2を満足した時に実行したい文3;
}
else  {
	条件1も条件2も満足しない時に実行したい文1;
	条件1も条件2も満足しない時に実行したい文2;
	条件1も条件2も満足しない時に実行したい文3;
}

厳密には,最初のif-else文(赤色)のelseに従属するif-else文(青色)があると考えるのが正しい.

if (条件1) {
	条件1を満足した時に実行したい文1;
	条件1を満足した時に実行したい文2;
	条件1を満足した時に実行したい文3;
}
else
	if (条件2) {
		条件1を満足しないが条件2を満足した時に実行したい文1;
		条件1を満足しないが条件2を満足した時に実行したい文2;
		条件1を満足しないが条件2を満足した時に実行したい文3;
	}
	else  {
		条件1も条件2も満足しない時に実行したい文1;
		条件1も条件2も満足しない時に実行したい文2;
		条件1も条件2も満足しない時に実行したい文3;
	}

但し,このように厳密に解釈してソースプログラムを書くと逆に分かりにくくなるので,普通に3分岐や4分岐をif-else文で表現するときには最初のような構造であるかのように書くことが良く行われており,これが教科書pp.50のような説明になる理由である.

補足: 
C言語の条件式として書ける形は二項比較だけである.つまり,
1 < x
y > z
といった形しか許されない.三項比較の形式,つまり,
10 < x < 50
という表現を使いたくなる気持ちだけは分かるが,このような表現を条件式として使うことは,C言語の規格上,許されていない.
あえて使うなら,教科書pp.48の論理演算子を用いて
10 < x && x < 50
というように二項比較の組合せとしてなら記述できる.

練習問題

教科書にあるプログラム例3.3,例3.4,例3.5,例3.7などを参考にして次のような内容を実行するプログラム(ファイル名weight.c)を作成せよ.

整数で標準体重を計算する式を次のように与える.

標準体重(kg) = 身長(cm) − 105

身長と体重を整数で入力させ,体重の値が先の計算式に基づいて計算した標準体重と比較したとき,

1)標準の一割増より体重が重いとき:

ちょっと太り過ぎです.健康のため少しダイエットしましょう.

2)標準の一割増から一割減までの範囲の時:

健康です.この状態を維持しましょう.

3)標準の一割減より少ないとき:

痩せ過ぎです.もう少し体力をつけましょう.

といった具合のメッセージ(英文でもよい)を表示してくれる適性体重判定プログラムを作成せよ.

但し,標準体重をXとしたとき,Xの一割増はX*110/100として計算するように留意すること.X*1.1の形で計算しようとしてはならない.

計算式中ではデータ型が一致しているのが大原則である.ソースプログラム中に定数として 1.1 と書き込むと整数ではなく実数型データとして扱われてしまう.そのため,上記の練習問題での「割り増し計算」が直観に合わない結果になる場合がある.

ヒント: プログラムの考え方の概略が以下に置いてあるので参考にせよ.

提出課題その2

次のようなプログラムで変数randomに乱数(さいころの目のように,出現する数値が決まっていない)を代入できる.

int random; /* 乱数を入れておくための整数型変数の宣言 */
........
........
srand(time(0)); /* 乱数を初期化するためにプログラムで最初に「一度だけ」実行しておく */
........
........
random = rand(); /* 関数rand()は実行する度に乱数を作り出すC言語の関数 */
........

上記の乱数発生メカニズムの具体的使い方は以下のソースプログラムとしてに置いてあるので,手元で試してみよ.何度か繰り返し実行してみると実行する度に表示される整数が異なる(乱数になっている)事が理解できるだろう.(尚,当然だが,ソースプログラムの内容をちゃんと読まなければ,理解できないのは言うまでもない.)

上記の乱数発生メカニズムを用いて「ジャンケンゲーム」プログラムを作成し,レポートとして提出すること.実行例は以下のとおりであるが,表示されるメッセージは適当で差しつかえない.また,適宜,自分なりの工夫が追加できれば理想的である.

$ gcc -o janken janken.c
$ ./janken
あなたが出したい手を選んで入力してください: [グー:0], [チョキ:1], [パー:2] -> 1
コンピュータの手:グー
あなたの負けです.顔を洗って出直してください.
$ ./janken
あなたが出したい手を選んで入力してください: [グー:0], [チョキ:1], [パー:2] -> 0
コンピュータの手:チョキ
あなたの勝ちです.参りました.
$

プログラム作成のヒント: 乱数を作り出して,その「3を法とする剰余(3で割った余り)」を算出して,それらがコンピュータの手であると考えると良い.勝ち負けの判定はif-else文を用いよ.

プログラムが完成したらソースプログラム(ファイル名はjanken.cとすること)を学習支援システムmoodleを利用して提出する.また,提出するソースプログラムの先頭部分には学生証番号と氏名を明記しておくこと.

レポート名: program/janken

締切り期限: 教員の指示による

switch-case文

整数式の値に応じた処理内容の切り替え

何かの整数式やint型変数の値に応じて複数の処理内容を切り替えたい場合が,様々なプログラミングの状況で必要になる事がある.そのように整数の値に応じて処理を複数の場合に切り替えたい場合はswitch-case文を用いると便利である.

switch (整数式) {
case 整数定数1: 実行文1a
               実行文1b
                ....
               break;
case 整数定数2: 実行文2a
               実行文2b
                ....
               break;
case 整数定数3: 実行文3a
               実行文3b
                ....
               break;
     ....
     ....
default: 実行文da // 上に該当する場合が無かった場合は,このdefault文が実行される.
         実行文db
         ....
}		

ここで教科書pp.60, 例4.2のプログラムが

として置いてあるので,これを各自の作業ディレクトリへコピーした上で,コンパイルして動作確認してみよう.

また,この例題プログラムはbreak文がコメントとして付け加えてある.このコメント記号を削除するとpp.63, 例4.3のプログラムと同じになる.コメント記号を削除して,break文が有効になるように修正して動作確認してみよう.

break文はどのような意味を持っているだろうか?

break文は,その時点で実行中の制御構造(switch-case文や繰り返し構文など)から強制的に抜け出るという働きをする事を理解しておこう.

次回へ向けて

教科書「新・C言語のススメ」第5章「繰り返しの処理」を良く読んで理解しておきましょう.もちろん,例題プログラムも予め動作させてみて,その考え方を頭の中に整理しておくこと.

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