На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Ручной slipt строки или то же, но с помощью std::regexp - что быстрее?
    Думаю, линейная, с небольшим бо́льшим единицы коэффициентом пропорциональности от длины списка разделителей.
      В общем, я ни разу не специалист в spirit, но то, что удалось вспомнить, вложил в сие. Недурно, как мне кажется. Спецам, владеющим оптимизацией spirit, велкам.
        Цитата Qraizer @
        В общем, я ни разу не специалист в spirit, но то, что удалось вспомнить, вложил в сие.


        Здесь, кстати, тот случай, когда основное время тратится на добавление в std::vector.
          Это к тому, что там семантика копирования вместо перемещения? Возможно. Потому спиритисты и приветствуются. Как сказать спириту, чтоб перемещал, я не знаю.
            Лучше так и с оптимизацией.
              Цитата Flex Ferrum @
              Лучше так и с оптимизацией

              А что именно там лучше?
                Цитата Олег М @
                А что именно там лучше?

                Там данные с разных вариантов строк для сплита. Ну и оптимизация включена. :)
                  Надо тогда уж и splitLineRaw() переделать под коллекцию разделителей.

                  Добавлено
                  Как-то так, что ли...
                  ExpandedWrap disabled
                    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;
                    }
                    Цитата Flex Ferrum @
                    Там данные с разных вариантов строк для сплита. Ну и оптимизация включена.


                    Т.е. можно смело сделать вывод, что все эти regexp'ы и spirit'ы - это, конечно, круто и здорово, но крайне неэффективно.
                    То же самое касается и парсеров istream, которые стопудово будут работать много хуже старого доброго sscanf.
                      Крайне неэффективно – это смотря какая задача. Исключения тоже, написанные на коленке под каждый конкретный случай, будут значительно эффективней общего языкового механизма. И самописный RTTI встречался, потому что языковой был запрещён Стандартом Кодирования. Задача сплита строки на подстроки по простому формальному признаку соответствия известному патерну довольно проста. Другое дело, когда стоит задача перенести в код LEX-грамматику. Или отрефакторить и реализоваться PHP-модуль.

                      Добавлено
                      К тому же не факт, что алгоритмы поиска в строках, реализованные в библиотеках, не заточены под большие массивы данных. Надо попробовать погонять эти splitLineXXX()-ы на парусоткилобайтных строках с 20-значным списком разделителей...
                        Цитата Олег М @
                        Т.е. можно смело сделать вывод, что все эти regexp'ы и spirit'ы - это, конечно, круто и здорово, но крайне неэффективно.

                        Всё зависит от задачи, как правильно заметил Qraizer. Вот, скажем, задали мне вчера вопрос: можно ли (и если можно, то как) при примерно таком коде:
                        ExpandedWrap disabled
                          int a = 0, b = 0, c = 0;
                           
                          cin >> /* ... */;

                        написать в консоле "b=2" и это сразу прыгнет в переменную b. Код вышел довольно простой.

                        ExpandedWrap disabled
                          #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, битовые поля в классах и прочие прелести оптимизации.
                          Цитата Flex Ferrum @
                          Как ты понимаешь, что чтобы решить эту задачу чисто алгоритмически тебе придётся написать портянку, которая сначала очистит от пробелов строку, потом побьёт её по знаку '=', потом опять

                          Единственное, что я понимаю, что такая задача, параметр1=значение1|параметр2=значение2...., довольно просто решается за один проход по строке, безо всяких regexp. Даже если вдруг понадобится удалять пробелы.
                          Естественно, если ты обрабатываешь ввод с клавиатуры, то похрену на производительность. Но когда идёт поток данных, то тут призадумаешься.
                            Цитата Олег М @
                            Единственное, что я понимаю, что такая задача, параметр1=значение1|параметр2=значение2...., довольно просто решается за один проход по строке, безо всяких regexp.

                            Так и regexp в данном случае может сделать один проход по строке. Он ведь просто не запрещает возвратные алгоритмы.
                              Цитата Flex Ferrum @
                              Так и regexp в данном случае может сделать один проход по строке. Он ведь просто не запрещает возвратные алгоритмы.

                              Если честно, я понятия не имею как он работает. Но, судя по твоим же примерам, не слишком хорошо. И это в простейшем случае и в одном потоке.
                                Существует и такое мнение:

                                Цитата

                                ...
                                MinGW-w64 4.9.2 на PCRE показывает результат в 8.3s, а на std::regex -- 44s (я не ошибся, сорок четыре секунды). Но у MinGW есть свои проблемы под Windows, так что здесь все вполне ожидаемо.

                                Но однозначно, проблема не в C++ как языке или его компиляторе, а конкретно в текущих версиях std::regex.
                                ...

                                Я не проверял, но чуйка подсказывает - похоже на правду. std::regex, имхо, коряв по реализации и недопилен по функционалу.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0760 ]   [ 17 queries used ]   [ Generated: 26.04.24, 02:46 GMT ]