본문 바로가기
C,C++/C++

[C++] 공백 단위로 문자열 자르는 split 함수 구현 ( find_if() 사용 )

by woohyeon 2019. 11. 1.
반응형

안녕하세요.

오늘은 표준 라이브러리 함수인 <algorithm> 헤더의 std::find_if() 함수를 사용하여 split 함수를 구현해보겠습니다.

split 함수는 문자열을 공백 단위로 나누어 벡터에 저장 후 벡터를 반환하는 함수입니다. 예를 들어 "hello world"라는 문자열을 인수로 전달하면 "hello", "world"를 요소로 갖는 벡터를 반환합니다. 더 간단한 코드 혹은 공백이 아닌 다른 문자를 기준으로 자르고 싶다면 다음 포스팅을 참고하세요.

https://woo-dev.tistory.com/156?category=882878


함수 프로토타입

std::vector<std::string> split(const std::string& str)

 

함수 구현을 위해 동작 방식을 단계 별로 나열해보겠습니다.

1) 인자로 전달된 문자열(string)의 첫 문자를 시작(begin)으로 아래 단계들을 수행합니다.
2) 공백으로 분리할 문자열의 시작 지점을 구하기 위해 공백이 아닌 문자(begin)를 찾습니다.
3) 단계 2) 에서 찾은 문자를 시작으로 하는 문자열의 끝을 구하기 위해 공백 문자(end)를 찾습니다.
4) begin != string.end() 인  [begin, end) 범위의 문자열을 벡터에 추가합니다.
5) 처음부터 반복하지 않도록 시작 지점을 end로 변경 후 위 단계들을 반복합니다.


위 단계를 코드로 구현해보겠습니다.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm> // std::find_if()


/*
	문자열을 공백 단위로 나누어 벡터에 저장 후 
	벡터를 반환하는 split 함수를 작성합니다.
*/


// 인수가 공백일 경우 true를 반환합니다.
// std::find_if()의 서술함수
bool space(char c)
{
	return isspace(c);
}

// 인수가 공백이 아닐 경우 true를 반환합니다.
// std::find_if()의 서술함수
bool not_space(char c)
{
	return !isspace(c);
}

std::vector<std::string> split(const std::string& str)
{
	typedef std::string::const_iterator iter;
	std::vector<std::string> ret;

	iter it_b = str.begin();
	
	while (it_b != str.end())
	{
		// 공백이 아닌 첫 문자를 찾습니다.
		// ex) "hello world!" 에서 'h'를 가리키는 반복자를 반환합니다.
		it_b = find_if(it_b, str.end(), not_space);

		// 위에서 찾은 문자로 시작하는 단어의 끝을 찾습니다.
		// "hello world!" 에서 "hello"의 'o' 다음 문자인 공백을 가리키는 반복자를 반환합니다.
		iter it_e = find_if(it_b, str.end(), space);
		
		// 범위가 유효할 경우
		if (it_b != str.end())
		{
			// 아래 생성자는 it_e가 가리키는 문자를 포함하지 않습니다.
			// "hello" 문자열 생성 후 벡터의 끝에 추가합니다.
			ret.push_back(std::string(it_b, it_e));
		}
		 
		// 저장한 문자열의 다음 위치부터 시작합니다.
		it_b = it_e;
	}

	return ret;
}


int main(void)
{
	std::string str = "hello hi hola bonjour";

	std::vector<std::string> vec;
	vec = split(str);

	for (std::vector<std::string>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter)
	{
		std::cout << *iter << "\n";
	} 

	return 0;
}

 

주요 내용 설명)

find_if 함수는 <algorithm> 헤더의 STL의 알고리즘입니다.  첫번째, 두번째 인자는 순차열을 나타내는 반복자이고, 세번째 인자는 서술함수입니다. find_if 함수는 순차열의 각 요소에 접근하면서 서술 함수를 호출하며 참을 반환하는 요소를 찾습니다.

it_b = find_if(it_b, str.end(), not_space);

 

위 코드는 it_b가 가리키는 요소부터 차례로 접근하며 not_space()를 호출합니다. not_space()는 인자로 전달된 문자가 공백이 아닐 경우 참을 반환하도록 작성한 서술함수입니다.  따라서 it_b는 공백이 아닌 요소를 가리키는 반복자를 얻습니다.

find_if() 에 대한 더 자세한 내용은 http://www.cplusplus.com/reference/algorithm/find_if/  참조하세요.


실행 결과)

 

참고 도서)

Accelerated C++




댓글