- 本日の作業内容
- 前回の宿題の結果について
また今回も残念なことにコンパイルエラーのプログラムが提出されました.採点しないので,出すだけ無駄です.提出されたことにすらなっていませんので,コンパイルエラーにならないものを出してください.
コンパイルエラー: b1923 b2109 b2122 b2126 b2135
一応参考までにアドバイスしておきますが,どうしてもコンパイルエラーの原因が分からずお手上げ状態になってしまったら,コメントアウトの機能を使用して,解答用紙の自分が組んだプログラムの部分をコメントとしてみてください.それから,徐々にコメントアウトの範囲を狭めて,どこにエラーがあるのか,突き止めましょう.
元々エラーメッセージにはエラーが発生した行が示されているのですが,閉じカッコ } やセミコロン ; などは,最終的に影響が出た場所を教えてくれるので,実際にそれらが抜けている場所とは異る行番号を出していることもありますので,そういった場合にはコメントアウトの活用は役立ちます.
エラーの発生場所が分かってもエラーの対処方法が分からないこともあるかもしれませんが,その場合にはそのコメントアウトを残したままで提出してください.もちろん合格点は与えられませんが,採点はしますので,提出扱いになります.
なお,コメントアウトは教科書では p.7 に「注釈」として説明されています.
出力時の番号間違いも相変わらず出てきました.
番号間違い: C006 b2141
不適切なインデントも今回もたくさん出ています.あまりにひどいものを後の方で紹介していますので,気をつけてください.採点する気が失せます.
不適切なインデント: C008 b2067 b2102 b2103 b2122 b2123 b2134 b2144 b2150 b2153 b2158 b2159
以下は例によって問題のあるプログラムの例です.参考にしてください.
int score = rand() % 50 + 50;
|
50から100までの整数ということで,数は全部で51個ありますね.発生させる乱数は,必要条件は満足していますが,十分条件を満足していません.簡単に言うと,100点が出てこない状況になっていますよね.
int n =rand() %51;
int score = n + 50;
|
変数の無駄遣いです.
if(score < 60 )
{
printf("My score of programing course: %d\n" , score );
printf("Evaluation: D\n");
}
else if(score >= 60 && score < 70)
{
printf("My score of programing course: %d\n" , score );
printf("Evaluation: C\n");
}
else if(score >= 70 && score < 80)
{
printf("My score of programing course: %d\n" , score );
printf("Evaluation: B\n");
}
else if(score >= 80 && score < 90)
{
printf("My score of programing course: %d\n" , score );
printf("Evaluation: A\n");
}
else
{
printf("My score of programing course: %d\n" , score );
printf("Evaluation: S\n");
}
|
中括弧で囲ったブロックの中に2つの printf() 文がありますが,1つめの printf() 文は変数 score の値に関係なく必ず同じものを表示するので,ブロックの中に入れて何度も記述する必要は無いです.
if (score >= 90)
{
printf("S\n");
}
else if (score < 90 && score >= 80)
{
printf("A\n");
}
else if (score < 80 && score >= 70)
{
printf("B\n");
}
else if (score < 70 && score >= 60)
{
printf("C\n");
}
else
{
printf("D\n");
};
|
上の2つのプログラムの else if() の式に論理演算子が使用されていますが,それらは条件をよく見ると不要であることがわかりますね.
if(point =90)
{
printf("Evaluation S");
}
if(80 <= point < 90)
{
printf("Evaluation A");
}
if(70 <= point < 80)
{
printf("Evaluation B");
}
if(60 <= point < 70)
{
printf("Evaluation C");
}
if(50 <= point < 60)
{
printf("Evaluation D");
}
|
else を使用していないことは良いプログラムとは言えません.なんらかの条件分岐があったとしても,結果として実行するものが一つであるのなら else を使用しましょう.また,Webテキストにあらかじめ説明していた不適切な比較演算子の使用法にもなっています.プログラム言語は数学とは違うので, a < x < b のような表現正しく動作しません.
int p;
char e;
p=rand()%51+50;
if(p<60)
{
e='D';
}
else if(p<70)
{
e='C';
}
else if(p<80)
{
e='B';
}
else if(p<90)
{
e='A';
}
else
{
e='S';
}
printf("My score of programing course: %d\n",p);
printf("Evaluation: %c\n",e);
printf("\n");
printf("\n-------------------------\n\n");
return 0;
|
あまりにもひどいインデント無視の例です.人にプログラムを見てもらいたいのなら,ブロックを意識し,適切にインデントを行って見通しの良い分かり易いソースにしてください.次回からも変わらないようならば,もう採点したくないですね.
100
S
----------------------
|
どのように画面に出力するかを課題では指定しています.無視しないで,指示通りに画面に表示されるようにしてください.
さて,以下に示す2つの例は絶対にやっちゃダメ!な例です.プログラミングは何のために行うのか,と言えば,自動化して人の作業を簡略化するためのものがほとんどです.人がラクをするためにプログラムを書くのです.下のような自分が苦労するようなプログラムを私が課題として出すことは絶対にありません!以後注意してください.
switch(num)
{
case 100:
case 99:
case 98:
case 97:
case 96:
case 95:
case 94:
case 93:
case 92:
case 91:
case 90: printf("Evaluation: S\n");
break;
case 89:
case 88:
case 87:
case 86:
case 85:
case 84:
case 83:
case 82:
case 81:
case 80: printf("Evaluation: A\n");
break;
case 79:
case 78:
case 77:
case 76:
case 75:
case 74:
case 73:
case 72:
case 71:
case 70: printf("Evaluation: B\n");
break;
case 69:
case 68:
case 67:
case 66:
case 65:
case 64:
case 63:
case 62:
case 61:
case 60: printf("Evaluation: C\n");
break;
default: printf("Evaluation: D\n");
break;
}
|
if ( b == 50 || b == 51 || b == 52 || b == 53 || b == 54 || b == 55 || b == 56 || b == 57 || b == 58 || b == 59 )
{
printf ("Evaluation: D\n");
}
else
{
if ( b == 60 || b == 61 || b == 62 || b == 63 || b == 64 || b == 65 || b == 66 || b == 67 || b == 68 || b == 69 )
{
printf ("Evaluation: C\n");
}
else
{
if ( b == 70 || b == 71 || b == 72 || b == 73 || b == 74 || b == 75 || b == 76 || b == 77 || b == 78 || b == 79 )
{
printf ("Evaluation: B\n");
}
else
{
if ( b == 80 || b == 81 || b == 82 || b == 83 || b == 84 || b == 85 || b == 86 || b == 87 || b == 88 || b == 89 )
{
printf ("Evaluation: A\n");
}
else
{
if ( b == 90 || b == 91 || b == 92 || b == 93 || b == 94 || b == 95 || b == 96 || b == 97 || b == 98 || b == 99 || b == 100 )
{
printf ("Evaluation: S\n");
}
}
}
}
}
|
- 前回の復習
if 文は, if だけで書く場合と, else をつける場合の2通りをこれまで学習してきました.そして,その2つは意味が違うということも説明しておきました.最後にもう一回確認しましょう.
- else を使用しない場合
特定の条件に合致した場合のみ処理を行い,そうでない場合には処理を行わない場合が該当します.例題で紹介したように,乱数が偶数ならば何かの処理を行う,というような場合です.
- else を使用する場合
ある条件に合致した場合にはAの処理を行い,そうでない場合にはBの処理を行う,というように,条件に応じて処理が分かれるものの,必ずどれかの処理を行う場合には else をつけてください.処理条件が3つ以上になる場合には else if で分岐を増やしていくことも可能です.
とにかく場合分けで対応しようとする癖がついてしまっている人が多くいましたす.2つの変数の値を小さい順もしくは大きい順に入れ替える際に使用した if() 文の手法がそのままより多くの変数の場合にも適用できるということを理解してください.
なんでもかんでも場合分けではなく,どうすれば必要な処理が実現できるのか,をまず考える習慣をつけてください.
- for() 文
- for 文の基本
for 文は教科書p.58にあるような形式で使用します.式1から式3までは初期値,実行条件(この式の値が「真」であれば処理を実行),増分を表します.これらは必要に応じて処理のために使用するので,必ずしも書かなくてはいけないものではありません.ここが空欄であれば,無限ループになります.
今後万一無限ループを作ってしまってプログラムが終わらない場合には,「コントロールキーとCのキー」を同時に押して処理を停止してください.Ctrl+Cと覚えておいてください.
- 変数
for 文の式1から式3までの設定では変数 i がよく使用されます.これは整数(Integer)の頭文字を取ったものです.for 文ではこのように i を使用しますので,他の場所で i を使用する場合には注意が必要です.ただし,複数の for
文が一つのプログラム中にあってもこの変数(仮変数)は i のままで構いません.ですので,変数 i が重複して何度も出てくるようなプログラム,例えば,
for(i=0; i<=5; i++)
{
printf("hoge\n");
}
for(i=10; i>=0; i--)
{
printf("hoge\n");
}
for(i=0; i<=100; i++)
{
printf("hoge\n");
}
|
でもエラーにはなりませんし,まずいプログラムでもありません.これで真っ当な書き方です.
少し先で扱う多重のループの場合には変数は使い分ける必要があります.その
際にはアルファベットの順番で i, j, k, l, m, ... などがよく使用
されます。
- 複合演算子
教科書p.34で紹介されていた複合演算子(代入演算子)は非常に重要です.以後,頻繁に使用される予定です.変数の値を変更する際に利用されますので,よく理解しておいてください.本日の実習でも使用します.また,略号の方がよく使用されますので,そちらも注意してください.
- インクリメント演算子
教科書のp.35に出ていたインクリメント演算子(とデクリメント演算子)も非常に重要です.変数の値を1増やす,もしくは,1減らすという処理ですので,こちらも頻繁に使用します.
応用例としては「カウンタ」があります.例えば,さいころを複数回振る作業で,1の目が何回出てきたかを数えるような処理のときに変数の値を1ずつ増やせるこの演算子は効果的です.
ときどき for 文の式3を以下のように書く人がいるのですが,これは環境によっては無限ループになるので,絶対に止めてください.
- 複合演算子と初期化
先程も書きましたが,複合演算子はこれから非常に重要なものになります.
このような複合演算子は変数自身の値を変えて行くことができるので,繰り返しの中で順に値が変わっていく場合に重宝します.ただし,注意しないと行けないのは,初期化を行わないと正しく動作しない場合があることです.
上の変数 a は値を1増やす処理となっていますが,元の値がそもそもなければ変なことになります.ですので,インクリメント演算子(複合演算子の特殊型)や複合演算子を使用する場合には,必ず変数の初期化を行ってください.教科書のp.59のリスト3_8では,総和を入れるための変数 total の値が0に初期化されています.これが大事です.
ところが,困ったことに教室のCコンパイラは初期化されていない変数の値を勝手に0にする仕様となっています.便利なのは便利ですが,これに慣れてしまうと他のコンパイラを使用した場合に不定の値が入ってしまい,予想外の結果となりかねません.C言語は使用するコンピュータやOSによって動作が微妙に違っていますので,必ず初期化するようにしてください.
- for() 文基本形
教科書には例題が少ないので,まずは,基本中の基本として以下のようなものを載せておきます.参考にしてください.
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=10; i++)
{
printf("%d\n", i);
}
return 0;
}
|
上の例は1から10までの整数を1行に1つずつ表示するもの.次の例は,1行に全部表示するものです.
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=10; i++)
{
printf("%d ", i);
}
printf("\n");
return 0;
}
|
10個の乱数を表示し終わった後に改行文字 \n を出力するための printf があることに注意してください.
- 実習
実習の演習問題はこちらです.
- 次回の予習範囲
次回も引き続き for 文です.演習問題で予習しておいてください.
- 宿題
宿題は,原則として当日の18:00以降に閲覧可能です.提出は翌週月曜日の10:00までです.