home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1993 Marc Stern (internet: stern@mble.philips.be)
- *
- * CALC
- *
- * Topic : Mathematical expression evaluation
- *
- * Allowed operators : + - * / () = < > <= >= <> on floating point numbers
- * % on integer numbers
- *
- */
-
-
-
-
- #include "calc.h"
- #include <math.h>
- #include <ctype.h>
- #include <stdio.h>
-
-
-
- static long double near get_expr( ) ;
- static long double near fetch_operand( ) ;
-
-
-
- static char *string ;
-
-
-
-
-
- /*******************************************************
- *
- * Function : get_expr
- * Topic : evaluate a mathematical expression
- * Return : value of the expression or HUGE_VAL
- * Input : string pointer (static variable)
- * Side-effects : string will begin after expression
- *
- *******************************************************
- */
-
- long double near get_expr( )
-
- {
- long double operand1 , operand2 , result = 0 ;
- char operator1 = '+' , operator2 ;
-
- for ( ; *string ; string++ )
- {
- operand1 = fetch_operand() ;
- if ( operand1 == HUGE_VAL ) return(HUGE_VAL) ;
-
- operator2 = *string ;
- while ( (*string == '*') || (*string == '/') || (*string == '%') || (*string == '<') || (*string == '>') || (*string == '=') )
- {
- string++ ;
-
- if ( *string == '=' )
- switch( operator2 )
- {
- case '>' : operator2 = '≥' ; string++ ; break ;
- case '<' : operator2 = '≤' ; string++ ; break ;
- case '=' : operator2 = '=' ; string++ ; break ;
- }
-
- if ( (operator2 == '<') && (*string == '>') )
- {
- operator2 = '≡' ;
- string++ ;
- }
-
- operand2 = fetch_operand() ;
- if ( operand2 == HUGE_VAL ) return(HUGE_VAL) ;
-
- switch( operator2 )
- {
- case '*' : operand1 *= operand2 ; break ;
- case '/' : operand1 /= operand2 ; break ;
- case '%' : operand1 = (long double) ( (int) operand1 % (int) operand2 ) ; break ;
- case '=' : operand1 = (operand1 == operand2) ; break ;
- case '>' : operand1 = (operand1 > operand2) ; break ;
- case '≥' : operand1 = (operand1 >= operand2) ; break ;
- case '<' : operand1 = (operand1 < operand2) ; break ;
- case '≤' : operand1 = (operand1 <= operand2) ; break ;
- case '≡' : operand1 = (operand1 != operand2) ; break ;
- }
- operator2 = *string ;
- }
- if ( operator1 == '+' ) result += operand1 ;
- else result -= operand1 ;
- if ( (! *string) || (operator2 == ')') ) break ;
- operator1 = operator2 ;
- }
-
- return( result ) ;
- }
-
-
- /*******************************************************
- *
- * Function : fetch_operand
- * Topic : fetch one operand or (...)
- * Return : value of the operand or (...)
- * Input : string pointer (static variable)
- * Side-effects : string will begin after expression
- *
- *******************************************************
- */
-
- long double near fetch_operand()
-
- {
- long double result ;
- char op_str[255] , *operand ;
-
- if ( *string == '(' ) { string++ ;
- result = get_expr() ;
- if ( (result == HUGE_VAL) || (*string != ')') )
- return(HUGE_VAL) ; /* ) missing */
- string++ ;
- }
- else { operand = op_str ;
- if ( *string == '-' ) *operand++ = *string++ ;
- while ( *string && (isdigit(*string) || (*string == '.')) )
- *operand++ = *string++ ;
- *operand = '\0' ;
- if ( sscanf(op_str , "%Lf" , &result) != 1 )
- return(HUGE_VAL) ; /* empty value or too large */
- }
-
- switch( *string ) { case '\0':
- case ')' :
- case '+' :
- case '-' :
- case '*' :
- case '/' :
- case '%' :
- case '<' :
- case '>' :
- case '=' :
- break ;
-
- default : return(HUGE_VAL) ; /* Bad operator */
- }
-
- return(result) ;
- }
-
-
- long double calc( char *calcul )
-
- { long double result ;
- char *ptr1 , *ptr2 ;
-
- for ( ptr1 = ptr2 = calcul ; *ptr1 ; *ptr1++ = *ptr2++ )
- while ( *ptr2== ' ' || *ptr2== '\t' ) ptr2++ ;
-
- *ptr2 = '\0' ;
-
- string = calcul ;
-
- result = get_expr() ;
-
- if ( result == HUGE_VAL ) *calcul = '\0' ;
- else { /* suppress trailing '0' (and final '.') */
- sprintf( calcul , "%Lf" , result ) ;
- simplify( calcul ) ;
- }
- return(result) ;
- }
-