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

API standards et tierces Java Discussion :

Parsing d'expressions arithmétiques


Sujet :

API standards et tierces Java

  1. #1
    Membre éclairé
    Inscrit en
    Septembre 2005
    Messages
    747
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 747
    Par défaut Parsing d'expressions arithmétiques
    Bonjour,

    j'essaye de faire un exo mais je ne sais pas très bien comment m'y prendre.
    Si quelqu'un pouvait m'aider ?

    Merci

    Voici l'énoncé :
    Écrire une classe ExprParser avec une méthode Expr parse(Scanner sc) qui construit une expression arithmétique de type Expr à partir de ce qu'elle lit sur le scanner passé en argument.
    On suppose pour cela que l'expression lue par le scanner est en notation préfixe, c'est-à-dire qu'on exprime l'opérateur, puis ses deux opérandes (on se limite au cas classique des opérations binaires +, -, / et *).
    Par exemple, l'expression préfixe :

    + - 7 3 / 5 * + 4 5 - 4 2


    représente en notation infixe l'expression

    (7 - 3) + 5 / ((4 + 5) * (4 - 2))


    Pour l'analyse, on pourra supposer que tous les opérateurs débutent par des caractères différents (on peut faire un "switch").
    Dans le cas où l'expression analysée serait incorrecte, on lèvera une exception de la classe ExprParseException qu'il faudra définir. Faite en sorte d'obliger le programmeur à récuperer cette exception. L'exception devra représenter le plus fidèlement possible le problème rencontré.

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    429
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 429
    Par défaut
    Bonjour,

    Il serait utile de connaître le type "Expr" (EDIT : ) pour savoir ce que tu cherches à obtenir.

    Cordialement,

    Nicolas

  3. #3
    Membre éclairé
    Inscrit en
    Septembre 2005
    Messages
    747
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 747
    Par défaut
    Citation Envoyé par Nicolas_75
    Bonjour,

    Il serait utile de connaître le type "Expr" (EDIT : ) pour savoir ce que tu cherches à obtenir.

    Cordialement,

    Nicolas
    Je t'ai mis une archive contenant l'interface Expr et les différentes classes.
    Expr est une interface permettant d'avoir une valeur de type Value (c'est un nombre) ou une expression de type BinOP (ça peut être une addition, soustraction,...)
    Fichiers attachés Fichiers attachés

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    429
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 429
    Par défaut
    Ci-dessous trois classes...

    1. Nouvelle classe "Minus"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Minus extends BinOp{
     
        public Minus(Expr a, Expr b){
    	super(a,b);
        }
     
        public double eval(){
    	return getA().eval()-getB().eval();
        }
    }
    2. Classe ExprParser

    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
    import java.util.Scanner;
     
    public class ExprParser {
     
        public static Expr exprparse(Scanner sc) {
            if (sc.hasNextInt()) {
                return new Value(sc.nextInt());
            } else { // le scanner renvoie un opérateur
                char op = sc.next().charAt(0);
                // on cherche les opérandes de l'opérateur dans la suite du scanner
                Expr premierOperande = exprparse(sc);
                Expr secondOperande = exprparse(sc);
                switch (op) {
                    case '+' : return new Add(premierOperande, secondOperande);
                    case '-' : return new Minus(premierOperande, secondOperande);
                    case '*' : return new Mult(premierOperande, secondOperande);
                    case '/' : return new Div(premierOperande, secondOperande);
                    default : return new Value(0); // ne devrait pas arriver
                }
            }
        }
    }
    3. Classe Main de test

    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
    25
    import java.util.Scanner;
     
    public class Main{
     
        public static String print(Expr e) {
            if (e instanceof Value) {
                return ""+e.eval();
            } else if (e instanceof Add) {
                return "("+print(((BinOp) e).getA())+" + "+print(((BinOp) e).getB())+")";
            } else if (e instanceof Mult) {
                return "("+print(((BinOp) e).getA())+" * "+print(((BinOp) e).getB())+")";
            }         else if (e instanceof Minus) {
                return "("+print(((BinOp) e).getA())+" - "+print(((BinOp) e).getB())+")";
            } else if (e instanceof Div) {
                return "("+print(((BinOp) e).getA())+" / "+print(((BinOp) e).getB())+")";
            } else return "";
        }
     
        public static void main(String [] args){
            Scanner sc = new Scanner("+ - 7 3 / 5 * + 4 5 - 4 2");
            Expr resultat = ExprParser.exprparse(sc);
            System.out.println(print(resultat));
            System.out.println(resultat.eval());
        }
    }
    Ces 3 classes, rajoutées à celles que tu as données ci-dessus, donnent un tout qui compile.
    Le résultat chez moi est :
    ((7.0 - 3.0) + (5.0 / ((4.0 + 5.0) * (4.0 - 2.0))))
    4.277777777777778
    J'ai fait cela vite : le code peut probablement être optimisé et amélioré.
    Il reste entre autres la gestion des exceptions à mettre en place.

    En espérant que cela puisse t'aider,

    Nicolas

  5. #5
    Membre Expert

    Profil pro
    Inscrit en
    Mai 2006
    Messages
    895
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 895
    Par défaut
    Bonjour,
    Personellement j'utiliserais du récurcif, ce qui donnerait à peu près cette algo
    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
    25
    26
    27
    28
    29
    30
    31
     
            Expr parse(Scanner sc)
            {
                return parseRec(sc,new ArrayList());
            }
     
            Expr parseRec(Scanner sc, ArrayList exprList)
            {
                if(sc.hasNextInt())
                {
                    exprList.add(sc.nextInt());
                    return parseRec(sc,exprList);
                }
                if(!scanner.hasNext())
                    if(exprList.length()!=0)
                        throw new Exception("Expression incorrecte");
                    else
                        return exprList.get(0);
                char c = sc.next(Pattern.compile("."));
                switch(c)
                {
                    case '+':
                        Expr expr1 = exprList.get(0);
                        Expr expr2 = exprList.get(1);
                        exprList.remove(expr1);
                        exprList.remove(expr2);
                        exprList.add(new Add(expr1, expr2));
                        return parseRec(sc,  exprList);
                    //... meme principe pour les autres opérateurs
                }
            }
    C'est un peu le principe des grammaires LR(1) que j'ai utilisé avec la grammaire suivante
    Expr -> op Expr Expr
    Expr -> num

Discussions similaires

  1. Algorithme expression arithmétique postfixée
    Par elhou80 dans le forum Turbo Pascal
    Réponses: 11
    Dernier message: 25/05/2007, 01h10
  2. Réponses: 8
    Dernier message: 15/05/2007, 11h02
  3. Réponses: 1
    Dernier message: 03/01/2007, 15h07
  4. Réponses: 1
    Dernier message: 09/12/2006, 10h13
  5. Evaluation d'une expression arithmétique
    Par MysticKhal_0 dans le forum Algorithmes et structures de données
    Réponses: 9
    Dernier message: 10/03/2006, 18h25

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