トリッカーに乗る豆腐メンタルの日記

トリッカー乗って遊んでる人の日記

C++のstringstreamでsplit的なものを書こうとしてハマった話

C++初心者がpythonとかにあるsplit関数的なものを書いたときの自分用備忘録。
istringstremの仕様をちゃんと理解していなくて、文字列の最後にスペースやタブがある場合にアタフタしたって話だゾ。
C++は赤ちゃんレベルなので間違っているポイントあればマサカリをオナシャス!

環境

何がしたい?

"aaa bbb ccc"

みたいな文字列から

["aaa", "bbb", "ccc"]

みたいなリストに変換したいだけ。
事前に要素数がわかれば簡単だけど、要素数がわからない or そもそも要素数を調べたいっていう状況。

istringstremを使う

google先生に聞いた結果、こんな実装が見つかった。

#include <iostream>
#include <sstream>
#include <vector>

int main()
{
    std::string line = "aaa bbb ccc";

    std::vector<std::string> vec;
    std::string str;

    std::istringstream iss(line);
    while (!iss.eof()) {
        iss >> str;
        vec.push_back(str);
    }

    // output
    std::cout << "vector length : " << std::to_string(vec.size()) << std::endl;
    for (auto s : vec)
        std::cout << s << std::endl;

    return 0;
}

出力↓

vector length : 3
aaa
bbb
ccc

なんだか動いてそうでヨシ!

文字列として最後にスペースがあるクソ文字列を突うずるっ込んってみる。
上のコードで、文字列を↓に変える

std::string line = "aaa bbb ccc ";

出力↓

vector length : 4
aaa
bbb
ccc
ccc

クゥーン…
\tや\nにしても同様に最後の要素が重複して、ほんとひで
文字列が末端のときに読み込んで初めてeofがtrueになるって仕様なんですね。

getlineを使う

再びgoogle先生に聞いたらgetlineを使う方法がモリモリ出てきた。

#include <iostream>
#include <sstream>
#include <vector>

int main()
{
    std::string line = "aaa bbb ccc";

    std::vector<std::string> vec;
    std::string str;

    std::stringstream ss(line);

    while (getline(ss, str, ' ')) {
        vec.push_back(str);
    }

    // output
    std::cout << "vector length : " << std::to_string(vec.size()) << std::endl;
    for (auto s : vec)
        std::cout << s << std::endl;

    return 0;
}

出力↓

vector length : 3
aaa
bbb
ccc

ヨシ!



文字列の末尾にスペースを入れてみる

std::string line = "aaa bbb ccc ";

出力↓

vector length : 3
aaa
bbb
ccc

やったぜ。

おまけ; pythonの場合

line = 'aaa bbb ccc'
vec = line.split()
print('vector length : ' + str(len(vec)))
[print(s) for s in vec]

やpn1

5/23 追記

getlineでやる方法はパッと見うまくいくんだけど、スペースが二個あると空文字がベクトルに紛れ込んでしまう。

じゃけん、ダサいけどif文で空文字つまみ出しましょうねー。

    while (getline(ss, str, ' ')) {
        if (!str.empty())
            vec.push_back(str);
    }

参考

http://risuo.hatenablog.com/entry/20120719/1342674411
https://qiita.com/tarokun/items/526c6d65d5b3024d6caa