Programm zum Auswerten logischer Ausdrücke und Ausgabe von Wahrheitstafeln
-
Guten Morgen,
hier der Auszug:
Der logische Ausdruck soll in folgender Form eingegeben werden:
y = abc + acd + .a.bd + ...
...mit
a..d = 4 logische Variablen
+ = Disjunktion (ODER)
. = Negation der folgenden Variablen
ab = Konjunktion (UND)Die Anzahl der Variablen kann zwischen 2 und 4 liegen.
...
Die Wahrheitstafel soll vom Programm an die Anzahl der Variablen angepasst werden. (von der Formatierung her)
Ich bin mir nicht ganz sicher, ob es für mich einfacher wäre bei der Konjunktion auch ein Zeichen dazwischen zu setzen, wie zb. & oder *. Es verwirrt mich sehr, dass dort einfach garkein Zeichen als Operator steht, da ich auch keine Ahnung habe wie ich es dem Programm begreiflich machen könnte, dass es sich im Falle von "ab" um a & b handelt.
Gruß
-
Der Ansatz wäre wie gesagt ein Parser, der aus diesem String eine logische Funktion macht (übrigens dürften die logischen Operatoren &&, || und ! eher passen als die binären Operatoren &, | und ~). Zur Umsetzung kannst du von der gegebenen Grundstruktur ausgehen (DNF):
- Die Formel setzt sich aus Elementarkonjunktionen zusammen, die per || verknüpft werden.
- Eine Elementarkonjunktion besteht aus Literalen, die per && verknüpft werden
- Ein Literal ist entweder x oder .x (=!x)
Mit dieser Information kannst du eine Schleife über alle 0/1-Kombinationen der Variablen bilden und dazu jeweils den Formelwert ausrechnen.
-
Hallo,
danke für die Antwort. Also das mit der Schleife hört sich sehr komplex an, da bei 4 Variablen auch 16 Zustände herrschen können (oder hab ich was falsch verstanden). Wie könnte so etwas aussehen? Kann es mir nicht so direkt vorstellen, wie du es meinst.
Gruß
-
Hi,
vielleicht hilft es dir ja auch, wenn du dir ein paar Aufgaben auf einen Zettel schreibst. Und zwar so, wie du dir vorstellst, dass das Programm es spaeter erstellen soll. Und dann schreibst du in Stichworten daneben wie du alles im Kopf geloest hast. oder machst sogar ein kleines Struktugramm
Ist dann immerhin schonmal ein Ansatz.
Viel Erfolg noch
-
Hallo,
werde ich mal machen. Mein Prof meinte noch als "Hinweis", ich solle mir einfach mal den Ausgangsvektor ansehen (also Spalte y) und dann anhand eines einfachen booleschen Ausdrucks überlegen, was genau da passiert (bei Eingabe des booleschen Ausdrucks). Er verwies desweiteren nochmals auf die bitweisen Operatoren, mit deren Hilfe man das Programm wohl mit wenig Code zusammenbauen kann.
Gruß
-
Ja, das wäre auch ein Ansatz - du betrachtest eine komplette Spalte der Wahrheitstabelle als Binärvektor und verrechnest ihn dann binär:
a=0x00FF;//0000000011111111 b=0x0F0F;//0000111100001111 c=0x3333;//0011001100110011 d=0x5555;//0101010101010101 erg = a&b&c | a&c&d | ~a&~b&d | ...;//das entspricht dem Ausdruck "y = abc + acd + .a.bd + ..." von oben
Anschließend mußt du erg nur noch in seine Bits zerlegen, um damit die Wertetabelle aufzubauen (zur Zerlegung folgst du der Grundstruktur aus '+').
-
Sorry, aber für mich hört sich das nicht gerade leicht an. Gibt es irgend ein Tutorial, welches sich mit dieser bitweisen Geschichte auseinandersetzt? Lese momentan "C von A bis Z". Dort wird das Thema nur seeeehr kurz angerissen. Ich wüsste garnicht wie man etwas in Bits zerlegt.
Gruß
-
vielleicht hilft euch das weiter: http://de.wikipedia.org/wiki/Karnaugh-Veitch-Diagramm
-
Ich weis zwar wie ein KV-Diagramm aufgebaut ist, jedoch ist mir nicht ganz klar wie ich dies auf mein Problem hier anwenden soll.
-
JackBeauregard schrieb:
Ich weis zwar wie ein KV-Diagramm aufgebaut ist, jedoch ist mir nicht ganz klar wie ich dies auf mein Problem hier anwenden soll.
ich bin drauf gekommen durch den letzten beitrag von CStoll. vielleicht kann man davon irgendwas ausschlachten für dein programm. allein schon die anordnung von 4 variablen in einer quadratischen matrix ist vielleicht eine überlegung wert...
-
Mal eine Prinziplösung:
const unsigned short inputs[]={0x00FF,0x0F0F,0x3333,0x5555};//Input-Spalten der Wertetabelle unsigned short klausel(char* data) { int res=0xFFFF; //werte eine einzelne Klausel 'abd' oder 'a.b' aus //dazu kannst du für jedes Zeichen bis zum '+'/'\0' den passenden input[] //(oder seine Negation) zu res dazu-ANDen return res; } unsigned short formel(char* data) { int res=0; //werte die komplette Formel aus //hier zerlegst du die Eingabe an den +-Zeichen und gibst jeden Teil an klausel() weiter //die jeweiligen Ergebnisse werden mit res ver-ORt return res; } #define bit(v,b) (v&(1<<b)!=0) int main() { char text[100]; //Formel in 'text' eingeben unsigned short val = formel(text); printf("a b c d | res\n"); for(int i=0;i<16;++i) printf("%i %i %i %i | %i\n",bit(input[0],i),bit(input[1],i),bit(input[2],i),bit(input[3],i),bit(val,i));
Eventuell solltest du dir mal die Funktionsweise der Bit-Operatoren ansehen.
-
Hallo,
bin erst heute wieder dazu gekommen etwas für das Programm zu tun. Es stellt sich nunmehr folgende Frage: Mein Prof will, dass die Konjunktion OHNE Operator durchgeführt wird, d.h. y = abc, was soviel wie "a und b und c" bedeuten soll. Es fällt mir schwer dies in Quelltext zu fassen, d.h. das Programm dazu zu bringen den Ausdruck abc als "a und b und c" zu erkennen. Vielleicht denke ich auch nur sehr umständlich. Bin über jeden Hinweis dankbar.
Gruß
-
Du gehst in einer Schleife über den Teilstring dieser Klausel und wählst anhand des jeweiligen Buchstaben aus, welche Eingabevariable du draufrechnest:
unsigned short klausel(char* data) { unsigned short res=0xFFFF; for(;strchr("abcd.",*data)!=NULL;++data)//alle Zeichen außer a bis d und '.' brechen die Schleife ab { if(isalpha(*data)//Buchstabe a bis d res&=inputs[*data-'a']; else//kein Buchstabe, also '.' { ++data; if(*data<'a' || *data>'d') error("falsche Eingabe"); res&= ~inputs[*data-'a']; } } return res; }
-
Hallo,
eins vorab, die Funktionen sind noch nicht wirklich fertig, d.h. bspw writelist ist noch garnicht auf die Variablenanzahl angepasst usw.. Habe bislang folgendes zusammengebaut:
#include <stdio.h> #define MAXFLEN 100 #define bit(v,b) ((v&(1<<b)) != 0) . . . int func(char funktion[MAXFLEN]) { int i; int c; int banz; do { printf("\nBitte booleschen Ausdruck eingeben:\n"); printf("Y = "); fgets(funktion, MAXFLEN, stdin); banz = pruef(funktion); } while(banz == 0); printf("Y = %s\n", funktion); return banz; } int menue(void) { printf("1 = Eingabe der logischen Funktion\n" "2 = Ausgabe der Wahrheitstafel\n" "0 = Programmende\n\n"); return readint("Auswahl: ", 0, 2); } int readint(char msg[], int lower, int upper) { int zahl, n; do { printf("%s", msg); n = scanf("%d", &zahl); while (getchar() != '\n'); if (n != 1) printf("\nBitte nur Zahlen eingeben!\n\n"); else if (zahl < lower) { printf("\nUngueltiger Bereich!\n\n", lower); n = 0; } else if (zahl > upper) { printf("\nUngueltiger Bereich!\n\n", upper); n = 0; } } while (n != 1); return zahl; } int writelist(void) { const unsigned short a = 0x00FF; const unsigned short b = 0x0F0F; const unsigned short c = 0x3333; const unsigned short d = 0x5555; int i; printf("\na b c d | y\n"); printf("--------|--\n"); for(i = 15; i >= 0; i--) printf("%i %i %i %i | %i\n", bit(a,i), bit(b,i), bit(c,i), bit(d,i)); } int main() { int i; int auswahl; char funktion[MAXFLEN]; printf("Boolesche Ausdruecke und Wahrheitstafeln\n" "----------------------------------------\n\n"); do { auswahl = menue(); switch (auswahl) { /*Auswahl des Menuepunktes 1*/ case 1: func(funktion); break; /*Auswahl des Menuepunktes 2*/ case 2: writelist(); break; /*Auswahl des Menuepunktes 0*/ case 0: printf("\nProgrammende!"); break; } } while(auswahl = 0); return 0; } int pruef(char funktion[MAXFLEN]) { int a = 0; int b = 0; int c = 0; int d = 0; int punkt = 0; int oder = 0; int i; if(funktion[0] == '+'){ printf("Zu Beginn des Ausdrucks kein Oder!"); return 0; } for(i = 0; i < MAXFLEN; i++){ if(funktion[i] == 'a'){ a = 1; punkt = 0; oder = 0; } else if(funktion[i] == 'b'){ b = 1; punkt = 0; oder = 0; } else if(funktion[i] == 'c'){ c = 1; punkt = 0; oder = 0; } else if(funktion[i] == 'd'){ d = 1; punkt = 0; oder = 0; } else if(funktion[i] == '.'){ if(punkt == 1){ printf("Syntaxfehler: Doppelte Negation an Stelle %i\n", i); return 0; } else { punkt = 1; } } else if(funktion[i] == '+'){ if(punkt == 1){ printf("Syntaxfehler: Negation des Oder-Symbols an Stelle %i\n", i); return 0; } if(oder == 0){ oder = 1; }else{ printf("Syntaxfehler: Zwei Oder-Symbole nacheinander an Stelle %i" "\n", i); return 0; } } else{ if(funktion[i] == ' '){ } else if(funktion[i] == '\n') { } else if(funktion[i] == '\0') { if(punkt == 1 | oder == 1) { printf("Unzulaessiges Symbol am Ende des Ausdrucks!\n"); return 0; } i = MAXFLEN; } else { printf("Syntaxfehler: Unzulaessiges Symbol(%c) an Stelle %i\n", funktion[i], i+1); return 0; } } } if((a+b+c+d) < 2){ printf("Bitte mindestens 2 Variablen benutzen!\n"); return 0; } if(((a+b+c+d) == 3) && (d == 1)){ printf("Bitte die Variablen nach Alphabetischer Reihenfolge waehlen!\n"); return 0; } if(((a+b+c+d) == 2) && ((c == 1)|(d == 1))){ printf("Bitte die Variablen nach Alphabetischer Reihenfolge waehlen!\n"); return 0; } return (a+b+c+d); }
Das Ganze soll so ablaufen, dass nach der Eingabe des log. Ausdrucks (Menüpunkt 1) ins Auswahlmenue zurückgesprungen werden soll und der Benutzer die Möglichkeit bekommen soll Menüpunkt 2 auszuwählen um so eine Wahrheitstabelle ausgegeben zu bekommen. Genauso soll nach der Ausgabe der Tabelle ins Auswahlmenue zurück gesprungen werden.
Wie kann dies realisiert werden? Ans Ende der Funktion ein main(); hängen wäre ja nicht wirklich gut ;). Wichtig ist ja hierbei, dass der eingegebene Ausdruck gespeichert wird damit er dann über die Wahrheitstafel ausgegeben werden kann.
Ich hoffe, dass ihr versteht was ich meine.
Achja, eine generelle Meinung/Kritik zum Quellcode wäre sehr willkommen. Da ich mich nicht unbedingt an das gehalten habe was CStoll mir vorgeschlagen hat, ist diese sicherlich angebracht ;).
Gruß
-
JackBeauregard schrieb:
Das Ganze soll so ablaufen, dass nach der Eingabe des log. Ausdrucks (Menüpunkt 1) ins Auswahlmenue zurückgesprungen werden soll und der Benutzer die Möglichkeit bekommen soll Menüpunkt 2 auszuwählen um so eine Wahrheitstabelle ausgegeben zu bekommen. Genauso soll nach der Ausgabe der Tabelle ins Auswahlmenue zurück gesprungen werden.
Wie kann dies realisiert werden? Ans Ende der Funktion ein main(); hängen wäre ja nicht wirklich gut ;). Wichtig ist ja hierbei, dass der eingegebene Ausdruck gespeichert wird damit er dann über die Wahrheitstafel ausgegeben werden kann.
Keiner nen Tipp? Habe es schon mit verschiedenen Schleifenkonstrukten versucht, aber bislang erfolglos.