引用别人的博文: http://www.open-open.com/lib/view/open1402278076447.html

可以解析 INI 格式的字符串、解析文件、保存到文件。

下面是头文件:

 #ifndef INI_PARSER_H
#define INI_PARSER_H
#ifdef __cplusplus
extern "C" {
#endif
struct tag_value_list; struct ini_parser {
struct tag_value_list * keyvalues;
int (*parse_file)(struct ini_parser *, const char * file);
int (*parse_string)(struct ini_parser *, const char *text);
char * (*value)(struct ini_parser *, const char * key);
void (*set_value)(struct ini_parser *, const char * key, const char * value);
void (*remove)(struct ini_parser *, const char *key);
int (*save_to_file)(struct ini_parser *, const char * file);
}; struct ini_parser * new_ini_parser();
void delete_ini_parser(struct ini_parser *); #ifdef __cplusplus
}
#endif
#endif // INI_PARSER_H
下面是源文件:
#include "ini_parser.h"
#include <stdio.h>
#include <string.h>
#include "tag_value.h" static struct tag_value_pair * parse_line(char *line, int len)
{
struct tag_value_pair * pair = ;
int count = ;
char * p = line;
char * end = ;
char * start = line;
if(!p) return ;
while(*p == ' ') p++; /*blank line*/
if(p - line == len ||
*p == '\r' ||
*p == '\n' ||
*p == '\0') return ; /*do not support group*/
if(*p == '[') return ;
/*comments*/
if(*p == '#') return ; /* extract key */
start = p;
end = line + len;
while(*p != '=' && p!= end) p++;
if(p == end)
{
/* none '=' , invalid line */
return ;
}
end = p - ;
while(*end == ' ') end--; /* skip blank at the end */
count = end - start + ; pair = new_tag_value_pair();
pair->szTag = malloc(count + );
strncpy(pair->szTag, start, count);
pair->szTag[count] = ; /* extract value */
p++;
end = line + len; /* next pos of the last char */
while( *p == ' ' && p != end) p++;
if(p == end)
{
delete_tag_value_pair(pair);
return ;
}
start = p;
end--; /* to the last char */
if(*end == '\n') { *end = ; end--; }
if(*end == '\r') { *end = ; end--; }
count = end - start + ;
if(count > )
{
pair->szValue = malloc(count + );
strncpy(pair->szValue, start, count);
pair->szValue[count] = ;
} /* release empty key-value pair */
if(!pair->szValue)
{
delete_tag_value_pair(pair);
return ;
} return pair;
} static int _parse_file(struct ini_parser * ini, const char *file){
FILE * fp = fopen(file, "r");
if(fp)
{
struct tag_value_pair * pair = ;
char buf[] = {};
while(fgets(buf, , fp))
{
pair = parse_line(buf, strlen(buf));
if(pair)
{
ini->keyvalues->add(ini->keyvalues, pair);
}
}
fclose(fp);
return ini->keyvalues->size;
}
return -;
} static int _parse_text(struct ini_parser * ini, const char * text){
char *p = text;
char * start = ;
struct tag_value_pair * pair = ;
if(!text) return -; while()
{
start = p;
while(*p != '\n' && *p != '\0' )p++;
if(*p == '\0') break; pair = parse_line(start, p - start);
if(pair) ini->keyvalues->add(ini->keyvalues, pair); p++;
} return ini->keyvalues->size;
} static char * _value(struct ini_parser * ini, const char * key){
struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
if(pair) return pair->szValue;
return ;
} static void _set_value(struct ini_parser * ini, const char * key, const char *value){
struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
if(pair)
{
if(pair->szValue) free(pair->szValue);
pair->szValue = strdup(value);
}
else
{
ini->keyvalues->add(ini->keyvalues, make_tag_value_pair(key, value));
}
} static void _remove(struct ini_parser * ini, const char * key){
struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);
if(pair)ini->keyvalues->remove(ini->keyvalues, pair);
} static void write_keyvalue(struct tag_value_pair * pair, FILE *fp)
{
fputs(pair->szTag, fp);
fputc('=', fp);
fputs(pair->szValue, fp);
fputc('\n', fp);
} static int _save_to_file(struct ini_parser * ini, const char * file){
if(ini->keyvalues->size > )
{
FILE * fp = fopen(file, "w");
if(fp)
{
struct tag_value_pair * pair = ini->keyvalues->head;
while(pair != ini->keyvalues->tail)
{
write_keyvalue(pair, fp);
pair = pair->next;
} if(pair)write_keyvalue(pair, fp); fclose(fp);
return ;
}
}
return -;
} struct ini_parser * new_ini_parser(){
struct ini_parser * ini = (struct ini_parser*)malloc(sizeof(struct ini_parser));
ini->keyvalues = new_tag_value_list();
ini->parse_file = _parse_file;
ini->parse_string = _parse_text;
ini->value = _value;
ini->set_value = _set_value;
ini->remove = _remove;
ini->save_to_file = _save_to_file;
return ini;
} void delete_ini_parser(struct ini_parser *ini){
if(ini)
{
delete_tag_value_list(ini->keyvalues);
free(ini);
}
}
测试代码:
#include "util/ini_parser.h"
#include "ini_test.h"
#include <stdio.h>
#include <assert.h> static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli zhang \n"; static void ini_parser_test_string()
{
struct ini_parser * ini = new_ini_parser();
int size = ini->parse_string(ini, g_szIniString); assert( size > );
assert( ini->value(ini, "second") == );
assert( ini->value(ini, "abc") == );
assert( ini->value(ini, "name") != NULL );
assert( ini->value(ini, "first") != NULL); printf("ini string: %s\n", g_szIniString);
printf("key-value pairs count = %d\n", size);
printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
printf("key \'first\'', value = %s\n", ini->value(ini, "first")); ini->set_value(ini, "baidu", "hahaha");
ini->save_to_file(ini, "write.conf"); ini->remove(ini, "first");
ini->save_to_file(ini, "write2.conf"); delete_ini_parser(ini);
} static void ini_parser_test_file()
{
struct ini_parser * ini = new_ini_parser();
int size = ini->parse_file(ini, "test.conf"); assert( size > );
assert( ini->value(ini, "second") == );
assert( ini->value(ini, "abc") == );
assert( ini->value(ini, "name") != NULL );
assert( ini->value(ini, "first") != NULL); printf("ini string: %s\n", g_szIniString);
printf("key-value pairs count = %d\n", size);
printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
printf("key \'first\'', value = %s\n", ini->value(ini, "first"));
printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu")); delete_ini_parser(ini);
} void ini_parser_test()
{
ini_parser_test_string();
ini_parser_test_file();
}

