内容就不多说了,直接贴代码吧。
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
-
-
typedef struct _language {
-
char *title;
-
char *info;
-
} LANGUAGE ;
-
-
typedef struct _section {
-
char *name;
-
int sec_size; /* 保存当前节点中 LANGUAGE *langObjecct 的个数大小 */
-
LANGUAGE *langObject;
-
} SECTION;
-
-
-
SECTION *return_struct_sec ( int *section_size )
-
{
-
static SECTION *_sec_cur;
-
static LANGUAGE *_slang;
-
-
int i,j;
-
char s[512];
-
-
_sec_cur = (SECTION *)malloc(sizeof(SECTION));
-
_sec_cur->langObject = (LANGUAGE *)malloc(sizeof(LANGUAGE));
-
-
for ( i = 0 ; i < 3 ; i++ )
-
{
-
_sec_cur[i].name = (char *)malloc(sizeof(char)*64);
-
_sec_cur[i].langObject = (LANGUAGE *)malloc(sizeof(LANGUAGE));
-
/* 特别注意,此处必须首先针对 LANGUAGE 结构体中的组成元素分配一块内存,否则会造成第一个 LANGUAGE 结构体,也就是下标为 0 的 LANGUAGE 的内容没有内存空间存放 */
-
_sec_cur[i].langObject->title = (char *)malloc(sizeof(char)*64);
-
_sec_cur[i].langObject->info = (char *)malloc(sizeof(char)*128);
-
if ( _sec_cur->langObject == NULL )
-
{
-
printf(" malloc language error ... \n");
-
return 0;
-
}
-
-
sprintf(_sec_cur[i].name," SEC_NAME = %02d",i);
-
for ( j = 0 ; j < 8 ; j++)
-
{
-
_sec_cur[i].langObject[j].title = (char *)malloc(sizeof(char)*64);
-
_sec_cur[i].langObject[j].info = (char *)malloc(sizeof(char)*128);
-
snprintf(_sec_cur[i].langObject[j].title ,63, " LanguageObject.Title = %02d%02d",i,j);
-
snprintf(_sec_cur[i].langObject[j].info ,127, " LanguageObject.Info = %02d%02d",i,j);
-
printf(" ============ %s ============ \n",_sec_cur[i].name);
-
printf(" ======Title %s ============ \n",_sec_cur[i].langObject[j].title);
-
printf(" ======Info = %s ============ \n",_sec_cur[i].langObject[j].info);
-
}
-
_sec_cur[i].sec_size = j;
-
}
-
*section_size = i;
-
return (SECTION *)_sec_cur;
-
}
-
-
int main ( void )
-
{
-
SECTION *_sec;
-
int sec_size;
-
int i,j;
-
LANGUAGE *_slang;
-
-
_sec = return_struct_sec ( &sec_size );
-
-
for ( i = 0; i<sec_size;i++ )
-
{
-
for ( j = 0 ; j < _sec[i].sec_size; j++ )
-
{
-
printf( "===== 0 ======%s\n",_sec[i].name);
-
printf( "===== 1 ======%s\n",_sec[i].langObject[j].title);
-
printf( "===== 2 ======%s\n",_sec[i].langObject[j].info );
-
}
-
}
-
return 0;
-
}
说明:
本例子演示了针对结构体嵌套结构体的指针的数据存储和访问的操作。
本例中,我们首先定义了一个 SECTION 的结构体指针,并在该结构体中又定义了一个指向 LANGUAGE 结构体的指针。这样的数据结构,特别适合针对 .ini 文件的数据结构的存储。我们来看一下一个典型的 ini 文件的样式,就以一个 odbcinst.ini 为例进行数据结构体存储 ini 文件的说明。
一个典型的 odbcinst.ini 文件的内容可能如下:
-
[PostgreSQL]
-
Description=ODBC for PostgreSQL
-
Driver=/usr/lib/psqlodbcw.so
-
Setup=/usr/lib/libodbcpsqlS.so
-
Driver64=/usr/lib64/psqlodbcw.so
-
Setup64=/usr/lib64/libodbcpsqlS.so
-
FileUsage=1
-
-
[MySQL]
-
Description=ODBC for MySQL
-
Driver=/usr/lib/libmyodbc5.so
-
Setup=/usr/lib/libodbcmyS.so
-
Driver64=/usr/lib64/libmyodbc5.so
-
Setup64=/usr/lib64/libodbcmyS.so
-
FileUsage=1
我们来看看这个数据结构。
首先我们发现这个 odbcinst.ini 文件有两个节点,分别时 PostgreSQL 和 MySQL , 然后我们发现每个节点中又存在不同的 KEY 和对应的 VALUE 值,每个 KEY 和 VALUE 值占用一行,中间用 “= ” 号分割,这样我们可以将这个文件的内容存放在 SECTION 结构体中。
其中 SECTION.name 存放节点的名字,SECTION.sec_size 存放节点中 key、value 个数大小,而 SECTION.langObject 中存放每个节点的 KEY 和 VALUE 。由于我们每个节点中的 KEY = VALUE 有不确定的个数,因此我们需要一个指向 KEY->VALUE 的结构体指针来进行存储,针对每个key-value来动态分配结构体 langObject 的内存。
同时,由于我们的 odbcinst.ini 文件中有多个节,因此我们需要用一个指向 SECTION 的指针来存储不同的节点的信息。
需要注意程序中注释起来的说明信息,进入 return_struct_sec 函数,还没有对 langObject 结构体进行操作时,我们就需要首先进行一次内存分配,否则或造成 SECTION 结构体的第一个节中的 LANGUAGE 结构体没有有效内存存放我们的第一个节点的第一个 key-value 内存,
具体的现象是,在 return_struct_sec 函数中可以访问到 _sec_cur[0].langObject[0].title 和 _sec_cur[0].langObject[0].info 的值,但是在调用 return_struct_sec 的主函数中,尽管已经将 _sec_cur 的内容返回,但是在打印这个结构体的内容的时候,发现 _sec_cur[0].langObject[0].title 和 _sec_cur[0].langObject[0].info 的内容指向了一个不确定的区域,造成内容丢失,初步分析为进入 return_struct_sec 函数时,第一次对 _sec_cur[0].langObject[0].title 和 _sec_cur[0].langObject[0].info 进行赋值时没有分配必要的内存空间。
因此:我们在进入 return_struct_sec 函数后,首先执行
_sec_cur
= (SECTION
*)malloc
(sizeof
(SECTION
));
_sec_cur
->langObject
= (LANGUAGE
*)malloc
(sizeof
(LANGUAGE
));
针对 _sec_cur 结构体和 _sec_cur 中指向 LANGUAGE *langObject 的指针进行了内存分配。
然后在我们进入到第一个 for 循环,也就是
for ( i
= 0
; i
< 3
; i
++ ) 的循环中,依次对 _sec_cur[i].langObject 结构体进行内存分配,并在我们的第二个 for 循环,也就是
for ( j
= 0
; j
< 8
; j
++) 对 _sec_cur[i].langObject[j].title 和 _sec_cur[i].langObject[j].info 进行内存分配,这样才能保证我们的 _sec_cur 有足够的空间连续存放 odbcinst.ini 中每个节点,以及每个节点所对应的 key、value 的内容。
最后,我们使用 return (SECTION *)_sec_cur ; 将该块内存返回给调用 return_struct_sec 函数的 main 函数中,并让 SECTION *_sec 指向这一块内存区域。(这里有一个注意的小细节,我们在 return_struct_sec 函数 中定义的 _sec_cur 是一个 static SECTION *_sec_cur ,这样做的目的是让 return_struct_sec 函数退出以后,其分配的内存地址仍然保留,供调用者的函数进行访问。有关 static 的含义及用法,自己翻书吧 ^_^. )。
阅读(2279) | 评论(0) | 转发(0) |