C++

Notions de base sur les expressions régulières en C++

Notions de base sur les expressions régulières en C++
Considérez la phrase suivante entre guillemets :

"Voici mon homme."

Cette chaîne peut être à l'intérieur de l'ordinateur, et l'utilisateur peut vouloir savoir si elle contient le mot « man ». S'il contient le mot homme, il peut alors vouloir changer le mot « homme » en « femme » ; de sorte que la chaîne doit lire :

"Voici ma femme."

Il existe de nombreux autres désirs comme ceux-ci de la part de l'utilisateur de l'ordinateur ; certains sont complexes. L'expression régulière, abrégée, regex, fait l'objet de la gestion de ces problèmes par l'ordinateur. C++ est livré avec une bibliothèque appelée regex. Ainsi, un programme C++ pour gérer les expressions régulières devrait commencer par :

#inclure
#inclure
en utilisant l'espace de noms std ;

Cet article explique les bases des expressions régulières en C++.

Contenu de l'article

  • Principes fondamentaux des expressions régulières
  • Schéma
  • Classes de personnages
  • Correspondance des espaces blancs
  • La période (.) dans le motif
  • Répétitions correspondantes
  • Alternance correspondante
  • Correspondance du début ou de la fin
  • Regroupement
  • Les constantes regex_constantes icase et multilignes
  • Faire correspondre l'ensemble de la cible
  • L'objet match_results
  • Position du match
  • Rechercher et remplacer
  • Conclusion

Principes fondamentaux des expressions régulières

Regex

Une chaîne comme "Voici mon homme.” ci-dessus est la séquence cible ou la chaîne cible ou simplement, la cible. "man", qui a été recherché, est l'expression régulière, ou simplement, regex.

Correspondant à

On dit que la correspondance se produit lorsque le mot ou la phrase recherché est localisé. Après appariement, un remplacement peut avoir lieu. Par exemple, après que « homme » se trouve au-dessus, il peut être remplacé par « femme ».

Correspondance simple

Le programme suivant montre comment le mot « homme » est associé.

#inclure
#inclure
en utilisant l'espace de noms std ;
int main()

regex reg("homme");
if (regex_search("Voici mon homme.", rég))
cout << "matched" << endl;
autre
cout << "not matched" << endl;
renvoie 0 ;

La fonction regex_search() renvoie true s'il y a une correspondance et renvoie false si aucune correspondance ne se produit. Ici, la fonction prend deux arguments : le premier est la chaîne cible et le second est l'objet regex. La regex elle-même est "man", entre guillemets. La première instruction de la fonction main() forme l'objet regex. Regex est un type et reg est l'objet regex. La sortie du programme ci-dessus est "correspondée", car "man" est vu dans la chaîne cible. Si "man" n'avait pas été vu dans la cible, regex_search() aurait renvoyé false et la sortie aurait été "non correspondante".

La sortie du code suivant n'est « pas de correspondance » :

regex reg("homme");
if (regex_search("Voici ma fabrication.", rég))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Pas de correspondance car l'expression régulière "man" n'a pas pu être trouvée dans l'intégralité de la chaîne cible, "Voici ma création."

Schéma

L'expression régulière, « homme » ci-dessus, est très simple. Les expressions régulières ne sont généralement pas si simples. Les expressions régulières ont des métacaractères. Les métacaractères sont des caractères avec des significations spéciales. Un métacaractère est un caractère sur les caractères. Les métacaractères regex C++ sont :

^ $ \ . * + ? ( ) [ ] |

Une expression régulière, avec ou sans métacaractères, est un modèle.

Classes de personnages

Crochets

Un motif peut avoir des caractères entre crochets. Avec cela, une position particulière dans la chaîne cible correspondrait à l'un des caractères des crochets. Considérez les cibles suivantes :

"Le chat est dans la chambre."
"La chauve-souris est dans la chambre."
"Le rat est dans la chambre."

