그냥 게임개발자
split() 함수 본문
split()
split()은 코딩테스트에서 많이 등장하는 로직이다.
split()함수란 다른 프로그래밍 언어에서도 문자열을 특정 문자열을 기준으로 쪼개어서 배열화 시키는 함수이다.
C++에서는 STL에서 split()함수를 지원하지 않는다.
그래서 만들어야 한다.
만들어도 시간복잡도는 O(n)이다.
예를 들어
aaa bbb ccc
여기 중간에 띄어쓰기(공백)이 있다.
그러면 띄어쓰기를 기반으로 나누어서 배열을 만든다 하면
[aaa, bbb, ccc]이렇게 만들어주는 함수가 split()함수이다.
split을 만드는데 있어서 외워야 되는 부분이 있다.
while ((pos = input.find(delimiter)) != string::npos)
{
token = input.substr(0, pos);;
ret.push_back(token);
input.erase(0, pos + delimiter.length());
}
이걸 외워야 하는데
차근차근 해석해보자.
while ((pos == input.find(delimiter)) != string::npos)
여기서 보면 input에서 일단 delimiter를 찾는다.
delimiter란 구분문자입니다.
한마디로 우리가 위에서 공백을 기준으로 잘라서 배열로 만들었지 않은가?
그런것을 delimiter라고 한다.
근데 이것을 무한 반복하는데 있어서 찾지 못할 때까지 반복한다.
string::npos란 -1 값을 가지는 상수로 find() 함수 수행 시에 찾는 문자열이 없을 때 반환된다.
그렇다면 찾지 못하면 find()함수에서는 -1을 반환하기에 종료가 무한 반복문이 종료가 될 것이다.
결국 input.find(delimiter)를 통해 문자열을 찾는다.
뭐 예를 들어 abcd가 있는데 delimiter가 d이다.
a[0]b[1]c[2]d[3]
그럼 pos에는 3이 들어간다
token = input.substr(0, pos);
그럼 3만큼 0에서 3까지 substr을 하기 때문에 abc를 추출한다.
그 다음
ret.push_back(token);
ret벡터에 token 문자열을 넣어준다.
그리고 앞에서 부터 문자열을 지운다.
예를들어 abcdabc에서 d가 delimiter라면 pos = 3,
delimiter의 사이즈는 1이기 때문에 앞에서 부터 4의 크기의 문자열을 제거해서 abc만 남게 된다.
input.erase(0, pos + delimiter.length());
진짜 제대로 설명해보려고 자세히 적었다.
그렇다면 진짜 코드를 봐보자.
vector<string> split(string input, string delimiter)
{
vector<string> ret;
long long pos = 0;
string token = "";
while ((pos = input.find(delimiter)) != string::npos)
{
token = input.substr(0, pos);
ret.push_back(token);
input.erase(0, pos + delimiter.length());
}
ret.push_back(input);
return ret;
}
int main()
{
string s = "안녕하세요 저는 산토스라고 합니다. 대충 살고 싶고 대충 개발하고 싶어요.";
vector<string> a = split(s, " ");
for (string b : a)
cout << b << '\n';
return 0;
}
결과물을 봐보자.
후 외워
vector<string> split(string input, string delimiter)
{
vector<string> ret;
long long pos = 0;
string token = "";
while ((pos = input.find(delimiter)) != string::npos)
{
token = input.substr(0, pos);
ret.push_back(token);
input.erase(0, pos + delimiter.length());
}
ret.push_back(input);
return ret;
}
더 빠른 split()도 있다.
위에서 설명한 것은 매번 erase()를 하는 단점이 있다.
이를 제거해서 좀 더 빠른 split() 코드는 다음과 같다.
vector<string> split(const string& input, string delimiter)
{
vector<string> result;
int start = 0;
int end = input.find(delimiter);
while (end != string::npos)
{
result.push_back(input.substr(start, end - start));
start = end + delimiter.size();
end = input.find(delimiter, start);
}
result.push_back(input.substr(start));
return result;
}
'C++ 나만의 복습' 카테고리의 다른 글
atoi(s.c_str())?? (0) | 2024.04.04 |
---|---|
memset이란 (0) | 2024.04.03 |
string - reverse() (0) | 2024.03.31 |
ASCII 코드와 문자열 (0) | 2024.03.31 |
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); (0) | 2024.03.31 |