2013-09-22 3 views
0

줄 단위로 구성 파일을 읽고 tokenize하고 결과를 별도의 변수에 저장하려고합니다. 내 구성 파일과 같은 다음파일을 한 줄씩 읽고 C에서 strtok()를 사용하여

stage 1 
num_nodes 2 
nonce 234567 

내가 확인하는 데 사용되는 첫 번째 줄 "단계"의 예를 들어 내가 구성 파일에서 단계의 값을 읽을 경우, 그래서 별도로 라인에 각 값을 토큰 화하는 데 필요 그 값을 변수에 저장하십시오. 내 토큰 화가 올바로 작동하는 것 같습니다. 그러나 토큰 화 후에 변수를 조작하려고하면 세그먼트 오류가 발생합니다. 대부분 나는 변수 중 하나, 즉 스테이지 또는 num_node 또는 nonce 중 하나만 성공적으로 조작 할 수 있지만 그 조합은 성공적으로 조작 할 수 없습니다.

num_nodes = num_nodes + 1; 

다음 잘 작동 :

stage = stage + 1; 
num_nodes = num_nodes + 1; 

처럼 뭔가를하려고해도 난 그냥 같은 하나 개의 변수를 변경 한 경우이, 그러나, 세그먼트 오류를 ​​제공합니다. 아래에 코드를 붙여 넣고 있습니다. 친절하게도 내가 여기에없는 것을 말해줍니다.

main(int argc, char *argv[]){ 
    int nonce; 
    int num_nodes; 
    int stage; 
    char filename[256]; 
    char *token1, *token2, *str; 
    FILE* fp; 
    char bufr[MAXLINE]; 

    printf("Please enter config file name\n"); 
    scanf("%s",filename); 
    printf("You entered %s\n", filename); 

    if((fp = fopen(filename, "r")) != NULL){ 

     while(fgets(bufr, MAXLINE, fp) != NULL){ 
      if(bufr[0] == '#') // to skip comments 
       continue; 

      printf("This is bufr: %s", bufr); 
      str = bufr; 

       for(str; ;str = NULL){ 
       token1 = strtok(str, " "); 

       if(strcmp(token2, "num_nodes") == 0){ 
        num_nodes = atoi(token1); 
        printf("num_nodes = %d\n", num_nodes); 
       } 

       if(strcmp(token2, "nonce") == 0){ 
        nonce = atoi(token1); 
        printf("nonce = %d\n", nonce); 
       }  

       if(strcmp(token2, "stage") == 0){ 
        stage = atoi(token1); 
        printf("stage = %d\n", stage); 
       }     

       token2 = token1; // making a copy of pointer 

       if(str == NULL){ 
        break; 
       } 
      }//end of for loop 

     }//end of while loop 
     fclose(fp); //close the file handle 
    } 
    else{ 
     printf("failed, file not found!\n"); 
    } 

/*  This is where the segmentation fault kicks in, try to uncomment two lines and it will give a segmentation fault, if uncomment just one, then it works fine. 
    nonce = nonce + 2; 
    num_nodes = num_nodes + 1; 
    printf("stage = %d\n", stage); 
*/ 
} 

답변

2

코드는 포함

token1 = strtok(str, " "); 

if (strcmp(token2, "num_nodes") == 0){ 
    num_nodes = atoi(token1); 
    printf("num_nodes = %d\n", num_nodes); 
} 

당신은 단지 token1을 설정 한,하지만 당신은 token2을 비교하기 위해 진행? 이것은 최소한 token2이 설정되지 않았을 때 처음으로 코어 덤프로 이어질 가능성이 있습니다.

마지막으로 루프가 끝나면 핵심 덤프가있는 유일한 이유는 할당 된 메모리 범위를 벗어나 덤벼 들었다는 것입니다. 이유는 분명하지 않지만 루프 구조가 궁금 해서요.

여기에 정리 된 코드가 나와 있습니다. 원본은 너무 나쁘지 않았지만, 불확정 상태 인 token2은 걱정했습니다.

