• ベストアンサー

C言語基本 2次元配列(for文:条件値について)

はじめまして。C言語の超入門者です。現在、基礎的な事を独学中なのですが、以下(10)(11)の部分の解釈で行き詰まってしまいました。 (1)#include <stdio.h> (2) (3)main() (4){ (5)int x,y; (6)int a[2][4]={ (7){1,2,3,4}, (8){5,6,7,8} (9)}; (10)for(x=0;x<2;x++){ (11)for(y=0;y<4;y++) (12)printf("a[%d][%d]=%d ",x,y,a[x][y]); (13)printf("\n"); (14)} (15)} (6)は、int a[2][4]・・・y方向に2列、x方向に4列 ↑■■■■■■■ ↑■5■6■7■8■ Y ■■■■■■■ 方■1■2■3■4■ 向■■■■■■■    X方向→→ なので (10)行目での条件を x<4 (11)行目での条件を y<2 とすると結果が正しく出ず、 (10)行目での条件を x<2 (11)行目での条件を y<4 と値を逆転させると正しく表示されるのは何故でしょうか? (6)int a[2][4]は、x方向は2列 , y方向は4列 と逆に考えたほうが正解なのでしょうか? 超初心者でも分かる簡潔かつ明快な回答を宜しくお願い致します。

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

  • ベストアンサー
  • fatbowler
  • ベストアンサー率48% (26/54)
回答No.6

どうもかゆいところに手が届いてなさそうなので補足します。 > (10)行目での条件を x<4 > (11)行目での条件を y<2 > とすると結果が正しく出ず、 > > (10)行目での条件を x<2 > (11)行目での条件を y<4 > と値を逆転させると正しく表示されるのは何故でしょうか? あなたの疑問に対する明快な答えは、 「あなたの頭の中の (x, y) とプログラムの (x, y) が食い違って(入れ替わって)いるためです。」 つまり、あなたがyだと思っているのはプログラム上のxに当たり、xだと思っているのが yに当たるるので、値の範囲もxが 0,1 、yは 0,1,2,3 で正常に表示されるのです。 「xは横方向、yは縦方向」 にこだわるなら、ANo.5のように、プログラムのxとyを入れ替え、頭の中にある (x, y) に合わせるのが最も良い解決法でしょう。 もちろん、a[y][x]というアクセスの仕方になります。 無理やり  int a[4][2] = {   { 1, 5 },   { 2, 6 },   { 3, 7 },   { 4, 8 }  };  for ( y = 0 ; y < 2 ; y++ ){   for ( x = 0 ; x < 4 ; x++ )    printf( "a[%d][%d]=%d ", x, y, a[x][y] );   printf( "\n" );  } とできなくはないですが、明らかに配列への格納の順番が不自然ですよね? ですのでC言語の世界では、 a[y][x] とするのが普通だと覚えて下さい。 なお、蛇足ながら頭にイメージするのは ↑■■■■■■■ ↑■5■6■7■8■ Y ■■■■■■■ 方■1■2■3■4■ 向■■■■■■■    X方向→→ ではなく、    X方向→→ Y ■■■■■■■ 方■1■2■3■4■ 向■■■■■■■ ↓■5■6■7■8■ ↓■■■■■■■ とした方がいいでしょうね。 Y方向は改行によって1進むので。

C-baby
質問者

お礼

fatbowlerさん、ご回答有難うございます。 正に私が悩んでいた核心を突いて頂き有難うございます。 ご説明頂いた内容をよく噛み砕いて考え直したいと思います。 また、どうしても分からない時にはご回答宜しくお願い致します。

C-baby
質問者

補足

