본문 바로가기

Programming/VC++

[C] strtok() 함수

strtok 함수는 생각보다 단순하지 않고.. input 변수가 변하는 side effect도 있기 때문에  implementation 코드를 보시면서 이해하는 것이 좋을 것 같습니다.


 1. char *(strtok) (char *s1, const char *s2)

 2. { /* find next token in s1[] delimited by s2[] */

 3.     char *sbegin, *send;

 4.     static char *ssave = "";

 5.

 6.     sbegin = (s1) ? s1 : ssave;

 7.     sbegin += strspn(sbegin, s2);

 8.     if (*sbegin == '\0')

 9.     {

10.         ssave = "";

11.        return (NULL);

12.     }

13.    send = strpbrk(sbegin, s2);

14.     if (*send != '\0')

15.         *send++ = '\0';

16.     ssave = send;

17.     return (sbegin);

18. }


% strspn(s1, s2)는 s2 내의 어떤 문자와도 일치하지 않는 s1의 최초의 index값을 돌려줌

% strpbrk(s1, s2)는 s2 내의 아무 문자와 일치하는 s1의 최초의 char *를 돌려줌


strtok 함수의 역할을 간단히 설명하자면 s2 스트링에 있는 구분자(delimiter)로 s1 스트링을

token 단위로 나누어 주는 것입니다. 그런데 이것을 한번 수행으로 다 하는 것이 아니라

매번 호출을 할때마다 그 다음 구분자가 나올때까지 자르기 때문에 사용법이 약간

어려운 것입니다.


즉, 처음 수행할때 s1에 구분자로 나눌 스트링을 넣고 두번째 수행부터는 s1에 NULL값을

넣음으로써 계속해서 구분자로 나누는 작업을 할 수 있게 됩니다.

아래의 예제를 보면 이해가 더 쉬울 것입니다.


 1. #include

 2. static char str[] = "?a???b,,,#c";

 3. char *t;

 4.

 5. t = strtok(str, "?");     /* t points to the token "a" */

 6. t = strtok(NULL, ",");   /* t points to the token "??b" */

 7. t = strtok(NULL, "#,"); /* t points to the token "c" */

 8. t = strtok(NULL, "?");   /* t is a null pointer */  


5번째 라인에서 첫번째 수행때는 str 을 입력으로 넣었고 6, 7, 8 라인에서는 입력에

NULL 을 넣어서 strtok 가 원본 스트링에서 계속 수행됨을 나타내고 있습니다.


5번째 라인을 수행하면 t는 '?' 로 구분되는 token인 "a"를 가리키게 됩니다.

이때 str 스트링에서 "a" 다음에는 '\0' 문자가 놓이게 되고.. (implementation 15번째 줄 참고)

ssave 변수는 그 다음에 있는 '?' 문자를 가리키고 있겠죠.. ("a" 다다음에 있는 '?')

그러므로 6번째 라인을 수행하면 t는 ','로 구분되는 token인 "??b"를 가리키게 됩니다.


7번째 라인을 수행하면 ",,#c" 스트링에 대해 "#," 구분자로 자르게 되는데

처음에 ,,# 은 모두 구분자에 해당하고 c이후에 스트링이 끝나므로 결과는 "c"가 됩니다.

8번째 라인은 ssave가 문자 끝에 도달해서 '\0'을 가리키므로 결과가 NULL 이지요.


implementation 코드를 보면 입력에 s1 스트링은 const char * 가 아닌 char * 타입으로 이는

함수내에서 이 스트링 값을 변형한다는 것을 나타낸다는 것에 주의를 해야합니다.

즉, 위의 예제를 수행하고 나면 str 변수는 아래와 같이 변해있을 것입니다.


str[0]=>'?', str[1]=>'a', str[2]=>'\0', str[3]=>'?', str[4]=>'?',

str[5]=>'b', str[6]=>'\0', str[7]=>',', str[8]=>',', str[9]=>'#',

str[10]=>'c', str[11]=>'\0'