home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 9
/
CD_ASCQ_09_1193.iso
/
maj
/
4331
/
strings.exe
/
STRCALC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-14
|
6KB
|
232 lines
/* 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 );
enum { NEQ = 200, /* not equal */
GOE, /* greater or equal */
LOE /* lower or equal */
};
static char * near simplify( char *number )
{
int 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;
int 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 == '=') || (*string == '!') )
{
string++;
if ( *string == '=' )
switch( operator2 )
{
case '>' : operator2 = GOE; string++; break;
case '<' : operator2 = LOE; string++; break;
case '=' : operator2 = '='; string++; break;
}
if ( ((operator2 == '<') && (*string == '>')) ||
((operator2 == '!') && (*string == '='))
)
{
operator2 = NEQ;
string++;
}
operand2 = fetch_operand();
if ( operand2 == HUGE_VAL ) return HUGE_VAL;
switch( operator2 )
{
case '^' : operand1 = pow( operand1, operand2); break;
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 GOE : operand1 = (operand1 >= operand2); break;
case '<' : operand1 = (operand1 < operand2); break;
case LOE : operand1 = (operand1 <= operand2); break;
case NEQ : 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 && (isxdigit(*string) || (*string == '.')) )
*operand++ = *string++;
*operand = '\0';
if ( toupper(*string) == 'H' )
{
long hexa;
string++;
if ( sscanf(op_str, "%lx", &hexa) != 1 ) return HUGE_VAL; /* empty value or too large */
result = hexa;
}
else 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 '>' :
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 :
* + - * / () = < > <= >= <> (or !=) on floats
* % on ints
*
* Return : result if OK
* HUGE_VAL if error
*
* Remark : Hexadecimal numbers must be followed by 'H'
*
* 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;
}