2013-11-01 4 views
0

C에서 사용자 설정 파일을 사용하는 방법은 무엇입니까?설정을 사용하는 방법은 무엇입니까

예를 들어, 다음과 같이 할 계획입니다. 파일에 settings.ext이 있고 3 개의 문자열 매개 변수 을 저장하고 싶다고합시다. 내가 뭘 할 것은 : 내가 두 번째 문자열을 원하는 경우 다음

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

: 내 문자열 매개 변수가 가장 32 바이트 길이에, 나는 파일 안에 내 매개 변수 (바이너리 모드)이 같은 를 저장한다고 가정 할 수 있습니다 가정 매개 변수에서 색인 : 32, 에서 다시 시작하여 32 바이트를 이진 모드로 읽습니다.

문자열 매개 변수에 별도의 파일이 있고 int 매개 변수에 대해 파일을 분리한다고 생각합니다 (비슷한 방식으로 int 매개 변수로 작업 할 것입니다).

합리적인 소리가 들립니까?

ps. 나는

+2

나의 팁은 설정을위한 바이너리 파일을 가지지 않는 것입니다. 'key1 = value1'과 같은 간단한 텍스트 형식을 별도의 줄에 사용하십시오. 문자열이 32 문자 (또는 터미네이터도 저장하는 경우 31 자) *를 초과하지 않기 때문에 * 앞으로 더 오래 원할 경우 어떻게 될지 생각해보십시오. –

+0

@ JoachimPileborg : 당신이 의미하는 바를 봅니다. 그러나 나는 장래에 더 긴 것들이 필요할 것 같지 않다. 게다가 바이너리 파일을 읽고 쓰는 편이 편합니다. 또한 텍스트 모드에서 글을 읽었을 지 모르겠다는 SDK도 있습니다. 이진 접근법을 고수 할 것만 같은 우려가 있다면 –

+0

그건 아주 나쁜 플랫폼 설명입니다. 이미 당신이 제안한 것을하기 위해 마음을 굳힌 것처럼 보입니다. 그리고 당신의 접근 방식에는 아무런 문제가 없습니다. 그것은 당신이 원하는 것을 할 수있는 가장 효율적인 방법은 아닙니다. – jbr

답변

0

난 내 머리 위로의, 저장 설정에 대한 바이너리 파일을 사용하지 않을 일부 임베디드 디바이스에 프로그래밍하고 다음과 같은 이유가있다 없다로 :

  1. 이 때문에 엔디안 매우 휴대용 아니다
  2. 확장하기 쉽지는 않지만 지금 당장 추가 구성 매개 변수가 필요하지는 않지만 나중에 할 수 있습니다.
  3. 다른 프로그램에서 편집하고 읽을 수 없으므로 스크립트로 소프트웨어를 설치하고 구성하는 것이 좋습니다.

대신 나는 일반 텍스트 구성 파일을 사용하고, 뭔가 libconfig처럼, 그것은 표준 라이브러리의 몇 ;-)

+0

이 응용 프로그램과 함께 이식성이 필요하지 않습니다. 연장하는 것이 왜 문제가 되는가? 문제는 개별 매개 변수의 길이가 변경된 경우 (J Pileborg 언급 된 바와 같이)하지만 내 경우에도 이러한 오류가 발생할지 의심 스럽다. –

+0

구성하기 위해 실제로는 세 개의 문자열 만 필요하면 대신 매개 변수로 전달하십시오. 그렇지 않으면 소프트웨어가 개발자가 기대하는 것보다 오래 살아야하기 때문에 libconfig를 사용하는 것이 더 쉽습니다. 따라서 처음부터 좋은 선택을 할 수도 있습니다. – jbr

+0

매개 변수로 전달한다는 것은 무엇을 의미합니까? 일부 장치에서 프로그래밍 중이며 임베디드 장치에 라이브러리를 설치하는 데 "신경 쓰지 않아도됩니다. 실제로 문자열 매개 변수와 int를 아마도 두어 가지게 될 것입니다. (그리고 어떻게 저장하고 싶은지 설명했습니다.) –

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); 

, 매우 간단합니다. 그리고 여기에 a가있다

main(int argc, char* argv[]) 
{ 
//... 
char configname[200]; 
strcpy(configname,"yourconfigfilename.cfg"); 
cfgparse(configname); //of course, you need a ConfigStoreObj ... 
//... 
} 

그리고 복잡한 구성을 쉽게하는 라이브러리가있다.

+0

나는 언급하지는 않았지만 SDK가있는 일부 장치에서 프로그래밍 중이며 텍스트 모드에서 쓰기 작업을 읽었는지 확실하지 않습니다. 따라서 제가 언급 한 접근법에 큰 오류가 없다면, 저는 그것에 충실해야한다고 생각합니다. –

+0

당신이 설명하는 것과 같은 제한된 환경에서 접근 방법은 합리적입니다. 필자는 다른 시스템에서 읽고 쓰는 구조체를 사용하여 모든 것을 구성한 시스템에서 작업했습니다. 우리는 구성 구조체를 작성한 프로그램 (텍스트와 바이너리)과 수신 시스템이 파일을 메모리로 읽어 들이기 만했습니다. 두 시스템 모두 빅 엔디 언 (big-endian) 이었으므로 바이트 순서 문제는 발생하지 않았습니다. – ChuckCottrill

+0

구성이 다른 시스템에서 읽혀 져야 할 때 실제로 흥미로운 부분이 있습니다. 설정을 구조체로 작성한 다음 endiannes 문제가 적용되고 패딩 등이 올바르게 적용될 수 있습니까? 하지만 제 경우에는 실제로 제한된 환경이라고 말했고이 설정 파일을 다른 시스템으로 보낼 필요가 없을 수도 있습니다. –

관련 문제