Разбор пользовательской строки в C++

У меня есть строка типа:


"../blabla/here_is_same0000:00/0000:00:1A.0/blabla/blabla/blabla"

Я хочу получить часть 1A.0 из строки и вернуться в виде десятичного числа. Эти места всегда идут после шаблона here_is_same0000:00. Также эти места (0000:00:1A.0) не всегда занимают третье место в данной строке.

Я написал такой код:

static const std::string test_str1{"../blabla/here_is_same0000:00/0000:00:1A.0/blabla/blabla/blabla"};

std::tuple<int, int> values(const std::string& in)
{
  static const std::string constant_pattern{"here_is_same0000:00"};
  std::size_t found_idx = in.find(constant_pattern);
  if (found_idx == std::string::npos)
  {
    return std::make_tuple(0,0);
  }

  std::string remaining = in.substr(found_idx + constant_pattern.length() + 1, in.length());
  
  found_idx = remaining.find("/");
  if (found_idx == std::string::npos)
  {
    return std::make_tuple(0,0);
  }

  remaining = remaining.substr(0, found_idx);
  found_idx = remaining.find_last_of(":");
  remaining = remaining.substr(found_idx + 1, remaining.length());

  std::stringstream ss(remaining);
  std::string items;
  std::vector<std::string> elements;
  while(std::getline(ss, items, '.'))
  {
    elements.push_back(std::move(items));
  }

  int x;
  std::stringstream ss_convert_x;
  ss_convert_x << std::hex << elements[0];
  ss_convert_x >> x;
  
  int y;
  std::stringstream ss_convert_y;
  ss_convert_y << std::hex << elements[1];
  ss_convert_y >> y;

  std::cout << x <<" "<< y;
  
  return std::make_tuple(x,y);
}

Но мне это кажется плохим, есть ли лучший способ?

🤔 А знаете ли вы, что...
C++ обладает высокой производительностью и эффективностью в использовании ресурсов.


61
1

Ответ:

Решено

Как уже упоминалось другими и даже предложено вашим термином «шаблон», «регулярное выражение» - это путь.

В этом случае вы можете просто использовать std::regex_search. Пожалуйста, прочитайте об этом здесь.

Преимущество заключается в том, что если функция поиска возвращает результат, вы можете быть уверены, что числа указаны в правильном формате. Так что функция std::stoi будет работать всегда.

Регулярное выражение можно разработать с помощью страницы онлайн-тестирования регулярных выражений, такой как regex101.

Тогда реализация будет очень простой. См. приведенный ниже пример:

#include <iostream>
#include <string>
#include <regex>
#include <tuple>

const std::string test{"../blabla/here_is_same0000:00/0000:00:1A.0/blabla/blabla/blabla"};

const std::regex re{R"(.*?here_is_same0000:00/0000:00:([0-9a-fA-F]+)\.(\d).*)"};

std::tuple<int, int> values(const std::string& in) {
    
    std::tuple<int, int> result{};
    if (std::smatch sm{};std::regex_search(test, sm, re))
        result = {std::stoi(sm[1],nullptr,16),std::stoi(sm[2])};
    return result;
}

int main() {
    const auto& [i1,i2] = values(test);
    std::cout << i1 << ' ' << i2 << '\n';
}