У меня есть строка типа:
"../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++, вам нужно будет использовать библиотеку std::string. Эта библиотека предоставляет множество полезных методов для работы со строками, например, метод substr(), который можно использовать для извлечения подстрок из строки. Кроме того, вы можете использовать класс std::stringstream для разбора строки с помощью оператора >>. Этот класс предоставляет различные методы для преобразования строковых объектов в различные типы, такие как int, float, double и т. д. Наконец, вы можете использовать метод find() для поиска определенного символа или подстроки в строке.
Я хочу написать этот код более читаемым @463035818_is_not_a_number
Не могли бы вы привести пример регулярного выражения для строки, которую я упомянул в вопросе @πάνταῥεῖ
Как уже упоминалось другими и даже предложено вашим термином «шаблон», «регулярное выражение» - это путь.
В этом случае вы можете просто использовать 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';
}
почему тебе это кажется плохим? Что вы имеете ввиду под "лучше"?