• ベストアンサー

C言語 for文を使った一例について

#include<stdio.h> main () { int i ; int j ; for(i = 0 ; i<5 ; i++){ /*行数の制御部*/ for(j = 0; j<(i+1) ; j++){ /* *の制御部*/ printf("*"); } printf("\n"); } return; } このプログラムを実行すると * ** *** **** ***** が表示されます。 for(j = 0; j<(i+1) ; j++){ ↑    printf("*");} ↑ 「*」の制御部となりますが、 何故「*」が1行目で1個表示されているのに 2行目では2個表示されているのですか? 行数と「*」は同じになると思われますが。 上記の質問の回答の程宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

iのforをfor(i)、jのforをfor(j)を表記して、各変数がどのように変移するかを書けば i i+1 j j<i+1 処理 --------------------------- 0 1 0 true *を表示 0 1 1 false for(j)を抜ける(そして改行) for(i)でiを++する。 1 2 0 true *を表示 1 2 1 true *を表示 1 2 2 false for(j)を抜ける(そして改行) for(i)でiを++する。 2 3 0 true *を表示 2 3 1 true *を表示 2 3 2 true *を表示 2 3 3 false for(j)を抜ける(そして改行) for(i)でiを++する。   ・   ・   ・ となり、*の数がどんどん増えることになります。

KGM
質問者

補足

わかりやすい説明で、ほぼ理解することができました。 i i+1 j j<i+1 処理 --------------------------- 0 1 0 true *を表示 ←(1) 0 1 1 false for(j)を抜ける(そして改行) for(i)でiを++する。 1 2 0 true *を表示 ←(2) 1 2 1 true *を表示 1 2 2 false for(j)を抜ける(そして改行)   ・   ・   ・ わからない点があるのですが、←矢印で 示している部分になります。 (1)では、初期値がi=0 , j=0なので *は一つだけ表示されるのはわかります。 (2)で、「1 2 0 true *を表示」の部分において j=0となっていますが、「0 1 1 false for(j)を抜ける」になるとjはインクリメントされ、 初期値が j=1となり、j=0にはならなく、*が表示されないと 思われます。 何故「0」があるのかを教えて頂けませんか。

すると、全ての回答が全文表示されます。

その他の回答 (14)

  • rentahero
  • ベストアンサー率53% (182/342)
回答No.15

while文はわかりますか? forを使った以下のような構文は、 for(A;B;C) { D; } whileを使って以下のように書き換えられます。 A; while(B) { D; C; } A,B,C,Dの処理の位置に注目してください。 これで元の for(i = 0 ; i<5 ; i++){ /*行数の制御部*/ for(j = 0; j<(i+1) ; j++){ /* *の制御部*/ printf("*"); } printf("\n"); } をかきかえてみると i=0; while(i<5) { j = 0; while( j<(i+1)) { printf("*"); j++; } i++; } となります。 もうわかりましたね。 jの初期化j=0;は、 iのループの中でかつjのループの外にあるから、です。 iのループを回るたびにjは0になるわけです。

KGM
質問者

お礼

書き込みありがとうございます。 非常に助かりました!!

すると、全ての回答が全文表示されます。
  • php504
  • ベストアンサー率42% (926/2160)
回答No.14

ちなみに質問者さんの考えている動作をするプログラムは #include <stdio.h> main () { int i ; int j ; j = 0; /*一回だけ初期化*/ for(i = 0 ; i<5 ; i++){ /*行数の制御部*/ for(; j<(i+1) ; j++){ /* *の制御部 初期化部分がない*/ printf("*"); } printf("\n"); } return; } こうなります。

すると、全ての回答が全文表示されます。
回答No.13

こんにちは、AEと申します。 文法的なことは皆さんが回答されていますので。 なるべく簡単に(^-^)。 > このようなフローがあると思われます。 > j=0の過程がどうしても導きだせません。 多重ループの場合、内側のループは最初から実行されることになります。ここの理解がキモでしょう。 「 for(j = 0; j<(i+1) ; j++) 」  の意味は 「jを0から、 (i + 1)まで、 1ずつ増加させる」   j=0;   j < (i + 1);   j ++; ということですので、jは0に始まり(i+1)未満でループから抜けます。 この処理が最初から行われるということは、j=0からカウントアップが開始されるわけで、結果として、iが5になるまで、jのループ内で(i+1)個の*が横方向に表示されるということになります。 printf()で、iやjの値がどう変化していっているか表示してみるとよいでしょう。理解しやすくなりますよ。 ただ、少し厳しくかつ偉そうに言ってしまいますが、 ○for()文の文法を理解する。 ○多重ループにおけるfor()文のアルゴリズムを正しく理解する。 ということも頑張りましょう! ※今ちょうど一生懸命勉強してはるとこですよね!:)。

