있습니다 악화, 특히, 바퀴를 재발견 할 이유가없는 것 간단한 태그/값 구성 파일을 쉽게 구문 분석 할 수있는 함수. 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);
, 매우 간단합니다. 그리고 여기에 a가있다
main(int argc, char* argv[])
{
//...
char configname[200];
strcpy(configname,"yourconfigfilename.cfg");
cfgparse(configname); //of course, you need a ConfigStoreObj ...
//...
}
그리고 복잡한 구성을 쉽게하는 라이브러리가있다.
나의 팁은 설정을위한 바이너리 파일을 가지지 않는 것입니다. 'key1 = value1'과 같은 간단한 텍스트 형식을 별도의 줄에 사용하십시오. 문자열이 32 문자 (또는 터미네이터도 저장하는 경우 31 자) *를 초과하지 않기 때문에 * 앞으로 더 오래 원할 경우 어떻게 될지 생각해보십시오. –
@ JoachimPileborg : 당신이 의미하는 바를 봅니다. 그러나 나는 장래에 더 긴 것들이 필요할 것 같지 않다. 게다가 바이너리 파일을 읽고 쓰는 편이 편합니다. 또한 텍스트 모드에서 글을 읽었을 지 모르겠다는 SDK도 있습니다. 이진 접근법을 고수 할 것만 같은 우려가 있다면 –
그건 아주 나쁜 플랫폼 설명입니다. 이미 당신이 제안한 것을하기 위해 마음을 굳힌 것처럼 보입니다. 그리고 당신의 접근 방식에는 아무런 문제가 없습니다. 그것은 당신이 원하는 것을 할 수있는 가장 효율적인 방법은 아닙니다. – jbr