本文介绍作者写的一个小工具,简单的代码中包含了C语言对字符串的处理技巧,对文本文件的简单解析,二进制文件的数据复制的方法,以及格式化输出文本文件的示例。

工具的输入是如下内容的配置文件:

  1. ;资源管理器配置脚本
  2. ;以行为单位,每行不能超过255个字符
  3. ;空行和以;开头的注释行会被忽略掉
  4. ;每行都关联一个资源文件,资源序号从0开始,依次递增
  5. .\img\img128x128.bin
  6. .\snd\start.wav
  7. .\img\sheis1.bin
  8. .\snd\balloon.wav
  9. .\img\sheis2.bin

工具的源代码贴在这里:

  1. #include <ctype.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. /* 定义相关文件名 */
  6. #define CONFIG_FILE_NAME        ("config.txt")
  7. #define RESPAK_FILE_NAME        ("resmm.bin")
  8. #define ADDRS_C_FILE_NAME       ("resmm_addrs.c")
  9. /* 定义配置行最大的字符数 */
  10. #define LINE_CHARS      (255)
  11. /* 定义复制文件数据时的缓冲区大小 */
  12. #define BUF_SIZE        (8 * 1024)
  13. /* 从配置行提取文件名 */
  14. static char* extract_file_name(const char* line, char* file_name)
  15. {
  16. /* 过滤配置行左边的空格符 */
  17. while(isspace(*line++)){};
  18. line--;
  19. /* 忽略空行和注释行 */
  20. if((*line == '\0') || (*line == ';'))
  21. return NULL;
  22. /* 提取文件名,并去掉右边的空格符 */
  23. strcpy(file_name, line);
  24. {
  25. char* p = file_name + strlen(file_name) - 1;
  26. while(isspace(*p--)){};
  27. p++;
  28. p++;
  29. *p = '\0';
  30. }
  31. return file_name;
  32. }
  33. /* 扫描有效文件数 */
  34. static int scan_file_count(FILE* cf)
  35. {
  36. char line[LINE_CHARS + 1];
  37. char file_name[LINE_CHARS + 1];
  38. int count = 0;
  39. while(!feof(cf))
  40. {
  41. fgets(line, LINE_CHARS, cf);
  42. if(extract_file_name(line, file_name) != NULL)
  43. count++;
  44. }
  45. return count;
  46. }
  47. /* 复制文件数据 */
  48. static size_t copy_file_datas(FILE* pf, FILE* rf)
  49. {
  50. unsigned char buf[BUF_SIZE];
  51. size_t total = 0;
  52. size_t len;
  53. do{
  54. len = fread(buf, sizeof(unsigned char), BUF_SIZE, rf);
  55. fwrite(buf, sizeof(unsigned char), len, pf);
  56. total += len;
  57. }while(len == BUF_SIZE);
  58. return total;
  59. }
  60. /* 主函数 */
  61. int main(int argc, char* argv[])
  62. {
  63. FILE* cf;
  64. FILE* pf;
  65. FILE* rf;
  66. int count;
  67. size_t* lens;
  68. size_t len;
  69. unsigned int addr;
  70. char line[LINE_CHARS + 1];
  71. char file_name[LINE_CHARS + 1];
  72. int i;
  73. /* 打开配置文件,并扫描有效文件数 */
  74. if((cf = fopen(CONFIG_FILE_NAME, "rt")) == NULL)
  75. {
  76. printf("Can\'t open %s!\n", CONFIG_FILE_NAME);
  77. return -1;
  78. }
  79. count = scan_file_count(cf);
  80. fseek(cf, 0L, SEEK_SET);
  81. /* 打开资源包文件 */
  82. if((pf = fopen(RESPAK_FILE_NAME, "wb")) == NULL)
  83. {
  84. printf("Can\'t create %s!\n", RESPAK_FILE_NAME);
  85. fclose(cf);
  86. return -1;
  87. }
  88. /* 复制打包资源文件,并统计其大小 */
  89. if((lens = (size_t*)malloc(sizeof(size_t) * count)) == NULL)
  90. {
  91. printf("No enough memory!\n");
  92. fclose(pf);
  93. fclose(cf);
  94. return -1;
  95. }
  96. i = 0;
  97. while(!feof(cf))
  98. {
  99. fgets(line, LINE_CHARS, cf);
  100. if(extract_file_name(line, file_name) != NULL)
  101. {
  102. if((rf = fopen(file_name, "rb")) == NULL)
  103. {
  104. printf("Can\'t open %s!\n", file_name);
  105. fclose(pf);
  106. fclose(cf);
  107. return -1;
  108. }
  109. if((len = copy_file_datas(pf, rf)) == 0)
  110. {
  111. printf("File %s is empty!\n", file_name);
  112. fclose(pf);
  113. fclose(cf);
  114. return -1;
  115. }
  116. lens[i++] = len;
  117. fclose(rf);
  118. }
  119. }
  120. fclose(pf);
  121. fclose(cf);
  122. /* 打开地址描述的C语言源文件 */
  123. if((cf = fopen(ADDRS_C_FILE_NAME, "wt")) == NULL)
  124. {
  125. printf("Can\'t open %s!\n", ADDRS_C_FILE_NAME);
  126. return -1;
  127. }
  128. /* 把各个资源的地址和长度信息写入C语言数组 */
  129. fprintf(cf, "#define RES_COUNT\t(%d)\n\n", count);
  130. fprintf(cf, "static const INT32U addrs[RES_COUNT] = \n{\n");
  131. addr = 0;
  132. for(i = 0; i < count; i++)
  133. {
  134. fprintf(cf, "\t\t0x%08x,\n", addr);
  135. addr += lens[i];
  136. }
  137. fprintf(cf, "};\n\n");
  138. fprintf(cf, "static const INT32U lens[RES_COUNT] = \n{\n");
  139. for(i = 0; i < count; i++)
  140. fprintf(cf, "\t\t0x%08x,\n", lens[i]);
  141. fprintf(cf, "};");
  142. fclose(cf);
  143. free(lens);
  144. return 0;
  145. }

