C言語の基本|順次・選択・繰り返し構造

プログラムの流れは3つの形からできている。順次・選択・繰り返しを理解して、アルゴリズムを組み立てる力を身につけよう。

C言語のプログラムには、入力、計算、条件判定、表示など、さまざまな処理が登場します。処理が増えてくると、何をどの順番で実行すればよいのか分からなくなることがあります。

そのようなときは、プログラムの流れを次の3つに分けて考えると整理しやすくなります。

  • 上から順番に処理する順次構造
  • 条件によって処理を分ける選択構造
  • 同じ処理を何度も実行する繰り返し構造

この3つは、基本制御構造と呼ばれます。

複雑に見えるプログラムも、処理の流れを細かく見ると、順次、選択、繰り返しの組み合わせで構成されています。

たとえば、複数の測定値を入力し、正常な値だけを合計する場合は、次の構造が組み合わされています。

  1. 測定値を入力する
  2. 正常な値かどうかを選択構造で判定する
  3. 正常なら合計へ加算する
  4. 同じ処理を繰り返す
  5. 最後に合計を表示する

基本制御構造を理解すると、長い処理でも小さな流れに分解して考えられるようになります。

基本制御構造は3種類

順次、選択、繰り返しには、それぞれ異なる役割があります。

構造処理の進み方C言語で対応するもの
順次構造記述された順番に処理する上から順番に記述した文
選択構造条件によって処理を分けるif、if else、switch
繰り返し構造回数や条件に従って処理を反復するfor、while、do-while

順次構造は、すべてのプログラムの土台です。特別な制御構文を使わなければ、文は基本的に上から下へ実行されます。

選択構造では、条件の結果に応じて実行する処理を変えます。ifやswitchが代表的です。

繰り返し構造では、同じ処理を決められた回数、または条件が成立している間だけ繰り返します。for、while、do-whileなどを使います。

図1:順次・選択・繰り返し構造の全体像

この図から分かること

順次構造は、入力、計算、表示のように処理を上から順番に実行します。

選択構造は、条件の結果に応じて処理Aまたは処理Bへ進みます。条件が真の場合と偽の場合で、実行される処理が変わります。

繰り返し構造は、条件が成立している間、同じ処理へ戻ります。条件が成立しなくなると、繰り返しを終了して次の処理へ進みます。

この3種類を組み合わせることで、さまざまなアルゴリズムを表現できます。

順次構造は上から順番に処理する

順次構造は、プログラムに記述された文を上から順番に実行する構造です。

たとえば、飛行速度と飛行時間からドローンの飛行距離を計算する場合は、次の順番で処理します。

  1. 飛行速度を入力する
  2. 飛行時間を入力する
  3. 飛行時間を分から時間へ換算する
  4. 飛行距離を計算する
  5. 計算結果を表示する

この処理では、途中で流れが分かれたり、以前の処理へ戻ったりしません。最初から最後まで、決められた順番で進みます。

流れ図では、各処理を上から下へ矢印でつないで表します。

飛行速度と飛行時間から飛行距離を計算するプログラム

ファイル名:7_4_1.c

#include <stdio.h>

int main(void)
{
    double speed;
    double flight_minutes;
    double distance;

    printf("飛行速度を入力してください(km/h)> ");
    scanf("%lf", &speed);

    printf("飛行時間を入力してください(分)> ");
    scanf("%lf", &flight_minutes);

    /* 飛行距離 = 飛行速度 × 飛行時間 */
    distance = speed * flight_minutes / 60.0;

    printf("飛行距離は%.2f kmです。\n", distance);
    printf("上から順番に処理する順次構造です。\n");

    return 0;
}
実行結果の例
飛行速度を入力してください(km/h)> 36
飛行時間を入力してください(分)> 25
飛行距離は15.00 kmです。
上から順番に処理する順次構造です。
順次構造のプログラムを詳しく確認する

このプログラムは、入力、計算、表示の順番で処理します。

記述役割
double speed;飛行速度を保存する変数を宣言する
double flight_minutes;飛行時間を保存する変数を宣言する
double distance;計算した飛行距離を保存する変数を宣言する
scanf("%lf", &speed);飛行速度を入力する
scanf("%lf", &flight_minutes);飛行時間を入力する
distance = speed * flight_minutes / 60.0;飛行距離を計算する
printf計算結果を表示する
return 0;プログラムを正常終了する

