Skip to content

strtok, strtok_r(3)


synopsis#

       #include <string.h>

       char *strtok(char *restrict str, const char *restrict delim);
       char *strtok_r(char *restrict str, const char *restrict delim,
                      char **restrict saveptr);

strtok_r은 thread-safe한 버전의 strtok이다. 전역변수를 사용하지 않고 saveptr이라는 외부변수를 사용하기 때문.

example#

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

int
main(int argc, char *argv[])
{
   char *str1, *str2, *token, *subtoken;
   char *saveptr1, *saveptr2;
   int j;

   if (argc != 4) {
       fprintf(stderr, "Usage: %s string delim subdelim\n",
               argv[0]);
       exit(EXIT_FAILURE);
   }

   for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
       token = strtok_r(str1, argv[2], &saveptr1);
       if (token == NULL)
           break;
       printf("%d: %s\n", j, token);

       for (str2 = token; ; str2 = NULL) {
           subtoken = strtok_r(str2, argv[3], &saveptr2);
           if (subtoken == NULL)
               break;
           printf("\t --> %s\n", subtoken);
       }
   }

   exit(EXIT_SUCCESS);
}

result

$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
        --> a
        --> bbb
        --> cc
2: xxx
        --> xxx
3: yyy
        --> yyy

해석

위의 예제는 이중 for문을 활용하여 nested token 분리를 수행하는 방법을 나타내고 있다.

delim은 파이썬 식의 delimiter와는 조금 다르다. 개별적인 char 바이트 중 하나라도 일치하는 것이 있다면 통과하기 때문이다. 예를 들어 위의 사용예제에서 첫번째 delim을 :;으로 주었는데 : 또는 ;에 대하여 모두 분리를 수행했다.

strtok는 토큰화할 문자열이 더 이상 남아있지 않는 경우에는 NULL을 리턴하고 그 외에는 비어있지 않은 문자열의 첫번째 주소를 리턴한다. 모든 delim들은 Null-terminated character로 수정된다는 점 유의.

처음 호출에만 인자 str이 필요하고 두 번째 호출부터는 NULL로 바꿔서 집어넣는 코드를 확인할 수 있다.