fatbowlerさんはじめ、有識者のご意見を再度お聞きしたくて、新たに質問させて頂きます。 様々なご回答を頂きながら、今更ながら気付いたのですが、for文(2重ループ)に対しての理解も不十分だったようです。 fatbowlerさんの投稿を拝見した後、参考書および有識者のWEBサイトを見て回ったのですが、今回の2重ループは以下のような捉え方をすればいいのかな?と半信半疑の状態ですので、ご指南の程、宜しくお願い致します。 --------------------------------------------------------------- 【今回の質問箇所】 (10)for(x=0;x<2;x++){ (11)for(y=0;y<4;y++) --------------------------------------------------------------- ■現在の2重ループ理解状況■ 【プロセス1】 ★x = 0 の状態で y=0 (結果:a[0][0] = 1) y=1 (結果:a[1][0] = 2) y=2 (結果:a[2][0] = 3) y=3 (結果:a[3][0] = 4) 以上yへの代入を実行しプロセス2へ --------------------------------------------------------------- 【プロセス2】 ★x = 1 の状態で y=0 ⇒ a[0][1] = 5 y=1 ⇒ a[1][1] = 6 y=2 ⇒ a[2][1] = 7 y=3 ⇒ a[3][1] = 8 以上yへの代入を実行し終了 --------------------------------------------------------------- 【イメージ】 ■■■■■ ■4■■8■y[3] ■■■■■ ■3■■7■y[2] ■■■■■ ■2■■6■y[1] ■■■■■ ■1■■5■y[0] ■■■■■ x[0] x[1] --------------------------------------------------------------- 上記内容で正しければ、今回の疑問は皆様のご協力で無事解決となるのですが。どうぞ、宜しくお願い致します。

その他の回答 (5)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★回答者 No.2 です。  ちょっと質問の解釈を間違いました。   >↑■■■■■■■ >↑■5■6■7■8■ >Y ■■■■■■■ >方■1■2■3■4■ >向■■■■■■■ >   X方向→→  を >int a[2][4]={ > { 1, 2, 3, 4 }, > { 5, 6, 7, 8 }, >};  というデータにして  [1][2][3][4]  [5][6][7][8]  と表示したいのなら回答者 No.3、No.4 さんので正しいです。 >for ( x = 0 ; x < 2 ; x++ ){ > for ( y = 0 ; y < 4 ; y++ ) >  printf( "a[%d][%d]=%d ", x, y, a[x][y] ); > printf( "\n" ); >}  ↑  これは変数の x、y の意味が逆ですね。だから  ↓  for ( y = 0 ; y < 2 ; y++ ){   for ( x = 0 ; x < 4 ; x++ )    printf( "a[%d][%d]=%d ", y, x, a[y][x] );   printf( "\n" );  }  と x、y の変数名を入れ替えれば良さそうです。つまり意味を。 >と値を逆転させると正しく表示されるのは何故でしょうか?  ↑  値を逆転させると正しく表示されますか?  変数名を入れ替えれば上手くいきますけど。    内側のループに x(横方向)を  外側のループに y(縦方向)にします。  ※上手く説明できなくて済みませんでした。 ・以上。

C-baby
質問者

お礼

super-dogさん、Oh-Orangeさん、SRitchieさん、ymmasayanさん、早速のご回答有難うございました。 皆様のご解説を見て、60分考えてみました。 しかし、(10)行目 x<□ および (11)行目 y<□ に入る値がどうしても (6)int a[2][4]={ からx<4 および (11)行目 y<2 ではないかと思ってしまうのです。 また、 ymmasayanさんのご説明で >内側のyのループが早く回り(4回)、外側のxのループが2回回ります。 とありましたが、xとyに対する処理は同時に行われている訳ではないのですか? Oh-Orangeさんから BASIC 出身者ですか? と質問されましたが、 私はプログラムのプの字をかじり始めたばかりの者です。 >値を逆転させると正しく表示されますか? >変数名を入れ替えれば上手くいきますけど。 ともご指摘がありましたが、 ------------------------------------------- 私的な『正しく表示される』の意味 (10)for(x=0;x<2;x++){ (11)for(y=0;y<4;y++) でコンパイル後 a[0][0]=1 a[0][1]=2 a[0][2]=3 a[0][3]=4 a[1][0]=5 a[1][1]=6 a[1][2]=7 a[1][3]=8 ------------------------------------------- 私的な『結果が正しく出ず』の意味 (10)for(x=0;x<4;x++){ (11)for(y=0;y<2;y++) でコンパイル後 a[0][0]=1 a[0][1]=2 a[1][0]=5 a[1][1]=6 a[2][0]=6618672 a[2][1]=4226262 a[3][2]=6693692 a[3][1]=0 ------------------------------------------- となることから、冒頭質問のように書きました。 本当に超初心者なので、皆様のご説明を理解できず申し訳ありません。

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.4

↑■■■■■■■ ↑■5■6■7■8■ Y ■■■■■■■ 方■1■2■3■4■ 向■■■■■■■    X方向→→ ではなくて ↑■■■■■■■ ↑■5■6■7■8■ 前■■■■■■■ 変■1■2■3■4■ 数■■■■■■■    後変数→→ です。 (10)for(x=0;x<2;x++){ (11)for(y=0;y<4;y++) (12)printf("a[%d][%d]=%d ",x,y,a[x][y]); から、内側のyのループが早く回り(4回)、外側のxのループが2回回ります。 したがって 1234 5678 と出力されます。 (10)と(11)をひっくり返すことはできません。

C-baby
質問者

お礼

ご回答有難うございました。 失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

  • SRitchie
  • ベストアンサー率21% (103/470)
回答No.3

No.1の方の回答で正解ですが、 こう書いた方が分かりやすいかな? for ( y = 0 ; y < 2 ; y++ ){ /* 行のループ */ for ( x = 0 ; x < 4 ; x++ ){ /* カラムのループ */ ・ ・ ・

C-baby
質問者

お礼

ご回答有難うございました。 失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★二次元配列について ・int a[2][4] という場合は  a[0][0]  a[0][1]  a[0][2]  a[0][3]    a[1][0]  a[1][1]  a[1][2]  a[1][3]    という順でメモリ内に確保されます。  つまり a[縦方向][横方向] と考えるべきです。 >(6)int a[2][4]は、x方向は2列 , y方向は4列 と逆に考えたほうが正解なのでしょうか?  ↑  int a[4][2] なら縦4行×横2列という感じなります。  なので x、y の数を入れ替えると上手く表示されただけです。 ・質問者さんは BASIC 出身者ですか?  多次元の配列の解釈(指定?)が C 言語系と BASIC 系で異なります。  BASIC 系では多次元配列が左→右に次元が大きくなりますが、C 言語系は右→左の順になります。  つまり int a[2][4] を a[横方向][縦方向] とした場合は  5、1  6、2  7、3  8、4  という縦型イメージになります。 ・正しくは int a[2][4] を a[縦方向][横方向] と解釈した方が良さそうです。  その場合は  for ( y = 0 ; y < 2 ; y++ ){   for ( x = 0 ; x < 4 ; x++ ){    printf( "a[%d][%d] = %d ", y, x, a[y][x] );   }   printf( "\n" );  }  となります。 ・今回の場合は for 文の(10)、(11)の行を入れ替えて  (11)for ( y = 0 ; y < 4 ; y++ ){  (10) for ( x = 0 ; x < 2 ; x++ )  (12)  printf( "a[%d][%d]=%d ", x, y, a[x][y] );  (13) printf( "\n" );  (14)}  とすればちゃんとイメージ通りに表示されます。  x、y の数を入れ替えるのではなく。 ・本当はメモリ・イメージと配列のイメージをあわせた方が分かりやすいです。  つまり、メモリの配置より  a[横方向][縦方向] よりも  a[縦方向][横方向] として  アクセスして下さい。 ・以上。

C-baby
質問者

お礼

ご回答有難うございました。 失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

noname#96023
noname#96023
回答No.1

2次元配列のx方向、y方向は単なる概念なので。。。 >(10)行目での条件を x<4 >(11)行目での条件を y<2 この条件では、(12)でa[3][1]を参照することになるので、 型宣言とあっていません

C-baby
質問者

お礼

ご回答有難うございました。 失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

関連するQ&A