• ベストアンサー

構造体の変数の値を、動的に取得する方法を教えてください

C言語で、構造体の変数の値を取得したいのですが、その際、 他の変数に格納してある文字列を元に動的に行いたいのですが、可能でしょうか? イメージとしては、 struct Entry{ char name[20]; char address[80]; char email[40]; }; struct Entry data; strcpy(data.name, "Taro"); strcpy(data.address, "Tokyo"); strcpy(data.email, "taro@taro"); char var_name[20]; strcpy(var_name, "email"); printf("%s", data.var_name); ↑この行の構造体の変数へのアクセス方法が間違っているのはわかっていますが、このような時に「taro@taro」と出力させたいのです。 var_nameの値を「name, address, email」に換える事により「Taro, Tokyo, taro@taro」と出力を切り換えたいと思っています。 普段は他の言語をよく使用しており、そちらではこの手法を時々使っていたのですが、C言語でも出来ないものかと思っております。 よろしくお願いします。

noname#163856
noname#163856

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

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.6

既に多数出ていますが、 そもそもC言語では関数名や手続きなどはプロジェクト内、 またはファイル内において一意で認識される名前である必要が あるため「同名で」「別の手続き」というのは、 そもそものC言語での考え方では厳しいといえると思います。 それっぽくC言語での例だと こんな感じになると思います。 (インデントは全角スペースなのでコンパイルには注意) #include <stdio.h> #include <string.h> #define MAXBUFFERLEN (80) /* varメンバの擬似連想配列に対する列挙指定子 */ enum{  name = 0,  email,  address,    /* ここに指定子を追加することで、 *   * 構造体メンバの配列も大きくなっていく */  age, //例えば年齢を追加。(ただし扱いは文字列)  MAXVARELEMENT, }; /* 構造体にこだわるなら */ struct Entry{  char var[MAXVARELEMENT][MAXBUFFERLEN]; }; int main( void ) {  struct Entry data;  strcpy(data.var[name], "Taro");  strcpy(data.var[address], "Tokyo");  strcpy(data.var[email], "taro@taro");  strcpy(data.var[age], "20");  printf( "%s\n", data.var[name] );  printf( "%s\n", data.var[address] );  printf( "%s\n", data.var[email] );  printf( "%s\n", data.var[age] );  return 0; }

noname#163856
質問者

お礼

回答して頂いた皆様、ありがとうございます。 今回の質問は、C言語をよりよく理解するのに役に立ちました。 ありがとうございました。

その他の回答 (5)

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

> この文章は、他の言語であれば動的に構造体の変数(もしくはクラスのプロパティ)にアクセスするのはOKだが、C言語の場合はそのような手法は良くないと言う意味でしょうか? 大体そんなところです。 > 私がこれまでに読んだ書籍では「動的にアクセスする方が効率が良くなる」と紹介しているものが多く、なぜ「効率が悪くなる」のか分からないのですが。 言語にもよりますが、動的な扱いに特化して設計・実装されている言語の場合、無理に静的に行おうとするとかえって効率が悪くなる可能性はあります。 しかし、コンピュータの一般論からすれば、静的に処理した方が実行時の効率はよくなります。 > 動的という意味では、オブジェクト指向のPolymorphismも抽象度の高い変換形式を実現できる方法として、有益であると思っています。 ポリモフィズムを実現するのは、必ずしも動的である必要はありません。 C言語ではちょっと厳しいですが、C++であれば、静的なポリモフィズムを実現するためにテンプレートメタプログラミングを使うのは普通のことです。

  • rabbit_cat
  • ベストアンサー率40% (829/2062)
回答No.4

そもそも、文字列として格納されている変数名でアクセスすることは、 たとえそれが可能な言語でも、なるべくやめたほうがいいですよ。 ものすごく読みにくくて、何やってるのかちょっと時間がたつと自分でもわからなくなる可能性が大です。昔敵視されてたgotoなんかより、ずっとタチ悪いと思います。 いわゆるeval関数というのは、たしかに超強力ですけど、その分、弊害も強力です。 変数名というのは、あくまで、プログラム中に使う仮の名前であって、本来であれば、例えばプログラム中の「a」という名前の変数を全て「b」に置換しても、正常に動くことが期待されています。この大前提を破るようなプログラムは極力避けるべきです。 eval関数と、オブジェクト指向のポリモーフィズムは、全く別の話です。

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

