原文地址:https://www.cnblogs.com/fuxianfeng1988/p/3292282.html
题目: 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:\r\n");
printf("section: %s\r\n", section);
printf("key : %s\r\n", key);
printf("value : %s\r\n",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:\r\n");
printf("section: %s\r\n", section);
printf("key : %s\r\n", key);
printf("value : %s\r\n", 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\r\n", ifd->filename);
enty = ifd->enty;
while (enty != NULL) {
printf("section:%s\r\n", enty->section);
printf("key :%s\r\n", enty->key);
printf("value :%s\r\n", 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(结束符'\0')
if (tmp_file == NULL) {
printf("no enough memory!\r\n");
}
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\n", 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!\r\n");
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 == '\n' || *begin == ';')
{
continue;
}
tmp = strchr(buf, '['); //找字符串buf中首次出现字符'['的位置
if (tmp != NULL)
{
begin = tmp + 1;
end = strchr(begin, ']');
if (end == NULL)
{ printf("the inifile is damaged!\r\n");
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!\r\n");
fclose(input);
free_inifile_dest_enty(ifd);
return -1;
}
enty->section = (char *)malloc(sect_len+1*sizeof(char));//section长度再加上结束符'\0'
if (enty->section == NULL)
{
printf("malloc section buffer error!\r\n");
free(enty);
fclose(input);
free_inifile_dest_enty(ifd);
return -1;
}
strncpy(enty->section, sect, sect_len);
*(enty->section+sect_len)='\0';
/* 处理key内容 */
buflen = tmp - begin;
enty->key = (char *)malloc(buflen+1*sizeof(char));
if (enty->key == NULL)
{
printf("malloc key buffer error!\r\n");
free(enty->section);
free(enty);
fclose(input);
free_inifile_dest_enty(ifd);
return -1;
}
strncpy(enty->key, begin, buflen);
*(enty->key+buflen)='\0';
/* 处理value内容 */
end = tmp++;
while (*end != '\0' && *end != '\n')
{
end++;
}
buflen = end - tmp;
enty->value = (char *)malloc(buflen+1*sizeof(char));
if (enty->value == NULL)
{
printf("malloc value buffer error!\r\n");
free(enty->section);
free(enty->key);
free(enty);
fclose(input);
free_inifile_dest_enty(ifd);
return -1;
}
strncpy(enty->value, tmp, buflen);
*(enty->value+buflen)='\0';
/* 配置信息挂到inifile句柄中 */
add_section_to_ifd(ifd, enty);
}
}
fclose(input);
return 0;
}
/**
* read_ini - 根据描述符句柄,读取key对应的值
* @ifd : inifile句柄描述符
* @section: 段值
* @key : key值
* @stored_value: 存储ini文件中的key对应的值
* @vlen : 保存value值空间的长度
*/
int read_ini(inifile_dest_t *ifd, const char *section, const char *key, char *stored_value, int vlen)
{
section_enty_t *enty, *tmp;
if (ifd == NULL || section == NULL || key == NULL || stored_value == NULL) {
return -1;
}
tmp = ifd->enty;
while (tmp != NULL) {
enty = tmp;
if ((strcmp(enty->section, section) == 0) && (strcmp(enty->key, key) == 0))
{
strncpy(stored_value, enty->value, vlen);
break;
}
tmp = tmp->next;
}
return 0;
}
/**
* write_ini - 设置对应key的value值
* @ifd : inifile句柄描述符
* @section: 段值
* @key : key值
* @value_write: 设置key对应的值
*/
int write_ini(inifile_dest_t *ifd, const char *section, const char *key, char *value_write)
{
section_enty_t *enty, *tmp;
char *ch;
int vlen;
if (ifd == NULL || section == NULL || key == NULL || value_write == NULL) {
return -1;
}
tmp = ifd->enty;
while (tmp != NULL) {
enty = tmp;
if ((strcmp(enty->section, section) == 0) && (strcmp(enty->key, key) == 0)) {
vlen = strlen(value_write);
ch = (char *)malloc(vlen+1*sizeof(char));
if (ch == NULL) {
printf("malloc value error!\r\n");
return -1;
}
free(enty->value);
enty->value = ch;
strncpy(enty->value, value_write, vlen);
*(enty->value+vlen)='\0';
write_info_back_inifile(ifd, enty);
break;
}
tmp = tmp->next;
}
return 0;
}
/* 关闭ini文件, 如果句柄有执行过write操作,将对应的key的值写回到文件中 */
int close_ini(inifile_dest_t *ifd)
{
if (ifd == NULL) {
return -1;
}
free_inifile_dest_enty(ifd);
return 0;
}