speedには、1時間あたりの飛行距離を表す速度を入力します。実行結果の例では36 km/hです。

flight_minutesには、分単位の飛行時間を入力します。実行結果の例では25分です。

速度は1時間あたりの値なので、flight_minutesを60.0で割り、分から時間へ換算します。

25分を時間に換算すると、約0.4167時間です。これに36 km/hを掛けると、飛行距離は15 kmになります。

プログラムは次の順番で進みます。

  • 変数を宣言する
  • 飛行速度を入力する
  • 飛行時間を入力する
  • 飛行距離を計算する
  • 結果を表示する
  • プログラムを終了する

上に書かれた処理が完了してから、その下にある処理へ進むのが順次構造の特徴です。

順次構造で意識したいこと

順次構造では、処理を記述する順番が重要です。

計算に必要な値を入力する前に計算を実行してはいけません。計算結果を表示する場合も、先に計算を完了させる必要があります。

たとえば、飛行距離を求める場合は、次の関係を意識します。

処理前提となる処理
飛行時間を入力する特になし
飛行速度を入力する特になし
飛行距離を計算する飛行時間と飛行速度の入力が完了している
飛行距離を表示する飛行距離の計算が完了している

順次構造では、前の処理で得た値を次の処理で使用することがよくあります。処理同士の前後関係を確認すると、正しい順番を決めやすくなります。

選択構造は条件によって処理を分ける

選択構造は、条件の判定結果に応じて、実行する処理を選ぶ構造です。

たとえば、ドローンのバッテリー残量によって、飛行を開始できるかどうかを判断するとします。

  • バッテリー残量が30%以上なら飛行可能と表示する
  • バッテリー残量が30%未満なら充電が必要と表示する

この場合、バッテリー残量が30以上かどうかが条件になります。

C言語では、ifやif elseを使って選択構造を表します。

形式使い方
if条件が真の場合だけ処理する
if else条件が真の場合と偽の場合で処理を分ける
switch1つの値に対して複数の選択肢から処理を選ぶ

今回のように、飛行可能と充電が必要の2方向に分ける場合は、if elseが適しています。

図2:バッテリー残量によって処理を選ぶ流れ

この図から分かること

バッテリー残量を入力した後、その値が30%以上かどうかを判定します。

条件が真なら、はいの方向へ進み、飛行できますと表示します。条件が偽なら、いいえの方向へ進み、充電してくださいと表示します。

選択構造では、分岐したすべての処理を同時に実行するわけではありません。条件の結果に対応する処理だけが実行されます。

流れ図のひし形は、C言語のifの条件式に対応しています。

バッテリー残量から飛行できるか判定するプログラム

ファイル名:7_4_2.c

#include <stdio.h>

int main(void)
{
    int battery_level;

    printf("バッテリー残量を入力してください(%%)> ");
    scanf("%d", &battery_level);

    /* バッテリー残量によって処理を選ぶ */
    if (battery_level >= 30) {
        printf("飛行を開始できます。\n");
    } else {
        printf("飛行前に充電してください。\n");
    }

    printf("条件によって処理を分ける選択構造です。\n");

    return 0;
}
実行結果の例

バッテリー残量として65を入力した場合は、飛行可能と判定されます。

バッテリー残量を入力してください(%)> 65
飛行を開始できます。
条件によって処理を分ける選択構造です。

バッテリー残量として18を入力した場合は、充電が必要と判定されます。

バッテリー残量を入力してください(%)> 18
飛行前に充電してください。
条件によって処理を分ける選択構造です。
選択構造のプログラムを詳しく確認する

battery_levelは、入力されたバッテリー残量を保存するint型の変数です。

記述役割
int battery_level;バッテリー残量を保存する変数を宣言する
scanf("%d", &battery_level);整数で入力された残量を保存する
if (battery_level >= 30)残量が30以上か判定する
printf("飛行を開始できます。\n");条件が真の場合に実行する
else条件が偽の場合の処理を示す
printf("飛行前に充電してください。\n");条件が偽の場合に実行する

