用C语言实现解析简单配置文件的小工具

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

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

 

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

工具的源代码贴在这里:

 

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

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

 

 

 

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

转载于:https://www.cnblogs.com/pengkunfan/p/3486604.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Delphi应用程序在命令行下带参数执行返回命令行提示的问题

在命令行模式&#xff08;CMD&#xff09;下执行时&#xff0c;想获得执行参数&#xff0c;用以下变量&#xff1a; ParamCount&#xff1a;参数个数 ParamStr&#xff1a;为参数数组 如果想在执行完一个操作后在命令行作出相应提示&#xff0c;就应该在相应位置放入…

开源的负载测试/压力测试工具 NBomber

负载测试和压力测试对于确保 web 应用的性能和可缩放性非常重要。尽管它们的某些测试是相同的&#xff0c;但目标不同。负载测试&#xff1a;测试应用是否可以在特定情况下处理指定的用户负载&#xff0c;同时仍满足响应目标。应用在正常状态下运行。压力测试&#xff1a;在极端…

人生失败的31种致命原因

人生失败的31种致命原因 一、不利的遗传背景。天生智力不足的人&#xff0c;是没什么办法可想的。唯一的补救办法就是“以勤补拙”。 二、缺乏明确的人生目标&#xff0c;凡是没有明确人生目标的人&#xff0c;便没有成功的希望&#xff0c;在我曾经分析过的100人中&#x…

男人都应该懂的一张图。。 | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅美国人为了教民众如何辨别韩国人制作的韩国女性标准照左右军事成为一个有钱人的概率有多高&#xff1f;最新版男人都该懂的汽车品牌从属关系图twi:NOCO_1002肥胖和骨架没有必然联系800斤胖子的X射线照 科普君XueShu 雪树来猜一猜这是…

python 抓取的网页默认是bytes的,要转码

python 抓取的网页默认是bytes的,要转码.查看网页源码可以看到,我本次抓取的网页的编码方式是utf-8的.req urllib.request.Request(urlmyurl,headers myheaders) data urllib.request.urlopen(req).read() print(data.decode("UTF-8"))这样就正常显示中文了转载于…

FireFox与IE的兼容

1. JavaScript对象的引用 为了减少JavaScript对象的下载次数&#xff0c;Tasian只会在浏览器第一次请求应用时才会下载JavaScript文件。JavaScript对象只会驻留在Top级窗体&#xff0c;任何其它窗体需要引用到该JavaScript对象&#xff0c;只需要在引如下的方式进行引用就行&am…

多语言应用开发中本地化信息对照表

