繰り返し処理
アルゴリズムと繰り返し処理
コンピュータのプログラムの処理には、順次処理(じゅんじしょり)と分岐処理(ぶんきしょり)があることはすでに述べました。ここでは、もう一つの処理である繰り返し処理について説明します。
コンピュータのプログラムの処理のことを、一般にアルゴリズムと言いますが、アルゴリズムはこの3つの処理によって記述されています。ここでは、C#における繰り返し処理の記述方法について説明します。
for 文
サンプルプログラム
まず手始めに、繰り返し処理の最も基本的な処理である for(フォー) 文について学んでいきましょう。for 文は、{} で囲まれた処理を、指定した条件が満たされる間繰り返す命令です。繰り返し処理をループ処理とも言うことから、for 文による繰り返しを for ループとも呼びます。for ループは C# のプログラムの中で最もよく使われる処理の一つです。しっかり覚えておきましょう。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample401
{
class Program
{
static void Main(string[] args)
{
for (int i = 1; i <= 5; i++)
{
Console.Write(i + " ");
}
Console.WriteLine();
}
}
}
for 文の書式
プログラムの結果を見ると、for 文の {} に囲まれた部分が5回実行され、i が 1 から 5 に1つずつ増加していることがわかります。for 文の書式は以下のとおりです。
{
処理
}
Sample401 にあてはめると、初期化処理で i = 1 としているので最初は i の値が 1 から始まります。条件式は i <= 5 なので、i が 5 以下の場合は処理が継続されます。増分処理には i++ と書いていますが、これはインクリメントと言って、i の値を 1 増加させる処理です。
つまり、このfor文は「i = 1 から始めて、i を1つずつ増やしながら i が 5 以下ならば {} 内の処理を実行し、i が 5 より大きくなればループを抜ける」という処理になります。
図4-1. for ループの仕組み
インクリメント・デクリメント
for 文では、インクリメントおよびデクリメントという処理をよく使います。デクリメントとはインクリメントの反対で、変数の値を 1 減らす処理です(表4-1)。
| 演算子 | 呼び名 | 意味 | 該当する演算 |
|---|---|---|---|
i++ | インクリメント(後置) | 変数の値を 1 増加させる | i = i + 1; / i += 1; |
++i | インクリメント(前置) | 変数の値を 1 増加させる | i = i + 1; / i += 1; |
i-- | デクリメント(後置) | 変数の値を 1 減少させる | i = i - 1; / i -= 1; |
--i | デクリメント(前置) | 変数の値を 1 減少させる | i = i - 1; / i -= 1; |
前置と後置の違い
i++ と ++i、i-- と --i はそれぞれまったく同じ意味であるように見えますが、前置(ぜんち)と後置(こうち)には違いがあります。例えば、以下のような処理を行うと、
int a2, b2, c2, d2;
a2 = a1++; // 後置:まず a2 = a1 を代入してから a1 を増加
b2 = ++b1; // 前置:まず b1 を増加してから b2 = b1 を代入
c2 = c1--; // 後置:まず c2 = c1 を代入してから c1 を減少
d2 = --d1; // 前置:まず d1 を減少してから d2 = d1 を代入
結果は次のようになります。
a2=1 b2=2 c2=1 d2=0
前置は演算の完了後に左辺へ代入されるのに対し、後置は代入の後に演算を行います。インクリメントを例にまとめると以下のとおりです。
a = ++i; ← i += 1; a = i; と同じ
様々な for 文の記述方法
基本的な for 文の使い方がわかったところで、様々な記述方法を見てみましょう(表4-2)。
| No. | 記述方法 | 実行結果 | 説明 |
|---|---|---|---|
| ① | for (int i = 0; i < 5; i++) | 0 1 2 3 4 | 0 から始め、5 になるとループを抜ける |
| ② | for (int i = -2; i <= 2; i++) | -2 -1 0 1 2 | -2 から 2 まで 1 つずつ増加させる |
| ③ | for (int i = 0; i < 10; i += 2) | 0 2 4 6 8 | 値を 2 つずつ増加させる |
| ④ | for (int i = 5; i >= 1; i--) | 5 4 3 2 1 | 5 から始め、値を 1 ずつ減少させる |
| ⑤ | for (int i = 2; i >= -2; i--) | 2 1 0 -1 -2 | 2 から -2 まで 1 つずつ減少させる |
| ⑥ | for (int i = 12; i > 0; i -= 3) | 12 9 6 3 | 値を 3 つずつ減少させる。0 になるとループを抜ける |
この例では int 型の場合を取り上げましたが、他のデータ型でも for ループを利用することは可能です。
for の二重ループ
サンプルプログラム
次に、for の二重ループ(for のネスト)を紹介します。これは for ループの中にさらに for ループを記述する処理で、よく用いられるテクニックです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample402
{
class Program
{
static void Main(string[] args)
{
// for の二重ループ
for (int i = 1; i <= 2; i++)
{
for (int j = 1; j <= 3; j++)
{
int k = i + j;
Console.Write(i + "+" + j + "=" + k + " ");
}
Console.WriteLine();
}
}
}
}
2+1=3 2+2=4 2+3=5
多重ループ
このプログラムでは、外側の変数 i のループが内側の変数 j のループを繰り返しています。3回 × 2回で、合計6回のループが実現しています(表4-3)。
| i | j | i+j |
|---|---|---|
| 1 | 1 | 2 |
| 1 | 2 | 3 |
| 1 | 3 | 4 |
| 2 | 1 | 3 |
| 2 | 2 | 4 |
| 2 | 3 | 5 |
このようにして、3重・4重のループを作ることも可能です。ただし、現実的に最も多く使われるのは2重ループ程度です。
while 文
サンプルプログラム
ループ処理を行うのは for 文だけではありません。while(ホワイル) 文を用いることによっても実現できます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample403
{
class Program
{
static void Main(string[] args)
{
int i = 0;
while (i <= 5)
{
Console.Write(i + " ");
i++;
}
Console.WriteLine();
}
}
}
while 文の書式
{
処理
}
while 文は、() 内の条件が成り立つ間は {} 内の処理を繰り返します。Sample403 では、i <= 5 という条件が成り立っている間、中の処理が繰り返されます。13行目で i を 0 で初期化し、ループ内で i の値を表示しながら i++ で値を増加させます。i が 6 になると i <= 5 が偽となり、ループから抜けます。
図4-2. while ループの仕組み
| i | 条件式 | 真/偽 |
|---|---|---|
| 0 | 0 <= 5 | 真 |
| 1 | 1 <= 5 | 真 |
| 2 | 2 <= 5 | 真 |
| 3 | 3 <= 5 | 真 |
| 4 | 4 <= 5 | 真 |
| 5 | 5 <= 5 | 真 |
| 6 | 6 <= 5 | 偽(ループ終了) |
このサンプルは Sample401 と同等の処理ですが、for 文と違うのは、インクリメントの処理や初期値の設定がループの外(または内部)に分かれている点です。
do〜while 文
サンプルプログラム
ループ処理の3つ目として、do〜while(ドゥ・ホワイル) 文について説明します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample404
{
class Program
{
static void Main(string[] args)
{
int i = 0;
do
{
Console.Write(i + " ");
i++;
} while (i <= 5);
Console.WriteLine();
}
}
}
do〜while 文の書式
実行結果は Sample401・Sample403 と変わりません。do〜while 文の書式は以下のとおりです。
{
処理
} while (条件式); ← while の後にセミコロンが必要
do〜while 文は、条件式の判定が後ろについているだけで、while 文とほぼ同じ働きをします。ただし、while の後に ;(セミコロン)が必要な点に注意してください。
図4-3. do〜while ループの仕組み
while 文との違い
「while と do〜while はどう違うのか?」という点について、以下のサンプルで確認してみましょう。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample405
{
class Program
{
static void Main(string[] args)
{
int i, num;
num = 1;
// while ループで実行
Console.Write("whileで実行:");
i = 1;
while (i < num)
{
Console.Write("*");
i++;
}
Console.WriteLine();
// do~while ループで実行
Console.Write("do~whileで実行:");
i = 1;
do
{
Console.Write("*");
i++;
} while (i < num);
Console.WriteLine();
}
}
}
do~whileで実行:*
while の方は何も表示されていませんが、do〜while の方は1つだけ表示されています。これは、while の場合 i の値がもともと条件を満たしていないため {} 内の処理が一切実行されないのに対し、do〜while の場合はまず {} の処理を実行してから条件判定を行うため、条件を満たしていなくても最低1回は処理が実行されることによるものです。
無限ループ
サンプルプログラム
最後に、ループ処理でよく出てくる無限ループについて説明しましょう。無限ループとは、その名のとおり「際限なく繰り返されるループ」です。ここでは while 文を用いたサンプルを紹介します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample406
{
class Program
{
static void Main(string[] args)
{
// 乱数の初期設定
Random rnd = new Random();
Console.WriteLine("6が出たら終了");
// 無限ループ
while (true)
{
int dice = rnd.Next(1, 7); // 1以上7未満の乱数を発生させる(1〜6)
Console.WriteLine(dice);
if (dice == 6)
{
break; // ループから抜ける
}
}
Console.WriteLine("終了");
}
}
}
2
2
3
6
終了
プログラムを実行すると「6が出たら終了」と出力され、1〜6の乱数が次々と出力されます。1〜5の数値が出るとそのまま繰り返されますが、6が出ると終了します。
乱数
C# で乱数を発生させる際には、まず以下のように乱数オブジェクトの生成を行います。オブジェクトについては 6日目で詳しく説明します。ここでは乱数を発生させるための手続きだと思ってください。
続いて、生成したオブジェクトから乱数を発生させます。
Next() の () 内に、発生させる乱数の範囲を指定します。最初の「1」は最小値、二つ目の「7」は「7未満」を意味します。つまり Next(1, 7) とすることで、1〜6の乱数を発生させることができます。
無限ループと break
while(true) とすると、条件式が常に真(true)となるため、処理は無限に繰り返されます。ただし、break(ブレイク) があるとループから抜けることができます。無限ループは for 文や do〜while でも実現でき、いずれも break で抜けることができます。
以上で、順次処理・分岐処理・繰り返し処理というアルゴリズムの三大要素を記述する方法について説明しました。次からは、より複雑なプログラムを作るために必要な知識を身につけていきましょう。