Русский
Русский
English
Статистика
Реклама

Перевод Небольшие, но важные функции

Будущих студентов курса "C++ Developer. Professional" приглашаем принять участие в открытом уроке "Backend на современном С++".

А пока делимся традиционным переводом материала.


Начиная с C++20 в несколько стандартных контейнеров, включая std::map, std::set и std::string, были добавлены некоторые очень полезные функции для поиска. Необходимость в них существовала уже в течении достаточно долгого времени, и мне приятно видеть, что комитет наконец признал их важность. Надеюсь, это только начало серии замечательных дополнений.

Map и set

Типовая операция при работе с map проверить, существует ли конкретный ключ. Как это сделать в C++17? Все просто:

std::map<int, std::string> m{ {1, "one"}, {2, "two"}, {3, "three"} }; if (m.find(1) != m.end()){   std::cout << "key found!\n";}

Хотя это может быть достаточно просто, это отнюдь совсем не удобно для пользователя. По этой причине многие пишут свою собственную функцию contains(), которая принимает map и ключ и возвращает логическое значение, указывающее, содержит ли map ключ. В C++20 это больше не нужно, т.к. std::map имеет родной метод contains().

std::map<int, std::string> m{ {1, "one"}, {2, "two"}, {3, "three"} }; if (m.contains(1)){   std::cout << "key found!\n";}

То же верно и для std::set

std::set<int> s{ 1, 2, 3 };if (s.contains(1)){   std::cout << "key found!\n";}

Даже больше, в C++20 функция contains() была добавлена к целому ряду типов:

Строки

Похожая проблема актуальна и для строк. Иногда нам нужно узнать, содержит ли строка другую строку. Вот как это делается в C++17:

std::string text{"The quick brown fox jumps over the lazy dog"}; if (text.find("fox") != std::string::npos){   std::cout << "fox found!\n";}

Частный случай, связанный со строками, это поиск подстроки в начале и в конце строки. Поиск в начале относительно прост:

if (text.find("The quick") == 0){   std::cout << "right start\n";}

Но для поиска в конце требуется вспомогательная функция. Возможная реализация такова:

bool ends_with(std::string const & text, std::string const & substr){   if (substr.size() > text.size()) return false;   return std::equal(text.begin() + text.size() - substr.size(), text.end(), substr.begin());}

Что можно использовать следующим образом:

if (ends_with(text, "lazy dog")){   std::cout << "right end\n";}

(Примечание: Вы можете найти альтернативные реализации этой функции здесь)

C++20 значительно упростил ситуацию, где std::basicC16CstringC17Cwith() и endsC18Cwith("The quick"))

if (text.starts_with("The quick")){   std::cout << "right start\n";} if(text.ends_with("lazy dog")){   std::cout << "right end\n";}

Однако в C++20 есть достаточно большое упущение: функция для проверки того, содержит ли строка подстроку. Во время последнего заседания комитета ISO C++, такой метод был добавлен в C++23 (P1679). Это позволит нам написать следующее:

if (text.contains("fox")){   std::cout << "fox found!\n";}

Именно так мы всегда и хотели писать код.

Но

Вы должны помнить, что эти новые строковые функции чувствительны к регистру. Они не принимают предикат, позволяющий настроить способ выполнения поиска. Следовательно, если вам нужно выполнить поиск без учета регистра, вам все равно нужно будет реализовать это самостоятельно. Возможные реализации contains(), startwith() и endwith(), которые выполняют поиск без учета регистра, показаны ниже:

bool contains_ci(std::string const & text, std::string const & substr){   if (substr.length() > text.length()) return false;    auto it = std::search(      text.begin(), text.end(),      substr.begin(), substr.end(),      [](char ch1, char ch2) {          return std::toupper(ch1) == std::toupper(ch2); });    return it != text.end();} bool starts_with_ci(std::string const& text, std::string const& substr){   if (substr.length() > text.length()) return false;    auto it = std::search(      text.begin(), text.begin() + substr.length(),      substr.begin(), substr.end(),      [](char ch1, char ch2) {         return std::toupper(ch1) == std::toupper(ch2); });    return it == text.begin();} bool ends_with_ci(std::string const& text, std::string const& substr){   if (substr.length() > text.length()) return false;    auto it = std::search(      text.rbegin(), text.rbegin() + substr.length(),      substr.rbegin(), substr.rend(),      [](char ch1, char ch2) {         return std::toupper(ch1) == std::toupper(ch2); });    return it == text.rbegin();}

А использовать их можно следующим образом:

if (contains_ci(text, "FOX")){   std::cout << "fox found!\n";} if (starts_with_ci(text, "THE QUICK")){   std::cout << "right start\n";} if (ends_with_ci(text, "LAZY DOG")){   std::cout << "right end\n";}

Узнать подробнее о курсе "C++ Developer. Professional".

Записаться на открытый урок "Backend на современном С++".


Читать ещё:

Источник: habr.com
К списку статей
Опубликовано: 03.12.2020 14:20:34
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании otus. онлайн-образование

Программирование

C++

Stl

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru