3級範囲のうち、これまでの資料で扱っていなかった3つのトピックをまとめて学ぶ。
while 文は「条件を先に判定してからループ」するが、
do-while 文は「処理を先に実行してから条件を判定」する。
do {
/* 処理(必ず1回は実行される) */
} while (条件式);
| while | do-while | |
|---|---|---|
| 条件判定のタイミング | ループの前(前判定) | ループの後(後判定) |
| 最低実行回数 | 0回(条件が最初から偽なら実行されない) | 1回(必ず1回は実行) |
| 末尾のセミコロン | 不要 | 必要(while(条件);) |
#include <stdio.h>
int main(void)
{
int i = 1;
do {
printf("%d\n", i);
i++;
} while (i <= 3); /* ← 末尾にセミコロン必要 */
return 0;
}
1 2 3
#include <stdio.h>
int main(void)
{
int i = 10;
/* while:1回も実行されない */
while (i < 3) {
printf("while: %d\n", i);
i++;
}
/* do-while:必ず1回実行される */
i = 10;
do {
printf("do-while: %d\n", i);
i++;
} while (i < 3);
return 0;
}
do-while: 10
while(条件); の末尾セミコロンを忘れるとコンパイルエラーになる。
「正しい入力が来るまで繰り返す」パターン。最低1回は入力を促す必要があるため do-while が自然。
#include <stdio.h>
int main(void)
{
int n;
do {
printf("1〜10の整数を入力: ");
scanf("%d", &n);
} while (n < 1 || n > 10); /* 範囲外なら繰り返す */
printf("入力値: %d\n", n);
return 0;
}
コンマ演算子(,)は複数の式を左から右へ順に評価し、最後の式の値を返す演算子。
式1, 式2, 式3 /* 左から順に評価し、式3の値が全体の値になる */
最もよく見る場面は for 文の初期化部と更新部で複数の変数を操作するとき。
/* 初期化部に2つの変数を書く */
for (i = 0, j = 10; i < 5; i++, j--) {
printf("i=%d, j=%d\n", i, j);
}
#include <stdio.h>
int main(void)
{
int i, j;
/* コンマ演算子で i と j を同時に操作 */
for (i = 0, j = 10; i < 3; i++, j -= 3) {
printf("i=%d, j=%d\n", i, j);
}
return 0;
}
i=0, j=10 i=1, j=7 i=2, j=4
int a;
a = (1 + 2, 3 + 4); /* 1+2 を評価(捨てる)→ 3+4=7 を a に代入 */
/* a は 7 になる */
() で囲まないと意図と異なる動作になる場合がある。
変数や型が占めるメモリのバイト数を返す演算子。
09章でも扱ったが、試験対策として改めて整理する。
sizeof(型名) /* 型のサイズ */
sizeof(変数名) /* 変数のサイズ */
sizeof(式) /* 式の結果の型のサイズ */
#include <stdio.h>
int main(void)
{
int a = 10;
double b = 3.14;
char c = 'A';
int arr[5];
printf("sizeof(int) = %d\n", (int)sizeof(int));
printf("sizeof(double) = %d\n", (int)sizeof(double));
printf("sizeof(char) = %d\n", (int)sizeof(char));
printf("sizeof(a) = %d\n", (int)sizeof(a));
printf("sizeof(arr) = %d\n", (int)sizeof(arr)); /* 配列全体 */
printf("配列の要素数 = %d\n", (int)(sizeof(arr) / sizeof(arr[0])));
return 0;
}
sizeof(int) = 4 sizeof(double) = 8 sizeof(char) = 1 sizeof(a) = 4 sizeof(arr) = 20 配列の要素数 = 5
sizeof(配列) / sizeof(配列[0]) で要素数が求められる定番パターン。size_t 型(符号なし整数)。(int) でキャストして %d を使うか、%zu を使う。
Q1. 次のコードの出力として正しいものはどれか。
#include <stdio.h>
int main(void)
{
int i = 5;
do {
printf("%d\n", i);
i++;
} while (i < 3);
return 0;
}
| 変数 | 初期 | 1周目(処理) | 1周目(条件判定) |
|---|---|---|---|
| i | 5 | 6 | 6(偽→終了) |
| 出力 | — | 5 | — |
正解:イ(5のみ)
do-while は必ず1回実行される。i=5 の時点で条件 i<3 は偽だが、先に処理が走るので5が出力される。
Q2. while 文と do-while 文の違いとして正しいものはどれか。
正解:ウ
do-while はブロックを先に実行し、その後条件を判定する(後判定)。
Q3. 次のコードで a の値はどれか。
int a;
a = (1 + 2, 3 * 4);
正解:ウ(12)
コンマ演算子は左から順に評価し、最後の式の値を返す。1+2=3 は捨てられ、3*4=12 が a に代入される。
Q4. int arr[10]; のとき sizeof(arr) / sizeof(arr[0]) の値はどれか。(Visual Studio / Windows 環境)
正解:ウ(10)
int は4バイト。sizeof(arr) = 4×10 = 40。sizeof(arr[0]) = 4。40÷4 = 10(要素数)。
Q5. 次の for 文でループが終わったとき i と j の値はどれか。
int i, j;
for (i = 0, j = 6; i < 3; i++, j -= 2) {
/* 処理 */
}
正解:イ(i=3, j=0)
i=0→1→2→3(条件偽で終了)と進むたびに j=6→4→2→0。ループは3回実行される。