Zahl und Operator Erkenner



  • volkard schrieb:

    Schon den Parser von Prof. Dankert gelesen?

    google spuckt http://www.rzbt.haw-hamburg.de/dnksoft/cammpus/parser.html aus.
    Soll ich jetzt die Quellcodes analysieren?



  • 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...


Anmelden zum Antworten