typedef struct _ex_table1
{
  int  x[10];
  int  y[10];
}ETable1;

ETable1 et1;
int ans1;

for( int a = 0; a < 10; a++ ){
  et1.x[a] = a+10;
  et1.y[a] = a*2;
}
for( int b = 0; b < 10; b++ ){
  if( et1.x[b] == 15 ){
    ans1 = et1.y[b];
    break;
  }
  else{
    ans1 = 0;
  }
}
printf( "%d", ans1 );

/////////////////////////////////
typedef struct _ex_table2
{
  int xx;
  int yy;
}ETable2;

ETable2et2[10];
int ans2;

for( int aa = 0; aa < 10; aa++ ){
  et2[aa].xx = aa+10;
  et2[aa].yy = aa*2;
}
for( int bb = 0; bb < 10; bb++){
  if( et2[bb].xx == 15 ){
    ans2 = et2[bb].yy;
    break;
  }
  else
  {
    ans2 = 0;
  }
}
printf("%d", ans2 );

と言う感じに、微妙にソースを書いてみたのですが、
上のメンバ(x,xx)の値が正しいものがあったら、
対応する下のメンバ(y,yy)を出力したいと思っていますが、
構造体を配列にした場合と、構造体メンバを配列にした場合は
どのように違うのでしょうか?
私には、同じように思えてしまいます。
どなたか、利点・欠点など教えていただけませんか?
よろしくお願い致します。

A 回答 (2件)

どちらでも同じですが、


typedef struct _ex_table1
{
  int  x[10];
  int  y[10];
}ETable1;

ETable1 et1;
だと、x[0]とy[0]の関連がソースを見て判断できません。
それぞれ個別の配列となってしまい配列番号nに入るxとyに関連があるようには見えないのです。
しかし、
typedef struct _ex_table2
{
  int xx;
  int yy;
}ETable2;

ETable2 et2[10];
とすれば、xxとyyに関連が生まれ、配列番号n番目のデータとして識別しやすくなります。

またSUB関数コール時に配列番号nに入っている情報だけを渡したい場合
ETable1では
sub(et1.x[n], et1.y[n]);
int sub(x, y)
{
 :
}
と渡さなければならないですが、
ETable2では
sub(et2[n]);
int sub(ETable2 et)
{
 :
}
で渡せます。

プログラムを作る時に、ひとつの塊としてみたいものをメンバとして並べ、それを必要数だけ用意する。ように作成します。

上記例であれば、xとyは対の情報であると判断できますので、
前者の書き方はよくない書き方で、後者のかきかたはよい書き方となります。
    • good
    • 0
この回答へのお礼

sub関数を造ったときのことを考えると分かりやすかったです。
値を渡すのがひとつでよくなり、
記述のし忘れが減ってデバックも簡単になりますね。
ありがとうございました。

お礼日時:2001/11/07 11:13

ご質問の二つのプログラムについては、得られる効果は同じだと思います。


どちらが適切かというのは、そのデータが何を示しているかによります。
例えば、5匹のタコの足を扱うプログラムがあったとします。
(変な例えですが、ゲームプログラム等でそんな必要があったと考えて下さい。)
下のどれが適切だと思いますか。(Legは適当に定義された型とします。)
(1)
typedef struct {
 Leg leg[8*5];
} Octpus;
Octpus tako;
(2)
typedef struct {
 Leg leg[8];
} Octpus;
Octpus tako[5];
(3)
typedef struct {
 Leg leg;
} Octpus;
Octpus tako[8*5];
(1)や(3)は不自然だと思いませんか?
要はプログラマが見て理解しやすいコードを書けばよいわけです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
サンプルなどからコピペばっかりしていたために、
基礎部分が分かりませんでした。
結果は同じなのですね。
見易さの問題ですか、なるほど。

お礼日時:2001/11/07 11:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qダイアログからビュークラスのメンバ変数へ代入するには?

プログラミング初心者です.
Visual C++.netを使っています.

Viewクラスから,Domodal()にてあるダイアログを呼び出しました.
ダイアログ上のあるボタンを押したら,Viewクラスのメンバ変数へ1を代入するという処理をしたいと考えています.
 ラジオボタンやエディタコントロールであれば,DDXを利用すればよいと思うのですが,単なるボタンの場合はどうすれば,呼び出し元のViewクラスの値を操作(この場合,代入)出来るのでしょうか?

