백준에서 알고리즘 문제를 풀다 보면 띄어쓰기나 특정 단어를 기준으로 분리해야 할 때가 있다.
나도 그런 일이 잦아서 사용하기 편한 라이브러리 함수들을 쓰려고 하는데,
이상하게 Split 관련 부분은 항상 헷갈려서 검색을 하게 된다.
그래서 이번 기회에 블로그에 확실히 정리하려고 한다.
istringstream
#include <sstream> 헤더를 포함시키면 사용 가능
문자열 format을 파싱(parsing)할 때 쓰는 클래스이다.
문자열에서 필요한 값을 추출하고 공백과 '\n'을 무시한다.
코딩 테스트에서 활용
#include <iostream>
#include <sstream>
using namespace std;
int main(){
string str1 = "This is Test";
string str2 = "AB/CDE/DFDG/ASCD";
//istringstream 변수 ss에 문자열 str을 넣어 초기화
istringstream ss1(str1);
istringstream ss2(str2);
string buffer; // 분리된 문자열을 넣는 버퍼
// istringstream, 문자열, 구분 문자 순서
// 띄어쓰기를 구분자로 분리됨
while(getline(ss1,buffer,' ')){
cout << buffer << endl;
}
cout << endl;
// 이번에는 '/'를 구분자로 문자 나눔
while(getline(ss2,buffer,'/')){
cout << buffer << endl;
}
}
// 출력 결과
// This
// is
// Test
// AB
// CDE
// DFDG
// ASCD
기본적으로 istringstream 자체에 문자열을 구분해 주는 기능 자체가 있다.
하지만 getline을 통해 어떤 구분자를 써서 나눴는지 알려주는 게
명시적으로 알아보기 쉬워서 나는 해당 방식을 사용한다.
응용 사용법
기본적으로 istringstream은
띄어쓰기에 대해 문자열을 구분한다.
그래서 getline 없이 istringstream을 선언하는 것만으로도 split이 된다.
만약 문자열의 구분자가 공백이고 한 번에 두 개 이상의 문자를 써야 한다면,
해당 방식을 사용하는 것도 좋다.
#include <iostream>
#include <sstream>
using namespace std;
int main(){
string str1 = "This is Test";
string str2 = "AB/CDE/DFDG/ASCD";
//istringstream 변수 ss에 문자열 str을 넣어 초기화
istringstream ss1(str1);
istringstream ss2(str2);
// 띄어쓰기는 자동으로 문자열에서 분리
cout << ss1.str() << endl;
cout << ss2.str() << endl;
string a,b;
// 분리된 첫번째 문자열은 a, 두번째 문자열은 b에 들어감
ss1 >> a >> b;
cout << "a의 값 : " << a << endl;
cout << "b의 값 : " << b;
}
// 출력 결과
// This is Test
// AB/CDE/DFDG/ASCD
// a의 값 : This
// b의 값 : is
이런 식으로 초기화를 해준 후
str() 함수만 사용해 주면 알아서 다 split 된 것을 확인할 수 있다.
게다가 해당 방식을 사용하면
ss1 >> a >> b
같이 분리된 문자열을 원하는 개수만큼 간편하게 사용 가능
stringStream
#include <sstream>을 헤더를 포함시키면 사용 가능
문자열에서 동작하는 스트림 클래스
문자열에서 내가 원하는 자료형의 데이터를 추출할 때 사용
#include <iostream>
#include <sstream>
using namespace std;
int main(){
string str1 = "123\n34 55 034\n 043";
string str2 = "This is Test Case";
stringstream ss1(str1);
stringstream ss2(str2);
int num;
string tmp;
// 정수형 num에 띄어쓰기나 '\n'까지 인식해서 담음
while(ss1 >> num) cout << num << endl;
cout << endl;
// 문자열 tmp에 담음
while(ss2 >> tmp) cout << tmp << endl;
}
//출력
// 123
// 34
// 55
// 34
// 43
// This
// is
// Test
// Case
stringstream을 사용하면 문자열을 자를 수 있고,
뿐만 아니라 원하는 자료형의 데이터로 변환이 가능하다.
그래서 만약 분리한 문자열을 다른 데이터형으로 바꿔야 한다면
istringstream대신 stringstream을 쓰는 게 더 편할 것 같다.
#include <iostream>
#include <sstream>
using namespace std;
int main(){
string str = "This,is,Test,Case";
stringstream ss(str);
string tmp;
while(getline(ss,tmp,',')){
cout << tmp << endl;
}
}
//출력
// This
// is
// Test
// Case
stringstream으로도 istringstream처럼
똑같은 형식으로 getline을 사용할 수 있다.
물론 이때는 구분자를 줄 수 있지만,
두 번째 받아주는 수를 무조건 문자열로 받아줘야 하기 때문에
stringstream에 장점이었던 자동 형변환은 사용할 수 없다.
그래서 그냥 이 기능 사용하려면
그냥 안 헷갈리게 istringstream 쓰는 게 덜 헷갈리지 않을까?