• ベストアンサー

callocで二次元配列を作成するには?

今、動的オブジェクトの勉強をしております。 動的の一次元配列の作り方として #include <stdio.h> #include <stdlib.h> int main(void) {    int *a;    int x;    printf("配列の大きさX入力>");    scanf("%d",&x);    a=calloc(x,sizeof(int));    return (0); } これでいいと思うんですが動的な2次元配列を 作りたいときはどのようにすればよろしいのでしょうか? (↓作りたい二次元配列の例(1)↓) int main(void) {    int *a;    int x , y;    printf("配列の大きさX入力>");    scanf("%d",&x);         //5と入力    printf("配列の大きさY入力>");    scanf("%d",&y);         //10と入力    上のように入力するとa[5][10]という配列が完成する } よろしくお願いします

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

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

★動的な2次配列の作り方。パート2 ・マクロ関数のバージョンも載せておきます。 // これがマクロ関数 #define MacroCell(a,x,y) ((a)[(y) * arrayX + (x)]) サンプル: int main( void ) {  int *a;  int arrayX; ←この名前とマクロ関数の定義を対応させること。  int arrayY;    printf( "配列の大きさX入力>" );  scanf( "%d", &arrayX ); //5と入力    printf( "配列の大きさY入力>" );  scanf( "%d", &arrayY ); //10と入力    if ( (a = (int *)calloc((arrayX * arrayY),sizeof(int))) != NULL ){   MacroCell(a,0,0)⇒X=0、Y=0   MacroCell(a,4,0)⇒X=4、Y=0     :   MacroCell(a,0,9)⇒X=0、Y=9   MacroCell(a,4,9)⇒X=4、Y=9      MacroCell(a,4,9) = 12345; ←代入時   printf( "a[9][4] = %d\n", MacroCell(a,4,9) ); ←参照時      free( a );  }  return 0; } その他: ・マクロ関数を作るときの注意点として、仮引数になる部分にカッコを付けます。  つまり、(y) とか、(x) とか、(a) とすること。カッコをなくして y、x、a とすると  マクロの呼び出しで  MacroCell( a, 3, 2 + 3 ) となっている場合に  a[ 2 + 3 * arrayX + 3 ] と展開されます。すると  a[ 3 * arrayX + 5 ] と計算されてしまいます。このためカッコをつけておくと  a[ (2 + 3) * arrayX + (3) ] と展開されて正しく  a[ 5 * arrayX + 3 ] と解釈されます。 ・また、配列名を表す a にも括弧を付けます。  これも同様にマクロ関数の呼び出しで  MacroCell( a + 5, X, Y ) とした場合に正しく  (a + 5)[Y * arrayX + X] と展開されることを狙っています。 ・以上。今後の参考に!→マクロの副作用も注意しましょう。

JIF0131
質問者

お礼

完全解決しました。ありがとうございます。 ポインタのポインタを使うという考え方が思いつきませんでした。

その他の回答 (2)

noname#50176
noname#50176
回答No.2

Oh-Orange さんの完璧ですね・・・(驚) 私だったら、 #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <windows.h> #define cell(X,Y,a,x)(a+X+x*Y) // X=1次側、Y=2次側、a=配列先頭ポインタ,x=配列の大きさのX int main(void) { int *a; int x , y , X , Y, data; printf("配列の大きさX入力>"); scanf("%d",&x); printf("配列の大きさY入力>"); scanf("%d",&y); a=(int*)calloc(x*y,sizeof(int)); X=1,Y=4; *cell(X,Y,a,x)=2; data=*cell(X,Y,a,x); printf("%d\r\n",data); free(a); return 0; } のようにします。 Oh-Orange さんのリストはアーキテクチャに優れてますね。

JIF0131
質問者

お礼

ご回答ありがとうございます。参考にします

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

