场景:C语言面向对象编程(6):配置文件解析

C语言面向对象编程(六):配置文件解析

在实际项目中,经常会把软件的某些选项写入配置文件。 Windows 平台上的 INI 文件格式简单易用,本篇文章利用《C语言面向对象编程(五):单链表实现》中实现的单链表,设计了一个“类” ini_parser 来读写 INI 格式的配置文件。

struct ini_parser 可以解析 INI 格式的字符串、文件,也可以将内存中的符合 INI 格式的数据写入文件,能够支持 Windows 、 Linux 、 Android 等多平台。目前暂不支持选项分组功能。

功能相对简单,直接看源码吧。

下面是头文件:

struct single_list;

struct ini_parser {

struct single_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);

void (*deletor)(struct ini_parser *ini);

};

struct ini_parser * new_ini_parser();    struct init_parser 的声明符合我们在本系列文章中提到的面向对象框架,需要说明的是,一旦 deletor 方法被调用, ini_parser 的实例将不再允许访问。

下面是源文件:

#include "ini_parser.h"

#include

#include

struct tag_value_pair{

struct slist_node node;

char * szTag;

char * szValue;

};

typedef struct tag_value_pair tag_value;

static void _tag_value_free(struct slist_node *node)

{

if(node) delete_tag_value_pair(node);

}

static int _tag_value_hittest(struct slist_node * node, void *key)

{

return strcmp((char*)tag, ((struct tag_value_pair*)node)->szTag);

}

static struct single_list * new_tag_value_list()

{

return new_single_list(_tag_value_free, _tag_value_hittest);

}

static struct tag_value_pair *new_tag_value_pair()

{

struct tag_value_pair * pair = (struct tag_value_pair *)malloc(sizeof(struct tag_value_pair));

pair->node.next = 0;

pair->szTag = 0;

pair->szValue = 0;

return pair;

}

static struct tag_value_pair * make_tag_value_pair(char * tag, char * value)

{

struct tag_value_pair *pair = 0;

if(!tag || !value)return 0;

pair = (struct tag_value_pair*)malloc(sizeof(struct tag_value_pair));

pair->szTag = strdup(tag);

pair->szValue = strdup(value);

pair->node.next = 0;

return pair;

}

static struct tag_value_pair * parse_line(char *line, int len)

{

struct tag_value_pair * pair = 0;

int count = 0;

char * p = line;

char * end = 0;m

char * start = line;

if(!p) return 0;

while(*p == ' ') ++p;

/*blank line*/

if(p - line == len ||

*p == '\r' ||

*p == '\n' ||

*p == '\0') return 0;

/*do not support group*/

if(*p == '[') return 0;

/*comments*/

if(*p == '#') return 0;

/* extract key */

start = p;

end = line + len;

while(*p != '=' && p!= end) ++p;

if(p == end)

{

/* none '=' , invalid line */

return 0;

}

end = p - 1;

while(*end == ' ') --end; /* skip blank at the end */

count = end - start + 1;

pair = new_tag_value_pair();

pair->szTag = malloc(count + 1);

strncpy(pair->szTag, start, count);

pair->szTag[count] = 0;

/* 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 0;

}

start = p;

--end; /* to the last char */

if(*end == '\n') { *end = 0; --end; }

if(*end == '\r') { *end = 0; --end; }

count = end - start + 1;

if(count > 0)

{

pair->szValue = malloc(count + 1);

strncpy(pair->szValue, start, count);

pair->szValue[count] = 0;

}

/* release empty key-value pair */

if(!pair->szValue)

{

delete_tag_value_pair(pair);

return 0;

}

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 = 0;

char buf[1024] = {0};

while(fgets(buf, 1024, fp))

{

pair = parse_line(buf, strlen(buf));

if(pair)

{

ini->keyvalues->add(ini->keyvalues, pair);

}

}

fclose(fp);

return ini->keyvalues->size;

}

return -1;

}

static int _parse_text(struct ini_parser * ini, const char * text){

char *p = text;

char * start = 0;

struct tag_value_pair * pair = 0;

if(!text) return -1;

while(1)

{

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 = NODE_T(ini->keyvalues->find_by_key(ini->keyvalues, key), struct tag_value_pair);

if(pair) return pair->szValue;

return 0;

}

static void _set_value(struct ini_parser * ini, const char * key, const char *value){

struct tag_value_pair * pair = NODE_T(ini->keyvalues->find_by_key(ini->keyvalues, key), struct tag_value_pair);

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 = NODE_T(ini->keyvalues->find_by_key(ini->keyvalues, key), struct tag_value_pair);

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 > 0)

{

FILE * fp = fopen(file, "w");

if(fp)

{

struct tag_value_pair * pair = NODE_T(ini->keyvalues->head,struct tag_value_pair);

while(pair != 0)

{

write_keyvalue(pair, fp);

pair = NODE_T(pair->node.next, struct tag_value_pair);

}

fclose(fp);

return 0;

}

}

return -1;

}

static void _delete_ini_parser(struct ini_parser *ini){

if(ini)

{

ini->keyvalues->deletor(ini->keyvalues);

free(ini);

}

}

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;

ini->deletor = _delete_ini_parser;

return ini;

}    下面是简单的测试代码:

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 > 0);

assert( ini->value(ini, "second") == 0 );

assert( ini->value(ini, "abc") == 0);

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");

ini->deletor(ini);

}

static void ini_parser_test_file()

