什么是使用设置的方法

时间:2013-11-01 07:08:20

标签: c

在C中使用自定义设置文件有哪些方法。

例如,我打算这样做。 假设我有文件settings.ext,我想存储3个字符串参数 内。我要做的是:假设我的字符串参数最多 32字节长度,我将假设我的文件内的参数被存储 像这样(在二进制模式下):

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

然后,如果我想要第二个字符串参数,我将从index:32开始读取32个字节, 再次以二进制模式。

我想我会为字符串参数分别创建单独的文件 int参数的文件(我将以类似的方式使用int参数)。

这听起来合理吗?

PS。我在一些嵌入式设备上进行编程

2 个答案:

答案 0 :(得分:0)

我不会使用二进制文件来保存设置,我的头脑中有以下原因:

  1. 由于字节序等原因,它不是很便携。
  2. 扩展起来并不是一件容易的事,你现在可能不需要任何额外的配置参数,但是你可以稍后再做。
  3. 很难编辑和阅读其他程序,能够使用脚本安装和配置软件是件好事。
  4. 相反,我会使用纯文本配置文件,例如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 ...
//...
}

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