C言語のfor文の書き方【繰り返し文】
- 作成日: 2020-08-07
- 更新日: 2023-12-25
- カテゴリ: C言語
C言語の繰り返し処理
C言語には繰り返し処理が書けるfor文という文があります。
繰り返し処理はループ処理とも呼ばれますが、ループ処理を書きたい時にこのfor
文を使います。
ループ処理とは無限ループや定数回ループなどのことを言います。
例えば↓は0
から4
より下までカウント変数をカウントし、画面にカウント変数の中身を表示するコードです。
#include <stdio.h>
int main(void) {
for (int i = 0; i < 4; i++) {
printf("%d\n", i);
}
return 0;
}
↑のコードを実行すると↓のような結果になります。
0
1
2
3
for
文を使ってループ処理を書けるようになると、大量の情報を処理できるようになります。
for文はプログラミングのだいご味と言ってもいいかもしれません。
パソコンに大量の処理をさせたい時はこのfor文が必ず顔を出します。
それぐらいポピュラーな文です。
関連記事
目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
プログラミングのポインタをわかりやすく解説【C言語】
コードで見るC言語とC++の7つの違い
目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
for文の構造
for
文は↓のような構造をしています。
for (初期化; 条件判定; 更新) {
処理;
}
まずfor
文は初期化部分でループの状態を初期化します。
初期化が終わると次に条件判定をします。
そして条件判定が終わると、今度は処理を実行します。
処理を一回実行したら、今度はループの更新を行います。
更新が終わったら再び条件判定を行って処理を実行します。
つまり
- 初期化
- 条件判定(真なら継続、偽なら終了)
- 処理
- 更新
- 2に戻る
こういうことになります。
2に戻るというところがミソで、ここがループになってますね。
そしてfor
文は条件判定が真ならループを継続し、条件判定が偽ならループを終了します。
for文の初期化
for
文の初期化部分を見てみます。
for (初期化; 条件判定; 更新) {
処理;
}
ここには変数を定義したり、計算処理を書いたり、関数を呼び出したりできるところです。
たとえばループで使うカウント変数を定義してみます。
for (int i = 0; i < 4; i++) {
printf("%d\n", i);
}
↑の場合、int i = 0;
というところが初期化部分で、ここでカウント変数i
を定義しています。
この部分で定義した変数はfor
文のブロック内で使うことが出来ます。
for
文のブロックとは {}
で囲まれた部分です。
ここの変数定義は複数可能です。
複数定義する場合は、カンマ(,
)で区切ります。
for (int i = 0, j = 0; i < 4; i++) {
printf("%d\n", i);
}
ただし複数の変数を定義する場合は、型を統一しておく必要があります。
つまり、同じ型の変数しか初期化部分では定義できません。
また、初期化部分ではfor
文の外で定義した変数を初期化したりも出来ます。
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", i);
}
関数を呼び出すことも出来ます。
for (func();;) {
}
初期化部分は省略することも可能です。
その場合、初期化部分のセミコロン(;
)は省略できません。
int i = 0;
for (; i < 4; i++) {
printf("%d\n", i);
}
for文の条件判定
条件判定ではfor
文を継続するか終了するか判定します。
for (初期化; 条件判定; 更新) {
処理;
}
ここにはC言語の式を書くことが出来ます。
比較式を書いたり、
for (int i = 0; i < 4; i++) {
printf("%d\n", i);
}
for (int i = 0; i != 4; i++) {
printf("%d\n", i);
}
for (int i = 0; i < 4 && i % 2 == 0; i++) {
printf("%d\n", i);
}
値を参照したり、
for (int i = 4; i; i--) {
printf("%d\n", i);
}
関数を呼び出したりできます。
for (int i = 0; check(i); i++) {
printf("%d\n", i);
}
条件判定文が真ならループは継続し、偽ならループが終了します。
ループが終了した場合、for
文のブロックの終了地点に処理が移動します。
また、for
文の条件判定は省略可能です。
for文の処理
for
文の処理部分です。
for (初期化; 条件判定; 更新) {
処理;
}
ここにはありとあらゆる制御文や変数宣言&定義、関数呼び出しなどを書くことが出来ます。
ブロック({}
)の中に書けるものはここにも書くことが出来ます。
for (int i = 0; i < 4; i++) {
switch (i) {
case 0: printf("zero\n"); break;
case 1: printf("one\n"); break;
default: printf("good\n"); break;
}
int item = get_item(i);
printf("item %d\n", item);
}
繰り返し処理の具体的な処理内容をここに書くのが一般的です。
break文でfor文から抜ける
処理の中にbreak
文を書くと、そのループから抜けることができます。
for (int i = 0; i < 4; i++) {
break;
}
↑の場合、break
文に達した時点でループが終了します。
for
文が入れ子になっている場合は、break
文を記述したブロックのfor
文から抜けます。
// 外側
for (int i = 0; i < 4; i++) {
// 内側
for (int j = 0; j < 4; j++) {
break;
}
}
↑の場合、break
文は「内側」のfor
文からは抜けますが、「外側」のfor
文からは抜けません。
また、break
文はif
文やブロック文の中でも有効です。
その場合、if
の外側にあるfor
文からブレークします。
for (int i = 0; i < 4; i++) {
if (i == 2) {
break;
}
}
↑の場合、カウント変数は0
, 1
とカウントされますが、2
になった時点でループからブレークします。
continue文でループをスキップする
処理を飛ばしたい場合はcontinue
文を使うとループを1回分スキップ出来ます。
for (int i = 0; i < 4; i++) {
if (i == 0) {
continue;
}
printf("%d\n", i);
}
↑の場合、カウント変数が0
の時はcontinue
文以降の処理をループ1回分スキップ(実行しない)します。
↑の実行結果は↓のようになります。
1
2
3
continue
文もif
文の中でも有効です。continue
文もif
文の外側にあるfor
文に作用します。
もちろんcontinue
文単体でも書くことが出来ます。
for (int i = 0; i < 4; i++) {
continue;
printf("%d\n", i);
}
↑の場合、ループ処理の先頭でcontinue
文が実行されるので、ループ内の処理は毎回スキップされます。
よって何も出力されません。
for文の更新
更新部分では、変数などの値を更新したりします。
ここにはC言語の式を書くことが出来ます。
for (初期化; 条件判定; 更新) {
処理;
}
たとえばループ処理が実行されるたびに、カウント変数をインクリメントしたい場合は↓のように書きます。
for (int i = 0; i < 4; i++) {
printf("%d\n", i);
}
更新部分の式は複数書けます。その場合はカンマ(,
)で区切ります。
for (int i = 0, j = 0; i < 4; i++, j++) {
printf("%d %d\n", i, j);
}
また、更新部分は省略可能です。
よく使われるfor文~無限ループ
for
文の初期化、条件判定、更新部分は省略可能ですが、これを全部省略するとどうなるのでしょうか?
for (;;) {
}
泣き顔みたいになってしまいましたね。
🦝 < つらいんやな
じつはこのfor
文、ただ処理を無限に繰り返すだけの無限ループになります。
無限ループはwhile
文を使った方法もよく知られています。
while (1) {
}
これとどっちが使われるかと言うのは、書き手の好みによります。
なので両方とも覚えておきましょう。
無限ループについてもっと詳しく
無限ループについてもっと詳しく見てみましょう。
for (;;) {
}
このfor文のループは永遠に続き止まりません。
このような無限ループに使いどころがあるのでしょうか?
それが無限ループはプログラミングでは非常によく使われるループです。
たとえばゲーム処理を考えてく見てください。
ゲームは電源が入っている間永遠とタイトル画面が出たりゲーム画面が出たりします。
このようなループ処理にも無限ループが使われている可能性が高いです。
無限ループから抜けるにはCtrl + C
などを入力する必要があります。
プログラミングのバグでも無限ループになることはあるので覚えておいた方がいいでしょう。
for文を使ったプログラムのサンプル
for文を使ったプログラムのサンプルとしてはバブルソートなどがあげられます。
/**
* 原始的なバブルソートを実行する
*
* @param[in|out] ary 配列
* @param[in] arylen 配列の長さ
*/
void bubble_sort(int *ary, int arylen) {
// 外側のfor文
for (int i = 0; i < arylen - 1; i += 1) {
// 内側のfor文
for (int j = 0; j < arylen - 1; j += 1) {
// 隣り合う要素同士を比較
if (ary[j] > ary[j + 1]) {
// スワップの実行
int tmp = ary[j];
ary[j] = ary[j + 1];
ary[j + 1] = tmp;
}
}
}
}
↑のバブルソートはfor文を2重(入れ子)にして使っています。
このようにfor文は入れ子にすることで複雑な処理を実現できます。
しかし計算オーダーが悪化することが多いため、速度が必要な処理では注意する必要があります。
できるなら1重のfor文で完結させた方が速度の出るプログラムは作れるでしょう。
まとめ
for
文は↓のような構造になっています。
- 初期化
- 条件判定(真なら継続、偽なら終了)
- 処理
- 更新
- 2に戻る
for
文を使えるようになると色々なプログラムを作れるようになるので、ぜひ覚えておきましょう。