【发布时间】:2011-08-26 02:03:05
【问题描述】:
我正在自己工作 - 简单、简短、愚蠢 - 我将用于其他项目的 ini 库。我编写了一个 ini 解析器,到目前为止非常简单且有效,现在是时候进入更难的部分了 - 如何以及在何处存储来自 ini 文件的解析数据。
我想过使用简单的链表(可能是双链表),但我无法在脑海中想象它。
struct keys
{
char *keyname;
char *keyval;
unsigned long hashkey;
struct keys *next;
struct keys *prev;
}
struct ini
{
char *section;
struct keys *okeys;
unsigned long hashkey;
struct ini *next;
struct ini *prev;
}
首先,我想以这种方式编写代码,但我看起来有点愚蠢,而且不够有效,我知道有更好的方法将部分、键和键值存储在链表中,但我想不出任何方法.或者,也许我应该尝试使用其他数据结构?我不知道,以这种方式做一个ini库需要太多的功能,比如一个用于添加部分的单独功能,一个用于添加键等的功能。我真的很想弄清楚要使用什么,但我被卡住了。
这是我的简单 ini 解析器的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define BUFF_SIZE 1024
#define INI_FILE "config.ini"
#define ERROR_FILE "error.log"
void load_ini(const char *name);
void log_it(const char *filename, const char *format, ...);
void trim(char *str);
unsigned int hash(const char *key);
int main(int argc, char *argv[])
{
load_ini(INI_FILE);
return 0;
}
/*2. load ini function */
void load_ini(const char *name)
{
char *line = NULL;
char *p = NULL;
FILE *ifile = NULL;
ifile = fopen(name, "r");
if(ifile == NULL)
{
log_it(ERROR_FILE, "(load_ini) can't open %s file", name);
return;
}
line = malloc(BUFF_SIZE * sizeof(char) + 1);
if(line == NULL)
{
log_it(ERROR_FILE, "(load_ini) malloc fail");
return;
}
while(fgets(line, BUFF_SIZE+1, ifile) != NULL)
{
trim(line);
if(strlen(line) < 3 || *line == ';' || *line == '#')
{
continue;
}
if(*line == '[')
{
if(p = strchr(line, ']'))
{
*p = '\0';
trim(line+1);
/* add section here */
}
}
else if(p = strchr(line, '='))
{
*p = '\0';
trim(line);
trim(p+1);
/* add key, and key value here */
}
}
free(line);
fclose(ifile);
}
/* 3. multifunctional log function with variable number of arguments */
void log_it(const char *filename, const char *format, ...)
{
va_list arglist;
FILE *fp = NULL;
fp = fopen(filename,"a");
if(fp == NULL)
{
/* :) */
return;
}
va_start(arglist, format);
vfprintf (fp, format, arglist);
va_end (arglist);
fclose (fp);
}
/* 4. trim function */
void trim(char *str)
{
char *start = str;
char *end = start + strlen(str);
while (--end >= start)
{
if (!isspace(*end))
{
break;
}
}
*(++end) = '\0';
while (isspace(*start))
{
start++;
}
if (start != str)
{
memmove(str, start, end - start + 1);
}
}
/* Bernstein hash */
unsigned int hash(const char *key)
{
unsigned int hash = 5381;
unsigned int i = 0;
int len = strlen(key);
for(i; i < len; ++i)
{
hash = 33 * hash + key[i];
}
return hash ^ (hash >> 16);
}
【问题讨论】:
-
哈希表在我看来是个好主意:一个用于部分,每个部分都包含/指向另一个用于键/值对的哈希表。
标签: c parsing linked-list ini