> 「効率が悪くなる」というのは具体的にはどのような意味でしょうか? プログラムサイズが大きく、実行速度が低下します。 また、C言語の場合には自分で実装しなければいけないわけですから、それだけプログラムが複雑になり、開発効率も保守効率も低下します。 結果として、それだけ費用が多く発生し、品質・信頼性が低下します(品質・信頼性の低下を防ぐには、さらに費用がかかります)。 これはC言語だから悪いのではなく、C言語にふさわしくない設計に問題があります。

noname#163856
質問者

お礼

ご回答ありがとうございます。 > これはC言語だから悪いのではなく、C言語にふさわしくない設計に問題があります。 この文章は、他の言語であれば動的に構造体の変数(もしくはクラスのプロパティ)にアクセスするのはOKだが、C言語の場合はそのような手法は良くないと言う意味でしょうか? 私がこれまでに読んだ書籍では「動的にアクセスする方が効率が良くなる」と紹介しているものが多く、なぜ「効率が悪くなる」のか分からないのですが。 動的という意味では、オブジェクト指向のPolymorphismも抽象度の高い変換形式を実現できる方法として、有益であると思っています。 とりあえず、最後の文章の意味がうまく解釈できなかったので、よろしければ補足していただけますか?

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

> 普段は他の言語をよく使用しており、そちらではこの手法を時々使っていたのですが、C言語でも出来ないものかと思っております。 この発想が間違っていると思います。 動的に構造体のメンバをアクセスできるようにすると、それだけ効率が悪くなります。 ですから、効率を重視する部分は通常の構造体で、メンバ名等を頼りにアクセスしたいなら連想配列を別途実装した方がよいでしょう。 ちなみに、メンバの指定方法が文字列ではなく、列挙定数でよいのであれば、もっと簡単で、かつ効率を損なうことなく実現する方法があるはずです。 (例えば、構造体ではなく、ポインタ配列を使うなど。)

noname#163856
質問者

お礼

> 動的に構造体のメンバをアクセスできるようにすると、それだけ効率が悪くなります。 「効率が悪くなる」というのは具体的にはどのような意味でしょうか? 今回の質問の内容とは離れてしまいますが、今後の参考にしたいと思いますので、教えていただけると助かります。

回答No.1

