• ベストアンサー

D言語の連想配列

D言語で以下のプログラムが動いてくれません。 なにがおかしいのでしょうか。 int main(char[][] args) { int[char[]] a; a["abc"]=1; a["def"]=2; a["ghi"]=3; char[][] x=a.keys; for(int i=0;i<x.length;i++) printf("%s\n",x[i]); return 0; } 実行結果 Error: Access Violation

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

D言語では配列の内部表現がC言語とは異なります。 char[]の場合、先頭の4バイトに要素数が格納され、続いて配列の実体のアドレスが格納されています。 今回の場合、 printf("%s\n",x[i]); のところでアクセス違反が発生しています。 これは、C言語から見れば、あたかも printf("%s\n", x[i].length, x[i]); のように、引数が3つ渡されたのと同等になります。 これを解決するには、 printf("%.*s\n", x[i]); とすればよい旨がマニュアルに記載されています。 ただ、今後CPUのアーキテクチャが異なる環境や、可変個引数のコーリングコンベンションが異なる環境にD言語が移植されると、必ずしも成立しないような気もしますが、現状ではこれで十分かと思います。

参考URL:
http://www.kmonos.net/alang/d/interface.html
nagata20000
質問者

お礼

解決しました。 ありがとうございました。

関連するQ&A

  • D言語の連想配列の配列

    D言語で連想配列の配列を使いたいのですが、 以下のソースをコンパイルするとコンパイルエラーが起きます。なにがいけないのでしょうか。 int main(char[][] args) { int[3][char[]] x; x[0]["abc"]=1; return 0; } エラーメッセージ test.d(4): cannot implicitly convert expression 0 of type int to char[] test.d(4): cannot implicitly convert expression "abc"i of type char[3] to int

  • D言語の連想配列

    D言語の連想配列を使いたいのですが、うまくいきません。同じキーを違うキーだと判定しているようです。 class ではなくstructだとうまくいくようなのですが… class A { int[2] a; this(int p,int q) { a[0]=p; a[1]=q; } int toCmp(A *x) { if(this.a[0]<x.a[0])return -1; if(this.a[0]>x.a[0])return 1; if(this.a[1]<x.a[1])return -1; if(this.a[1]>x.a[1])return 1; return 0; } } int main(char[][] args) { int[A] x; x[new A(1,2)]=1; x[new A(1,2)]=2; foreach(A a,int i;x) { printf("(%d %d) %d\n",a.a[0],a.a[1],i); } return 0; } 実行結果 (1 2) 2 (1 2) 1

  • C言語のポインタと配列

    どうにも理解しようとしていますが全体像が理解できないので、わかっていることわからないことまとめていくのでバンバン指摘してくださるとうれしいです。 1.配列の宣言には int a[]; a[] = {1,2,3}ですが、コンピュータは{"1","2","3"}の部分の数を数えて[]に代入しているので、 int [][3] = {{1,2,3},{4,5,6}}のような配列を作ったとき[][3]の部分の左側の数字も勝手に代入している。 この時なぜ3が勝手に代入されないかがわからない 2.数字とメモリ int s = {1,2,3}をメモリ的に表現すると、123の順に並んでいる。s[1]=2 int s[][2] = {{1,2,3},{4,5,6}}をメモリ的に表現すると123456に並んでいる。s[1][1]= 5 ここまで文字列以外の配列は添え字だけで管理されている。 3.文字列とポインタ char s[] = "abc"とするとメモリ的にはabc\0であり、[]には4が代入され、s[1]はb自身を指す。 char *s = "abc"をメモリで表すとabc\0であり、\0が来るまでを文字列と認識する。 sは&s[0]とも表現できるように、最初のアドレスを指し示している。 char *s[]= {"abc","def"}をメモリ的に表現するとabc\0def\0であり、[]には2がコンピュータにより判断されて代入される。\0までを文字列として表現しようとする。s [1] は"def"の最初のアドレスを指し示すが、s[1][1]とするとe自身を指すようになる。この時、s[1] = &s[1][0]と表現することは可能であると考えられる。 文字列を直接さす場合でも、ポインタで表現する場合でも、\0が要素の最後に来るのでしょうか? また、{{"abc","def"},{"ghi","jkl"}}を文字列で直接表す場合は char s[2][2] = {{"abc","def"},{"ghi","jkl"}}; となるかと思いますが char *s[2][2] = {{"abc","def"},{"ghi","jkl"}}; とするとs[1][1]でghiの最初のアドレスを、s[1][1][0]でg自身を表せるようになるのでしょうか?

  • 関数に配列を渡して値を変える

    関数に配列を渡して値を書き換えたいのですが、文字配列である char b[10]="abc"; の書き換えが綺麗にできません。 どのように書いたら綺麗にできますか? void hen(int *a, char *b,char **c){ *a=7; b[0]='d'; b[1]='e'; b[2]='f'; //こういう書き方なら渡せるけれどb[10]="def"; 見たいな書き方で一行で値を渡す方法はないものかな? *c="jkl"; } void main (void){ int a=5; char b[10]="abc"; char *c="ghi"; hen(&a,b,&c); printf("%d %s %s\n",a,b,c); }

  • 配列のポインタに渡す引数

    2次元配列に値をつめて、char*[]に渡すための 引数XXXは、どう設定すれば、よいのでしょうか? a(work);で、問題ないのでしょうか? いまいちchar*とchar*[]の違いがよくわかりません。 void main { char work[3][5]; sprintf(work[0], %s, "abc"); sprintf(work[1], %s, "def"); sprintf(work[2], %s, "ghi"); a( XXX );←ここの引数 } int a( char* [] ){ }

  • 配列の長さについて

    現在課題で書いているプログラムに以下のような関数があるのですが、 unsigned char key[32]; int w[60]; int data[NB]; int nk; int nr; int data2[32]; int Cipher(int *); int invCipher(int *); void encryptEBC(int *); void decryptEBC(int *); main(){ unsigned char keys[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; unsigned char iv[]={0xcb,0x70,0x05,0x9e,0x27,0x2f,0x4e,0xd2, 0xd0,0xbe,0x0b,0x06,0xbf,0x16,0xec,0x5a}; unsigned char init2[]={'1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0', '1','2','3','4','5','6','7','8','9','0',0x0a}; //unsigned char init2[]={'h','e','l','l','o'}; int isize = sizeof(init2)/sizeof(init2[0]); int dsize2 = sizeof(data2)/sizeof(data2[0]); printf("%d,%d\n",isize,dsize2); FILE *fp; char *fname = "test.txt"; unsigned char init[16]; int i = 0; int c; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } while( (c = fgetc( fp )) != EOF ){ init[i] = c; i = i+1; } fclose( fp ); memcpy(key,keys,16); nk = 4; nr = nk + 6; KeyExpansion(key); memcpy(data,init,16); memcpy(data2,init2,isize); printf("%d\n",dsize2); datadump("PLAINTEXT: ",data,16); datadump("KEY: ",key,16); Cipher(data); datadump("Cipher: ",data,16); invCipher(data); datadump("invCipher: ",data,16); printf("\n"); printf("%d\n",dsize2); datadump("PLAINTEXT: ",data2,dsize2); encryptEBC(data2); printf("%d\n",dsize2); datadump("EBCCipher: ",data2,dsize2); decryptEBC(data2); datadump("invCipher: ",data2,dsize2); printf("\n"); return 0; } void encryptEBC(int data[]){ int dsize = sizeof(data)/sizeof(data[0]); int tmp[16]; int i,j,k; printf("%d\n",dsize); KeyExpansion(key); for (i = 0; i < dsize; i += 16) { for (j = 0; j < 16; j++){ tmp[j] = data[i + j]; } Cipher(tmp); for(k=0;k<16;k++){ data[i+k] = tmp[k]; } } } 関数encryptEBC内のdsizeの値がこの場合だとmain内の配列data2の長さ32になってほしいのですが、1になってしまいます。 非常に見ずらいプログラムで申し訳ないのですが、どなたか1になってしまう理由、またどうすれば正しくdata2の長さを求められるか教えていただけないでしょうか?

  • D言語の連想配列をコピーしたい

    D言語で連想配列をコピーしたいのですが、 int[char[]] x; int[char[]] y; for(char[] a,int b;x) { y[a]=b; } などと要素を一つ一つコピーするしかないのでしょうか。 もっと効率のよいコピーはないのでしょうか。

  • C++ operatorの使用について

    C++初心者で、現在オペレーターの使用方法について勉強しています。 下記プログラムの「 x = x + z;」箇所の処理について、理解できず行き詰っています。 初期化した際のx, y, zそれぞれの値が x = Help y = !e z = M となったところまでは、理解できています。 その後、x = x + zの処理に入る際、 1.abc operator+(abc) 2.void operator=(abc) の順でオペレーターの処理を行うと思います。 その際、1.はzを使用して処理をするところまでは分かるのですが、 return value: HelpM\n(\:バックスラッシュ)がx, y, zのどこに入るのか、 その後どのオブジェクトを持って2.の処理に入るのかどうか 理解できておりません。 初心者のため、文章がわかりづらい点等あるかと思いますが、 アドバイス頂けたら幸いです。 宜しくお願いいたします。 ========================================================================== #include <cstdio> #include <cstring> class abc { char def[21]; public: abc(void) { strcpy(def, "Help"); } abc(const char s[ ]) { strcpy(def, s); } abc(char c) { def[0] = c; def[1] = '\0'; } void operator=(abc); // redefines = between abc's!!! abc operator+(abc); void out( ) { printf("%s\n", def); } }; void abc::operator=(abc x) { int i, n = strlen(x.def); for(i = 0; i < n; i++) def[i] = x.def[n - (i + 1)]; def[n] = '\0'; } abc abc::operator+(abc a) { int i = 0; abc c; strcpy(c.def, def); while(c.def[i] != '\0') i++; for(int j = 0; a.def[j] != '\0'; j++) { c.def[i] = a.def[j]; i++; } c.def[i] = '\0'; return c; } int main( ) { abc x, y("!e"), z('M'); x = x + z; x.out( ); y = y + x; y.out( ); return 0; }

  • c言語 文字列と配列

    #include<stdio.h> int charlen(int n); void cap2sml(int b); int main() { char a[100],b[100]; int n,i; /*Input CARACTERS*/ printf("CAPITAL?\n"); fgets(a,100,stdin); charlen(n); printf("total cahrs=%d\n",n); //printf in main cap2sml(i); printf("small=%s\n",b); return(0); int charlen(int n) n=0; while(1){ if(a[n]=='\0') break; n++; } void cap2sml(int b) int i; for(i=0;a[i]!='\0';i++){ b[i]=a[i]+0x20; } b[i]='\0' } のプログラムでエラーがでるのですが、どこを直せばよいでしょうか? ユーザー関数を使い文字列(大文字)を入力したときの文字列の長さと大文字を小文字に変化するプログラムです

  • C言語プログラム 配列

    C言語プログラム初心者です。以下のプログラムに対して、実行結果がなぜそうなるかがわからないので、詳しく教えてください。 #include<stdio.h> int func(int a[ ],int b[ ],int n); main(){ int i,k; static int a[12] ={1,2,3,4,5,(省略)・・・,12};  static int b[12] ={21,22,23,24,(省略)・・・,32}; k = func(a,b,6); k = func(b+3,a+3,6); printf("a = "); for(i=0;i<12;i++)printf("%d",a[i]); printf("\n = b"); for(i=0;i<12;i++)printf("%d",b[i]); printf("\n k = %d\n",k); } int func(int a[ ],int b[ ],int n){ int i,x=0; for(i=0;i<n;i++);{ a[i] = b[i]; x = x+a[i]; } return(x); } 結果: a = 21 22 23 .... 26 7 8 9 10 11 12 b = 21 22 23 .... 26 7 8 9 30 31 32 k = 99

専門家に質問してみよう