28
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

getline()で文字列分割する方法

Last updated at Posted at 2019-07-08

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,' ')」でいいんでないの?
と思われるかもしれません.

しかし,以下のような例ではうまくいきません.

ダメな例1
#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を取り除いた以下の例もうまくいきません.

ダメな例2
#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()を使ってみてはいかがでしょうか?

28
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?