Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ stringstream 활용: 쉼표로 구분된 문자열에서 정수 추출하기


쉼표(,)로 구분된 여러 개의 정수가 포함된 문자열이 있다고 가정해 보겠습니다. 이때 각 정수를 분리해 내고, 정수 하나씩 서로 다른 줄에 출력해야 합니다. 이러한 작업은 C++의 stringstream(sstream 헤더)을 사용하면 손쉽게 해결할 수 있습니다.

stringstream은 C++ 표준 라이브러리에서 제공하는 문자열 기반 스트림 클래스입니다. 스트림에서 데이터를 꺼낼 때는 추출 연산자(>>)를, 스트림에 데이터를 넣을 때는 삽입 연산자(<<)를 사용하며, str() 함수를 이용하면 내부 문자열 버퍼의 내용을 설정하거나 가져올 수 있습니다.

예를 들어 입력 문자열이 s = "56,9,85,256,47"이라면 출력은 다음과 같습니다.

56
9
85
256
47

해결 알고리즘

이 문제는 다음 단계를 따라 해결할 수 있습니다.

  • take_int(string str) 함수를 정의합니다.
    • 입력 문자열로 초기화한 stringstream 객체 ss를 생성합니다.
    • 결과를 저장할 정수 벡터 result를 선언합니다.
    • ss에서 정수를 성공적으로 추출하는 동안 다음을 반복합니다.
      • 추출한 값 tmp를 result의 끝에 추가합니다.
      • 스트림에서 문자 하나(쉼표)를 읽어 건너뜁니다.
    • result를 반환합니다.
  • main 함수에서 다음을 수행합니다.
  • integers = take_int(s)를 호출하여 정수 목록을 얻습니다.
  • i가 0부터 integers의 크기 미만일 때까지 반복하며 각 정수를 한 줄에 하나씩 출력합니다.

동작 원리

여기서 핵심은 while(ss >> tmp) 조건입니다. 스트림에서 정수 추출에 성공하면 조건이 참이 되어 반복이 계속되고, 더 이상 읽을 정수가 없으면 거짓이 되어 루프가 자연스럽게 종료됩니다. 또한 정수와 정수 사이에는 항상 쉼표가 있으므로, 정수를 하나 읽은 뒤 ss >> ch;로 쉼표를 소비해 주어야 다음 반복에서 정수를 정확하게 읽을 수 있습니다.

예제 코드

아래 구현 예제를 통해 더 자세히 이해해 보겠습니다.

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

vector<int> take_int(string str) {
    stringstream ss(str);
    vector<int> result;
    char ch;
    int tmp;
    while(ss >> tmp) {
        result.push_back(tmp);
        ss >> ch;
    }
    return result;
}

int main(){
    string s = "56,9,85,256,47";
    vector<int> integers = take_int(s);
    for(int i = 0; i < integers.size(); i++)
        cout << integers[i] << "\n";
}

입력

56,9,85,256,47

출력

56
9
85
256
47

이 알고리즘은 문자열을 한 번만 순회하므로 시간 복잡도는 O(n)입니다. 참고로 구분자가 쉼표가 아닌 공백이나 다른 문자인 경우에도 동일한 원리로 처리할 수 있으며, C++11 이후 환경이라면 getline()과 stoi()를 조합하거나 정규식(regex)을 활용하는 방법도 좋은 대안이 될 수 있습니다.