Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.190.159.10] |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Думаю, линейная, с небольшим бо́льшим единицы коэффициентом пропорциональности от длины списка разделителей.
|
Сообщ.
#17
,
|
|
|
В общем, я ни разу не специалист в spirit, но то, что удалось вспомнить, вложил в сие. Недурно, как мне кажется. Спецам, владеющим оптимизацией spirit, велкам.
|
Сообщ.
#18
,
|
|
|
Цитата Qraizer @ В общем, я ни разу не специалист в spirit, но то, что удалось вспомнить, вложил в сие. Здесь, кстати, тот случай, когда основное время тратится на добавление в std::vector. |
Сообщ.
#19
,
|
|
|
Это к тому, что там семантика копирования вместо перемещения? Возможно. Потому спиритисты и приветствуются. Как сказать спириту, чтоб перемещал, я не знаю.
|
Сообщ.
#21
,
|
|
|
Цитата Flex Ferrum @ Лучше так и с оптимизацией А что именно там лучше? |
Сообщ.
#22
,
|
|
|
Цитата Олег М @ А что именно там лучше? Там данные с разных вариантов строк для сплита. Ну и оптимизация включена. |
Сообщ.
#23
,
|
|
|
Надо тогда уж и splitLineRaw() переделать под коллекцию разделителей.
Добавлено Как-то так, что ли... template<typename It> std::vector<std::string>& splitLineRaw(std::vector<std::string>& result, It cur, It e, const char* c) { while (cur != e) { auto start = cur; while (cur != e) { int i; for (i = 0; c[i] != '\0' && *cur != c[i]; ++i) ; if (c[i] != '\0') break; ++cur; } result.push_back(std::string(start, cur)); if (cur == e) break; ++cur; } return result; } |
Сообщ.
#24
,
|
|
|
Цитата Flex Ferrum @ Там данные с разных вариантов строк для сплита. Ну и оптимизация включена. Т.е. можно смело сделать вывод, что все эти regexp'ы и spirit'ы - это, конечно, круто и здорово, но крайне неэффективно. То же самое касается и парсеров istream, которые стопудово будут работать много хуже старого доброго sscanf. |
Сообщ.
#25
,
|
|
|
Крайне неэффективно – это смотря какая задача. Исключения тоже, написанные на коленке под каждый конкретный случай, будут значительно эффективней общего языкового механизма. И самописный RTTI встречался, потому что языковой был запрещён Стандартом Кодирования. Задача сплита строки на подстроки по простому формальному признаку соответствия известному патерну довольно проста. Другое дело, когда стоит задача перенести в код LEX-грамматику. Или отрефакторить и реализоваться PHP-модуль.
Добавлено К тому же не факт, что алгоритмы поиска в строках, реализованные в библиотеках, не заточены под большие массивы данных. Надо попробовать погонять эти splitLineXXX()-ы на парусоткилобайтных строках с 20-значным списком разделителей... |
Сообщ.
#26
,
|
|
|
Цитата Олег М @ Т.е. можно смело сделать вывод, что все эти regexp'ы и spirit'ы - это, конечно, круто и здорово, но крайне неэффективно. Всё зависит от задачи, как правильно заметил Qraizer. Вот, скажем, задали мне вчера вопрос: можно ли (и если можно, то как) при примерно таком коде: int a = 0, b = 0, c = 0; cin >> /* ... */; написать в консоле "b=2" и это сразу прыгнет в переменную b. Код вышел довольно простой. #include <iostream> #include <regex> #include <string> using namespace std; int main() { int a = 0; int b = 0; int c = 0; std::regex parseRegex(R"(\s*([abc])\s*=\s*([+-]?\d+)\s*)"); std::smatch baseMatch; for (;;) { std::string line; std::getline(std::cin, line); if (line == "exit") break; if (!std::regex_match(line, baseMatch, parseRegex)) { std::cout << "Can't match the string! Invalid string format." << std::endl; continue; } if (baseMatch.size() != 3) { std::cout << "Invalid string format." << std::endl; continue; } auto varName = baseMatch[1].str(); auto varValueStr = baseMatch[2].str(); auto varValue = atoi(varValueStr.c_str()); if (varName == "a") a = varValue; else if (varName == "b") b = varValue; else if (varName == "c") c = varValue; std::cout << "a = " << a << std::endl; std::cout << "b = " << b << std::endl; std::cout << "c = " << c << std::endl; } return 0; } Как ты понимаешь, что чтобы решить эту задачу чисто алгоритмически тебе придётся написать портянку, которая сначала очистит от пробелов строку, потом побьёт её по знаку '=', потом опять очистит от пробелов, потом - проверить что в левой части a, b или c, а в правой - валидное число. И всё это на if'ах, find'ах и тримах. А тут - прогнал через регулярку и получил результат, распиханный в слоты. Удобно. И, главное, более-менее понятно. И изменения вносить несложно. Добавлено Цитата Qraizer @ Крайне неэффективно – это смотря какая задача. Исключения тоже, написанные на коленке под каждый конкретный случай, будут значительно эффективней общего языкового механизма. И самописный RTTI встречался, потому что языковой был запрещён Стандартом Кодирования. Задача сплита строки на подстроки по простому формальному признаку соответствия известному патерну довольно проста. Другое дело, когда стоит задача перенести в код LEX-грамматику. Или отрефакторить и реализоваться PHP-модуль. В данном контексте интерес представляет код clang'а. Где ручной RTTI, почти полное отсутствие рантайм-полиморфизма в AST, битовые поля в классах и прочие прелести оптимизации. |
Сообщ.
#27
,
|
|
|
Цитата Flex Ferrum @ Как ты понимаешь, что чтобы решить эту задачу чисто алгоритмически тебе придётся написать портянку, которая сначала очистит от пробелов строку, потом побьёт её по знаку '=', потом опять Единственное, что я понимаю, что такая задача, параметр1=значение1|параметр2=значение2...., довольно просто решается за один проход по строке, безо всяких regexp. Даже если вдруг понадобится удалять пробелы. Естественно, если ты обрабатываешь ввод с клавиатуры, то похрену на производительность. Но когда идёт поток данных, то тут призадумаешься. |
Сообщ.
#28
,
|
|
|
Цитата Олег М @ Единственное, что я понимаю, что такая задача, параметр1=значение1|параметр2=значение2...., довольно просто решается за один проход по строке, безо всяких regexp. Так и regexp в данном случае может сделать один проход по строке. Он ведь просто не запрещает возвратные алгоритмы. |
Сообщ.
#29
,
|
|
|
Цитата Flex Ferrum @ Так и regexp в данном случае может сделать один проход по строке. Он ведь просто не запрещает возвратные алгоритмы. Если честно, я понятия не имею как он работает. Но, судя по твоим же примерам, не слишком хорошо. И это в простейшем случае и в одном потоке. |
Сообщ.
#30
,
|
|
|
Существует и такое мнение:
Цитата ... MinGW-w64 4.9.2 на PCRE показывает результат в 8.3s, а на std::regex -- 44s (я не ошибся, сорок четыре секунды). Но у MinGW есть свои проблемы под Windows, так что здесь все вполне ожидаемо. Но однозначно, проблема не в C++ как языке или его компиляторе, а конкретно в текущих версиях std::regex. ... Я не проверял, но чуйка подсказывает - похоже на правду. std::regex, имхо, коряв по реализации и недопилен по функционалу. |