Cではstructに関数を入れられないので、こんな感じでしょうか? ちなみにC++ではclassを使います。 struct Entry{ char name[20]; char address[80]; char email[40]; }; struct Entry data; char *get_data(char *var_name) { if (strcmp(var_name,"name") return data.name; if (strcmp(var_name,"address") return data.address; if (strcmp(var_name,"email") return data.email; return ""; } void main() { strcpy(data.name,"Taro"); strcpy(data.address,"Tokyo"); strcpy(data.email,"taro@taro"); char var_name[20]; strcpy(var_name,"email"); printf("%s",get_data(var_name)); }

noname#163856
質問者

お礼

早速ご回答ありがとうございます。 自分のやりたい事に、だいぶ近づいてきました。 if文による条件分岐を使わずにできれば最高なのですが(構造体の変数の数とともに、分岐も増えてしまうので)、可能でしょうか?

関連するQ&A

  • [C] 構造体メンバーのカンマ区切り出力

    構造体メンバーのカンマ区切り出力をしたいと思っています。 たとえば struct XXX { char name[20]; char address[40]; char tel[12]; ... 100メンバーくらいある } のような構造体があったとします。 printf("%s,%s,%s\n", s_ptr->name, s_ptr->address, s_ptr->tel); などのようにメンバー名(変数名)を参照せずに、構造体のメンバーへのポインタを順次取得しループして出力するなどして、実現することは可能でしょうか?

  • 構造体について

    凄く初歩的な質問で申し訳ありませんが… 入門書の構造体のところで 以下のようなプログラムの例がありました。 #include <stdio.h> struct seiseki { /* 構造体の宣言 */ int no; char name[20]; double average; }; int main(void) { int i; struct seiseki seito1, seito2[20]; /* 構造体変数と構造体配列の宣言 */ >char name[20] というのは、NAMEの領域を20文字 確保すると言うことですよね? >struct seiseki seito1, seito2[20] ここの箇所が分からないのですが seito2[20]の20というのは どうして20なのですか? NAMEだけではないので もっと大きな数字になるような気がするのですが… またseito1の方は どうして数字が何もないんですか? 考え違いをしているところを ご指摘して頂ければ幸いです。

  • 構造体宣言したポインタ変数に値を代入するには?

    strcpy(p -> key ,name);と打ってp -> key に入力した名前を格納したいのですがうまくいきません。 ほかにもp -> key = nameなども試してみましたがコンパイルエラーが出現してダメでした。 うまく格納できるやり方があれば教えてください。よろしくお願いします。 #include<stdio.h> #include<string.h> #define WORD_LENGTH 50 /* 文字列の最大長 */ typedef struct cell{ char key[WORD_LENGTH]; struct cell *next; /* 次のセルへのポインタ */ } CELL; void main(void) { char name[WORD_LENGTH]; CELL *p; printf("名前入力\n"); scanf("%s\n", name); strcpy(p -> key ,name); printf("%s\n", p -> key); }

  • 構造体

    構造体を受け取って、メンバの値を変数に代入する部分での質問です。 lParamには構造体のアドレスが入っています。 strcpy(buf, ((struct mpoint*)lParam)->r); これによって構造体のrメンバの文字列値をbufにコピーしたいのですが、文法が違うようなので正しく直したものを教えてください。

  • 構造体型のポインタ変数を含む構造体

    struct seiseki_tag { Int32 math ; Int32 english ; Int32 science; } ; typedef struct seiseki_tag SEISEKI ; struct personal_tag { Char name ; Int32 num ; SEISEKI *sptr } : typedef struct personal_tag PERSONAL ; struct info_tag { PERSONAL person_info ; } ; typedef struct info_tag INFO ; たとえば、上記のように3つの構造体があり、PERSONAL構造体のメンバーに SEISEKI構造体の型を持つポインタ変数が含まれているような場合で、下記のように INFO型のポインタ変数からSEISEKI構造体のメンバーを参照する方法を教えてください。 PERSONAL構造体メンバーのnameやnumは INFO *info ; info->person_info.name ; info->person_info.num ; のように参照すると思いますが、sptrが示すSEISEKI構造体のメンバーへの アクセスができません。下記のように参照を試みたのですがコンパイルは 通るのですが、実際に参照できていませんでした。 INFO *info ; SEISEKI *seiseki ; seiseki = info->person_info.sptr ; seiseki->math ; 判りにくい説明で申し訳ありませんが、どなたか教えていただければと思います。 よろしくお願いいたします。

  • c言語 構造体

    初歩の質問ですがお手柔らかに… ポインタもまだ理解しきれていません。 winapiの勉強しながらプログラムを作っています。 windows7,VisualStudio2010使用です。 struct A{ char *name; double i; } *data;//これはグローバル変数にしてあります。 (中略) (以下ダイアログプロシージャ内) TCHAR Buf[128]; GetDlgItemText(hDlg, IDC_XXXXX,Buf,(int)sizeof(Buf) -1); ここから、構造体AのメンバnameにBufの内容をコピーしたいのですが、この後を data->name = Buf ; とすると、nameのポインタがBufと同じものになり、Bufはローカル変数なのでこの関数が終わるとこのアドレスの値はめちゃくちゃになるのでnameを別の関数内では参照できなくなりました。 &(data->name) = 00C09814   &(Buf) = 002EF590 を &(data->name) = 002EF590 &(Buf) = 002EF590 として参照できるようにするのではなく、 アドレス 00C09814に アドレス002EF590の文字をコピーしてdata->nameとBufを別のアドレスで内容が同じものにしたいのです。 *(data->name + i) =*(Buf +i)をループで回してもうまくいかず、 sprintf() や strcpy() も試したのですが、コンパイルはできてもどこか不具合があるらしく、アプリケーションを動かすとこの部分で動作を停止してしまいます。 この場所で data->name = "text" とすると、問題なく文字列を代入できました。 わけのわからないことを言っている部分もありますが、どなたかご教授お願いします。

  • 構造体の配列について(2)

    前回「構造体の配列について」という質問タイトルで、質問させていただいたのですが、理解が完全ではないため同じようなプログラム内容ではありますが、疑問を書かせていただきます。よろしくお願いします。 ----------------------------------------------------------------------- #include<stdio.h> #include<string.h> struct person{ char name[1];    //// (1) //// int height; int weight; }; int main() { struct person dt[10]; strcpy(dt[0].name,"日本一郎"); strcpy(dt[2].name,"関東次郎"); strcpy(dt[9].name,"関西三郎"); dt[1].weight=99; dt[1].height=168; printf("%s %s %s %d %d \n",dt[0].name,dt[2].name,dt[9].name,dt[1].weight,dt[1].height); return 0; } ----------------------------------------------------------------------- 以上のプログラムの(1)の部分で、文字を1文字しか格納出来ないのに、 strcpy(dt[0].name,"日本一郎"); strcpy(dt[2].name,"関東次郎"); strcpy(dt[9].name,"関西三郎"); としても何故正しく実行できるのかわかりません。 前回いろいろとご回答いただいたのに、しっかりと理解できない者ですが、教えていただければ嬉しいです。

  • 構造体から他の構造体への代入

    現在C言語で簡単なプログラミングを書いているのですが、 構造体(1)(下記参照)から、構造体(2)(下記参照)への代入の方法がわからず悩んでいます。もしよければ手を貸してください!! 標準関数などがないということはわかったので、 地道に代入を行いたいです。 イメージ・・・(data[n].b = moji[n].d;) (1)struct list_kouzou{ int a; char b[30]; char c[8]; }data[100]; (2)struct list_tai{ char d[30]; }moji[15];

  • C言語での構造体

    C言語の構造体で配列を扱うとき、 struct ○○{  char ○○[○] とすれば出来ますが、同じようにして構造体で二次元配列を扱うことは出来ますか? 一度組んでみたのですが、 #include<stdio.h> struct aaa{ int no; char name[128]; char y_name[128]; char n_name[128]; char s_name[128][128]; }; int main(void){ int i; struct aaa iryo[99]; printf("入力前\n"); /* 構造体配列に scanf()でデータを入力 */ for(i = 0; i < 3; i++) { // printf("input...\n"); scanf("%d", &iryo[i].no); scanf("%s", iryo[i].name); scanf("%s", iryo[i].y_name); scanf("%s", iryo[i].n_name); scanf("%s", iryo[i].s_name); } printf("入力後\n"); printf("出力前\n"); /* 入力データの確認 */ for(i = 0; i < 3; i++) { printf("番号:%02d 内容:%s Y分岐:%s N分岐:%s 他分岐:%s\n", iryo[i].no, iryo[i].name, iryo[i].y_name, iryo[i].n_name, iryo[i].s_name); } printf("出力後\n"); printf("%d",sizeof(struct aaa)); return 0; } としたら、エラーは出ませんが、実行すると何も表示されませんでした。

  • 別ファイルの構造体の値を読み込む、変えるには?

    別のファイルに下の構造体があったとして、どのように書けば構造体のデーターを読み込んだり、値を変えたり出来ますか? static struct{ char *name[2]; double d_data[2]; int i_data[4]; double s_data[2]; int state[2][3]; int regi[5]; }kya_data[2]={ {   { "奈美" , "爆弾" },   {    43.0000 ,    54.0000 ,   } , {    50 , 50 , 50 , 50   } , {    0.100,    0.100,   } , {   { 0 , 0 , 0 } ,   { 0 , 0 , 0 }   } , {    100 , 0 , 0 , 0 , 0   } },{   { "由美" , "湖" },   {    23.0000 ,    76.0000 ,   } , {    50 , 50 , 50 , 50   } , {    0.100,    0.100,   } , {   { 0 , 0 , 0 } ,   { 0 , 0 , 0 }   } , {    0 , 0 , 0 , 0 , 100   } } };

専門家に質問してみよう