KGM
質問者

お礼

言語をやるのは初めてで、さっぱりわからない状態です。。。 ですが、これから着実に進めていきたいと思いますので、 今後とも宜しくお願いします。

すると、全ての回答が全文表示されます。
  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.12

for(i=0; i<n ; i++){ /* 処理 */ } は次のように書き換えられます i=0; while(i<n){ /* 処理 */ i++; } 質問の場合は for(i = 0 ; i<5 ; i++){ /*行数の制御部*/ for(j = 0; j<(i+1) ; j++){ /* *の制御部*/ printf("*"); } printf("\n"); } なので i = 0; while( i < 5 ) { /*行数の制御部*/  j = 0;  while( j < (i+1) ) { /* *の制御部*/   printf("*"); /* ここでは改行しない */   j++;  }  printf("\n"); /* ここで改行 */  i++; } です。 「初期化」や「インクリメント(++のこと)」、「printfの出力」がどのような順番で実行されているか、確認してください。

KGM
質問者

お礼

非常にわかりやすかったです^^ これで、完全に解決することができました。

すると、全ての回答が全文表示されます。
回答No.11

>2回目のループ開始(i=1) >↓ >i(1)<5→jループに移る >↓ >j=0 //一回目のループでj++されたからj=1になるのでは? >↓ forの処理は、 (1) for文の2番目の式(制御式)がfalseになったとき(2) returnまたはgotoでfor処理の外へジャンプした (3) breakでfor処理を抜けた いずれの場合も終了(完了)します。 だから再度、同じfor文を実行してもそれは継続ではなく新規になります。

すると、全ての回答が全文表示されます。
  • gimmick
  • ベストアンサー率49% (134/270)
回答No.10

>j=0の過程がどうしても導きだせません。 for文で指定する初期化文は、そのfor文を実行する前に1回だけ処理されます。 つまり、質問文の二重ループは次の処理と同等です。 for(i = 0 ; i<5 ; i++){  j = 0;  for(; j<(i+1) ; j++){   printf("*");  }  printf("\n"); }

KGM
質問者

お礼

返信が遅れました。 みなさまの書き込みのお陰で、ようやく理解できました。 最初は、書き方を工夫して慣らしていこうと思います。

すると、全ての回答が全文表示されます。
回答No.9

