2013-08-13 2 views
2

그래서 strtok() 등의 C 라이브러리 함수를 사용하지 않는 토큰 파서를 구현하려고하는데 액세스 위반과 관련된 몇 가지 문제가 있습니다. 그것은 못 박히지 않았다. 누군가 포인터를 제공 할 의사가 있습니까?C Token Parsing

int main(int argc, char* argv[]) 
{ 
    int maxTokens = 10; 
    char* tokens[10]; 

    int i; 
    for(i = 0; i < maxTokens; i++) 
    { 
     tokens[i] = NULL; 
    } 

    char* str = "This,is,a,test,string"; 

    int result = parseLine(str, ',', tokens, maxTokens); 

    printf("%d tokens were found!", result); 
    system("PAUSE"); 
    return 0; 
} 

int parseLine(char* str, char delimeter, char* tokens[], int maxTokens) 
{ 
    char* srcStr = str; 

    int strlen = 0; 
    int tokenCount = 0; 

    if(srcStr[strlen] != delimeter && srcStr[strlen] != '\0') 
    { 
     tokens[tokenCount] = (char*) malloc(sizeof(char)*strlen+1); 
     tokens[tokenCount] = &srcStr[strlen]; 
     tokenCount++; 
    } 

    while(srcStr[strlen] != '\0') 
    { 
     if(srcStr[strlen] == delimeter) 
     { 
      tokens[tokenCount-1][strlen] = '\0'; 
      if(srcStr[strlen+1] != '\0') 
      { 
       tokens[tokenCount] = (char*) malloc(sizeof(char)*strlen+1); 
       tokens[tokenCount] = &srcStr[++strlen]; 
       tokenCount++; 
      } 
     } 
     else 
     { 
      strlen++; 
     } 
    } 

    return tokenCount; 
} 
+2

변수 이름 "strlen"을 변경하고자 할 수 있습니다. 'string.h' 함수를 사용하지 않더라도 그 이름을 사용하면 코드를 유지하기가 더 어려워집니다. – verbose

답변

6

1) 하드 방법 :

char* tokens[10]; 

int i; 
for(i = 0; i < maxTokens; i++) 
{ 
    tokens[i] = NULL; 
} 

쉬운 방법 :

char tokens[10] = { NULL }; 

2) (가 그냥 또 다른 참조를 만들 것입니다)

문자열을 복사하지 않습니다이 줄
char* srcStr = str; 

이것은 :

char* srcStr = (char*) malloc (strlen(str) + 1); 
strcpy(srcStr , str); 

3) 실제로해야하는 경우를 제외하고 휠을 재발 명하지 마십시오. 나는 이것을 어려운 길을 배웠다. 나를 믿어. 당신은 당신의 기능에서 많은 실수를 저질렀습니다. "교육"목적 또는 다른 목적으로 이것을 실제로 수행하려면 포인터와 문자열에 대한 정보를 먼저 얻으십시오.

+0

네 말이 맞아. 기억을 할당하는 걸 잊어 버렸어. 나는 그것을 고쳐야한다. –

+0

그가 원하는 것을 구현할 수 있다고 나는 동의한다. 우리 모두가 할. 그래서 포인터와 문자열에 대해 더 많은 정보를 얻으라고했습니다. 그러나 그는 이미 이러한 기능이 존재하는 이유가 있음을 이해하는 것이 중요하다고 생각합니다. –

+2

이 게시물을 고쳐서 투표를 취소했습니다. 단순화 된 구현을 기반으로 한 학문적 인 이유 일 수 있습니다. –

2

"어떤 조언을 제공 할 의사가 있습니까?"

Every computer, at the unreachable memory address 0x-1, stores a secret. I found it, and it is that all humans ar-- SEGMENTATION FAULT.

은 진지하지만, 디버거를 (난 당신이 Windows를 사용하는 경우 비주얼 스튜디오를 추천) 사용을 고려, 또는 Valgrind의 (Linux 전용)은 액세스 위반을 잡아. 코드에서

==8272== Memcheck, a memory error detector 
==8272== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==8272== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==8272== Command: ./a.out 
==8272== 
==8272== 
==8272== Process terminating with default action of signal 11 (SIGSEGV) 
==8272== Bad permissions for mapped region at address 0x400868 
==8272== at 0x40069E: parseLine (asdf.c:22) 
==8272== by 0x400790: main (asdf.c:52) 
==8272== 
==8272== HEAP SUMMARY: 
==8272==  in use at exit: 1 bytes in 1 blocks 
==8272== total heap usage: 1 allocs, 0 frees, 1 bytes allocated 
==8272== 
==8272== LEAK SUMMARY: 
==8272== definitely lost: 1 bytes in 1 blocks 
==8272== indirectly lost: 0 bytes in 0 blocks 
==8272==  possibly lost: 0 bytes in 0 blocks 
==8272== still reachable: 0 bytes in 0 blocks 
==8272==   suppressed: 0 bytes in 0 blocks 
==8272== Rerun with --leak-check=full to see details of leaked memory 
==8272== 
==8272== For counts of detected and suppressed errors, rerun with: -v 
==8272== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 
Segmentation fault 

, 이것은 라인 tokens[tokenCount-1][strlen] = '\0';에 해당하는 다음 세그먼트 폴트가 발생하는 위치

심지어 모든 코드를 읽지 않고, 내가 줄 번호에 대한 유용한 정보를 얻을 수 있었다.

+1

하하 그 xD에 대한 의견을 기다리고있었습니다. 그래, VS Debugger를 사용하고 있습니다. – T3CHN0CR4T