<개인공부>/[C언어, C++]

[C언어/C++] strtok 함수(문자열 자르기)에 대해서.

BlockDMask 2020. 3. 31. 01:27
반응형

안녕하세요. BlockDMask 입니다.

오늘 공부할 함수는 문자열을 일정 기준을 정해서 싹둑싹둑 자를 수 있는 strtok 함수입니다.

C언어 strtok 함수에 대해서 한번 알아보러 가보겠습니다.


<목차>

1. strtok 정의와 함수 설명

2. strtok 예제1

3. strtok 예제2

 


1. C/C++ strtok 정의와 함수 설명


▶ strtok 헤더파일

C언어 : <string.h>

C++ : <cstring>


▶ strtok 함수 정의

char* strtok(char* str, char* delimiters);


strtok 이라는 함수의 이름을 분석해보면 str + tok 인데요.

string을 tokenize한다. 라고 표현할 수 있습니다. 문자열(string)을 토큰(token)처럼 조각조각 내는 함수 입니다.


char* 타입의 문자열 str을 첫번째 매개변수로 받아서, 두번째 매개변수로 들어온 char* 타입의 구분자를 기준으로

문자열을 이쁘게 잘라서 문자열의 포인터를 하나씩 하나씩 반환하는 함수 입니다.


반환값은 포인터를 반환하는데 자른 문자열을 가리키는 char* 입니다. 포인터를 통해서 어떤식으로 문자를 구분하는지 아래 strtok 함수 동작 원리를 보면 이해가 쉬울것 같습니다.


strtok 함수를 통해서 우리는 이런걸 할 수 있습니다.

"코로나19 의료진 여러분 힘내세요." 이렇게 띄어쓰기가 되어있는 문장에서 띄어쓰기 제외하고 단어들을 가지고싶다 할때

strtok을 이용하면

"코로나19" "의료진" "여러분" "힘내세요."같이 띄어쓰기를 제외한 단어들만 가지고 올 수 있습니다.


이럴때도 유용하겠죠. 환자들의 이름들이 "김환자, 박대구, 이시국, 김마스크" 이런식으로 되어있다고 할 때

이름만 가지고 오고싶다. 할때 strtok("문자열", "구분자")를 이용해서

쉼표(,)와 띄어쓰기( )를 구분자로 넣어서 환자의 이름만 쏙쏙 가지고 올 수 있습니다.



▶ strtok 함수 동작 원리를 세가지로 설명해보려 합니다.


1. 글로 설명하는 strtok 함수 흐름
이 함수는 조금 특별하게 동작을 합니다. 함수를 처음 호출할때는 문자열을 넣어주지만 동일한 문자열에 한에서 다음 자른것을 가지고 올때는 따로 문자열을 넣지도 않고, strtok 함수를 계속 호출 합니다.

예를들어 "Block D Mask"라는 문자열이 있고 " " 공백(띄어쓰기)을 기준으로 문자열을 자른다고 할때, 이런식으로 흐름이 진행됩니다.


첫번째 인자에는 짜를 문자열,  두번째 인자는 구분할 기준을 집어 넣습니다.

char* ptr = strtok("Block D Mask", " ");


그러면 strtok 이라는 함수는 문장에서 구분자로 들어온 " " 공백을 찾습니다.

알맞은 구분자를 " " 를 찾게 되면 해당 구분자를 문장의 끝을 알리는 \0 으로 바꾸어 줍니다.


strtok의 첫번째 반환값은 "Block"이 됩니다.

이 상태에서 또다시 strtok(NULL, " "); 함수를 호출하게 되면 이전에 찾은 구분자 뒤에서 부터 다시 구분자를 찾게 됩니다.


"D Mask"라는 문자가 이제 남았는데요. D 다음에있는 띄어쓰기를 보고 strtok 함수는 그 띄어쓰기를 '\0'로 바꾸어 줍니다.

"D\0Mask" 라는 문장이 되면서, strtok 함수는 문자열 "D"를 가리키는 포인터를 반환하게 됩니다.


이 상태에서 또다시 strtok(NULL, " "); 함수를 호출하게 되면 아까 기억했던 "D\0Mask" 함수에서 변환했던 \0이부분의 바로 뒤에서 부터 구분자를 찾게되는데, 이때!!!!!!! Mask" 하고 문자가 끝나기 때문에 M에서부터 문자열끝까지를 가리키는 "Mask"를 가리키는 포인터를 반환하게 됩니다.


이 상태에서 또다시 strtok(NULL, " "); 함수를 호출하면 문자열의 끝까지 탐색했기 때문에 strtok 함수는 NULL을 반환하게 됩니다.


눈치 채셨는지 모르지만, strtok 함수를 처음 불러줄때만 원하는 문자열을 집어넣고 그 다음부터는 첫번째 인자에 NULL을 넣어주는 것을 알 수 있는데요, 이는 strtok 함수에게 "이전에 너가 구분자를 찾았던 그 문자열 주소에서 부터 다시 찾아달라"는 뜻을 가지고 있다고 생각하면됩니다.


또 눈치 채셨는지 모르지만, strtok 함수는 한번에 이쁘게 딱 문자열을 분리해주는 함수가 아닙니다.

strtok 함수가 NULL을 반환할 때 까지 계속해서 불러줘야하는 함수입니다.


2. 코드로 보는 strtok 함수 흐름

위에서 말한 strtok 함수의 흐름을 코드에서 살펴보면 이렇습니다.


1
2
3
4
5
6
7
char str[] = "Block D Mask.";    //구분할 문자열
char *ptr = strtok(str, " ");    //첫번째 strtok 사용.
while (ptr != NULL)              //ptr이 NULL일때까지 (= strtok 함수가 NULL을 반환할때까지)
{
    printf("%s\n", ptr);         //자른 문자 출력
    ptr = strtok(NULL" ");     //자른 문자 다음부터 구분자 또 찾기
}
cs




3. 그림으로 보는 strtok 함수 흐름

글로 설명하니 저도 이해가 잘 안가네요. 미천한 PPT 실력을 뽐내보도록 하겠습니다.




그림으로 보니 이해가 좀 쉬워졌을까요?

두번째 인자로 들어온 구분자를 찾아서 '\0'로 바꿔준다. 이것만 기억하면 될듯 합니다.

그럼이제 예제들을 보러 가시죠.


2. C언어, C++ strtok 예제1


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include<string.h>    //C++ : <cstring>
 
int main(void)
{
    char str[] = "Kim,Park,Lee,Choi,Seo";
 
    char *ptr = strtok(str, ",");    //구분자는 콤마(,)입니다.
 
    while (ptr != NULL)
    {
        printf("%s\n", ptr);        //자른 문자 출력
        ptr = strtok(NULL",");
    }
 
    return 0;
}
 
cs


▷예제 결과

문자열이 콤마(,)를 기준으로 잘 잘리는걸 볼 수 있습니다.



3. C++, C언어 strtok 예제2


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
#include<string.h>
 
int main(void)
{
    char str[] = "x + y - z + 9 = 1000";
    char *ptr = strtok(str, "+-= ");    //구분자는 "+-= "입니다.
    while (ptr != NULL)
    {
        printf("%s\n", ptr);
        ptr = strtok(NULL"+-= ");
    }
 
    return 0;
}
cs

▷예제 결과
strtok의 두번째 인자로 하나의 구분자 뿐만 아니라 구분하고싶은 여러 문자들을 한꺼번에 포함할 수 있습니다.


반응형