C言語編 第15章 同じ処理を繰り返す(for文)

先頭へ戻る

このエントリーをはてなブックマークに追加

この章の概要

この章の概要です。

for文

前章では while文によるループ構造を紹介しました。 今回は for文を紹介しましょう。

C言語には3種類のループ構文がある訳ですが、基本的にはどれか1つあればどんなループでも作れます。 それなのに3種類も用意されているのは、場合によって向き・不向き(というより書きやすさの問題)があるからです。 for文は、3つのループ文の中で最も高機能なループです。 それだけに使う機会が多く、逆に最初は理解しづらいループです。

for文の構造は次のようになっています。

for( 初期設定式; 条件式; 再設定式 ){
	ループさせる処理
}

「初期設定式」は、最初に for文に差し掛かったときに、1度だけ実行される式です。 ここで、ループを始める前の準備を行います。

「条件式」は、while文のものと同じで、真のときループし、偽のときに for文全体を終了させて、その後の処理へ進みます。

「再設定式」は、「ループさせる処理」が最後まで終了したときに実行される式で、1回分のループを終える度に実行されます。

実行される処理の順序を整理すると、次のようになります。

  1. 「初期設定式」を実行。2へ。
  2. 「条件式」を調べる。「真」なら3へ。「偽」なら6へ。
  3. 「ループさせる処理」を実行する。4へ。
  4. 「ループさせる処理」が全て終了したら5へ。
  5. 「再設定式」を実行。2へ戻る。
  6. for文を終了させて、次の処理へ進む。

たとえ、初回の時点で条件式が偽になるとしても、「初期設定式」の部分だけは実行されることに注意して下さい。


では実際の使用例を確認しましょう。 前章のサンプルプログラムを、for文で書き変えてみます。

#include <stdio.h>

int main(void)
{
	char c;
	char str[20];
	int i;

	puts( "1文字入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%c", &c );

	/* 10回出力する */
	for( i = 0; i < 10; ++i ){
		printf( "%c\n", c );
	}

	return 0;
}

実行結果:

1文字入力して下さい。
y
y
y
y
y
y
y
y
y
y
y

標準入力から受け取った文字を 10回表示するプログラムです。 注目すべき箇所は、for文の部分だけです。

while文のときのサンプルでは、変数count を作り、ループ回数を数えさせましたが、 こういう「ループ回数を数える」作業を、for文では変数i で行うことが多いです。 所詮、変数の名前だけの問題ではあるのですが、この場面では妙な気を起こさずに、慣例に従って、変数i を使う方が、 誰の目にも読みやすいプログラムになります。 なお、ループの内側にループがあるような構造なら、内側ではアルファベットを1つ進めて、変数j を使います。
この変数i は、ループ回数を制御する目的のために用意する変数であり、それほど一般的ではありませんが、 ループ制御変数と呼ぶことがあります。 i という変数名を、ループ制御変数以外の目的で使うことは極力避けるべきでしょう。

for文の「初期設定式」で、変数i に初期値 0 を与え、「再設定式」で加算します。 この「再設定式」の部分ですが、「++i」という見慣れない記述になっています。 これについては後述しますが、意味的には「変数i を +1 する」ということになります。

あとは、「条件式」の部分で、変数i の値が 10未満であることを確かめるだけです。 前章で練習したように、変数の初期値を 10 から初めて、1回ループするたびに 1 ずつ減らしていくスタイルでも もちろんプログラムはできますが、1 ずつ増やしていく方が分かりやすいと言えます。
減らしていく方のプログラムは、練習問題として取っておくことにします。

インクリメント

先ほど登場した「++i」という記述ですが、この意味は「変数i を +1 する」です。 ここで「++」をインクリメント演算子と呼びます。 また、+1 することをインクリメントと呼びます。

インクリメント演算子には2通りの使い方があり、これがなかなか曲者です。 1つは「++i」という記述で、もう1つは「i++」という記述です。 両者が違いをもつのは、インクリメントした結果を代入する場合です。

#include <stdio.h>

