본문 바로가기

별걸다하는 IT/프로그래밍언어

[C언어][string.h]문자열 관련 함수 - strtok, strtok_s 문자열 파싱, 분리하기, 자르기

반응형

[C/ C++ 포스팅 목차 링크 바로가기]

안녕하세요~ ㅎㅎ

저는 휴가로 여행갔다가 오늘 돌아왔습니다 ~~ㅎㅎ

 

오늘은 string.h라이브러리에 있는 문자열 관련 함수 중, 문자열을 분리하는(?) 자르는 함수 strtok에 대해서 살펴볼게요

문자열 대상

C언어 기준, '\0'으로 끝나는 C형식 문자열 방식에서 사용되는 ,

string.h 라이브러리에 정의되어 있는 문자열 함수입니다. 따라서 #include <string> 라이브러리에 정의되어 있는 string 타입을 사용하시면 안됩니다~

문자열 길이 구하는 함수

strtok

문자열을 토큰으로 분리한다.

string token의 약자

헤더파일

#include <string.h>

함수 프로토타입

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

인자:

char * str : C style의 문자열

const char* delimiters: 분리할 기준이 되는 문자 (구분자, 딜리미터)

리턴 값:

문자열에서 찾은 토큰의 주소값을 리턴하며, 토큰이 더 이상 없다면 널 포인터를 리턴합니다.

토큰은 구분자를 기준으로 문자열을 쪼갰을 때 문자열 조각을 의미하며 토큰의 주소값은 쪼개진 문자열의 시작 주소를 말합니다.

역할:

구분자를 기준으로 문자열을 자릅니다. 만약 strtok(str, " ");처럼 구분자를 공백문자로 넣어주면 공백을 기준으로 문자열을 자릅니다. 여기서 리턴값은 str 문자열 중 " "를 만나기 직전까지 문자열이 될거예요. (정확히는 문자열 시작 주소)

한 예로 str이 "deer mom"일 때, strtok(str, " ")를 출력하면 "deer"이 나오겠죠 ㅎㅎ

작동 원리

사진을 보면 한눈에 파악할 수 있뜸!

t라고 적혀있는것은 토큰 token을 의미해요 ㅎㅎ

"See the quick red fox"라는 문자열 s를 공백 기준으로 잘랐을 때 과정을 보여주는 사진입니다~

(a)는 문자열 s 그자체~!

(b)는 strtok를 한 번 수행했을 때~ (c)는 strtok를 두 번 수행했을 때, (d)는 strtok를 세번째 시행했을 때 어떻게 진행되는지 과정을 보여주고 있는 사진입니다. 밑에 다시한번 자세하게 반복할그예요~

 

인자로 받은 문자열에서 구분자가 있는 위치를 널 포인트로 치환해줌으로써, 문자열을 끊기게 만드는 거예요 ㅎㅎ

분명 a,b,c,d,e,f 모두 같은 문자열 s를 출력하고 있는데 출력을 해보면 널문자를 기준으로 문자열이라고 판단하기 때문에 "See the quick red fox"를 출력하는 (a)예시와 다르게 (b)에서는 s값으로 "See"를 출력하게 되는거죠 ㅎㅎ

사용 예시

strtok수행시 문자열과 토큰 비교 예시:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[] = "hello nice to meet you";
	char del[] = " ";
	char* token;
	token = strtok(str1, del);
	printf("str1: %s\n", str1);
	printf("token: %s\n", token);
	return 0;
}

결과창

보면 str1이 본래는 "hello nice to meet you"였지만, strtok 수행 이후에는 hello로 잘린 것을 볼 수 있습니당.

token은 잘린 문자열의 시작 주소를 가리키고 있고, 출력했을 경우, 문자의 끝을 나타내는 널문자까지 읽어들여서 문자열을 출력해요. str1이 hello로 변경되었으므로, 본래 문자열을 보관하고 싶을 경우 따로 저장을 해야합니다.

strtok 두 번째 수행시 문제:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[] = "hello nice to meet you";
	char del[] = " "; 	char* token;
	token = strtok(str1, del);
	printf("first strtok - str1: %s\n", str1);
	printf("first strtok - token: %s\n", token);

	token = strtok(str1, del);
	printf("second strtok - str1: %s\n", str1);
	printf("second strtok - token: %s", token);

	return 0;
}

strtok를 두 번째 사용하게 되면 hello다음인 nice를 분리해서 줘야 할 것 같지만.. 실제로 수행해보면 hello를 반환하는 것을 확인할 수 있어요.

왜? 이미 첫 번째 strtok에서 str1을 hello로 잘라버렸으니까~~~ str1을 다시 분리 대상 문자열을 의미하는 첫 번째 매개변수 인자값으로 넣으면 안되는거~

strtok 두 번째 파싱을 위한 올바른 사용법 예시:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[] = "hello nice to meet you";
	char del[] = " "; 	char* token;
	token = strtok(str1, del);
	printf("first strtok - str1: %s\n", str1);
	printf("first strtok - token: %s\n", token);

	token = strtok(NULL, del);
	printf("second strtok - str1: %s\n", str1);
	printf("second strtok - token: %s\n", token);
	return 0;
}

실행결과

strtok는 내부적으로 파싱하고 직전에 파싱하고 남은 문자열을 저장하고 있어요 ㅎㅎ