格式化输出的文本文件是这样的:

  1. #define RES_COUNT   (5)
  2. static const INT32U addrs[RES_COUNT] =
  3. {
  4. 0x00000000,
  5. 0x00008000,
  6. 0x0000889a,
  7. 0x0001089a,
  8. 0x0001219a,
  9. };
  10. static const INT32U lens[RES_COUNT] =
  11. {
  12. 0x00008000,
  13. 0x0000089a,
  14. 0x00008000,
  15. 0x00001900,
  16. 0x00008000,
  17. };

用C语言实现解析简单配置文件的小工具的更多相关文章

  1. marked插件在线实时解析markdown的web小工具

    访问地址: https://mdrush.herokuapp.com/ github项目: https://github.com/qcer/MDRush 实现简介: 1.动态数据绑定 借助Vuejs, ...

  2. 简单的mongo小工具 python

    #!/bin/python #coding=utf-8 ### eg : mgotool.py -i 127.0.0.1 -p 10001 -a xxxxx -u root -rc #import s ...

  3. R语言:用简单的文本处理方法优化我们的读书体验

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html 前言 延续之前的用R语言读琅琊榜小说,继续讲一下利用R语言做一些简单的文本处理.分词的事情.其实 ...

  4. [C语言]声明解析器cdecl修改版

    一.写在前面 K&R曾经在书中承认,"C语言声明的语法有时会带来严重的问题.".由于历史原因(BCPL语言只有唯一一个类型——二进制字),C语言声明的语法在各种合理的组合下 ...

  5. 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(1)

    1.前言与作者 首先声明,我是由于非常偶然的机会获得<C语言入门很简单>这本书的,绝对不是买的.买这种书实在丢不起那人. 去年这书刚出版时,在CU论坛举行试读推广,我当时随口说了几句(没说 ...

  6. 留念 C语言第一课简单的计算器制作

    留念 C语言第一课简单的计算器制作 学C语言这么久了.  /* 留念 C语言第一课简单的计算器制作 */   #include<stdio.h>  #include<stdlib.h ...

  7. 用C语言编写一个简单的词法分析程序

    问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...

  8. 用Go语言实现一个简单的聊天机器人

    一.介绍 目的:使用Go语言写一个简单的聊天机器人,复习整合Go语言的语法和基础知识. 软件环境:Go1.9,Goland 2018.1.5. 二.回顾 Go语言基本构成要素:标识符.关键字.字面量. ...

  9. Spring中 <context:property-placeholder 的使用与解析 .properties 配置文件的加载

    转: Spring中property-placeholder的使用与解析 Spring中property-placeholder的使用与解析 我们在基于spring开发应用的时候,一般都会将数据库的配 ...

随机推荐

  1. 机器学习(5): K-means 算法

    3. K-means 算法:        3.1 Clustering 中的经典算法,数据挖掘十大经典算法之一      3.2 算法接受参数 k :然后将事先输入的n个数据对象划分为 k个聚类以便 ...

  2. 为ubuntu添加多媒体以及flash等等常用包

    因为多媒体mp3,mp4以及flash等等都是一些有版权的东东,ubuntu不能直接集成到安装盘内,所以,做了2个常用包,来存放它们. ubuntu-restricted-addons ubuntu- ...

  3. Xilinx IP核的根目录地址,有datasheet 和仿真相关的资料

    C:\Xilinx\14.7\ISE_DS\ISE\coregen\ip\xilinx\dsp\com\xilinx\ip Xilinx IP核的根目录地址,有datasheet 和仿真相关的资料

  4. CF 366E - Dima and Magic Guitar 最远曼哈顿距离

    题目:http://codeforces.com/problemset/problem/366/E 事实上就是找 n * m 矩阵中数字 x 和 数字 y 的最远距离. 方法參照武森的论文<浅谈 ...

  5. qsort函数以及sort函数使用方法

     sort函数的使用方法 做ACM题的时候,排序是一种常常要用到的操作. 假设每次都自己写个冒泡之类的O(n^2)排序,不但程序easy超时,并且浪费宝贵的比赛时间,还非常有可能写错. STL里面 ...

  6. 可以动态增加系统的U盘启动器(基于grub)

    前言:最近面试无果,就在宿舍看那本<30天自制操作系统>,里面使用的系统文件格式是img,要在真机上运行,就需要使用U盘进行启动,因为现在都没有软盘.而网上很多都是用软件写入U盘的.反正我 ...

  7. linux io ports io memory

    http://m.blog.csdn.net/article/details?id=7204458

  8. flask celery 使用方法

    一.安装 由于celery4.0不支持window,如果在window上安装celery4.0将会出现下面的错误flask_clery 你现在只能安装pip install celery==3.1 二 ...

  9. .net 中异步SOCKET发送数据时碰到的内存问题

    做CS的开发一直都是这样的方式: server端用 C++编写,采用IOCP机制处理大量客户端连接.数据接收发送的问题 client端用 C++ 或C# 写,没什么特殊要求. 最近工作时间上比较宽裕, ...

  10. eclipse 项目中的java文件没有在WEB-INF目录下的classes中 生成相对应的编译后的类

    1.首先确定project->Build Automatically是否勾选上: 2.执行完第一步之后测试一下看是否能编译,如果还是不能,则进行手动编译:  3,进入clean对话框,选择Cle ...