arthur24
Messages postés17Date d'inscriptionmardi 16 décembre 2003StatutMembreDernière intervention20 août 2015
-
7 déc. 2007 à 09:55
divadav
Messages postés94Date d'inscriptionlundi 13 janvier 2003StatutMembreDernière intervention22 janvier 2009
-
20 déc. 2007 à 18:51
Bonjour à tous,
Voici mon problème. Je travaile sous VS2005 et je tente d'évaluer une
condition booléenne contenue dans une variable de type string.
La variable est simplement déclarée par : dim str as string
A l'issu d'un traitement, le contenu de la variable est du type
"((<valeur_booléenne>)AND(<valeur_booléenne>))" et je cherche à évaluer cette
expression pour obtenir la valeur booléenne de l'ensemble de l'expression.
J'ai pensé résoudre le problème par l'appel de Cbool : cBool(str) mais
j'obtiens le message "La conversion de la chaîne "((True)AND(True))" en type
'Boolean' n'est pas valide."
La fonction Cbool n'accepte pas en paramètre de variable de type string.
L'anomalie est la même avec l'appel directe sous la forme
cbool("((True)AND(True))"). Par contre, l'exécution de cbool((True)AND(True))
retourne bien la valeur True.
La fonction Cbool n'est visiblement pas le bon moyen pour évaluer une chaîne
de caractère contenant une expression booléenne. Mais je ne connais pas
d'autre moyen de résoudre ce problème.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 7 déc. 2007 à 10:47
je joues beaucoup avec ce genre de choses, ces temps-ci...
joues avec ton parenthesage, justement...
remplace les variables par 1 ou 0
et traite ce qui se trouve entre parentheses...
((((a) and (b)) or (c)) and (d))
((( 1 and 0 ) or 1 ) and 1 )
(( 0 or 1 ) and 1 )
( 1 and 1 )
1
si tu structures bien la chose, ca devrait etre maintenable et pas trop long
tu parcoures ta chaine, tu mémorise la pos de ta parenthese ouvrante
si tu tombes sur une autre ( , tu stocke sa position (tu ecrase l'autre)
si tu tombes sur ), tu traites (récursif) l'expression contenue entre les deux parentheses et tu modifie la chaine d'entrée...
ca va te simplifier la chose et tu tombera rapidement sur ton résultat.
arthur24
Messages postés17Date d'inscriptionmardi 16 décembre 2003StatutMembreDernière intervention20 août 2015 18 déc. 2007 à 10:08
Depuis quelques jours je me disais que des outils externes au code (SQL, Excel,...) devait bien permettre d'évaluer des expressions booléennes. Connaissant mieux SQL, j'ai fait quelques recherches sur le sujet et, ce matin, je suis tombé sur cet article :
J'ai trouvé dans la procédure stockée décrite les éléments qui me manquaient pour formater correctement une expression analysable, par exemple, par SQL Server.
Le "AND" devient &, le "OR" devient |, etc.
Le "TRUE" devient 1, le "FALSE" devient 0.
Il suffit de reformater l'expression booléenne de départ pour l'exprimer avec les opérateur du SGBD, constituer une requète du style "SELECT " & MonExpressionBool et d'exécuter le tout comme n'importe quelle requète.
Le SGBD retourne le résultat de l'évaluation, sans soucis de profondeur dans le parenthésage, et quelle qu'en soit la structure.
Bien sur, cette solution n'est pas élégante du point de vue algorithmique. Elle déplaira aux fans de la récursion, mais elle a le mérite d'être simple et immédiatement applicable dans une application adossée à une base de données.
Ces quelques jours auront eu le mérite de me replonger dans les joies des fonctions réccursives, ça faisait longtemps...
pneau
Messages postés258Date d'inscriptionmercredi 21 avril 2004StatutMembreDernière intervention27 octobre 20105 7 déc. 2007 à 10:11
salut,
est ce que ta chaine contient systématique 2 booléens ? et le mot clé And ?
le mieux, à mon avis est de faire une recherche grace aux parenthèses.
en parcourant la chaine de manière séquentiel tu pourras détecter les valeurs des booléens et l'opérateur
sinon, tu peux essayer en faisant des recherches des valeurs "TRUE" et "FALSE" avec instr
@+
Pat
Don't Worry , Be Happy
<hr />lorsque le problème est résolu, pensez Réponse Acceptée
arthur24
Messages postés17Date d'inscriptionmardi 16 décembre 2003StatutMembreDernière intervention20 août 2015 7 déc. 2007 à 10:25
L'expression citée est un exemple simplifié.
Elle est du type : [ ( ] [(<valeur_booléenne>)] [And,Or] [ (<valeur_booléenne>) ] [ ) ] ce qui peut donner par exemple :
((((true) and (false)) or (true)) and (false)).
Le parenthésage est toujours complet, sans omission basée sur la priorité des opérateurs logique.
Mon problème n'est pas de détecter les valeurs booléennes mais d'évaluer l'expression complète pour obtenir une valeur booléenne.
Je cherche donc une fonction dont la déclaration pourrait ressembler à :
Function ExvalueExpressionBooleenne(ByVal Expression As String) As Boolean
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 7 déc. 2007 à 15:10
c'est pas très complexe, tu as l'avantage d'avoir les parentheses bien placées....
l'histoire de 45 minutes de coding, pour avoir un truc fonctionnel...
arthur24
Messages postés17Date d'inscriptionmardi 16 décembre 2003StatutMembreDernière intervention20 août 2015 17 déc. 2007 à 16:54
Chose promise, chose due, voici une fonction qui évalue les expressions booléennes au format suivant : [ ( ] [(<valeur_booléenne>)] [And,Or] [
(<valeur_booléenne>) ] [ ) ] ce qui peut donner par exemple : ((((1) and (0)) or (1)) and (0)).
Au cours des tests, je suis tombé sur un cas particulier que je ne traite pas encore correctement, mais que je ne devrais pas rencontrer dans l'appli sur laquelle je travaille : une expression du type ((1)AND((0)or(1))), càd une expression dont le niveau de parenthésage le plus profond n'est pas le premier exprimé. Dans ce type de cas, ma fonction se plante. Je pense qu'il faudrait non plus parser en recherchant les parenthèses mais plutôt les opérateurs logiques.
N'hésitez pas à me faire part de vos remarques.
Public Function ParseBoolExp(ByVal ExpressionBool As String) As Boolean
Dim posO, posF, i As Integer
Dim FinTrt As Boolean
'Longueur d'un élément booléen, 3 pour (0) ou (1) et 6 pour (true) ou (fals)
Const LenElemBool = 3
FinTrt = False
i = 0
While ExpressionBool(i) = "("
i = i + 1
End While
posO = i
posF = InStr(Mid(ExpressionBool, posO + LenElemBool), ")") + posO + 2
Select Case Mid(ExpressionBool, posO, posF - posO + 1).ToUpper
Case "(1)AND(1)", "(0)AND(0)", "(1)OR(1)", "(0)OR(1)", "(1)OR(0)"
ExpressionBool = Left(ExpressionBool, posO - 1) & "1" & Mid(ExpressionBool, posF + 1)
If ExpressionBool = "1" Then
FinTrt = True
ParseBoolExp = True
End If
Case "(0)AND(1)", "(1)AND(0)", "(0)OR(0)"
ExpressionBool = Left(ExpressionBool, posO - 1) & "0" & Mid(ExpressionBool, posF + 1)
If ExpressionBool = "0" Then
FinTrt = True
ParseBoolExp = False
End If
Case "1", "(1)"
ParseBoolExp = True
FinTrt = True
Case "0", "(0)"
ParseBoolExp = False
FinTrt = True
End Select
If Not (FinTrt) Then
ParseBoolExp = ParseBoolExp(ExpressionBool)
End If
divadav
Messages postés94Date d'inscriptionlundi 13 janvier 2003StatutMembreDernière intervention22 janvier 20092 20 déc. 2007 à 15:23
Salut Salut !
Je vois que tu as déjà accepté des réponses, et que tu n'as donc (normalement) plus de problème... Permet moi cependant d'ajouter une petite contribution !
En fait, il existe un moyen en .Net d'évaluer une expression de type chaîne comme du code VB ou C#.
Pour cela, il faut utiliser des objets comme VBCodeProvider, et les méthodes de System.Reflexion.
Si je reprend ta problématique, tu dis entre autre vouloir une fonction avec le prototype suivant :
Function ExvalueExpressionBooleenne(ByVal Expression As String) As Boolean
Et bien voici à quoi cela ressemblerait :
<hr size="2" width="100%" />Function ExvalueExpressionBooleenne(ByVal Expression As String) As Boolean
Dim vbCode As VBCodeProvider = New VBCodeProvider
Dim cParam As CompilerParameters = New CompilerParameters
' Ajout des références
cParam.ReferencedAssemblies.Add("system.dll")
' Options du compilateur
cParam.CompilerOptions = "/t:library"
cParam.GenerateInMemory = True
' Génération du code source
Dim sCode As StringBuilder = New StringBuilder("")
sCode.AppendLine("Imports System")
sCode.AppendLine("Namespace Divad")
sCode.AppendLine(vbTab & "Class EvalVbCode")
sCode.AppendLine(vbTab & vbTab & "Public Function EvalBooleanExpression(ByVal expr As String) As Boolean")
divadav
Messages postés94Date d'inscriptionlundi 13 janvier 2003StatutMembreDernière intervention22 janvier 20092 20 déc. 2007 à 18:51
Oups, je me rends compte que j'ai oublié une ligne dans l'exemple que je donne... Il fallait lire :
<hr size="2" width="100%" /> ' Génération du code source
Dim sCode As StringBuilder = New StringBuilder("")
sCode.AppendLine("Imports System")
sCode.AppendLine("Imports System.Diagnostics")
sCode.AppendLine("Namespace Divad")
<hr size="2" width="100%" />Hé oui, si on n'importe pas "System.Diagnostics", ça fait une erreur à la compilation : il ne voit pas l'objet "Debug", et ne peut donc pas compiler...
P.S. : Au fait, on fait comment pour modifier un message et éviter le double post ?