★動的な2次配列の作り方。 ・文章での説明が苦手なのでサンプルを載せます。 サンプル: int main( void ) {  int *a;  int **aa; ←これ追加。  int i, x, y;    printf( "配列の大きさX入力>" );  scanf( "%d", &x ); //5と入力    printf( "配列の大きさY入力>" );  scanf( "%d", &y ); //10と入力    if ( (a = (int *)calloc((x * y),sizeof(int))) != NULL ){   if ( (aa = (int **)calloc(y,sizeof(int*))) != NULL ){    for ( i = 0 ; i < y ; i++ ){     aa[ i ] = &a[ i * x ];    }    aa[0][0]⇒X=0、Y=0    aa[0][4]⇒X=4、Y=0      :    aa[9][0]⇒X=0、Y=9    aa[9][4]⇒X=4、Y=9        free( aa );   }   free( a );  }  return 0; } その他: ・a は X、Y の全体のメモリを確保しています。  aa は a のメモリ領域の Y 軸のポインタを格納した配列です。  よって、aa[Y][X] としてアクセスすればよい。 ・他にも方法はありますが、この方法が一番メモリの使用量や確保回数が少ないと思います。  あとマクロ関数を利用すれば a のメモリ領域だけを確保してマクロ関数でアクセスする  方法がメモリ量を一番抑えることが出来ます。 ・以上。おわり。→3次元配列の考え方は同じに出来ます。

参考URL:
http://oshiete1.goo.ne.jp/qa3002995.html
JIF0131
質問者

お礼

上のパート2]のとお礼の場所が逆になってしまいました。 マクロ関数の使う方法はちょっと難しそうですね・・・・ かなり勉強になりました。ありがとうございます