L'expression régulière, [cbr]at correspondrait à cat dans la première cible. Il correspondrait à la batte dans la deuxième cible. Il correspondrait au rat dans la troisième cible. C'est parce que « chat » ou « chauve-souris » ou « rat » commence par « c » ou « b » ou « r ». Le segment de code suivant illustre cela :

regex reg("[cbr]at");
if (regex_search("Le chat est dans la pièce.", rég))
cout << "matched" << endl;
if (regex_search("La chauve-souris est dans la pièce.", rég))
cout << "matched" << endl;
if (regex_search("Le rat est dans la pièce.", rég))
cout << "matched" << endl;

La sortie est :

apparié
apparié
apparié

Gamme de caractères

La classe, [cbr] dans le modèle [cbr], correspondrait à plusieurs caractères possibles dans la cible. Il correspondrait à « c » ou « b » ou « r » dans la cible. Si la cible n'a aucun des "c" ou "b" ou "r", suivi de "at", il n'y aurait pas de correspondance.

Certaines possibilités comme 'c' ou 'b' ou 'r' existent dans une plage. La plage de chiffres, 0 à 9 a 10 possibilités, et le modèle pour cela est [0-9]. La gamme d'alphabets minuscules, a à z, a 26 possibilités, et le modèle pour cela est [a-z]. La gamme d'alphabets majuscules, A à Z, a 26 possibilités, et le modèle pour cela est [A-Z]. - n'est pas officiellement un métacaractère, mais entre crochets, cela indiquerait une plage. Ainsi, ce qui suit produit une correspondance :

if (regex_search("ID6id", regex("[0-9]")))
cout << "matched" << endl;

Notez comment le regex a été construit comme deuxième argument. La correspondance se produit entre le chiffre, 6 dans la plage, 0 à 9, et le 6 dans la cible, "ID6id". Le code ci-dessus est équivalent à :

if (regex_search("ID6id", regex("[0123456789]")))
cout << "matched" << endl;

Le code suivant produit une correspondance :

char str[] = "ID6iE" ;
if (regex_search(str, regex("[a-z]")))
cout << "matched" << endl;

Notez que le premier argument ici est une variable de chaîne et non le littéral de chaîne. La correspondance est entre 'i' dans [a-z] et 'i' dans "ID6iE".

N'oubliez pas qu'une gamme est une classe. Il peut y avoir du texte à droite de la plage ou à gauche de la plage dans le motif. Le code suivant produit une correspondance :

if (regex_search("ID2id est un ID", regex("ID[0-9]id")))
cout << "matched" << endl;

La correspondance est entre "ID[0-9]id" et "ID2id". Le reste de la chaîne cible, « est un ID », ne correspond pas dans cette situation.

Tel qu'il est utilisé dans le sujet des expressions régulières (regex), le mot classe signifie en fait un ensemble. C'est-à-dire que l'un des personnages de l'ensemble doit correspondre.

Remarque : Le trait d'union - est un métacaractère uniquement entre crochets, indiquant une plage. Ce n'est pas un métacaractère dans la regex, en dehors des crochets.

Négation

Une classe comprenant une plage peut être annulée. C'est-à-dire qu'aucun des caractères de l'ensemble (classe) ne doit correspondre. Ceci est indiqué par le métacaractère ^ au début du modèle de classe, juste après le crochet ouvrant. Ainsi, [^0-9] signifie faire correspondre le caractère à la position appropriée dans la cible, qui n'est pas un caractère dans la plage, de 0 à 9 inclus. Le code suivant ne produira donc pas de correspondance :

if (regex_search("0123456789101112", regex("[^0-9]")))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Un chiffre compris entre 0 et 9 peut être trouvé dans l'une des positions de chaîne cible, « 0123456789101112 » ; donc il n'y a pas de correspondance - négation.

Le code suivant produit une correspondance :

if (regex_search("ABCDEFGHIJ", regex("[^0-9]")))
cout << "matched" << endl;

Aucun chiffre n'a pu être trouvé dans la cible, « ABCDEFGHIJ » ; donc il y a une correspondance.

[a-z] est une plage en dehors de [^a-z]. Et donc [^a-z] est la négation de [a-z].

