char型の二次元配列の意味が分からないのです・・・。
char namae[5][10] = {
"a1",
"a2",
"a3",
"a4"
};
printf("%s\n",namae[1]);
という文があったのですが、これは実行するとa2と表示されました。どうしてなのでしょう。
そもそもcharは文字1文字ですよね。char[5]という一次元配列に5文字の文字列を入れることができるというのは分かります。でもchar[5][10]ってどんな文字列を入れるのでしょうか。
どうして初期化で"a1"という二文字を順々と並べるのか、printfでどうしてnamae[1]なのかが意味不明です。二次元配列だからnamae[1][0]とかで指定するのではないのかと思うのですが。
とにかく混乱です(>_<)
ご存知の方、教えていただけませんか?
No.1ベストアンサー
- 回答日時:
2次元配列は「1次元配列の1次元配列」だと考えてください。
char[5][10]は char[10]の配列が5つの配列です。
char namae[5][10] = {
"a1", ←これはnamae[0]にあるchar[10]の配列に入る
"a2", ←これはnamae[1]にあるchar[10]の配列に入る
"a3", ←これはnamae[2]にあるchar[10]の配列に入る
"a4" ←これはnamae[3]にあるchar[10]の配列に入る
};
配列を使わなければ
char namae0[10] = "a1" ;
char namae1[10] = "a2" ;
char namae2[10] = "a3" ;
char namae3[10] = "a4" ;
char namae4[10] = "" ; /* 配列の大きさに満たない部分は0で初期化 */
という事です。namaeのあとの数字が配列の一つ目の添字に対応します。
>どうして初期化で"a1"という二文字を順々と並べるのか
2文字なのはたまたまで、9文字まで(\0が必要なので、10-1文字分)使えます。
並んでいるのは、上のように初期化するためです。
>printfでどうしてnamae[1]なのか
printfの%sに対応するのは「文字列」、つまり、charの配列か charへのポインタです。
char[][]は「charの配列の配列」なので、対応していません。
namae[1]は「charの配列」なので、%sで対応できます。
上の例にある namae1 だったら%sで表示できるのはわかるのではないでしょうか。
>二次元配列だからnamae[1][0]
これは、上の例でいえば namae1[0]です。つまり、ただのcharになります。文字列にはなりません。
ご回答ありがとうございます。
分かりやすくてだいぶ分かってきました!!
#include <stdio.h>
main()
{
char a[5][10] = {
"abcde",
"fghij",
""
};
printf("a[0][1]=%c\n",a[0][1]);
printf("a[0]=%s\n",a[0]);
printf("a[2]=%s\n",a[2]);
printf("a[2][0]=%d\n",a[2][0]);
}
こう書いてみたら、1番目のprintfで一文字だけ取り出せるし、2番目では文字列が出るし、3番目では文字列が入ってないし、4番目では数字の0がでます(^_^)
ただ、不思議なのはint型の配列だとint[5][10]とあったときint[10]の配列が5つって考えますか? 5行、10列の数値を入れるセルがあるって考えちゃうんです。
No.4
- 回答日時:
回答はすでに出ていますが……。
実は、ポイントになるのは、「Cには2次元配列は存在しない」という事実です。(規格上はそうです)
じゃ、char namae[5][10] という表現は何かと言いますと、
char name[10] という「型」の、さらに、配列 です。
もちろん、name[1][1] は、name[][1] という要素の、[1] 番目 ということですから、事実上2次元配列のように扱えます。
この事実は、後々、いろんなところでいろいろな悪さをします。
たとえば、Cでは、初期化の際、「配列の要素数は省略できる」という決まりがあります。
たとえば、
char name[] = "abcdefg";
など。
ただし、上記の場合、
char name[][10] = {"....", "....", "..."};
とはできますが、
chae name[][] = ...
というのはできません。
[10] のほうは、(配列の要素数ではなくて)型の一部だからです。
これは、2次元配列のつもりで、malloc() なんかを使おうとした際にも、いろいろと、面倒を起こすことがあります。
ありがとうございます!! そうなんです。もうほぼ解決したのでそろそろ閉じようと思ってました(^_^;
char namae[5][10]というのはnamae[10]という型の配列なのですね。namae[10]が型なので、namae[5][10]の[10]の部分は要素数を表しているのではなく、省略できない。
char namae[]="abcde"; とかはよく使うので、混同しそうですね。配列の要素数と型の違いがわかってよかったです。頭がすっきりしました!!
malloc()はメモリの確保に使うんでしたっけ。まだ1,2回しか記述したことがありません(汗)。
No.3
- 回答日時:
> ただ、不思議なのはint型の配列だとint[5][10]とあったときint[10]の配列が5つって考えますか? 5行、10列の数値を入れるセルがあるって考えちゃうんです。
これは、どう解釈するか、の違いです。
今回のは、「charの配列を『文字列』として解釈する」というCの仕様の関係で二次元配列にしたもので、仮に、string型という文字列専用の型があれば string[5]とするべきものでした。
また、char [5][10]も、「5行10列のchar型整数を入れるセルがある」と解釈することもできます。
実際、 8bitの画像データでそのように使い、 image[y][x]=100; 等とするケースもあります。
逆に int [5][10]でも、「10科目のテストの点を5人分」という場合は、int[10]の配列が5個、と考えた方がわかりやすいです。
ありがとうございます!!
charの配列を文字列として見れば、char a[5][10]は10文字のが5個。整数を入れるものだと考えれば5行10列あるとも見れるのですね。
int型の配列でも行列以外の見方があるとわかってよかったです。これからもCの勉強がんばります(^_^)
No.2
- 回答日時:
> char namae[5][10]
これは char [10]の配列が5つ集まった配列になります。
つまり"a1","a2",……という文字列は、それぞれ、char [10]の配列空間に代入されていることになります。
配列の名前は配列の先頭データを指すポインタと同じなので、二次元配列は一次元配列のポインタの配列と同義になります。
仮に
char b1[10], b2[10], b3[10], b4[10], b5[10];
char *c[5];
とあったとき、
b1 = "a1";
b2 = "a2";
b3 = "a3";
b4 = "a4";
b5 = "a5";
c = {b1, b2, b3, b4, b5};
とするのと同じです。
そこで
>printf("%s\n",namae[1]);
としたとき、name[1]は、文字配列"a2"の先頭アドレスを指していることになるのです。
>二次元配列だからnamae[1][0]とかで指定するのではないのかと思うのですが。
文字列内の個々の文字要素にアクセスするときはそうなります。
例えば、
name[1][0]とすれば、それは'a'ですし、
name[1][1]とすれば、それは'2'になります。
name[1][2]なら、そこには文字列の末端を示す'\0'が入っています。
この回答への補足
すごいです!!
例えば、char a[5][10]のa[5]って5個のアドレスが配列になってるのですね!!
少なくともa[0]はa[0][10]のアドレスでした(^O^)
#include <stdio.h>
main()
{
int i;
char *pt;
char a[5][10] = {
"abcde",
"fghijk"
};
pt = a[0];
for(i=0; i<=4; i++){
printf("%c", (*pt+i));
}
puts("");
puts(a[1]);
}
ご回答ありがとうございます!!
char namae[5][10]をchar[10]の配列が5つ集まった配列と考えるのはNo.1さまと同じですね。char型の二次元配列はそう理解すると良いのですね。
ポインタ配列を使った説明、なんとか理解できます。c[0]はb1[0]のアドレスを格納しているのですよね。そこにあるデータがa1で。
ただ、それと
>>printf("%s\n",namae[1]);
>としたとき、name[1]は、文字配列"a2"の先頭アドレスを指していることになるのです。
とのつながりが明確には理解できないのですが、char型の二次元配列はchar namae[5][10]だとすれば、
namae[0]がnamae[0][10]のアドレスだという理解でいいのですか? まるで普通のchar a[5]のaがアドレスであるのと同じということでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
2次元配列を戻り値とする関数?
-
VBで構造体の配列を関数に渡す...
-
VB2010でのコントロール多次元...
-
C# 配列の変数宣言について。
-
Functionの戻り値を2次元配列...
-
配列を使わずに、変数名を動的...
-
LGノートPCグラムについて
-
テキストファイルから文字列を...
-
配列で格納したものをmsgboxで...
-
if文の判定条件に配列
-
c言語でのヒストグラム作成用の...
-
大きさが領域未定の画像の配列...
-
配列について
-
市販のビンゴカードについて
-
メモリの初期値
-
VBでC言語のポインタみたい...
-
配列変数のアドレス
-
C言語 変換指定%sについてです。
-
実数→文字列の方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
先頭アドレスとは何ですか?
-
C言語で特定列だけを抽出して配...
-
配列の参照渡しで型が一致しま...
-
VBで構造体の配列を関数に渡す...
-
C++ vectorに配列をプッシュしたい
-
【速いブラインドタッチ】手を...
-
unsigned char配列への入力の仕方
-
配列をEraseしてもメモリが開放...
-
【C言語】配列の中に配列を入れ...
-
ExcelVBAで質問です。離れた二...
-
4勤2休のシフト作成
-
Functionの戻り値を2次元配列...
-
Redimした動的配列はEraseする...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
おすすめ情報