Aベストアンサー

ダイアログのコンストラクタに変数を増やすなどして、Viewクラスのポインタをダイアログに登録します。

ダイアログのボタンクリックハンドラで既に登録されているViewクラスのポインタを使用して希望の変数を変更するとできます。

これは色々な方法があります。

逆にダイアログクラスにボタンのクリック結果を変数として残しておき、ダイアログが終了してからダイアログのクリック結果をViewクラスが確認する方法もあります。

他には、ダイアログのボタンクリックハンドラから、Viewクラスへメッセージを送信するという方法もありますね。

色々有るので色々勉強してくださいね。

Qchar AA[]{"全角文字"};から"全"という一字を取り出したい

 今晩は、Cの初心者です、宜しくお願いします。
 全角文字の入ったchar AA[]{"全角文字"};から"全"という文字一字を取り出す時にAA[0]とかくとエラーになります。
 どのようにしたら取り出せるのでしょう。
 ポインタを使う方法と使わない方法を教えて下さい。
 宜しくお願いします。

Aベストアンサー

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出す必要があります。

>char AA[]={'全','角'};

char AA[]="全角";
とし
>printf("%s%s\n" , AA[0],AA[1] ) ;

printf("%c%c\n" , AA[0],AA[1] ) ;
とすれば、「全」だけを表示する事が可能と思われます。

日本語を文字列で表示する為の文字コードについては
Shift-JISだけでなく、UnicodeやUTF・EUC・JISなどがあります。

もう少し詳しく記載してあるホームページはないか探してみましたが、ちょっと無理でした。

参考URL:http://marupeke296.com/CPP_charUnicodeWideChar.html

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出...続きを読む

Q構造体メンバ 構造体ポインタ 値代入

typedef struct _test_t{
int aaa;
int bbb;
} test_t;

typedef struct _globalData{
int xxx;
test_t* pTestData[256];
} globalData_t;

globalData_t globalData;


int main(){

test_t testData1 = {1,1};
test_t testData2 = {2,2};

*globalData.pTestData[1] = testData1; /* (1) */

globalData.pTestData[2] = &testData1; /* (2) */

}

上記のようなグローバルデータの構造体globalData
のメンバの構造体配列にtest_t型の構造体を格納し保持するには、
(1)、(2)のどちらが正しいでしょうか?

Aベストアンサー

> 代入、*globalData.pTestData[xxx] = testData1;
> 削除 *globalData.pTestData[xxx] = NULL;

削除時点でヌルポインタになってしまうので、ご所望の書き方では削除後に代入はできません。
ちなみに削除はアスタリスクを取って
globalData.pTestData[xxx] = NULL;
が正しいと思います。

なぜNULLを代入したいのでしょうか?
「もしNULLなら構造体の値を代入」などの処理をしたいのであれば、まずはNULLのポインタに
領域を確保するか、すでに確保されているアドレスを代入することになります。
ご所望の代入方法をするためには、まず「領域の確保」が必要です。

これを踏まえて、代入と削除を書くと以下のようになるかと思います。

#include <stdio.h>
#include <string.h>

typedef struct _test_t {
int aaa;
int bbb;
} test_t;

typedef struct _globalData {
int xxx;
test_t *pTestData[256];
} globalData_t;

globalData_t globalData;

int main()
{
test_t testData1 = { 1, 1 };
test_t testData2 = { 2, 2 };

test_t testDataBuf[256];
int i;
for(i=0; i<256; i++)
globalData.pTestData[i] = &testDataBuf[i];

// 代入
*globalData.pTestData[1] = testData1;/* (1) */

// delete
globalData.pTestData[1] = NULL;

// 再代入
globalData.pTestData[1] = &testDataBuf[1]; // NULL状態を解消
*globalData.pTestData[1] = testData1;
}


しかし、これは無駄な処理に見えます。
このコードを読んだ人は「なぜDeleteがNULL代入なのだろうか?」と疑問に思うかもしれません。


私ならば・・・

案1
aaaが-1なら未使用というルールにして
#define delete_test_t(x) (x.aaa = -1)
#define is_enable(x) (x.aaa != -1)
とかで管理しといて、あとでソース読むのが楽になるようにケアすると思います。

案2
DeleteでNull代入する代わりにtest_t構造体に使用中フラグを追加


alloc禁止の前提ではこんなところですかね。