C语言解析Ini格式文件的更多相关文章

  1. shell解析ini格式文件

    功能 本脚本实现了ini文件中的查询修改指定value 百度云连接地址 链接:https://pan.baidu.com/s/12_T5yST7Y3L1H4_MkVEcvA 密码:fo5p 解压后先看 ...

  2. C语言解析WAV音频文件

    C语言解析WAV音频文件 代码地址: Github : https://github.com/CasterWx/c-wave-master 目录 前言 了解WAV音频文件 什么是二进制文件 WAV的二 ...

  3. SHELL读取 ini 格式文件做配置文件

    ini文件格式一般都是由节.键.值三部分组成 格式: [第一节 ] 第一个键 = 值 第二个键 = 第二个值 [第二节 ] 第一个键 = val1,val2,val3 例子: [COM] KINGGO ...

  4. 利用 nodejs 解析 m3u8 格式文件,并下 ts 合并为 mp4

    利用 nodejs 解析 m3u8 格式文件,并下 ts 合并为 mp4 以前看视频的时候,直接找到 video标签,查看视频地址,然后下载下来.. 后来发现,好多 video 标签打开元素审查,如下 ...

  5. WP8解析XML格式文件

    DOTA2 WebAPI请求返回的格式有两种,一种是XML,一种是JSON,默认是返回JSON格式,如果要返回XML格式的话,需要在加上format=xml. 这里举一个简单的解析XML格式的例子(更 ...

  6. dom4解析xml格式文件实例

    以下给4种常见的xml文件的解析方式的分析对比: DOM DOM4J JDOM SAX 解析XML文件的几种方式和区别答: Dom解析 在内存中创建一个DOM树,该结构通常需要加载整个文档然后才能做工 ...

  7. dom4j解析xml格式文件实例

    以下给4种常见的xml文件的解析方式的分析对比: DOM  DOM4J  JDOM  SAX Dom解析    在内存中创建一个DOM树,该结构通常需要加载整个文档然后才能做工作.由于它是基于信息层次 ...

  8. Linux C语言解析.bmp格式图片并显示汉字

    bmp.h 文件 #ifndef __BMP_H__ #define __BMP_H__ #include <unistd.h> #include <stdio.h> #inc ...

  9. XmlDocument解析Soap格式文件案例:

    private static string Analysis(string strResult) { var doc = new System.Xml.XmlDocument(); //加载soap文 ...

随机推荐

  1. 一些常用的sql语句

    1.查询表里的null值:is null 和 is not null  select*from student where email is null       返回的该表里面邮箱为null的结果集 ...

  2. Windows动态库学习心得

    最近在工作中需要给项目组其他成员提供调用函数,决心抛弃以前“拷贝头文件/源文件”的简陋方法,采用动态库的方式对自己开发的接口进行模块化管理.因之前一直没有机会从事Windows动态库的开发,现借助这个 ...

  3. Strint类成员

    String& String::operator=(const string& other){ if(this == &other) {  return *this; } de ...

  4. CSS + DIV 让页脚始终底部

    一 前言 经常设计页面时用到三层DIV,头DIV与脚DIV一般固定高度,而中间层DIV根据内容的多少,高度不定,我们经常希望但内容很少时,脚DIV保持在底部,当内容很多时,脚DIV被中间内容挤到下面, ...

  5. Raspberry pi(-) Mac下安装系统

    购买树莓派一般的操作说明书都是windows下的,因为本人只有MBP,外加虚拟机Parallels Desktop无法识别SD卡,所以就直接参考Mac教程了. 1.系统镜像官网下载 推荐用Raspbi ...

  6. WIN7-修改域名

    前言:访问本地项目有如下的几种方式,其中通过修改域名配置文件的方式使用的较少,不过在某些项目中也会使用的到(比如:我曾经参与的一个项目使用到SpringCloud框架,需要将每个微服务注册到,服务控制 ...

  7. hbm.xml 详解总结

    转自 http://blog.csdn.net/tuke_tuke/article/details/49717991 一.hibernate映射文件的作用: Hibernate映射文件是Hiberna ...

  8. C++学习基础十一——子类对象向父类对象的转化

    一.C++中可以实现子类向父类的转换,主要分为三种形式: 1.对象转换:不能实现动态绑定,即不能实现多态. 2.引用转换:动态绑定,实现多态. 3.指针转换:动态绑定,实现多态. 注意:一般不会出现父 ...

  9. excel 作图中次横坐标及次纵坐标的调试,以及excel自定义轴标签的步骤方法

    在工作中除了要做一些常用的图表之外,不时还会有一切奇怪图表的制作需求. 今天的内容主要记录的是如何对excle图表的次横坐标及次纵坐标进行调试,以及如何自定义调整轴标签 首先看下如何做次纵坐标,工作中 ...

  10. Unity已经学会的

    1.以MonoBehaviour为脚本的开发模式. 2.MonoBehaviour的大多数API. 3.动画系统大多数了解. 4.UI了解一些,能写UI. 5.Editor了解一些,能写Editor. ...