c语言实现配置文件的读写

配置文件的格式如下:

key1 = value1

key2 = value2

  .

  .

  .

名值对以一个=链接,一条记录以换行符分割

头文件:

#include<stdio.h>
#include<stdlib.h>
#include <string.h>

函数原型:

复制代码
void trim(char *strIn, char *strOut);//去除字符串首位空格void getValue(char * keyAndValue, char * key, char * value);
//根据key得到valueint writeCFG(const char *filename/*in*/, const char *key/*in*/, const char *value/*in*/);
//写入配置文件void readCFG(const char *filename/*in*/, const char *key/*in*/, const char **value/*out*/);
//读取配置文件
复制代码

函数实现:

复制代码
  1 void trim(char *strIn, char *strOut){
  2 
  3     char *start, *end, *temp;//定义去除空格后字符串的头尾指针和遍历指针
  4 
  5     temp = strIn;
  6 
  7     while (*temp == ' '){
  8         ++temp;
  9     }
 10 
 11     start = temp; //求得头指针
 12 
 13     temp = strIn + strlen(strIn) - 1; //得到原字符串最后一个字符的指针(不是'\0')
 14 
 15     while (*temp == ' '){
 16         --temp;
 17     }
 18 
 19     end = temp; //求得尾指针
 20 
 21 
 22     for(strIn = start; strIn <= end; ){
 23         *strOut++ = *strIn++;
 24     }
 25 
 26     *strOut = '\0';
 27 }
 28 
 29 void getValue(char * keyAndValue, char * key, char * value){
 30 
 31     char *p = keyAndValue;
 32 
 33     p = strstr(keyAndValue, key);
 34     if(p == NULL){
 35         //printf("没有key\n");
 36         return ;
 37     }
 38 
 39     p += strlen(key);
 40     trim(p, value);
 41 
 42     p = strstr(value, "=");
 43     if(p == NULL){
 44         printf("没有=\n");
 45         return;
 46     }
 47     p+= strlen("=");
 48     trim(p, value);
 49 
 50     p = strstr(value, "=");
 51     if(p != NULL){
 52         printf("多余的=\n");
 53         return;
 54     }
 55     p = value;
 56     trim(p, value);
 57 
 58 }
 59 int writeCFG(const char *filename/*in*/, const char *key/*in*/, const char *value/*in*/){
 60 
 61     FILE *pf = NULL;
 62     char ftemp[flen] = {0}, fline[1024] = {0}, *fp;    //文件缓存数组
 63     long fsize = 0;
 64     int reg = 0;
 65     int exit = 0;
 66     int i = 0;
 67 
 68     pf = fopen(filename, "r+");
 69     if(pf == NULL){
 70         pf = fopen(filename, "w+");
 71     }
 72     //获得文件大小
 73     fseek(pf, 0, SEEK_END); // 将文件指针指向末尾
 74     fsize = ftell(pf);
 75     if(fsize > flen){
 76         printf("文件不能超过8k\n");
 77         reg = -1;
 78         goto end;
 79     }
 80     fseek(pf, 0, SEEK_SET); //将文件指针指向开头
 81 
 82     //一行一行的读,如果存在key则修改value存到缓存数组中
 83     while(!feof(pf)){
 84         fgets(fline, 1024, pf);
 85         if(strstr(fline, key) != NULL && exit == 1)
 86             strcpy(fline, "");
 87         if(strstr(fline, key) != NULL && exit == 0){ //判断key是否存在
 88             exit = 1;
 89             sprintf(fline,"%s = %s\n", key, value);
 90         }
 91         
 92         printf("fline = %s\n", fline);
 93         strcat(ftemp, fline);
 94         
 95     }
 96     if(exit != 1){//如果不存在则把key value写入到最后一行
 97         sprintf(fline,"%s = %s\n", key, value);
 98         strcat(ftemp, fline);
 99     }
100     if(pf != NULL){
101         fclose(pf);
102         pf = fopen(filename, "w+");
103         fp = (char *)malloc(sizeof(char) * strlen(ftemp) + 1);
104         strcpy(fp, ftemp);
105         fp[strlen(fp) - 1] = EOF;
106         fputs(fp, pf);
107         if(fp != NULL){
108             free(fp);
109             fp = NULL;
110         }
111         fclose(pf);
112     }
113     end :
114         if(pf != NULL)
115             fclose(pf);
116     //重新创建一个以filename命名的文件
117     return reg;
118 }
119 
120 void readCFG(const char *filename/*in*/, const char *key/*in*/, const char **value/*out*/){
121 
122     FILE *pf = NULL;
123     char line[1024] = {0}, vtemp[1024] = {0};
124 
125     pf = fopen(filename, "r"); //以只读方式打开
126     
127     while(!feof(pf)){
128         fgets(line, 1024, pf);
129         getValue(line, key, vtemp);
130         if(strlen(vtemp) != 0)
131             break;
132     }
133     if(strlen(vtemp) != 0){
134         *value = (char *)malloc(sizeof(char) * strlen(vtemp) + 1);
135         strcpy(*value, vtemp);
136     }    
137     else
138         *value = NULL;
139     if(pf != NULL)
140         fclose(pf);
141 }
复制代码

