在很多项目中,我们会遇到这样的问题:程序中有很多硬编码,当这些硬编码需要换成另一种数据或者字符串时,我们必须的去修改源代码,这造成了很大的不方便。而如果这些硬编码能不通过修改源代码而起到相应的作用时,给我们代码的维护和观赏性得到大大的改观。解决这样的办法当然是有很多种。
此前工作的内容是应用C++在linux下编程,当初的MySQL的用户名、密码、端口、IP都是通过读取配置文件来加载的,当修改密码和端口时,不用去修改程序,只需重启下程序就OK了,一直觉得C++中类和map的存在使这样的方法很容易的实现了,在C语言中不存在这类和map,所以对于这种数据结构上只能用链表来完成。最近新换了一份工作,趁着在项目的前期准备的一点时间做个读取配置信息的程序为以后做准备。
本程序只是简单的应用了下,希望看到这篇文章和代码的前辈们能指点指点。代码中本来打算是用两个结构体来实现的,但是想到一般的配置文件的信息并不是很大,所以就选择了一个结构体。当放在惜寸如金的嵌入式中的时候,最好还是能将一个结构体改为两个结构体为好。
代码如下,本人是应届毕业生,这篇博客为我的嵌入式工程师工作的开始,还请前辈们多多指教。
#include "fileHandle.h"
int main(int argc, char **argv)
{
char *fileName = NULL;
char *value = NULL;
int nameLen = 0;
if (argc > 0)
{
printf("%s\n", argv[0]);
nameLen = strlen(argv[0]);
fileName = malloc(nameLen+5);
memset(fileName, 0, nameLen+5);
strcat(stpcpy(fileName, argv[0]), ".ini");
printf("%s\n", fileName);
if(fileInit(fileName) < 0)
{
printf("file init error \n");
return 0;
}
value = get_value("sdf", "sdfd");
printf("value==%s\n", value);
}
free_link();
return 0;
}
/*********************************************************
读取配置文件内容
配置文件的格式为
[title] []内没有空格字符限制在20以内
key=value key字符限制在20以内 value在50以内
Build in 2014.07.10
*********************************************************/
#include "fileHandle.h"
NODE *L_head = NULL;
/*************************************************
Function: 初始化文件 文件内容的读出
Input: char *fileName 路径下的文件 文件名称需和执行文件名一致 且在同一路径下
Return: 0 succeed -1 failed
*************************************************/
int fileInit(char *fileName)
{
FILE *fp = NULL;
long nFileSize = 0;
char *szContent = NULL;
fp = fopen(fileName, "rb+");
if(fp == NULL)
{
printf("fopen failed\n");
return -1;
}
fseek(fp, 0, SEEK_END);
nFileSize = ftell(fp);
rewind(fp);
szContent = malloc(nFileSize+1);
if(szContent == NULL)
{
printf("malloc failed\n");
fclose(fp);
fp = NULL;
return -1;
}
fread(szContent, nFileSize, 1, fp);
fclose(fp);
fp = NULL;
if(fileStrtok(szContent) < 0)
return -1;
return 0;
}
/*************************************************
Function: 处理配置文件内容
Input: char *content 文件内容
Return: 0 succeed -1 failed
*************************************************/
int fileStrtok(char *content)
{
char *szTemp = NULL;
char szBuf[TITLE_SIZE];
char szTitle[TITLE_SIZE];
char szKey[KEY_SIZE];
char szValue[VALUE_SIZE];
NODE *L_new = NULL;
szTemp = strtok(content, "\n");
while(szTemp)
{
memset(szBuf, 0, sizeof(szBuf));
memset(szKey, 0, sizeof(szKey));
memset(szValue, 0, sizeof(szValue));
sscanf(szTemp, "[%s", szBuf);
if(strlen(szBuf) != 0)
{
memset(szTitle, 0, sizeof(szTitle));
stpcpy(szTitle, szBuf);
szTitle[strlen(szBuf)-1] = 0;
}
else
{
sscanf(szTemp, "%[^=, ]=%[^=, ]", szKey, szValue);
if(strlen(szKey) != 0 && strlen(szValue) != 0)
{
L_new = (NODE *)malloc(NODE_SIZE);
L_new->title = malloc(strlen(szTitle)+1);
L_new->key = malloc(strlen(szKey)+1);
L_new->value = malloc(strlen(szValue)+1);
if(L_new == NULL ||
L_new->title == NULL ||
L_new->key == NULL ||
L_new->value == NULL)
{
printf("malloc failed\n");
return -1;
}
stpcpy(L_new->title, szTitle);
stpcpy(L_new->key, szKey);
stpcpy(L_new->value, szValue);
L_head = insert_link(L_new);
}
}
szTemp = strtok(NULL, "\n");
}
return 0;
}
/*************************************************
Function: 提取内容加入链表
Input: NODE *L_new 内容结构体
Return: NODE* (可有可无)
*************************************************/
NODE *insert_link(NODE *L_new)
{
NODE *L_mov = NULL;
NODE *L_Tem = NULL;
L_mov = L_head;
if(L_head == NULL)
{
L_head = L_new;
L_new->next = NULL;
return L_head;
}
while(L_mov->next)
{
L_mov = L_mov->next;
}
L_mov->next = L_new;
L_new->next = NULL;
return L_head;
}
/*************************************************
Function: 打印链表信息
Input:
Return:
*************************************************/
void print_link()
{
NODE *L_mov = NULL;
L_mov = L_head;
while(L_mov)
{
printf("title == %s key == %s value == %s\n", L_mov->title, L_mov->key, L_mov->value);
L_mov = L_mov->next;
}
}
/*************************************************
Function: 释放链表申请的空间
Input:
Return:
*************************************************/
void free_link()
{
NODE *L_mov = NULL;
L_mov = L_head;
while(L_mov)
{
L_head = L_head->next;
free(L_mov->title);
free(L_mov->key);
free(L_mov->value);
free(L_mov);
L_mov = L_head;
}
}
/*************************************************
Function: 获取key对应下的值
Input: char *title, char *key
Return: 找到返回value 没找到返回""
*************************************************/
char *get_value(char *title, char *key)
{
NODE *L_mov = NULL;
L_mov = L_head;
while(L_mov)
{
if(strcmp(L_mov->title, title)==0 && strcmp(L_mov->key, key)==0)
return L_mov->value;
L_mov = L_mov->next;
}
return "";
}
/*********************************************************
读取配置文件内容
配置文件的格式为
[title] []内没有空格字符限制在20以内
key=value key字符限制在20以内 value在50以内
Build in 2014.07.10
*********************************************************/
#ifndef __FILE__H
#define __FILE__H
#include
#include
#include
#define NODE_SIZE sizeof(NODE)
#define TITLE_SIZE 20 //目标名大小
#define KEY_SIZE 20 //关键字大小
#define VALUE_SIZE 50 //内容大小
typedef struct Config
{
char *title;
char *key;
char *value;
struct Config *next;
}NODE;
NODE *L_head;
//配置文件插入链表
extern NODE *insert_link(NODE *L_new);
//释放申请的空间
extern void free_link();
//打印链表信息
extern void print_link();
//获取配置文件指定的内容
extern char *get_value(char *title, char *key);
//文件获取
extern int fileInit(char *fileName);
//处理文件
extern int fileStrtok(char *content);
#endif