> 代入、*globalData.pTestData[xxx] = testData1;
> 削除 *globalData.pTestData[xxx] = NULL;

削除時点でヌルポインタになってしまうので、ご所望の書き方では削除後に代入はできません。
ちなみに削除はアスタリスクを取って
globalData.pTestData[xxx] = NULL;
が正しいと思います。

なぜNULLを代入したいのでしょうか?
「もしNULLなら構造体の値を代入」などの処理をしたいのであれば、まずはNULLのポインタに
領域を確保するか、すでに確保されているアドレスを代入することになります。
ご所望の代入方...続きを読む

Qint nII[10] = { 0 }について

久々にCを使ってプログラムを組んでいるのですが、基本的な構文を思い出せず
いくつか教えていただきたく質問させていただきました。

1)配列すべてを初期化するのに、宣言時に

int nII[10] = { 0 };

で大丈夫だった(全ての要素が0で初期化)と記憶しているのですが、間違いないでしょうか?

2)構造体の初期化は

struct tm tm;
memset(&tm, 0, sizeof(struct tm))

で大丈夫でしょうか?

3)構造体の宣言は

typedef struct{
int a;
}HOGE, *LPHOGE;

HOGE st; // <- struct HOGE stと同じ
LPHOGE pst; // <- struct HOGE* pstと同じ

で問題ないでしょうか?

以上、3つ質問になって申し訳ないのですが、よろしくお願いします。

Aベストアンサー

1)OK
2)たぶんOK
3)HOGEという名前の構造体はない(当該の構造体には名前がない)ので、
// 以下のコメント記述が誤っています。ただし、

HOGE st;
LPHOGE pst;
という定義そのものはOK

