本例子根据给定的 ini 文件名和给定的 ini 节点获取对应节点的信息, 并保存在 _ini_struct 结构体数组中。


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>

  5. #ifndef SUCCESS
  6. #define SUCCESS 1
  7. #endif

  8. typedef struct _ini_struct {     /* 以 key , value 方式,保存 ini 节点中的节点信息 */
  9.     char    *key;
  10.     char    *value;
  11. } INISTRUST ;


  12. /* TRIM LEFT */

  13. int rtrim( char *pszString)
  14. {
  15.     int nForwardCursor = 0;
  16.     int nTrailingCursor = 0;
  17.     int bTrim = 1;

  18.     for( nForwardCursor = 0 ; pszString[nForwardCursor] != '\0'; nForwardCursor++ )
  19.         if ( bTrim && isspace( pszString[nForwardCursor] ))
  20.             continue ;
  21.         else {
  22.             bTrim = 0;
  23.             pszString[nTrailingCursor] = pszString[nForwardCursor];
  24.             nTrailingCursor++;
  25.         }
  26.     pszString[nTrailingCursor] = '\0';
  27.     return SUCCESS;
  28. }

  29. /* TRIM RIGHT */
  30. int ltrim( char *pszString )
  31. {
  32.     int nForwardCursor = 0;
  33.     int nTrailingCursor = 0;
  34.     int bTrim = 1;
  35.     for ( nForwardCursor=strlen(pszString)-1;
  36.             nForwardCursor >= 0 && isspace( pszString[nForwardCursor] );
  37.             nForwardCursor-- )
  38.     {
  39.     }
  40.     pszString[nForwardCursor+1] = '\0';
  41.     return SUCCESS;
  42. }

  43. /* TRIM LEFT & RIGHT */
  44. int trim(char *str)
  45. {
  46.     ltrim(str);
  47.     rtrim(str);
  48.     return SUCCESS;
  49. }

  50. /* ********************************************************
  51.  *  char **read_ini(char *filename , int *iniline )
  52.  *        从文件名为 filename 的 ini 文件中读取信息,并将其
  53.  *        保存在一个 char *[] 字符串数组中。
  54.  *        传入参数:
  55.  *            char *filename       一个有效的 ini 文件名
  56.  *            int  *iniline       该文件中读取的记录行数
  57.  *        返回值:
  58.  *            char *[]            保存该 ini 文件的所有记录的
  59.  *                                字符串数组
  60.  * ******************************************************* */
  61. char    **read_ini(char *filename,int *iniline)
  62. {
  63.     FILE    *fp;
  64.     char    *str;
  65.     static char    **ini_str;
  66.     int    ini_i;
  67.     int    i,j;

  68.     ini_str = ( char **)malloc(sizeof(char *));
  69.     *ini_str = ( char *)malloc(sizeof(char *)*1024);
  70.     str = ( char *)malloc(sizeof(char)*1024);

  71.     if ( (fp = fopen(filename,"rb")) != NULL )
  72.     {
  73.         ini_i = 0;
  74.         while(!feof(fp))
  75.         {
  76.             bzero(str,1024);
  77.             if ( fgets(str,1024,fp) != NULL )
  78.             {
  79.                 for ( i = 0 ; i < strlen(str); i++ )
  80.                 {
  81.                     /* 切掉 ini 文件中的注释信息 */
  82.                     if ( str[i] == ';' || str[i] == '\n' )
  83.                     {
  84.                         str[i] = '\0';
  85.                     }
  86.                 }
  87.                 trim(str);
  88.                 if ( str[0] != '\0' && str[0] != '\n') {
  89.                     ini_str[ini_i] = ( char *)malloc(sizeof(char)*1024);
  90.                     snprintf(ini_str[ini_i],1024,"%s",str);
  91.                     ini_i++;
  92.                 }
  93.             }
  94.         }
  95.     }
  96.     fclose(fp);
  97.     *iniline = ini_i;
  98.     return (char **)ini_str;
  99. }
  100.  

  101. /* *********************************************************************************
  102.  *  INISTRUST *get_ini_node ( char *filename , char *nodename,
  103.  *                            INISTRUST *_sec_node , int *node_size )
  104.  *       根据给定的ini文件名和指定的节点 ,提取该文件中指定节点的信息内
  105.  *       容,并将其保存在结构体 _ini_struct 数组中
  106.  *       传入参数:
  107.  *            char *filename           一个有效的 ini 文件的文件名
  108.  *            char *nodename           待提取的 ini 文件中的节点名
  109.  *            INISTRUST *_sec_node     保存提取到的节点信息的 key,value 结构体数组
  110.  *            int *node_size           保存该节点的信息记录条数,一个 key、value 对
  111.  *                                     为一条记录
  112.  *       返回值:
  113.  *           struct *_ini_struct       保存提取的节点的 key、value 键值信息结构数组
  114.  * ******************************************************************************* */
  115. INISTRUST *get_ini_node ( char *filename , char *nodename, INISTRUST *_sec_node , int *node_size )
  116. {
  117.     INISTRUST *_ini_node;
  118.     char    **ini_array;
  119.     int    ini_line;
  120.     int    i,j,flag = 0;
  121.     char    *token;
  122.     int    i_size = 0;

  123.     *node_size = 0;
  124.     _ini_node = _sec_node ;

  125.     _ini_node = (INISTRUST *)malloc(sizeof(INISTRUST));
  126.     _ini_node->key = (char *)malloc(sizeof(char)*128);
  127.     _ini_node->value = (char *)malloc(sizeof(char)*256);
  128.     ini_array = read_ini(filename,&ini_line);
  129.     for ( i = 0 ; i< ini_line ; i++ )
  130.     {
  131.         if ( ini_array[i][0] == '[' )
  132.         {
  133.             if ( strcmp(ini_array[i],nodename)) {
  134.                 flag = 0;
  135.                 continue;
  136.             } else {
  137.                 flag = 1;
  138.                 continue;
  139.             }
  140.         } else if ( flag == 1 ) {
  141.             _ini_node[i_size].key = (char *)malloc(sizeof(char)*128);
  142.             _ini_node[i_size].value = (char *)malloc(sizeof(char)*256);
  143.             token = strtok(ini_array[i],"=");
  144.             while( token != NULL )
  145.             {
  146.                 if ( j %2 == 0 )
  147.                 {
  148.                     snprintf(_ini_node[i_size].key,128,"%s",token);
  149.                     trim(_ini_node[i_size].key);
  150.                 } else {
  151.                     snprintf(_ini_node[i_size].value,256,"%s",token);
  152.                     trim(_ini_node[i_size].value);
  153.                 }
  154.                 token=strtok(NULL,"=");
  155.                 j++;
  156.             }
  157.             i_size++;
  158.         }
  159.     }
  160.     *node_size=i_size;
  161.     return (INISTRUST *)_ini_node;
  162. }


  163. int main ( int argc , char **argv)
  164. {
  165.     char    **ini_s;
  166.     int    ini_line;
  167.     int    i;
  168.     INISTRUST *s_ininode = get_ini_node ( argv[1] , argv[2], s_ininode , &ini_line );
  169.     printf("=== %d \n",ini_line);
  170.     for ( i = 0 ; i < ini_line ; i++ )
  171.     {
  172.         printf(" == KEY = %s \n",s_ininode[i].key);
  173.         printf(" == VOL = %s \n",s_ininode[i].value);
  174.     }

  175.     return 0;
  176. }
以上是一个完整的从 ini 文件中提取指定节点信息的示例,可以直接使用。
基本实现思路是:
第一步:首先将 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 的记录条数。

11-10 15:35