web-dev-qa-db-fra.com

Est-ce l'erreur regex C ++ 11 moi ou le compilateur?

OK, ce n'est pas le programme d'origine dans lequel j'ai eu ce problème, mais je l'ai dupliqué 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, Soit dit en passant, est:

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

Et le résultat quand j'essaye 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 Ou [a-z]. Est-ce un problème avec le compilateur? Je pourrais peut-être croire que le moteur d'expression régulière de C++ 11 a différentes façons de dire "espace" ou "caractère Word", mais les crochets ne fonctionnent pas est un tronçon. Est-ce quelque chose qui a été corrigé dans 4.6.2?

MODIFIER:

Joachim Pileborg a fourni une solution partielle, en utilisant un paramètre supplémentaire regex_constants Pour activer une syntaxe qui prend en charge les crochets, mais ni basic, extended, awk, ni ECMAScript ne semblent prendre en charge les termes avec barre oblique inverse comme \\s, \\w ou \\t.

MODIFIER 2:

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

54
Shay Guy

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


Ancienne 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 le drapeau regex_constants::ECMAScript Par défaut donc il doit comprendre cette syntaxe.

Est-ce l'erreur regex C++ 11 moi ou le compilateur?

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

33
jfs

L'erreur est due au fait que la création d'une expression régulière par défaut utilise la syntaxe ECMAScript pour l'expression, qui ne prend pas en charge les crochets. Vous devez déclarer l'expression avec l'indicateur basic ou extended:

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

Edit On dirait que libstdc ++ (qui fait partie de GCC et la bibliothèque qui gère tous les trucs C++) n'implémente pas encore complètement les expressions régulières. Dans leur document d'état ils disent que La grammaire d'expression régulière ECMAScript modifiée n'est pas encore implémentée.

28

Le support des regex s'est amélioré entre gcc 4.8.2 et 4.9.2. Par exemple, l'expression régulière =[A-Z]{3} échouait pour moi avec:

Erreur d'expression régulière

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

7
Drew Noakes