2010-11-15 10 views
5

J'écris un petit programme en ligne de commande qui demande à l'utilisateur des polynômes sous la forme ax^2 + bx^1 + cx^0. Je vais analyser les données plus tard mais pour l'instant j'essaie juste de voir si je peux faire correspondre le polynôme avec l'expression régulière (\+|-|^)(\d*)x\^([0-9*]*) Mon problème est, il ne correspond pas à plusieurs termes dans le polynôme saisi par l'utilisateur sauf si je change à ((\+|-|^)(\d*)x\^([0-9*]*))* (la différence est que l'expression entière est groupée et a un astérisque à la fin). La première expression fonctionne si je tape quelque chose comme "4x^2" mais pas "4x^2+3x^1+2x^0", car elle ne vérifie pas plusieurs fois.Pourquoi Boost.Regex ne trouve-t-il pas plusieurs correspondances dans une chaîne?

Ma question est, pourquoi ne pas Boost.Regex's regex_match() trouver plusieurs correspondances au sein de la même chaîne? Cela se fait dans l'éditeur d'expressions régulières que j'ai utilisé (Expresso) mais pas dans le code C++ actuel. Est-ce censé être comme ça? Faites-moi savoir si quelque chose n'a pas de sens et je vais essayer de clarifier. Merci pour l'aide.

Edit1: Voici mon code (je suis le tutoriel ici: http://onlamp.com/pub/a/onlamp/2006/04/06/boostregex.html?page=3)

int main() 
{ 
    string polynomial; 

    cmatch matches; // matches 

    regex re("((\\+|-|^)(\\d*)x\\^([0-9*]*))*"); 

    cout << "Please enter your polynomials in the form ax^2+bx^1+cx^0." << endl; 

    cout << "Polynomial:"; 
    getline(cin, polynomial); 

    if(regex_match(polynomial.c_str(), matches, re)) 
    { 
     for(int i = 0; i < matches.size(); i++) 
     { 
      string match(matches[i].first, matches[i].second); 
      cout << "\tmatches[" << i << "] = " << match << endl; 
     } 
    } 

    system("PAUSE"); 
    return 0; 
} 

Répondre

7

Vous utilisez la mauvaise chose - regex_match vise à vérifier si un (simple) correspond à l'ensemble regex d'une séquence de caractères. En tant que tel, vous devez soit spécifier une regex qui correspond à l'ensemble de l'entrée, ou utiliser autre chose. Pour votre situation, il probablement a le plus de sens pour modifier l'expression régulière comme vous l'avez déjà fait (le regrouper et ajouter une étoile Kleene). Si vous voulez parcourir les termes individuels du polynôme, vous voudrez probablement utiliser quelque chose comme regex_token_iterator. Edit: Bien sûr, puisque vous l'intégrez en C++, vous devez également doubler toutes les barres obliques inverses. En regardant cela, je suis aussi un petit confus au sujet de l'expression rationnelle que vous utilisez - il ne me semble pas que cela devrait vraiment fonctionner correctement. Juste par exemple, il semble exiger un "+", "-" ou "^" au début d'un terme, mais le premier terme n'aura normalement pas cela. Je suis également un peu incertain pourquoi il y aurait un "^" au début d'un terme. Puisque l'exposant est normalement omis quand il est nul, il est probablement préférable de lui permettre d'être omis. En tenant compte de cela, j'obtiens quelque chose comme: "[- +]? (\ D *) x (\^([0-9]) *)".

intégration que dans un code, nous pouvons obtenir quelque chose comme ceci:

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

int main() { 

    std::string poly = "4x^2+3x^1+2x"; 

    std::tr1::regex term("[-+]?(\\d*)x(\\^[0-9])*"); 

    std::copy(std::tr1::sregex_token_iterator(poly.begin(), poly.end(), term), 
     std::tr1::sregex_token_iterator(), 
     std::ostream_iterator<std::string>(std::cout, "\n")); 
    return 0; 
} 

Au moins pour moi, qui imprime chaque terme individuellement:

4x^2
+ 3x^1
+ 2x

Notez que pour l'instant, je viens d'imprimer chaque terme complet, et modifié votre entrée pour montrer la capacité de reconnaître un terme qui ne comprend pas pouvoir (explicitement, de toute façon).

Edit: pour recueillir les résultats dans un vecteur au lieu de les envoyer à std::cout, vous feriez quelque chose comme ceci:

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

int main() { 
    std::string poly = "4x^2+3x^1+2x"; 

    std::tr1::regex term("[-+]?(\\d*)x(\\^[0-9])*"); 
    std::vector<std::string> terms; 

    std::copy(std::tr1::sregex_token_iterator(poly.begin(), poly.end(), term), 
     std::tr1::sregex_token_iterator(), 
     std::back_inserter(terms)); 

    // Now terms[0] is the first term, terms[1] the second, and so on. 

    return 0; 
} 
+0

J'ai essayé de modifier l'expression régulière, mais il n'a pas travaillé . Cela va correspondre, mais la seule information dans le tableau "matches" est la substance de la dernière sous-expression.Par exemple, si je saisis "4x^2 + 3x^1", ma sortie lit: correspond à [0] = 4x^2 + 3x^1 correspond à [1] = + 3x^1 correspond à [2] = + correspond à [3 ] = 3 correspondances [4] = 1 J'obtiens seulement le dernier terme du polynôme; Je dois être capable d'analyser le tout. –

+0

@Zeebo: peut-être que la version que j'ai éditée dans la réponse sera utile. –

+0

Désolé, j'aurais dû être plus clair. J'ai seulement besoin des coefficients et des exposants. J'essaie d'écrire un programme pour effectuer une division synthétique, donc tout ce que j'ai besoin de savoir sont les coefficients (et s'ils sont positifs ou négatifs), combien de termes il y a, et les exposants (parce que 0x^n doit être inséré si un terme manque, par exemple 4x^4 + 7x^2 doit être 4x^2 + 0x^3 + 7x^2.) –