测试:

复制代码
 1 #define filename "c:/cfg.ini"
 2 void menu(){
 3     printf("===========================\n");
 4     printf("1 写入配置文件\n");
 5     printf("2 读取配置文件\n");
 6     printf("0 退出程序");
 7     printf("===========================\n");
 8 }
 9 
10 int tWrite(){
11     
12     char key[1024] = {0}, value[1024] = {0};
13 
14     printf("请输入key:");
15     scanf("%s", key);
16     printf("请输入value:");
17     scanf("%s", value);
18     printf("\n您输入的是:%s = %s\n", key, value);
19 
20     return writeCFG(filename/*in*/,key/*in*/,value/*in*/);
21 }
22 
23 void tRead(){
24     char key[1024] = {0}, *value;
25 
26     printf("请输入key:");
27     scanf("%s", key);
28 
29     readCFG(filename/*in*/,key/*in*/, &value/*out*/);
30     if(value == NULL){
31         printf("没有key\n");
32         return ;
33     }
34     printf("\nvalue = %s\n", value);
35 
36     if(value != NULL){
37         free(value);
38         value = NULL;
39     }
40 
41 }
42 int main(){
43     
44     int choose;
45     
46     while(1){
47         choose = 0;
48         menu();
49         printf("请输入选择:");
50         scanf("%d", &choose);
51         switch(choose){
52             case 1:
53                 if(tWrite() == -1)
54                     return -1;
55                 break;
56             case 2:
57                 tRead();
58                 break;
59             case 0:
60                 return 0;
61             default: 
62                 return 0;
63         }
64     }
65     system("pause");
66     return 0;
67 }
复制代码

运行结果:

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

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

相关文章

数据链路层: HDLC

一. 协议机 发送方和接收方. 同时有限状态机把协议形式化为一个四元组 (S,M,I,T), 其中你S表示进程和信道可能进入的集合, M 表示数据帧的状态, I 表示进程的初始状态, T 表示两两状态之间的转化. 每个系统状态可以分为发送状态, 接受状态和信道状态. 把状态用一个点进行表示,…

bob-tong 字符串函数之Strtok()函数

https://www.cnblogs.com/Bob-tong/p/6610806.html Strtok()函数详解&#xff1a; 该函数包含在"string.h"头文件中 函数原型&#xff1a; char* strtok (char* str,constchar* delimiters ); 函数功能&#xff1a;   切割字符串&#xff0c;将str切分成一个个子…

数据链路层:SLIP(串型线路IP) PPP(点对点协议)

SLIP 没有差错控制, 传输时必须知道对方IP, 传输使用于低速业务 19.2k.应用非常受限 PPP协议 1. PPP协议功能 处理错误检测 支持多协议(IP, IPX, DECnet 等) 连接时允许协商 IP 地址 允许身份验证 2. PPP 的组成 串型链路上封装数据报, 即支持异步链路也支持面向 比特…

strpbrk函数

http://blog.csdn.net/tommy_wxie/article/details/7554332 函数原型&#xff1a;extern char *strpbrk(char *str1, char *str2) 参数说明&#xff1a;str1待比较的字符串&#xff0c;str2为指定被搜索的字符串。 所在库名&#xff1a;#include <string.h> …

网络层网络层服务及其 IP 地址

ARP 协议功能 将 IP 地址通过广播(一个网段, 不能跨路由器), 目标 MAC 地址是FFFFFFFF 解析目标IP地址的 MAC 地址. IP 协议 网络层的一个协议, 是一个协议的统称, 包括 ARP(地址解析协议) 协议, ICMP(网络控制报文协议) 协议, IGMP(网际组管理协议) 协议. 其中 ICMP 和 IG…

传输层:IP 地址解析 路由转发

IP 地址与硬件地址 1. 地址解析 通过IP地址将其如何转换为 MAC 地址.解决同一个局域网上的主机或路由的 IP 地址和硬件地址的映射问题. 即以太网上除了主机还有路由. 即如果发出的请求所有的主机都没有做出相应, 那么该以太网上的路由会对其做出响应. (1) 以太网内部主机与…

网络层:构成超网(CIDR)

