home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1993 Marc Stern (internet: stern@mble.philips.be) */
-
- #include "strings.h"
- #include <math.h>
- #include <ctype.h>
- #include <stdio.h>
-
-
- /*
- Functions : get_expr
- fetch_operand
- simplify
- strcalc
-
- */
-
- static char *string;
- static long double near get_expr( void );
- static long double near fetch_operand( void );
-
-
-
- static char * near simplify( char *number )
-
- { char point = 0;
- char *ptr1 , *ptr2;
-
- for ( ptr1 = ptr2 = number; *ptr1; ptr1 ++ )
- {
- if ( *ptr1 != '0' ) ptr2 = ptr1;
- if ( *ptr1 == '.' ) point = 1;
- }
-
- if ( point ) *(ptr2 + 1) = '\0';
- if ( *ptr2 == '.' ) *ptr2 = '\0';
-
- return number;
- }
-
-
-
-
-
-
-
- /*******************************************************
- *
- * 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( void )
- {
- 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( void )
- {
- 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;
- }
-
-
-
- /***
- * Function : strcalc
- *
- * Description : Mathematical expression evaluation
- *
- * Parameters : in/out char * calcul expression to calculate
- *
- * Values : Allowed operators : + - * / () = < > <= >= <> on floats
- * % on ints
- *
- * Return : result if OK
- * HUGE_VAL if error
- *
- * OS/Compiler : All
- ***/
-
-
- long double strcalc( 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;
- }
-