Я намагаюся перебирати слова рядка.
Можна вважати, що рядок складається зі слів, відокремлених пропуском.
Зауважте, що мене не цікавлять рядкові функції C або подібні маніпуляції з символами/доступ до них. Також, будь ласка, віддайте перевагу елегантності над ефективністю у вашій відповіді.
Найкраще рішення, яке я маю на даний момент:
#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);
}
Чи є більш елегантний спосіб зробити це?
Це мій улюблений спосіб ітерації по рядку. Ви можете робити все, що завгодно з кожним словом.
string line = "a line of text to iterate through";
string word;
istringstream iss(line, istringstream::in);
while( iss >> word )
{
// Do something on `word` here...
}
Такого методу НТЛ ще не має в своєму розпорядженні.
Однак, ви можете або використовувати функцію C's strtok()
, використовуючи член std::string::c_str()
, або написати свою власну. Ось приклад коду, який я знайшов після швидкого пошуку в 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);
}
}
Взято з: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
Якщо у вас виникли питання щодо прикладу коду, залиште коментар і я поясню.
І те, що в ньому не реалізовано ітератор з іменем типу typedef
або перевантажено оператор <<
не означає, що це поганий код. Я досить часто використовую функції C. Наприклад, printf
і scanf
працюють швидше, ніж std::cin
і std::cout
(значно), синтаксис fopen
набагато більш дружелюбний до бінарних типів, і вони також мають тенденцію створювати менші EXE.
Не ведіться на цю угоду "елегантність над продуктивністю".
Використання std::stringstream
, як у вас, працює чудово, і робить саме те, що ви хотіли. Якщо ви просто шукаєте інший спосіб, ви можете використовувати std::find()
/std::find_first_of()
та std::string::substr()
.
Ось приклад:
#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;
}