Zahl und Operator Erkenner
-
bashzeronine schrieb:
Soll ich jetzt die Quellcodes analysieren?
Sollen wir das lieber für dich machen?
-
_matze schrieb:
bashzeronine schrieb:
Soll ich jetzt die Quellcodes analysieren?
Sollen wir das lieber für dich machen?
Du solltest dir vielleicht was eigenes überlegen,
oder die Dokumentation lesen.
-
Und wo ist die Dokumentation zu finden?
-
Außerdem bat ich um eine oder mehrere geeignete Funktionen, mit dem ich z. B. Stringstellen vergleichen kann etc.
-
Außerdem bat ich um eine oder mehrere geeignete Funktionen, mit dem ich z. B. Stringstellen vergleichen kann etc.
Und ich bitte dich:
Erstens darum das du mal die augen aufmachst und selbst guckst
und zweitens das du dir erstmal selbst gedanken machst und mal etwas ausprobierst.
-
Ich empfehle da ja immer flex und bison mit einem umfangreichen Tutorial und vielen Beispielen ...
-
volkard schrieb:
Schon den Parser von Prof. Dankert gelesen?
knivil schrieb:
Ich empfehle da ja immer flex und bison mit einem umfangreichen Tutorial und vielen Beispielen ...
das ist doch alles masslos übertrieben.
@bashzeronine: hier ist was einfacheres: http://gd.tuwien.ac.at/languages/c/cref-mleslie/CONTRIB/SNIP/eval.c
-
Außerdem bat ich um eine oder mehrere geeignete Funktionen, mit dem ich z. B. Stringstellen vergleichen kann etc.
Das geht mit man: strcmp und man: memcmp.
-
Rekursiv kann man die verschachtelten Klammern auflösen:
#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <time.h> #include <ctype.h> static char* s = NULL; #define NAMELEN_MAX 16 #define isop(x) x == '*' || x == '/' || x == ':' || x == '^' #define issig(x) x == '+' || x == '-' #define isval(x) x >= '0' && x <= '9' || x == '.' #define iscomma(x) x == ',' #define isname(x) x >= 'a' && x <= 'z' || x >= 'A' && x <= 'Z' || x == '_' #define namechar(x) isname(x) || x >= '0' && x <= '9' #define isop_rightassociative(x) x == '^' typedef struct { char fname[NAMELEN_MAX+1]; double (*pf) (double); }Function; Function functions[]= { { "abs", fabs }, { "acos", acos }, { "asin", asin }, { "atan", atan }, { "cos", cos }, { "cosh", cosh }, { "exp", exp }, { "log", log }, { "log10", log10 }, { "sin", sin }, { "sinh", sinh }, { "sqrt", sqrt }, { "tan", tan }, { "tanh", tanh } }; double parse (); double parse_operator (double lv, char op); Function* function_ptr ( char* fname ) { int first = 0; int last = sizeof(functions)/sizeof(*functions) -1; int i = 0; int cmp = 0; while( first <= last ) { i = ( first + last )/2; cmp = strcmp(fname, functions[i].fname ); if ( cmp < 0 ) last = i-1; else if ( cmp > 0 ) first = i+1; else { return &functions[i]; } } printf ("%s not found.\n", fname ); return 0; } int function_name (char* buf, int size) { int imax = size-1, i = 0; memset(buf, 0, size); while ( i <= imax && namechar(*s) ) buf[i++] = *s++; if ( namechar(*s) ) { printf ("function_name: expression too long, " "started with %s\n", buf); return 1; } return 0; } double value () { char* stopstr = NULL; double value = strtod( s, &stopstr ); if ( stopstr == s ) { printf("Syntax error: %s\n", s ); exit(1); } s = stopstr; return value; } int sigval (char c) { if (c=='+') return 1; else return -1; } double do_function () { Function* fptr = NULL; double value = 0.0; char fname [NAMELEN_MAX+1] = {0}; if ( function_name(fname, sizeof(fname))) exit(1); if ( NULL == (fptr = function_ptr(fname))) exit(1); while(isspace(*s)) s++; if (*s != '(') { printf ("do_function: '(' expected.\n"); exit(1); } else { value = parse(); } return fptr->pf(value); } double do_operation ( double lv, char op, double rv ) { switch(op) { case '+': lv = lv + rv; break; case '-': lv = lv - rv; break; case '/': lv = lv/rv; break; case ':': lv = lv/rv; break; case '^': lv = pow(lv,rv); break; case '*': lv = lv * rv; break; default: printf( "Unknown operator: %c\n", op ); exit(1); } return lv; } int priority ( char op ) { int priority = -1; switch(op) { case '+': priority = 1; break; case '-': priority = 1; break; case '*': priority = 2; break; case '/': priority = 2; break; case ':': priority = 2; break; case '^': priority = 3; break; default: printf( "Unknown operator: %c\n", op ); exit(1); } return priority; } double check_op (char op, char nop, double lv, double rv) { if( priority(op) >= priority(nop) && !(op == nop && isop_rightassociative(op))) { lv = do_operation (lv, op, rv); } else { rv = parse_operator(rv, nop); lv = do_operation (lv, op, rv); } return lv; } double parse_operator (double lv, char op) { char nop = 0, r = 0; // Flags. double rv = 0.0; while (*s) { if (isspace(*s)) { s++; continue; } if (*s == '(') { s++; rv = parse(); r = 1; s++; continue; } if (isval(*s)) { rv = value(); r = 1; continue; } if (isname(*s)) { rv = do_function(); r = 1; continue; } if (issig(*s)) { if (!r) { rv = sigval(*s); r = 1; nop = '*'; } else { nop = *s; } } if (op && nop) { lv = check_op (op,nop,lv,rv); op = nop; nop = r = 0; } s++; } // while(s) if (r) lv = do_operation ( lv, op, rv ); return lv; } double parse () { double lv=0.0, rv=0.0; char op = 0, nop = 0, l = 0, r = 0; // Flags. while (*s) { if (isspace(*s)) { s++; continue; } if ( *s == ')' ) break; if ( *s == '(' ) { s++; if (!l) { lv = parse(); l = 1; } else { rv = parse(); r = 1; } s++; continue; } if (isval(*s)) { if (!l) { lv = value(); l = 1; } else { rv = value(); r = 1; } continue; } if (isname(*s)) { if (!l) { lv = do_function(); l = 1; } else { rv = do_function(); r = 1; } continue; } if (issig(*s)) { if (!l) { lv = sigval(*s); l = 1; op = '*'; s++; continue; } if (!op) { op = *s; s++; continue; } if (!r) { rv = sigval(*s); r = 1; nop = '*'; } else { nop = *s; } } if (isop(*s)) { if(!op) op = *s; else nop = *s; } if (op && nop) { lv = check_op (op,nop,lv,rv); op = nop; nop = r = 0; } s++; } // while(s) if (r) lv = do_operation ( lv, op, rv ); return lv; } double evaluate (char* expr) { s = expr; return parse(); } int main (void) { double value; char* s; s = "10 ^ cos ( 1 )"; value = evaluate (s); printf("%lf\n", value); s = "1*(1*(1*(1*(1)*1)*1)*1)*1"; value = evaluate (s); printf("%lf\n", value); s = "2^1^2"; value = evaluate (s); printf("%lf\n", value); s = "2*(3*(4*(1+1)))"; value = evaluate (s); printf("%lf\n", value); s = "((((1)*1)*1)*1)"; value = evaluate (s); printf("%lf\n", value); s = " 10 ^ ( 1.1 + .9 )"; value = evaluate (s); printf("%lf\n", value); return 0; }
Hier müsste man noch einen Syntaxcheck vorschalten.
Gruß,
B.B.
-
Hier müsste man noch einen Syntaxcheck vorschalten.
Das müsste man erst mal lesen...