54 votes

Cette erreur d'expressions rationnelles C++11 est-elle due à moi ou au compilateur ?

OK, ce n'est pas le programme original dans lequel j'ai eu ce problème, mais je l'ai reproduit dans un programme beaucoup plus petit. Problème très simple.

main.cpp :

#include <iostream>
#include <regex>
using namespace std;

int main()
{
    regex r1("S");
    printf("S works.\n");
    regex r2(".");
    printf(". works.\n");
    regex r3(".+");
    printf(".+ works.\n");
    regex r4("[0-9]");
    printf("[0-9] works.\n");
    return 0;
}

Compilé avec succès avec cette commande, aucun message d'erreur :

$ g++ -std=c++0x main.cpp

La dernière ligne de g++ -v d'ailleurs, l'est :

gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)

Et le résultat lorsque j'essaie de l'exécuter :

$ ./a.out 
S works.
. works.
.+ works.
terminate called after throwing an instance of 'std::regex_error'
  what():  regex_error
Aborted

Cela se produit de la même manière si je change r4 en \\s , \\w o [a-z] . S'agit-il d'un problème avec le compilateur ? Je pourrais croire que le moteur regex de C++11 a différentes façons de dire "espace blanc" ou "caractère de mot", mais des crochets qui ne fonctionnent pas, c'est un peu exagéré. Est-ce un problème qui a été corrigé dans la version 4.6.2 ?

EDITAR:

Joachim Pileborg a fourni une solution partielle, en utilisant un supplément de regex_constants pour activer une syntaxe qui prend en charge les crochets, mais ni le paramètre basic , extended , awk ni ECMAScript semblent prendre en charge les termes en antislash, tels que \\s , \\w o \\t .

EDIT 2 :

L'utilisation de chaînes de caractères brutes ( R"(\w)" au lieu de "\\w" ) ne semble pas fonctionner non plus.

34voto

J.F. Sebastian Points 102961

Mise à jour : <regex> est maintenant implémenté et publié dans GCC 4.9.0.


Vieille réponse :

La syntaxe ECMAScript accepte [0-9] , \s , \w etc, voir ECMA-262 (15.10) . Voici un exemple avec boost::regex qui utilise également la syntaxe ECMAScript par défaut :

#include <boost/regex.hpp>

int main(int argc, char* argv[]) {
  using namespace boost;
  regex e("[0-9]");
  return argc > 1 ? !regex_match(argv[1], e) : 2;
}

Ça marche :

$ g++ -std=c++0x *.cc -lboost_regex && ./a.out 1

Selon la norme C++11 (28.8.2) basic_regex() utilise regex_constants::ECMAScript par défaut, il doit donc comprendre cette syntaxe.

Cette erreur d'expressions rationnelles C++11 est-elle due à moi ou au compilateur ?

gcc-4.6.1 ne supporte pas les expressions régulières c++11 (28.13) .

29voto

Joachim Pileborg Points 121221

L'erreur est due au fait que la création d'une regex par défaut utilise la syntaxe ECMAScript pour l'expression, qui ne prend pas en charge les parenthèses. Vous devez déclarer l'expression avec l'option basic o extended drapeau :

std::regex r4("[0-9]", std::regex_constants::basic);

Editar Il semblerait que libstdc++ (qui fait partie de GCC et qui est la bibliothèque qui gère tous les éléments C++) n'implémente pas encore complètement les expressions régulières. Dans leur document de statut ils disent que Grammaire d'expression régulière ECMAScript modifiée n'est pas encore mis en œuvre.

7voto

Drew Noakes Points 69288

La prise en charge des regex a été améliorée entre gcc 4.8.2 et 4.9.2. Par exemple, la fonction regex =[A-Z]{3} a échoué pour moi avec :

Erreur de regex

Après la mise à jour vers gcc 4.9.2, cela fonctionne comme prévu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X