Une calculatrice "en ligne"

Présentation

Images

CalculatriceCalculatriceCalculatrice

Description

Vous en avez marre de ces sources de calculette qui se contentent de vous offrir des boutons ?
Je comprends.
Cependant, il faut avouer que la réalisation d'une calculatrice capable de transformer le string :
(sqr(e(ln((1+3)*(1/(2^2))))))^2
en calcul n'est pas facile (pour les plus courageux, ca vaut 1 :-))!

Il faut bien penser que les maths ne nous simplifient pas le travail : priorité des opérations, parenthèses (le code 2(2+1) = 2*(2+1) n'est pas forcément évident !)...

Cette calculette semble bien s'en tirer...cependant, j'ai commencé à la programmer il y a 48h, il est donc possible que certains bugs se soient dissimulés.

Le code est extrêmement commenté...il n'utilise aucune API, aucune fonction avancée..le calcul est entièrement géré par le module appelé "Théorie". (211 lignes de code // 84 lignes de commentaires)
Le but était d'obtenir un code très souple et portable. On aurait certes pu utiliser les expressions régulières, ou un composant tout fait, mais dans ce cas là on perdait toute la portabilité de l'ensemble. Le fait d'avoir tout programmé from scratches permettrait ainsi d'exporter le code en n'importe quel langage en moins d'une demie heure, voire même de l'implanter sur un microprocesseur et de lancer sa propre calculette !

Le module "Graphique", quant à lui, "colorie" le code : il met en exposant les puissances, met le contenu des parenthèses en couleur...(utilisation du contrôle RichTextBox 6.0)(41 lignes de code // 8 lignes de commentaires)

Et la Form ne contient que 30 lignes...

La calculette gère les opérations standards : + - * / % (modulo), et ! (factorielle),ainsi que e (exponentielle), ln (logarithme népérien),tan et atn, avec gestion des priorités! C'est à dire que :
1 + 2/2 = 2
...ce qui pour l'ordinateur était loin d'être clair !

Il y a aussi un outil somme, qui s'utilise de la façon suivante :
somme([Nom_Variable]=[départ],[Arrivee],[Calcul])

Cette somme est incorporable dans n'importe quel calcul, et vous pouvez même effectuer des sommes à l'intérieur de sommes à l'intérieur de sommes à l'intérieur de sommes...bref!
Par exemple, le code suivant renvoie une approximation de PI en utilisant la méthode du développement limité d'arctangente :
4*somme(k=0,5000,(-1)^k*(1/(2*k+1))).

Plus d'informations

Si vous ne comprenez pas tout, lancez un calcul, et regardez la fenêtre exécution : elle affiche en temps réel les calculs effectués.

Par exemple :

Initialisation du calcul (sqr(e(ln((1+3)*(1/(2^2))))))^2
-------------------------------------------------------
     Math_It va effectuer le calcul (sqr(e(ln((1+3)*(1/(2^2))))))^2
          Math_It va effectuer le calcul sqr(e(ln((1+3)*(1/(2^2)))))
               Math_It va effectuer le calcul (e(ln((1+3)*(1/(2^2)))))
                    Math_It va effectuer le calcul (ln((1+3)*(1/(2^2))))
                         Math_It va effectuer le calcul ((1+3)*(1/(2^2)))
                              Math_It va effectuer le calcul 1+3
                                   Math_It va effectuer le calcul 3
3 a renvoyé 3
1+3 a renvoyé 4
                                        Math_It va effectuer le calcul 1/(2^2)
                                             Math_It va effectuer le calcul 2^2
                                                  Math_It va effectuer le calcul 2
2 a renvoyé 2
2^2 a renvoyé 4
1/(2^2) a renvoyé 0,25
(1+3)*(1/(2^2)) a renvoyé 1
ln((1+3)*(1/(2^2))) a renvoyé 0
e(ln((1+3)*(1/(2^2)))) a renvoyé 1
sqr(e(ln((1+3)*(1/(2^2))))) a renvoyé 1
                                                       Math_It va effectuer le calcul 2
2 a renvoyé 2
(sqr(e(ln((1+3)*(1/(2^2))))))^2 a renvoyé 1

Comme vous le voyez, le calcul se décompose sous plusieurs formes très simples...(ce qui est, rappelons le, le but de la récursivité !)

De plus, le code est extrêmement souple : si quelqu'un voulait par exemple créer un grapheur, il n'y aurait pas de grosses difficultés.
De même, si quelqu'un souhaitait le passer dans un autre langage, il lui suffirait de traduire le module théorie dans le bon langage...Comme ce module utilise des fonctions communes à tous les langages, il n'y a aucun problème.
Quant à la rapidité, c'est acceptable : pour un DL de 5000 termes, le temps d'exécution est très inférieur à 2 secondes.

A propos du débordement

Les calculs se font avec des variables Double...ce qui laisse assez de marges pour les calculs.

Téléchargement

Ce fichier n'est disponible que pour Windows, car il a été écrit en Visual Basic.

Fichier ZIP (EXE + Sources)

Fichier EXE

Code source

Feuille

Code source : Calculette.frm
  • Langage : vb
  • ΔT : 0.019s
  • Taille :2569 caractères
'2008
'neamar@neamar.fr

'A voir :
'Problème de commutativité de la soustraction : sqr(2) - 1 - ,4142 = PB....
'quand on marque 2e2, rajouter un * : 2*e2
'EN COURS Gestion plus poussée des erreurs
'CORRIGE ! Priorité de * et / par rapport à + et -
' CORRIGE ! 2^2^3 =>mauvais ordre
'EN COURS Ajout des fonctions
'Priorité du Modulo ?
'FINI Autoriser les très grands nombres && les nombres à virgules
'Autoriser les nombres décimaux en input
Option Explicit




Private Sub Calcul_Change()
'Rafraichir les parenthèses
If Colorier.Value Then DrawCalcul Calcul
End Sub


Private Sub Calcul_KeyPress(KeyAscii As Integer)
'Si on presse ², remplacer automatiquement par ^2
If KeyAscii = 178 Then KeyAscii = 0: Calcul.SelText = "^2"

'Ne pas autoriser les sauts de ligne, les considérer comme une validation du calcul
If KeyAscii = 13 Then
    KeyAscii = 0    'Annule l'appui sur la touche
    Lancer_Click
End If
End Sub

Private Sub Colorier_Click()
'Quand on décoche le bouton, remettre le texte à 0
'Si on le coche, on met le texte à 0..ce qui lance automatiquement la colorisation
Calcul.TextRTF = Calcul.Text
End Sub

Private Sub Form_Load()
    'Calcul par défaut :
    Calcul.Text = "(sqr(e(ln((1+3)*(1/(2^2))))))^2"
    Information(2).Caption = "Fonctions supportées :" & vbCrLf & "e | ln | sqr | + | - | * | / | % | ! |"
End Sub

Private Sub Form_Resize()
    On Error Resume Next
    Resultat.Height = Me.Height / 15 - Resultat.Top - 50
    Resultat.Width = Me.Width / 15 - Resultat.Left - 20
    Calcul.Width = Me.Width / 15 - Calcul.Left - 20
    Lancer.Left = Me.Width / 15 - Lancer.Width - 40
    Colorier.Left = Me.Width / 15 - Colorier.Width - 40
End Sub


Private Sub Lancer_Click()
Dim Resultat_Calcul As Double
'Ne pas afficher de messages
Information(1).Caption = vbNullString

'Enlever les sauts de ligne
Calcul.Text = Replace(Replace(Calcul.Text, vbCrLf, ""), ")(", ")*(")
Debug.Print vbCrLf & vbCrLf & "Initialisation du calcul " & Calcul.Text
Debug.Print "-------------------------------------------------------"

'Effectuer le calcul
Pile_Appel = 0: Erreur = vbNullString
Resultat_Calcul = Math_It(Calcul.Text)
Information(1).Caption = Erreur

'Et l'afficher
Resultat.Text = Calcul.Text & IIf(Erreur = vbNullString, "       Calculs effectués en " & Pile_Appel & " sous parties." & vbCrLf & Resultat_Calcul, vbCrLf & Erreur) & vbCrLf & vbCrLf & vbCrLf & vbCrLf & Replace(Resultat.Text, vbCrLf & vbCrLf, vbCrLf)

'Puis colorier le résultat
DrawCalcul Resultat

End Sub


 

Modules

Module Théorie

Code source : Theorie.bas
  • Langage : vb
  • ΔT : 0.111s
  • Taille :17137 caractères
Option Explicit

Public Pile_Appel As Long
Public Erreur As String

Private Dont_Use_Debugger As Boolean

Private Function Calculer(Operation As String, PremierParametre As Double, SecondParametre As Double) As Double
On Error GoTo Err_handler
'Prend en paramètre une opération et deux nombres, et calcule...logique, non ?
Select Case Operation
Case "+"
    Calculer = PremierParametre + SecondParametre
Case "-"
    Calculer = PremierParametre - SecondParametre
Case "*"
    Calculer = PremierParametre * SecondParametre
Case "/"
    Calculer = PremierParametre / SecondParametre
Case "%" 'Modulo : reste de la division euclidienne : 5 % 2 = 1
    Calculer = PremierParametre Mod SecondParametre
Case "^" 'Puissance 4^2 = 4² = 16
    Calculer = PremierParametre ^ SecondParametre
End Select
Exit Function
Err_handler:
    Erreur = Err.Description
    Calculer = 0
End Function

Private Function Factorielle(n As Long)
    'Renvoie la factorielle de n de facon récursive
    'Tire parti du fait que n! = n * (n+1)!

    'La factorielle n'est définie que sur N
    If n < 0 Then
        Erreur = "Impossible de calculer une factorielle négative !"
        Factorielle = 0
        Exit Function
    End If

    'Pour calculer la factorielle, on utilise la définition originale : seulement sur des entiers ! On va pas non plus se taper des intégrales de e !
    If n = 0 Then
        Factorielle = 1 'Par conventiuon, 0! = 1
    Else
        Factorielle = n * Factorielle(n - 1)    'Encore un peu de récursivité
    End If
End Function

Public Function Math_It(Expression As String) As Double
    'Cette fonction transforme un string passé en paramètre en nombre réel, c'est bien entendu la plus importante du programme !
    'Variables pour le calcul théorique :
    Dim Somme As Double, Dernier_Nombre As Double, Nombre_Actuel As Double, Caractere_Actuel As String, Chiffre_Actuel As Double, AjouterApresVirgule As Boolean, NbDecimales As Long
    'Somme => Contient la somme actuelle. C'est cette variable qui sera renvoyée à la fin.
    'Par définition, les opérations standards ont besoin de deux nombres : le nombre à gauche, et celui à droite.
    'Dernier_Nombre correspond au nombre de gauche
    'Nombre_Actuel correspond au nombre de droite, il change en quasi-permanence
    'Caractere_Actuel correspond au caractère en cours de traitement. (voir boucle for plus bas)
    'Chiffre_Actuel correspond au chiffre en cours de traitement, soit VAL(Caractere_Actuel) SI caractere_Actuel est un nombre.
    'AjouterApresVirgule : si le nombre en cours de traitement (Nombre_Actuel) n'est pas un entier, on met cette booléenne à true.
    'NbDecimales : le nombre de décimales du nombre...


    'Variables utilisées en pratique pour réussir la théorie ^^
    Dim Taille As Long, i As Long, Derniere_Operation As String, Fin_Bloc_Instruction As Long


    'Augmenter de 1 la taille de la pile pour pouvoir afficher le nombre de  sous calculs effectués
    Pile_Appel = Pile_Appel + 1
    'Afficher le calcul dans le volet execution
    If Not (Dont_Use_Debugger) Then Debug.Print Space$(5 * Pile_Appel) & "Math_It va effectuer le calcul " & Expression


    'Vérifier que le nombre de parenthèses ouvrantes = nombres de parenthèses fermantes
    If Not VerifierIntegriteReferentielle(Expression) Then
        'Si probleme, on sort de la fonction...et on renvoie 0
        Math_It = 0
        Exit Function
    End If

    'Si le calcul est de la forme "(.......)", on peut supprimer les parenthèses qui entourent
    While Left$(Expression, 1) = "(" And TrouverParentheseFermante(Mid$(Expression, 2)) = Len(Expression) - 2
        Expression = Mid$(Expression, 2, Len(Expression) - 2)
    Wend    'On répete tant qu'on en a la possibilité

    'Initialiser les variables : on va faire semblant que le calcul commence par 0+[Expression].
    'On met donc Somme à 0, et Derniere_Operation à +
    Somme = 0: Nombre_Actuel = 0: Chiffre_Actuel = 0: Dernier_Nombre = 0: Derniere_Operation = "+": AjouterApresVirgule = False

    'On enregistre la taille du string pour accélérer le traitement
    Taille = Len(Expression)
    'On va effectuer une boucle : pour chaque caractère, on réflechira comment le traiter
    For i = 1 To Taille
        Caractere_Actuel = Mid$(Expression, i, 1)
        If IsNumeric(Caractere_Actuel) Then
            'Si le nombre est un nombre, l'ajouter au nombre en cours de traitement
            Nombre_Actuel = Concatener_Nombre(Nombre_Actuel, Caractere_Actuel)
            If AjouterApresVirgule Then NbDecimales = NbDecimales + 1
        Else
            'Si le caractere n'est pas un nombre, on va devoir faire un calcul...
            'Première chose à faire : mettre le nombre sous forme décimale si besoin est
            If AjouterApresVirgule Then
                AjouterApresVirgule = False
                Nombre_Actuel = Nombre_Actuel / (10 ^ NbDecimales)
            End If
            'Si le caractère actuel n'est pas un nombre, ca complique le problème !
            If Caractere_Actuel = "(" And i <> 1 Then
                'Si on utilise une fonction directe (2(2+1), sous entendu 2*(2+1), il faut faire aparaitre le *
                        If i <> 1 Then
                            If IsNumeric(Mid$(Expression, i - 1, 1)) Then
                                Somme = Calculer(Derniere_Operation, Somme, Nombre_Actuel)
                                Derniere_Operation = "*"
                            End If
                        End If
            End If


            'Effectuer la dernière opération si on est en présence d'une opération standard
            If Caractere_Actuel = "+" Or Caractere_Actuel = "-" Or Caractere_Actuel = "*" Or Caractere_Actuel = "/" Or Caractere_Actuel = "%" Or Caractere_Actuel = "^" Then
                'On effectue la dernière opération que l'on devait faire
                Somme = Calculer(Derniere_Operation, Somme, Nombre_Actuel)
                'L'opération est effectuée, vider la variable NombreActuel, stocker la prochiane opération
                Nombre_Actuel = 0
                'Et on stocke l'opération pour la prochaine fois
                Derniere_Operation = Caractere_Actuel 'A ce moment précis, dernièreopération=prochaine operation....
                If Caractere_Actuel = "^" Then
                    'Si on a puissance, l'opération a priorité sur tout le reste ! On calcule l'exposant, et on applique direct.
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i)
                    Nombre_Actuel = Math_It(Mid$(Expression, i + 1, Fin_Bloc_Instruction))
                    i = i + Fin_Bloc_Instruction
                End If

                If Caractere_Actuel = "+" Or Caractere_Actuel = "-" Then
                    'On doit respecter la priorité des opéarations *,/ et ^par rapport à + et -
                    'Donc on subdivise le travail...+ étant commutatif, ce n'est pas un problème.
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i)
                    Nombre_Actuel = Math_It(Mid$(Expression, i + 1, Fin_Bloc_Instruction))
                    i = i + Fin_Bloc_Instruction
                    'Exit For
                End If
            Else
                'Le caractère pour indiquer un nombre décimal est au choix . ou ,
                If Caractere_Actuel = "," Or Caractere_Actuel = "." Then AjouterApresVirgule = True
                'Si ce n'est pas + - * /, c'est plus complexe :-)

                '///////////////////////////////////////////////////////////////////////////////////////
                'Fonctions supportées
                '///////////////////////////////////////////////////////////////////////////////////////

                If LCase$(Caractere_Actuel) = "e" Then  'Exponentielle
                    'Cas de l'exponentielle
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i)
                    If Nombre_Actuel = 0 Then Nombre_Actuel = 1
                    'On multiplie par NombreActuel de facon à corriger le cas 2e2 = 2*e2
                    Nombre_Actuel = Nombre_Actuel * Exp(Math_It(Mid$(Expression, i + 1, Fin_Bloc_Instruction)))
                    i = i + Fin_Bloc_Instruction
                End If
                If LCase$(Mid$(Expression, i, 2)) = "ln" Then   'Logarithme népérien
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i + 1)
                    Nombre_Actuel = Log(Math_It(Mid$(Expression, i + 2, Fin_Bloc_Instruction)))
                    i = i + Fin_Bloc_Instruction + 1
                End If
                If LCase$(Mid$(Expression, i, 3)) = "sqr" Then  'Racine carrée
                    'Pour rappel, SQR(x) = x^(1/2)
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i + 2)
                    Nombre_Actuel = Sqr(Math_It(Mid$(Expression, i + 3, Fin_Bloc_Instruction)))
                    i = i + Fin_Bloc_Instruction + 2
                End If
                If LCase$(Mid$(Expression, i, 5)) = "somme" Then  'Faire une somme
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i + 4)
                    Nombre_Actuel = LancerSomme(Mid$(Expression, i + 6, Fin_Bloc_Instruction - 2))
                    i = i + Fin_Bloc_Instruction + 4
                End If
                If LCase$(Mid$(Expression, i, 3)) = "atn" Then  'Racine carrée
                    'Pour rappel, SQR(x) = x^(1/2)
                    Fin_Bloc_Instruction = TrouverFinBLoc(Expression, i + 2)
                    Nombre_Actuel = Atn(Math_It(Mid$(Expression, i + 3, Fin_Bloc_Instruction)))
                    i = i + Fin_Bloc_Instruction + 2
                End If
                If Caractere_Actuel = "!" Then Nombre_Actuel = Factorielle(Int(Nombre_Actuel)) 'Factorielle


                '///////////////////////////////////////////////////////////////////////////////////////
                'Cas des parenthèses
                '///////////////////////////////////////////////////////////////////////////////////////

                If Caractere_Actuel = "(" Then
                    'Voilà le cas interessant du problème : si on a  des parenthèses...on fait appel à la récursivité.
                    'D'abord, il faut trouver la parenthèse correspondante, et l'envoyer à math_It (oui oui, la fonction dans laquelle on est !)
                    'ainsi, pour le calcul suivant : 2*(1+3) on va d'abord calculer (1+3) et ensuite * par 2
                    Fin_Bloc_Instruction = TrouverParentheseFermante(Mid$(Expression, i + 1))
                    Nombre_Actuel = Math_It(Mid$(Expression, i + 1, Fin_Bloc_Instruction))
                    i = i + Fin_Bloc_Instruction
                End If

            End If

        End If
    Next

    'Ca y est c'est terminé !
    'Ou presque...car il ne faut pas oublier qu'il reste le dernier calcul à effectuer (on effectue tous les calculs en retard...)
    'D'abord, calculer le prochain nombre.
    If AjouterApresVirgule Then
        AjouterApresVirgule = False
        Nombre_Actuel = Nombre_Actuel / (10 ^ NbDecimales)
    End If
    'Ca y est, c'est terminé ! On effectue la dernière opération avec les derniers nombres, et on renvoie.
    Somme = Calculer(Derniere_Operation, Somme, Nombre_Actuel)
    If Not (Dont_Use_Debugger) Then Debug.Print Expression & " a renvoyé " & Somme
    Math_It = Somme