[A-Z] est une plage en dehors de [^A-Z]. Et donc [^A-Z] est la négation de [A-Z].

D'autres négations existent.

Correspondance des espaces blancs

"ou \t ou \r ou \n ou \f est un caractère d'espacement. Dans le code suivant, l'expression régulière, "\n" correspond à "\n" dans la cible :

if (regex_search("De la première ligne.\r\nDe la ligne deux.", regex("\n"))))
cout << "matched" << endl;

Correspondance avec n'importe quel caractère d'espacement

Le modèle ou la classe pour correspondre à n'importe quel caractère d'espace blanc est, [ \t\r\n\f]. Dans le code suivant, "est mis en correspondance :

if (regex_search("un deux", regex("[ \t\r\n\f]")))
cout << "matched" << endl;

Correspondance avec n'importe quel caractère non blanc

Le modèle ou la classe correspondant à tout caractère autre qu'un espace blanc est [^ \t\r\n\f]. Le code suivant produit une correspondance car il n'y a pas d'espace dans la cible :

if (regex_search("1234abcd", regex("[^ \t\r\n\f]")))
cout << "matched" << endl;

La période (.) dans le motif

La période (.) dans le modèle correspond à n'importe quel caractère, y compris lui-même, sauf \n, dans la cible. Une correspondance est produite dans le code suivant :

if (regex_search("1234abcd", regex(".")))
cout << "matched" << endl;

Aucun résultat correspondant dans le code suivant car la cible est « \n ».

if (regex_search("\n", regex(".")))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Remarque : À l'intérieur d'une classe de caractères entre crochets, le point n'a pas de signification particulière.

Répétitions correspondantes

Un caractère ou un groupe de caractères peut apparaître plusieurs fois dans la chaîne cible. Un motif peut correspondre à cette répétition. Les métacaractères, ?, *, + et sont utilisés pour faire correspondre la répétition dans la cible. Si x est un caractère d'intérêt dans la chaîne cible, alors les métacaractères ont les significations suivantes :

x* : signifie correspondre à 'x' 0 fois ou plus, je.e., n'importe quel nombre de fois
x+ : signifie correspondre à « x » 1 fois ou plus, je.e., au moins une fois
X? : signifie correspondre à 'x' 0 ou 1 fois
xn, : signifie correspondre à 'x' au moins n fois ou plus. Notez la virgule.
xn : correspond à 'x' exactement n fois
xn,m : correspond à 'x' au moins n fois, mais pas plus de m fois.

Ces métacaractères sont appelés quantificateurs.

Illustrations

*

Le * correspond au caractère précédent ou au groupe précédent, zéro ou plusieurs fois. « o* » correspond à « o » dans « chien » de la chaîne cible. Il correspond également à « oo » dans « livre » et « à la recherche ». L'expression régulière, "o*" correspond à "boooo" dans "The animal booooed.". Remarque : « o* » correspond à « dig », où « o » apparaît zéro (ou plus).

+

Le + correspond au caractère précédent ou au groupe précédent, 1 ou plusieurs fois. Comparez-le avec zéro ou plusieurs fois pour *. Ainsi, l'expression régulière, "e+" correspond à "e" dans "manger", où "e" apparaît une fois. « e+ » correspond également à « ee » dans « mouton », où « e » apparaît plus d'une fois. Remarque : « e+ » ne correspondra pas à « dig » car dans « dig », « e » ne se produit pas au moins une fois.

?

le ? correspond au caractère précédent ou au groupe précédent, 0 ou 1 fois (et pas plus). Donc, "e?” correspond à “dig” car 'e' apparaît dans “dig”, temps zéro. "e?” correspond à “set” car 'e' apparaît dans “set”, une fois. Remarque : « e?” correspond toujours à “mouton”; bien qu'il y ait deux 'e' dans "mouton". Il y a une nuance ici - voir plus tard.

n,

Cela correspond à au moins n répétitions consécutives d'un caractère précédent ou d'un groupe précédent. Ainsi, l'expression régulière "e2," correspond aux deux "e" de la cible "mouton" et aux trois "e" de la cible "mouton". "e2," ne correspond pas à "set", car "set" n'a qu'un seul "e".

