在C中使用自定义设置文件有哪些方法。
例如,我打算这样做。
假设我有文件settings.ext
,我想存储3个字符串参数
内。我要做的是:假设我的字符串参数最多
32字节长度,我将假设我的文件内的参数被存储
像这样(在二进制模式下):
32 byte 32 byte 32 byte
---------------------------------------------
| 1 param || 2 param || 3 param |
然后,如果我想要第二个字符串参数,我将从index:32开始读取32个字节, 再次以二进制模式。
我想我会为字符串参数分别创建单独的文件 int参数的文件(我将以类似的方式使用int参数)。
这听起来合理吗?
PS。我在一些嵌入式设备上进行编程
答案 0 :(得分:0)
我不会使用二进制文件来保存设置,我的头脑中有以下原因:
相反,我会使用纯文本配置文件,例如libconfig,没有理由重新发明轮子,特别是如果让它变得更糟; - )
答案 1 :(得分:0)
有一些标准库函数可以轻松解析简单的标记/值配置文件。阅读有关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 ...
//...
}
还有一些库可以使复杂的配置变得容易。