Expressions régulières en C++ avec exemples : en pratique
\n\nLes expressions régulières (regex) sont un outil puissant pour le traitement de texte, permettant de rechercher, remplacer et valider des chaînes selon des motifs complexes. En C++, le support des expressions régulières est apparu avec la norme C++11 via la bibliothèque <regex>. Dans cet article, nous allons voir comment utiliser std::regex en pratique : des vérifications simples à l'extraction de données et au remplacement de texte.
Ce contenu sera utile aussi bien aux débutants qui découvrent le C++ qu'aux développeurs expérimentés souhaitant rafraîchir leurs connaissances. Nous aborderons les fonctions clés : std::regex_match, std::regex_search et std::regex_replace, ainsi que le travail avec les groupes de capture.
Composants principaux de la bibliothèque <regex>
\n\nAvant de passer aux exemples, examinons les classes et fonctions principales :
\n\n- \n
- std::regex — classe représentant l'expression régulière elle-même (le motif). Créée à partir d'une chaîne contenant le motif et d'un indicateur de grammaire optionnel (par défaut ECMAScript). \n
- std::smatch — conteneur pour stocker les résultats de recherche (pour les chaînes de type
std::string). L'équivalent eststd::cmatchpour les chaînes C. \n - std::regex_match — vérifie si la chaîne entière correspond exactement au motif. \n
- std::regex_search — recherche une sous-chaîne correspondant au motif, à n'importe quel endroit de la chaîne. \n
- std::regex_replace — remplace toutes les correspondances avec le motif par la chaîne spécifiée (avec prise en charge des références arrière). \n
Toutes les fonctions acceptent des indicateurs pour contrôler le comportement (par exemple, std::regex_constants::icase pour la recherche insensible à la casse).
Exemple 1 : Validation d'une chaîne par rapport à un motif (std::regex_match)
\n\nLa tâche la plus simple est de vérifier si une chaîne correspond à un format donné. Par exemple, vérifions si une chaîne est une adresse email valide (version simplifiée) :
\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string email = "user@example.com";\n // Motif pour vérifier l'email (simplifié)\n std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})");\n\n if (std::regex_match(email, pattern)) {\n std::cout << "Email valide." << std::endl;\n } else {\n std::cout << "Email invalide." << std::endl;\n }\n\n // Vérification d'un email invalide\n std::string bad_email = "user@.com";\n if (std::regex_match(bad_email, pattern)) {\n std::cout << "Email valide." << std::endl;\n } else {\n std::cout << "Email invalide." << std::endl;\n }\n\n return 0;\n}\n\nRésultat :
\nEmail valide.\nEmail invalide.\n\nExplication :
\n- \n
- Nous utilisons un littéral de chaîne brute
R"(...)"pour éviter d'échapper les barres obliques inverses. \n - La fonction
std::regex_matchretournetrueuniquement si la chaîne entière correspond exactement au motif. \n - Le motif
[a-zA-Z0-9._%+-]+signifie "un ou plusieurs caractères parmi l'ensemble spécifié". \n
Exemple 2 : Recherche de sous-chaîne et extraction de données (std::regex_search)
\n\nSouvent, il ne s'agit pas seulement de vérifier, mais de trouver toutes les occurrences d'un motif et d'extraire des parties de la chaîne. Pour cela, on utilise std::regex_search dans une boucle. Dans l'exemple suivant, nous allons trouver tous les numéros de téléphone au format +7-XXX-XXX-XX-XX dans un texte et extraire le code de l'opérateur :
#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string text = "Contacts : +7-495-123-45-67 et +7-916-987-65-43. Numéro supplémentaire : +7-495-111-22-33.";\n // Motif : +7-code(3 chiffres)-... (groupes de capture pour le code et le reste)\n std::rege