int main(void)
{
	int num;
	int ans;


	/* ++num の場合の実験 */
	num = 10;
	ans = ++num;
	printf( "%d\n", ans );

	/* num++ の場合の実験 */
	num = 10;
	ans = num++;
	printf( "%d\n", ans );

	return 0;
}

実行結果:

11
10

まったく同じ形で書いた3行分のソースですが、「++num」の場合と「num++」の場合とでは、結果が異なることが分かります。
「++num」のように、変数の前に「++」と書く場合を前置インクリメントと呼び、 「まず +1 を行ってから、次へ進む」という意味になります。 従って、変数num の値が元々 10 だった場合、まず +1 されて 11 になった後、代入などの次の処理を行うことになります。
「num++」のように、変数の後に「++」と書く場合を後置インクリメントと呼び、 「次に行うことを先に行ってから、+1 を行う」という意味になります。 従って、変数num の値が元々 10 だった場合、まず 10 のまま代入が行われ、その後で +1 されます。

変数num 自身の結果だけを見れば、いずれの場合も 10 から 11 にインクリメントされた訳ですが、 代入と組み合わさると、代入される値が変わってくる訳です。 「代入」と書いていますが、例えば次のような場合も同じです。

#include <stdio.h>

int main(void)
{
	int num = 10;

	printf( "%d\n", num++ );
	printf( "%d\n", ++num );
	printf( "%d\n", num );

	return 0;
}

実行結果:

10
12
12

関数の実引数として指定することも、結果として代入と同じ意味合いになります(関数の仮引数へ代入しているとイメージすれば良い)。 このプログラムの実行結果は、なぜこういう結果になるのか、よく理解しておいて下さい。


インクリメントと代入を組み合わせる記述は、慣れるまで難しいものです。 特に、後置インクリメントと代入を行う文で、「代入が先に行われている」というのは、なかなか理解し難いものでしょう。

なお、代入を行わないのであれば、以下の4つはどれも同じ結果になります。

最後にまた新しい記法が出てきましたが、「+=」は加算と代入を一緒にした演算子です。 「num += 1」ならば、「変数num を +1 して、変数num に書き戻します。 「+=」と同様に「-=」「*=」「/=」「%=」も使え、それぞれやはり同様の意味を持ちます。 これらは「num = num + 1」のような、やや面倒な記述を簡単に書くために用意されています。

他の書き方でも記述できるが、それがやや面倒な場合に、簡単に書けるように用意された構文を、 構文糖(シンタックスシュガー)と呼びます。「+=」などもその1つです。

for文の「再設定式」においては「++i」よりも「i++」の方が使われているのをよく見かけます。 単に慣習的なものですが、C++ という言語では、実行効率の面から前置スタイルの方が好まれます。 そのため、特に前置と後置のどちらを使うべきか理由がないときは、前置を使うクセを付けておくといいです。

デクリメント

インクリメントが「+1」を意味するのなら、「-1」はどうなのかということになります。 「-1」はデクリメントと呼ばれ、「++」と同様に「--」というデクリメント演算子が存在します。

インクリメントのことを理解できていれば、デクリメントは何ら難しくありません。 ただ「++」を「--」に置き換えるだけです。
「--num」なら前置デクリメントで、「num--」なら後置デクリメントです。 代入との関係性も同様です。


練習問題

問題@ 本文中のサンプルプログラム(標準入力から受け取った文字を 10回出力する)で、 for文の部分を、 インクリメントさせる方法ではなく、デクリメントさせる方法で書き換えて下さい。

問題A 1 から 5 までの整数の合計を求めるプログラムを、for文を使って作成して下さい。

問題B 1 から 10 までの整数を小さい方から大きい方へ、ただし奇数だけを出力するようなプログラムを作成して下さい。 2通りのやり方を考えてみて下さい。

問題C 1 から順に数字を2倍、2倍、2倍・・・としていき、それぞれの結果を画面に表示するプログラムを作って下さい。 値が 1000 を超えた時点で終了させて下さい。


解答ページはこちら

参考リンク

更新履歴

'2010/8/30 誤字の修正。

'2009/4/5 新規作成。



前の章へ

次の章へ

C言語編のトップページへ

Programming Place Plus のトップページへ