본문 바로가기
백준일지

[C++]입출력: stringstream

by 민지기il 2024. 3. 26.

문자열로부터 입력을 받는 법 / 출력을 문자열로 바꾸는 법을 배운다.

 

stringstream을 이용하면 문자열로부터 입력을 받아올 수 있다.

이는 istringstream과 ostringstream의 기능을 모두 갖고 있는 클래스이지만 가독성을 위해 나눠서 작성한다.

 

방법1) stringstream 사용

    int num; //출력할 공간 만들기

    string nm="123 345 657"

    stringstream sstream; //strinstream 함수의 객체 sstream 생성

    sstream.str(nm); //객체 stream에 문자열 nm 넣기

    while(sstream>>num) cout<<num<<'\n'

//123

//345

//657 이렇게 출력된다.

 

방법2) istringstream 사용

    istringstream in_1("123 456 789"); //data type이 istringstream
    int n;
    while (in_1>>n) cout<<n<<'\n';

//123

///456

//789 출력된다.

 

방법3) ostringstream 사용

출력을 따로 ostringstream 변수에 저장해뒀다가 문자열로 바꿔준다.

int main(void) {
    fastio;
    ostringstream out;
    out<<"hello world!"<<'\n'; //hello world! 출력
    out<<setw(5)<<setfill('0')<<123<<'\n'; //00123 출력
    out<<fixed<<setprecision(10)<<123.456789<<'\n'; //123.4567890000 출력
    string s=out.str(); //버퍼에 있는 문자열을 str()로 가져와서 s에 저장
    cout<<s<<'\n'; //위에 것들 출력
}

<주의>

1. out << setw(5) << setfill('0') << "" << '\n'; //00000
setw(5)로 폭을 5로 설정하고 빈 공간을 0으로 채운다. 이후 <<""로 빈 문자열을 출력한다.
이 빈 문자열은 출력 폭에 포함되어서 '0'이 5개가 출력된다.
<< '\n'을 통해 개행 문자가 출력되는데, 00000 뒤에 추가되어 출력된다.
2. out << setw(5) << setfill('0') << '\n'; //0000
여기서는 << "" 대신에 << '\n'만 출력한다. 
이러면 빈 문자열이 없으므로 출력 폭에 채울 문자는 '0' 하나가 빠진다. 
따라서 '0'이 4개가 출력되고, 그 뒤에 개행 문자가 출력된다.

 

stringstream: C++ 표준 라이브러리에서 제공하는 함수로 문자열을 스트림으로 처리하는 데에 사용된다.
str()함수는 stringstream 클래스의 함수로 stringstream 객체에 문자열을 설정하거나 반환한다.

 

<백준>

8595번))

"a12bc9d7"에서 12, 9, 7만 따로 입력받는 방법을 생각해보자.

미리 문자열을 저장해둔 뒤 불필요한 문자를 공백으로 바꾸고 다시 istringstream으로 입력을 받아오면 원하는 부분만 가져올 수 있다.

int main() {
fastio;
long long n, sum = 0; string s; cin >> n >> s;
for (auto& i : s) if (!isdigit(i)) i = ' ';
stringstream in(s);
while (in >> n) sum += n;
cout << sum << '\n';

질문) 왜 n과 sum을 int로 처리하면 틀리지?

답) 틀린 이유는 숫자의 범위인데, 정말 극단적인 상황을 예시로 들어보면, 999999a999999a9999......가 계속되어 제한길이인 5백만자가 들어온다고 가정하자. 이떄 99999는 약 71만번 등장하게 되는데, 999999 * 71만 = 약 7.1천억이므로, int형 범위를 넘어선다.

따라서 int형이 아닌 long long형으로 해결해야한다. (int는 -2,147,483,648부터 +2,147,483,647까지 처리한다. 21억)

 

+) 왜

    string s;

    cin>>n;

    cin.ignore();

    getline(cin,s); 이렇게 안하지? 보니까 입력자체를 a12bc9d7 처럼 띄어쓰기 없이 한 단어만 하니까 cin도 가능! 

 

알아두기) for (auto& i : s) 는 s라는 컨테이너의 각 요소를 순회하면서 i 각 요소를 할당한다.
auto는 자료형을 자동으로 추론하라는 의미이다. &는 참조이다.
string s = "hello";
for (auto& i : s) {
    std::cout << i <<'\n'; // 각 문자를 출력
}
처음에 i는 'h'에 대한 참조가 되고, 그 다음에는 'e', 'l', 'l', 'o'에 대한 참조가 된다.

 

12605번)) 단어 순서 뒤집기

스페이스로 띄어쓰기 된 단어들의 리스트가 주어질때, 단어들을 반대 순서로 뒤집어라.

각 라인은 w개의 영단어로 이루어져 있으며, 총 L개의 알파벳을 가진다.

각 행은 알파벳과 스페이스로만 이루어져 있다. 단어 사이에는 하나의 스페이스만 들어간다.

int main(){

    fastio;

    int N; //N줄 입력

    string s;

    cin>>N;

    cin.ignore();

    for(int i=1; i<=N;i++){

        getline(cin,s);

        stringstream in(s); //in 객체가 s를 stream으로 다루게 만들어 준다.

        vector<string> v;

        while(in>>s) v.push_back(s); // in 스트림으로부터 문자열을 읽어와 s에 저장한다.

        for(int i=v.size()-1;i>=0;i--) cout<<v[i]<<' ';

        cout<<'\n';

    }

}

 

알아두기) vector 컨테이너: 자동으로 메모리가 할당되는 배열

<구조>

<size와 capacity>

-vector<int> v(5, 2); // 2로 초기화된 5개의 원소를 가지는 vector v

-vector<int>v = { 1, 2, 3}; // 초기화

-v.begin() 벡터 시작점의 주소 값 반환 / v.end() 벡터 (끝점+1) 주소값 반환

-v.capacity()는 1, 2, 4, 4, 8,8,8,8,16,16,16,16,16,16,16,16... 처럼 전에 것에 2배 갯수로 증가한다.

- 벡터는 정수, 문자, 실수, 문자열, 사용자가 정의한 클래스 등 다양한 자료형을 포함할 수 있다.

-정수와 문자가 혼합된 벡터도 만들 수 있다.

'백준일지' 카테고리의 다른 글

[C++] STL 자료구조: Queue  (0) 2024.04.03
[C++] STL 자료구조: stack  (0) 2024.03.31
[C++] STL 자료구조: string  (0) 2024.03.28
[C++] STL 자료구조: array, vector  (0) 2024.03.28
[C++] 입출력: cin, cout  (0) 2024.03.23