CIDR构成超网 CIDR消除了原来的传统的 A,B, C, D类地址, 使用了各种网络前缀来代替原来分类地址中的网络号和子网号, IP 地址由原来的三级分类又变成了两级分类. 其中网络号和子网号是一个随机的长度. 其中 CIDR 也可以使用 / 的形式来表示, 其中在 / 前面写上网络前缀的位数.…

网络层:网关协议

一. 网关 所谓的网管即就是之前路由器的名字, 即路由器和网关是一个东西 二. 内部网关协议 1. RIP协议 路由信息协议 RIP 是内部网关协议 IGP中最先得到的广泛使用的协议. 同时 RIP 是一种分布式基于距离向量的路由选择协议. RIP 协议要求网络中的每一个路由都必须维护自己…

网络基础: 浅析应用层一

应用层 1. http协议 在 http 中协议分为了协议方案名, 登录信息名, 服务器地址, 服务器端口号(http协议绑定的端口号), 文件类型, 查询的字符串, 片段标识位 2. http 请求协议格式 httpp 总共分为三大部分, 其中首行即就是第一部分, 分为三个区域, 第一去个区域是请方法, 第…

socket 编程篇六之IPO多路复用-select poll epoll

http://blog.csdn.net/woxiaohahaa/article/details/51498951 文章参考自&#xff1a;http://blog.csdn.net/tennysonsky/article/details/45745887&#xff08;秋叶原 — Mike VS 麦克《Linux系统编程——I/O多路复用select、poll、epoll的区别使用》&#xff09; 此外&#x…

浅谈传输层

1. 传输层的作用 在传输层中有两个特别重要的协议 TCP/UDP . 以快递员送快递为例说明这个问题吧. 在进行包裹传输的过程中快递员需要根据快递上的目的地址(目的计算机)来投递包裹(IP数据报), 加入在快递单上只写了收件人的所在地, 所在单位, 而只写了收件人的姓没有写收件人的…

I/O复用的 select poll和epoll的简单实现

http://www.cnblogs.com/wj9012/p/3876734.html 一个tcp的客户端服务器程序 服务器端不变&#xff0c;客户端通过I/O复用轮询键盘输入与socket输入&#xff08;接收客户端的信息&#xff09; 服务器端&#xff1a; 1 /*服务器:2 1.客户端关闭后&#xff0c;服务器再向客户端发送…

TCP相关代码

TCP 基础代码 //tcp_server.c #include<stdio.h> #include<error.h> #include<sys/types.h> #include<string.h> #include<unistd.h> #include<sys/socket.h> #include<netinet/in.h> #include <arpa/inet.h> #include<st…

几种并发服务器模型的实现:多线程,多进程,select,poll,epoll

http://www.cnblogs.com/wj9012/p/3879605.html 客户端使用select模型&#xff1a; 1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <errno.h>5 #include <sys/types.h>6 #include <sys/socket.h>7 #include …

linux进程通信---几个发送信号的函数(kill,raise,alarm,pause)

http://blog.csdn.net/zzyoucan/article/details/9235685 信号&#xff1a;信号是unix中最古老的进程通信的一种方式&#xff0c;他是软件层次上对中断机制的模拟&#xff0c;是一种异步通信方式&#xff0c;信号可以实现用户空间进程和内核空间进程的交互&#xff0c;内核进程…

Linux epoll模型

http://www.cnblogs.com/venow/archive/2012/11/30/2790031.html 定义&#xff1a; epoll是Linux内核为处理大批句柄而作改进的poll&#xff0c;是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著的减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利…

Linux IO模式及 select、poll、epoll详解

https://segmentfault.com/a/1190000003063859 同步IO和异步IO&#xff0c;阻塞IO和非阻塞IO分别是什么&#xff0c;到底有什么区别&#xff1f;不同的人在不同的上下文下给出的答案是不同的。所以先限定一下本文的上下文。 本文讨论的背景是Linux环境下的network IO。一 概念…

mysql思维导图

后期会不断进行更新

C++第一节课

C数据类型 几个概念 命名空间是C标准库引入的,其中命名空间可以解决变量冲突问题,当出现局部变量和全局变量同名的时候, 局部变量优先被访问.同时命名空间的格式如同一下代码 namespace name1 { int a 0; }namespace name2 { int a 2; } 注意C中的所有组件都是在一个叫做s…

【C/C++】关键字static

http://blog.csdn.net/woxiaohahaa/article/details/51014224 参考自&#xff1a;http://www.cnblogs.com/biyeymyhjob/archive/2012/07/19/2598815.html &#xff08;华山大师兄&#xff09; 这里我们只讨论了C语言的static 首先我们回顾一下各种变量在内存中的位置&#xff1…