2009-10-02 11 views
20

Estoy simbolizando con lo siguiente, pero no estoy seguro de cómo incluir los delimitadores.Tokenizar una cadena e incluir delimitadores en 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); 

    } 
} 

Respuesta

16

El C++ String Toolkit Library (StrTk) tiene la siguiente solución:

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

Debe resultar con token_list tienen los siguientes elementos:

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

Más ejemplos se pueden encontrar Here

2

No puedo realmente seguir su código, ¿podría publicar un programa que funcione?

De todos modos, este es un tokenizer simple, sin casos de borde de pruebas:

#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())); 
} 

Ejemplo de entrada, delimitador = $$:

Hello$$Stack$$Over$$$Flow$$$$! 

Tokens:

Hello$$ 
Stack$$ 
Over$$ 
$Flow$$ 
$$ 
! 

Nota: I ¡nunca utilizaría un tokenizer que escribí sin probar! por favor use boost::tokenizer!

+2

1 para la mención Boost.Tokenizer –

+0

He editado m y publicación para incluir toda la función. Veo lo que hizo, pero los delimitadores serán una cadena y cada carácter de la cadena será un delimitador. Pasó así ",.! \ N" Así que una coma, un punto, una exclamación y una nueva línea se insertarán en el vector también, pero no en el espacio. De esta forma puedo unirme al vector y usar un espacio entre los elementos del vector y reconstruir la cadena. – Jeremiah

+0

coma, punto, exclamación y nueva línea que incluye el espacio serán los delimitadores. lo siento quería dejarlo claro. – Jeremiah

0

Depende de si desea los delimitadores precedentes, los siguientes delimitadores, o ambos, y lo que desea hacer con cadenas al principio y al final de la cadena que pueden no tener delimitadores antes/después de ellas.

Supongo que quiere cada palabra, con sus delimitadores anteriores y siguientes, pero NO cadenas de delimitadores por sí mismo (por ejemplo, si hay un delimitador después de la última cadena).

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

Por el momento, lo he escrito más como un algoritmo STL, teniendo un iterador para su salida en lugar de asumir que siempre está empujando a una colección. Como depende (por el momento) que la entrada sea una cadena, no usa iteradores para la entrada.

+0

Quiero la cadena "Cadena de prueba, en la web. \ NTest línea uno". ser tokens como tal. Quiero un espacio, un commma, un punto y \ n para ser delimitadores. prueba cadena , en la web . \ n Prueba línea uno . – Jeremiah

+0

Lo sentimos, no se publicó correctamente. Después del delimitador de palabras, se suponía que tenía cada cosa en una nueva línea. – Jeremiah

2

si los delimitadores son caracteres y no cadenas, entonces puede usar strtok.

+0

¿eh? ¿Qué pasa con strtok? –

+0

Gracias .. Casi me había olvidado de esta función: P – poorva

+1

'strtok' consume los tokens delimitadores, creo. – Santa

4

Ahora estoy un poco descuidado, pero esto es con lo que terminé. No quería usar el impulso ya que esta es una tarea escolar y mi instructor quería que usara find_first_of para lograr esto.

Gracias por la ayuda de todos.

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; 
} 
Cuestiones relacionadas