Analyseur d'expression algébrique facilement extensible

Soyez le premier à donner votre avis sur cette source.

Vue 6 515 fois - Téléchargée 319 fois

Description

Montre comment créer un analyseur d'expression algébrique facilement en découpant le travail.
Il comprend une fonction travaillant sur les parenthèses et une autre analysant les expressions de base (1+2)

Voici le fonctionnement :
Soit le calcul suivant :
On va rechercher la première parenthèse fermante. Elle se situe à la fin de l'expression : (2+5)
On effectue le calcul et l'on remplace la parenthèse par le résultat : 2+(7*45*(4+56*(2+7))+7)/4
Voici le détail du calcul à chaque "tour" du prog:
2+(7*45*(4+56*9)+7)/4
2+(7*45*(4+504)+7)/4
2+(7*45*508+7)/4
2+(315*508+7)/4
2+(160020+7)/4
2+160027/4
2+40558.25
40558.25

Source / Exemple :


'/-------------------------------------------------\
'|                                                 |
'|  TITRE : Analyseur d'expression arithmétique    |
'|                                                 |
'|  Expression supposrtées :                       |
'|       Opérateurs de base : +,-,*,/,^            |
'|       Parenthèses : ()                          |
'|       Fonctions : SIN,ABS,SQR                   |
'|                                                 |
'|  BUGS connus de l'auteur :                      |
'|     2*-5 donne -5  (*)Corrigé par mr_saturne    |
'|                                                 |
'| Caractéristique du code :                       |
'|              Facilement extensible              |
'\-------------------------------------------------/
 Function evaluer(calc As String)

 Dim fact() As String
 Dim oper() As String
 Dim fpos As Integer
 Dim n As String
 Dim ffin As Integer
 ReDim fact(1) As String
 ReDim oper(1) As String
 Dim test_neg As Integer

 '********************************************
 '**IMPLEMENTATION DES FONCTIONS SPECIFIQUES**
 '********************************************

 'Cosinus
 Do Until InStr(calc, "cos") = 0
 fpos = InStr(calc, "cos")
 n = ""
 If fpos > 0 Then
 For ix = fpos + 3 To Len(calc)
 If IsNumeric(Mid(calc, ix, 1)) Or Mid(calc, ix, 1) = "." Then n = n + Mid(calc, ix, 1) Else Exit For
 Next ix
 calc = Replace(calc, "cos" + LTrim(str(n)), LTrim(str(Cos(n * 3.1415 / 180))))
 End If
 Loop

 'Sinus
 Do Until InStr(calc, "sin") = 0
 fpos = InStr(calc, "sin")
 n = ""
 If fpos > 0 Then
 For ix = fpos + 3 To Len(calc)
 If IsNumeric(Mid(calc, ix, 1)) Or Mid(calc, ix, 1) = "." Then n = n + Mid(calc, ix, 1) Else Exit For
 Next ix
 calc = Replace(calc, "sin" + LTrim(str(n)), LTrim(str(Sin(n * 3.1415 / 180))))
 End If
 Loop

 'Racine carée
 Do Until InStr(calc, "sqr") = 0
 fpos = InStr(calc, "sqr")
 n = ""
 If fpos > 0 Then
 For ix = fpos + 3 To Len(calc)
 If IsNumeric(Mid(calc, ix, 1)) Or Mid(calc, ix, 1) = "." Then n = n + Mid(calc, ix, 1) Else Exit For
 Next ix
 calc = Replace(calc, "sqr" + LTrim(str(n)), LTrim(str(Sqr(n))))
 End If
 Loop

 'Valeure absolue
 Do Until InStr(calc, "abs") = 0
 fpos = InStr(calc, "abs")
 n = ""
 If fpos > 0 Then
 For ix = fpos + 3 To Len(calc)
 If IsNumeric(Mid(calc, ix, 1)) Or Mid(calc, ix, 1) = "." Or Mid(calc, ix, 1) = "-" Then n = n + Mid(calc, ix, 1) Else Exit For
 Next ix
 calc = Replace(calc, "abs" + LTrim(str(n)), LTrim(str(Abs(n))))
 End If
 Loop

 '********************************************
 '**RECHERCHE DES FACTEURS ET DES OPERATEURS**
 '********************************************

 For ix = 1 To Len(calc) ' debut de boucle

 Select Case Mid(calc, ix, 1) ' recherche des operateurs

 Case "^": ' exponenciation
 ReDim Preserve fact(UBound(fact()) + 1) As String ' Ajouter un indice dans les facteurs
 oper(UBound(oper)) = "^" ' Ajouter l'operateur à la liste
 ReDim Preserve oper(UBound(oper()) + 1) As String ' Ajouter un indice dans les opérateurs

 Case "*": ' multiplication
 ReDim Preserve fact(UBound(fact()) + 1) As String
 oper(UBound(oper)) = "*"
 ReDim Preserve oper(UBound(oper()) + 1) As String

 Case "/": ' division
 ReDim Preserve fact(UBound(fact()) + 1) As String
 oper(UBound(oper)) = "/"
 ReDim Preserve oper(UBound(oper()) + 1) As String

 Case "+": ' addition
 ReDim Preserve fact(UBound(fact()) + 1) As String
 oper(UBound(oper)) = "+"
 ReDim Preserve oper(UBound(oper()) + 1) As String

 Case "-": ' soustraction
 ReDim Preserve fact(UBound(fact()) + 1) As String
 oper(UBound(oper)) = "-"
 ReDim Preserve oper(UBound(oper()) + 1) As String

 Case Else: ' autres cas
 fact(UBound(fact)) = fact(UBound(fact)) + Mid(calc, ix, 1) ' ajouter le bout de chaine au dernier indice de fact

 End Select

 Next

