Я пытаюсь перебрать слова строки.
Можно предположить, что строка состоит из слов, разделенных пробелами.
Обратите внимание, что меня не интересуют строковые функции Си или подобные манипуляции / доступ к символам. Кроме того, пожалуйста, дайте приоритет элегантности над эффективностью в вашем ответе.
Лучшее решение, которое у меня есть сейчас:
#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);
}
Есть ли более элегантный способ сделать это?
while (iss) { string subs; iss >> subs; cout << "Substring: " << sub << endl; }
string sub; while (iss >> sub) cout << "Substring: " << sub << '\n';
Ответы:
Для чего стоит, вот еще один способ извлечь токены из входной строки, полагаясь только на стандартные библиотечные средства. Это пример силы и элегантности дизайна STL.
Вместо того, чтобы копировать извлеченные токены в выходной поток, их можно вставить в контейнер, используя тот же общий
copy
алгоритм.... или создать
vector
непосредственно:источник
Я использую это, чтобы разделить строку разделителем. Первый помещает результаты в предварительно построенный вектор, второй возвращает новый вектор.
Обратите внимание, что это решение не пропускает пустые токены, поэтому следующие найдут 4 элемента, один из которых пуст:
источник
empty()
проверку:if (!item.empty()) elems.push_back(item)
->
?f(split(s, d, v))
при этом, при желании, он по- прежнему обладает преимуществом предварительного выделенияvector
.Возможное решение с использованием Boost может быть:
Этот подход может быть даже быстрее, чем
stringstream
подход. А поскольку это универсальная шаблонная функция, ее можно использовать для разделения других типов строк (wchar и т. Д. Или UTF-8) с использованием всех видов разделителей.Смотрите документацию для деталей.
источник
источник
getline
вwhile
условии, например, разделить запятыми, используйтеwhile(getline(ss, buff, ','))
.Для тех, кому неудобно жертвовать всей эффективностью ради размера кода и рассматривать «работоспособность» как тип элегантности, следующее должно быть приятно: (и я думаю, что класс контейнера шаблонов является удивительно элегантным дополнением):
Я обычно выбираю использовать
std::vector<std::string>
типы в качестве второго параметра (ContainerT
) ... ноlist<>
это намного быстрее, чемvector<>
для случаев, когда прямой доступ не требуется, и вы даже можете создать свой собственный класс строки и использовать что-то вродеstd::list<subString>
гдеsubString
не делает никаких копий с невероятной скоростью увеличивается.Он более чем в два раза быстрее самого быстрого токена на этой странице и почти в 5 раз быстрее, чем некоторые другие. Также с идеальными типами параметров вы можете исключить все копии строк и списков для дополнительного увеличения скорости.
Кроме того, он не выполняет (крайне неэффективный) возврат результата, а скорее передает токены в качестве ссылки, что также позволяет вам создавать токены с использованием нескольких вызовов, если вы того пожелаете.
Наконец, он позволяет указать, следует ли обрезать пустые токены из результатов с помощью последнего необязательного параметра.
Все, что для этого нужно
std::string
... остальное необязательно. Он не использует потоки или библиотеку надстройки, но достаточно гибок, чтобы иметь возможность естественным образом принимать некоторые из этих внешних типов.источник
typedef ContainerT Base; typedef typename Base::value_type ValueType; typedef typename ValueType::size_type SizeType;
затем соответственно заменить value_type и size_types.trimEmpty = true
. Имейте в виду, что"abo"
это не разделитель в этом ответе, а список символов-разделителей. Было бы просто изменить его так, чтобы он содержал одну строку символов-разделителей (я думаю, чтоstr.find_first_of
должен измениться наstr.find_first
, но я могу ошибаться ... не могу проверить)Вот еще одно решение. Это компактно и достаточно эффективно:
Он может быть легко настроен для работы с разделителями строк, широкими строками и т. Д.
Обратите внимание, что разделение
""
приводит к одной пустой строке, а разделение","
(т. Е. Sep) приводит к двум пустым строкам.Он также может быть легко расширен для пропуска пустых токенов:
Если желательно разделить строку на несколько разделителей, пропуская пустые токены, можно использовать эту версию:
источник
Это мой любимый способ перебора строки. Вы можете делать все, что вы хотите на слово.
источник
word
какchar
?stringstream ss("Hello World, this is*@#&$(@ a string"); char c; while(ss >> c) cout << c;
Это похоже на вопрос переполнения стека. Как мне токенизировать строку в C ++? ,
источник
Мне нравится следующее, потому что он помещает результаты в вектор, поддерживает строку в качестве разделителя и дает контроль над сохранением пустых значений. Но тогда это выглядит не так хорошо.
Конечно, в Boost есть функция,
split()
которая работает частично так. И, если под «пустым пространством» вы действительно подразумеваете любой тип пустого пространства, использование Boost's split сis_any_of()
великолепно работает.источник
В STL такого метода уже нет.
Тем не менее, вы можете использовать
strtok()
функцию C, используяstd::string::c_str()
член, или вы можете написать свою собственную. Вот пример кода, который я нашел после быстрого поиска в Google ( «разделение строки STL» ):Взято из: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
Если у вас есть вопросы по поводу примера кода, оставьте комментарий, и я объясню.
И то, что он не реализует
typedef
вызываемый итератор или перегружает<<
оператор, не означает, что это плохой код. Я использую функции C довольно часто. Например,printf
иscanf
оба быстрее, чемstd::cin
иstd::cout
(значительно),fopen
синтаксис намного более удобен для двоичных типов, и они также имеют тенденцию создавать меньшие EXE-файлы.Не продавайте по этой сделке «Элегантность над производительностью» .
источник
Вот функция разделения, которая:
игнорирует пустые токены (может быть легко изменено)
Пример использования:
источник
У меня есть решение этой проблемы в 2 строки:
Тогда вместо печати вы можете поместить его в вектор.
источник
Еще один гибкий и быстрый способ
Чтобы использовать его с вектором строк (Правка: поскольку кто-то указал не наследовать классы STL ... hrmf;)):
Это оно! И это только один из способов использовать токенизатор, например, как просто считать слова:
Ограничено воображением;)
источник
Appender
примечания "Почему мы не должны наследовать класс от классов STL?"Вот простое решение, которое использует только стандартную библиотеку регулярных выражений
Аргумент regex позволяет проверять множественные аргументы (пробелы, запятые и т. Д.)
Я обычно проверяю только разделение на пробелы и запятые, поэтому у меня также есть эта функция по умолчанию:
В
"[\\s,]+"
проверяет пространства (\\s
) и запятых (,
).Обратите внимание, если вы хотите разделить
wstring
вместоstring
,std::regex
наstd::wregex
sregex_token_iterator
наwsregex_token_iterator
Обратите внимание, что вы также можете получить строковый аргумент по ссылке, в зависимости от вашего компилятора.
источник
R"([\s,]+)"
.Использование
std::stringstream
как у вас работает отлично, и делать именно то, что вы хотели. Если вы просто ищете другой способ сделать что-то, вы можете использоватьstd::find()
/std::find_first_of()
иstd::string::substr()
.Вот пример:
источник
prev_pos = pos += delimiter.length();
Если вам нравится использовать boost, но вы хотите использовать целую строку в качестве разделителя (вместо отдельных символов, как в большинстве ранее предложенных решений), вы можете использовать
boost_split_iterator
.Пример кода, включающий удобный шаблон:
источник
Вот решение для регулярных выражений, которое использует только стандартную библиотеку регулярных выражений. (Я немного заржавел, поэтому может быть несколько синтаксических ошибок, но это по крайней мере общая идея)
источник
Есть функция с именем
strtok
.источник
strtok
из стандартной библиотеки C, а не C ++. Не безопасно использовать в многопоточных программах. Он изменяет строку ввода.strtok
когда другой поток все еще обрабатывает, этот указатель на символ будет перезаписан, и тогда оба потока будут иметь неправильные результаты. mkssoftware.com/docs/man3/strtok.3.aspПоток строки может быть удобен, если вам нужно проанализировать строку по непробельным символам:
источник
До сих пор я использовал тот в Boost , но мне нужно что-то, что не зависит от этого, поэтому я пришел к этому:
Хорошим моментом является то, что в
separators
вас может пройти более одного персонажа.источник
Я свернул свой собственный, используя strtok, и использовал boost, чтобы разбить строку. Лучший метод, который я нашел, - это библиотека C ++ String Toolkit . Это невероятно гибкий и быстрый.
Инструментарий обладает гораздо большей гибкостью, чем этот простой пример, но его полезность в разборе строки на полезные элементы невероятна.
источник
Коротко и элегантно
может использовать любую строку в качестве разделителя, также может использоваться с двоичными данными (std :: string поддерживает двоичные данные, включая нули)
с помощью:
вывод:
источник
Я сделал это, потому что мне нужен был простой способ разделения строк и строк на основе c ... Надеюсь, кто-то еще может найти это полезным. Также он не зависит от токенов, и вы можете использовать поля в качестве разделителей, что является еще одним ключом, который мне нужен.
Я уверен, что есть улучшения, которые могут быть сделаны, чтобы еще больше улучшить его элегантность, и, пожалуйста, сделайте все возможное
StringSplitter.hpp:
StringSplitter.cpp:
Примеры:
Будет выводить:
Это
является примером CString
Чтобы оставить пустые записи (по умолчанию пустые места будут исключены):
Цель состояла в том, чтобы сделать его похожим на метод Split () в C #, где разбиение строки так же просто, как:
Я надеюсь, что кто-то еще может найти это столь же полезным, как и я.
источник
Что насчет этого:
источник
Этот ответ берет строку и помещает ее в вектор строк. Он использует библиотеку наддува.
источник
Вот еще один способ сделать это ..
источник
Мне нравится использовать методы boost / regex для этой задачи, поскольку они обеспечивают максимальную гибкость для определения критериев расщепления.
источник
Недавно мне пришлось разбить верблюжье слово на подслово. Здесь нет разделителей, только верхние символы.
Например, это разделяет «AQueryTrades» на «A», «Query» и «Trades». Функция работает с узкими и широкими строками. Поскольку он уважает текущую локаль, он разделяет "RaumfahrtÜberwachungsVerordnung" на "Raumfahrt", "Uberwachungs" и "Verordnung".
Примечание
std::upper
должно действительно передаваться как аргумент шаблона функции. Тогда более обобщенные из этой функции могут быть разделены на разделители как","
,";"
или" "
тоже.источник
std::isupper
могут быть переданы в качестве аргумента, а неstd::upper
. Второго положитьtypename
перед собойString::const_iterator
.источник
Использование
std::string_view
иrange-v3
библиотека Эрика Ниблера :https://wandbox.org/permlink/kW5lwRCL1pxjp2pW
Используя
for
цикл диапазона вместоranges::for_each
алгоритма:источник