template関数でsplit関数を実装する (空白文字列区切り)
template関数を使用することで、複数の型を同じ関数で扱うことができるようになります。
使い方
関数呼び出し時には、通常の関数呼び出しとは異なり、型を指定する必要があります。
const std::vector<std::string> result1 = SplitWords<std::string>(input1);
コード例1
#include <iostream> #include <vector> #include <sstream> template <class T> std::vector<T> SplitWords(const std::string &line) { std::vector<T> words; std::istringstream ss{line}; std::string buf; T t; int count = 0; while(ss >> t) { words.emplace_back(t); count++; } std::cout << "Loop count : " << count << std::endl; return words; } int main (void) { const std::string input1 = "abc\n def\n\n ghi\n"; const std::vector<std::string> result1 = SplitWords<std::string>(input1); std::cout << "result 1 size : " << result1.size() << std::endl; for (const auto & item : result1) { std::cout << item << std::endl; } const std::string input2 = "12.3\n 45.6\n 78.9\n"; const std::vector<double> result2 = SplitWords<double>(input2); std::cout << "result 2 size : " << result2.size() << std::endl; for (const auto & item : result2) { std::cout << item << std::endl; } const std::string input3 = "1\n 222\n\n 333\n 44\n\n\n"; const std::vector<double> result3 = SplitWords<double>(input3); std::cout << "result 3 size : " << result3.size() << std::endl; for (const auto & item : result3) { std::cout << item << std::endl; } EXIT_SUCCESS; }
Loop count : 3 result 1 size : 3 abc def ghi Loop count : 3 result 2 size : 3 12.3 45.6 78.9 Loop count : 4 result 3 size : 4 1 222 333 44
コード例2(istringstreamのeofメソッドを使った実装)
ifs.eof()の場合は、入力文字列に改行コードがある場合は、ループカウンタが余計に一回実行された。
この方法では、行中の改行文字列'\n'
は正しく認識できないため注意してください。
#include <iostream> #include <vector> #include <sstream> template <class T> std::vector<T> SplitWords(const std::string &line) { std::vector<T> words; std::istringstream ss{line}; std::string buf; int count = 0; while(!ss.eof()) { T t; ss >> t; words.emplace_back(t); count++; } std::cout << "Loop count : " << count << std::endl; return words; } int main (void) { const std::string input1 = "abc\n def\n\n ghi\n"; const std::vector<std::string> result1 = SplitWords<std::string>(input1); std::cout << "result 1 size : " << result1.size() << std::endl; for (const auto & item : result1) { std::cout << item << std::endl; } const std::string input2 = "12.3\n 45.6\n 78.9\n"; const std::vector<double> result2 = SplitWords<double>(input2); std::cout << "result 2 size : " << result2.size() << std::endl; for (const auto & item : result2) { std::cout << item << std::endl; } const std::string input3 = "1\n 222\n\n 333\n 44\n\n\n"; const std::vector<double> result3 = SplitWords<double>(input3); std::cout << "result 3 size : " << result3.size() << std::endl; for (const auto & item : result3) { std::cout << item << std::endl; } EXIT_SUCCESS; }
Loop count : 4 result 1 size : 4 abc def ghi Loop count : 4 result 2 size : 4 12.3 45.6 78.9 78.9 Loop count : 5 result 3 size : 5 1 222 333 44 44
リンク
[std::istringstream] 文字列 split (区切り文字 = 空白)
C++ テンプレート ヘッダと実装を別にした時に起こること
begin()よりもstd::begin()を使うと配列とコンテナを同様に扱える
*【C/C++】 streamクラスのeofメンバ - http://murakan.cocolog-nifty.com/blog/2009/12/cstreameof-7401.html