#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#define EVAL_MAX 255
double calc(double o1, double o2, char op)
{
if(op=='*')
{
return o1*o2;
}
else if(op=='/')
{
return o1/o2;
}
else if(op=='+')
{
return o1+o2;
}
else if(op=='-')
{
return o1-o2;
}
//and
else if(op=='&')
{
if(o1 && o2)return 1.0;
else return 0.0;
}
//or
else if(op=='|')
{
if(o1 || o2)return 1.0;
else return 0.0;
}
//nicht
else if(op=='!')
{
if(!o1)return 1.0;
else return 0.0;
}
//größer-gleich
else if(op=='g')
{
if(o1 >= o2) return 1.0;
else return 0.0;
}
//kleiner-gleich
else if(op=='k')
{
if(o1 <= o2) return 1.0;
else return 0.0;
}
//ungleich
else if(op=='u')
{
if(o1 != o2)return 1.0;
else return 0.0;
}
//größer
else if(op=='>')
{
if(o1 > o2)return 1.0;
else return 0.0;
}
//kleiner
else if(op=='<')
{
if(o1 < o2)return 1.0;
else return 0.0;
}
return -1;
}
int execute_symbol(double *vals, char *ops, int *vals_am, int *ops_am, int symbol)
{
// suchen der zugeörigen Werte
int first_value=0;
int k;
for(k=0;k<*ops_am;k++)
{
if(k>=symbol)break;
if(ops[k]!='(' && ops[k]!=')')first_value++;
}
//Berechnung der Operation
double e = calc(vals[first_value],vals[first_value+1],ops[symbol]);
//Einträge ersetzen
//Werte
vals[first_value]=e;
//NOT hat nur einen zugehörigen Zahlenwert
//Ist der Operator '!' darf der 2. Wert nicht entfernt werden
if(ops[symbol]!='!')
{
for(k=first_value+1;k<*vals_am;k++)
{
vals[k]=vals[k+1];
}
*vals_am = *vals_am-1;
}
//Operationen
for(k=symbol;k<*ops_am;k++)
{
//dfhgb
ops[k]=ops[k+1];
}
*ops_am = *ops_am-1;
return 1;
}
int simplify(double *vals, char *ops, int *vals_am, int *ops_am)
{
//nicht mehr zu vereinfachen: nur noch ein wert vorhanden
if(*vals_am==1) return 0;
//operatoren nach überflüssigen Klammern durchsuchen:
int i;
for(i=0;i<*ops_am;i++)
{
//suche nach: "()"
if(ops[i]=='(' && ops[i+1]==')')
{
for(int j=i;j<*ops_am;j++)
{
ops[j]=ops[j+2];
}
*ops_am = *ops_am-2;
}
}
int max_klammer=0,curr_klammer=0;
int max_klammer_p=0;
for(i=0;i<*ops_am;i++)
{
if(ops[i]=='(')curr_klammer++;
else if(ops[i]==')')curr_klammer--;
if(curr_klammer>max_klammer)
{
max_klammer=curr_klammer;
max_klammer_p=i;
}
}
//nicht aller klammern vom Benutzer geschlossen
if(curr_klammer>0)
{
int a;
for(a=0;a<curr_klammer;a++)
{
ops[*ops_am+a]=')';
}
ops_am+=a;
}
//zuviele Klammern geschlossen
else if(curr_klammer<0) return -2;
//tiefste Klammerebenen Bearbeiten
if(max_klammer>0)
{
//NOT vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
else if(ops[max_klammer_p+i]=='!')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
//Punktrechnung vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
else if(ops[max_klammer_p+i]=='*' ||
ops[max_klammer_p+i]=='/')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
//Strichrechnung vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
if(ops[max_klammer_p+i]=='+' ||
ops[max_klammer_p+i]=='-')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
//[Größer/kleiner]-[un/gleich] vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
else if(ops[max_klammer_p+i]=='g' ||
ops[max_klammer_p+i]=='k' ||
ops[max_klammer_p+i]=='>' ||
ops[max_klammer_p+i]=='<' ||
ops[max_klammer_p+i]=='u' ||
ops[max_klammer_p+i]=='=')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
//AND vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
else if(ops[max_klammer_p+i]=='&')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
//OR vorhanden? -> einen Auflösen
for(i=0;1;i++)
{
if(ops[max_klammer_p+i]==')')break;
else if(ops[max_klammer_p+i]=='|')
{
execute_symbol(vals, ops, vals_am, ops_am, max_klammer_p+i);
return 1;
}
}
}
//keine Klammern gefunden
else
{
//NICHT (NOT) vorhanden?
for(i=0;1;i++)
{
if(i==*ops_am)break;
if(ops[i]=='!')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
//Punktrechnung vorhanden?
for(i=0;1;i++)
{
if(i==*ops_am)break;
if(ops[i]=='*' ||
ops[i]=='/')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
//strichrechnung vorhanden?
for(i=0;1;i++)
{
if(i>=*ops_am)break;
if(ops[i]=='+' ||
ops[i]=='-')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
//[Größer/kleiner]-[un/gleich] vorhanden?
for(i=0;1;i++)
{
if(i>=*ops_am)break;
if(ops[i]=='g' ||
ops[i]=='k' ||
ops[i]=='>' ||
ops[i]=='<' ||
ops[i]=='u' ||
ops[i]=='=')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
//UND vorhanden?
for(i=0;1;i++)
{
if(i>=*ops_am)break;
if(ops[i]=='&')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
//ODER vorhanden?
for(i=0;1;i++)
{
if(i>=*ops_am)break;
if(ops[i]=='|')
{
execute_symbol(vals, ops, vals_am, ops_am, i);
return 1;
}
}
}
return -1;
}
double eval(char *exp)
{
//alle Leerzeichen entfernen
unsigned int laenge = strlen(exp);
char *temp = (char*) malloc(sizeof(char)*laenge);
int a=0;
for(int i=0;1;i++)
{
if(exp[i]!=' ')
{
temp[a]=exp[i];
a++;
}
if(temp[a]=='\0' || temp[a]=='\n')
{
temp[a]='\0';
break;
}
}
strcpy(exp,temp);
//printf("|exp:'%s'\n",exp);
//getch();
double vals[EVAL_MAX];
char ops[EVAL_MAX];
int vals_am=0,ops_am=0;
//alle zahlenwerte einlesen
char *p;
for(int k=0;1;k++)
{
if(exp[k]>=48 && exp[k]<=57)
{
vals[0] = strtod(&exp[k],&p);
break;
}
else if(k>=laenge)
{
printf("kein gueltiger mathematischer Ausdruck!");
return 0.0;
}
}
for(vals_am=1;vals_am<EVAL_MAX;vals_am++)
{
if(*p=='\0')break; //ende des Ausdrucks
//Überspringe Klammern und Rechenzeichen
while(1)
{
//drei Zeichen: AND
if(*p=='A'&& *(p+sizeof(char))=='N'&& *(p+2*sizeof(char))=='D')
{p += 3*sizeof(char); break;}
//zwei Zeichen: <= >= OR == <>
else if(
*p=='<' && *(p+sizeof(char))=='='
|| *p=='>' && *(p+sizeof(char))=='='
|| *p=='=' && *(p+sizeof(char))=='='
|| *p=='<' && *(p+sizeof(char))=='>'
|| *p=='O' && *(p+sizeof(char))=='R')
{p += 2*sizeof(char); break;}
//Ein Zeichen: ( ) + - * / ! < >
if(*p=='(' || *p==')' ||*p=='+' || *p=='-' ||*p=='*' || *p=='/' ||*p=='!' ||*p=='<' || *p=='>')
{p += sizeof(char); break;}
//printf("Vergleiche: %c,%c,%c\n",*p,*(p+sizeof(char)),*(p+2*sizeof(char)));
}
char *d;
vals[vals_am] = strtod(p, &d);
p=d;
}
int n;
//alle Operationen einlesen:
ops_am=0;
for(n=0;ops_am<EVAL_MAX;n++)
{
if(exp[n]=='\0')break;
else if(exp[n]=='(' ||
exp[n]==')' ||
exp[n]=='+' ||
exp[n]=='-' ||
exp[n]=='*' ||
exp[n]=='/')
{
//printf("exp[%i]=%c\n",n,exp[n]);
ops[ops_am]=exp[n];
ops_am++;
}
else if(exp[n]=='A' && exp[n+1]=='N' && exp[n+2]=='D')
{
ops[ops_am]='&';
n+=2;
ops_am++;
}
else if(exp[n]=='O' && exp[n+1]=='R')
{
ops[ops_am]='|';
n++;
ops_am++;
}
else if(exp[n]=='N' && exp[n+1]=='O' && exp[n+2]=='T')
{
ops[ops_am]='!';
n+=2;
ops_am++;
}
else if(exp[n]=='>' && exp[n+1]=='=')
{
ops[ops_am]='g';
n++;
ops_am++;
}
else if(exp[n]=='<' && exp[n+1]=='=')
{
ops[ops_am]='k';
n++;
ops_am++;
}
else if(exp[n]=='<' && exp[n+1]=='>')
{
ops[ops_am]='u';
n++;
ops_am++;
}
else if(exp[n]=='=' && exp[n+1]=='=')
{
ops[ops_am]='=';
n++;
ops_am++;
}
else if(exp[n]=='>')
{
ops[ops_am]='>';
n++;
ops_am++;
}
else if(exp[n]=='<')
{
ops[ops_am]='<';
n++;
ops_am++;
}
}
/*
gotoxy(1,11);
printf("Berechnung:%s \n",exp);
printf("%i Werte:",vals_am);
for(i=0;i<vals_am;i++)
{
printf("%lf,",vals[i]);
}
printf(" \n%i Ops:",ops_am);
for(i=0;i<ops_am;i++)
{
printf("%c,",ops[i]);
}
//*/
//den Ausdruck sooft vereinfachen, bis nur noch eine Zahl überig ist
while(1)
{
//den Ausdruck 1x vereinfachen
int c=simplify(vals, ops, &vals_am, &ops_am);
//Ausdruck besteht nur noch aus einem Wert -> ende
//ODER: Fehler bei a<0
if(c<=0) break;
//printf("values:%i",vals_am);
}
if(a<0)
{
if(a==-2)printf("Ungueltige Klammerbilanz");
return 0.0;
}
//printf(" \nErgebnis: %lf ",vals[0]);
return vals[0];
}