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

プログラミングの勉強をしています。
右上が直角とかるプログラムを作成せよという問題でサンプルコードが次のように書かれていました。

int main(void)
{
int i,j,k;

printf("何段ですか:");
scanf("%d",&i);

for (k=0; k<i; k++) {
for (j=0; j<k; j++) {
printf(' ');
}
for (; j<i; j++) {
printf('*');
}
printf("¥n")
}
return 0;
}

このサンプルコードについて
for(k=0から最後の文まで意味が分からなくて質問させていただきました。
分からない点はk,jが何に対する変数かとそれぞれのforがどういった意味の繰り返しかということです。
分かるかたがいましたら解説をお願い致します。

A 回答 (4件)

それを知るには


for (k=0; k<i; k++) {
の i が何を表わしているのか、を考えましょう。


iは
printf("何段ですか:");
scanf("%d",&i);
で入力した「段数」です。

※ 練習用ということで、 i という単純な変数名を使っていますが、
実践では、意味のある名前を付けるのが、プログラムをわかりやすくするコツです。
例えば: rows,size , dansuu 等


出力した図形は

上から1段目 最上段+0段目: 空白が0個 + *がi個 の計 i 個
上から2段目 最上段+1段目: 空白が1個 + *がi -1個 の計 i 個
...
上からX段目 最上段+(X-1)段目: 空白がX-1個 + *が(i -(X-1))個 の計 i 個
...
上からi段目 最上段+(i-1)段目: 空白がi-1個 + *が1個 の計 i 個

という形になります。
これを
for( 段数分の繰り返し ) {
 1談分の出力
}
と繰り返したい場合、いろんなやり方が考えられます。
for( 段数分の繰り返し ) でのループ変数から、他の「上から何段目」「最上段+?段目」「空白の個数」「*の個数」が求められれば、どんな方法でも構いません。
ですが、どうせなら、楽にできるものがいいです。

それぞれを k とすると
「上から何段目」 for( k=1;k<=i;k++)
「最上段+?段目」「空白の個数」 for( k=0;k<i;k++)
「*の個数」 for( k=i;k>=1;k--)
いずれでも、ループ内の計算を変えれば利用できます。

その中で
「最上段+?段目」「空白の個数」 for( k=0;k<i;k++)
を採用したのが、そのプログラムです。


また、C言語でも ループは 0 から始めることが多いです。

配列は 0 から始まります。
ポインタは 基準となるアドレス ±α で使うことが多いです。
このように「基準 + 差分」という処理をする場合には、 差分=0 から始めるのが都合がいいです。
    • good
    • 0

「ループ」「多重ループ」「ループの入れ子構造」はご理解できてますか?




forループは
for(〜) {
 ここを繰り返し
}
という形で 「ここを繰り返し」の部分を繰り返します。
この 「ここを繰り返し」の部分には、長くて複雑なプログラムも書けます。
そして、forループも書けます。

このプログラムの場合
for (k=0; k<i; k++) {
}
でループしていて、「ここを繰り返し」の部分が

for (j=0; j<k; j++) {
printf(' ');
}
for (; j<i; j++) {
printf('*');
}
printf("¥n")

となっています。
※ このように、ループの中にループがあるような構造を「多重ループ」「ループの入れ子構造」と呼びます。


for (k=0; k<i; k++) { と変数kを使ってループしているので、
ループを展開すれば

k=0;
for (j=0; j<k; j++) {
printf(' ');
}
for (; j<i; j++) {
printf('*');
}
printf("¥n")

k=1;
「ここを繰り返し」
.....
k=i - 1;
「ここを繰り返し」
/* ループ終了 */


「ここを繰り返し」
の部分を一つ一つ見ていけば
・「空白を出力(改行無し)」をforで繰り返し
・「*を出力(改行無し)」をforで繰り返し
・改行を出力
だとわかります。
これは、「1行分の空白と*と改行の出力」です。
つまり
for (k=0; k<i; k++) {
 「1行出力」
}
というのがメインプログラムです。



for (j=0; j<k; j++) {
のループの方はわかるでしょう。


少し高度なのは、
for (; j<i; j++) {
という書き方です。

for文は for(初期化式; 判定式 ; 更新式 ) という形に ; で区切られています。
・初期化式:
ループ開始時に1回だけ実行される。
省略すると、何もしない
・判定式
判定結果が真である限り、ループを続ける。/条件を満さなくなったらループを抜ける。
省略すると、常にループを続ける
・更新式
各ループの終了時に実行する。
省略すると、何もしない


for (j=0; j<k; j++) {

j=0 に初期化
0<k でループ継続
ループ終了時に j++ で j=1
1<k でループ継続
ループ終了時に j++ で j=1
...
ループ終了時に j++ で j=k
k<k でないのでループ首領

という動作になるので、forループ終了時には j=k となっています。
その直後に for (; j<i; j++) { があるので、このループは j=k の状態から開始したことになります。
わざわざ書けば for (j=k ; j<i; j++) { です。
    • good
    • 0
この回答へのお礼

丁寧な回答ありがとうございます。
不明な点が少しあるので質問させていただきます。
なぜ最初のループがk=0で始まっているのでしょうか?
kがそもそも何を表しているのでしょうか?
そこが分からないので教えていただきたいです。

お礼日時:2020/08/17 16:58

とりあえず実行できるようにしてみました:


https://paiza.io/projects/4aaA7XblE2Q4Ky-mhRhbgA
出力結果をみると、主題どおり右上が直角になってます。
この形をつくるために
1) for ( j=0; j<k; j++ ){ printf( " " ); }
2) for ( ; j<i; j++ ){ printf( "*" ); }
3) printf( "\n" );
――を繰り返してますが、k=0のとき、そしてk=1のときに、1)や2)がどういう出力をするかをデバッガでステップ実行させてみてください。そのうえで、k=2やk=3のときの挙動を頭の中でシミュレートできれば、意味を理解したといえると思います。
    • good
    • 0

>分かるかたがいましたら解説をお願い致します。


ソースコードを インデントをつけて書き直して見れば、わかるのでは?

int main(void)
{
 int i,j,k;

 printf("何段ですか:");
 scanf("%d",&i);

 for (k=0; k<i; k++) {
  for (j=0; j<k; j++) {printf(' ');}
  for (  ; j<i; j++) {printf('*');}
  printf("¥n");
 }
 return 0;
}
    • good
    • 0

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