입력을 공백 기준으로 구분해서 받는 방법 : C++
알고리즘 문제를 풀다 보면 입력을 공백 기준으로 나누어 받아야 하는 경우가 많다.
일반적으로 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) 설정만 함께 사용해주는 것만 유의해주자.
댓글남기기