関連するQ&A

  • C言語の二次元配列について教えて下さい。

    二次元配列で、次の行列の1の要素の添え字を書き出したいです。例えばa11の場合、(0,0)の様にしたいです。 {1,0,1,0} {0,1,1,1}   {1,0,0,1} 自分で出来る範囲で組み上げたプログラムを載せます。 #include <stdio.h> int main(void) { int x,y; int a[3][4]= {{1,0,1,0}, {0,1,1,1}, {1,0,0,1}}; for(x=0;x<3;x++){ for(y=0;y<4;y++){ printf("%3d",a[x][y]); } } return (0); } 実行結果 (0,0) (0,2) (1,1) (1,2) (1,3) (2,0) (2,3) あくまで上の実行結果を出力するものを組み上げたいのですが、続きがさっぱり解りません。それと上記のプログラムには何らかの間違いがあるかもしれません。どなたか解る方、出来るだけ簡単なプログラムを教えて下さい。宜しくお願います。

  • ポインタと二次元配列

    二次元配列a[ ][ ]の第1行の要素以後を0にするプログラムで動きます。 疑問なんですが、4行目のa[ ][4]は、なぜ[ ]のように空欄になっているんでしょうか。 また、8行目のpa=a[1];は、なぜpa=a[0];ではだめなんでしょうか。第1行は先頭行で0行目を意味しているのではないでしょうか。 #include <stdio.h> void main(void) /*ポインタと二次元配列*/ { static int a[ ][4]={{1,2,3,0}, {4,5,6,0}, {7,8,9,-999}}; int j,k,*pa; pa=a[1]; while(*pa!=-999){ *pa=0; pa++; } for(j=0;j<3;j++){ for(k=0;k<4;k++) printf("%5d",a[j][k]); printf("\n"); } }

  • 2次元配列とポインタの引数受け渡しについて

    2次元配列を関数に渡すときは、引数に渡す2次元配列と同じサイズを指定、もしくは2次元目のサイズのみ合わせて渡す方法がありますが、両方とも違うサイズで同じ関数を使いたいです。 最初は中身が同じで引数で受け取る2次元配列のサイズだけ、それぞれに合わせた引数を持つ関数を2つ作っていたのですが、なんだか冗長な気がしました。 そこで、2次元配列の先頭ポインタとサイズを受け取るようにすればいいのかと思い、テストとして次のプログラムを作成してみました。 #include <stdio.h> void func(unsigned char *a, int y, int x); int main(void) { unsigned char a[10][10]; func(a, 10, 10); printf("%d\n", a[7][4]); return 0; } void func(unsigned char *a, int y, int x) { int i, j; for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { *(a + i*y + j) = i * j; } } } もちろんこれでも動くのですが、やはりこういう書き方はルールにはないので、コンパイルで警告が出ます。 a.c: In function ‘main’: a.c:10: warning: passing argument 1 of ‘func’ from incompatible pointer type a.c:4: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[10]’ このような書き方はやはりやめたいいのでしょうか。 また、その際はサイズ別に関数を作るしかないのでしょうか。 他にいい方法があれば教えていただけると助かります。

  • 配列のソート(昇順)

    最大で30個の整数データを入力し、それを大きい順に並べ替えるプログラムを1次元配列と繰り返し・if文を使って作成しなさい。 という問題で #include<stdio.h> main() { int a[30],x,y,z; printf("Seisu wo 30 ko Nyuryoku \n"); for(x=0;x<=29;x++) scanf("%d",&a[x]); printf("before sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); for(x=0;x<=28;x++) for(y=0;y<=28-x;y++) if(a[y]<a[y+1]) { z=a[y];a[y]=a[y+1];a[y+1]=z; } printf("\n after sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); } ここまで出来たのですが最大で30個ということなので(例)「10個の整数を入力して Z を入力したら終了」 としたいのですがどこをどのようにすればいいですか?

  • 2次元配列

    大学の課題なのですが 10×10の2次元配列に、平面のビットパターンが入っているとする(0と1の整数が入っているとする)。左右反転して出力しなさい。 という問題で、自分は以下のプログラムを作ったのですが、うまくうごいてくれません。だれか間違いを指摘していただけないでしょうか。 よろしくお願いします。 #include<stdio.h> int main(void) { int i,j; int data[10][10]={0,1}; for(i=0;i<10;i++){ for(j=0;j<10;j++){ printf("%3d",data[10-i][10-j]); } printf("\n"); } return(0); }

  • 多元配列について(ANSI C)

    動的多元配列で、 Voidポインタに、多種の型がぶら下がった多元配列を作り、 読み書きをしたいのですがどのようにしたらよろしいでしょうか。 具体的には、 x[0][1]は、intで「2」が入っている x[0][4]は、intで「9」が入っている x[1][2]は、charでしかも文字列の配列で「goo」が入っている x[1][5]は、charでしかも文字列の配列で「教えて」が入っている x[0]は、int型の配列。X[1]は、文字列型の配列。 というようなものです。 一応ソースは作ってみたのですが、int型では問題なくいくのですが、 文字列は、コンパイルはできますが、実行すると予期せぬことが起きます。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main (void) {      void **topPointa;      int * iDataInput;      int * iDataOutput ;      char * chDataInput;      char * chDataInput2;      char * chDataOutput1 ;      // ポインタアドレス用のメモリ確保      topPointa = (void *) calloc (10 , sizeof(void *));      if(topPointa == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      //int配列のメモリ確保      iDataInput = (int * ) calloc (10 , sizeof(int));      if(iDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      iDataInput[0] = 3 ;      iDataInput[1] = 4 ;      topPointa[0] = (void * ) &iDataInput;      //int配列の取り出し      iDataOutput = *(int *) topPointa[0];      printf( "int: %d\n", iDataOutput[0] );      printf( "int: %d\n", iDataOutput[1] );      //char配列 のメモリ確保      chDataInput = (char * ) calloc (10 , sizeof(char *));      if(chDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      chDataInput2 = (char * ) calloc (10 , sizeof(char));      if(chDataInput2 == NULL) {           printf("メモリが確保できません\n");           exit(-1);       }      strcpy(chDataInput2 , "hoe");      chDataInput[0] = &chDataInput2;      topPointa[1] = (void * ) &chDataInput;      //char配列の取り出し      chDataOutput1 = *(char *) topPointa[1];      printf( "char: %S\n", chDataOutput1[0] );      free(iDataInput);      free(chDataInput);      free(chDataInput2);      return 0; } 言語は、C言語ANCI Cでお願いします。 以上。よろしくお願いします。

  • scanf が無視されます

    例えば下のようなプログラムを実行するとmain関数の scanf が無視 されてしまいますが何故なのでしょうか。コンパイラはLSI C-86試食版です。 ----------------------------- #include <stdio.h> int main ( ) ; void aa ( ) ; int main ( ) { int i ; aa ( ) ; printf ( " input i. \n " ) ; scanf ( " %d ", &i ) ; printf ( " i = %d\n ", i ) ; } void aa ( ) { int x, y ; while ( scanf ( " %d ", &x ) ! = EOF ) { y = x ; printf ( " y= %d\n ", y ) ; } } --------------------------------

  • C言語の質問です。

    #include"stdio.h" int main(void){ int a, b, add; scanf_s("%d%d", &a, &b); add = a+b; printf("add=%d\n", add); return 0; } と、------------------------------------------------------------------------------ #include"stdio.h" int tasizan(int x, int y); int main(void){ int a, b, add; scanf_s("%d%d", &a, &b); add = tasizan(a, b); printf("add=%d\n", add); return 0; } int tasizan(int x, int y){ int aa; aa = x + y; return aa; } の違いを教えてください。

  • 2次元配列を引数とする関数について

    2次元配列を引数とする関数について 私は今、2次元配列を引数とする関数の表を作るという課題に取り組んでいます。 条件として、int a[数字][数字]={{1,2,3...}}という配列の宣言と同時の初期化は使わず、 関数内で表の値を代入し、値を表示する関数を作り、事実上二つの関数を作るというものです。 私は以下のようなプログラムを作り、動かしましたが、[数字][数字]=********のような本来 あるべき実行結果とは異なる数字の羅列が出てきてしまいました。 ↓ #include <stdio.h> void func(int a[][6]); void fund(int b[4][6]); void main(void) { int a[4][6]; fund(a); func(a); } void func(int a[][6]) { int i,j,b[4][6]; fund(b); for(i=0;i<4;i++)        { for(j=0;j<6;j++) { printf("a[%d][%d]=%d\n",i,j,a[i][j]); printf("\n"); } } } void fund(int b[4][6]) { int i,j; for(i=0;i<4;i++) { for(j=0;j<6;j++)          { scanf("b[%d]*[%d]=%d\n",&i,j,b[i][j]); } } } 本来の実行結果 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 紙にも書いて何回も見直しましたが、どこがおかしいのかわかりませんでした。 どうすれば良いのでしょうか? 何か良いアドバイスをよろしくお願いします。

  • 配列

    このプログラムを #include<stdio.h> int x,y; int n; void RUL(int n),DLU(int n),LDR(int n),URD(int n); main() { scanf("%d",&n); printf("#位相%dのヒルベルト曲線\n",n); x=0; y=0;printf("(%d %d) \n)",x,y); RUL(n); } void RUL(int n) { if(n<=0) {return;} URD(n-1);x=x+1;printf("(%d %d)\n",x,y); RUL(n-1);y=y+1;printf("(%d %d)\n",x,y); RUL(n-1);x=x-1;printf("(%d %d)\n",x,y); DLU(n-1); } void DLU(int n) { if(n<=0) {return;} LDR(n-1);y=y-1;printf("(%d %d)\n",x,y); DLU(n-1);x=x-1;printf("(%d %d)\n",x,y); DLU(n-1);y=y+1;printf("(%d %d)\n",x,y); RUL(n-1); } void LDR(int n) { if(n<=0) {return;} DLU(n-1);x=x-1;printf("(%d %d)\n",x,y); LDR(n-1);y=y-1;printf("(%d %d)\n",x,y); LDR(n-1);x=x+1;printf("(%d %d)\n",x,y); URD(n-1); } void URD(int n) { if(n<=0) {return;} RUL(n-1);y=y+1;printf("(%d %d)\n",x,y); URD(n-1);x=x+1;printf("(%d %d)\n",x,y); URD(n-1);y=y-1;printf("(%d %d)\n",x,y); LDR(n-1); } 実行結果は (0 0) (0 1) ・ ・ ・ (0 254) (0 255) になります。これを2次元配列で表したのですがどのようにいじればいいでしょうか?おねがいします。

専門家に質問してみよう