End Function

Private Function LancerSomme(Expression As String) As Double
    Dim i As Long, Start As Long, Fin As Long, Taille As Long, Dernier_i As Long, Calcul As String, Calcul_Temporaire As String, Somme As Double
    Dim Variable As String
    'On arrête l'affichage du debugger temporairement pour ne pas surcharger la fenetre
    Dont_Use_Debugger = True


    Taille = Len(Expression)
    'D'abord, trouver les paramètres

    'Le nom de la variable
    For i = 1 To Taille
        If Mid$(Expression, i, 1) = "=" Then Exit For
    Next
    If i = Taille Then GoTo Somme_incorrecte
    Dernier_i = i + 1
    Variable = Left$(Expression, i - 1)

    'Sa valeur de départ
    For i = Dernier_i To Taille
        If Mid$(Expression, i, 1) = "," Then Exit For
    Next
    If i = Taille Then GoTo Somme_incorrecte
    Start = Int(Math_It(Mid$(Expression, Dernier_i, i - Dernier_i)))
    Dernier_i = i + 1

    'Et sa valeur d'arrivée
    For i = Dernier_i To Taille
        If Mid$(Expression, i, 1) = "," Then Exit For
    Next
    If i = Taille Then GoTo Somme_incorrecte
    Fin = Int(Math_It(Mid$(Expression, Dernier_i, i - Dernier_i)))
    Dernier_i = i + 1

    'Et enfin, le calcul qui devra être effectué !
    Calcul = Mid$(Expression, Dernier_i)

    Debug.Print "La somme " & Calcul; " va être effectué de " & Start & " à " & Fin & " (variable : " & Variable & ")"

    'Lancer le calcul
    Somme = 0
    For i = Start To Fin
        'D'abord, remplacer la variable par sa valeur
        Calcul_Temporaire = Replace(Calcul, Variable, i)
        'Debug.Print Calcul_Temporaire, Math_It(Calcul_Temporaire)
        Somme = Somme + Math_It(Calcul_Temporaire)
    Next

    LancerSomme = Somme

    'On arrête l'affichage du debugger temporairement pour ne pas surcharger la fenetre
    Dont_Use_Debugger = False
    Exit Function


