なぜ、繰り返し処理の理解が重要なのか、その理由

この記事では、当社の新人エンジニア研修の参考にC#を解説します。

前回は「条件分岐で場合に応じた処理ができるようになる」について学びました。

今回は繰り返し処理(ループ処理)について解説します。人間だったら退屈になってしまうような反復作業も、コンピュータにとっては得意分野です。例えば信号機のように、一日中「赤 → 黄 → 青」を繰り返し続けるのも苦になりません。

C#では、主に以下3つの繰り返し構文を学習します。

  1. while
  2. for
  3. do ... while

1. while

英語の while は「~の間」という意味です。

構文

while (継続条件式)
{
    // 文(処理内容)
}
  1. 「継続条件式」が true なら中の処理を実行し、再度条件式を評価 → true ならまた繰り返し
  2. false ならループを終了します。
using System;

namespace Chap05
{
    public class Example01
    {
        public static void Main(string[] args)
        {
            int i = 0;
            while (i < 3)
            {
                Console.WriteLine(i);
                i++;
            }
        }
    }
}

<実行結果>

0
1
2
  1. i が3になるまで i < 3true のため、コンソールに 0, 1, 2 と出力します。
  2. もし i++ を書き忘れると、i がずっと0のままなので i < 3 は永遠に true となり、無限ループに陥ります。IDEやコンソールで無限ループが起きた際の停止方法を覚えておきましょう。

2. for

while文と同様の処理をする場合でも、変数の初期化・条件式・更新処理を1行にまとめられるのがfor文です。英語の for にも「(期間や回数)~の間」というニュアンスがあります。

以下の図のようにwhile文と全く同じことをするにもコンパクトにかけるという特徴があります。

新人エンジニア
while文とfor文の比較

構文

for (初期化式; 継続条件式; 更新式)
{
// 文(処理内容)
}
  1. ループに入るに、初期化式を1度だけ実行
  2. 継続条件式が true なら中の文を実行し、実行後に更新式を行う
  3. 継続条件式が false になったらループを終了

下図の順番をしっかり頭に入れましょう。

新人エンジニア
for文の構造
using System;

namespace Chap05
{
    public class Example02
    {
        public static void Main(string[] args)
        {
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
}

<実行結果>

0
1
2

  • int i = 0;i を初期化 → i < 3true{ ... } 実行 → i++ → 再度 i < 3判定… を繰り返します。
  • 処理内容は while版と同じですが、初期化・条件式・更新がまとまっており、可読性が高いのが利点です。

例題

次のfor文の繰り返し回数を答えなさい。

for (int i = 0; i < 100; i++) {}
for (int i = 1; i < 100; i++) {}
for (int i = 0; i <= 100; i++) {}
for (int i = 1; i <= 100; i++) {}
for (int i = 0; i < 100; i+=2) { }
for (int i = 100; i > 0; i--) { }

for文と変数スコープ

for (int i = 0; i < 6; i++)
{
    Console.WriteLine(i);
}
Console.WriteLine(i); // ここでiを参照できるか?
  • 上記はコンパイルエラーになります。iforブロックの中で宣言されたため、ループの外にはスコープが及ばないのです。
  • もしループの外でもiを使いたいなら、あらかじめ int i; を書いてから for (i = 0; i < 6; i++) とするなどが必要です。

3. ユーザー入力を受け付ける例

C#では主に Console.ReadLine() を使いユーザー入力を受け付けます。入力は文字列として受け取り、数値として使いたい場合は int.Parse() などで変換します。

例:ユーザーが入力した回数ぶんカウントアップする

using System;

namespace Chap05
{
    public class Example05
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("何回数え上げますか?");
            // キーボードから読み込む (文字列)
            string line = Console.ReadLine();
            // 文字列→整数に変換
            int count = int.Parse(line);

            int i = 0;
            while (i < count)
            {
                Console.WriteLine(i);
                i++;
            }
        }
    }
}

<実行イメージ>

何回数え上げますか?
5
0
1
2
3
4

4. ループを中断する break

無限ループを意図的に書きつつ、何らかの条件が起きたときループを抜けることができます。ループ脱出には break 文を使います。

using System;