多语言应用开发中本地化信息对照表。包含区域编号、本地化名称、英语名称、中文名称、国家地区码、语言代码和流通币种等。区域编号本地化名称英语名称中文名称国家地区语言流通币种排序id-idBahasa IndonesiaIndonesian印度尼西亚语IDidIDR1ms-myBahasa MelayuMalay (Malaysia…

学做菜咯

以前在QQ空间发的贴&#xff0c;现在转到这边来&#xff0c;嘿嘿。青蛙达 - 07月28日- 14时28分今天中午做我个人最喜欢的菜之一《咖喱鸡饭》 早上到超市买了&#xff1a; 大蒜头、洋葱、南瓜、鸡翅膀、咖喱粉、胡椒粉、白糖、桂皮 回来发现原来把辣椒粉当成胡椒粉买回来了....…

java一般方法有哪些方法有哪些方法_Java代码优化有哪些方法?

Java代码优化是Java编程开发很重要的一个步骤&#xff0c;Java代码优化要注重细节优化&#xff0c;一个两个的细节的优化&#xff0c;产生的效果不大&#xff0c;但是如果处处都能注意代码优化&#xff0c;对代码减少体积、提高代码运行效率是有巨大帮助的&#xff0c;还能在一…

Facebook 中国程序员之死

全世界只有3.14 % 的人关注了青少年数学之旅9 月 19 日&#xff0c;一位 Facebook 软件工程师从加州门洛帕克&#xff08;Menlo Park&#xff09;总部四楼纵身跳下&#xff0c;结束年轻的生命。Facebook 新闻发言人证实确有其事&#xff0c;并说公司将会联系员工家人。门洛帕克…

HTTP头信息

通常 HTTP 消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的消息体组成。HTTP 的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域…

[导入]数据库物理模型设计的其他模式之继承模式

连载之7原创&#xff1a;胖子刘&#xff08;转载请注明作者和出处&#xff0c;谢谢&#xff09;数据库物理模型设计的其他模式除了上面提到的四种主要设计模式&#xff0c;还有一些其他模式&#xff0c;在某些项目中可能会用到&#xff0c;在这里先简单做个说明&#xff0c;暂不…

最近ゲームにはまってる。

小D的[今日口语]栏目里今天教的一句话正好表达了我最近的状态最近&#xff08;さいきん&#xff09;ゲームにはまってる&#xff08;最近我很迷游戏&#xff09;这个“迷”字用得很对感觉自己现在还是孩子状态会沉溺于一种东西而无法自拔周末的时候一般都是游戏完累了才有心情去…

dialog element 删掉标题_ElementUI 销毁Dialog数据(简单粗暴)

在使用element开发通过之中使用Dialog弹窗创建数据或者数据回显在经常不过了。而且数据创建和数据编辑正常都是使用同一组件。出现的问题&#xff1a;title"提示弹窗":visible.sync"dialogVisible"width"30%"destroy-on-close>使用dialog 提供…

一个简单的方式搞定密码的加盐哈希与验证

过去一段时间来, 众多的网站遭遇用户密码数据库泄露事件。层出不穷的类似事件对用户会造成巨大的影响&#xff0c;因为人们往往习惯在不同网站使用相同的密码&#xff0c;一家 “暴库”&#xff0c;全部遭殃。单向加密一个简单的方案是将明文密码做单向哈希后存储。单向哈希算法…

“我数学太烂,但高考136分!”刷完上万道题后,我找到2个月多考58分的捷径…...

全世界只有3.14 %的人关注了青少年数学之旅01难上天的高考试卷&#xff0c;我逆袭考到136分&#xff01;我叫刘辉&#xff0c;来自湖北省的某个县城&#xff0c;今年我数学考到了136分的好成绩&#xff0c;成功被一所985高校录取。↓我的高考成绩↓但回想一年之前&#xff0c;我…

php吞了throw错误,PHP 异常与错误处理

异常处理&#xff1a;意外&#xff0c;是在程序运行过程中发生的意料之外的事&#xff0c;使用异常改变脚本正常流程。try{}catch(异常对象){}如果try中代码没问题&#xff0c;则执行完try中代码后就到catch后执行如果try中代码有异常发生&#xff0c;则抛出一个异常对象&#…

[Forward] 因为火炬,所以迟到,工资照扣

今天跟往常一样,到香蜜湖等230 看到深南大道主道那边站了一名JC叔叔 在前面的主辅岔道口看到有交J叔叔...对面又大堵车...心想大事不妙..又要交通管制了......两hui期间因为交通管制让我第一个月上班就来了一次迟到 这时候是8点钟多一点开始管制.....很后悔没有上到最后一…

三分钟总览微软任务并行库TPL

点击上方蓝字进行关注有小伙伴问我每天忽悠的TPL是什么&#xff1f;☹️ 这次站位高一点&#xff0c;严肃讲一讲。引言俗话说&#xff0c;不想开飞机的程序员不是一名好爸爸&#xff1b;作为微软技术栈的老鸟&#xff0c;一直将代码整洁之道奉为经典&#xff0c; 优秀的程序员将…

第五章 MyEclipse配置hadoop开发环境

1.首先要下载相应的hadoop版本的插件&#xff0c;我这里就给2个例子&#xff1a; hadoop-1.2.1插件&#xff1a;http://download.csdn.net/download/hanyongan300/6238153 hadoop2.2.0插件&#xff1a;http://blog.csdn.net/twlkyao/article/details/17334693 上一章我也讲了怎…