Si pour lui toutes les opérandes sont vraies cela vient a priori des entrées du dictionnaire, pas de l'algorithme. Encore une fois le débogage pas-à-pas avec l'inspection des valeurs à tout instant permettra de vérifier cette hypothèse.
Version imprimable
Si pour lui toutes les opérandes sont vraies cela vient a priori des entrées du dictionnaire, pas de l'algorithme. Encore une fois le débogage pas-à-pas avec l'inspection des valeurs à tout instant permettra de vérifier cette hypothèse.
je crois que l'on ne sait pas compris.
Je t'explique si je saisi 4 paramètres et que ma règle correspond à ceci :
(1&2)|(3&4).
Il faut qu'en sorti j'ai false car je dois avoir saisi soit 1&2 soit 3&4.
Mon dictionnaire aura en entrée :
1 True
2 True
3 True
4 True
Ce qui est juste car cela correspond à la saisi des paramètres.
Effectivement on ne se comprend pas : vrai & vrai donne vrai, vrai | vrai donne vrai. Donc l'algo a raison de renvoyer "vrai".
:aie:
Tout mon algo est foireux. Il faut que je le reprenne alors.
Pourrais tu m'aider sur ce coup?
Merci
Justement, non, l'algo est juste d'après l'exemple que tu donnes.
Ou alors est-ce que tu veux dire que tu t'es trompé de problème ?
Qu'est-ce qui ne va pas ?
Je t'explique mon but.
Il me faut une fonction qui me renvoi un booleen.
Cette fonction a en entrée une règle et un dictionnaire:
- règle : peut etre de type (1&2)|(3&4)
- dictionnaire est de type <int,booleen>. Le int correspond au numéro du paramètre et le booleen permet de savoir si ce paramètre a été renseigné.
Mon but est en fonction de la règle renvoyé un booleen qui check si les paramètres sont saisie en fonction de la règle.
Si j'ai rule = (1&2)|(3&4)
et dictionnaire =
1 True
2 True
3 True
4 True
alors je dois renvoyé false car ma rule contient un |(ou). Je devrais avoir soit (1&2) de saisi soit (3&4).
Il peut y avoir toute sorte de règle mais elles sont bien regroupé dans des parenthèses et mon dictionnaire sera toujours bien renseigné en fonction de la saisie des param.
J'espere avoir été clair sur mon but. J'espere aussi que l'on trouvera un moyen de mettre cela en place pour tout type de règle.
Merci
Désolé mais ça n'a aucun sens, tu fais une erreur de logiquecar (vrai & vrai) | (vrai & vrai) est vrai.
Vrai & vrai -> vrai
Vrai | vrai -> vrai.
Si tu veux que vrai $ vrai renvoie faux, alors $ n'est pas la règle "OU" (|). Est-ce que tu ne confonds pas avec le OU exclusif (^) ?
"|" veut dire "A ou B ou les deux"
"^" veut dire "soit A soit B mais pas les deux".
C'est exactement ce que je veux avec le ^. Je pensais pas qu'il servait à cela. Je ne l'avais jamais utilisé.
Cela signifie que j'ai juste à modifier mon code au niveau du |et mettre ^.
C'est bien cela ?
Merci pour ton aide. J'ai appris plein de choses
J'ai effectué des tests avec le ^ mais ça ne marche pas pour tous les cas.
si j'ai vrai^vrai => false ok pour moi
si j'ai vrai^false => vrai nok pour moi
si j'ai false^vrai => false ok pour moi
si j'ai false^false => false ok pour moi
Il manque un cas à gérer vrai^false
La table de l'opérateur ^est :
1^1 -> 0
1^0 -> 1
0^1 -> 1
0^0 -> 0
D'après ce que tu nous décris il y a donc deux problèmes :
* L'algo a un bogue car il ne respecte pas cette table de vérité.
* Tu t'es encore trompé dans ce que tu veux : si ton programme doit toujours renvoyer faux, alors remplace tout le code par "return false".
J'ai l'impression que tout cela t'énerve et j'en suis vraiment désole.
Tout dépend de ma règle. En fonction de ma règle et de la saisi de mes paramètres alors je renvois vrai ou faux.
si j'ai (1&2) et que 1 et 2 sont saisi alors je renvoi Vrai
si j'ai (1&2) et que 1 saisi et 2 non saisi alors je renvoi false
etc
si j'ai (1&2)|(3&4) et que 1,2,3,4 saisi alors je renvoi false car d'après ma règle je devrai avoir que 1&2 de saisi ou 3&4 mais pas les quatre.
j'espère être assez clair dans mon explication.
Je ne suis pas du tout énervé. Mais tu n'arrives pas à expliquer correctement ce que tu veux ou quel est ton problème.
Là tu me dis que (1&1)^(1&1) doit donner 0. Je suis parfaitement d'accord mais tu m'as dit que ça fonctionnait dans ton précédent message. Ça ne fonctionne plus ? Si oui à quel moment est-ce que ça plante ? Au passage je présume que tu voulais écrire "^" et non "|", sinon le comportement est normal.
Relis mon précédent message (#50) : tes attentes correspondent-elles à la table que j'avais donnée ?
Je ne sais toujours pas ce que tu veux ni ce qui ne va pas. Essaie d'être plus formel et plus clair. Utilise une table de vérité au besoin, etc.
Salut,
je suis de retour et désolé pour mon absence j'étais pris sur un autre projet.
Alors je savais que j'allais pas trop me faire comprendre vu la complexité de mon algo. Mais je vais reprendre avec une table de vérité comme demandé.
La table de l'opérateur ^ est :
1^1 -> 0
1^0 -> 1
0^1 -> 1
0^0 -> 0
La table de l'opérateur & est :
1&1 -> 1
1&0 -> 0
0&1 -> 0
0&0 -> 0
Plusieurs Exemples détaillés par rapport à mes règles et que j'ai testé avec l'algo:
(1&1)^(1&1) ==> (1)^(1) => 0 (j'obtiens ce résultat avec l'algo)
(0&0)^(0&0) ==> (0)^(0) => 0 (j'obtiens ce résultat avec l'algo)
(1&1)^(0&0) ==> (1)^(0) => 1 (j'obtiens ce résultat avec l'algo)
(0&0)^(1&1) ==> (0)^(1) => 1 (je n'obtiens pas ce résultat avec l'algo, mon algo me renvoi 0)
D'autres exemples de fonctionnement voulu:
(1&0)^(1&1) ==> 0 je devrais obtenir 0 en retour car d'après ma règle seule la première parenthèse ou la deuxième doit être rempli. Si j'ai des données saisi dans la 1er et la 2eme je dois renvoyer false
Tout dépend de ma règle. si j'ai ^alors seul il faut checker que seul un lot de donnée d'une parenthèse doit être renseigné. Il faut aussi vérifier que le & dans la parenthèse est ok c'est dire que les 2 doit être renseigné.
C'est un peu complexe et pas simple à comprendre et expliquer mais je fais de mon mieux.
Sincèrement, n'hésite pas à revenir vers moi pour toute autres explications et si tu le souhaites on peut reprendre pas à pas le détail de l'explication
Merci pour ta patience et ton aide précieuse DonQuiche
Je te remercie pour ce dernier message, qui est très clair.
Voici mes remarques:
* Ce que tu veux est bien la règle "^" (ou exclusif). Et il y a bien un bogue dans le programme au vu du premier problème. Pourrais-tu me montrer ton code actuel s'il te plaît ? Et quid du débogage pas-à-pas ? As-tu notamment vérifié les valeurs retournées pour les deux opérandes de "^" ?
* Je t'invite à refaire le cas problématique en plaçant un point d'arrêt (F9) sur la dernière ligne de ta fonction principale ("return resultat") et à me donner les valeurs successives rencontrées pour resultat au cours d'une exécution (F5, relève, F5, relève, F5, relève, etc). Normalement ça devrait être dans l'ordre :
0 (pour "a")
0 (pour "b")
0 (pour "a&b")
0 (pour "(a&b)")
1 (pour "c")
1 (pour "d")
1 (pour "c&d")
1 (pour "(c&d)")
1 (pour "(a&b)^(c&d)")
* Concernant le deuxième problème, en réalité (1&0)^(1&1) -> 0^1 -> 1, et non pas 0 comme tu l'avais écrit. Pas de bogue ici. Le comportement que tu semble décrire me fait plutôt penser à (a|b)^(c|d).
Merci pour ton retour
Voici mon code actuel
Mon appel pour la fonction checkRule:Code:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 protected bool checkRule(string rules, Dictionary<int?, bool> groupValids,ref int position) { int len = rules.Length; bool resultat =true; if (string.IsNullOrEmpty(rules)) return true; if (PositionValide(rules,position)) { if (PositionValide(rules,position) && rules[position] == '(') { position++; resultat &= checkRule(rules, groupValids, ref position); } else { string operande = LireNombre(rules, ref position); if (!string.IsNullOrEmpty(operande)) { resultat = groupValids[int.Parse(operande)]; //position++; resultat &= checkRule(rules, groupValids, ref position); } } if (PositionValide(rules,position) && rules[position] == '&') { position++; resultat &= checkRule(rules, groupValids, ref position); } if (PositionValide(rules,position) && rules[position] == '|') { position++; resultat ^= checkRule(rules, groupValids, ref position); } if (PositionValide(rules,position) && rules[position] == ')') { position++; resultat &= checkRule(rules, groupValids, ref position); } } return resultat; }
rules = (1&2)|(3&4)
groupvalids =
1,False
2,False
3,true
4,true
5,true (mais à ne pas prendre en compte car pas dans la règle)
position = 0
Voici le résultat que j'obitens en effectuant le debug comme tu me l'as dit:
1
1
1
1
1
1
0
0
0
0
0
0
Voila
Sinon concernant le |ce n'est pas précisément ce que je veux car si je fais cela je serais pas bon dans d'autres cas pour mon debug
Ok, je vois le problème avec ton code : tu as des appels inutiles à checkRule, qui sèment la pagaille. Rappelle-toi que checkRule est supposé parser l'opérande sur laquelle le code est positionné. Il n'y a aucune raison de parser une opérande après un nombre ou après une parenthèse fermée.
Tu vois maintenant l'intérêt d'écrire un code qui plante en cas de problème : ce bogue aurait été détecté plus tôt parce que l'algo t'aurait sauté au visage. Par exemple si tu vires te test "string.IsNullOrEmpty(operande)" alors ton code actuel lèvera une erreur parce que tu appelles checkRule au mauvais moment. Du coup en remontant dans la pile d'appel tu tomberas sur la ligne problématique. Même chose si tu avais remis le test pour la parenthèse fermante dans le bloc gérant la parenthèse ouverte.
Tout ça étant dit, deux problèmes qui rendent ton code confus à la lecture :
* Tu as des "&=" inutiles. A l'exception du cas de l'opérateur "&" ce devraient être de simples assignations.
* Tu devrais réécrire tes règles pour y remplacer "|" par "^" plutôt que redéfinir le sens de "|" dans ton code. Si tu désignes un chat, ne l'appelle pas "un chien", c'est le meilleur moyen pour rendre ton code incompréhensible et causer des bogues plus tard.
* Si tu utilises l'anglais, utilises un anglais correct : validGroups, et non pas groupValids. ;)
J'ai l'impression qu'en fait, voici l'ensemble des règles qui se cachent derrière sa syntaxe "(a&b)|(c&d)" :
C'est à dire que le formulaire est découpé en deux parties :
Partie 1 contenant les champs A et B.
Partie 2 contenant les champs C etD.
Il faut que tous les champs d'une seule des deux parties soient tous remplis, et que tous les champs de l'autre ne le soient pas.
Donc c'est vrai si (combinaison avec un et logique) :
1/ a égale à b
2/ c égale à d
3/ a différent c
Ce qui donne, si je ne m'abuse :
(a&b)|(c&d)&!(a&c)
Non ?
Peut-être bien. Si tu as raison sur ton interprétation de ses propos alors la formule serait plutôt (tous trois équivalents) :
"(a et b mais ni c ni d) OU (c et d mais ni a ni b)"
((a&b) & !(c|d)) | ((c&d) & !(a|b))
(a & b & !c & !d) | (c & d & !a & !b)
Tes trois points sont justes mais la traduction serait en fait :Citation:
Donc c'est vrai si (combinaison avec un et logique) :
1/ a égale à b
2/ c égale à d
3/ a différent c
Ce qui donne, si je ne m'abuse :
(a&b)|(c&d)&!(a&c)
!(a^b) & !(c^d) & (a^c)
On doit pouvoir prouver que c'est équivalent aux deux autres.
En effet le "ou exclusif" est vrai si et seulement si les deux opérandes sont distinctes. Le "et" correspond pour sa part à "toutes deux vraies".
C'est tout à fait ça qu'il me faut stringBuilder.
Mon formulaire est découpé en fonction de ma règle.
Du coup en fonction du & et du |(correspond ^), je dois gérer la saisi des champs.
Comme vous l'avez indiqué, si (a&b)|(c&d) alors:
Citation:
"(a et b mais ni c ni d) OU (c et d mais ni a ni b)"
Bien évidement tout doit s'adapter à ma règle qui peut être écrite de différentes manières en fonction de mes formulaires.
si j'ai (a&b&c)|(d) alors (a et b et c mais ni d) OU (d mais ni a et b et c)
etc etc
Du coup, ai je un gros changement à faire dans mon code ?
Que dois je retirer ou ajouter car la je n'ai pas compris ce que tu veux dire ?Citation:
Tu vois maintenant l'intérêt d'écrire un code qui plante en cas de problème : ce bogue aurait été détecté plus tôt parce que l'algo t'aurait sauté au visage. Par exemple si tu vires te test "string.IsNullOrEmpty(operande)" alors ton code actuel lèvera une erreur parce que tu appelles checkRule au mauvais moment. Du coup en remontant dans la pile d'appel tu tomberas sur la ligne problématique. Même chose si tu avais remis le test pour la parenthèse fermante dans le bloc gérant la parenthèse ouverte.
pourriez vous m'indiquer comment orienter mon algo?
Je sens que l'on approche du bout.
Merci
Tu as maintenant un algo qui vérifie tes règles. Le problème c'est que tu as découvert que tes règles ne conviennent pas. Donc soit tu réécris tes règles, soit tu décides que "&" ne veut pas dire "&", que "|" ne veut pas dire "|" etcétéra.
Dans ce dernier cas tu dois formaliser ce dont tu as besoin, c'est à dire expliquer le nouveau comportement général que tu désires, avec une règle applicable à tous les cas et pas seulement un exemple. Tu es le seul à savoir toute la diversité de cas que tu pourrais rencontrer et ce que tu veux obtenir. Que se passe t-il par exemple quand il y a six valeurs ? Sept valeurs ? Douze valeurs avec plusieurs niveaux ?
Je ne peux pas répondre avant que tu aies formalisé. Mais si ça se trouve tout est à jeter et dès le départ des équations booléennes n'étaient pas adaptées à ton problème.Citation:
Du coup, ai je un gros changement à faire dans mon code ?
Par contre cette fois essaie de cerner correctement le problème dès le début, histoire de ne pas reperdre deux semaines sur une solution qui n'a aucun intérêt parce que pas adaptée au problème.
Un expression doit commencer par une parenthèse ouverte ou un nombre. Donc dans le second cas tu ne devrais jamais avoir une chaîne "opérande" vide. En choisissant de tester ce cas afin de ne pas lever d'exception tu te retrouves à supporter un cas invalide, pour lequel tu renvoies un résultat erroné. Mieux vaudrait laisser le programme planter pour te permettre de détecter l'erreur.
a) Ne cherche jamais à gérer les cas invalides qui ne devraient jamais se produire (sauf en cas d'erreur de ta part).
b) Fais en sorte que ces cas invalides plantent bruyamment et dès que possible.
merci pour ton explication.
Je vais te formaliser exactement et précisément ce que je souhaite:
Partons du fait que mes parenthèses représentent des niveaux.
Si j'ai (a&b) alors je n'ai qu'un niveau :
(a&b)
(
|
-- a
|
-- ET(&)
|
-- b
|
)
Cela signifie que que je devrais renseigner a et b pour valider ma règle.
Autre Exemple avec ((a&b)|(c&d)) :
((a&b)|(c&d))
(
|
|
-- (
| |
| -- a
| |
| -- ET(&)
| |
| -- b
| |
| )
|
|
--OU (|)
|
|
-- (
| |
| -- c
| |
| -- ET(&)
| |
| -- d
| |
| )
|
|
)
je devrais avoir:
-soit a et b renseigné mais ni c ni d
OU
-soit c et d renseigné mais ni a ni b
Il faut voir les priorités dans la règle comme des les règles mathématique au niveau des parenthèses, mais il faut tout de même analyser le reste de l'expression pour vérifier toute la règle.
Dans un premiers temps, on regroupe par parenthèse et on analyse pour renvoyé soit true soit false.
Plus j'ai des paramètres, plus ma règle sera longue si besoin.
Ce n'est pas simple à comprendre mais sur les derniers commentaire on a sorti exactement mon besoin avec DonQuiche et StringBuilder.
Le | faut le comprendre comme un ^ou exclusif bien evidement. Je changerais ma syntaxe à l'avenir dans ma règle mais pour le moment je vais fonctionner comme cela.
Si tu souhaites d'autres précisions je suis à ta disposition.
Merci
Tu m'as malheureusement mal compris.
J'avais bien saisi que tu voulais que "(a et b) ou (c et d)" soit en fait compris comme "(a et b mais ni c ni d) OU (c et d mais ni a ni b)". Mais ça c'est un exemple particulier. Qu'en est-il pour les autres formules ? Comment faut-il les interpréter ?
Peux-tu par exemple avoir une règle "((a&b)&(c&d))|((e|f)&(g^h))" ? Comment veux-tu l'interpréter alors ?
PS : J'ai l'impression que tu restes sur l'idée que c'est un bogue de l'algo qui ne considérerait pas la formule dans son ensemble. Si oui oublie tout de suite cette idée : l'algo fonctionne correctement, c'est toi qui exiges un comportement qui ne correspond pas aux règles mathématiques que tu donnes.
Il faut pouvoir interpréter toutes les formules.
Par contre, je n'aurais pas de ^. J'aurais comme opérande uniquement & et | qu'il faut interpréter comme un ET et un OU exclusif.
Je peux avoir toute sorte de formule.
Par exemple celle que tu fournit : ((a&b)&(c&d))|((e|f)&(g^h))" serait ecrite comme cela ((a&b)&(c&d))|((e|f)&(g|h)).
A la place du ^j'aurais |.
Ca me donnerait :
- soit a et b et c et d mais ni e,f,g,h
- soit e et g ni f ,h ,a, b, c, d
- soit e et h ni f ,g ,a , b, c, d
- soit f et g ni e ,h ,a , b, c, d
- soit f et h ni e ,g ,a , b, c, d
interpréter les opérandes et les parenthèses en fonction de leur position.
En somme un ensemble d'opérandes est accepté si :
a) La règle est vraie.
b) Si une opérande vraie quelconque passe à faux, alors la règle est fausse.
Dans ce cas c'est facile, tu testes d'abord la première condition avec l'algo obtenu jusqu'ici puis pour chaque opérande vraie tu vérifies qu'en la passant à faux la règle devient fausse, toujours avec l'algo établi jusqu'ici. Ca fonctionnera tant que tu n'auras pas d'opérateur négation (NON) et qu'un résultat faux n'aura pas de conditions additionnelles.
Mais ton problème sent vraiment le poisson. A mon avis il est mal posé ou c'est une idée tordue pour l'UI. A mon avis tes règles n'ont pas besoin d'être quelconques, tu n'as jamais eu besoin d'algèbre booléenne mais seulement de tester quelques combinaisons précises. Si oui tu aurais mieux faut d'exprimer tes règles ainsi (pour reprendre le dernier exemple) en énumérant simplement les ensembles valides :
(a,b,c,d) ; (e,g) ; (f,h) ; (f,g)
Ça aurait été un jeu d'enfant à parser et ça aurait été beaucoup plus simple à comprendre.
je suis d'accord avec toi sur ce que tu dis à la fin.
Je m'adapte au projet. Je fais de la maintenance et je ne peux pas tout modifier comme cela.
Je prend conscience de ce que je demande et j'avoue que je m'exprime mal mais c'est pas simple non plus à comprendre.
Toutes mes valeurs dépendent de ma formule.
Ma formule est écrite de la sorte car si je suis en erreur alors je l'affiche en remplaçant le & par ET et le | par OU. Que ce soit parlant à l'utilisateur finale.
Je m'excuse encore une fois pour toute ça. Je ne peux pas faire autrement.
Bonjour,
Ton algo c'est a but pédagogique ou fonctionnel ?
Personnellement je m'orienterai plutôt (peut-etre a tord)
vers les CodeDom pour faire ta fonction afin d’exécuter a la volée ta requête
(voir code ci-dessous desolé pour les commentaires j'ai fait ca vite)
---------------------------------------------------------------------------
Code:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 /* * Crée par SharpDevelop. * * \file ...............cs * \author Mister MOK * \version 1.0 * \date 04/02/2014 * \time 19:21 * \brief Classe .............. * * \details .............. */ using System; using System.Collections; using System.CodeDom.Compiler; using System.Reflection; using System.Collections.Generic; namespace TestParser { public class FormuleParser { public bool m_Error; private string strInstrDbl = string.Empty; private string strInstrBool = string.Empty; public object myobj = null; public ArrayList errorMessages; public void PrepareFormule(string expr, int NbVAR) { expr = expr.ToLower(); errorMessages = new ArrayList(); CodeDomProvider cp = CodeDomProvider.CreateProvider("C#"); CompilerParameters cpar = new CompilerParameters(); cpar.GenerateInMemory = true; cpar.GenerateExecutable = false; cpar.ReferencedAssemblies.Add("system.dll"); System.Text.StringBuilder SB = new System.Text.StringBuilder(); //-------------------------------------------------------- SB.Append("using System;"); SB.Append("[Serializable]"); SB.Append("class clsExecCode"); SB.Append("{"); SB.Append("public clsExecCode(){}"); #region fonctions compilée a la voléee strInstrBool = "public bool evalBOOL("; strInstrBool += "bool var1"; for (byte i = 1; i < NbVAR ; i++) strInstrBool += ",bool var" + (i+1).ToString(); strInstrBool += ")"; SB.Append(strInstrBool); SB.Append("{"); SB.Append("try"); SB.Append("{return " + expr + ";}"); SB.Append("catch"); SB.Append("{return false;}"); SB.Append("}"); #endregion SB.Append("}"); //-------------------------------------------------------- CompilerResults cr = cp.CompileAssemblyFromSource(cpar, SB.ToString()); foreach (CompilerError ce in cr.Errors) // ajout des erreurs éventuelles errorMessages.Add(ce.ErrorText); if (cr.Errors.Count == 0 && cr.CompiledAssembly != null) { Type ObjType = cr.CompiledAssembly.GetType("clsExecCode"); try { if (ObjType != null) myobj = Activator.CreateInstance(ObjType); } catch (Exception ex) { errorMessages.Add(ex.Message); } m_Error = true; } else m_Error = false; } public bool eval(bool[] TAB) { bool val = false; Object[] myParams = new object[TAB.Length]; for (byte i = 0; i < TAB.Length; i++) myParams[i] = (Object)TAB[i]; if (myobj != null) { MethodInfo evalMethod = myobj.GetType().GetMethod("evalBOOL"); val = (bool)evalMethod.Invoke(myobj, myParams); } return val; } } //------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------ class Program { public static void Main(string[] args) { Console.WriteLine("Hello World!"); FormuleParser TestFormule = new FormuleParser(); TestFormule.PrepareFormule("(var1 & var2) | (var1 & var3) ",3); bool X = TestFormule.eval(new bool[]{true,true,true}); Console.Write(string.Format("\r\n{0}\r\n\r\n",X)); // TODO: Implement Functionality Here Console.Write("Press any key to continue . . . "); Console.ReadKey(true); } } } }
MisterMok > Merci pour ton aide mais ton algo est un peu trop complexe pour moi. je ne comprend pas tout car malheureusement pas assez expérimenté.
C'est à but fonctionnel que je fait cet algo.
C'est une application que j'ai repris et dont je fais la maintenance.
En tout cas, je te remercie beaucoup pour ton aide. Je suis pas loin du résultat que je souhaite. Il reste encore des cas à gérer.
Le code est moins compliqué qu'il n'y parait. Ca semble lourd mais c'est surtout
parce que c'est long a lire a cause des verifications. Mais au final tu écris dynamiquement ta fonction et l'exploite comme si tu l'avais créée dans ton code
Vas te créer une classe intégrant ta fonction du genre :Code:
1
2
3 FormuleParser TestFormule = new FormuleParser(); TestFormule.PrepareFormule("(var1 & var2) | (var1 & var3) ",3); // 3 parametres
qu'au final tu appelle comme ceci :Code:
1
2
3
4
5 public bool evalBOOL(bool var1, bool var2, bool var3) { return (var1 & var2) | (var1 & var3) ; }
où var1 = true ; var2 = true ; var3 = true;Code:
1
2 bool X = TestFormule.eval(new bool[]{true,true,true});
Après si tu veux créer 8 entrée tu fais :
Mais je comprend , si tu arrives à la fin ce serait dommage d'abandonnerCode:
1
2
3
4 FormuleParser TestFormule = new FormuleParser(); TestFormule.PrepareFormule("Test a faire",8); // 8 parametres bool X = TestFormule.eval(new bool[8]{true,true,true,true,true,true,true,true});
si près du but ( et surtout frustrant )
Bon dev à toi, et courage !
Même si effectivement ça n'a plus d'intérêt au point où il en est, je reconnais que rétrospectivement je lui aurais conseillé CodeDom si j'avais su que le parser lui poserait autant de difficultés. Mes premiers pas sont très loin derrière moi, j'ai déjà écrit plusieurs parsers et je n'avais pas réalisé que c'était conceptuellement aussi difficile à comprendre.
CodeDom a le gros avantage d'être conceptuellement plus simple et pour un débutant c'est essentiel. En revanche la mise en oeuvre est finalement plus complexe et plus lourde que le parser que j'avais proposé en page 1, qui est une magnifique petite chose de 70 lignes aérées et bien découpées, très élégante et légère, et fonctionnelle dans tous les environnements (ce qui n'est pas le cas de CodeDom qui nécessite des privilèges peu recommandés sur un serveur).
Franchement je ne sais plus quoi faire et où faire mes modifs.
Dois je revenir en arrière et tout revoir Ou continuer dans ma démarche et faire des modifs mais je ne sais même pas ou.
Desole pour tout
Dans mon précédent post j'avais formalisé ton problème ainsi :
a) La règle doit être vraie.
b) Si une opérande vraie quelconque passe à faux, alors la règle doit devenir fausse.
L'algo actuel, tel que tu me l'avais récemment présenté, permettait de vérifier si ta règle est vraie ou fausse. Tu peux l'utiliser tel quel. Simplement ça ne suffit pas : quand la règle est vraie, tu dois ensuite vérifier qu'elle devient fausse si n'importe quelle opérande vraie devient fausse.
En somme si tu as une règle f et quatre opérandes a=1, b=1, c=0, d=0 alors tu dois vérifier que :
a) f(1, 1, 0, 0) == 1
b) f(0, 1, 0, 0) == 0
c) f(1, 0, 0, 0) == 0
Ton code actuel te permet d'évaluer f.
Oui ok.
Comment je fais ça dans mon code?
Moi je dois verifier que j'ai vrai au départ et si pour le reste j'ai faux alors je suis ok. Par contre si le reste est vrai ou une opérande est vrai alors en retour je suis faux.
Pas très simple à comprendre.
Quel modif je dois faire dans mon algo et a quel niveau du code?
Merci
Pour chaque opérande, si elle est vraie, alors tu la mets à faux, tu appelles ton algo, tu vérifies le résultat, puis tu la remets à vrai et tu passes à la suivante.
Et tout ça doit être dans une nouvelle fonction de plus haut niveau que ton algo actuel.
Coucou,
je suis de retour apres 2semaines d'absence.
Desole mais ma femme a accouché et j'ai du faire le pompier.
Bref, revenons à nos problèmes.
Ce que tu m'indiques DonQuiche et que je dois fausser mon resultat au fur et à mesure que j'avance dans l'analyse de chaque opérande.
Tu me dis de mettre une fonction de plus haut niveau qui appel mon l'algo que j'ai mis en place, mais là je ne comprends pas car je devrais faire appel à l'algo pour chaque opérande.
Voici mon code d'appel à la fonction
Voici ma fonction checkRuleCode:
1
2
3
4 int position = 0; bool isOK; isOK = checkRule(RuleValidator, ParamSaisie, ref position);
Ce que tu me dis ne fonctionnera pas ou peut etre je me trompe.:?Code:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 protected bool checkRule(string rules, Dictionary<int?, bool> validGroups,ref int position) { int len = rules.Length; bool resultat =true; if (string.IsNullOrEmpty(rules)) return true; if (PositionValide(rules,position)) { if (PositionValide(rules,position) && rules[position] == '(') { position++; resultat = checkRule(rules, validGroups, ref position); } else { string operande = LireNombre(rules, ref position); if (!string.IsNullOrEmpty(operande)) { resultat = validGroups[int.Parse(operande)]; //position++; resultat = checkRule(rules, validGroups, ref position); } } if (PositionValide(rules,position) && rules[position] == '&') { position++; resultat &= checkRule(rules, validGroups, ref position); } if (PositionValide(rules,position) && rules[position] == '|') { position++; resultat ^= checkRule(rules, validGroups, ref position); } if (PositionValide(rules,position) && rules[position] == ')') { position++; resultat = checkRule(rules, validGroups, ref position); } } return resultat; }
Félications pour cet heureux événement. Par contre tu n'as pas du tout compris ce que j'avais expliqué : il fallait garder ton algo intact et en faire une sous-partie d'une solution plus vaste.
Je renomme ton ancien algo checkRules en "parseExpression". Version précédente, inchangée. Voici le nouveau checkRules:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 checkRules(...) si !parseExpresion(...) retourner faux pour chaque opérande si isOperandOptional(...) retourner faux fin retourner vrai fin isOperandOptional(...) si opérande == faux retourner faux opérande = faux var résultat = parseExpression(...) opérande = vrai retourner résultat // toujours vrai malgré le changement de valeur pour cette opérande? fin