0

What are some approaches to work with custom setting files in C.

For example, I plan to do it like this. Say I have file settings.ext and I want to store 3 string parameters inside. What I will do is: assuming my string parameters are at most 32 bytes length, I will assume that my parameters inside file are stored like this (in binary mode):

32 byte        32 byte        32 byte
---------------------------------------------
| 1 param     || 2 param     || 3 param     |

Then if I want second string parameter, I will read 32 bytes starting from index: 32, again in binary mode.

I think I will have separate file for string parameters and separate file for int parameters (I will work with int parameters in similar manner).

Does this sound reasonable?

ps. I am programming on some embedded device

4

2 回答 2

0

我不会使用二进制文件来保存设置,在我看来,不这样做的原因如下:

  1. 由于字节顺序等原因,它不是很便携。
  2. 它不是很容易扩展,您现在可能不需要任何额外的配置参数,但您可能稍后再做。
  3. 很难从其他程序中编辑和读取,很高兴能够使用脚本安装和配置您的软件。

相反,我会使用纯文本配置文件,例如libconfig,没有理由重新发明轮子,特别是如果让它变得更糟;-)

于 2013-11-01T07:26:23.833 回答
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 ...
//...
}

还有一些库可以使复杂的配置变得容易。

于 2013-11-01T07:26:37.217 回答