¿Cómo hago un bucle a través de las palabras?

Estoy tratando de ordenar las palabras de la cadena.

Se puede suponer que la cadena consiste en palabras separadas por espacios.

Tenga en cuenta que no estoy interesado en las funciones de cadena C o manipulaciones similares / acceso a caracteres. Además, dé prioridad a la elegancia sobre la eficiencia en su respuesta.

La mejor solución que tengo ahora es:

 #include <iostream> #include <sstream> #include <string> using namespace std; int main() { string s = "Somewhere down the road"; istringstream iss(s); do { string subs; iss >> subs; cout << "Substring: " << subs << endl; } while (iss); } 

¿Hay una manera más elegante de hacer esto?

2749
25 окт. conjunto de Ashwin Nanjappa 25 de octubre 2008-10-25 11:58 '08 a las 11:58 2008-10-25 11:58
@ 76 respuestas
  • 1
  • 2
  • 3

Por lo que cuesta, aquí hay otra forma de extraer tokens de la cadena de entrada, confiando solo en las bibliotecas estándar. Este es un ejemplo del poder y la elegancia del diseño de STL.

 #include <iostream> #include <string> #include <sstream> #include <algorithm> #include <iterator> int main() { using namespace std; string sentence = "And I feel fine..."; istringstream iss(sentence); copy(istream_iterator<string>(iss), istream_iterator<string>(), ostream_iterator<string>(cout, "\n")); } 

En lugar de copiar los tokens recuperados al flujo de salida, puede insertarlos en un contenedor utilizando el mismo algoritmo de copy general.

 vector<string> tokens; copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens)); 

... o crea un vector directamente:

 vector<string> tokens{istream_iterator<string>{iss}, istream_iterator<string>{}}; 
1241
26 окт. Respuesta dada por Zunino el 26 de octubre. 2008-10-26 03:43 '08 a las 3:43 2008-10-26 03:43

Lo uso para separar una cadena por un delimitador. El primero coloca los resultados en un vector preconstruido, el segundo devuelve un nuevo vector.

Tenga en cuenta que esta solución no omite tokens vacíos, por lo que se encontrarán los siguientes 4 elementos, uno de los cuales está vacío:

2343
25 окт. La respuesta la da Evan Teran el 25 de octubre. 2008-10-25 21:21 '08 a las 9:21 pm 2008-10-25 21:21

Una posible solución utilizando Boost puede ser:

 #include <boost/algorithm/string.hpp> std::vector<std::string> strs; boost::split(strs, "string to split", boost::is_any_of("\t ")); 

Este enfoque puede ser incluso más rápido que el enfoque de stringstream . Y dado que esta es una función de plantilla universal, se puede utilizar para separar otros tipos de cadenas (wchar, etc. o UTF-8) utilizando todo tipo de delimitadores.

Para más detalles, ver.

810
25 окт. La respuesta se da ididak 25 oct. 2008-10-25 23:28 '08 a las 11:28 2008-10-25 23:28
 #include <vector> #include <string> #include <sstream> int main() { std::string str("Split me by whitespaces"); std::string buf; // Have a buffer string std::stringstream ss(str); // Insert the string into a stream std::vector<std::string> tokens; // Create vector to hold our words while (ss >> buf) tokens.push_back(buf); return 0; } 
336
06 марта '11 в 8:52 2011-03-06 08:52 la respuesta se da kev 06 de marzo de 2011 a las 8:52 2011-03-06 08:52

Para aquellos con quienes no es adecuado sacrificar toda la eficiencia para el tamaño del código y ver "efectivo" como un tipo de elegancia, lo siguiente debería ser un punto dulce (y creo que la clase de contenedor-plantilla es una adición sorprendentemente elegante):

 template < class ContainerT > void tokenize(const std::string str, ContainerT tokens, const std::string delimiters = " ", bool trimEmpty = false) { std::string::size_type pos, lastPos = 0, length = str.length(); using value_type = typename ContainerT::value_type; using size_type = typename ContainerT::size_type; while(lastPos < length + 1) { pos = str.find_first_of(delimiters, lastPos); if(pos == std::string::npos) { pos = length; } if(pos != lastPos || !trimEmpty) tokens.push_back(value_type(str.data()+lastPos, (size_type)pos-lastPos )); lastPos = pos + 1; } } 