n

Cela correspond exactement à n répétitions consécutives d'un caractère ou d'un groupe précédent. Donc la regex, "e2" correspond aux deux 'e' dans la cible, "mouton". "e2" ne correspond pas à "set" car "set" n'a qu'un seul "e". Eh bien, « e2 » correspond à deux e dans la cible, « mouton ». Il y a une nuance ici - voir plus tard.

n,m

Cela correspond à plusieurs répétitions consécutives d'un caractère précédent ou d'un groupe précédent, n'importe où de n à m, inclus. Donc, "e1,3" ne correspond à rien dans "dig", qui n'a pas de "e". Il correspond au "e" dans "set", aux deux "e" dans "mouton", aux trois "e" dans "mouton" et aux trois "e" dans "mouton". Il y a une nuance au dernier match - voir plus tard.

Alternance correspondante

Considérez la chaîne cible suivante dans l'ordinateur.

« La ferme a des porcs de différentes tailles."

Le programmeur peut vouloir savoir si cette cible a « chèvre » ou « lapin » ou « cochon ». Le code serait le suivant :

char str[] = "La ferme a des porcs de différentes tailles.";
if (regex_search(str, regex("chèvre|lapin|cochon")))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Le code produit une correspondance. Notez l'utilisation du caractère d'alternance, |. Il peut y avoir deux, trois, quatre et plus d'options. C++ essaiera d'abord de faire correspondre la première alternative, "chèvre", à chaque position de caractère dans la chaîne cible. S'il ne réussit pas avec "chèvre", il essaie l'alternative suivante, "lapin". S'il ne réussit pas avec "lapin", il essaie l'alternative suivante, "cochon". Si "cochon" échoue, alors C++ passe à la position suivante dans la cible et recommence avec la première alternative.

Dans le code ci-dessus, « cochon » correspond.

Correspondance du début ou de la fin

Début


Si ^ est au début de l'expression régulière, le texte de début de la chaîne cible peut être mis en correspondance avec l'expression régulière. Dans le code suivant, le début de la cible est « abc », qui correspond :

if (regex_search("abc et def", regex("^abc")))
cout << "matched" << endl;

Aucune correspondance n'a lieu dans le code suivant :

if (regex_search("Oui, abc et def", regex("^abc")))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Ici, « abc » n'est pas au début de la cible.

Remarque : Le caractère circonflexe, '^', est un métacaractère au début de l'expression régulière, correspondant au début de la chaîne cible. C'est toujours un métacaractère au début de la classe de caractère, où il nie la classe.

Finir

Si $ est à la fin de l'expression régulière, le texte de fin de la chaîne cible peut être mis en correspondance avec l'expression régulière. Dans le code suivant, la fin de la cible est « xyz », qui correspond :

if (regex_search("uvw et xyz", regex("xyz$")))
cout << "matched" << endl;

Aucune correspondance n'a lieu dans le code suivant :

if (regex_search("uvw et xyz final", regex("xyz$")))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Ici, "xyz" n'est pas à la fin de la cible.

Regroupement

Les parenthèses peuvent être utilisées pour regrouper des caractères dans un motif. Considérez l'expression régulière suivante :

"un concert (pianiste)"

Le groupe est ici « pianiste » entouré des métacaractères ( et ). C'est en fait un sous-groupe, alors que "un concert (pianiste)" est le groupe entier. Considérer ce qui suit:

"Le (le pianiste est bon)"

Ici, le sous-groupe ou la sous-chaîne est « le pianiste est bon ».

Sous-chaînes avec des parties communes

Un comptable est une personne qui s'occupe des livres. Imaginez une bibliothèque avec un comptable et une étagère. Supposons que l'une des chaînes cibles suivantes se trouve dans l'ordinateur :

"La bibliothèque a une étagère qui est admirée.";
"Voici le comptable.";
"Le comptable travaille avec l'étagère.";

