電子書籍の厳選無料作品が豊富!

#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個表示されているのですか?
行数と「*」は同じになると思われますが。

上記の質問の回答の程宜しくお願いします。

A 回答 (15件中1~10件)

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を++する。
  ・
  ・
  ・
となり、*の数がどんどん増えることになります。

この回答への補足

わかりやすい説明で、ほぼ理解することができました。

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」があるのかを教えて頂けませんか。

補足日時:2006/02/27 01:24
    • good
    • 0

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になるわけです。
    • good
    • 0
この回答へのお礼

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

お礼日時:2006/03/02 12:00

ちなみに質問者さんの考えている動作をするプログラムは


#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;
}
こうなります。
    • good
    • 0

こんにちは、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()文のアルゴリズムを正しく理解する。

ということも頑張りましょう!
※今ちょうど一生懸命勉強してはるとこですよね!:)。
    • good
    • 0
この回答へのお礼

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

お礼日時:2006/03/02 11:57

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の出力」がどのような順番で実行されているか、確認してください。
    • good
    • 0
この回答へのお礼

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

お礼日時:2006/03/02 11:59

>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文を実行してもそれは継続ではなく新規になります。
    • good
    • 0

>j=0の過程がどうしても導きだせません。



for文で指定する初期化文は、そのfor文を実行する前に1回だけ処理されます。
つまり、質問文の二重ループは次の処理と同等です。

for(i = 0 ; i<5 ; i++){
 j = 0;
 for(; j<(i+1) ; j++){
  printf("*");
 }
 printf("\n");
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2006/03/02 11:55

まず、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 は、「繰り返し(このときは初期化されない)」と「移る(このときは初期化される)と違いがあります。
    • good
    • 0

>何故、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が継続している間は実行されません。

この回答への補足

丁寧な書き込みをしていただき、感謝感激です。

ただ、どうしても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の過程がどうしても導きだせません。

補足日時:2006/02/27 11:02
    • good
    • 0

「(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から始まることになります。

この回答への補足

何故、jが最初に初期化されるのですか。
それは、iでは起きないのですか。

i=0 i=0の条件でループが始まる

i=0 J=0の条件でループが終了

i++ j++される(i=1 J=1)

i=1 J=1の条件でループ開始

このような過程の中で、jがどう初期化されるのかを
教えて下さい。宜しくお願いします。

補足日時:2006/02/27 09:14
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!