Intento iterar sobre las palabras de una cadena.
Se puede suponer que la cadena está compuesta por palabras separadas por espacios en blanco.
Tenga en cuenta que no me interesan las funciones de cadena en C ni ese tipo de manipulación/acceso a los caracteres. También, por favor, dar prioridad a la elegancia sobre la eficiencia en su respuesta.
La mejor solución que tengo en este momento 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 alguna forma más elegante de hacer esto?
Esta es mi forma favorita de iterar a través de una cadena. Puedes hacer lo que quieras por 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...
}
El STL no dispone ya de este método.
Sin embargo, puedes usar la función strtok()
de C utilizando el miembro std::string::c_str()
, o puedes escribir el tuyo propio. Aquí hay un ejemplo de código que encontré tras una rápida búsqueda en Google ("STL string split "):
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 tienes dudas sobre el ejemplo de código, deja un comentario y te lo explicaré.
Y que no implemente un typedef
llamado iterador o sobrecargue el operador <<
no significa que sea un código malo. Yo uso funciones de C con bastante frecuencia. Por ejemplo, printf
y scanf
son más rápidas 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 producir EXEs más pequeños.
No te dejes convencer por este trato de "Elegancia sobre rendimiento ".
Usar std::stringstream
como lo has hecho funciona perfectamente, y hace exactamente lo que querías. Sin embargo, si buscas una forma diferente de hacer las cosas, puedes usar std::find()
/std::find_first_of()
y std::string::substr()
.
He aquí 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;
}