Normalmente prefiero usar los tipos std::vector<std::string> como mi segundo parámetro ( ContainerT ) ... pero la list<> más rápida que el vector<> cuando no se necesita acceso directo, e incluso puedes crear tu propia cadena class y use algo como std::list<subString> , donde el subString no hace copias a una velocidad increíble.

Es más del doble de rápido que el tokenized más rápido en esta página y casi 5 veces más rápido que otros. Además, con los tipos de parámetros ideales, puede eliminar todas las copias de cadenas y listas para un aumento de velocidad adicional.

Además, no realiza una devolución (altamente ineficiente) del resultado, sino que pasa tokens como referencia, lo que también le permite crear tokens usando varias llamadas si lo desea.

Finalmente, le permite especificar si desea vaciar tokens vacíos de los resultados utilizando el último parámetro opcional.

Todo lo que necesita es std::string ... el resto son opcionales. No utiliza subprocesos o una biblioteca de impulso, pero es lo suficientemente flexible como para aceptar naturalmente algunos de estos tipos extranjeros.

174
29 сент. La respuesta la da Marius el 29 sep. 2009-09-29 18:12 '09 a las 18:12 2009-09-29 18:12

Aquí hay otra solución. Es lo suficientemente compacto y eficiente:

 std::vector<std::string> split(const std::string  char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = end + 1; } tokens.push_back(text.substr(start)); return tokens; } 

Se puede programar fácilmente para manejar delimitadores de filas, cadenas anchas, etc.

Observe que dividir "" da como resultado una línea en blanco, y dividir "," (es decir, sep) da como resultado dos líneas en blanco.

También se puede implementar fácilmente para omitir tokens vacíos:

 std::vector<std::string> split(const std::string  char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { if (end != start) { tokens.push_back(text.substr(start, end - start)); } start = end + 1; } if (end != start) { tokens.push_back(text.substr(start)); } return tokens; } 