'Remplace les chiffres négatifs
rech:
 ix = 1
 test_neg = 0
 While ix < UBound(fact) 'parcours tous les facteurs
 If fact(ix) = "" And oper(ix) = "-" Then 'négatif trouvé
 fact(ix) = (-1) * fact(ix + 1) 'on remplace le vide par le facteur suivant en négatif

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1) 'on décale le tableau des opérateurs
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2) 'on décale le tableau des facteurs
 Next iy

 fact(UBound(fact)) = "" 'on supprime le facteur obsolette

 test_neg = 1
 End If
 ix = ix + 1 'on passe au suivant
 Wend
 If test_neg = 1 Then GoTo rech 'si un négatif a été trouvé on refait un passage

 'Ajout des facteurs et des opérateurs dans les listes pour le deboguage
 List1.Clear
 List2.Clear
 For ix = 1 To UBound(fact)
 List1.AddItem (fact(ix))
 Next ix

 For ix = 1 To UBound(oper)
 List2.AddItem (oper(ix))
 Next ix

 '**************************
 '**CALCUL DE L'EXPRESSION**
 '**************************

 'EXPONENTIELLE
 For ix = 1 To UBound(fact) ' Parcourir tous les facteurs
 If oper(ix) = "^" Then ' Si on trouve oper(ix)="^"
 fact(ix) = LTrim(str(Val(fact(ix)) ^ Val(fact(ix + 1)))) ' Calculer le nouveau facteur

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1) ' > Enlever un operateur et décaller le tableau
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2) ' > Enlever un facteur et décaller le tableau
 Next iy

 fact(UBound(fact)) = "" ' Effacer le facteur obsolette
 End If
 Next ix

 'MULTIPLICATION
 For ix = 1 To UBound(fact)
 If oper(ix) = "*" Then
 fact(ix) = LTrim(str(Val(fact(ix)) * Val(fact(ix + 1))))

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1)
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2)
 Next iy

 fact(UBound(fact)) = ""
 End If
 Next ix

 'DIVISION
 For ix = 1 To UBound(fact)
 If oper(ix) = "/" Then
 fact(ix) = LTrim(str(Val(fact(ix)) / Val(fact(ix + 1))))

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1)
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2)
 Next iy

 fact(UBound(fact)) = ""
 End If
 Next ix

 'ADDITION
 For ix = 1 To UBound(fact)
 If oper(ix) = "+" Then
 fact(ix) = LTrim(str(Val(fact(ix)) + Val(fact(ix + 1))))

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1)
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2)
 Next iy

 fact(UBound(fact)) = ""
 End If
 Next ix

 'SOUSTRACTION
 For ix = 1 To UBound(fact)
 If oper(ix) = "-" Then
 fact(ix) = LTrim(str(Val(fact(ix)) - Val(fact(ix + 1))))

 For iy = ix To UBound(oper) - 1
 oper(iy) = oper(iy + 1)
 Next iy

 For iy = ix To UBound(fact) - 2
 fact(iy + 1) = fact(iy + 2)
 Next iy

 fact(UBound(fact)) = ""
 End If
 Next ix

 For ix = 1 To UBound(fact)
 evaluer = evaluer + fact(ix) + oper(ix) ' Construction de la nouvelle expression.
 Next

