본문 바로가기
프로그래밍/C

C ] strtok, strtok_r : 구분 문자로 문자열 쪼개기

by eteo 2023. 1. 15.

 

 

strtok 함수는 문자열을 구분문자(delimiter) 단위로 쪼개는데 사용되는데 이렇게 쪼개진 문자열을 토큰(token)이라고 한다.

 

str에 쪼개고자 하는 문자열을 전달하면 str의 가장 첫번째 문자가 토큰의 시작이 되고 delim에 포함된 문자들 중 하나를 만나는 곳이 토큰의 마지막이 되며, 원래 delimiter가 있었던 토큰의 마지막을 null-terminted 하고 토큰의 시작 주소를 리턴한다.

 

strtok 함수는 내부에 static 변수로 str 문자열에서 작업을 끝낸 다음 위치를 기억하고 있기 때문에,

이 다음에 str인자로 NULL을 전달하며 호출하면 이전에 찾았던 토큰 바로 다음 문자부터 시작해서 분리작업을 진행한다.

 

그러다 맨처음에 전달된 str 문자열의 NULL 문자에 도달하게 되면 이 후 str인자로 NULL이 전달되는 모든 호출에서 NULL포인터를 리턴하게 된다.

 

나중에 str인자로 다른 문자열을 전달하면 그 문자열로 토큰 분리작업을 하게 될 것이다.

 

 

 

#include <string.h>

char *strtok(char *str, const char *delim);

 

파라미터

  • str : delimiter 단위로 분리할 문자열, 이 값이 NULL 이면 static 변수에서 저장하고 있던 이전 호출에서 작업한 그 다음 위치부터 분리작업을 진행한다. (원본 문자열을 보존하려면 임시변수에 복사해 전달해야한다.)
  • delim : 문자열을 분리할 delimiter 들. 이중 하나라도 만나면 분리한다.

리턴값

  • NULL 이 아닌값 : 정상적으로 분리하였고, 분리된 토큰의 시작 포인터를 리턴한다.
  • NULL : 더이상 분리할 데이터가 없다.

 

 

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

/* /또는 - 또는 : 또는 space를 delimiter로 사용합니다. */
#define DELIM_CHARS     "/-: "

int main(int argc, char **argv)
{
    char time[1024] = "2023/01/15 20:29:30";
    char *ptr;

    printf("time : %s\n", time);
    ptr = strtok(time, DELIM_CHARS);

    while(ptr) {
        printf("ptr = %s\n", ptr);
        
        ptr = strtok(NULL, DELIM_CHARS);
    }

    return 0;
}

출처 : https://www.it-note.kr/85

 

 

 

strtok 함수는 내부에 static 변수를 사용하므로 multi-thread에 safe하지 않아서 대신 strtok_r 함수를 사용할 것이 권장된다.

 

사용법은 같으나, 다음 처리를 위한 위치를 저장하는 포인터로 내부 static 변수를 사용하는 대신 외부변수를 쓰게끔 하였다.

 

#include <string.h>

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

 

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

/* /또는 - 또는 : 또는 space를 delimiter로 사용합니다. */
#define DELIM_CHARS     "/-: "

int main(int argc, char **argv)
{
    char time[1024] = "2023/01/15 20:29:30";
    char *ptr;
    char *next_ptr;

    printf("time : %s\n", time);
    ptr = strtok_r(time, DELIM_CHARS, &next_ptr);

    while(ptr) {
        printf("ptr = %s\n", ptr);
        
        ptr = strtok_r(NULL, DELIM_CHARS, &next_ptr);
    }

    return 0;
}

 

 

 

 

strtok_r 함수

char *
__strtok_r (char *s, const char *delim, char **save_ptr)
{   
  char *end;
  
  if (s == NULL)
    s = *save_ptr;

  if (*s == '\0')
    {
      *save_ptr = s;
      return NULL;
    }
    
  /* Scan leading delimiters.  */
  s += strspn (s, delim);
  if (*s == '\0')
    {
      *save_ptr = s;
      return NULL;
    }

  /* Find the end of the token.  */
  end = s + strcspn (s, delim);
  if (*end == '\0')
    {
      *save_ptr = end;
      return s;
    }

  /* Terminate the token and make *SAVE_PTR point past it.  */
  *end = '\0';
  *save_ptr = end + 1;
  return s;
}

 

 

 

Reference : 

https://modoocode.com/102

https://www.it-note.kr/85

https://jybaek.tistory.com/593