Supposons que l'intérêt du programmeur n'est pas de savoir laquelle de ces phrases est dans l'ordinateur. Pourtant, son intérêt est de savoir si « bibliothèque » ou « comptable » est présent dans la chaîne cible de l'ordinateur. Dans ce cas, son regex peut être :

"bibliothèque|comptable."

Utiliser l'alternance.

Notez que « livre », qui est commun aux deux mots, a été tapé deux fois, dans les deux mots du motif. Pour éviter de taper « book » deux fois, la regex serait mieux écrite comme :

"livre(étagère|gardien)"

Ici, le groupe « shelf|keeper » Le métacaractère alternance a toujours été utilisé, mais pas pour deux longs mots. Il a été utilisé pour les deux parties finales des deux longs mots. C++ traite un groupe comme une entité. Ainsi, C++ recherchera "shelf" ou "keeper" qui vient immédiatement après "book". La sortie du code suivant est « correspondante » :

char str[] = "La bibliothèque a une étagère qui est admirée.";
if (regex_search(str, regex("book(shelf|keeper)")))
cout << "matched" << endl;

« étagère » et non « comptable » ont été appariés.

Les constantes regex_constantes icase et multilignes

icase

La correspondance est sensible à la casse par défaut. Cependant, il peut être rendu insensible à la casse. Pour ce faire, utilisez la constante regex::icase, comme dans le code suivant :

if (regex_search("Feedback", regex("feed", regex::icase)))
cout << "matched" << endl;

La sortie est « correspondante ». Ainsi, « Feedback » avec un « F » majuscule a été associé à « feedback » avec un « f » minuscule. "regex::icase" est devenu le deuxième argument du constructeur regex(). Sans cela, la déclaration ne produirait pas de correspondance.

Multiligne

Considérez le code suivant :

char str[] = "ligne 1\nligne 2\nligne 3" ;
if (regex_search(str, regex("^.*$"))))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

La sortie n'est "pas adaptée". L'expression régulière, "^.*$," correspond à la chaîne cible de son début à sa fin. ".*" signifie tout caractère sauf \n, zéro ou plusieurs fois. Donc, en raison des caractères de nouvelle ligne (\n) dans la cible, il n'y avait pas de correspondance.

La cible est une chaîne multiligne. Pour '.' pour correspondre au caractère de nouvelle ligne, la constante "regex::multiline" doit être créée, le deuxième argument de la construction regex(). Le code suivant illustre cela :

char str[] = "ligne 1\nligne 2\nligne 3" ;
if (regex_search(str, regex("^.*$", regex::multiline)))
cout << "matched" << endl;
autre
cout << "not matched" << endl;

Faire correspondre la chaîne cible entière

Pour faire correspondre la chaîne cible entière, qui n'a pas le caractère de nouvelle ligne (\n), la fonction regex_match() peut être utilisée. Cette fonction est différente de regex_search(). Le code suivant illustre cela :

char str[] = "premier deuxième troisième" ;
if (regex_match(str, regex(".*deuxième.*")))
cout << "matched" << endl;

Il y a une correspondance ici. Cependant, notez que l'expression régulière correspond à l'ensemble de la chaîne cible et que la chaîne cible n'a pas de '\n'.

L'objet match_results

La fonction regex_search() peut prendre un argument entre la cible et l'objet regex. Cet argument est l'objet match_results. L'ensemble de la chaîne (partie) correspondante et les sous-chaînes correspondantes peuvent être connues avec elle. Cet objet est un tableau spécial avec des méthodes. Le type d'objet match_results est cmatch (pour les chaînes littérales).

Obtenir des correspondances

Considérez le code suivant :

char str[] = "La femme que vous cherchiez!";
cmatch m;
if (regex_search(str, m, regex("w.m.n")))
cout << m[0] << endl;

La chaîne cible contient le mot « femme ». La sortie est « femme », ce qui correspond à la regex, « w.m.n". À l'index zéro, le tableau spécial contient la seule correspondance, qui est « femme ».

Avec les options de classe, seule la première sous-chaîne trouvée dans la cible est envoyée au tableau spécial. Le code suivant illustre cela :

