趣味は車輪の再発明♪

[C++] 文字列分割テンプレート関数


詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識
Gary Bradski Adrian Kaehler
オライリージャパン
売り上げランキング: 25,746


■ たかみんつ / ソフト開発メモINDEX / C++インデックス /


文字列(std::string)を任意の区切り文字で分割するテンプレート関数です。 C++では結構面倒な処理ですよね。最初から計画されていればよいのだけど、ふと必要になったら「えーっと?どうすんだっけ?」みたいに戸惑う感じ。 デバッグも含めて無駄に時間が過ぎていく。

Boostでは楽に出来るらしいですが、文字列分割するためだけに環境設定いじるのもなんだかなぁという時はぜひ御自由に、 GitHub Gist takamin/string_split.h からご利用ください。

string_split.h テンプレート関数です

#include <string>
template<class StorageType>
void split(
    char c, const std::string& s,
    StorageType& result)
{
    size_t pos, offset = 0;
    while (true) {
        pos = s.find(c, offset);
        if (pos == std::string::npos) {
            result.push_back(
                s.substr(offset, pos));
            break;
        }
        else {
            result.push_back(
                s.substr(offset, pos - offset));
            offset = pos + 1;
        }
    }
}

分割結果が保存される第三引数へは、vector<string>list<string> など、 push_back(string&)メソッドが定義されたクラスオブジェクトへの参照を指定できます。

test.cpp こちらはテストコード(長文失礼)

#include <iostream>
#include <typeinfo>
#include <assert.h>
#include "string_split.h"
#include <vector>
#include <list>
#include <deque>

using namespace std;

template <class StorageType>
void test_split(
    StorageType& split_result)
{
    split_result.clear();
    ::split(',', "", split_result);
    assert(split_result.size() == 1);
    assert(split_result.at(0) == "");

    split_result.clear();
    ::split(',', "A", split_result);
    assert(split_result.size() == 1);
    assert(split_result.at(0) == "A");


    split_result.clear();
    ::split(',', "AB", split_result);
    assert(split_result.size() == 1);
    assert(split_result.at(0) == "AB");


    split_result.clear();
    ::split(',', ",", split_result);
    assert(split_result.size() == 2);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "");


    split_result.clear();
    ::split(',', "A,", split_result);
    assert(split_result.size() == 2);
    assert(split_result.at(0) == "A");
    assert(split_result.at(1) == "");


    split_result.clear();
    ::split(',', ",A", split_result);
    assert(split_result.size() == 2);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "A");


    split_result.clear();
    ::split(',', ",A,", split_result);
    assert(split_result.size() == 3);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "A");
    assert(split_result.at(2) == "");


    split_result.clear();
    ::split(',', ",,", split_result);
    assert(split_result.size() == 3);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "");
    assert(split_result.at(2) == "");


    split_result.clear();
    ::split(',', "ABC,BCD", split_result);
    assert(split_result.size() == 2);
    assert(split_result.at(0) == "ABC");
    assert(split_result.at(1) == "BCD");


    split_result.clear();
    ::split(',', ",ABC,BCD", split_result);
    assert(split_result.size() == 3);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "ABC");
    assert(split_result.at(2) == "BCD");


    split_result.clear();
    ::split(',', "ABC,BCD,", split_result);
    assert(split_result.size() == 3);
    assert(split_result.at(0) == "ABC");
    assert(split_result.at(1) == "BCD");
    assert(split_result.at(2) == "");


    split_result.clear();
    ::split(',', "ABC,,BCD,", split_result);
    assert(split_result.size() == 4);
    assert(split_result.at(0) == "ABC");
    assert(split_result.at(1) == "");
    assert(split_result.at(2) == "BCD");
    assert(split_result.at(3) == "");


    split_result.clear();
    ::split(',', ",ABC,BCD,", split_result);
    assert(split_result.size() == 4);
    assert(split_result.at(0) == "");
    assert(split_result.at(1) == "ABC");
    assert(split_result.at(2) == "BCD");
    assert(split_result.at(3) == "");
    
    std::cerr << "test for "
        << typeid(split_result).name()
        << " pass." << std::endl;
}
int main(int argc, char*argv[]) {
    vector<string> vector_split_result;
    test_split(vector_split_result);
    deque<string> deque_split_result;
    test_split(deque_split_result);
    std::cerr << "all test pass." << std::endl;
}

結果をvectorとdequeで受け取るテストをやってます。MinGWのg++で確認済みです。


Pythonプロフェッショナルプログラミング 第2版
秀和システム (2015-05-21)
売り上げランキング: 1,813


クラウドではじめる機械学習 Azure MLでらくらく体験
脇森浩志 杉山雅和 羽生貴史
リックテレコム
売り上げランキング: 2,081

実践Node.js プログラミング (Programmer's SELECTION)
Mike Cantelon Marc Harter T.J. Holowaychuk Nathan Rajlich
翔泳社
売り上げランキング: 40,213

■ たかみんつ / ソフト開発メモINDEX / C++インデックス /



RSS Feed Widget
[C++] 文字列分割テンプレート関数
(http://bicycle.life.coocan.jp/takamints/index.php/doc/cplusplus/split)
by Koji Takami ( email: vzg03566@gmail.com, GitHub: takamin )