ループカウンタのi,j,k
C言語系ではよく以下のようにループカウンタにi, jという名前の変数を使う。
for(int i=0; i<3; ++i) for(int j=0; j<7; ++j) { printf("%d, %d\n", i, j); }
今まで外側のループカウンタから順番にi, j, k, ...という変数名を付けていたがこのやり方には欠点がある。
以下のようなループが二つあったとして,
//ループ0 for(int i=0; i<3; ++i) { printf("%d\n", i); } //ループ1 for(int i=0; i<7; ++i) { printf("%d\n", i); for(int j=0; j<11: ++j) { printf("-%d\n", i*j); } }
ループ1をループ0の中に入れたくなったとき,以下のようにループ1のi, jをj, kに変更するのは面倒だ。
//ループ2 for(int i=0; i<3; ++i) { printf("%d\n", i); for(int j=0; j<7; ++j) { printf("%d\n", j); for(int k=0; k<11: ++k) { printf("-%d\n", j*k); } } }
ループ1を別関数にしてループ0から呼び出すようにすれば,ループ2を書き換えずに済むが
小さなループのために関数を追加するのも気が引けるし,もしループ1が同じスコープ内の大量の一時変数に依存していると
関数に分けるのも面倒になる。
しかし,外側からi,j,kという変数名を使うというルールを無視すれば
ループ1をそのままループ0内にカトペ(cut&paste)してインデントするだけで済む。
//ループ3 for(int i=0; i<3; ++i) { printf("%d\n", i); //ループ3-1 for(int i=0; i<7; ++i) { printf("%d\n", i); //ループ3-2 for(int j=0; j<11: ++j) { printf("-%d\n", i*j); } } }
しかし上記のループ3-2を今度はループカウンタi,jを使っている2重ループの内側へ移すときには修正が必要になる。
そこで多重ループ内では常にiが現在のスコープのループカウンタ,jが一つ外側のループカウンタ,kがそのまた一つ外側のループカウンタ,
となるようにコードを書くようにする。
例えば以下のようにループを書いておくとループ処理を少しの修正でカトペすることができる。
for(int i=0; i<3; ++i) { printf("%d\n", i); for(int j=i, i=0; i<7; ++i) { printf("%d\n", j*i); for(int k=j, j=i, i=0; i<11; ++i) printf("%d\n", k+j+i); for(int j=i, i=0; i<11; ++i) printf("%d\n", j+i); } }
この方法はC++と(たぶん)C99と(普段使わないのでよく知らないが)java, C#等のC言語系でも使えると思う。
だが、この方法でも深いループでずっと外側までのループカウンタが必要になるときにint l=k, k=j, j=i, i=0と書くのは
少し面倒だ。
C++ならテンプレートとかBoostライブラリを駆使すればもう少し短く書けるような気がするので今度考えてみよう。