End Function

Rem  !!! Veuillez mentionner mon nom si vous comptez l'utiliser dans votre programme !!!

Option Base 1 ' premier indice du tableau = 1

Sub calculer_Click() ' Au clicque sur le bouton
'MsgBox parenthese(calcul.Text) ' pour deboguage
Do Until parenthese(calcul.Text) = "aucune" ' fair j'usqu'à ce que la fonction retourne "aucune"
If parenthese(calcul.Text) = "error" Then MsgBox "ERREUR : parenthèse manquante ou mal placée " + Chr(10) + " le programme a tenté de retrouver l'erreur" + Chr(10) + " veuillez suprimer les parenthèses inutiles et appuyer sur calculer", vbCritical, "!!! ERREUR utilisateur !!!": Exit Sub ' si la fonction retourne une erreur
calcul = Replace(calcul, "(" + parenthese(calcul.Text) + ")", evaluer(parenthese(calcul.Text))) ' Simplifier le calcul au operateur de base (plus de () )
Loop ' fin de boucle
calcul = evaluer(calcul) ' evaluer l'expression simplifiée
End Sub

Function parenthese(calc As String)
Dim pospo, pospf As String
Rem rechecherche de la première parenthèse fermente
pospf = InStr(1, calcul.Text, ")")
If pospf <> 0 Then
pospo = InStrRev(calcul.Text, "(", pospf)
If pospo = 0 Then GoTo err1
parenthese = Mid(calcul.Text, pospo + 1, pospf - pospo - 1)
Else
parenthese = "aucune"
End If
Exit Function
err1:
parenthese = "error"
End Function

Conclusion :


Merci à mr_saturne pour son travail.(Modification de evaluer() )

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_max12
Messages postés
1491
Date d'inscription
dimanche 19 novembre 2000
Statut
Modérateur
Dernière intervention
7 juillet 2014
-
C'est intéressant.
cs_Urgo
Messages postés
780
Date d'inscription
lundi 16 décembre 2002
Statut
Membre
Dernière intervention
16 avril 2009
1 -
"2+40558.25
40558.25"

Erreur quant tu nous tiens... (40560.25)"
krissssss
Messages postés
88
Date d'inscription
jeudi 26 décembre 2002
Statut
Membre
Dernière intervention
2 janvier 2007
-
Pour Urgo :
Merci pour l'erreur ;-)
J'ai pas sû trouver d'où venais ces erreurs.
Si tu penses savoir où elle a lieu, aide moi s'il te plais.
Et ne va pas dormir trops tard, 04:43:48 c'est pas une heure. :-D
Encore merci pour ce commentaire (et probablement les suivants ;-)).

Pour Max12:
Merci pour ton encouragement.
Je vais peut-être le porter en Delphi, qui sait...

En gros, c'est mon prof qui m'a demmandé une calculatrice style Windows.J'ai préféré une plus évoluée :p (Je la lui montre à la rentrée...)

Bon amusement avec cette source.
Et voyez la puissance du diviser pour régner !

Aller, après ce long Auto-commentaire-réponse, je vous dis : "à la prochaine" :-)
shadowmoy
Messages postés
340
Date d'inscription
jeudi 25 juillet 2002
Statut
Membre
Dernière intervention
25 août 2007
-
tu aurais pu utiliser le vbscript sous vb pour faire ca et ca aurait été beaucoup beaucoup plus rapide

ou alors fo gerer une stack et faire des push memoire et des operations de bases direct en memoire c plus rapide et utilisé dans les languages de script ...
cqui789
Messages postés
261
Date d'inscription
jeudi 13 janvier 2005
Statut
Membre
Dernière intervention
18 mai 2009
2 -
pour ton '2*-5 donne -5' bug, ton programme comprend 2*0-5 qui vaut effectivement -5
tu as un probleme similaire avec 'cos-5'
je suggere que tu cree une fonction pour relever la valeur numerique qui suit une fonction ou un operateur et qui considere la possibilite que cette valeur commence par "-"

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.