C++で文字列を分割する場合は,find系統の関数を使って自作のsplit関数を実装することが一般的なのかと思います.
今回は,もっと簡単に文字列分割する方法を紹介します.
ずばり,「getline()」を使います.
この関数は元々「getline(cin, str)」のように,標準入力cinで文字列を1行取得して,既に宣言されている文字列strに代入するという処理によく使われます.
ただし,1行の中にスペースやカンマなどのデリミタが含まれており,それらを用いた分割を行いたい場合にも,実は使用可能です.(ということを最近知りました)
##標準的な方法
今回,分割対象の文字列を以下とします.
1行だけで,スペースによって区切られています.
A B C D E
スペースで分割し,vectorに格納します.
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main(void){
vector<string> v; // 分割した文字列を格納するvector
string str, s;
str = "A B C D E" // 分割対象の文字列str
stringstream ss{str}; // 入出力可能なsstreamに変換
while ( getline(ss, s, ' ') ){ // スペース(' ')で区切って,格納
v.push_back(s);
}
for (const string& s : v){ // vの中身を出力
cout << s << endl;
}
}
実行結果は以下の通りです.
しっかり分割できていますね.
A
B
C
D
E
ポイントは,stringstreamを使うことです.
分割対象の文字列を,stringstreamに変換します.
while ( getline(ss, s, ' ') ) の部分で,ssの中からスペース(' ')手前までの文字列をsとして取得し,それをvに代入しています.
##標準入力から取得した文字列の分割
通常の「getline(cin,str)」で対象文字列を一旦取得しておき,それをstringstream(ss)に変換してから,「getline(ss,s,' ')」を実行します.
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main(void){
vector<string> v;
string str, s;
getline(cin,str);
stringstream ss{str};
while ( getline(ss, s, ' ') ){
v.push_back(s);
}
for (const string& s : v){
cout << s << endl;
}
}
標準的な方法における「str = "A B C D E"」を,「getline(cin,str)」に変えただけですね.
これを見て,2回もgetline()呼ぶ必要なくない?
「getline(cin,str,' ')」でいいんでないの?
と思われるかもしれません.
しかし,以下のような例ではうまくいきません.
#include <iostream>
#include <vector>
using namespace std;
int main(void){
vector<string> v;
string str, s;
while (getline(cin, str, ' ')){
v.push_back(str);
};
for (const string& s : v){
cout << s << endl;
}
}
これを実行すると,シェルで文字列を打ち込み,Enterを押しても改行されるだけで,入力を求められ続けます.
つまり,whileのおかげで入力が終わりません(笑)
だからといって,whileを取り除いた以下の例もうまくいきません.
#include <iostream>
using namespace std;
int main(void){
vector<string> v;
string str;
getline(cin, str, ' '));
cout << str << endl;
}
この場合,仮に「A B C D」と入力しても,最初の「A」しか取得できません.
##おわりに
split関数を自作するのが面倒な方は,getline()を使ってみてはいかがでしょうか?