本課題は渡辺先生の作成した「応用理工情報処理」(金曜クラス)のテキストをもとに改訂したものです。
渡辺先生に感謝!
今回はテキスト第4章に従って処理を繰り返し実行させる方法である do文とwhile文 を学びます。
do も while も「条件式」が真である間はコードブロックを繰り返し実行する文です。使い方は次のようになります。
do 文
do{
コードブロック
} while (条件式);
while 文
while(条件式){
コードブロック
}
繰り返しの判定に用いる条件式は if文の条件式と同じです。先週も触れましたが、C言語では、x > 0 のような式も真であれば0以外、偽であれば0という値を持っています。この事は、この先条件式を使ったプログラミングで「テクニック」として使うことがあるので覚えておいて下さい。
do と while の違いは「do文は条件式が偽でも必ず1回はコードブロックを実行する場合に用いる」ということです。この違いにより、例えば、次のようなことがおこります。
do 文
i = 0;
do{
i++; /* 変数 i の値を 1 増やす。 i = i + 1と同じ */
}while (i < 0);
/* i++ が一回実行されているので、最終的に i は 1になっています。*/
while 文
i = 0;
while (i<0) {
i++; /* 最初の条件文 i<0 がいきなり成り立たないので、 */
/* このコードブロックは一度も実行されません。 */
}
/* 最終的に i は 0のままです。*/
do を使うことで、例えば、次のようなプログラムを作ることができます。
数値入力を受け付ける。
入力された数値が 0 から 10までの間の値でなければ、0 から 10の間の値が入力されるまで入力を繰り返す。
このプログラムを擬似コードで書くと次のようになります。
do{
数字の入力
} while ( 入力された数字は 0 より小さい、もしくは10より大きいか?);
テキストp. 72, List 4-1のプログラムを実行してdo文がどう機能するかを学びましょう
/* 読み込んだ整数値は奇数であるか偶数であるか(好きなだけ繰り返す) */
#include <stdio.h>
int main (void)
{
int retry;
/* 処理を続けるか */
do {
int no;
printf ("整数を入力してください:");
scanf("%d", &no);
if (no % 2)
puts ("その数は奇数です。");
else
puts("その数は偶数です。");
printf ("もう一度?【Yes…0/No…9】:");
scanf("%d", &retry);
} while (retry == 0);
return (0);
}
whileの条件判断は、retry == 0 で行われています。この式が真(つまり retry が 0)である間は do と while ではさまれたコードブロックが繰り返し実行されるわけです。
ここで使っている条件式は、(!retry)と書いても(retry == 0)と同じ意味を持ちます。"!"は論理否定演算子で、retry が0(つまり偽)であれば、!retry は真になります。1となります。
(retry == 0)を(!retry)と書き換えて、プログラムが同じように動作することを確認してみてください。
{ と }で囲まれた領域はコードブロック(複合文)と呼び、C言語では文法的に1つの文と同等に扱われます。このコードブロックの先頭で変数を宣言することが可能です。
このプログラムでは no という int 型変数を宣言しています。コードブロックの内部で宣言された変数はそのコードブロック内だけで有効で、そのコードブロックの外部からは参照できません。(プログラムの処理がコードブロックから外に出た時点でその変数のメモリが開放され、変数は消えてしまいます。)注意して下さい。
(テキスト p. 78)
/* 1から5までの和を求めて表示(複合代入演算子) */
#include <stdio.h>
int main (void)
{
int no = 1;
int sum = 0;
do {
sum += no; /* sumにnoを加える */
no += 1; /* no に 1を加える この文は、no++; とも書ける*/
} while (no <= 5);
printf ("1から5までを足した値は%dです。\n", sum);
return (0);
}
複合代入演算子とは、演算子の左右のオペランド(値)を使って計算を行い、その結果を左オペランドの変数に代入する演算子です。例を見てみましょう。
a += b;
は a と b を足した結果を a に代入します。つまり、
a = a+b;
と全く同じです。
複合演算子は足し算だけでなく、加減乗除すべてで使えます。以下のように。
a += b; は a = a+b; と同じ。
a -= b; は a = a-b; と同じ。
a *= b; は a = a*b; と同じ。
a /= b; は a = a/b; と同じ。
複合演算子を使うかどうかは「プログラムが読みやすく成るかどうか」という視点から決めれば大丈夫です。
複合演算のうち、a += 1; (つまり、a の値を1増やす a = a+1; )と a -= 1; (つまり、aの値を1減らす a = a-1; )はよく使われるため、さらに簡潔に表記するための演算子が用意されています。
値を1増やす:
a ++; は a = a+1; と等しく、++ はインクリメント演算子と呼ばれます。
値を1減らす:
a --; は a = a-1; と等しく、-- はデクリメント演算子と呼ばれます。
テキスト p. 81, List 4-5のプログラムでwhile文を学びましょう。
/* 読み込んだ整数値を0までカウントダウン */
#include <stdio.h>
int main (void) {
int no;
printf ("整数を入力してください:");
scanf ("%d", &no);
while (no >= 0) {
printf("%d ", no);
no--; /* noの値をデクリメントする(一つ減らす) */
}
putchar ('\n'); /* 改行 */
return (0);
}
do 文と違い、while 文では繰り返しの条件判断を最初に行っています。
関数 putchar( )は文字を画面に出力します。putchar('\n') は改行文字 \n を画面に出力する、つまり改行することです。
シングルクォーテーションマークで囲んだ 'A' は文字定数を表します。ダブルクォーテーションマークで囲んだ"A"は文字列定数を表します。文字列定数には文字列の終端を認識するために末尾に '\0' という特殊文字が入っていますが、文字定数には入りません。この辺りは C言語のデータ型でも扱いにくい部分ですが「文字と文字列は違うものだ」ということは頭に入れておいてください。
以下のコードは、0から9までの整数の乱数を生成するものです。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int k;
srand(time(NULL)); /* 乱数列を現在時刻で初期化 */
k = rand()%10;
printf ("生成した乱数:%d\n", k);
return (0);
}
このプログラムを参考に、0から9までの整数の値を当てる数あてゲームを作成して下さい。
画面上には以下の出力例のように表示されるものとします。ここでは3回目で数を当てていますが、当たらなければ何回でも繰り返すものとします。
---------出力例----------
0から9までの整数を当ててください。
何回目の入力で当たるでしょうか。
1回目の入力:5
もっと小さな数です。
2回目の入力:3
もっと大きな数です。
3回目の入力:4
大正解! 3回目で正解です。
while, do, if のどれかもしくはそのいくつかを組み合わせて、100以下のすべての素数を表示するプログラムを作成してください。
ヒント
自分よりも小さいく、かつ2位上の自然数のどれかで割り切れれば、その数は素数ではありません。
検索[C言語 演算子 剰余]