Токенизировать строку и включить разделители в С++
Я хочу отметить следующее, но не знаю, как включить в него разделители.
void Tokenize(const string str, vector<string>& tokens, const string& delimiters)
{
int startpos = 0;
int pos = str.find_first_of(delimiters, startpos);
string strTemp;
while (string::npos != pos || string::npos != startpos)
{
strTemp = str.substr(startpos, pos - startpos);
tokens.push_back(strTemp.substr(0, strTemp.length()));
startpos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, startpos);
}
}
Ответы
Ответ 1
С++ String Toolkit Library (StrTk) имеет следующее решение:
std::string str = "abc,123 xyz";
std::vector<std::string> token_list;
strtk::split(";., ",
str,
strtk::range_to_type_back_inserter(token_list),
strtk::include_delimiters);
В результате token_list должен иметь следующие элементы:
Token0 = "abc,"
Token1 = "123 "
Token2 = "xyz"
Дополнительные примеры можно найти Здесь
Ответ 2
Теперь я немного неряшлив, но это то, чем я закончил. Я не хотел использовать boost, так как это школьное задание, и мой инструктор хотел, чтобы я использовал find_first_of для выполнения этого.
Спасибо за помощь всем.
vector<string> Tokenize(const string& strInput, const string& strDelims)
{
vector<string> vS;
string strOne = strInput;
string delimiters = strDelims;
int startpos = 0;
int pos = strOne.find_first_of(delimiters, startpos);
while (string::npos != pos || string::npos != startpos)
{
if(strOne.substr(startpos, pos - startpos) != "")
vS.push_back(strOne.substr(startpos, pos - startpos));
// if delimiter is a new line (\n) then addt new line
if(strOne.substr(pos, 1) == "\n")
vS.push_back("\\n");
// else if the delimiter is not a space
else if (strOne.substr(pos, 1) != " ")
vS.push_back(strOne.substr(pos, 1));
if( string::npos == strOne.find_first_not_of(delimiters, pos) )
startpos = strOne.find_first_not_of(delimiters, pos);
else
startpos = pos + 1;
pos = strOne.find_first_of(delimiters, startpos);
}
return vS;
}
Ответ 3
Я не могу следовать вашему коду, не могли бы вы опубликовать рабочую программу?
Во всяком случае, это простой токенизатор, не проверяющий случаи краев:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void tokenize(vector<string>& tokens, const string& text, const string& del)
{
string::size_type startpos = 0,
currentpos = text.find(del, startpos);
do
{
tokens.push_back(text.substr(startpos, currentpos-startpos+del.size()));
startpos = currentpos + del.size();
currentpos = text.find(del, startpos);
} while(currentpos != string::npos);
tokens.push_back(text.substr(startpos, currentpos-startpos+del.size()));
}
Пример ввода, разделитель = $$
:
Hello$$Stack$$Over$$$Flow$$$$!
лексем:
Hello$$
Stack$$
Over$$
$Flow$$
$$
!
Примечание. Я бы никогда не использовал токенизатор, который я написал без тестирования! используйте boost:: tokenizer!
Ответ 4
если разделители являются символами, а не строками, вы можете использовать strtok.
Ответ 5
Это зависит от того, хотите ли вы использовать предыдущие разделители, следующие разделители или и то, и другое, и то, что вы хотите делать со строками в начале и в конце строки, которые могут не иметь разделителей до/после них.
Я собираюсь предположить, что вам нужно каждое слово с его предыдущими и последующими разделителями, но НЕ любые строки разделителей сами по себе (например, если есть разделитель, следующий за последней строкой).
template <class iter>
void tokenize(std::string const &str, std::string const &delims, iter out) {
int pos = 0;
do {
int beg_word = str.find_first_not_of(delims, pos);
if (beg_word == std::string::npos)
break;
int end_word = str.find_first_of(delims, beg_word);
int beg_next_word = str.find_first_not_of(delims, end_word);
*out++ = std::string(str, pos, beg_next_word-pos);
pos = end_word;
} while (pos != std::string::npos);
}
На данный момент я написал это скорее как алгоритм STL, беря итератор для его вывода, а не предполагая, что он всегда нажимает на коллекцию. Поскольку это зависит (на данный момент), когда вход является строкой, он не использует итераторы для ввода.