Please enter config file name 
You entered config.file 
This is bufr: # Comment 
This is bufr: 
This is bufr: stage 1 
token1 = <<stage>>; token2 = <<>> 
token1 = <<1 
>>; token2 = <<stage>> 
stage = 1 
This is bufr: num_nodes 2 
token1 = <<num_nodes>>; token2 = <<des>> 
token1 = <<2 
>>; token2 = <<num_nodes>> 
num_nodes = 2 
This is bufr: nonce 234567 
token1 = <<nonce>>; token2 = <<67 
>> 
token1 = <<234567 
>>; token2 = <<nonce>> 
nonce = 234567 
This is bufr: 
stage = 1 

공지 사항 token2의 왼쪽 오버 파편 : 출력의 한 버전 등의 정보가 포함되어 있습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

enum { MAXLINE = 4096 }; 

int main(void) 
{ 
    int nonce = -1; 
    int num_nodes = -1; 
    int stage = -1; 
    char filename[256]; 
    char *token1, *token2, *str; 
    FILE *fp; 
    char bufr[MAXLINE]; 

    printf("Please enter config file name\n"); 
    scanf("%s", filename); 
    printf("You entered %s\n", filename); 

    if ((fp = fopen(filename, "r")) == NULL) 
    { 
     printf("failed, file not found!\n"); 
     return(1); 
    } 

    while (fgets(bufr, MAXLINE, fp) != NULL) 
    { 
     printf("This is bufr: %s", bufr); 
     if (bufr[0] == '#' || bufr[0] == '\n') 
      continue; 

     token2 = ""; 
     for (str = bufr; (token1 = strtok(str, " \n\t")) != 0; str = NULL) 
     { 
      printf("token1 = <<%s>>; token2 = <<%s>>\n", token1, token2); 
      if (strcmp(token2, "num_nodes") == 0) { 
       num_nodes = atoi(token1); 
       printf("num_nodes = %d\n", num_nodes); 
      } 
      if (strcmp(token2, "nonce") == 0) { 
       nonce = atoi(token1); 
       printf("nonce = %d\n", nonce); 
      } 
      if (strcmp(token2, "stage") == 0) { 
       stage = atoi(token1); 
       printf("stage = %d\n", stage); 
      } 

      token2 = token1; 

      if (str == NULL) /* Terminate after name/value */ 
       break; 
     } 

    } 
    fclose(fp); 

    nonce = nonce + 2; 
    num_nodes = num_nodes + 1; 
    printf("stage = %d\n", stage); 
    printf("nonce = %d\n", nonce); 
    printf("nodes = %d\n", num_nodes); 

    return(0); 
} 

이 코드는 명령 줄을 사용하여 GCC 4.8.1와 맥 OS X 10.8.5에 깨끗하게 컴파일 : 나는 아래의 코드에 더 그것을 정리라는 입력 파일을 감안할 때

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition cfg.c -o cfg 

config.file하는 (끝에서 빈 라인)

# Comment 

stage 1 
num_nodes 2 
nonce 234567 
  

출력했다 :

,321 0
+0

: 여기

http://www.hyperrealm.com/libconfig/

당신은 예를 볼 수 있습니다 token1, 즉 token2 = token1이며 두 번째 반복에서 마지막 반복에서 읽은 토큰을 확인하고 그에 따라 변수를 업데이트하는 데 사용됩니다. –

+0

'token2'가 설정되어 있지 않을 때 걱정되는 첫 번째 반복문입니다. 나는 코드를 탐험 중이다. 지금 당장은 내가 가지고있는 버전이 많은 문제를 안고 있다고 말할 수있다. 그러나 토큰을 사용하기 전에'token2 = ""'를 설정한다. (초기화되지 않은 변수에 액세스하는 것은 재앙을위한 처방이다.) –

+0

그 점에 동의하십시오. –

1

야, libconfig를 사용하여 구성 파일을 읽을 수 있습니다. 이것을하기 위해 알고리즘을 작성하는 것보다 libconfig로 이것을하는 것이 더 쉽습니다.당신은 깨끗한 루프 구조에 대한 권리는 아니지만, 루프의 한 반복 후 나는의 복사본을 만들

http://simplestcodings.blogspot.com.br/2012/02/libconfig-to-read-configuration-files.html

+0

프로덕션 솔루션의 경우 libconfig 라이브러리가 더 나은 솔루션입니다. 그러나 연습 문제는 'strtok()'을 사용할 수 있습니까?'및 구성 파일을 읽는 것이 단순히 학습을 테스트하는 수단 일 수 있습니다. –