Регулярные выражения в C++ с примерами: практическое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Регулярные выражения в C++ с примерами: на практике

Регулярные выражения (regex) — мощный инструмент для обработки текста, позволяющий искать, заменять и проверять строки по сложным шаблонам. В C++ поддержка регулярных выражений появилась в стандарте C++11 через библиотеку <regex>. В этой статье мы разберем, как использовать std::regex на практике: от простых проверок до извлечения данных и замены текста.

Материал будет полезен как новичкам, которые только знакомятся с C++, так и опытным разработчикам, желающим освежить знания. Мы рассмотрим ключевые функции: std::regex_match, std::regex_search и std::regex_replace, а также работу с группами захвата.

Основные компоненты библиотеки <regex>

Прежде чем перейти к примерам, разберемся с основными классами и функциями:

  • std::regex — класс, представляющий само регулярное выражение (шаблон). Создается из строки с шаблоном и опциональным флагом грамматики (по умолчанию ECMAScript).
  • std::smatch — контейнер для хранения результатов поиска (для строк типа std::string). Аналог — std::cmatch для C-строк.
  • std::regex_match — проверяет, соответствует ли вся строка шаблону целиком.
  • std::regex_search — ищет подстроку, соответствующую шаблону, в любом месте строки.
  • std::regex_replace — заменяет все совпадения с шаблоном на указанную строку (с поддержкой обратных ссылок).

Все функции принимают флаги для управления поведением (например, std::regex_constants::icase для регистронезависимого поиска).

Пример 1: Проверка строки на соответствие шаблону (std::regex_match)

Самая простая задача — проверить, соответствует ли строка заданному формату. Например, проверим, является ли строка корректным email-адресом (упрощенная версия):

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

int main() {
    std::string email = "user@example.com";
    // Шаблон для проверки email (упрощенный)
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");

    if (std::regex_match(email, pattern)) {
        std::cout << "Email корректен." << std::endl;
    } else {
        std::cout << "Email некорректен." << std::endl;
    }

    // Проверка на неверный email
    std::string bad_email = "user@.com";
    if (std::regex_match(bad_email, pattern)) {
        std::cout << "Email корректен." << std::endl;
    } else {
        std::cout << "Email некорректен." << std::endl;
    }

    return 0;
}

Вывод:

Email корректен.
Email некорректен.

Пояснение:

  • Мы используем сырой строковый литерал R"(...)", чтобы не экранировать обратные слеши.
  • Функция std::regex_match возвращает true, только если вся строка полностью соответствует шаблону.
  • Шаблон [a-zA-Z0-9._%+-]+ означает "один или более символов из указанного набора".

Пример 2: Поиск подстроки и извлечение данных (std::regex_search)

Часто нужно не просто проверить, а найти все вхождения шаблона и извлечь части строки. Для этого используется std::regex_search в цикле. В следующем примере мы найдем все номера телефонов в формате +7-XXX-XXX-XX-XX в тексте и извлечем код оператора:

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

int main() {
    std::string text = "Контакты: +7-495-123-45-67 и +7-916-987-65-43. Доп. номер: +7-495-111-22-33.";
    // Шаблон: +7-код(3 цифры)-... (группы захвата для кода и остального)
    std::regex pattern(R"(\+7-(\d{3})-\d{3}-\d{2}-\d{2})");
    std::smatch matches;

    // Ищем все совпадения
    auto begin = text.cbegin();
    auto end = text.cend();
    while (std::regex_search(begin, end, matches, pattern)) {
        std::cout << "Найден номер: " << matches.str() << std::endl;
        std::cout << "  Код оператора: " << matches.str(1) << std::endl;
        // Сдвигаем начало поиска после найденного совпадения
        begin = matches.suffix().first;
    }

    return 0;
}

Вывод:

Найден номер: +7-495-123-45-67
  Код оператора: 495
Найден номер: +7-916-987-65-43
  Код оператора: 916
Найден номер: +7-495-111-22-33
  Код оператора: 495

Пояснение:

  • Круглые скобки () в шаблоне создают группы захвата. matches.str(1) возвращает содержимое первой группы.
  • Мы используем итераторы begin и end для поиска в цикле. После каждого совпадения сдвигаем begin на позицию после найденного текста.
  • Метод matches.suffix() возвращает часть строки после совпадения.

Пример 3: Замена текста с использованием обратных ссылок (std::regex_replace)

Функция std::regex_replace позволяет заменить все вхождения шаблона на новую строку. В строке замены можно использовать обратные ссылки вида $1, $2 и т.д., которые ссылаются на группы захвата. Например, переформатируем телефонные

Блоги

Рекомендаций по книгам