いきなりですが問題です.出力と一致するよう,プログラムコードの「………」を正しいCのコードに置き換えてください.
プログラムコード(各問共通):
for (i = 0; i < 3; i++) for (j = ………) printf("(%d,%d)", i, j);
出力1:
(0,0)(0,1)(0,2)(1,0)(1,1)(1,2)(2,0)(2,1)(2,2)
出力2:
(0,2)(1,1)(1,2)(2,0)(2,1)(2,2)
出力3:
(0,0)(2,2)(0,2)(2,0)(1,1)
出力1と出力2については,nlmateにちょうどそのものの出題があるので,答えは書かないことにします.出力2は昨年度の担当科目の試験問題で出し,今年度はプレ試験問題で出して解説しました.
出力1から出力3まで,変数i, jの変化を図にすると,次のようになります.
出力1:
出力2:
出力3:
それで出力3ですが,iも増えたり減ったり,jも増えたり減ったりで,2重ループとして素直に記述できそうにありません.
こういうときは状態遷移です.変数iとjの値のペア(i,j)を一つの状態とし,一つの式で2つの変数に代入して,両方の値を変えてやります.すなわち,
- (i,j)=(0,0)なら,(i,j)←(2,2)
- (i,j)=(2,2)なら,(i,j)←(0,2)
- (i,j)=(0,2)なら,(i,j)←(2,0)
- (i,j)=(2,0)なら,(i,j)←(1,1)
- (i,j)=(1,1)のときも考えておきましょう…(i,j)←(3,3) *1
一つの式で2つの変数に代入というのは,コンマ演算子でできます.forの増分の中で,else ifは使えませんが,3項演算子の入れ子で表現します.プログラムは以下のようになります.
#include <stdio.h> int main(void) { int i, j; for (i = 0; i < 3; i++) for (j = 0; j < 3; (i == 0 && j == 0) ? (i = 2, j = 2) : (i == 2 && j == 2) ? (i = 0, j = 2) : (i == 0 && j == 2) ? (i = 2, j = 0) : (i == 2 && j == 0) ? (i = 1, j = 1) : (i = 3, j = 3)) printf("(%d,%d)", i, j); printf("\n"); return 0; }
3項演算子のインデント方法については,かつてはてブしていた三項演算子?:の正しい書き方を見直しました.
こうしてみると,外側の,iに関するfor文は1回しか実行しないので,ループにする必要性がないことに気づきます.実のところ,nlmateに入れるにはよろしくない問題です.それと,「(i == 0 && j == 0)」などのカッコは除去できるのに対し,「(i = 2, j = 2)」ほかのほうは除去できません.演算子の優先順位を再確認する,またとない機会になりました.
*1:対称性からこうしましたが,出力1,出力2と同じ「終わらせ方」にするなら,(i,j)←(2,3)と書くべきでしょうね.