C++のgetlineでstringをsplitする際の注意点2

C++のgetlineでstringをsplitする際の注意点 - bettamodokiのメモのつづき. Pythonのsplit関数の挙動を確認してみた.

print("aaa,bbb,ccc".split(','))  # => ['aaa', 'bbb', 'ccc']
print("aaa,bbb,,ccc".split(','))  # => ['aaa', 'bbb', '', 'ccc']
print("aaa,bbb,ccc,".split(','))  # => ['aaa', 'bbb', 'ccc', '']
print("aaa".split(','))  # => ['aaa']
print("".split(','))  # => ['']

空文字を与えた場合, 空のリストではなく空文字を要素とするリストを返す. つまり, 文字列inputに含まれるdelimiterの数+1の要素を持つリストを常に返す.

https://docs.python.jp/3/library/stdtypes.html#str.split

というわけで少しだけ改変を加えた.

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

std::vector<std::string> split(const std::string& input, char delimiter)
{
    std::istringstream stream(input);
    std::string field;
    std::vector<std::string> result;
    while (std::getline(stream, field, delimiter)) {
        result.push_back(field);
    }
    if (input.empty() || input.back() == delimiter) {
        result.push_back("");
    }
    return result;
}

void test(const std::string& input)
{
    std::cout << "'" << input << "'" << " => [";
    for (const std::string& s : split(input, ',')) {
        std::cout << "'" << s << "', ";
    }
    std::cout << "]" << std::endl;
}

int main()
{
    test("aaa,bbb,ccc");
    test("aaa,bbb,,ccc");
    test("aaa,bbb,ccc,");
    test("aaa");
    test("");
}

結果は以下の通り.

'aaa,bbb,ccc' => ['aaa', 'bbb', 'ccc', ]
'aaa,bbb,,ccc' => ['aaa', 'bbb', '', 'ccc', ]
'aaa,bbb,ccc,' => ['aaa', 'bbb', 'ccc', '', ]
'aaa' => ['aaa', ]
'' => ['', ]

https://onlinegdb.com/rk7jOW0-7

上に書いた通り, 空文字を入力とした場合の挙動が異なるため, いずれにせよ自分が何を求めているのかに注意して使うほうが良い.