现在的位置: 首页 > 综合 > 正文

C 添加, 读取配置文件 函数

2013年08月11日 ⁄ 综合 ⁄ 共 2755字 ⁄ 字号 评论关闭

发现读取配置文件, 还是用得比较多的. 网上搜了下, 有不少的代码范例了.

不过一般实现的函数需要传递的参数都有配置文件的路径.

个人认为在某些情况下参数传入 流 重用性更大一点.

本想基于流的参数将 读取, 添加, 删除, 修改 配置文件的函数全部实现. 但发现

删除 , 修改 需要重新打开流, 单纯传入一个流参数不能方便实现.

以下是读取, 添加 配置的函数实现.

"oper_config.h"

/*
 * author: dengzhaoqun
 * date	 : 2011/07/23
 */

#ifndef OPER_CONFIG_H_
#define OPER_CONFIG_H_

#define MAX_LINE_LEN 210

char *read_config(FILE *fp, char *key);
int add_config(FILE *fp, char *key, char *value);

#endif

"oper_config.c"

/*
 * author: dengzhaoqun
 * date  : 2011/07/22
 */

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

#include "oper_config.h"

static int check_key(char *line, char *key);
static char *get_value(char *line);


// fp 需要以读的方式得到
char *
read_config(FILE *fp, char *key)
{
	char line[MAX_LINE_LEN] = {'\0'};
	char *value = NULL;
	int ret;

	while(fgets( line, sizeof(line), fp) != NULL)
	{
		ret = check_key(line, key);
		if(ret == -1)
		{
			continue;
		}
		else
		{
			value = get_value(line);
			if(value == NULL)
			{
				del_config(fp, key);
				return NULL;
			}
			else
			{
				return value;
			}
		}
	}/* while */

	return NULL;
}


static int
check_key(char *line, char *key)
{
	char *k_start, *k_end;		// 指示 key 在 line 中的起始和结束位置
	int line_len;

	line_len = strlen(line);
	if(line_len < 3)
	{
		return(-1);
	}
	else
	{
		k_start = &line[0];
		while(((*k_start == ' ') || (*k_start == '\t'))
				&& ( k_start <= &line[line_len - 1]))
		{
			k_start ++;
		}

		if(*k_start == '#')
		{
			return(-1);
		}

		k_end = strchr(line, '=');
		if(k_end == NULL)
		{
			return(-1);
		}
		k_end --;
		while(((*k_end == ' ') || (*k_end == '\t'))
				&& (k_end >= k_start))
		{
			k_end --;
		}
		if((*k_end == ' ') || (*k_end == '\t'))
		{
			return(-1);
		}

		if(strncmp(key, k_start, k_end-k_start + 1) != 0)
		{
			return(-1);
		}
	}

	return(0);
}/* check_key() */


static char*
get_value(char *line)
{
	char *v_start, *v_end;		// 指示 value 在 line 中的起始和结束位置
	char *value = NULL;
	int line_len;
	int val_len;

	line_len = strlen(line);

	v_start = strchr(line, '=');	// 已经在 check_key 中检验过'='的存在
	v_start ++;
	while(((*v_start == ' ') || (*v_start == '\t'))
			&& (v_start <= &line[line_len - 1]))
	{
		v_start ++;
	}

	v_end = &line[line_len - 1];
	if(((*v_end == ' ') || (*v_end == '\t')
			|| (*v_end == '\n')
			|| (*v_end == '\r'))
			&& (v_end > v_start))
	{
		v_end --;
	}
	if((*v_end == ' ') || (*v_end == '\t')
			|| (*v_end == '\n')
			|| (*v_end == '\r'))
	{
		return NULL;
	}

	val_len = v_end - v_start + 1;
	value = (char *)malloc((val_len + 1) * sizeof(char));
	if(value == NULL)
	{
		printf("malloc failed.\n");
		return NULL;
	}
	strncpy(value, v_start, val_len);
	value[val_len] = '\0';
	return value;
}/* get_value() */


// fp 需要以添加的方式得到
int
add_config(FILE *fp, char *key, char *value)
{
	char *line = NULL;
	int key_len;
	int val_len;

	key_len = strlen(key);
	val_len = strlen(value);
	
	if( (fp == NULL) || (key == NULL) || (value == NULL))
	{
		return(-1);
	}

	line = (char *)malloc((key_len + val_len + 5) * sizeof(char));
	if(line == NULL)
	{
		printf("malloc failed.\n");
		return(-1);
	}
	else
	{
		strncpy(line, key, key_len);
		line[key_len] = ' ';
		line[key_len + 1] = '=';
		line[key_len + 2] = ' ';
		line[key_len + 3] = '\0';
		strncat(line, value, val_len);
		line[key_len + val_len + 3] = '\n';
		line[key_len + val_len + 4] = '\0';

		if(fputs(line, fp) == EOF)
		{
			return(-1);
		}
	}

	free(line);

	return(0);
}/* add_config() */
	

说明:

1)  配置文件的数据格式  key = value

2) 支持 '#' 开头注释

3) key, value 前后可有空格, tab.

基于路径的实现, 请参考 http://www.linuxidc.com/Linux/2011-03/33712.htm

抱歉!评论已关闭.