はじめまして。
最近プログラムを勉強し始めたうみと申します。
構造体TEST_Aのなかに、他の構造体Bを作成します。Bの大きさは可変なのでポインタで
宣言しました。作成した構造体は以下の通りです。
typedef struct
{
char test[30];
char test2[30];
} TEST_B
typedef struct
{
int A1 ;
char A2[30] ;
TEST_B *pTEST_B;
} TEST_A
TEST_Bの構造体に、データを入れていきたいのですが、どのようにコーディングしたら
いいのか分かりません。初歩的な質問で申し訳ないのですが、皆様のお力を貸してくだ
さい。
初めての質問で説明不足な点が多々あると思いますが、お許しください。
まず、構造体をちゃんと書きます。
まんまだと、コンパイル通りませんよねぇ。
typedef struct TEST_B
{
char test[30];
char test2[30];
} TEST_B;
typedef struct TEST_A
{
int A1 ;
char A2[30] ;
TEST_B *pTEST_B;
} TEST_A;
> TEST_Bの構造体に、データを入れていきたいのですが、・・・(一部略)
こんな感じで使います。
TEST_A valueA;
strcpy( valueA.pTEST_B->test, Nanjya test);
strcpy( valueA.pTEST_B->test2, Dojya test2);
strcpy( valueA.A2, A2 jya);
構造体は同じものを利用して、可変とゆうことなのでmallocで
int i=2; // TEST_Bの個数
TEST_A testa;
test.pTEST_B = (TEST_B*)malloc(sizeof(TEST_B)*i);
test.A1 = 1;
strcpy(test.A1, abc);
strcpy(test.pTEST_B[0].test, def);
strcpy(test.pTEST_B[1].test2, ghk);
free(test.pTEST_B);
仲澤@失業者 様、ねむねむ 様
ご回答ありがとうございます。
>strcpy(test.pTEST_B[0].test, def);
>strcpy(test.pTEST_B[1].test2, ghk);
ポインタでTEST_Bを宣言しても、普通の構造体のように[0]、[1]のように使うことがで
きるのですね。勉強不足で申し訳ありません。
実際に構造体に入れたデータを使いたい時も、TEST_Bの配列分for文で回して取り出せば
いいのでしょうか。
本当に初心者で申し訳ありません。
> ポインタでTEST_Bを宣言しても、普通の構造体のように[0]、[1]のように使うことが
> できるのですね。勉強不足で申し訳ありません。
構造体ではなくて配列の間違いではないかと思います。
ポインタで宣言した変数に対しても配列と同じ形でアクセスが可能です。
この辺はC言語の入門書にも書いてあるはずなので確認されたほうが良いです。
> 実際に構造体に入れたデータを使いたい時も、TEST_Bの配列分for文で回して
> 取り出せばいいのでしょうか。
設定するときも取り出すときも同じ事なのでfor文で回して取り出せます。
数が多い場合は普通はそうしますね。
もし、入門書を使わずに勉強を始めたのであれば、
入門書を使った方が良いですよ。
Web上の情報はだと膨大な情報から適切な物を選別する必要がありますが、
ある程度知識が無いとなかなか選別できないと思います。
書籍ですと整理された形で提供されているので知識が少ないうちは
書籍で勉強した方が無難です。
PATIO様、ご回答ありがとうございます。
週末本を買ったので勉強します。
>int i=2; // TEST_Bの個数
このように構造体の数を決めないやり方は自己参照構造体を作成すれば良いのでしょう
か?
自己参照構造体にする必要は無いと思いますけれど。
いわゆるリスト構造とか双方向チェインとかの事だと思いますが、
これは繋ぎ変えが容易になると言うメリットの方が大きいので
単に可変長配列を実現したいだけならそこまでしなくて良いと思います。
かえって次の要素へのアクセスが面倒になるだけだと思うので。
C言語で単純に可変長の配列を表現するなら
構造体のポインタを宣言して必要なサイズ分のメモリを
malloc等で割り当てるのが一般的でしょう。
この時、配列のサイズとポインタをセットにして管理すると
良いかと思います。
後は、必要がなくなったら割り当てたメモリを忘れずに開放する
くらいでしょうか。
C言語で可変長配列を使うにはプログラマの側できちんと
メモリの管理をする必要が有りますので注意が必要になります。
開放しないでポインタの値を書き換えてしまうとそのメモリは
プログラムが終了するまで開放できなくなります。
こういうプログラムミスをするとどんどんメモリが使い潰されて
スワップが起こって極端に遅くなったり、メモリ不足でエラーが
起こったりします。
PATIO 様、さっそくのご回答ありがとうございます。
自己参照構造体にする必要は無いのですね。勉強になります、ありがとうございます。
>構造体のポインタを宣言して必要なサイズ分のメモリを
>malloc等で割り当てるのが一般的でしょう。
必要なサイズが分からない場合は、あふれない程度の大きさのメモリを確保すれば良い
のですか?
度々の質問で申し訳ありません。
えーと、どのような実装を想定しているのでしょう?
実際に動作するときもサイズが全く分からないのでしょうか?
もしわからないのであれば、初期サイズを決めておいて
最初はそのサイズで確保しておきます。
確保したサイズ以上になったときは、予め決めておいたサイズ分
拡張したサイズでメモリを再確保します。
この辺はmallocとかreallocとかの関数を調べて見てください。
実行時にメモリを確保すると言うことは、
再確保する事でサイズを変更できると言うことです。
但し、この辺の操作をするのはプログラマになりますから
前のレスでも書いた通り、メモリリークにならないよう
注意して実装する必要があります。
要は、プログラマがメモリの管理も責任を持ってやる必要が
あると言う話です。
あと、実際にサイズがわかるまで確保を遅らせても
動作に支障が無いのであれば、メモリの確保を遅らせると言う
方法もあるのではないでしょうか?
ユーザーに与えられた条件とか指定されたファイルのサイズとか
何らかの方法で得られるデータ数とかを元にしてメモリの確保を
行う事は可能だと思います。
その為のメモリ確保の関数でしょう?
mallocに引き渡す引数が確保するメモリサイズなのですから
確保するサイズがわかってから確保すれば良いのでは?
PATIO 様
ご回答ありがとうございます。
今回実装しようとしている処理は、ユーザーが停止するまでの間、データを蓄積すると
いう処理を実装したいので、ユーザーが処理を停止するまでサイズが分からないかと思
ったのです。
PATIO様から教えていただいた通り、mallocとreallocの使い方も理解できていない
ので、調べてみます。
気になったので書いておきます。
ユーザーが停止するまでデータを蓄積する場合、
ユーザーが停止する前にメモリが足りなくなったら
どうするのでしょう?
メモリは有限ですからずっと貯め続けるわけには
行かないと思いますよ。
メモリが足りなくなったらどうするのか?
と言うことは予め考えておくべきです。
これは、ファイルとしてHDDに記録する場合でも
同じ事です。