有几个标准库函数可以轻松解析简单的标签/值配置文件。阅读有关 strtok 和 atoi/atof 的信息,您可能会发现像这样的简单配置文件很容易解析。您可以在配置中混合字符串和数值,并支持更长的字符串。
name1=value1
name2=value2
name3=value3
...
这样做的好处是,它既易于人类阅读/编辑,又可由相当简单的配置解析器解析。并且传递一个文件名来读取使得它相当独立。
int
cfgparse(char *cfgname)
{
FILE* cfgfh;
if(!cfgname) return -1;
if( !(cfgfh=fopen(cfgname,"r")) ) {
printf("error: cannot open %s\n",cfgname);
return -2;
}
char buffer[256]; //pick an acceptable max size
while( fgets(buffer,sizeof(buffer),cfgfh) )
{
//check for comments, empty lines
char* tag = strtok(buffer,"=");
char* val = strtok(NULL,";\n");
//strip leading/trailing whitespace, handle empty lines,
//do something with tag, value here
Cfgadd(tag,value);
}
}
您可以在数组中实现简单的配置存储。列表将是动态的,而树或散列将提高性能。
#define MaxKeyLen (200)
#define MaxValLen (200)
typedef struct
{
char* key; //a array would work here
char* value; //a union would allow string, int, and float
} ConfigObj;
#define CONFIGMAX (200)
const int ConfigMax=CONFIGMAX;
typedef struct
{
ConfigObj tab[CONFIGMAX]; //or make this a pointer or a list
int NextAvail;
} ConfigStoreObj;
ConfigStoreObj cfg; //or make this a pointer or a list
static int ConfigFind(ConfigStoreObj* cfg, char* key)
{
int n;
for( n=0; (n<cfg->NextAvail) && (cfg->tab[n].key); n++ )
{
if( strcmp(cfg->tab[n].key,key)==0 ) //found it
{
return n;
}
}
return -1;
}
const char* ConfigGet(ConfigStoreObj* cfg, char* key)
{
int n = ConfigFind(cfg,key);
if( n<0 ) return NULL; //or ""?
return cfg->tab[n].value;
}
int ConfigSet(ConfigStoreObj* cfg, char* key, char* value)
{
char* newvalue;
int n=ConfigFind(cfg,key);
if( n<0 ) return -1; //error
printf("dup(%s)\n",value); fflush(stdout);
if( !(newvalue = strndup(value,MaxValLen)) ) {
printf("error, cannot store %s:%s\n",key,value);
return -3;
}
{
if(cfg->tab[n].value) free(cfg->tab[n].value);
cfg->tab[n].value = newvalue;
}
//return cfg->tab[n].value;
return n;
}
int ConfigAdd(ConfigStoreObj* cfg, char*key, char*value)
{
char *newkey=NULL, *newvalue=NULL;
int n = ConfigFind(cfg,key);
if( n<0 )
{
if( n<ConfigMax )
{
n = cfg->NextAvail++;
printf("dup(%s)\n",key); fflush(stdout);
if( !(newkey = strndup(key,MaxKeyLen)) ) {
printf("error, cannot store %s:%s\n",key,value);
return -3;
}
}
else return -1;
}
printf("dup(%s)\n",value); fflush(stdout);
if( !(newvalue = strndup(value,MaxValLen)) ) {
printf("error, cannot store %s:%s\n",key,value);
if(newkey) free(newkey);
return -3;
}
{
if(cfg->tab[n].value) free(cfg->tab[n].value);
cfg->tab[n].value = newvalue;
}
//return cfg->tab[n].value;
return n;
}
你可能还想,
ConfigStoreObj* ConfigStoreNew(int size);
char* ConfigDel(ConfigStoreObj* cfg, char*key);
int ConfigPrint(ConfigStoreObj* cfg);
打开一个配置文件进行读取是相当容易的,如上所示。这是一个
main(int argc, char* argv[])
{
//...
char configname[200];
strcpy(configname,"yourconfigfilename.cfg");
cfgparse(configname); //of course, you need a ConfigStoreObj ...
//...
}
还有一些库可以使复杂的配置变得容易。