はじめまして。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列 と逆に考えたほうが正解なのでしょうか?
超初心者でも分かる簡潔かつ明快な回答を宜しくお願い致します。
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進むので。
この回答への補足
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]
---------------------------------------------------------------
上記内容で正しければ、今回の疑問は皆様のご協力で無事解決となるのですが。どうぞ、宜しくお願い致します。
fatbowlerさん、ご回答有難うございます。
正に私が悩んでいた核心を突いて頂き有難うございます。
ご説明頂いた内容をよく噛み砕いて考え直したいと思います。
また、どうしても分からない時にはご回答宜しくお願い致します。
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(縦方向)にします。
※上手く説明できなくて済みませんでした。
・以上。
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
-------------------------------------------
となることから、冒頭質問のように書きました。
本当に超初心者なので、皆様のご説明を理解できず申し訳ありません。
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)をひっくり返すことはできません。
ご回答有難うございました。
失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。
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[縦方向][横方向] として
アクセスして下さい。
・以上。
ご回答有難うございました。
失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# C言語でif文が予想と違う動きをする件について7 4 2023/03/20 00:26
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分 1 2022/07/19 17:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# 至急お願いします。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分母 3 2022/07/19 17:09
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- C言語・C++・C# LU分解法のピボット選択機能実装について(C言語・gcc-9) 1 2022/07/22 15:20
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列を使って魔方陣
-
#if 1 #elseの意味について
-
構文エラー";"が型の前にあり...
-
getcの改行判定
-
C言語のプログラミング (基礎...
-
c言語プログラミングで1から100...
-
C言語 数字以外を入力させない...
-
C言語のwhile文を使った素数判...
-
計算結果がlong型以上になる場...
-
C言語 重複しない4ケタの乱数...
-
raspberrypiでロータリエンコーダ
-
c言語for文
-
C言語基本 2次元配列(for文...
-
10進数からN進数に変換するプロ...
-
C言語で電卓を作成する。
-
和を求める問題
-
C言語 プログラム
-
for文を使用して値を代入したい...
-
while文について、c言語...
-
C言語 入力した数値の平均値の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
構文エラー";"が型の前にあり...
-
#if 1 #elseの意味について
-
for文の中にswitch文はいれられ...
-
getcの改行判定
-
C言語階乗の総和を求める
-
配列を使って魔方陣
-
while文について、c言語...
-
プログラミングで二番目に大き...
-
C言語 数字以外を入力させない...
-
c言語のwhile文を使った計算で...
-
C言語プログラムが理解できなくて…
-
C言語で電卓を作成する。
-
配列を関数に渡す方法
-
C言語の二分法のプログラムにつ...
-
c言語for文
-
scanf関数を用いての加減乗除%...
-
階乗のプログラム!!
-
計算結果がlong型以上になる場...
-
c言語プログラミングで1から100...
-
初心者です。for文、if文を使っ...
おすすめ情報