[C++] sstream으로 문자열 조작하기
문자열 조작이 필요한 이유
여러 종류의 알고리즘 문제에서 자주 사용되는 것이 “문자열 조작”입니다.
한 문자열 안에 여러 정보가 함께 주어지거나 변수와 함께 특정 형식으로 출력해야 하는 경우가 있습니다.
예를들어, 공백으로 구분된 여러 정보가 한 개의 문자열로 주어질 때
각 정보를 하나씩 vector에 저장하는 함수를 구현하려고 합니다.
이 함수를 하드 코딩으로 구현하면 아래와 같이 구현할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<string>
#include <vector>
using namespace std;
int main() {
string order = "ABC 123 3.14";
vector<string> info;
int start_index = 0;
for(int end_index = 1; end_index < order.size(); ++end_index) {
if(order[end_index] == ' ') {
user_name.push_back(string(order.begin() + start_index, order.begin() + end_index));
start_index = end_index + 1;
} else if(end_index + 1 == order.size()) {
user_name.push_back(string(order.begin() + start_index, order.end()));
}
}
for(auto name : user_name) {
cout << name << endl;
}
/*
[출력 결과]
ABC
123
3.14
*/
return 0;
}
위와 같은 코드는 가독성이 떨어져 기능 수정, 확장이 어렵다는 단점이 존재합니다.
C++ STL에서는 sstream 헤더에서 위 코드를 개선할 수 있는 여러 기능을 제공합니다.
sstream 헤더에는 여러 클래스가 존재하지만 이 포스트에서는 자주 사용되는
‘istringstream, ostringstream, stringstream’에 대해서 설명하겠습니다.
istringstream
이 클래스는 생성자로 전달받은 문자열에서 공백(‘ ‘, ‘\n’, ‘\t’ 등)을 기준으로 나눌 수 있습니다.
위에서 하드 코딩했던 내용을 사용하면 아래의 코드처럼 개선할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <sstream>
using namespace std;
int main() {
istringstream iss("ABC 123 3.14");
string alpha;
int number;
float PI;
iss >> alpha >> number >> PI;
cout << alpha << endl << number << endl << PI;
return 0;
}
위 코든느 하드 코딩 보다 비교적 간략하고
심지어 원하는 자료형으로 전달받을 수 있다는 장점이 있습니다.
반드시 int, float으로 받아야 하는 것이 아니기 때문에 3개의 정보를 문자열로 받을 수 있습니다.
ostringstream
이 클래스는 C++20의 format 헤더와 비슷하게 사용할 수 있습니다.
이 클래스 객체와 « 연산자로 함께 원하는 모양의 문자열을 만들 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <sstream>
using namespace std;
int main() {
ostringstream oss("ABC 123 3.14");
oss << "ABC" << endl << 123 << endl << 3.14;
cout << oss.str();
return 0;
}
이 클래스 객체는 문자열만 아니라 다른 기본 자료형도 받을 수 있다는 특징이 있습니다.
stringstream
이 클래스는 이전 istringstream, ostringstream의 기능을 함께 사용할 수 있는 클래스입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <sstream>
using namespace std;
int main() {
// istreamstring처럼 사용하기
stringstream iss("ABC 123 3.14");
string alpha;
int number;
float PI;
iss >> alpha >> number >> PI;
cout << alpha << endl << number << endl << PI << endl;
// ostreamstring처럼 사용하기
stringstream oss("ABC 123 3.14");
oss << "ABC" << endl << 123 << endl << 3.14;
cout << oss.str();
return 0;
}
추가로 동일한 유형의 문자열이 반복적으로 주어질 경우 아래와 같이 사용할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <sstream>
using namespace std;
int main() {
// istreamstring처럼 사용하기
stringstream ss("my_name your_name our_name");
string name;
while(ss >> name) {
cout << name << endl;
}
return 0;
}