テキスト(意味のあるテキストまたは算術式)があり、それを単語に分割したい。
単一の区切り文字がある場合、次を使用します。
std::stringstream stringStream(inputString);
std::string Word;
while(std::getline(stringStream, Word, delimiter))
{
wordVector.Push_back(Word);
}
文字列をいくつかの区切り文字でトークンに分割するにはどうすればよいですか?
区切り文字の1つが改行であると仮定すると、次の行は行を読み取り、区切り文字でさらに分割します。この例では、区切り文字スペース、アポストロフィ、およびセミコロンを選択しました。
std::stringstream stringStream(inputString);
std::string line;
while(std::getline(stringStream, line))
{
std::size_t prev = 0, pos;
while ((pos = line.find_first_of(" ';", prev)) != std::string::npos)
{
if (pos > prev)
wordVector.Push_back(line.substr(prev, pos-prev));
prev = pos+1;
}
if (prev < line.length())
wordVector.Push_back(line.substr(prev, std::string::npos));
}
ブーストがある場合は、次を使用できます。
#include <boost/algorithm/string.hpp>
std::string inputString("One!Two,Three:Four");
std::string delimiters("|,:");
std::vector<std::string> parts;
boost::split(parts, inputString, boost::is_any_of(delimiters));
手動の方法を誰も指摘しなかった理由はわかりませんが、ここにあります:
const std::string delims(";,:. \n\t");
inline bool isDelim(char c) {
for (int i = 0; i < delims.size(); ++i)
if (delims[i] == c)
return true;
return false;
}
および機能:
std::stringstream stringStream(inputString);
std::string Word; char c;
while (stringStream) {
Word.clear();
// Read Word
while (!isDelim((c = stringStream.get())))
Word.Push_back(c);
if (c != EOF)
stringStream.unget();
wordVector.Push_back(Word);
// Read delims
while (isDelim((c = stringStream.get())));
if (c != EOF)
stringStream.unget();
}
この方法で、必要に応じてdelimsで何か便利なことができます。
ブーストを使用せずに自分で行う方法に興味がある場合。
区切り文字列が非常に長いと仮定します-文字列のすべての文字が区切り文字であるかどうかをチェックするMを言うと、コストO(M)それぞれなので、ループでそうします元の文字列のすべての文字、たとえば長さNの場合、O(M * N)です。
ディクショナリを使用します(マップ-「区切り文字」から「ブール値」のように-ここでは、各区切り文字のindex = ascii値がtrueである単純なブール配列を使用します)。
文字列を繰り返し処理し、charが区切り文字であるかどうかをO(1)でチェックします。これにより、最終的にO(N)全体が得られます。
これが私のサンプルコードです。
const int dictSize = 256;
vector<string> tokenizeMyString(const string &s, const string &del)
{
static bool dict[dictSize] = { false};
vector<string> res;
for (int i = 0; i < del.size(); ++i) {
dict[del[i]] = true;
}
string token("");
for (auto &i : s) {
if (dict[i]) {
if (!token.empty()) {
res.Push_back(token);
token.clear();
}
}
else {
token += i;
}
}
if (!token.empty()) {
res.Push_back(token);
}
return res;
}
int main()
{
string delString = "MyDog:Odie, MyCat:Garfield MyNumber:1001001";
//the delimiters are " " (space) and "," (comma)
vector<string> res = tokenizeMyString(delString, " ,");
for (auto &i : res) {
cout << "token: " << i << endl;
}
return 0;
}
注:tokenizeMyStringは値によってベクトルを返し、最初にスタック上に作成するため、ここではコンパイラーの力を使用しています>>> RVO-戻り値の最適化:)