for文

ループ文

プログラミングでは同じ処理を複数回繰り返すことがよくあります。
そのような場合に同じ処理を何行も記述するのは無駄なので、ループ文を使用します。

for文は処理の繰り返し(ループ)のための構文で、頻繁に使われます。


static void Main(string[] args)
{
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine(i);
    }
    Console.ReadLine();
}
0
1
2
3
4

for文の書式は以下のようになります。


for (初期化式; 条件式; 反復式)
{
    //繰り返し実行される文
}

for文は、条件式が真(true)を返す間、つまり条件式が偽(false)になるまでブロック内の文を繰り返し実行します。

for文で用いる式

for文は初期化式条件式反復式の三つの式を使用します。

初期化式

まず最初に初期化式が実行されます。
これはループの実行前に最初に一度だけ実行される式です。
ここで変数を宣言することもでき、その変数はforブロック内で使用できます。
(for文が終了した後はその変数は使えなくなります)

多くの場合、初期化式ではループの終了判定に使用する変数を宣言します。
(ループカウンタという)
変数名は何でも構いませんが、ループカウンタの場合はint型の頭文字の「i」が用いられることが多いです。
ただ「i」は少し見づらいので避ける人もいます。

複数の変数を宣言したい場合はコンマで区切って記述します。
これは通常の変数の宣言の場合と同じです。


//変数iとjを宣言
for(int i = 0, j = 0; i < 5; i++){}

条件式

次に条件式が実行されます。
for文は条件式が真の場合にループを実行します。
サンプルではループカウンタの変数iが5以上になるまで(4以下の間)ループ文が実行されます。

条件判定についてはif文の時と同じです。

もし最初の条件判定が偽になる場合、一度もループは実行されずにfor文は終了します。

文の実行

次に、ブロック内の文が実行されます。
初期化式で変数を宣言している場合、その変数を使用できます。

反復式

ブロック内の文の実行が終わったら、最後に反復式が実行されます。
反復式ではループの終了条件判定のための変数(ループカウンタ)をインクリメント(1を加算)することが多いです。
ループ文が一回実行されるたびに反復文が必ず一回実行されるので、カウントのし忘れがなくなります。

反復式の実行が終わると、再び条件判定に処理が移ります。
この条件判定式が偽になるまでfor文は実行され続けます。

無限ループに注意

for文などのループ文では無限ループに気を付ける必要があります。

for文は条件式が偽となるまで文が繰り返し実行されます。
判定方法にミスがあるといつまでたっても偽にならず、永遠に処理が終わらない無限ループが発生します。


//無限ループ
//iは0未満になることはない
for(int i = 0; i >= 0; i++)
{
    //何か処理
}

//無限ループ
//iは永遠に0のまま
for(int i = 0; i < 5; i++)
{
    //何か処理
    i--;
}

サンプルコードではわざと無限ループを作っていますが、このコードは実行しないでください。
永遠に処理が終わらないので、プログラムがフリーズ(停止)してしまいます。

終了条件判定用の変数はforブロック内で書き換えると無限ループに陥る危険性があります。
この変数の書き換えはしないか、書き換える場合は細心の注意を払って無限ループが発生しないようにしてください。

ループカウンタに小数型(float、double)を使用しない

終了条件判定の変数にはfloat型やdouble型なども指定できますが、これらのデータ型は計算誤差があります。
その誤差によって思い通りにループ文が実行できない場合があります。
場合によってはそれが原因で無限ループに陥ることもあります。


//ループは何回実行されるか?
for(double d = 0; d < 1; d += 0.1)
{
    Console.WriteLine(d);
}

このコードの変数dは「0、0.1、0.2…0.9、1」となっていくはずです。
最後の「1」は条件式を満たさないので、ループは計10回実行されるように思われますが、このコードはVisual C#のコンパイラでは11回実行されます。
(最後の「1」も出力されてしまう)
これはdouble型の計算誤差で0.99999...という値になってしまっているためです。

同じように、以下のようなコードは無限ループの危険があります。


//無限ループの危険性あり
for(double d = 0; d != 1; d += 0.1)
{
    Console.WriteLine(d);
}

変数dは計算誤差によりぴったりと「1」にならない可能性があります。
(Visual C#では「1」になりません)
そのため、変数dが「1」になるまでループ、という処理にしてしまうと無限ループになってしまいます。

変則的なfor文

for文は初期化式、条件式、反復式の三つを使用しますが、これらは必ず指定しなければならないわけではありません。
必要がないならば省略することができます。


int num = 0;

for(;;)
{
    if (num > 5)
        break;

    Console.WriteLine(num++);
}
0
1
2
3
4

必要のない式は空にします。
ただしセミコロン(;)は省略できません。
すべての式を使用しない場合はセミコロンをふたつ記述することになります。

このコードはfor文で無限ループを作り出しています。
そのままではまずいので、後述するbreak文でループを脱出しています。

ブロック記号の省略

for文でループされる処理が一行で書ける場合はブロック記号を省略できます。


string[] strs = new string[]
{
    "abc", "def", "ghi"
};

//ブロック記号省略
for (int i = 0; i < strs.Length; i++)
    Console.WriteLine(strs[i]);

//別にこう書いても構わない    
for (int i = 0; i < strs.Length; i++)
{
    Console.WriteLine(strs[i]);
}

break文

上のサンプルコードで登場したbreak文は現在のループを終了させます。
(またはswitch文を終了させます)

for文内でbreak文が実行される場合、最後の反復式は実行されません。


int num = 0;

//初期化式と条件式を省略したfor文
for(;; num++)
{
    if (num >= 5)
        break;
    Console.WriteLine(num);
}
Console.WriteLine();
Console.WriteLine(num);
0
1
2
3
4

5

continue文

break文に似たものにcontinue文があります。
continue文は現在のループの先頭に処理を移します。


int num = 0;

//初期化式と条件式を省略したfor文
for (;; num++)
{
    if (num < 5)
    {
        Console.WriteLine(num);
        continue;
    }
    Console.WriteLine("for文終了");
    break;
}
Console.WriteLine();
Console.WriteLine(num);
0
1
2
3
4
for文終了

5

変数numが5未満の場合はcontinue文を実行し、処理をループの先頭に戻しています。
for文内でcontinue文が実行される場合は反復式が実行されます。