注: これはもともと、
gSoapユーティリティによって生成されたアドレス構造に特に投稿されましたが、ポインターを持つネストされた構造体に一般的に適用できます...
以下は、ネストされたセクション内のフィールド数が実行時まで不明な、ネストされた構造構造内のメンバーとポインターを初期化、割り当て、割り当て、および解放するための ANSI C メソッドについて説明しています。
この処理を必要とする構造体の形状を説明すると、データ スキーマは既知の数のヘッダーフィールドで構成され、各フィールドは行ごとに 1 つの値を持ちます。最後のフィールド (行) は、ヘッダーセクションとデータ********
セクションの間の区切り文字として機能します。データ セクションには不明な数のデータ レコードが含まれていますが、各レコードには既知の (そして一定の) 数のコンマ区切りフィールドが含まれています。
サンプルデータ:
以下に示す 2 つのファイルは、完全にコメント化されています。一緒に、ANSI C コンパイラでコンパイルおよびビルドします。
InitComplexStructs.h:
//The struct names typical in gSoap generated code
//are longer and more complicated.
//for example, a typical client soap_call___ns...()
//function prototype may look like this:
//SOAP_FMAC5 int SOAP_FMAC6 soap_call___ns1__SendLEDF(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _ns3__ledf_send *ns3__xxmtsvclws, struct _ns3__ledf_recv *ns3__xxmtsvclwsResponse)
//where areguments 4 & 5 are respectively:
// arg 4: struct _ns3__ledf_send *ns3__xxmtsvclws
// arg 5: struct _ns3__ledf_recv *ns3__xxmtsvclwsResponse
//
//for this project we will assume arg 4 represents a complex (nested)
//set of data structures, and for illustration purposes, shorten the
//name to aaa:
// struct aaa contains members to accomodate a fixed number of strings
// as well as a pointer to struct bbb
struct aaa {
char *aaaStr1;
char *aaaStr2;
char *aaaStr3;
char *aaaStr4;
char *aaaStr5;
struct bbb *pBbb;
};
// struct bbb is used to set array order size
// (or the number of copies necessary of struct ccc)
// it contains the array size (index value) member "numRows"
// and a pointer to a struct, which will work like a pointer
// to array of struct ccc
struct bbb {
int numRows;
struct ccc *row;
};
// struct ccc contains members to accomodate a variable number of
// sets of strings, number of sets determined by the array row[]
// initialized to array size "numRows" in struct bbb
// (see initComplexStructs.c for how this is done)
struct ccc {
char *cccStr1;
char *cccStr2;
char *cccStr3;
char *cccStr4;
char *cccStr5;
};
InitComplexStructs.c
///////////////////////////////////////////////////////////
///// Using nested data structures ////////////////////////
///////////////////////////////////////////////////////////
//
// client-side gSoap generated code will often use nested
// data structures to accomodate complex data types
// used in the 4th and 5th arguments of the client
// soap_call__ns...() functions.
//
// This program illustrates how to work with these
// structures by a calling application in the
// following way :
//
// - Initialization of structs
// - Allocation of structs and members
// - Assignment of values to members
// - Freeing of allocated memory
//
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
#include <ansi_c.h>
#include "InitComplexStructs.h"
struct aaa _aaa, *p_aaa;
struct bbb _bbb, *p_bbb;
struct ccc _row, *p_row;
void InitializeStructs(void);
void AllocateStructs(void);
void AssignStructs(void);
void FreeStructs(void);
char typicalStr[]={"aaaStr 1"};
size_t sizeStr = sizeof(typicalStr);
void main (void)
{
InitializeStructs();
AllocateStructs();
AssignStructs();
FreeStructs();
}
void InitializeStructs(void)
{
p_aaa = &_aaa;
p_bbb = &_bbb;
p_row = &_row;
}
void AllocateStructs(void)
{
int i;
//allocate members of p_aaa
p_aaa->aaaStr1 = calloc(sizeStr, 1);
p_aaa->aaaStr2 = calloc(sizeStr, 1);
p_aaa->aaaStr3 = calloc(sizeStr, 1);
p_aaa->aaaStr4 = calloc(sizeStr, 1);
p_aaa->aaaStr5 = calloc(sizeStr, 1);
p_aaa->pBbb = malloc( sizeof(*p_bbb));
//Allocate member of next nested struct - pBbb
//Note: The order of array is determined
//by the value assigned to "numRows"
//Note also: the value for numRows could be passed in by argument
//since the calling function has this information.
//Just requires prototype mod from void to int argument.
p_aaa->pBbb->numRows = 3;
p_aaa->pBbb->row = calloc(p_aaa->pBbb->numRows,sizeof(*p_row));
//Allocate the innermost struct ccc accessed through *row
for(i=0;i<p_aaa->pBbb->numRows;i++)
{
p_aaa->pBbb->row[i].cccStr1 = calloc(sizeStr, 1);
p_aaa->pBbb->row[i].cccStr2 = calloc(sizeStr, 1);
p_aaa->pBbb->row[i].cccStr3 = calloc(sizeStr, 1);
p_aaa->pBbb->row[i].cccStr4 = calloc(sizeStr, 1);
p_aaa->pBbb->row[i].cccStr5 = calloc(sizeStr, 1);
}
}
void AssignStructs(void)
{
int i;
strcpy(p_aaa->aaaStr1, "aaaStr 1");
strcpy(p_aaa->aaaStr1, "aaaStr 2");
strcpy(p_aaa->aaaStr1, "aaaStr 3");
strcpy(p_aaa->aaaStr1, "aaaStr 4");
strcpy(p_aaa->aaaStr1, "aaaStr 5");
for(i=0;i<p_aaa->pBbb->numRows;i++)
{
strcpy(p_aaa->pBbb->row[i].cccStr1, "bbbStr 1");
strcpy(p_aaa->pBbb->row[i].cccStr2, "bbbStr 2");
strcpy(p_aaa->pBbb->row[i].cccStr3, "bbbStr 3");
strcpy(p_aaa->pBbb->row[i].cccStr4, "bbbStr 4");
strcpy(p_aaa->pBbb->row[i].cccStr5, "bbbStr 5");
}
}
void FreeStructs(void)
{
int i;
for(i=0;i<p_aaa->pBbb->numRows;i++)
{
free(p_aaa->pBbb->row[i].cccStr1);
free(p_aaa->pBbb->row[i].cccStr2);
free(p_aaa->pBbb->row[i].cccStr3);
free(p_aaa->pBbb->row[i].cccStr4);
free(p_aaa->pBbb->row[i].cccStr5);
}
free(p_aaa->pBbb->row);
free(p_aaa->pBbb);
free(p_aaa->aaaStr1);
free(p_aaa->aaaStr2);
free(p_aaa->aaaStr3);
free(p_aaa->aaaStr4);
free(p_aaa->aaaStr5);
}