2009-10-02 3 views
20

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

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

    } 
} 

ответ

16

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

Это должно привести с список_элементов имеют следующие элементы:

 
Token0 = "abc," 
Token1 = "123 " 
Token2 = "xyz" 

Еще примеры могут быть найдены Here

2

Я не могу следовать вашему коду, не могли бы вы опубликовать рабочую программу?

В любом случае, это простой токенизатор, без проверки крайних случаев:

#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!

+2

+1 для Сообщение Boost.Tokenizer –

+0

Я отредактировал m y, чтобы включить всю функцию. Я вижу, что вы сделали, но разделители будут строкой, и каждый символ в строке будет разделителем. Пропустили так »,.! \ N" Таким образом, запятая, период, восклицательный знак и новая строка также будут помещены в вектор, но не в пространство. Таким образом, я могу присоединиться к вектору назад и использовать пространство между элементами вектора и перестроить строку. – Jeremiah

+0

запятая, период, восклицательный знак и новая строка, включая пробел, будут разделителями. извините, хотел сделать ясно. – Jeremiah

0

Это зависит от того, хотите ли вы иметь предшествующие разделители, следующие разделители или и то, и другое, и то, что вы хотите делать со строками в начале и в конце строки, которые могут не иметь разделителей до/после них.

Я собираюсь предположить, что вам нужно каждое слово с его предыдущими и последующими разделителями, но НЕ любые строки разделителей сами по себе (например, если существует разделитель, следующий за последней строкой).

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

+0

Мне нужна строка «Тестовая строка» в Интернете. \ NНастроить строку ». чтобы быть такими же. Я хочу пространство, commma, период и \ n, чтобы быть разделителями. Test строка , на веб . \ n Испытание линия . – Jeremiah

+0

Извините, это не сообщение правильно. После разделителя слов у него должно было быть все на новой линии. – Jeremiah

2

Если разделители являются символами, а не строками, то вы можете использовать strtok.

+0

да? что случилось с strtok? –

+0

Спасибо .. Я почти забыл об этой функции: P – poorva

+1

'strtok' потребляет маркеры-разделители, я считаю. – Santa

4

Теперь я немного неряшлив, но это то, с чем я закончил. Я не хотел использовать 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; 
} 
Смежные вопросы