ifの条件式はbattery_level >= 30です。

入力された値が30以上なら条件は真になり、飛行を開始できますと表示します。

入力された値が30未満なら条件は偽になり、elseの処理へ進みます。

battery_levelの値battery_level >= 30実行される処理
65飛行を開始できますと表示する
30飛行を開始できますと表示する
29飛行前に充電してくださいと表示する
18飛行前に充電してくださいと表示する

30は30以上という条件に含まれます。そのため、battery_levelが30の場合はif側の処理が実行されます。

条件式の真と偽

C言語の選択構造では、条件式の結果が真か偽かによって処理が決まります。

比較には、次のような比較演算子を使います。

比較演算子意味条件式の例
==等しいbattery_level == 100
!=等しくないbattery_level != 0
>より大きいbattery_level > 30
>=以上battery_level >= 30
<より小さいbattery_level < 30
<=以下battery_level <= 20

条件式を作るときは、境界となる値をどちらの処理に含めるのか確認します。

30%以上を飛行可能とするなら>=を使います。30%より大きい場合だけ飛行可能とするなら>を使います。

演算子が1つ違うだけで、境界値に対する判定結果が変わります。

switchを使った選択構造

選択構造には、if以外にswitchもあります。

switchは、1つの式の値に応じて複数の処理から1つを選ぶ場合に向いています。

たとえば、操作番号によって処理を選ぶ場合です。

  • 1なら飛行状態を表示する
  • 2ならバッテリー残量を表示する
  • 3なら着陸処理を実行する
  • それ以外なら入力エラーを表示する

ifは大小関係や複数の条件を判定する場合に使いやすく、switchは特定の値ごとに処理を分ける場合に使いやすいという違いがあります。

繰り返し構造は同じ処理を何度も実行する

繰り返し構造は、決められた回数や条件に従って、同じ処理を反復する構造です。

たとえば、複数回の飛行時間を合計する場合、入力と加算を何度も行います。

同じ処理を繰り返し記述するのではなく、forやwhileを使って1つの処理を反復させます。

繰り返し構文特徴向いている処理
for繰り返す回数を管理しやすい5回入力する、配列を順番に処理する
while条件が真の間だけ繰り返す特定の値が入力されるまで続ける
do-while処理後に条件を判定する最低1回は必ず実行したい

繰り返す回数が最初から決まっている場合は、forが分かりやすい選択です。

終了するタイミングが入力値などによって決まる場合は、whileが適しています。

do-whileは、条件を判定する前に処理を実行するため、処理部分が最低1回は実行されます。

図3:0以下が入力されるまで飛行時間を合計する流れ

この図から分かること

最初に合計を0で初期化し、飛行時間を入力します。

入力された飛行時間が正の値なら、合計へ加算して再び入力処理へ戻ります。0以下なら、繰り返しを終了して合計を表示します。

繰り返し構造では、繰り返される処理だけでなく、終了条件も明確にすることが大切です。

この流れ図では、飛行時間が0以下であることが終了条件です。

0以下が入力されるまで飛行時間を合計するプログラム

ファイル名:7_4_3.c

#include <stdio.h>

int main(void)
{
    int flight_minutes;
    int total_minutes = 0;

    printf("飛行時間を分単位で入力してください。\n");
    printf("0以下を入力すると終了します。\n");

    while (1) {
        printf("飛行時間 > ");
        scanf("%d", &flight_minutes);

        /* 0以下なら繰り返しを終了する */
        if (flight_minutes <= 0) {
            break;
        }

        /* 正の飛行時間を合計する */
        total_minutes += flight_minutes;
    }

    printf("合計飛行時間は%d分です。\n", total_minutes);
    printf("入力と加算を繰り返す繰り返し構造です。\n");

    return 0;
}
実行結果の例
飛行時間を分単位で入力してください。
0以下を入力すると終了します。
飛行時間 > 18
飛行時間 > 22
飛行時間 > 15
飛行時間 > 0
合計飛行時間は55分です。
入力と加算を繰り返す繰り返し構造です。
繰り返し構造のプログラムを詳しく確認する

flight_minutesには、1回分の飛行時間を保存します。total_minutesには、入力された飛行時間の合計を保存します。

