호우동의 개발일지

Today :

article thumbnail

썸네일

백준에서 알고리즘 문제를 풀다 보면 띄어쓰기나 특정 단어를 기준으로 분리해야 할 때가 있다.

나도 그런 일이 잦아서 사용하기 편한 라이브러리 함수들을 쓰려고 하는데,
이상하게 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 쓰는 게 덜 헷갈리지 않을까?

 

참고 사이트

https://chbuljumeok1997.tistory.com/42

 

코테용- c++ split 함수 (string 나누기/string 잘라서 배열에 넣기)

코테를 c++로 하면서 느낀점은..속도를 제외하고 c++의 좋은점을 아직 잘 모르겠다는 점이다.. 항상 코딩테스트를 보면 string을 잘라야하는 순간이 생기는데 그럴때마다 자바로 갈아타고 싶다.. 이

chbuljumeok1997.tistory.com

https://roadtosuccess.tistory.com/84

 

[C++] string 자르는 2가지 방법(feat. istringstream 이용하기, substr 이용하기)

C++을 사용하다보면 문자열을 자를 때, python과 Java와 다르게 .split()이라는 내장함수가 없기 때문에 다른방법으로 만들어서 사용해야한다. C++에서 간단하게 문자열을 자르는 방법 두가지를 작성

roadtosuccess.tistory.com