C言語基礎|for文の基本

はじめに:for文は「回数が決まっている繰り返し」にめちゃ強い

while文でも繰り返しは書けるんだけど、回数が決まっている処理をやるときは for文が本領発揮します。
開始値・継続条件・増分(更新)を、for の ( ) の中にまとめられるので、パッと見で

  • どこから始まる?
  • いつまで続く?
  • どう増える?

が分かりやすいんです。

この章では、for文の「基本の型」をしっかり固めていきますね。

サンプル:合計点を入力して、平均点と評価を出す(for文で人数分だけ繰り返す)

人数が決まっている入力 → 合計 → 平均は、for文の超定番のプログラムです。このプログラムを例に解説をします。

プロジェクト名:chap4-14-1 ソースファイル名:chap4-14-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// 指定された人数分の点数を読み込み、平均点と評価を表示
#include <stdio.h>

int main(void)
{
    int n;
    int sum = 0;

    printf("何人分の点数を入力しますか:");
    scanf("%d", &n);

    for (int i = 1; i <= n; i++) {
        int score;
        printf("%d人目の点数:", i);
        scanf("%d", &score);
        sum += score;
    }

    if (n <= 0) {
        puts("人数は1以上にしてください。");
        return 0;
    }

    double avg = (double)sum / n;
    printf("平均点は%.1f点です。\n", avg);

    if (avg >= 80)
        puts("評価:とても良い感じ!");
    else if (avg >= 60)
        puts("評価:合格ライン!");
    else
        puts("評価:復習しよう!");
    
    return 0;
}

実行例

何人分の点数を入力しますか:3
1人目の点数:70
2人目の点数:90
3人目の点数:60
平均点は73.3点です。
評価:合格ライン!

for文の書式(まずは形を覚える)

for文の基本形

要素書式役割
A(前処理)初期化式 / 宣言最初の1回だけ実行される
B(制御式)継続条件真の間だけループ本体を実行
C(更新)増分式などループ本体のあと毎回実行される

for文はこの3つをセミコロンで区切ります。

for (A; B; C)
    文;

for文の流れ(A→B→本体→C→B…)

for文の基本フロー

A を実行(最初の1回だけ)
        ↓
B を評価(継続条件)
    真  ↓         偽
本体を実行  →  ループ終了
        ↓
C を実行(更新)
        ↓
B に戻る

この流れを知っていると、for文が「何回回るか」を頭の中で追いやすくなります。

while文との対応(for文は前判定繰り返し)

for文は while文と同じく、前判定です。
つまり、B の条件が最初から偽なら、ループ本体は 1 回も実行されません。

for と while の置き換え(ほぼ同等)

for文while文(同等の流れ)
for (A; B; C) 本体A; while (B) { 本体; C; }

この対応が分かると、「for文が苦手…」って感覚がかなり薄れます。

カウンタ用変数 i の意味(なぜ i が多いの?)

for文でよく見る i は、繰り返し回数を数える変数(カウンタ用変数)です。

  • i は index(添字)の i としても使われがち
  • 昔の言語の習慣もあって、短い i や j がよく使われる

とはいえ、意味が分かりにくい場面では person や count みたいな名前にしてもOKです。
読みやすさ優先でいきましょう。

A・B・C をそれぞれ丁寧に理解しよう

A 前処理(最初に1回だけ)

サンプルではこれです。

int i = 1

for の中で宣言した変数 i は、基本的に その for文の中だけで有効です。
だから別の for文で同じ名前をまた使っても問題になりにくく、保守もしやすいです。

B 制御式(続ける条件)

サンプルではこれです。

i <= n

この判定が真の間だけ、ループが回ります。

省略すると常に真扱いになるので、break などがないと無限ループになります。

for (;;)
    文;

C 更新(毎回の後始末・次の準備)

サンプルではこれです。

i++

ループ本体のあとに毎回実行されます。
ここに i += 2 みたいな書き方をすると、2ずつ増えるループになります。

定型パターン「n回繰り返す」を比べる

「n回だけ処理したい」は超よく出ます。

n回繰り返す代表形

for 版:
for (i = 0; i < n; i++)
    本体

while 版:
i = 0;
while (i < n) {
    本体
    i++;
}

for と while の違い(読みやすさの観点)

観点for文while文
回数が決まっている得意(見やすい)書けるが散らばりがち
条件が複雑やや読みにくくなることも状況次第で読みやすい
変数のスコープfor内宣言が便利ループ外に置きがち

ここで登場した命令の書式まとめ

for文

書式何をする?
for (A; B; C) 文A を1回実行し、B が真の間、文を繰り返し、毎回 C を実行する

+=(複合代入)

書式何をする?
sum += scoresum に score を加えて sum に代入する

++(増分)

書式何をする?
i++i を 1 増やす

演習問題

演習4-10:1 から n までの偶数の和を求める

n を読み込み、1 から n までの偶数の和を表示せよ。

解答例

プロジェクト名:chap4-14-2 ソースファイル名:chap4-14-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int n;
    int sum = 0;

    printf("n の値:");
    scanf("%d", &n);

    for (int i = 2; i <= n; i += 2)
        sum += i;

    printf("1 から %d までの偶数の和は %d です。\n", n, sum);
    return 0;
}

演習4-11:ABCDE を繰り返し表示(指定文字数だけ)

正の整数 n を読み込み、ABCDE を繰り返して n 文字だけ表示せよ。

(例)
n:12
ABCDEABCDEAB

解答例

プロジェクト名:chap4-14-3 ソースファイル名:chap4-14-3.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int n;
    printf("表示する文字数:");
    scanf("%d", &n);

    const char s[] = "ABCDE";

    for (int i = 0; i < n; i++)
        putchar(s[i % 5]);

    putchar('\n');
    return 0;
}

演習4-12:歩数と消費カロリーの対応表を表示

開始歩数、終了歩数、増分を整数で読み込み、
消費カロリー(仮)を kcal = steps * 0.04 として表形式で表示せよ。
小数部は2桁表示すること。

解答例

プロジェクト名:chap4-14-41 ソースファイル名:chap4-14-4.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int start, end, step;

    printf("何歩から:");
    scanf("%d", &start);
    printf("何歩まで:");
    scanf("%d", &end);
    printf("何歩ごと:");
    scanf("%d", &step);

    for (int s = start; s <= end; s += step) {
        double kcal = s * 0.04;
        printf("%d steps  %.2f kcal\n", s, kcal);
    }

    return 0;
}