
C言語で書かれたプログラムは、基本的に上から下へ順に命令を実行する。しかし実際には、条件を満たしたときだけ処理を行ったり、同じ処理を繰り返したりすることが多い。このように流れを切り替える仕組みを制御フローと呼ぶ。
制御フローを理解すれば、プログラムに判断力を与えられる。たとえば、数値が正のときだけ計算を実行するif文や、入力が続く限り処理を繰り返すwhile文がある。単純な順次実行だけでは複雑な処理を表現できないため、条件分岐と繰り返しの考え方は欠かせない。C言語の制御フローはシンプルでありながら表現の幅が広く、他の言語でも役立つ。
本記事では、if文やswitch文といった分岐、for文やwhile文による繰り返し、breakやcontinueでの流れの調整まで、プログラムの骨格を形作る要素を順に整理していく。
文とブロックの基本ルール
C言語では、ひとつの命令を文と呼ぶ。文の終わりには必ずセミコロンを付ける。これがなければコンパイルエラーになる。変数への代入や関数の呼び出しなど、どのような命令も文の形にそろえることで、プログラム全体の流れがはっきりする。
x = 10;
printf("%d\n", x);この例では、代入と出力の二つの文が並んでいる。どちらもセミコロンで終わっているため、コンパイラは正しく区切りを理解できる。
複数の文をまとめたいときは、中括弧で囲んでブロックを作る。ブロックはひとつの大きな文として扱われる。関数定義では必ず本体を中括弧で囲む。if文やfor文などの制御構文でも、処理が1行だけなら中括弧を省略できる。しかし省略すると可読性が下がり、意図しない動作を招く危険がある。
if (a > b)
printf("a is larger\n");この書き方は一見すっきりしている。しかし次のように文を追加すると、どちらがif文に属するか分かりにくくなる。
if (a > b)
printf("a is larger\n");
printf("done\n");見た目では両方が条件に従うように見えるが、実際には2行目は常に実行される。これを避けるためには、中括弧を付けて意図を明示する。
if (a > b) {
printf("a is larger\n");
printf("done\n");
}ブロックの中では新しい変数を宣言できる。変数の有効範囲はそのブロックに限定されるため、必要な場所だけで使える。
if (flag == 1) {
int temp = 5;
printf("%d\n", temp);
}このtemp変数はif文の中だけで有効になる。外に出れば参照できない。これによりプログラムが整理され、変数の衝突も防げる。インデントを整えることで、ブロックの範囲が一目で分かりやすくなる。文とブロックのルールを守ることは、エラーを減らすだけでなく、他人にも理解しやすいコードを書く第一歩になる。
条件分岐の仕組みと実践的な使い方
プログラムでは処理を選択して実行するために条件分岐を使う。C言語では主に if-else 文と switch 文が利用される。if 文は条件式を判定し、真であれば指定した処理を実行する。
if-else の例
#include <stdio.h>
int main() {
int score = 85;
if (score >= 90) {
printf("評価: A\n");
} else {
printf("評価: B以下\n");
}
return 0;
}複数の条件を順に判定したいときは else if を連鎖させる。条件の順序を工夫すると、不要な判定を減らして効率よく処理できる。
else if の例
#include <stdio.h>
int main() {
int score = 75;
if (score >= 90) {
printf("評価: A\n");
} else if (score >= 80) {
printf("評価: B\n");
} else if (score >= 70) {
printf("評価: C\n");
} else {
printf("評価: D\n");
}
return 0;
}else は直前の if または else if にのみ対応する。対応関係が曖昧だと意図しない処理が実行されることがある。コードを読みやすくするために、else の前には改行を入れて整形すると安全である。
switch 文は変数の値に応じて複数の分岐を行う。case ラベルを順に比較し、値が一致した箇所から処理を実行する。break を忘れると次の case に処理が流れるため、必ず書くか、意図的に省略する場合はコメントを残すとよい。
switch の例
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("月曜日\n");
break;
case 2:
printf("火曜日\n");
break;
case 3:
printf("水曜日\n");
break;
default:
printf("休日\n");
break;
}
return 0;
}複雑な条件分岐では、各条件をブロック {} でまとめると整理しやすい。処理を独立させることで修正や追加を行いやすくなる。変数の比較や論理式は簡潔に書き、長くなるときは補助変数を使うと可読性が高まる。
繰り返し処理の基本と活用例
C言語には繰り返し処理を行うための構文として while 文、for 文、do-while 文 の3種類がある。それぞれの特徴を理解して使い分けることが、効率的で安全なコードを書くための第一歩となる。
while 文は条件式を先に評価し、真の間だけ処理を繰り返す。条件が最初から偽なら1度も実行されない。
int i = 0;
while (i < 5) { // 条件が真の間だけ繰り返す
printf("%d\n", i);
i++;
}do-while 文は処理を1回実行してから条件を評価するため、最低1回は必ず実行される。初回必須の処理に向いている。
int i = 0;
do {
printf("%d\n", i);
i++;
} while (i < 5); // 条件は最後に判定for 文は「初期化・条件判定・増分操作」を1行にまとめられるため、繰り返し回数が明確なときに使いやすい。配列や文字列処理の典型的なイディオムでもある。
int arr[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) { // 配列を順に処理
printf("%d\n", arr[i]);
}文字列処理では ‘\0’ を終端条件にループするのが定番で、特定の文字を置換するような操作にも自然に応用できる。
char str[] = "hello";
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == 'l') str[i] = 'x'; // 'l' を 'x' に置換
}
printf("%s\n", str); // → hexxo回数が明確なら for、条件成立まで繰り返すなら while、必ず1回処理するなら do-while が基本方針だ。これらを状況に応じて選び、配列や文字列の例を試すことで理解が深まる。
ループ制御と例外的なgoto文の利用
C言語ではループ内の処理を途中で制御するために、break と continueがよく使われる。
break
break は現在のループを即座に終了させ、ループの外へ処理を移す。典型的には検索処理で目的の要素を見つけたときに利用する。
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // i が 5になったらループ終了
}
printf("%d ", i);
}
// 出力: 0 1 2 3 4continue
一方、continue はその時点のループ本体の残りをスキップし、次の繰り返しへ進む。不要な処理を飛ばす場合に便利である。
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue; // 偶数はスキップ
}
printf("%d ", i);
}
// 出力: 1 3 5 7 9break文は「もうループをやめる」という合図になる。条件に合う要素を見つけたときや、これ以上処理が不要になったときに使うと便利だ。breakが実行されると、その時点でループ全体を抜けて次の処理へ進む。
continue文は「今回はスキップ、次をやろう」という合図になる。ループ全体は続くが、その周だけは残りの処理を飛ばして次の繰り返しに移る。条件によって特定のケースを飛ばしたいときに役立つ。
goto
さらに、C言語には無条件でジャンプできる goto 文 がある。通常は使用を避けるが、多重ループの脱出 や エラーハンドリング で役立つことがある。
int matrix[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 5) {
printf("Found 5 at (%d, %d)\n", i, j);
goto END; // 外側ループまで一気に抜ける
}
}
}
END:
;関数内で複数の初期化やリソース確保を行うとき、途中でエラーが起きたら共通の終了処理へジャンプするテクニックもある。
ただし、goto は乱用するとコードが追いにくくなり、可読性・保守性を損なう。利用する際はラベル名やジャンプ先の意図を明確にし、必要最小限にとどめる。基本は break と continue を正しく使い、どうしても必要な場合のみ goto を選択するのが安全である。
制御フローを理解することの重要性
プログラムの処理は、条件分岐やループなどの制御フローによって順序が決まる。この基本は、C言語だけでなく他の言語でも応用できる。条件の判定や繰り返しの仕組みを整理し、処理の順序を意識することで、バグを減らし効率の良いコードを作れる。
制御フローを意識すると可読性や保守性も高まる。どの条件で処理が分かれるか、ループが何回繰り返されるかを明確にしておくことで、修正や拡張が容易になる。基本を押さえ段階的に応用し実践的なスキルを習得していこう。




