Подтвердить что ты не робот

Токенизировать строку и включить разделители в С++

Я хочу отметить следующее, но не знаю, как включить в него разделители.

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);

    }
}
4b9b3361

Ответ 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, беря итератор для его вывода, а не предполагая, что он всегда нажимает на коллекцию. Поскольку это зависит (на данный момент), когда вход является строкой, он не использует итераторы для ввода.