Somme_incorrecte:
    Erreur = "La somme n'est pas correcte !"
    LancerSomme = 0
End Function
Private Function Concatener_Nombre(Nombre As Double, Chiffre_A_Ajouter As String) As Double
    'Cette fonction recoit en paramètre un nombre et un string, elle renvoie le nombre avec le string ajouté.
    'Par exemple, elle prend en paramètre 125,"7" et renvoie 1257
    'NbChiffres = Int(Log(Nombre) / 2.30258509299405) 'Calcule le Log en base 10 du nombre, C.a.d son nombre de décimales
    Concatener_Nombre = 10 * Nombre + Val(Chiffre_A_Ajouter)
End Function

Public Function TrouverFinBLoc(Expression As String, i As Long)
'i est l'endroit ou commencer la recherche
'TrouverFinBLoc prend en paramètre une expression et renvoie la fin du bloc commmencant à l'emplacement i
'| => valeur de i
'Par  exemple, pour 1+ | (2+5) *2, le bloc se termine après )
'Ou encore, pour 2^|25+2, le bloc prend en compte 25 et rien d'autre
Dim i2 As Long, Fin_Bloc_Instruction As Long
If Mid$(Expression, i + 1, 1) = "(" Then
    'Cas x^(2*2)
    Fin_Bloc_Instruction = TrouverParentheseFermante(Mid$(Expression, i + 2)) + 2
    'Ce calcul n'est pas complètement optimisé
    'Par exemple, pour (3+5), le programme effectuera d'abord 3+5 PUIS (3+5), d'ou encombrement inutile de la pile d'appel
