点击(此处)折叠或打开
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #ifndef SUCCESS
- #define SUCCESS 1
- #endif
- typedef struct _ini_struct { /* 以 key , value 方式,保存 ini 节点中的节点信息 */
- char *key;
- char *value;
- } INISTRUST ;
- /* TRIM LEFT */
- int rtrim( char *pszString)
- {
- int nForwardCursor = 0;
- int nTrailingCursor = 0;
- int bTrim = 1;
- for( nForwardCursor = 0 ; pszString[nForwardCursor] != '\0'; nForwardCursor++ )
- if ( bTrim && isspace( pszString[nForwardCursor] ))
- continue ;
- else {
- bTrim = 0;
- pszString[nTrailingCursor] = pszString[nForwardCursor];
- nTrailingCursor++;
- }
- pszString[nTrailingCursor] = '\0';
- return SUCCESS;
- }
- /* TRIM RIGHT */
- int ltrim( char *pszString )
- {
- int nForwardCursor = 0;
- int nTrailingCursor = 0;
- int bTrim = 1;
- for ( nForwardCursor=strlen(pszString)-1;
- nForwardCursor >= 0 && isspace( pszString[nForwardCursor] );
- nForwardCursor-- )
- {
- }
- pszString[nForwardCursor+1] = '\0';
- return SUCCESS;
- }
- /* TRIM LEFT & RIGHT */
- int trim(char *str)
- {
- ltrim(str);
- rtrim(str);
- return SUCCESS;
- }
- /* ********************************************************
- * char **read_ini(char *filename , int *iniline )
- * 从文件名为 filename 的 ini 文件中读取信息,并将其
- * 保存在一个 char *[] 字符串数组中。
- * 传入参数:
- * char *filename 一个有效的 ini 文件名
- * int *iniline 该文件中读取的记录行数
- * 返回值:
- * char *[] 保存该 ini 文件的所有记录的
- * 字符串数组
- * ******************************************************* */
- char **read_ini(char *filename,int *iniline)
- {
- FILE *fp;
- char *str;
- static char **ini_str;
- int ini_i;
- int i,j;
- ini_str = ( char **)malloc(sizeof(char *));
- *ini_str = ( char *)malloc(sizeof(char *)*1024);
- str = ( char *)malloc(sizeof(char)*1024);
- if ( (fp = fopen(filename,"rb")) != NULL )
- {
- ini_i = 0;
- while(!feof(fp))
- {
- bzero(str,1024);
- if ( fgets(str,1024,fp) != NULL )
- {
- for ( i = 0 ; i < strlen(str); i++ )
- {
- /* 切掉 ini 文件中的注释信息 */
- if ( str[i] == ';' || str[i] == '\n' )
- {
- str[i] = '\0';
- }
- }
- trim(str);
- if ( str[0] != '\0' && str[0] != '\n') {
- ini_str[ini_i] = ( char *)malloc(sizeof(char)*1024);
- snprintf(ini_str[ini_i],1024,"%s",str);
- ini_i++;
- }
- }
- }
- }
- fclose(fp);
- *iniline = ini_i;
- return (char **)ini_str;
- }
- /* *********************************************************************************
- * INISTRUST *get_ini_node ( char *filename , char *nodename,
- * INISTRUST *_sec_node , int *node_size )
- * 根据给定的ini文件名和指定的节点 ,提取该文件中指定节点的信息内
- * 容,并将其保存在结构体 _ini_struct 数组中
- * 传入参数:
- * char *filename 一个有效的 ini 文件的文件名
- * char *nodename 待提取的 ini 文件中的节点名
- * INISTRUST *_sec_node 保存提取到的节点信息的 key,value 结构体数组
- * int *node_size 保存该节点的信息记录条数,一个 key、value 对
- * 为一条记录
- * 返回值:
- * struct *_ini_struct 保存提取的节点的 key、value 键值信息结构数组
- * ******************************************************************************* */
- INISTRUST *get_ini_node ( char *filename , char *nodename, INISTRUST *_sec_node , int *node_size )
- {
- INISTRUST *_ini_node;
- char **ini_array;
- int ini_line;
- int i,j,flag = 0;
- char *token;
- int i_size = 0;
- *node_size = 0;
- _ini_node = _sec_node ;
- _ini_node = (INISTRUST *)malloc(sizeof(INISTRUST));
- _ini_node->key = (char *)malloc(sizeof(char)*128);
- _ini_node->value = (char *)malloc(sizeof(char)*256);
- ini_array = read_ini(filename,&ini_line);
- for ( i = 0 ; i< ini_line ; i++ )
- {
- if ( ini_array[i][0] == '[' )
- {
- if ( strcmp(ini_array[i],nodename)) {
- flag = 0;
- continue;
- } else {
- flag = 1;
- continue;
- }
- } else if ( flag == 1 ) {
- _ini_node[i_size].key = (char *)malloc(sizeof(char)*128);
- _ini_node[i_size].value = (char *)malloc(sizeof(char)*256);
- token = strtok(ini_array[i],"=");
- while( token != NULL )
- {
- if ( j %2 == 0 )
- {
- snprintf(_ini_node[i_size].key,128,"%s",token);
- trim(_ini_node[i_size].key);
- } else {
- snprintf(_ini_node[i_size].value,256,"%s",token);
- trim(_ini_node[i_size].value);
- }
- token=strtok(NULL,"=");
- j++;
- }
- i_size++;
- }
- }
- *node_size=i_size;
- return (INISTRUST *)_ini_node;
- }
- int main ( int argc , char **argv)
- {
- char **ini_s;
- int ini_line;
- int i;
- INISTRUST *s_ininode = get_ini_node ( argv[1] , argv[2], s_ininode , &ini_line );
- printf("=== %d \n",ini_line);
- for ( i = 0 ; i < ini_line ; i++ )
- {
- printf(" == KEY = %s \n",s_ininode[i].key);
- printf(" == VOL = %s \n",s_ininode[i].value);
- }
- return 0;
- }
基本实现思路是:
第一步:首先将 ini 文件读取出来,保存在 char *ini_array[] 字符串数组中,在保存的过程中,剔除了注释信息(ini文件中以 ';' 标注注释信息 ),并将每行信息的前后空格剔除。
第二步:将 char *ini_array[] 字符串数组传入 INISTRUCT *_get_ini_node 函数。
第三步:在_get_ini_node 函数中,首先判断每行的首字符是否是 '[' ,如果是,则该行是一个节点名,否则是某个节点下的 key、value, 当找到一个节点名时,对该节点字符串与传入的节点名称进行匹配,如果匹配成功,则将 flag = 1 ,表示下面的行是该节点的 key、value 值,对下面的行使用 strtok 进行拆解,拆解的匹配字符是“=”。然后将拆解的字符串分别存储到 _ini_node[i_size].key 和 _ini_node[i_size].value 中,然后返回到 for 循环中进行下一个判断。
注意事项:
1、此列子中应仔细体会字符串数组 char **ini_str 和结构体 struct _ini_struct *_ini_node 指针的使用方法,尤其是在 get_ini_node 函数中对结构体 struct _ini_struct *_ini_node 指针的两次内存分配操作。
2、本例子中使用了一个小技巧,即在函数 get_ini_node 定义了一个结构体指针 struct _ini_struct *_ini_node , 并将该指针直接指向了传入的结构体指针 struct _ini_struct *_sec_node , 从而实现了直接对 *_sec_node 的操作,实际上,程序没有返回 struct _ini_struct * 时,该程序也可以正常运行,并得到正确的结构,即在 main()函数中,作如下修改:
INISTRUCT *s_ininode = get_ini_node ( argv[1] , argv[2] , s_ininode , &iniline);
修改为:
INISTRUCT *s_ininode;
get_ini_node ( argv[1] , argv[2] , s_ininode , &iniline);
程序也可以正常运行,并得到正确的结果。
3、iniline 保存的是该节点的 key、value 的记录条数。