アプリ版:「スタンプのみでお礼する」機能のリリースについて

はじめまして。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列 と逆に考えたほうが正解なのでしょうか?

超初心者でも分かる簡潔かつ明快な回答を宜しくお願い致します。

A 回答 (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進むので。

この回答への補足

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]
---------------------------------------------------------------
上記内容で正しければ、今回の疑問は皆様のご協力で無事解決となるのですが。どうぞ、宜しくお願い致します。

補足日時:2007/07/15 06:33
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/07/15 01:25

★回答者 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(縦方向)にします。
 ※上手く説明できなくて済みませんでした。
・以上。
    • good
    • 0
この回答へのお礼

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
-------------------------------------------
となることから、冒頭質問のように書きました。

本当に超初心者なので、皆様のご説明を理解できず申し訳ありません。

お礼日時:2007/07/15 01:13

↑■■■■■■■


↑■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)をひっくり返すことはできません。
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

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

お礼日時:2007/07/15 06:44

No.1の方の回答で正解ですが、


こう書いた方が分かりやすいかな?

for ( y = 0 ; y < 2 ; y++ ){ /* 行のループ */
for ( x = 0 ; x < 4 ; x++ ){ /* カラムのループ */



    • good
    • 0
この回答へのお礼

ご回答有難うございました。

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

お礼日時:2007/07/15 06:49

★二次元配列について


・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[縦方向][横方向] として
 アクセスして下さい。
・以上。
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

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

お礼日時:2007/07/15 06:50

2次元配列のx方向、y方向は単なる概念なので。

。。
>(10)行目での条件を x<4
>(11)行目での条件を y<2
この条件では、(12)でa[3][1]を参照することになるので、
型宣言とあっていません
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

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

お礼日時:2007/07/15 06:50

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