Si es necesario dividir una línea en varios delimitadores al omitir tokens vacíos, se puede usar esta versión:

 std::vector<std::string> split(const std::string text, const std::string delims) { std::vector<std::string> tokens; std::size_t start = text.find_first_not_of(delims), end = 0; while((end = text.find_first_of(delims, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = text.find_first_not_of(delims, end); } if(start != std::string::npos) tokens.push_back(text.substr(start)); return tokens; } 
155
13 сент. Respuesta dada por Alec Thomas el 13 de septiembre. 2011-09-13 23:46 '11 a las 11:46 PM 2011-09-13 23:46

Esta es mi forma favorita de iterar una cadena. Puedes hacer lo que quieras por cada palabra.

 string line = "a line of text to iterate through"; string word; istringstream iss(line, istringstream::in); while( iss >> word ) { // Do something on `word` here... } 
111
25 окт. la respuesta es dada por gnomed el 25 oct. 2008-10-25 12:16 '08 a las 12:16 2008-10-25 12:16

Es como una pregunta de desbordamiento de pila. ¿Cómo quiero tokenizar una cadena en C ++? .

 #include <iostream> #include <string> #include <boost/tokenizer.hpp> using namespace std; using namespace boost; int main(int argc, char** argv) { string text = "token test\tstring"; char_separator<char> sep(" \t"); tokenizer<char_separator<char>> tokens(text, sep); for (const string t : tokens) { cout << t << "." << endl; } } 
78
25 окт. La respuesta se da Ferruccio 25 oct. 2008-10-25 13:58 '08 a la 1:58 pm 2008-10-25 13:58

Me gusta lo siguiente porque pone los resultados en un vector, admite la cadena como separador y da control sobre la preservación de valores nulos. Pero no se ve tan bien.

 #include <ostream> #include <string> #include <vector> #include <algorithm> #include <iterator> using namespace std; vector<string> split(const string s, const string delim, const bool keep_empty = true) { vector<string> result; if (delim.empty()) { result.push_back(s); return result; } string::const_iterator substart = s.begin(), subend; while (true) { subend = search(substart, s.end(), delim.begin(), delim.end()); string temp(substart, subend); if (keep_empty || !temp.empty()) { result.push_back(temp); } if (subend == s.end()) { break; } substart = subend + delim.size(); } return result; } int main() { const vector<string> words = split("So close no matter how far", " "); copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); } 

Por supuesto, Boost ha split() , que funciona parcialmente así. Y, si por espacio en blanco realmente quiere decir cualquier tipo de espacio en blanco, usar la partición Boost con is_any_of() funciona bien.

65
25 окт. La respuesta se da Shadow2531 25 oct. 2008-10-25 13:01 '08 a la 1:01 pm 2008-10-25 13:01

STL ya no tiene tal método.

Sin embargo, puede usar la strtok() C strtok() usando std::string::c_str() , o puede escribir la suya propia. Este es un ejemplo del código que encontré después de una búsqueda rápida en Google ( "División de la cadena STL" ):

 void Tokenize(const string str, vector<string> tokens, const string delimiters = " ") { // Skip delimiters at beginning. string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". string::size_type pos = str.find_first_of(delimiters, lastPos); while (string::npos != pos || string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } } 

Tomado de: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

Si tiene preguntas sobre el código de muestra, deje un comentario y se lo explicaré.

Y solo porque no implementa un typedef llamado iterador o sobrecarga, el operador << no significa que este sea un código incorrecto. Yo uso las funciones de C bastante a menudo. Por ejemplo, printf y scanf son más rápidos que std::cin y std::cout (significativamente), la sintaxis de fopen es mucho más amigable para los tipos binarios, y también tienden a crear EXEs más pequeños.

No vendas este trato de "Elegancia sobre rendimiento" .

50
25 окт. La respuesta se da nlaq 25 oct. 2008-10-25 12:08 '08 a las 12:08 2008-10-25 12:08

Aquí está la función de separación, que:

  • es común
  • utiliza C ++ estándar (sin mejoras)
  • acepta múltiples delimitadores
  • ignora las fichas vacías (se pueden cambiar fácilmente)

     template<typename T> vector<T> split(const T  str, const T  delimiters) { vector<T> v; typename T::size_type start = 0; auto pos = str.find_first_of(delimiters, start); while(pos != T::npos) { if(pos != start) // ignore empty tokens v.emplace_back(str, start, pos - start); start = pos + 1; pos = str.find_first_of(delimiters, start); } if(start < str.length()) // ignore trailing delimiter v.emplace_back(str, start, str.length() - start); // add what left of the string return v; } 

Ejemplo de uso:

  vector<string> v = split<string>("Hello, there; World", ";,"); vector<wstring> v = split<wstring>(L"Hello, there; World", L";,"); 
39
13 марта '12 в 3:09 2012-03-13 03:09 La respuesta la da Marco M. 13 de marzo de 2012 a las 3:09 2012-03-13 03:09

Otra forma flexible y rápida.

 template<typename Operator> void tokenize(Operator op, const char* input, const char* delimiters) { const char* s = input; const char* e = s; while (*e != 0) { e = s; while (*e != 0  strchr(delimiters, *e) == 0) ++e; if (e - s > 0) { op(s, e - s); } s = e + 1; } } 

Úselo con un vector de cadena (Edición: porque alguien indicó que no hereda las clases STL ... hrmf;)):

 template<class ContainerType> class Appender { public: Appender(ContainerType container) : container_(container) {;} void operator() (const char* s, unsigned length) { container_.push_back(std::string(s,length)); } private: ContainerType container_; }; std::vector<std::string> strVector; Appender v(strVector); tokenize(v, "A number of words to be tokenized", " \t"); 

Que es esto Y esta es solo una forma de usar un tokenizador, por ejemplo, cómo simplemente contar palabras:

 class WordCounter { public: WordCounter() : noOfWords(0) {} void operator() (const char*, unsigned) { ++noOfWords; } unsigned noOfWords; }; WordCounter wc; tokenize(wc, "A number of words to be counted", " \t"); ASSERT( wc.noOfWords == 7 ); 

Limitado por la imaginación;)

34
01 апр. La respuesta se da Robert 01 apr. 2010-04-01 17:16 '10 a las 17:16 2010-04-01 17:16

Tengo una solución de 2 líneas para este problema:

 char sep = ' '; std::string s="1 This is an example"; for(size_t p=0, q=0; p!=s.npos; p=q) std::cout << s.substr(p+(p!=0), (q=s.find(sep, p+1))-p-(p!=0)) << std::endl; 

Luego, en lugar de imprimir, puedes ponerlo en un vector.

34
16 сент. La respuesta la da rhomu el 16 de septiembre. 2012-09-16 17:06 '12 a las 17:06 2012-09-16 17:06

Aquí hay una solución simple que usa solo la biblioteca de expresiones regulares estándar.

 #include <regex> #include <string> #include <vector> std::vector<string> Tokenize( const string str, const std::regex regex ) { using namespace std; std::vector<string> result; sregex_token_iterator it( str.begin(), str.end(), regex, -1 ); sregex_token_iterator reg_end; for ( ; it != reg_end; ++it ) { if ( !it->str().empty() ) //token could be empty:check result.emplace_back( it->str() ); } return result; } 

El argumento regex permite verificar múltiples argumentos (espacios, comas, etc.)

Por lo general, solo verifico la división en espacios y comas, por lo que también tengo esta función predeterminada:

 std::vector<string> TokenizeDefault( const string str ) { using namespace std; regex re( "[\\s,]+" ); return Tokenize( str, re ); } 

"[\\s,]+" comprueba los espacios ( \\s ) y las comas ( , ).

Tenga en cuenta que si desea dividir wstring lugar de string ,

  • cambia todas las std::regex a std::wregex
  • cambiar todo sregex_token_iterator a wsregex_token_iterator

Tenga en cuenta que también puede tomar un argumento de cadena por referencia, dependiendo de su compilador.

30
06 мая '14 в 8:49 2014-05-06 08:49 la respuesta se da dk123 06 de mayo de 2014 a las 8:49 2014-05-06 08:49

Si le gusta usar boost, pero desea usar toda la cadena como un delimitador (en lugar de caracteres simples, como en la mayoría de las soluciones propuestas anteriormente), puede usar boost_split_iterator .

Un ejemplo de código que incluye una plantilla conveniente:

 #include <iostream> #include <vector> #include <boost/algorithm/string.hpp> template<typename _OutputIterator> inline void split( const std::string str, const std::string delim, _OutputIterator result) { using namespace boost::algorithm; typedef split_iterator<std::string::const_iterator> It; for(It iter=make_split_iterator(str, first_finder(delim, is_equal())); iter!=It(); ++iter) { *(result++) = boost::copy_range<std::string>(*iter); } } int main(int argc, char* argv[]) { using namespace std; vector<string> splitted; split("HelloFOOworldFOO!", "FOO", back_inserter(splitted)); // or directly to console, for example split("HelloFOOworldFOO!", "FOO", ostream_iterator<string>(cout, "\n")); return 0; } 
24
24 марта '11 в 15:47 2011-03-24 15:47 la respuesta la da zerm el 24 de marzo de 2011 a las 15:47 2011-03-24 15:47

Usa std::stringstream mientras trabajas muy bien y haz exactamente lo que quieres. Si solo está buscando otra forma de hacer algo, puede usar std::find() / std::find_first_of() y std::string::substr() .

Aquí hay un ejemplo:

 #include <iostream> #include <string> int main() { std::string s("Somewhere down the road"); std::string::size_type prev_pos = 0, pos = 0; while( (pos = s.find(' ', pos)) != std::string::npos ) { std::string substring( s.substr(prev_pos, pos-prev_pos) ); std::cout << substring << '\n'; prev_pos = ++pos; } std::string substring( s.substr(prev_pos, pos-prev_pos) ); // Last word std::cout << substring << '\n'; return 0; } 
23
25 окт. La respuesta la da KTC el 25 de octubre. 2008-10-25 12:28 '08 a las 12:28 2008-10-25 12:28

Hay una función llamada strtok .

 #include<string> using namespace std; vector<string> split(char* str,const char* delim) { char* saveptr; char* token = strtok_r(str,delim, vector<string> result; while(token != NULL) { result.push_back(token); token = strtok_r(NULL,delim, } return result; } 
18
14 июня '10 в 15:17 2010-06-14 15:17 Pratik Deoghare da la respuesta el 14 de junio de 2010 a las 15:17 2010-06-14 15:17

Aquí hay una solución de expresión regular que usa solo la biblioteca de expresiones regulares estándar. (Estoy un poco oxidado, por lo que puede haber algunos errores de sintaxis, pero esto es al menos una idea general)

 #include <regex.h> #include <string.h> #include <vector.h> using namespace std; vector<string> split(string s){ regex r ("\\w+"); //regex matches whole words, (greedy, so no fragment words) regex_iterator<string::iterator> rit ( s.begin(), s.end(), r ); regex_iterator<string::iterator> rend; //iterators to iterate thru words vector<string> result<regex_iterator>(rit, rend); return result; //iterates through the matches to fill the vector } 
17
29 окт. La respuesta es dada por AJMansfield el 29 de octubre. 2012-10-29 19:15 '12 a las 19:15 2012-10-29 19:15

Un flujo de cadena puede ser conveniente si necesita analizar una cadena usando caracteres no espaciales:

 string s = "Name:JAck; Spouse:Susan; ..."; string dummy, name, spouse; istringstream iss(s); getline(iss, dummy, ':'); getline(iss, name, ';'); getline(iss, dummy, ':'); getline(iss, spouse, ';') 
16
12 авг. respuesta dada por lukmac 12 ago. 2011-08-12 22:05 '11 a las 10:05 pm 2011-08-12 22:05

Hasta ahora he usado el que estaba en Boost , pero necesitaba algo que no dependiera de él, así que vine a esto.

 static void Split(std::vector<std::string> lst, const std::string input, const std::string separators, bool remove_empty = true) { std::ostringstream word; for (size_t n = 0; n < input.size(); ++n) { if (std::string::npos == separators.find(input[n])) word << input[n]; else { if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); word.str(""); } } if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); } 

Es bueno que en separators puedas pasar más de un personaje.

14
14 янв. La respuesta se da Goran 14 de enero. 2011-01-14 12:22 '11 a las 12:22 2011-01-14 12:22

Corto y elegante

 #include <vector> #include <string> using namespace std; vector<string> split(string data, string token) { vector<string> output; size_t pos = string::npos; // size_t to avoid improbable overflow do { pos = data.find(token); output.push_back(data.substr(0, pos)); if (string::npos != pos) data = data.substr(pos + token.size()); } while (string::npos != pos); return output; } 

puede usar cualquier cadena como delimitador, también se puede usar con datos binarios (std :: string admite datos binarios, incluidos los ceros)

utilizando:

 auto a = split("this!!is!!!example!string", "!!"); 

salida:

 this is !example!string 
14
02 нояб. respuesta es dada por el usuario 1438233 02 nov. 2015-11-02 17:39 '15 a las 5:39 pm 2015-11-02 17:39

Hice mi propio uso de strtok y utilicé boost para separar las cuerdas. El mejor método que encontré es la biblioteca de C ++ String Toolkit . Es increíblemente flexible y rápido.

 #include <iostream> #include <vector> #include <string> #include <strtk.hpp> const char *whitespace = " \t\r\n\f"; const char *whitespace_and_punctuation = " \t\r\n\f;,="; int main() { { // normal parsing of a string into a vector of strings std::string s("Somewhere down the road"); std::vector<std::string> result; if( strtk::parse( s, whitespace, result ) ) { for(size_t i = 0; i < result.size(); ++i ) std::cout << result[i] << std::endl; } } { // parsing a string into a vector of floats with other separators // besides spaces std::string s("3.0, 3.14; 4.0"); std::vector<float> values; if( strtk::parse( s, whitespace_and_punctuation, values ) ) { for(size_t i = 0; i < values.size(); ++i ) std::cout << values[i] << std::endl; } } { // parsing a string into specific variables std::string s("angle = 45; radius = 9.9"); std::string w1, w2; float v1, v2; if( strtk::parse( s, whitespace_and_punctuation, w1, v1, w2, v2) ) { std::cout << "word " << w1 << ", value " << v1 << std::endl; std::cout << "word " << w2 << ", value " << v2 << std::endl; } } return 0; } 

El kit de herramientas tiene mucha más flexibilidad de lo que muestra este simple ejemplo, pero su utilidad para analizar una cadena en elementos útiles es increíble.

13
07 янв. La respuesta se da DannyK 07 de enero. 2014-01-07 23:28 '14 a las 23:28 2014-01-07 23:28

Hice esto porque necesitaba una forma sencilla de separar las líneas de las líneas c ... Espero que alguien más pueda encontrarlo útil. Además, no se basa en tokens, y puedes usar campos como delimitadores, que es otra clave que necesito.

Estoy seguro de que hay mejoras que pueden mejorarse para mejorar aún más su elegancia y, por favor, por todos los medios

StringSplitter.hpp:

 #include <vector> #include <iostream> #include <string.h> using namespace std; class StringSplit { private: void copy_fragment(char*, char*, char*); void copy_fragment(char*, char*, char); bool match_fragment(char*, char*, int); int untilnextdelim(char*, char); int untilnextdelim(char*, char*); void assimilate(char*, char); void assimilate(char*, char*); bool string_contains(char*, char*); long calc_string_size(char*); void copy_string(char*, char*); public: vector<char*> split_cstr(char); vector<char*> split_cstr(char*); vector<string> split_string(char); vector<string> split_string(char*); char* String; bool do_string; bool keep_empty; vector<char*> Container; vector<string> ContainerS; StringSplit(char * in) { String = in; } StringSplit(string in) { size_t len = calc_string_size((char*)in.c_str()); String = new char[len + 1]; memset(String, 0, len + 1); copy_string(String, (char*)in.c_str()); do_string = true; } ~StringSplit() { for (int i = 0; i < Container.size(); i++) { if (Container[i] != NULL) { delete[] Container[i]; } } if (do_string) { delete[] String; } } }; 

StringSplitter.cpp:

 #include <string.h> #include <iostream> #include <vector> #include "StringSplit.hpp" using namespace std; void StringSplit::assimilate(char*src, char delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } void StringSplit::assimilate(char*src, char* delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } long StringSplit::calc_string_size(char* _in) { long i = 0; while (*_in++) { i++; } return i; } bool StringSplit::string_contains(char* haystack, char* needle) { size_t len = calc_string_size(needle); size_t lenh = calc_string_size(haystack); while (lenh--) { if (match_fragment(haystack + lenh, needle, len)) { return true; } } return false; } bool StringSplit::match_fragment(char* _src, char* cmp, int len) { while (len--) { if (*(_src + len) != *(cmp + len)) { return false; } } return true; } int StringSplit::untilnextdelim(char* _in, char delim) { size_t len = calc_string_size(_in); if (*_in == delim) { _in += 1; return len - 1; } int c = 0; while (*(_in + c) != delim  c < len) { c++; } return c; } int StringSplit::untilnextdelim(char* _in, char* delim) { int s = calc_string_size(delim); int c = 1 + s; if (!string_contains(_in, delim)) { return calc_string_size(_in); } else if (match_fragment(_in, delim, s)) { _in += s; return calc_string_size(_in); } while (!match_fragment(_in + c, delim, s)) { c++; } return c; } void StringSplit::copy_fragment(char* dest, char* src, char delim) { if (*src == delim) { src++; } int c = 0; while (*(src + c) != delim  *(src + c)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } void StringSplit::copy_string(char* dest, char* src) { int i = 0; while (*(src + i)) { *(dest + i) = *(src + i); i++; } } void StringSplit::copy_fragment(char* dest, char* src, char* delim) { size_t len = calc_string_size(delim); size_t lens = calc_string_size(src); if (match_fragment(src, delim, len)) { src += len; lens -= len; } int c = 0; while (!match_fragment(src + c, delim, len)  (c < lens)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } vector<char*> StringSplit::split_cstr(char Delimiter) { int i = 0; while (*String) { if (*String != Delimiter  i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char Delimiter) { do_string = true; int i = 0; while (*String) { if (*String != Delimiter  i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } vector<char*> StringSplit::split_cstr(char* Delimiter) { int i = 0; size_t LenDelim = calc_string_size(Delimiter); while(*String) { if (!match_fragment(String, Delimiter, LenDelim)  i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String,Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char* Delimiter) { do_string = true; int i = 0; size_t LenDelim = calc_string_size(Delimiter); while (*String) { if (!match_fragment(String, Delimiter, LenDelim)  i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } 

Ejemplos:

 int main(int argc, char*argv[]) { StringSplit ss = "This:CUT:is:CUT:an:CUT:example:CUT:cstring"; vector<char*> Split = ss.split_cstr(":CUT:"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

Se mostrará:

Es
esto es

un ejemplo
CString

 int main(int argc, char*argv[]) { StringSplit ss = "This:is:an:example:cstring"; vector<char*> Split = ss.split_cstr(':'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This[SPLIT]is[SPLIT]an[SPLIT]example[SPLIT]string"; StringSplit ss = mystring; vector<string> Split = ss.split_string("[SPLIT]"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This|is|an|example|string"; StringSplit ss = mystring; vector<string> Split = ss.split_string('|'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

Guardar entradas vacías (por defecto, las entradas vacías están excluidas):

 StringSplit ss = mystring; ss.keep_empty = true; vector<string> Split = ss.split_string(":DELIM:"); 

El objetivo era hacer que se pareciera al método C # Split (), donde dividir una línea es tan simple como:

 String[] Split = "Hey:cut:what's:cut:your:cut:name?".Split(new[]{":cut:"}, StringSplitOptions.None); foreach(String X in Split) { Console.Write(X); } 

Espero que alguien más lo encuentre útil, como yo.

11
31 авг. La respuesta es dada por Steve Dell el 31 de agosto. 2012-08-31 22:11 '12 a las 10:11 pm 2012-08-31 22:11

¿Qué tal esto?

 #include <string> #include <vector> using namespace std; vector<string> split(string str, const char delim) { vector<string> v; string tmp; for(string::const_iterator i; i = str.begin(); i <= str.end(); ++i) { if(*i != delim  i != str.end()) { tmp += *i; } else { v.push_back(tmp); tmp = ""; } } return v; } 
10
ответ дан gibbz 24 июня '11 в 1:04 2011-06-24 01:04