2014-03-13 3 views
3

파일이 있습니다. 각 행을 읽고 토큰을 탭으로 배열에 저장하려고합니다. 그러나 토큰 [0] .. token [4]는 strtok()의 ​​결과 인 각 char의 주소를 가리키고 있습니다. 그래서 token [0] ... token [4]는 파일의 다음 줄에서 strtok을 호출 할 때마다 바뀝니다. 이 문제를 어떻게 해결합니까? char* tokens[MAX_SIZE] 대신 char tokens[MAX_SIZE]을 시도하면 strtok가 char *을 반환하기 때문에 변환 오류가 발생합니다.C 토큰 화 및 배열로 저장

파일은

20 34 90 10 77 

80 12 37 29 63 

45 21 55 18 46 

내 코드입니다 :

FILE *f; 
if ((f = fopen("myinput.txt","r")) == NULL) { 
    perror("Failed to open file:"); 
    return -1; 
} 
char * line; 
size_t len = 0; 
char *tokens[MAX_SIZE]; 
int i = 0; 
while (getline(&line, &len, f) !=-1) { 

    char* lineWithoutNullByte = strtok(line,"\n"); 
    tokens[i]=strtok(lineWithoutNullByte,"\t"); 
    i++; 
    int x = 1; 
    while (x){ 

       tokens[i] = strtok(NULL, "\t"); 
       if (tokens[i] == NULL){ 
        x=0; 
       }else{ 
        i++; 
       } 


    } 
    printf("test: %s %s %s %s %s\n", tokens[0],tokens[1],tokens[2],tokens[3],tokens[4]); 


} 

예상 출력

test: 20 34 90 10 77 
    test: 20 34 90 10 77 
    test: 20 34 90 10 77 

입니다하지만 점점 오전 :

test: 20 34 90 10 77 
    test: 80 12 37 29 63 
    test: 45 21 55 18 46 

는 명확히하기 : 이 의미, 내가 전체 tokens 배열을 인쇄하는 경우 당신은 당신이 제대로 strtok에서 얻을 토큰을 사용하지 않는

45 21 55 18 46 
45 21 55 18 46 
45 21 55 18 46 
+1

왜 첫 번째 줄이 세 번 반복 되길 기대합니까? 파일과 일치하는 내용이 있습니까? – dasblinkenlight

+0

두 번째 마지막 줄에 토큰 0 ~ 4 만 인쇄하고 있습니다. 문제가 무엇인지 알아 내려고했습니다. – Jean

+0

전체 토큰 배열을 인쇄하면 읽습니다. 45 21 55 18 46 45 21 55 18 46 45 21 55 18 46 – Jean

답변

3

, 나는 점점됩니다 : 당신이 반환 된 버퍼에서 온 얻을 토큰을 에 의해 getline. 첫 번째 호출은 새로운 버퍼를 제공합니다. 라인이 할당 된 공간에 맞기 때문에 후속 호출은 동일한 버퍼에 기록합니다.

버퍼에 포인터를 저장하면 다음 번에 새 데이터가있는 행이 이전 공간에 배치 될 때 해당 주소를 가리키는 모든 토큰이 새 데이터를 "보게"됩니다. 이 문제를 방지하려면, 당신은 strdup에게 전달하여 올바른 예를 들어, strtok에서 그들을 촬영 한 후 토큰을 복사해야합니다

char *tmp = strtok(NULL, "\t"); 
if (tmp == NULL) { 
    x = 0; 
    tokens[i] = NULL; 
} else { 
    i++; 
    tokens[i] = strdup(tmp); 
} 

당신은뿐만 아니라 strdup에 첫 번째 토큰을해야합니다.

참고 :이 방법을 사용하면 프로그램 완료 후 개별 토큰을 free해야합니다. 이 동시 환경에서 사용할 수 없습니다, 또는 문자열을 토큰 화하는 것을 의미

또한
free(line); 

, strtok 비 재진입 : 당신은 또한 외부 while 루프의 끝에서 getline에 의해 반환 된 버퍼를 확보해야 중첩 루프에서. 대신 strtok_r을 사용해야합니다.

+0

친애하는 각하, 고마워! 이제 그 이유를 이해합니다. 토큰을 복사하는 것이 전부였습니다! 나는 strtok_r에 대해 알게 될 것이다.대단히 감사합니다 – Jean

+0

strtok_r은 내가 잘못하지 않은 경우 표준이 아닙니다 – Dabo

+0

@Dabo Correct. 하지만 getline도 마찬가지입니다. – dasblinkenlight

0

strtok 대신 strtok_r을 사용해야합니다. 왜냐하면 strtok은 처음에는 효과적이기 때문입니다. 나는 이유를 모르지만 나는 한 번이 문제에 직면 해있다.