cmatch m;
if (regex_search("Le rat, le chat, la chauve-souris!", m, regex("[bcr]at")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

La sortie est "rat" à partir de l'index zéro. m[1] et m[2] sont vides.

Avec les alternatives, seule la première sous-chaîne trouvée dans la cible est envoyée au tableau spécial. Le code suivant illustre cela :

if (regex_search("Le lapin, la chèvre, le cochon!", m, regex("chèvre|lapin|cochon")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

La sortie est "lapin" à partir de l'index zéro. m[1] et m[2] sont vides.

Groupements

Lorsque des groupes sont impliqués, le modèle complet correspond, va dans la cellule zéro du tableau spécial. La prochaine sous-chaîne trouvée va dans la cellule 1 ; la sous-chaîne suivante va dans la cellule 2 ; etc. Le code suivant illustre cela :

if (regex_search("Meilleur libraire aujourd'hui!", m, regex("book((sel)(ler))")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

La sortie est :

libraire
vendeur
sel
ler

A noter que le groupe (vendeur) vient avant le groupe (sel).

Position du match

La position de match pour chaque sous-chaîne dans le tableau cmatch peut être connue. Le comptage commence à partir du premier caractère de la chaîne cible, à la position zéro. Le code suivant illustre cela :

cmatch m;
if (regex_search("Meilleur libraire aujourd'hui!", m, regex("book((sel)(ler))")))
cout << m[0] << "->" << m.position(0) << endl;
cout << m[1] << "->" << m.position(1) << endl;
cout << m[2] << "->" << m.position(2) << endl;
cout << m[3] << "->" << m.position(3) << endl;

Notez l'utilisation de la propriété position, avec l'index de la cellule, comme argument. La sortie est :

libraire->5
vendeur -> 9
sel->9
ler->12

Rechercher et remplacer

Un nouveau mot ou une nouvelle phrase peut remplacer la correspondance. La fonction regex_replace() est utilisée pour cela. Cependant, cette fois, la chaîne où le remplacement se produit est l'objet de chaîne, pas le littéral de chaîne. Ainsi, la bibliothèque de chaînes doit être incluse dans le programme. Illustration:

#inclure
#inclure
#inclure
en utilisant l'espace de noms std ;
int main()

string str = "Ici, vient mon homme. Voilà ton homme.";
string newStr = regex_replace(str, regex("homme"), "femme");
cout << newStr << endl;
renvoie 0 ;

La fonction regex_replace(), telle que codée ici, remplace toutes les correspondances. Le premier argument de la fonction est la cible, le second est l'objet regex et le troisième est la chaîne de remplacement. La fonction renvoie une nouvelle chaîne, qui est la cible mais ayant le remplacement. La sortie est :

"Voici ma femme. Voilà ta femme."

Conclusion

L'expression régulière utilise des modèles pour faire correspondre les sous-chaînes dans la chaîne de séquence cible. Les modèles ont des métacaractères. Les fonctions couramment utilisées pour les expressions régulières C++ sont : regex_search(), regex_match() et regex_replace(). Une regex est un motif entre guillemets doubles. Cependant, ces fonctions prennent l'objet regex comme argument et pas seulement le regex. La regex doit être transformée en un objet regex avant que ces fonctions puissent l'utiliser.

Ajoutez des gestes de souris à Windows 10 à l'aide de ces outils gratuits
Ces dernières années, les ordinateurs et les systèmes d'exploitation ont considérablement évolué. Il fut un temps où les utilisateurs devaient utilise...
Contrôlez et gérez le mouvement de la souris entre plusieurs moniteurs dans Windows 10
Gestionnaire de souris à double affichage vous permet de contrôler et de configurer le mouvement de la souris entre plusieurs moniteurs, en ralentissa...
WinMouse vous permet de personnaliser et d'améliorer le mouvement du pointeur de la souris sur un PC Windows
Si vous souhaitez améliorer les fonctions par défaut de votre pointeur de souris, utilisez un logiciel gratuit WinMouse. Il ajoute plus de fonctionnal...