알고리즘 문제를 풀다 보면 입력을 공백 기준으로 나누어 받아야 하는 경우가 많다.

일반적으로 C++에서는 iostream의 표준 입력 스트림인 std::cin을 사용하여 입력을 받는다.

1
2
int a, b;
cin >> a >> b;

이처럼 >> 연산자를 사용하여 공백이나 줄바꿈을 기준으로 입력을 쉽게 구분할 수 있다. 하지만 관성적으로 쓰는 이런 방법 말고 다른 방법은 없을까? 하는 생각이 들어 여러가지 방법에 대해 서치해본 과정을 공유해보고자 한다.


1. std::cin>> 연산자

가장 간단한 방법이다.

1
2
3
4
5
6
7
#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c; // 공백으로 구분된 3개 숫자 입력
}
  • 특징
    • 공백 ( ), 탭 (\t), 줄바꿈 (\n)을 기준으로 자동 분리
    • 코딩테스트에서 가장 많이 사용
  • 한계
    • 공백이 포함된 문자열 전체를 한 줄로 받아야 하는 경우 사용 불가

2. 문자열로 한 줄 입력 후, 공백 단위로 분리 (getline + istringstream)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <sstream> // istringstream 사용
#include <string>
using namespace std;

int main() {
    string line;
    getline(cin, line); // 한 줄 전체 입력

    istringstream iss(line);
    string word;

    while (iss >> word) { // 공백 단위로 나누기
        cout << word << endl;
    }
}
  • 특징
    • 입력 개수가 가변적이거나, 한 줄 전체를 다루고 싶을 때 유용

3. strtok

1
2
3
4
5
6
7
char str[] = "10 20 30 40";
char* token - strtok(str, " ");

while (token != NULL) {
    cout << token << endl;
    token = strtok(NULL, " ");
}
  • 특징
    • C 기반 레거시 방식의 문자열 처리
    • 빠르지만 요즘 C++에서는 잘 사용하지 않음

4. vector<string> 으로 공백 분리

1
2
3
4
5
6
7
vector<int> v;
stringstream ss(line);
int x;

while (ss >> x) {
    v.push_back(x);
}

5. find + substr으로 직접 파싱 (C++ 17 이상)

1
2
3
4
5
6
7
8
9
10
11
string s = "10 20 30";
size_t pos;

while ((pos = s.find(' ')) != string::npos)
{
    string token = s.substr(0, pos);
    cout << token << endl;
    s.erase(0, pos + 1);
}

cout << s << endl;
  • 특징
    • 특정 구분자 처리 가능

6. 각 방법별 성능 비교

대략적인 속도 순서는

cin ≥ strtok > find/substr > stringstream

으로, 가장 느린 것은 보통 stringstream이다. 이유는 내부적으로 스트림 파싱 로직 + 형변환이 추가로 수행되기 때문이다.

하지만 일반적인 입력 규모에서는 큰 차이가 없고, n이 1,000,000개가 넘어가는 시점부터 cin이 눈에 띄게 안정적이게 된다.

결론적으로 공백 기준 입력을 처리하는 방법은 이렇게 여러 가지가 있지만, 대부분의 문제에서는 std::cin만으로도 충분히 해결할 수 있다. 입력 크기가 매우 큰 경우에 ios::sync_with_stdio(false) 설정만 함께 사용해주는 것만 유의해주자.

태그:

카테고리:

업데이트:

댓글남기기