- ベストアンサー
構造体のメンバをfor文で回したい
次のようなソースで typedef struct test{ int a; int b; int c; }TEST; TEST xx; xx.a=xx.a+3; xx.b=xx.b+3; xx.c=xx.c+3; printf("%d %d %d\n",xx.a,xx.b,xx.c); のようなことをしたいんですが、 xx.a=xx.a+3; xx.b=xx.b+3; xx.c=xx.c+3; の処理の部分をfor文で回せるようにしたいです。 構造体の宣言のところで配列をつかって struct test{ int abc[3]; } とすれば簡単にいくのは分かるんですが、a,b,cそれぞれに分かりやすい名前をつけたいので、配列で確保したくないです。 何かいい方法はないでしょうか? 実際計算に使うんですが、メンバはすべてdouble型で30個程度になると思います。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
軽くなったので続きをば 共用体は、なるべくメンバのアドレスを共有するように動作します。だから、共用体の宣言を変えない限り確保されるパターンが変わることはありません。 だから、安心して使っても大丈夫です。 特に今回のように、配列と名前アクセスを行いたいのであれば、moca12980さんが先の補足にあげられたようにやればまったく問題ありません。 --テストプログラムここから typedef union test{ struct{double a,b,c,d[17];}; double temp[20]; }uABC; uABC abc; int main() { int i; for(i=0; i<20; i++) abc.temp[i]=i; printf("a=%.2f,\tb=%.2f,\tc=%.2f\n", abc.a, abc.b, abc.c); for(i=0; i<17; i++) printf("d[%02d]=%.2f,\t", i, abc.d[i]); printf("\n"); return 0; } --テストプログラムここまで 実は、変数の個数が少なければ、defineでもかわせます。個数が増えると見通しがいい分共用体の方が楽なんですけど。 --テストプログラムここから double temp[20]; #define U_a(A) A[0] #define U_b(A) A[1] #define U_c(A) A[2] #define U_d(A,X) A[(X) + 3] int main() { int i; for(i=0; i<20; i++) temp[i]=i; printf("a=%.2f,\tb=%.2f,\tc=%.2f\n", U_a(temp), U_b(temp), U_c(temp)); for(i=0; i<17; i++) printf("d[%02d]=%.2f,\t", i, U_d(temp, i)); printf("\n"); return 0; } --テストプログラムここまで
その他の回答 (6)
- jacta
- ベストアンサー率26% (845/3158)
#1です。 > 列挙体を使うというのは、どういう方法になるんでしょうか?#2の方のやり方ということでしょうか? はい。そうなります。 配列が含まれているとのことですが、列挙定数の値は不連続でも構わないので、 typedef struct test { int a; int b; int c; int z[10]; int d; } TEST; を typedef struct test { int x[14]; } TEST; enum { a, b, c, z, d = z + 10 }; のようにすれば、 TEST xx; xx[z + 0] += 1; xx[z + 3] += 2; xx[d] += 3; のように扱うこともできるかと思います。
お礼
回答ありがとうございます。 まだまだ曖昧なところはありますが、列挙体の使い方がわかりました。 これから勉強してちゃんと理解したいと思います。
- rentahero
- ベストアンサー率53% (182/342)
多分あなたの要求しているものは共用体(union)だね。 え~教えて!gooが今のような状態だと私の書き方*1ではストレスがたまって仕方がないので、軽くなるまで私は保留。 どなたも回答がなければサイトが軽くなってから詳しく書きます。 多分1週間以内には軽くなるとは思ってます
お礼
共用体を使うのも考えてはいました。 typedef union test{ struct{ int a,b,c,d[17]; } int temp[20]; }uTEST; uTEST abc[5];//5が#3の方のお礼のところに書いた変数数 このようにすると abc[0].aがabc[0].temp[0] abc[0].bがabc[0].temp[1] ・・・ abc[1].aがabc[1].temp[1] abc[1].bがabc[1].temp[1] ・・・ と参照できるようになっていいようにも思えるんですが、共用体についてや、アドレスについて知らないことだらけで何かの拍子に上に書いた対応がズレたり、何かバグが潜むんじゃないかと思い使えないでいました。 共用体の使い方等、軽くなってから回答いただけるならお待ちしていますのでよろしくお願いします。
- hello_world
- ベストアンサー率46% (15/32)
No.3の回答をしたものですが、大丈夫かと思いますが自分の回答でどうしてもいくつか細かい所が気になってしまったので修正します(^^; 1.for文で+99.9としていますが、これはmoca12980さんの希望の値に変えてください。 2.printf文で%fと書いていますが、%lfが正しいですね
- hello_world
- ベストアンサー率46% (15/32)
あくまでメンバが全てdoubleである事が前提であれば、 typedef struct _TEST { double a; double b; double c; } TEST; int main() { TEST test; double* p; int i; test.a = 0.0; test.b = 0.0; test.c = 0.0; p = &test.a; for ( i = 0; i < 3; i++ ) { *p = *p + 99.9; p++; } printf( "%f %f %f", test.a, test.b, test.c ); } と構造体の最初のメンバのアドレスから辿ることができます。ただこの方法は限定された条件でのみ使用可能ですので注意してください。
お礼
回答ありがとうございます。 この方法でもうまくいきました。 ちょっと質問には直接関係ないことになるんですが、 このプログラムで、各変数(a1,a2,a3,a4・・)にそれぞれ5+変数数の設定値(b,c,d,e,f,g_a1,g_a2,g_a3・・)を持たせるのに、配列を使って a[変数数][設定値数]という配列を確保していました。 でも実際には、for文でa[0][0],a[0][1],....,a[2][0],a[2][1],...,a[4][0],.....の順番で同じ計算をさせたい部分があるので、 int xxx[変数数*設定値数];と1次元配列で確保して int (* abc)[設定値数]; abc=(int (*)[設定値数])xxx; として xxx[0]~xxx[設定値数]がabc[0][0]~abc[0][設定値数]に xxx[設定値数]~xxx[2*設定値数]がabc[1][0]~abc[1][設定値数] ・・・ と2次元配列でも参照できるようにしていまた。 この配列の2次元目?(設定値の部分)を今回変数ごとに構造体で持たせて、 struct test{ //設定値 int b,c,d,e[17]; }; struct test abc[変数数]; として確保して これを、abc[0].b,abc[0].c,abc[0].d,abc[0].e[0],・・・とfor文で回せるようにabc[0].setteiti[0],abc[0].setteiti[1]・・・と対応するようにしたいと思って質問しました。 もちろん回答いただいたポインタの方法でも思っているとおりの動作をするのですが、もっといい方法があったらアドバイスお願いします。
- valvelde
- ベストアンサー率35% (46/129)
配列で確保して添え字に定数を使えばいいのではないでしょうか。 enum{ a, b, c, }; struct test{ int abc[3]; }; test xx; xx.abc[a] = xx.abc[a]+3; xx.abc[b] = xx.abc[b]+3; xx.abc[c] = xx.abc[c]+3; for(i = 0;i < 3;++i){ xx.abc[i] = xx.abc[i]+3; }
お礼
回答ありがとうございます。 enumというのを今日はじめて知りました。 >enum{ > a, > b, > c, >}; この宣言というのは、aが0で、bが1で、cが2ということになるということでいいんでしょうか? 質問のときには書かなかったのですが、構造体のメンバで宣言したいものが厳密には struct test{ int a; int b; int c; int z[17]; } と中に配列も入っています。 回答の方法で試してみたのですが、 enum{a,b,c,z[17]}; としてしまうとコンパイルエラーになってしまいます。 これを改善する方法はないでしょうか? 実際のところ、 struct test{int a,b,c,z[17];}; というのを もう一つの配列abc[20]でも参照できるように abc[0]がa abc[1]がb abc[2]がc abc[3]がz[0] abc[4]がz[1] abc[5]がz[2] ・ ・ という風にしたいと思っています。 もしくは、enumを使って abc[0]がabc[a] abc[1]がabc[b] abc[2]がabc[c] abc[3]がabc[z[0]] abc[4]がabc]z[1]] abc[5]がabc[z[2]] ・ ・ というのも可能なら、こうやりたいです。。
- jacta
- ベストアンサー率26% (845/3158)
各メンバへのポインタを配列にすればよいのでは? int *pxx[] = { &xx.a, &xx.b, &xx.c }; for (i = 0; i < 3; i++) pxx[i] += 3; といった具合です。 C++であれば、(本当の意味で)メンバへのポインタを使うことも出来ます。 int TEST::*pxx[] = { &TEST::a, &TEST::b, &TEST::c }; for (i = 0; i < 3; i++) xx.*pxx[i] += 3; けれども一番簡単なのは、素直に配列にして、インデックスを列挙体にして名前を付ける方がずっとよいかと思います。
お礼
回答ありがとうございます。 最初に書いてある方法でもうまくいきました。 C++でのやり方は、C++がわからないのでどういうことなのか理解できませんでした。 列挙体を使うというのは、どういう方法になるんでしょうか?#2の方のやり方ということでしょうか? よろしければやり方を教えてください。 構造体自体も最近使い始めたばかりで、いい方法がないかいろいろ検討中です。。
お礼
回答ありがとうございます。 あの方法で大丈夫だったんですね。 今回で、構造体や列挙体の使い道も分かってきたので、必要に応じて使い分けて行きたいと思います。 今回質問したことについては、やはり共用体が一番しっくりくる気がするので、まずは共用体で試してみます。