stringstream

stringstream STL은 C++에서 문자열을 다루는데 유용하게 사용된다.
주로 공백을 포함한 문자열을 처리하기 위한 작업을 이행하고, 필요한 정보를 추출하기에 적합하다.

1. 문자열에서 원하는 데이터 추출

#include <string>
#include <sstream>

int main(){
    int num;
    string s1 = "123 456";
    string s2 = "abc 123 456";
    stringstream ss(s1);

    while (ss >> num){cout << num << " ";}
    cout << endl;
    ss.clear();
    
    ss.str(s2);
    while (ss >> num){
        cout << "출력 x" << endl;
        cout << num << " ";
    }
    cout << endl;

    return 0;
}
output
123 456


stringstream은 주어진 문자열에서 필요한 자료형을 빼내는 것에 유용하다. 문자열에서 공백과 ‘\n’을 제외하고
원하는 자료형을 추출하는 방법이다. s2문자열을 stream으로 추출할 때, 첫 abc가 int형 변수인 num에 들어갈 수 없기에
반복문이 실행되지 않고 다음 코드인 cout « endl;으로 넘어간다.

2. clear();

int main(){
    int num;
    string s1 = "123 456";
    string s2 = "999 123 456";
    stringstream ss(s1);

    while (ss >> num){cout << num << " ";}
    cout << endl;
    //ss.clear();
    
    ss.str(s2);
    while (ss >> num){
        cout << "출력 x" << endl;
        cout << num << " ";
    }
    cout << endl;

    return 0;
}
output
123 456


그렇다면 위 코드는 왜 두 번째 반복문이 출력되지 않을까?

그 이유는 stream에서 첫 루프 반복이 끝난 이후 상태가 EOF로 설정되고
이후 상태를 초기화하지 않으면 문제가 발생한다. 따라서 주석 처리한 ss.clear();를 실행하면 두 번째 반복문까지 실행된다.


3. getline

int main(){
    string s;
    getline(cin, s);
    stringstream ss(s);
    
    string word;
    while (ss >> word){
        cout << word << " ";
    }
    cout << endl;
}

string을 입력받을 때, 공백을 포함하여 입력받고 싶다면 getline함수를 사용한다.
이후 문자열 s를 stringstream ss에 등록하고 데이터를 추출한다.



4. 코딩 테스트 예시

D 기업 프로그래밍 콘테스트 예선 문제 중 간단한 테스트를 예제로 사용법에 대하여 서술하겠다.

N명의 학생 정보가 있다. 학생 정보는 학생의 이름과 학생의 성적으로 구분된다.
각 학생의 이름과 성적 정보를 입력받아, 성적이 낮은 순서대로 출력하는 프로그램 작성하시오.

입력 예시
2
홍길도 95
이순신 77
int main(){
    map<string, string> m;
    int n;
    cin >> n;
    cin.ignore(); // 

    for (int i = 0; i < n; i++){
        string s;
        getline(cin, s);
        stringstream ss(s);
        string score, name;
        ss >> name >> score;
        m.insert({score, name});
    }

    for (auto iter : m){cout << iter.second << " ";}
    cout << endl;

    return 0;
}

첫 입력을 int형 정수 n으로 cin한다. 이때 cin » n; 이후 cin.ignore();을 작성한 이유는
cin » n;에서 남아있는 개행 문자(‘\n’)로 인해 getline함수가 올바르지 않게 실행될 수 있기 때문이다.

반복문을 n번 실행한다. 반복문안에서 getline함수를 통해 입력받은 문자열을 s에 저장
stringstream에 s를 넣고 처음 값을 name에 다음 값을 score에 넣은 뒤, map에 score, name 페어를 insert한다.

이때 map을 사용한 이유는 key, value 페어를 저장하기도 하고
key값을 기준으로 자동 오름차순 정렬되는 map에 특성이 있어, key에 해당하는 데이터에 score를 대입하여
문제에서 원하는 점수 기준 오름차순을 구현하였다.

마지막으로 map을 순회하며, second값인 name을 출력시킨다.

input, output
2
홍길동 95
이순신 77

. . .

이순신 홍길동



stringstream STL을 사용하면 문자열을 공백 기준으로 처리하기 유용하다.
string을 입력받을 땐, 개행 문자에 주의하여 입력받을 수 있도록 한다. ( cin.ignore(); 사용 )