「std::stringにはstrtokみたいなのないの?」 って訊かれた。
ないのよねー ^^;
いいもんいいもん、作ればあるもん! ってんで作ってみた。
# boost::tokenizer はもっと高機能です
----- tokenizer.h -----
#ifndef TOKENIZER_H__
#define TOKENIZER_H__
#include <string> // string
#include <utility> // pair
template<typename charT, typename traits=std::char_traits<charT>,
typename alloc=std::allocator<charT> >
class tokenizer {
public:
typedef std::basic_string<charT,traits,alloc> string_type;
typedef std::pair<typename string_type::size_type,
typename string_type::size_type> range_type;
// コンストラクタ: 区切り文字の集合を引数に与える
explicit tokenizer(const string_type& delim) : delim_(delim) {}
// 与えた文字列のトークン分割を開始する
void start(const string_type& source) { source_ = source; reset(); }
// startに与えた文字列のトークン分割を最初からやりなおす
void reset() { range_.first = 0; range_.second = 0; }
// トークンを切り出す。切り出すトークンがなければfalseを返す
bool next() {
range_.first =
source_.find_first_not_of(delim_, range_.first + range_.second);
if ( range_.first == std::string::npos ) {
return false;
}
range_.second = source_.find_first_of(delim_, range_.first);
if ( range_.second == std::string::npos ) {
range_.second = source_.size() - range_.first;
return true;
}
range_.second -= range_.first;
return true;
}
// nextで切り出されたトークンを返す
string_type token() const
{ return source_.substr(range_.first, range_.second); }
// next切り出されたトークンの位置と長さを返す
range_type range() const { return range_; }
private:
string_type source_; // 分割対象となる文字列
string_type delim_; // 区切り文字の集合
range_type range_; // トークンの位置と長さ
};
#endif
---- つかいかた -----
#include <iostream>
#include "tokenizer.h"
int main() {
tokenizer<char> tk(",.");
tk.start("Hello,world.");
while ( tk.next() ) {
std::cout << tk.token() << std::endl;
}
}