Else
    'C'est un simple nombre..on trouve les chiffres, et on renvoie les nombres
    i2 = i + 1
    While (IsNumeric(Mid$(Expression, i2, 1)) Or Mid$(Expression, i2, 1) = "^" Or (Mid$(Expression, i2, 1) = "-" And i2 = i + 1))
        i2 = i2 + 1
    Wend
    Fin_Bloc_Instruction = i2 - i - 1
End If

'C'est tout...
TrouverFinBLoc = Fin_Bloc_Instruction
End Function

Public Function TrouverParentheseFermante(Chaine) As Long
'Trouver la parenthèse fermante associée à une certaine parenthèse
'InStr(i + 1, Chaine, ")") - i - 1)) ne fonctionne pas si l'on a imbrication de parenthèes, e.g (1+5(1+3)+2)
Dim i As Long, Parentheses_Rencontrees As Long, Taille As Long, Caractere_Actuel As String

Parentheses_Rencontrees = 1
Taille = Len(Chaine)
For i = 1 To Taille
    Caractere_Actuel = Mid$(Chaine, i, 1)
    If Caractere_Actuel = "(" Then Parentheses_Rencontrees = Parentheses_Rencontrees + 1    'A chaque fois qu'on rencontre une (, on dit qu'il faudra une ) de plus avant de sortir
    If Caractere_Actuel = ")" Then Parentheses_Rencontrees = Parentheses_Rencontrees - 1
    If Parentheses_Rencontrees = 0 Then Exit For
Next
'Quand on sort, c'est qu'on a la parenthèse...ou qu'elle n'existe pas !
TrouverParentheseFermante = i - 1
End Function

Private Function VerifierIntegriteReferentielle(Expression_De_Test As String) As Boolean
'Cette fonction au nom pompeux vérifie que le nombre de parenthèses "(" est égale au nombre de ")". Logique, non ?
'Si il y a un pb, elle remplit la variable globale Erreur et renvoie False

Dim Curseur As Long, CompteurOuvrantes As Long, CompteurFermantes As Long
    Curseur = InStr(1, Expression_De_Test, "(")
    Do While Curseur
        CompteurOuvrantes = CompteurOuvrantes + 1
        Curseur = InStr(Curseur + 1, Expression_De_Test, "(")
    Loop

    Curseur = InStr(1, Expression_De_Test, ")")
    Do While Curseur
        CompteurFermantes = CompteurFermantes + 1
        Curseur = InStr(Curseur + 1, Expression_De_Test, ")")
    Loop

    If CompteurOuvrantes <> CompteurFermantes Then
        Erreur = "ERREUR : " & CompteurOuvrantes & " '(' trouvés, et " & CompteurFermantes & " ')'. [sous partie : " & Expression_De_Test & "]"
        VerifierIntegriteReferentielle = False
    Else
        VerifierIntegriteReferentielle = True
    End If
End Function


 

Module Graphique

Code source : Graphique.bas
  • Langage : vb
  • ΔT : 0.015s
  • Taille :2113 caractères
Option Explicit

Public Sub DrawCalcul(RTB As RichTextBox)
    'Colorie le texte à l'intérieur d'un RichTextBox fourni en paramètre.

    Dim Texte As String, Caractere_Actuel As String * 1
    Dim Taille As Long, i As Long, Fin_BlocInstructions As Long

    Dim Couleurs(10) As Long, Indentation_Couleur As Long
    'Créer un tableau avec les couleurs à utiliser
    Indentation_Couleur = 0
    Couleurs(1) = RGB(256, 0, 0)
    Couleurs(2) = RGB(0, 256, 0)
    Couleurs(3) = RGB(0, 0, 256)
    Couleurs(4) = RGB(256, 128, 0)
    Couleurs(5) = RGB(256, 0, 256)
    Couleurs(6) = RGB(0, 155, 155)

    'Sauvegarder la position intiale du curseur
    Dim SvgSelStart As Long
    SvgSelStart = RTB.SelStart

    'Remettre la mise en forme à 0
    Texte = RTB.Text
    Taille = Len(Texte)
    RTB.SelStart = 1
    RTB.SelLength = Taille
    RTB.SelColor = vbBlack
    RTB.SelCharOffset = 0
    RTB.SelFontSize = 8

    'Boucler sur tous les caractères
    For i = 1 To Taille
        Caractere_Actuel = Mid$(Texte, i, 1)

        'Si parenthèses : trouver la parenthèse fermante associée et colorier
        If Caractere_Actuel = "(" Then
            'Trouver la prochaine parenthèse et colorier le tout
            Fin_BlocInstructions = TrouverParentheseFermante(Mid$(Texte, i + 1))
            Indentation_Couleur = ((Indentation_Couleur + 1) Mod 6)
            RTB.SelStart = i
            RTB.SelLength = Fin_BlocInstructions
            RTB.SelFontSize = RTB.SelFontSize / (5 / 6)
            RTB.SelColor = Couleurs(Indentation_Couleur + 1)
        End If

        'Si on a des puissances, on met en hauteur pour avoir une jolie visualisation graphique du concept
        If Caractere_Actuel = "^" Then
            Fin_BlocInstructions = TrouverFinBLoc(Texte, i)
            RTB.SelStart = i
            RTB.SelLength = Fin_BlocInstructions
            RTB.SelCharOffset = RTB.SelCharOffset + 60
            RTB.SelFontSize = RTB.SelFontSize * 0.75    'Et en plus, on diminue la taille
        End If
    Next
    RTB.SelStart = SvgSelStart
End Sub


 
Auteur
Neamar
Date
Mai 2008
But
La récursivité
Langage
Visual Basic
Menu
Index des ressources

Chargement du sommaire...