C语言实现<读取>和<写入> *.ini文件(转)

原地址:https://blog.csdn.net/niha1993825jian/article/details/41086403

#include <stdio.h>  
#include <errno.h>  
#include <ctype.h>  
#include <string.h>  
#include <stdlib.h>  
#include <stdbool.h>  
  
#define  MAX_VALUE  64 /* 定义section,key,value字符串最大长度 */  
// printf("File = %s
Line = %d
Func=%s
Date=%s
Time=%s
", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__);  
#define  PRINT_ERRMSG(STR) fprintf(stderr,"line:%d,msg:%s,eMsg:%s
", __LINE__, STR, strerror(errno))  
  
typedef struct _option {  
  char    key[MAX_VALUE];   /* 对应键 */  
  char    value[MAX_VALUE]; /* 对应值 */  
  struct  _option *next;    /* 链表连接标识 */  
}Option;  
  
typedef struct _data {  
  char    section[MAX_VALUE]; /* 保存section值          */  
  Option  *option;            /* option链表头           */  
  struct  _data *next;        /* 链表连接标识           */  
}Data;  
  
typedef struct {  
  char    comment;              /* 表示注释的符号    */  
  char    separator;            /* 表示分隔符        */  
  char    re_string[MAX_VALUE]; /* 返回值字符串的值  */  
  int     re_int;               /* 返回int的值       */  
  bool    re_bool;              /* 返回bool的值      */  
  double  re_double ;           /* 返回double类型    */  
  Data    *data;                /* 保存数据的头      */  
}Config;  
  
/** 
* 判断字符串是否为空 
* 为空返回true,不为空返回false 
**/  
bool str_empty(const char *string)  
{  
  return NULL == string || 0 == strlen(string);  
}  
  
/** 
* 向链表添加section,key,value 
* 如果添加时不存在section则新增一个 
* 如果对应section的key不存在则新增一个 
* 如果section已存在则不会重复创建 
* 如果对应section的key已存在则只会覆盖key的值 
**/  
bool cnf_add_option(Config *cnf, const char *section, const char *key, const char *value)  
{  
  if (NULL == cnf || str_empty(section) || str_empty(key) || str_empty(value)) {  
    return false; /* 参数不正确,返回false */  
  }  
    
  Data *p = cnf->data; /* 让变量p循环遍历data,找到对应section */  
  while (NULL != p && 0 != strcmp(p->section, section)) {  
    p = p->next;  
  }  
    
  if (NULL == p) { /* 说明没有找到section,需要加一个 */  
    Data *ps = (Data*)malloc(sizeof(Data));  
    if (NULL == ps) {  
      exit(-1); /* 申请内存错误 */  
    }  
    strcpy(ps->section, section);  
    ps->option = NULL;    /* 初始的option要为空 */  
    ps->next = cnf->data; /* cnf->data可能为NULL */  
    cnf->data = p = ps;   /* 头插法插入链表 */  
  }  
    
  Option *q = p->option;  
  while (NULL != q && 0 != strcmp(q->key, key)) {  
    q = q->next; /* 遍历option,检查key是否已经存在 */  
  }  
    
  if (NULL == q) { /* 不存在option,则新建一个 */  
    q = (Option*)malloc(sizeof(Option));  
    if (NULL == q) {  
      exit(-1); /* 申请内存错误 */  
    }  
    strcpy(q->key, key);  
    q->next = p->option; /*这里p->option可能为NULL,不过也没关系 */  
    p->option = q; /* 头插法插入链表 */  
  }  
  strcpy(q->value, value); /* 无论如何要把值改了 */  
    
  return true;  
}  
  
/** 
* 去掉字符串内所有空白 
* 且忽略注释部分 
* 最终得到没有空白的字符串 
**/  
bool strip_comments(char *string, char comment)  
{  
  if (NULL == string || '
' == *string || '
' == *string) {  
    return false; /* 第一个字符为回车或换行,表示空行 */  
  }  
    
  char *p, *q; /* 下面去掉字符串中所有空白字符 */  
  for (p = q = string; *p != '