Q派生クラスのメンバを基底クラスの参照に代入(C++

文末のコードのように、
基底クラスで、派生クラスのメンバの参照を持つのはまずいでしょうか。
(classではなくstructにしているのは質問上でのpublic:の省略のためだけです)

初期化順序的には、基底クラスの参照先は、
基底クラスのコンストラクタが走る時点で初期化されていないので、
コンストラクタ内で参照に対して何かしようとすると問題になると思っています。

基底クラスのコンストラクタ内で派生クラスメンバの参照に対して何かしなければ、
参照は有効で、派生クラスのコンストラクタ実行後であれば
問題なく動くと思ってよいでしょうか。

struct A {

int& m_ref;

A(int& ref) : m_ref(ref) { }

};

struct B : public A {

int m_obj;

B() : A(m_obj) { }

};

Aベストアンサー

継承は、子が親を知っている状態です。
お話しされているクラスは、親が子を知っている状態で、関係が反転しています。
これは非常に難解な状況で、子の処理結果を親が受け取りたいということなら、
テンプレートメソッドなどで対応するべきです。

Qint kosuu; とstruct tanka_kosuu kosuu[10]; の関係は

同プログラムの内容で現在3個の質問をしておりますが!
 その質問を解決する上で4つ目の質問をさせていただきます。
 悪しからず・・・
 さて
以下のサイトのプログラムで 些細な疑問がございます。
https://oshiete.goo.ne.jp/qa/9062058.html
 で
 struct tanka_kosuu {
int tanka; 
int kosuu; 
int kingaku; /
以上の中にあるkosuuと
 struct tanka_kosuu kosuu[10];のkosuu[10]とは直接関係がありますか?
 馬鹿な質問ばかりで申し訳ございませんがよろしくお願いいたします。

Aベストアンサー

#No.1です。

>kosuu[10];をakb[10];変えたところ 以下の errorでてコンパイルできません!?
> example10.c(15) : error C2065: 'kosuu' : 定義されていない識別子です。


宣言している変数名を変更したら、その変数を利用している場所(エラーメッセージで15行目と書かれています)の変数名も変更する必要があると思いませんか?

下の例で、1行目も変数をaからbに変えたら、2行目,3行目のaも、bに変える必要があのはご理解いただけますよね?
01: int a;
02: a = 10;
03: printf("a=%d\n", a);

Q構造体メンバへの代入

とても初歩的なことなのですが、
typedef struct _X{
int x;
}X[50];
と構造体を定義して
X[0].x = 0;
と0を代入しようとすると、「宣言が正しく終了していない」とエラーが出てしまいます。
これはなぜでしょうか?
ちなみにMicrosoft Visual C++ 2005 Express Editionを使っています。

Aベストアンサー

> typedef struct _X{
> int x;
> }X[50];

これは、目的と違った宣言になっています。
回答の2,3の方の言うとおりです。

typedefを使いたいのであれば、
typedef struct {
int x;
} INTX;
INTX X[50];
代入は、 X[0].x=0; と記述してもOKです。

typedefは、新しい型を宣言する場合に使います。
ここでは、INTXという新しい型を宣言しています。

typedefを使わない方法なら
struct {
int x;
} X[50];

これで、X[0].x=0; と記述できます。

ここでは、構造体に名前をつけていませんが、つけることもできます。
struct IX {
int x;
} X[50];

これは、
struct IX {
int x;
};
struct IX X[50];
とするのと同義です。

Qint i,j; \n i=0,j=5;

int i,j;
i=0;
j=5:
と書いてあるソースは普通ですが、
int i,j;
i=0,j=5:
と書いてあるソースもあります。
後者はC++の正しい書式ですか?

カンマ演算子というのは後者のカンマのことですか?

Aベストアンサー

 正しい書式です。

i=0,j=5;
 における、「,」をカンマ演算子といいます。2項の演算子です。カンマで区切られた演算を「左から順番に」実行し、最後の演算を結果として返します。
 したがって、例の文であれば、i=0を実行し、次にj=5を実行。そして、j=5の結果の5を結果として返します。
 ・・・
 が、本来的には、あまり、例のような使い方はしませんね。よく見られるのは、次のような場合です。

 for (i=0,j=0 ; i < 50 ; ++i,++j) {

 のような形でよく見られます。for文の各式は、一つの式でなければならないので、こんな書き方をするわけです。初期化と更新部が一つにまとまり、ループが読みやすくなるのが利点かな。

Q構造体メンバがポインタであるときの代入

typedef struct WRITE_BUF_TYPE{
 byte adr_h; // ワードアドレス上位
 byte adr_l; // ワードアドレス下位
 byte *buf_adr; // 送信/受信先 アドレス
 byte cnt; // 文字数
};

struct W_BUF_TYPE b[10];

構造体、データ定義を上のようにしています。
b[10]の空きを探して書き込むサブルーチンを作ったのですが、*buf_adrの設定方法がわかりません。
ご存知の方、教えてください。

サブルーチン
sub_func(int8 *adr){
 byte i;
 for(i=0;i<10;i++){
   if(b[i].adr_h==0){  // b[10]の空き検索
   b[i].buf_adr=*adr; // アドレスを設定する。ここでエラーとなります。
 }
}
サブルーチンでバッファのアドレスを受けて、b[10]の空きエリアに設定するプログラムです。

Aベストアンサー

b[i].buf_adr=*adr; → b[i].buf_adr=adr;
ポインタ同士なのだから、そのまま転記する。
最初の書き方だと、ポインタ←ポインタの指している内容(整数)を
行うと言う意味なので、エラーになる。
別に左辺が構造体のメンバでなくても間違いです。

Qtry{}catch(){}とデストラクタの関係を教えてください。

try-catchでメモリ確保を含むクラスをスローした場合、デストラクタはどの時点で働くのか、教えてください。たとえば、↓の使いかたは大丈夫でしょうか?

【1】
try{
 throw(CError(100, "エラー情報"));
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
}

【2】
try{
 CError err(100, "エラー情報");
 throw(err); // (1)
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
 //まだデストラクタはちゃんと動作するのでしょうか?
 //catchが呼び出し元のメンバであったりしても大丈夫なのでしょうか?
}

宜しくお願いします。

Aベストアンサー

【1】【2】どちらの場合も問題がありません。
コンパイラが必要に応じてerrオブジェクトのコピーを作成します。
デストラクタが呼び出されるタイミングはコンパイラに依存するところもあると思いますが、
例えばVC7.1では【2】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) CErrorクラスのテンポラリオブジェクト(以下a)のコピーコンストラクタが呼び出される。
(3) errオブジェクトのデストラクタが呼び出される
(4) catch文まで到達
(5) aオブジェクトのデストラクタが呼び出される。

VC7.1では、【1】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) catch文まで到達
(3) errオブジェクトのデストラクタが呼び出される。

コンパイラがオブジェクトのコピーを省略しているようです。


人気Q&Aランキング

おすすめ情報