まず、for() の基本として、 for(<1> ; <2> ; <3>} {.... } は、 ・繰り返しに入る前に<1>を実行 ・<2> の条件が満たされている限り.... を繰り返す ・繰り返しが終わる度に、<3> を実行 はOKですね。 この場合、 for(i = 0 ; i<5 ; i++){ /*行数の制御部*/ for(j = 0; j<(i+1) ; j++){ /* *の制御部*/ というループは、併置されているわけではなく、「外側のループ」「内側のループ」になります。 外側の for(i = 0; ... ) によって、ある処理が5回実行されます。外側のループ自体は、1度しか通過しません(その1度のループの中で、「ある処理」が5回実行されるわけです) ですから、i = 0 という初期化は、1度しか起こりません。 5回実行される「ある処理」とは、実は、for(j = 0...)というループです。 これは、5回実行されます(それぞれの実行中で、* の印字は、i + 1 回実行されます) つまり、j = 0 という初期化は5回実行されます。 このように、i は、1度しか初期化されず、j が5回初期化されるのは、i のループと j のループが、同じものではなく、j のループは、i の「中身」だからです。 ということになるのですが。 ↓ > i(1)<5→jループに移る > j=0 //一回目のループでj++されたからj=1になるのでは? j の初期化は、「j のループが開始された」時に発生します。故に、「jループに移る」時には、必ず実行され、j は0になります。 これに対して、「i ループに『移る』」という箇所はありません(実際には、最初に一回ある) だから、i は、初期化されないのです。 i は、「繰り返しのみ」 j は、「繰り返し(このときは初期化されない)」と「移る(このときは初期化される)と違いがあります。

すると、全ての回答が全文表示されます。
回答No.8

>何故、jが最初に初期化されるのですか。 >それは、iでは起きないのですか >for(j = 0; j<(i+1) ; j++){ /* *の制御部*/ >printf("*"); >} for文は、本来3行以上必要な処理を1行にまとめて書かれています。 つまり、 loop_start: j = 0; loop_check: if (j<(i+j)) goto loop_end  { loop内の処理   printf("*");  } loop_next: j++; goto loop_check loop_end: と、これだけの処理がfor文の中にあるのです。 jを初期化するloop_start:はfor文に入ったときに1度だけ実行され forが継続している間は実行されません。

KGM
質問者

補足

丁寧な書き込みをしていただき、感謝感激です。 ただ、どうしてもjの値がインクリメントされても 「0」になる理由がのみこめません。 1回目のループ開始(i=0) ↓ i(0)<5→jループに移る ↓ j=0 ↓ j(0)<(1):*を表示→j++ ↓ j(1)<(1):条件終了。jループを抜ける ↓ i<5:\n(改行)を表示→i++→1回目のループを抜ける ↓ 2回目のループ開始(i=1) ↓ i(1)<5→jループに移る ↓ j=0 //一回目のループでj++されたからj=1になるのでは? ↓ j(0)<(2):*を表示→j++ ↓ j(1)<(2):*を表示→j++ ↓ j(2)<(2):*条件終了。jループを抜ける ↓ i<5:\n(改行)を表示→i++→2回目のループを抜ける ↓ 3回目のループ(i=2) このようなフローがあると思われます。 j=0の過程がどうしても導きだせません。

すると、全ての回答が全文表示されます。
  • edomin
  • ベストアンサー率32% (327/1003)
回答No.7

「(2)で、「1 2 0 true *を表示」の部分においてj=0となっていますが、「0 1 1 false for(j)を抜ける」になるとjはインクリメントされ、 初期値がj=1となり、j=0にはならなく、*が表示されないと思われます。 何故「0」があるのかを教えて頂けませんか。」 forループの条件で最初に「j=0」を与えているからです。 for文を抜けた直後の「j」は「1」ですが、「i」のループによって再度forループに突入します。その際、最初に初期化されるので、質問のプログラムだとj=0から始まることになります。

KGM
質問者

補足

何故、jが最初に初期化されるのですか。 それは、iでは起きないのですか。 i=0 i=0の条件でループが始まる ↓ i=0 J=0の条件でループが終了 ↓ i++ j++される(i=1 J=1) ↓ i=1 J=1の条件でループ開始 このような過程の中で、jがどう初期化されるのかを 教えて下さい。宜しくお願いします。

すると、全ての回答が全文表示されます。
  • gimmick
  • ベストアンサー率49% (134/270)
回答No.6

二重ループの部分を(A)とします。(説明を短くするため、外側のループの5は3に変えます。) ----(A)--------------------------------- for(i = 0 ; i < 3 ; i++){  for(j = 0; j < (i + 1); j++){   printf("*");  }  printf("\n"); } ---------------------------------------- (A)の外側のforループを展開します。これを(B)とします。 ----(B)--------------------------------- for(j = 0; j < 1; j++){  printf("*"); } printf("\n"); for(j = 0; j < 2; j++){  printf("*"); } printf("\n"); for(j = 0; j < 3; j++){  printf("*"); } printf("\n"); ---------------------------------------- (B)のforループを全て展開します。これを(C)とします。 ----(C)--------------------------------- printf("*"); printf("\n"); printf("*"); printf("*"); printf("\n"); printf("*"); printf("*"); printf("*"); printf("\n"); ---------------------------------------- というわけで、(A)の処理は(C)の処理と同じ働きをします。 (マシン語レベルで同一とは言えませんが。) 不明な点があったら補足してください。

KGM
質問者

補足

書き込みありがとうございます。 今、for文のメカニズムがわからない状態です。 i , j の中に入る数字で、「jが初期化される」と いうことがさっぱりわからないのです。 その点について、詳しく教えて頂けたらと思っています。

すると、全ての回答が全文表示されます。

関連するQ&A