코드상으로 첫 번째 인자로 NULL을 넣어주면, 남은 문자열을 대상으로 나머지 파싱을 진행해요 ㅎㅎ

더 이상 구분할 수 없을때까지... strtok with 반복문 예시!:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[] = "hello nice to meet you";
	char del[] = " "; 	char* token;
	token = strtok(str1, del);
	while (token != NULL) {
		printf("%s\n", token);
		token = strtok(NULL, " ");
	}
	return 0;
}

실행결과

이런식으로 반복문과 같이 사용할 경우, 문자열을 구분자를 기준으로 끝까지 분리할 수 있다.

주의할 점 or 같이 알아두면 좋을 점

▶C언어 문자열에서 사용해야 한다. string 클래스 형태의 문자열에서는 사용 불가!

▶비주얼스튜디오에서 strtok를 사용하려면 가장 상단에 '#pragma warning(disable: 4996)' 추가해줘야 한다.

▶그렇지 않을 경우, strtok_s를 사용해야 한다.

▶문자열을 구분자로 여러번 파싱하려면 두 번째 strtok에서는 첫 번째 매개변수 값으로 NULL을 주어야한다.

▶원본이 유지되지 않으므로, 기존 문자열을 재사용할일이 있을 경우 복사본을 만들어놓고 사용해야한다.

▶주로 반복문과 짝짝꿍으로 사용된다.

▶더 이상 구분할 수 없으면 NULL을 반환한다.

▶구분자를 하나의 문자로 구분할거라 해도 작은따옴표가 아닌, 문자열을 의미하는 큰따옴표에 넣어줘야 한다.

▶구분자는 하나의 문자만 인식할 수 있는 것은 아니다. 한 예로, 컴마, 세미콜론 두 가지로 구분하고 싶을 경우 구분자로 ",;"를 넣어주면 됨.

▶문자열 포인터에 문자열 리터럴이 들어있어서 읽기 전용인 경우에는 strtok()함수를 사용할 수 없다.

▶대표적인 예료 날짜와 시간이 합쳐져있을 때, 구분자를 기준으로 날짜와 시간을 따로 저장할 수 있지

▶문자열을 나누는게 아니라 특정 위치에서부터 일정 길이의 문자열을 뽑고 싶은거면 strcnpy 함수가 적합하다.

▶strtok_r 함수가 있는데 strtok_s가 strtok_r의 윈도우 버전인 것이다.

▶참고로 strtok_r과 strtok_s 둘 다 호환이 되는 프로그램을 작성하고 싶으면, 전처리기 #if를 이용할 수 있다.

#if defined(_WIN32) || defined(_WIN64) //윈도우일 경우
# define strtok_r strtok_s // strtok_r을 strtok_s로 해석해라
#endif

함수 원형 코드

아.... strtok함수에 관련해서 포스팅을 안한줄 알았는데.. strtok포스팅을 예전에 올린게 있었군요 (흑흑 그렇게 열시미 올려놓고 왜 기억을 못하니..! )

함수 원형코드는 제가 작성한 포스팅에 잘 풀이 되어있으니, 그 포스팅을 첨부하도록 할게요

▼문자열 헤더파일 string.h 파헤치기 (strtok, strtok_s 왜 NULL을 전달하는가)

 

문자열 헤더파일 string.h 파헤치기 (strtok, strtok_s 왜 NULL을 전달하는가)

[C언어, C++언어, Java언어 기초 프로그래밍 목차 링크 모음] 오늘은 문자열을 특정 구분자를 기준으로 나눠주는 strtok 함수를 살펴볼게요 string.h 라이브러리 파헤치기 strtok, strtok_s편 strtok() 문자열을..

jhnyang.tistory.com

여기에 strtok_s 까지 잘 비교해서 설명이 되어있어요 ㅎㅎ

오늘은 여기까지~!

string.h 라이브러리 또 다른 함수 보기

string.h 라이브러리의 다른 함수를 이어서 보시려면 아래 링크로!

↓ 문자열 길이를 알려주는 strlen함수

 

[C언어][string.h]문자열 관련 함수- strlen(길이)함수의 모든 것, 함수 코드, 사용법 및 예제, 주의사항 등

[C, C++완전정복 목차] 안녕하세요~!! 오랜만이예요 ㅎㅎ 그동안 할일이 초큼 쌓여있는걸 처리하느라..ㅎㅎㅎ 오늘은 무진장~~ 많이 쓰이는, 안사용할 수가 없는 문자열 관련 함수들을 정리해보려고 해요 ㅎㅎ st..

jhnyang.tistory.com

↓ 문자열 복사 함수 strcpy, strncpy

 

[C언어]문자열 복사 함수 strcpy, strcnpy와 주의사항, 널문자 (null) - string.h 라이브러리 파헤치기

[C언어, C++언어 완전정복 목차 링크!] 안녕하세요~! 저번 시간 strlen, strtok 함수에 이어서 string.h 라이브러리에 속한 또 다른 함수 중 하나를 살펴보려고 합니다. 오늘은 매우매우 보편적이고 기본적이고..

jhnyang.tistory.com

공감, 댓글, 광고보답은 질좋은 정보를 공유하는데 큰 응원이 됩니다 :) 

질문, 조언, 오타지적 등 환영해요

고럼 다음 포스팅에서 봐요!

반응형