記述役割
int flight_minutes;1回分の飛行時間を保存する
int total_minutes = 0;合計飛行時間を0で初期化する
while (1)breakが実行されるまで処理を繰り返す
scanf("%d", &flight_minutes);飛行時間を入力する
if (flight_minutes <= 0)入力された値が0以下か判定する
break;whileの繰り返しを終了する
total_minutes += flight_minutes;正の飛行時間を合計へ加える

whileの条件に1を指定すると、条件は常に真になります。そのため、whileだけを見ると処理は繰り返され続けます。

このプログラムでは、ifとbreakを使って繰り返しを終了します。

flight_minutesが0以下になるとifの条件が真になり、breakが実行されます。breakは、現在実行しているwhileを終了し、その後の処理へ進みます。

入力された値が正の整数ならifの条件は偽になるため、breakは実行されません。total_minutesへ飛行時間を加算してから、whileの先頭へ戻ります。

実行結果では、次のように合計が変化します。

入力値判定加算後のtotal_minutes
18正の値なので加算する18
22正の値なので加算する40
15正の値なので加算する55
00以下なので終了する55

最後に入力した0は終了を指示する値なので、合計には加算されません。

繰り返し構造で必要な3つの要素

繰り返し構造を作るときは、次の3つを明確にします。

  • 繰り返しを始める前の初期値
  • 繰り返しを続ける条件または終了する条件
  • 条件に関係する値の更新

たとえば、forで5回繰り返す場合は、次のように考えます。

要素内容
初期値繰り返しに使う変数を0にする
継続条件変数が5より小さい間だけ続ける
更新処理が終わるたびに変数を1増やす

更新処理がないと、条件の結果が変化せず、繰り返しが終了しない可能性があります。

whileとbreakを組み合わせる場合も、どの条件でbreakを実行するのかを明確にします。

3つの構造を組み合わせる

実際のプログラムは、順次構造、選択構造、繰り返し構造を組み合わせて作ります。

たとえば、5回分のセンサー値を入力し、正の値だけを合計する処理は、次のように分解できます。

  1. 合計を0にする
    順次構造
  2. 入力処理を5回実行する
    繰り返し構造
  3. センサー値を入力する
    順次構造
  4. 入力値が正かどうか判定する
    選択構造
  5. 正の値なら合計に加える
    順次構造
  6. 5回の入力が終わったら合計を表示する
    順次構造

このように、1つの繰り返しの中へ選択構造を入れることができます。選択構造の中に別の選択構造を入れることもできます。

組み合わせが増えたときは、処理を小さな単位に分けて、どの部分が順次、選択、繰り返しなのかを確認します。

流れ図とC言語の対応

流れ図の見た目制御構造C言語で対応するもの
矢印が上から下へ進む順次構造文を上から順番に記述する
判断記号から流れが分かれる選択構造if、if else、switch
矢印が以前の処理へ戻る繰り返し構造for、while、do-while
繰り返しの途中から外へ出る繰り返しの終了break

流れ図が上から下へ進んでいれば、その順番にC言語の文を記述します。

ひし形の判断記号があれば、その条件をifなどの条件式へ置き換えます。

処理から以前の判断へ戻る矢印があれば、forやwhileなどの繰り返しを使います。

流れ図とC言語を対応させて考えると、図からコードへの変換がしやすくなります。

基本制御構造からアルゴリズムを組み立てる手順

アルゴリズムを考えるときは、最初からC言語の文法に置き換えようとせず、処理の目的を小さな手順に分解します。

  1. 必要な入力を整理する
  2. 必要な計算や代入を順番に並べる
  3. 条件によって処理が変わる場所を探す
  4. 同じ処理を繰り返す場所を探す
  5. 繰り返しの回数や終了条件を決める
  6. 最後に表示する結果を決める
  7. 順次、選択、繰り返しをC言語へ置き換える

条件によって流れが変わる場所には、ifやswitchを使います。同じ処理を複数回実行する場所には、for、while、do-whileを使います。

それ以外の入力、計算、代入、表示は、基本的に上から順番に記述します。

この考え方を身につけると、長いプログラムでも、順次、選択、繰り返しという小さな構造に分けて整理できるようになります。