IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

opération mathématique à partir d'une variable de type string


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    sans emploi
    Inscrit en
    Février 2014
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2014
    Messages : 365
    Par défaut opération mathématique à partir d'une variable de type string
    Bonjour

    J'ai une variable de type "string" composée de chiffres et d'opérateurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string cadre_input_calcul = "1+2-3/4*5";
    Comment faire pour calculer l'opération?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float operation= ??cadre_input_calcul??
    Cordialement

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Il n'existe aucune fonction qui évaluerait le texte dans une chaine de caractère. Il te faut un code qui "lise" la chaine, y détecte les nombres et symboles, et effectue alors les actions nécessaires.

  3. #3
    Membre éclairé
    Homme Profil pro
    sans emploi
    Inscrit en
    Février 2014
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2014
    Messages : 365
    Par défaut
    merci

    pour détecter les nombres
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    #include <stdio.h>
    #include <string>
    #include <sstream>
    #include <typeinfo>		// pour typeid
    #include <ctype.h>      // pour isdigit()
    #include <iostream>		// pour cout
    #include <regex>
     
     
    int main( int argc, char* args[] )
    {
        const std::string string3 = "9,42+308,7-41+36*234,56/546+7.56*769,3";
        std::regex  regex3("([0-9]+[.|,]{0,1}[0-9]*)");  
        std::smatch match3;
        if (regex_search(string3, match3, regex3))
        {
            for (int i=1; i<match3.size(); i++) 
            {
                std::cout << match3[i] << std::endl;
            }
        }
    return 0;
    }
    problème: il ne fait apparaitre que le premier nombre: 9,42

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 768
    Par défaut
    Sur la documentation cplusplus.com std::regex_search, il faut relancer la recherche.
    Et toutes les entêtes C comme stdio.h ont 1 version C++ cstdio (on retire l'extension .h et on préfixe 1 c)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <iostream>
    #include <regex>
     
    #include <cstdlib>
     
     
    int main(int argc, char* args[])
    {
        std::string string3 = "9,42+308,7-41+36*234,56/546+7.56*769,3";
        std::regex  regex3("([0-9]+[.|,]{0,1}[0-9]*)");  
        std::smatch match3;
     
        while( regex_search(string3, match3, regex3) ) {
            for (auto x:match3) { std::cout << x << " "; }
            std::cout << std::endl;
     
            string3 = match3.suffix().str();
        }
     
     
        return EXIT_SUCCESS;
    }

  5. #5
    Membre éclairé
    Homme Profil pro
    sans emploi
    Inscrit en
    Février 2014
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2014
    Messages : 365
    Par défaut
    merci

    je ne vois pas comment récupérer les valeurs sous forme terme_facteur[i]=x[i]

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    A vrai dire, les expressions régulières ne te seront pas d'un très grand secours pour résoudre ton problème. Je m'explique:

    Une expression régulière va parcourir une "chaine de caractères d'origine" à la recherche d'un patron, représenté sous la forme d'une chaine de caractères, qui permettra à l'expression régulière d'extraire une "sous chaine de caractères" de la "chaine d'origne" si le patron recherché est trouvé.

    C'est certes très pratique, mais... cela ne remplit certainement pas l'ensemble de nos besoins, car ceux-ci vont "un cran plus loin" en nécessitant de convertir les chaines de caractères qui représentent des nombres en valeurs numériques.

    Attention, je ne dis absolument pas que l'on ne peut en aucun cas avoir recours aux expressions régulières. Je dis juste que c'est peut être se faire "beaucoup de mal pour rien", car les moyens dont on dispose pour convertir une chaine de caractères en valeur numérique ne nécessitent absolument pas que la chaine convertie ne soit composée que du nombre à convertir.

    De manière générale, pour extraire les valeurs numériques d'une chaine de caractères en C++, tu dois utiliser les fonctions std::sto* (std::stoi et autres pour les entiers, std::stof, std::stod, et std::stold pour les réels).

    Le deuxième paramètre (le premier qui soit optionnel) nous permet de fournir un pointeur sur un entier qui correspondra à la position du premier caractère de la chaine de caractères qui "ne fait clairement pas partie du nombre".


    Par contre, il faudra jouer avec les "sous-chaines de caractères" afin de pouvoir récupérer les différents opérateurs et, au delà, l'expression complète que l'on souhaite évaluer.

    Par contre, il va aussi falloir prendre en compte le fait que la partie décimale d'un nombre en informatique est représentée par le point "." et non par la virgule ","

    Ainsi, si on veut traiter une chaine de caractères (que je vais utiliser tout au long de cette explication) qui prend la forme de " std::string str = "9,42+308,7-41+36*234,56/546+7.56*769,3";, les deux premières choses que nous voudrons faire sont:
    1. effectuer une "copie de travail" de la chaine, afin de ne pas aller modifier la chaine "d'origine"
    2. remplacer toutes les virgules qui apparaissent par des points, histoire que nos fonctions de conversion y "retrouvent leur jeunes".

    La première étape est toute simple, car il nous suffira d'une ligne proche de
    pour avoir une variable nommée copy qui est la copie conforme de la chaine de caractères str.

    La deuxième étape n'est a priori pas beaucoup plus compliquée, car nous disposons d'une fonction d'algorithme nommé std::replace_if capable de le faire pour nous (il faut juste penser à inclure le fichier d'en-tête <algorithm>). Une ligne proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::replace_if(copy.begin(), copy.end(), [](char c){return c==',';},'.');
    devrait faire l'affaire
    Je sais, elle a l'air compliquée comme cela, mais elle en fait, elle est toute simple et parfaitement logique... si tu ne la comprends pas, n'hésite pas à me le dire, je t'expliquerai le tout au besoin

    Bien, maintenant que nous avons la certitude que la chaine de caractères (copy) pourra être traitée correctement avec la fonction std::stof, il est peut être utile de prendre trente secondes pour réfléchir à notre situation actuelle et au résultat que l'on souhaite obtenir...

    Notre situation actuelle est que nous sommes désormais face à une chaine de caractères dont on peut clairement dire qu'il s'agit "d'une expression mathématique" (complexe).

    Notre objectif de départ étant de récupérer les différentes valeurs numériques que cette expression contient, ainsi que ... les opérateurs mathématiques qui séparent ces différentes valeurs (ce sera plus facile, semblet-t-il, pour atteindre l'objectif final ).

    L'objectif final étant de pouvoir évaluer le résultat de cette expression une fois que toutes les opérations auront été effectuées. Accessoirement, s'il y avait moyen de respecter les règles de priorités pour les différents opérateurs, ce serait franchement pas mal

    Tiens, au fait... Je viens d'introduire quelques notions sympa ici, dont la notion d'"opérateurs mathématiques". Comme ces opérateurs seront essentiels au calcul du résultat final, nous serions peut être bien inspirés d'introduire cette notion dans notre "DSL" (acronyme de Domain Specific Language ou, si tu préfères, notre langage spécifique au domaine de notre projet).
    Le plus simple serait sans doute de créer une énumération reprenant les quatre opérations de base et qui serait proche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    enum MathOperator{
        plus,
        minus,
        multiply,
        divide,
        max
    };
    La valeur "max" n'est présente ici que pour une question de facilité, car elle nous permettra par la suite des choses sympa ... ou non

    Et, bien sur, on pourrait fournir une fonction qui fournisse la valeur énumérée correspondant au symbole représenté par le caractère en question:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    constexpr MathOperator mathFromChar(char c){
        switch c{
            case '+' : return plus;
            case '-' : return minus;
            case '*' : return multiply;
            case '/' : return divide;
            default : assert(false && You should never come here");
        }
        return max;
    }
    Cette fonction est déclarée comme étant constexpr uniquement parce que cela permettra au compilateur de faire quelques optimisations supplémentaires

    Maintenant que nous avons une fonction pour extraire un float (je parle bien sur de std::stof) et une autre fonction pour récupérer le type d'opérateur mathématique utilisé dans le cadre de "l'expression mathématique dont on veut calculer le résultat, ben ... YAPUKA ... mettre tout cela en musique

    Pour se faire, nous aurons encore besoin de deux variables particulières:
    • un float, d'abord, pour pouvoir extraire les réels représentés par la chaine de caractères et
    • un size_t ensuite, pour savoir la position du "premier caractère n'ayant pas été utilsé par la fonction.

    le float peut être déclaré au moment où l'on récupère le résultat de std::stof, par contre le size_t devra être déclaré avant (car on doit en prendre l'adresse pour la transmettre à stof...).

    Cela pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    size_t position{0};
    float extracted = std::stof(copy, &position);
    Nous pouvons "assez facilement" utiliser la nouvelle valeur de position pour récupérer l'opérateur mathémathique sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MathOperator oper = mathFromChar(copy[position]);
    Bien sur, nous ne devons donc pas oublier que le premier caractère qui nous intéresse se trouve désormais à position +1, mais il est désormais temps de supprimer "tout ce qui a déjà été traité" de la chaine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    copy = copy.substr(position + 1);
    Nous sommes désormais rendus au point où
    1. nous avons extrait la première valeur numérique de la chaine de caractères
    2. nous avons extrait le premier opérateur mathématique de la chaine de caractères
    3. nous avons supprimé de la chaine de caractères tous les caractères qui ont déjà été utilisés lors des deux extractions sus-citées.

    Ce qu'il faut désormais, c'est "continuer sur cette lancée" afin de parcourir toute la chaine de caractères... Et ca, je vais te laisser faire, autrement, cela n'aurait absolument aucun intérêt

    Dans l'idéal, il faudrait trouver le moyen de stocker toutes les informations obtenues, histoire que l'on puisse les manipuler "à notre aise" ... après avoir parcouru toute la chaine de caractères

    Fais attention au fait qu'il y a peut être une petite astuce à la fin de la chaine de caractères, étant donné qu'elle est censée se cloturer par ... une valeur numérique

    Une fois que nous aurons parcouru l'ensemble de la chaine de caractères, il faudra trouver le moyen de "recréer" l'expression mathématique qu'elle représentait de manière à pouvoir en calculer le résultat final.

    Soit toujours bien attentif au fait que la multiplication et la division ont priorité sur l'addition lorsque tu évalue le résultat final.

    Une fois que tu en sera rendu là, nous pourrons éventuellement améliorer le tout en ajoutant le support d'espaces "surnuméraires" (par exemple avant et après un opérateur mathématique), mais ... à chaque jour suffit sa peine, n'est ce pas?
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 528
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 528
    Par défaut
    Citation Envoyé par binco Voir le message
    Comment faire pour calculer l'opération?
    Peut-être qu'un "parser" d'expression serait utile ?
    En voilà un excellent que j'utilise sur mon projet source sur GitHub

  8. #8
    Membre éclairé
    Homme Profil pro
    sans emploi
    Inscrit en
    Février 2014
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2014
    Messages : 365
    Par défaut
    merci beaucoup ça fonctionne

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 09/09/2011, 16h38
  2. Réponses: 6
    Dernier message: 14/02/2007, 21h08
  3. Des " dans une variable de type String
    Par 4lkaline dans le forum Langage
    Réponses: 6
    Dernier message: 06/11/2006, 14h20
  4. convertir une variable de type String en Number
    Par lilbrother974 dans le forum Flash
    Réponses: 13
    Dernier message: 06/09/2006, 08h28
  5. Ajouter a une variable de type string, un entier
    Par Little-Freud dans le forum SL & STL
    Réponses: 12
    Dernier message: 05/03/2005, 19h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo