2011-01-14 3 views
4

strtok을 사용하여 madddy 문자열을 분할하는 다음 스 니펫을 고려해보십시오.strtok을 이해하려고 시도합니다

char* str = (char*) malloc(sizeof("Madddy")); 
strcpy(str,"Madddy"); 

char* tmp = strtok(str,"d"); 
std::cout<<tmp; 

do 
{ 
    std::cout<<tmp; 
    tmp=strtok(NULL, "dddy"); 
}while(tmp!=NULL); 

출력이 Ma입니다. 그러나 strtok을 다음과 같이 수정하여

tmp=strtok(NULL, "ay"); 

출력이 Madd가됩니다. 그렇다면 strtok은 어떻게 작동합니까? strtok이 구분 기호 문자열에있는 모든 문자를 구분 기호로 사용하도록 기대했기 때문에 나는이 질문을 가지고 있습니다. 그러나 어떤 경우에는 그렇게하고 있지만, 경우에 따라 예기치 않은 결과가 나타납니다. 아무도 내가 이것을 이해하도록 도울 수 있습니까?

+6

나는 정직하게이 작업을 수행하는 올바른 방법이 완전히'strtok' 사용을 중지하는 것입니다 생각 :

여기에 더 C와 같은 것으로 수정 한 코드입니다. 스레드 안전성을 보장하지 않으면 사용하기 어렵고 디버그하기 어려운 기능입니다. 파싱을하기 위해서는'string :: find'와'string :: substr'의 조합을 사용하는 것이 가장 좋습니다. – templatetypedef

+0

또는'boost :: token_iterator' –

+0

특히 C++가 아니라 C를 사용하고 있기 때문에 중요성과 강조를 위해이 작업을 반복 할 의향이 있습니다. 또한 boost :: tokenize를 살펴보아야 할 수도 있습니다. –

답변

1

구분 기호 "d"로 처음 ​​strtok (루프 밖)를 호출 한 것을 잊어 버린 것 같습니다.

strtok이 정상적으로 작동합니다.참조 here이 있어야합니다. 두 번째 예 (strtok("ay"))에 대한

:

첫째, 당신은 (STR, "D") strtok를 호출. 첫 번째 "d"를 찾고 문자열을 분리합니다. 특히, tmp = "Ma"및 str = "ddy"(첫 번째 "d"를 삭제)를 설정합니다.

그런 다음 strtok (str, "ay")를 호출합니다. str에서 "a"를 찾겠지 만 문자열이 "ddy"이므로 일치가 발생하지 않습니다. 그런 다음 "y"를 찾습니다. 따라서 str = "dd"및 tmp = "".

"Madd"를 본 것처럼 인쇄합니다.

+0

@ Karthick : 첫 번째 예제가 작동하지만 생각대로 작동하지 않을 수 있습니다. 나는 cout << tmp 대신에 cout << tmp << "-"를 사용하여 실제로 어떤 일이 일어나는지를보기를 권장합니다. 빈 문자열이 많이 있음을 알 수 있습니다. –

10

"strtok을 이해하려고 시도 중입니다."행운을 빌어 요!

어쨌든, 우리는 제대로 2011 년 Tokenise에있어 : ​​

std::string str("abc:def"); 
char split_char = ':'; 
std::istringstream split(str); 
std::vector<std::string> token; 

for (std::string each; std::getline(split, each, split_char); token.push_back(each)); 

:

+3

예,이 질문에 엄격하게 대답하지 않는다는 것을 알고 있습니다. 하지만 IMO는 가치 있고 우수한 대안이며, 아직 답변이 가치 있다고 생각합니다. –

+0

나는이 문제를 완전히 알고 있습니다.하지만 표준 규격에 대해서 궁금합니다. –

3

프레드 프린스톤 아마 strtok() 사용 D. 다중 쓰레드 환경에 선행하여 소스 문자열을 깨기 (수정)합니다.

첫 번째 매개 변수에 NULL과 함께 호출되면 마지막 문자열을 계속 구문 분석합니다. 이 기능은 편리했지만 당일에도 약간 특이했습니다.

+0

+1 Fred Flintstone 참조. –

2

사실 코드가 잘못, 의심 할 여지가 예기치 않은 결과를 얻을 수 없습니다 :

char* str = (char*) malloc(sizeof("Madddy")); 

char* str = (char*) malloc(strlen("Madddy") + 1); 
+1

예, 첫번째 예제는 아마도 포인터의 크기 인 4 바이트 (32 비트 환경에서)를 할당합니다. ''abcdefghijkm''와 같은 문자열 상수의 타입은 포인터입니다 (특히 컴파일러에 따라'char *'또는'const char *'). – wallyk

+1

@wallyk : 사실, (http://codepad.org/H7zJkjCN). 문자열 리터럴 유형은 문자 배열입니다. @Anders : 코드가 이상 하긴하지만, 당신도 동일하게 작동합니다. * –

+0

@Fred Nurk : 오 예. 패턴을 깨뜨린 것 같아요, 아마 더 유용 할 것 같습니다. 그것은 오랫동안 피할 수있는 구조였습니다. (위의 잘못된 정보에 대한 사과.) – wallyk

0

해야한다 나는 또 다른 질문에 대한 functions causing security problems/bad practise functions and the c standard library에서 영감 질문을했다.

거기에서 나에게 주어진 답을 인용 :

그것은 실제로 분리 문자를 대체하면서 strtok() 기능을 가진 일반적인 함정은, 구문 분석 문자열이 변경되지 않은 상태로되어 있다고 가정하는 것입니다 '\0'.

또한 전체 문자열이 토큰 화 될 때까지 을 호출하면 strtok()이 사용됩니다. 일부 라이브러리 구현 strtok()가 동시에 여러 스레드에서 호출 경우, 일부 불쾌한 suprises을 유도 할 수있다 글로벌 변수에 strtok()의 내부 상태를 저장합니다.

질문 C++로 태그를 지정 했으므로 다른 것을 사용하십시오! C를 사용하고 싶다면 안전한 방식으로 작동하는 고유 한 토크 나이저를 구현하는 것이 좋습니다.

0

태그를 C가 아닌 C로 변경 했으므로 printf를 사용하여 무슨 일이 일어나고 있는지 볼 수 있도록 함수를 다시 작성했습니다. Hoang은 정확합니다. 당신은 정확한 출력을보고 있지만 같은 줄에 모든 것을 인쇄하고 있다고 생각하기 때문에 출력에 혼란을 느낍니다. 그가 정확히 무슨 일이 일어나고 있는지 설명하면서 Hoang의 대답을보십시오. 또한 다른 사람들이 언급했듯이 strtok은 입력 문자열을 파기하므로주의해야합니다. 스레드로부터 안전하지는 않습니다. 그러나 더러운 토큰 장치가 필요하면 작동합니다. 또한, 정확하게 strlen을 사용하도록 코드를 변경했으며, sizeof는 Anders가 올바르게 지적한 바 아닙니다.

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

char* tmp = strtok(str,"d"); 
printf ("first token: %s\n", tmp); 

do 
{ 
    tmp=strtok(NULL, "ay"); 
    if (tmp != NULL) { 
     printf ("next token: %s\n", tmp); 
    } 
} while(tmp != NULL); 
관련 문제