C++ 에서 문자열을 파싱하는 (자르는) (토큰화하는) 방법을 정리해보자.
문자열변수.find("검색할 문자열");
// 성공 : 찾은 하는 문자열의 첫 번째 인덱스 주소 반환한다.
// 실패 : string::npos 를 반환한다.
int main()
{
    string s = "Good Morning";
    int a = s.find("Good");
    int b = s.find(" ");
    int c = s.find("Morning");
    cout << a << " " << b << " " << c;
    return 0;
}

문자열변수.substr(시작할 위치, 길이);
// 시작할 위치로부터 길이 만큼의 문자열을 잘라낸다.
// 만약 길이를 생략할 경우 문자열의 끝까지 다르게 된다.
int main()
{
    string s = "Good Morning";
    string a = s.substr(0, 4);
    string b = s.substr(4, 1);
    string c = s.substr(5);
    cout << a << "\n";
    cout << b << "\n";
    cout << c << "\n";
    return 0;

위의 2개의 함수 find, substr 를 이용해 문자열을 자르는 것이 가능하다.
#include <string>
#include <iostream>
using namespace std;
int main()
{
    string s = "Good Morning";
    s += " "; // 문자열의 마지막에 공백 추가
    string delimiter = " "; // 구분자 
    int cur_pos = 0;
    int pos;
    while ((pos = s.find(delimiter, cur_pos)) != string::npos)
    {
        int len = pos - cur_pos;
        string result = s.substr(cur_pos, len);
        cout << result << "\n";
        cur_pos = pos + 1;
    }
    return 0;
}

문자열의 마지막의 공백 (구분자) 을 추가하지 않을 시 첫번째 공백을 만나고 Good 을 출력한 뒤
더 이상 문자열의 공백이 존재하지 않으므로 Morning 을 출력하지 못하고 끝나게 된다.
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    string s = "Good Morning";
    s += " ";
    string delimiter = " ";
    vector<string> my_v;
    int cur_pos = 0;
    int pos;
    while ((pos = s.find(delimiter, cur_pos)) != string::npos)
    {
        my_v.push_back(s.substr(0, pos));
        s.erase(0, pos + delimiter.length());
    }
    for (auto i : my_v)
    {
        cout << i << "\n";
    }
    return 0;
}
 
문자열에 여러 자료형이 들어있거나 파싱하는 작업이 필요할때 사용하는 라이브러리로
입력 스트림으로 문자열 안의 공백과 "\n" 을 기준으로  여러 개의 다른 형식으로
차례대로 분리할 때 사용한다.
#include <iostream>
#include <typeinfo>
#include <sstream>
using namespace std;
int main()
{
    string s = "Hello My Age is 25";
    istringstream iss(s);
    string s1, s2, s3, s4;
    int age;
    iss >> s1 >> s2 >> s3 >> s4 >> age;
    cout << s1 << "\n";
    cout << s2 << "\n";
    cout << s3 << "\n";
    cout << s4 << "\n";
    cout << age << "\n";
    return 0;
}

반복문으로 사용 시 자료형에 맞는 데이터가 없을 때까지 실행된다.
#include <iostream>
#include <typeinfo>
#include <sstream>
using namespace std;
int main()
{
    string s = "22323Hello";
    istringstream iss(s);
    int n;
    while (iss >> n)
        cout << n << "\n";
    return 0;
}

출력 스트림으로 문자열을 조립하거나 특정 형식을 문자열로 변환하기 위해 사용한다.
#include <iostream>
#include <typeinfo>
#include <sstream>
using namespace std;
int main()
{
    ostringstream oss;
    string s1 = "Hello";
    string s2 = "My";
    string s3 = "Name";
    string s4 = "is";
    int age = 25;
	
    // 문자열을 조립
    oss << s1 << " " << s2 << " " << s3 << " " << s4 << " " << age;
    cout << oss.str(); // 만든 문자열을 가져옴
}

입출력 스트림으로 입력과 출력에 대해 모두 사용 가능하다.
istringstream 과 ostreamstring 대신 stringstream 사용
#include <iostream>
#include <typeinfo>
#include <sstream>
using namespace std;
int main()
{
    string s = "22323Hello";
    stringstream iss(s);
    int n;
    while (iss >> n)
        cout << n << "\n";
    stringstream oss;
    string s1 = "Hello";
    string s2 = "My";
    string s3 = "Name";
    string s4 = "is";
    int age = 25;
    oss << s1 << " " << s2 << " " << s3 << " " << s4 << " " << age;
    cout << oss.str();
}

sstream 라이브러리를 통해 원하는 구분자를 통한 문자열 파싱이 가능하다.
이전 문자열 입력에서 보았듯이 getline 을 통해 공백이나 '\n' 이 아닌 다른 문자열 기준으로
구분이 가능하다.
https://velog.io/@sw801733/C-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0
#include <iostream>
#include <string>
#include <typeinfo>
#include <sstream>
using namespace std;
int main()
{
    string s = "My,Age,is,25";
    stringstream ss(s);
    string token;
    while (getline(ss, token, ','))
    {
        cout << token << "\n";
    }
}
공백이 포함된 구분자 (", ") 일 경우
#include <iostream>
#include <string>
#include <typeinfo>
#include <sstream>
#include <algorithm>
using namespace std;
int main()
{
    string s = "My, Age, is, 25";
    stringstream ss(s);
    string token;
    while (getline(ss, token, ','))
    {
    	// 공백 제거
        token.erase(remove_if(token.begin(), token.end(), ::isspace), token.end());
        cout << token << "\n";
    }
    return 0;
}