{

struct ini_parser * ini = new_ini_parser();

int size = ini->parse_file(ini, "test.conf");

assert( size > 0);

assert( ini->value(ini, "second") == 0 );

assert( ini->value(ini, "abc") == 0);

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"));

ini->deletor(ini);

}

void ini_parser_test()

{

ini_parser_test_string();

ini_parser_test_file();

}

struct ini_parser 已经运用在实际的项目中,目前为止没发现什么问题。

c语言面向对象编程显示,c语言面向对象编程相关推荐

  1. c语言程序设计年历显示,C语言程序设计报告《万年历》.doc

    . .. <"万年历"> -C语言程序设计报告 专 业: 计算机科学与技术 班 级: 姓 名: 指导教师: 年月 日 目录 TOC \o "1-1" ...

  2. c语言程序设计年历显示,C语言程序设计万年历

    满意答案 沙漠风暴X 2013.09.05 采纳率:48%    等级:12 已帮助:7244人 #include int leap (int year) {if(year%4==0&& ...

  3. 【Golang第8章:面向对象编程】Go语言的结构体是什么,怎么声明;Golang方法的调用和声明;go语言面向对象实例,go语言工厂模式;golang面向对象的三大特性:继承、封装、多态

    介绍 这个是在B站上看边看视频边做的笔记,这一章是Glang面向对象编程 这一章内容较多,内容有Go语言的结构体是什么,怎么声明:Golang方法的调用和声明:go语言面向对象实例,go语言工厂模式: ...

  4. 用java有理数类包含加减乘除,7.1 面向对象的简介 - VimL 语言编程指北路

    面向对象是一种编程思想,并不特指某种编程语言.所以不必惊讶用 VimL 也能以面向 对象的方式来写代码.本章先简单介绍一下面向对象的编程思想,再探讨如何利用 VimL 现有的特性实现面向对象编程.最后 ...

  5. plc和c语言谁的前景好,PLC面向对象编程和梯形图逻辑,到底谁更实用一些?

    在工业自动化领域,梯形图逻辑仍然是最常用的编程语言之一,但对于更加复杂的控制对象,面向对象编程不失为一种高效率的方式.下面先来谈谈面向对象编程: 面向对象编程是计算机高级语言的一种先进的编程模式,在工 ...

  6. 黑马程序员——OC语言------类的声明实现、面向对象

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 面向对象 一.面向对象的思想 C语言是面向过程,OC是面向对象,那么什么是面向对象呢?面向对象和 ...

  7. 笔记整理3----Java语言高级(三)11 综合练习+12 面向对象-static变量 与 代码块+13 面向对象-继承与抽象类+14 面向对象-接口与多态+15 面向对象-包修饰符

    11 综合练习+12 面向对象-static变量 与 代码块+13 面向对象-继承与抽象类+14 面向对象-接口与多态+15 面向对象-包&修饰符 第11天 综合练习 今日内容介绍 综合练习 ...

  8. c语言使用node类型指针,C语言利用 void 类型指针实现面向对象类概念与抽象

    不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...

  9. 殷人昆 数据结构(用面向对象方法与C++语言描述)(第二版)实现汇总(持续更新)

    殷人昆 数据结构(用面向对象方法与C++语言描述)(第二版)实现汇总 殷人昆 数据结构(用面向对象方法与C++语言描述)(第二版)实现汇总 第二章 线性表 第二章 线性表 约瑟夫问题(线性表实现)约瑟 ...

最新文章

  1. nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战
  2. .net安装部署中添加卸载程序简单方法
  3. 关于Pac-Man,你所要了解的 一切
  4. w3c html5 客户端缓存数据格式,Html5应用程序缓存(Cache manifest)
  5. Python GUI界面编程初步 05- GUI框架PyQt的运用 - 02 PyQt的信号和槽例子
  6. 66. 编写高效的 JavaScript
  7. 最有效的Safari的广告拦截插件
  8. ListView 优化
  9. 腾讯信鸽推送(一):服务端架构
  10. 计算机视觉-OpenCV入门讲解
  11. 【巷子】---fetch---基本使用
  12. 智能体温计APP方案开发
  13. ruoyi框架分页总条数total返回错误解决方案
  14. background-clip和background-origin
  15. 正本清源!!!!!!:HWDB1.1数据集.gnt转换成.png
  16. 微信小程序“this.setdata is not a function”
  17. UE4 /UE5 PC/安卓优化
  18. wpf datagrid设置右键菜单打开时选中项的背景色
  19. python多重继承初始化顺序_Python 多重继承顺序
  20. QTextStream格式带中文对齐输出问题

热门文章

  1. Zhong__k8s基础尝试和配置flannel
  2. R语言基于lm模型构建线性回归模型(蟋蟀的鸣叫声与温度的关系)、计算回归模型的RMSE指标、计算回归模型的R方指标(R-squared)
  3. NotFoundError:Tensor name incept5b_1/... not found in checkpoint files /home/cqh2/...
  4. 路由器分出ITV与网络信号资料
  5. 在Excel中批量生成条形码,支持Code128、Code39、Jan13等等格式
  6. 房产证.房屋他项权证.车辆登记证.报到证.企业资质等图片展览.
  7. 谷歌浏览器,无需安装
  8. switch、break与continue的用法
  9. oracle 版本演进,【比较】Oracle不同版本中关于ALTER TABLESPACE的功能演进
  10. iOS开发之数据存取