namespace Chap05
{
    public class Example06
    {
        public static void Main()
        {
            int sum = 0;
            while (true)
            {
                Console.Write("整数値を入力してください (終了は -1):");
                string line = Console.ReadLine();
                int n = int.Parse(line);

                if (n == -1)
                {
                    break; // whileループを終了
                }

                sum += n;
                Console.WriteLine($"現在の合計: {sum}");
            }
        }
    }
}

<実行例>

整数値を入力してください (終了は -1):2
現在の合計: 2
整数値を入力してください (終了は -1):4
現在の合計: 6
整数値を入力してください (終了は -1):-1
(ここでループ終了)
  1. n == -1 という終了条件が真になった瞬間、ループを強制的に抜けます。
  2. for(;;) と書いてもC#では無限ループとして機能します。

5. ループを1回スキップする continue

continue 文は、今のループ処理を途中でスキップして、次の反復(次回のループ)へ移行させます。if文で同じことは書けるので、使いすぎると読みづらい場合もあります。

using System;

namespace Chap05
{
    public class Example08
    {
        public static void Main()
        {
            int sum = 0;
            for (int i = 0; i < 3; i++)
            {
                Console.Write("整数値を入力してください: ");
                int n = int.Parse(Console.ReadLine());
                if (n < 0)
                {
                    // 負数ならスキップ
                    continue;
                }
                sum += n;
                Console.WriteLine($"入力された数値: {n}");
                Console.WriteLine($"現在の合計: {sum}");
            }
            Console.WriteLine("終わります。");
        }
    }
}

<実行例>

整数値を入力してください: 2
入力された数値: 2
現在の合計: 2
整数値を入力してください: -1
(ここで continue → この回の残り処理をスキップ)
整数値を入力してください: 2
入力された数値: 2
現在の合計: 4
終わります。

6. ループのネスト

ループの中にさらに別のループを入れることを「ループのネスト」「入れ子処理」と呼びます。典型的な例は「九九表」のように、2重ループで i=1..9j=1..9 を組み合わせる場合です。

using System;

namespace Chap05
{
    public class Example09
    {
        public static void Main()
        {
            for (int i = 1; i <= 9; i++)
            {
                for (int j = 1; j <= 9; j++)
                {
                    Console.Write($"{i * j}\t"); // タブ区切り
                }
                Console.WriteLine(); // 改行
            }
        }
    }
}

<実行結果>

1 2 3 … 9
2 4 6 … 18
… (以下略)

  • 外側のループ(青色)が9回、内側のループ(オレンジ色)もそれぞれ9回まわるため、合計81回の掛け算が行われます。
新人エンジニア

ループのネストのイメージ

7. do ... while

C#にも do ... while 文がありますが、使用頻度はそれほど高くありません。必ず1回は処理を実行してから、継続判定を行うという性質があります。

構文

do
{
// 文
}
while (継続条件式);
  1. whileの後ろに セミコロン(;) を付ける点に注意
  2. { ... } を少なくとも1回は実行し、実行後に 継続条件式 を評価 → true なら再度ループ、false なら終了
using System;

namespace Chap05
{
    public class Example10
    {
        public static void Main()
        {
            int count = 0;
            do
            {
                count++;
            } while (count < 0);
            Console.WriteLine(count);
        }
    }
}

<実行結果>

1

  • count が0から始まり、do { count++ } while (count < 0) の判定をするときは既に1なので count < 0false → 1回だけ実行されて終了、結果は1が表示されます。
  • 初学者がwhile(...)の後にセミコロンを書いてしまうミスは、普通のwhile文でやると空文になってしまうので注意しましょう。

<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

while文やfor文は「継続条件がtrueの間、処理を繰り返す」構文である

for(初期化; 条件; 更新) では「条件式は繰り返し処理の前に判定」、「更新式は繰り返し処理の後に実行」される

break文はループを中断し、continue文はループを1回スキップする

□ 終了条件と継続条件の関係を論理否定で相互に変換できる

□ ループの中にループを入れるのを「ループのネスト」と呼ぶ

次回は、「6章. 配列を使い大量データを便利に扱う」を学びます。

最後までお読みいただきありがとうございます。