题目: INI文件操作库
INI文件就是扩展名为“ini”的文件。在Windows系统中,INI文件很多,最重要的就是“System.ini”、 “System32.ini”和“Win.ini”。该文件主要存放用户所做的选择以及系统的各种参数。用户可以通过修改INI文件,来改变应用程序和系统的很多配置。
首先,我们先来了解下INI文件的结构。INI文件是一种按照特定方式排列的文本文件。每一个INI文件构成都非常类似,由若干段落(section)组成。在每个段落下面,是若干个以单个单词开头的关键词(key)和一个等号,等号右边的就是关键字对应的值(value)。即一般形式如下:
[Section1]
KeyWord1 = Valuel
KeyWord2 = Value2
[gmy_p]
exist_p=0
linux_p=123
其中[gmy_p]为section;exist_p为key;0为key的值value。
在本题中我们假设INI文件的结构中没有section部分,即我们所定义的inifile文件结构如下:
Key1 = Valuel
Key2 = Value2
我们需要实现一个能对inifile文件进行读写操作的库。该库通过包含inifile.h来调用。读操作中需要将文件中每行的key值和其对应的value值读出;写操作中需要将给定的key和value值按照inifile文件的结构写入文件中。
下面给出inifile.h中函数原型
int load(char * filename); #装载正常返回0
int read(char * section, char * key, char * stored_value);
int write(char * section, char * key, char * value_write);
需要写的程序:
(1) 在inifile.c中实现三个函数
(2) 写一个示例程序,看看infile这个库能不能正常工作。
提示:
由于不知道inifile中有多少个section和多少个value,所以需要用到链表来存储。
#####main.c######### #include <stdio.h> #include <stdlib.h> #include <string.h> #include "inifile.h" int main(void) { int result; inifile_dest_t ifd; char *section, *key, *wvalue; char value[MAX_VALUE_LEN]; memset(&ifd, 0, sizeof(inifile_dest_t));//将ifd中前sizeof(inifile_dest_t)个字节用 0 替换并返回ifd 。 /* 加载ini文件 */ result = load_ini(&ifd, "system.ini"); if (result != 0) { } /* 显示ini文件内容 */ //show_inifile_info(&ifd); /* 读取ini文件key的值 */ memset(value, 0, MAX_VALUE_LEN); section = "drivers"; key = "timer"; result = read_ini(&ifd, section, key, value, MAX_VALUE_LEN); if (result != 0) { close_ini(&ifd); return -1; } printf("read inifile info: "); printf("section: %s ", section); printf("key : %s ", key); printf("value : %s ",value); /* 设置ini文件key的值 */ section = "drivers"; key = "timer"; wvalue = "qingtian"; result = write_ini(&ifd, section, key, wvalue); if (result != 0) { close_ini(&ifd); return -1; } printf("write inifile info: "); printf("section: %s ", section); printf("key : %s ", key); printf("value : %s ", wvalue); /* 关闭已经打开的ini文件,释放资源 */ close_ini(&ifd); return 0; }
################inifile.h############# #ifndef _INIFILE_H_ #define _INIFILE_H_ #define MAX_SECTION_LEN 128 /* 最大section长度 */ #define MAX_KEY_LEN 128 /* 最大kye长度 */ #define MAX_VALUE_LEN 128 /* 最大value长度 */ #define MAX_BUFFER_LEN 128 /* 最大缓冲区长度 */ #define TRUE 1 #define FALSE 0 typedef struct section_enty_s { char *section; /* section name */ char *key; /* key */ char *value; /* key value */ struct section_enty_s *next; } section_enty_t; typedef struct inifile_dest_s { char *filename; /* open ini file name */ struct section_enty_s *enty; } inifile_dest_t; /* 读取ini文件,把文件信息保存到文件描述符句柄中 */ extern int load_ini(inifile_dest_t *ifd, char *filename); /* 根据描述符句柄,读取key对应的值 */ extern int read_ini(inifile_dest_t *ifd, const char *section, const char *key, char *stored_value, int vlen); /* 设置对应key的value值 */ extern int write_ini(inifile_dest_t *ifd, const char *section, const char *key, char *value_write); /* 显示ini文件信息 */ extern void show_inifile_info(inifile_dest_t *ifd); /* 关闭ini文件, 如果句柄有执行过write操作,将对应的key的值写回到文件中 */ extern int close_ini(inifile_dest_t *ifd); #endif /* _INIFILE_H_ */
#################inifile.c###################
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "inifile.h" /* 释放section节点 */ static void free_sect_enty(section_enty_t *enty) { if (enty->section != NULL) { free(enty->section); } if (enty->key != NULL) { free(enty->key); } if (enty->value!= NULL) { free(enty->value); } free(enty); } /* 释放已经加载的ini文件 */ static void free_inifile_dest_enty(inifile_dest_t *ifd) { section_enty_t *tmp, *p; tmp = ifd->enty; while (tmp != NULL) { p = tmp->next; free_sect_enty(tmp); tmp = p; } } /* 显示ini文件内容信息 */ void show_inifile_info(inifile_dest_t *ifd) { section_enty_t *enty; if (ifd == NULL) { return; } printf("inifile name:%s ", ifd->filename); enty = ifd->enty; while (enty != NULL) { printf("section:%s ", enty->section); printf("key :%s ", enty->key); printf("value :%s ", enty->value); enty = enty->next; } } /* 往inifile句柄中添加一section节点 */ static void add_section_to_ifd(inifile_dest_t *ifd, section_enty_t *enty) { enty->next = ifd->enty; ifd->enty = enty; } /* 更新值到ini文件中 */ static int write_info_back_inifile(inifile_dest_t *ifd, section_enty_t *enty) { FILE *input, *output; char buf[MAX_BUFFER_LEN]; char *ch, *tmp, *tmp_file; int filename_len, wflags; /* 为临时文件添加"_tmp"文件名 */ filename_len = strlen(ifd->filename); tmp_file = (char *)malloc(filename_len + 5); //新建文件名为"system.ini_tmp",所以加4+1(结束符' ') if (tmp_file == NULL) { printf("no enough memory! "); } sprintf(tmp_file, "%s%s", ifd->filename, "_tmp"); //第一个参数是字符缓冲区,保存格式转换后的字符串;第二个是格式字符串 input = fopen(ifd->filename, "r"); //"r"模式下该文件必须存在 if (input == NULL) { return -1; } output = fopen(tmp_file, "w"); //"w"模式下若文件不存在则建立文件 if (output == NULL) { return -1; } while ((ch = fgets(buf, MAX_BUFFER_LEN, input)) != NULL) //失败或读到文件结尾时返回NULL { if (strstr(buf, enty->section) != NULL) //从字符串buf中查找是否有字符串enty->section,若有则返回enty->section在buf中的起始位置的指针,否则,返回NULL { wflags = 1; fprintf(output, "%s", buf); //int fprintf(FILE *stream,char *format,[argument]),其作用是格式化输出到一个流/文件中 continue; //fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件. f } if ( strstr(buf, enty->key) != NULL) { tmp = strchr(buf, '='); //对比函数strstr if (tmp != NULL) { tmp++; strcpy(tmp, enty->value); wflags = 0; fprintf(output, "%s ", buf); continue; } } fprintf(output, "%s", buf); } fclose(input); fclose(output); /* 修改临时文件名 */ (void)remove(ifd->filename); //int remove(const char *filename),删除一个文件 (void)rename(tmp_file, ifd->filename); //int rename(char *oldname, char *newname);给一个文件重命名 free(tmp_file); return 0; } /** * load_ini - 读取ini文件,把文件信息保存到文件描述符句柄中 * @ifd : ini文件句柄描述符指针 * @filename: 文件名 */ int load_ini(inifile_dest_t *ifd, char *filename) { FILE *input; int buflen, sect_len; //sect_flag; char buf[MAX_BUFFER_LEN]; char sect[MAX_SECTION_LEN]; char *ch, *tmp; char *begin, *end; section_enty_t *enty; if (ifd == NULL || filename == NULL) { return -1; } /* 将文件名称保存到句柄中 */ ifd->filename = (char *)malloc(strlen(filename)); if (ifd->filename == NULL) { return -1; } strcpy(ifd->filename, filename); //extern char *strcpy(char* dest, const char *src) input = fopen(filename, "r"); if (input == NULL) { printf("open ini file error! "); return -1; } /* read a line from file buffer */ memset(buf, 0, MAX_BUFFER_LEN); memset(sect, 0, MAX_SECTION_LEN); //sect_len = sect_flag = 0; while ((ch = fgets(buf, MAX_BUFFER_LEN, input)) != NULL) //char *fgets(char *buf, int bufsize, FILE *stream); { begin = buf; /* 删除头部的空格 */ while(*begin == ' ') { begin++; } if (*begin == ' ' || *begin == ';') { continue; } tmp = strchr(buf, '['); //找字符串buf中首次出现字符'['的位置 if (tmp != NULL) { begin = tmp + 1; end = strchr(begin, ']'); if (end == NULL) { printf("the inifile is damaged! "); continue; } /* 拷贝字符串内容到sect数组 */ sect_len = end - begin; strncpy(sect, begin, sect_len);//复制begin中的前sect_len字节的内容到sect continue; } /* 处理key与对应的value字段 */ if ((tmp = strchr(buf, '=')) != NULL) { enty = (section_enty_t *)malloc(sizeof(section_enty_t)); if (enty == NULL) { printf("malloc section enty error! "); fclose(input); free_inifile_dest_enty(ifd); return -1; } enty->section = (char *)malloc(sect_len+1*sizeof(char));//section长度再加上结束符' ' if (enty->section == NULL) { printf("malloc section buffer error! "); free(enty); fclose(input); free_inifile_dest_enty(ifd); return -1; } strncpy(enty->section, sect, sect_len); *(enty->section+sect_len)='