[C++]입출력: stringstream
문자열로부터 입력을 받는 법 / 출력을 문자열로 바꾸는 법을 배운다.
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배 갯수로 증가한다.
- 벡터는 정수, 문자, 실수, 문자열, 사용자가 정의한 클래스 등 다양한 자료형을 포함할 수 있다.
-정수와 문자가 혼합된 벡터도 만들 수 있다.