В прошлом году мне понадобилось доработать токенизатор в моем движке. Поэтому я быстро набросал новую простейшую версию.
Токенизатор хранит лишь начало/конец токена аля std::string_view. Поддерживается UTF-8. Поддерживает произвольный набор разделителей и их произвольную длину. Может быть достаточно легко доработан до поддержки японского, корейского, тайского и прочих языков.
Тут выкладываю лишь свой набросок токенизатора. Доработанная версия, вошедшая в движок, была сделана на его основе.
#include <iostream> #include <string> #include <vector> class Tokenizer { public: using DelimetersList = std::vector<std::string>; Tokenizer(const DelimetersList& delimiters) : m_delimiters(delimiters) { } void tokenize(const std::string& str) { m_tokens.clear(); size_t start = 0; size_t end = 0; while (end != str.length()) { auto delimiter = findDelimiter(str, start); end = delimiter.pos; m_tokens.push_back({ start, end - start }); start = end + delimiter.length; } } struct Token { size_t begin; size_t length; }; using TokensList = std::vector<Token>; const TokensList& getTokens() const { return m_tokens; } private: struct Delimiter { size_t pos; size_t length; }; Delimiter findDelimiter(const std::string& str, size_t start) const { size_t minPos = str.length(); size_t length = 0; for (auto& delimiter : m_delimiters) { auto pos = str.find(delimiter, start); if (pos < minPos) { minPos = pos; length = delimiter.length(); } } return { minPos, length }; } private: const DelimetersList m_delimiters; private: TokensList m_tokens; }; int main() { std::string s = "お客#様のレビ#ュー\nはゲー\nム#の改善に役#立ちます!"; std::cout << "string: \n" << s << "\n----\n" << std::endl; Tokenizer tokenizer({ " ", "\n", "\r", "#" }); tokenizer.tokenize(s); for (auto& t : tokenizer.getTokens()) { std::cout << s.substr(t.begin, t.length) << std::endl; } return 0; }