home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / maj / 4331 / strings.exe / STRCALC.C < prev    next >
C/C++ Source or Header  |  1993-07-14  |  6KB  |  232 lines

  1. /*  Copyright (C) 1993   Marc Stern  (internet: stern@mble.philips.be)  */
  2.  
  3. #include "strings.h"
  4. #include <math.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7.  
  8.  
  9. /*
  10.    Functions :   get_expr
  11.                  fetch_operand
  12.                  simplify
  13.                  strcalc
  14.  
  15. */
  16.  
  17. static char *string;
  18. static long double near get_expr( void );
  19. static long double near fetch_operand( void );
  20.  
  21. enum { NEQ = 200,  /*        not equal */
  22.        GOE,        /* greater or equal */
  23.        LOE         /*   lower or equal */
  24.      };
  25.  
  26.  
  27. static char * near simplify( char *number )
  28. {
  29.  int point = 0;
  30.  char *ptr1 , *ptr2;
  31.  
  32.  for ( ptr1 = ptr2 = number; *ptr1; ptr1 ++ )
  33.     {
  34.      if ( *ptr1 != '0' ) ptr2 = ptr1;
  35.      if ( *ptr1 == '.' ) point = 1;
  36.     }
  37.  
  38.  if ( point ) *(ptr2 + 1) = '\0';
  39.  if ( *ptr2 == '.' ) *ptr2 = '\0';
  40.  
  41.  return number;
  42. }
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. /*******************************************************
  51.  *
  52.  * Function     : get_expr
  53.  * Topic        : evaluate a mathematical expression
  54.  * Return       : value of the expression or HUGE_VAL
  55.  * Input        : string pointer (static variable)
  56.  * Side-effects : string will begin after expression
  57.  *
  58.  *******************************************************
  59.  */
  60.  
  61. long double near get_expr( void )
  62. {
  63.  long double operand1 , operand2 , result = 0;
  64.  int operator1 = '+' , operator2;
  65.  
  66.  for ( ; *string; string++ )
  67.     {
  68.      operand1 = fetch_operand();
  69.      if ( operand1 == HUGE_VAL ) return HUGE_VAL;
  70.  
  71.      operator2 = *string;
  72.      while ( (*string == '^') || (*string == '*') || (*string == '/') || (*string == '%') || (*string == '<') || (*string == '>') || (*string == '=') || (*string == '!') )
  73.         {
  74.          string++;
  75.  
  76.          if ( *string == '=' )
  77.             switch( operator2 )
  78.         {
  79.          case '>' : operator2 = GOE; string++; break;
  80.          case '<' : operator2 = LOE; string++; break;
  81.          case '=' : operator2 = '='; string++; break;
  82.         }
  83.  
  84.      if ( ((operator2 == '<') && (*string == '>')) ||
  85.               ((operator2 == '!') && (*string == '='))
  86.             )
  87.             {
  88.              operator2 = NEQ;
  89.              string++;
  90.             }
  91.  
  92.          operand2 = fetch_operand();
  93.      if ( operand2 == HUGE_VAL ) return HUGE_VAL;
  94.  
  95.           switch( operator2 )
  96.           {
  97.            case '^' : operand1 = pow( operand1, operand2); break;
  98.            case '*' : operand1 *= operand2; break;
  99.            case '/' : operand1 /= operand2; break;
  100.            case '%' : operand1 = (long double) ( (int) operand1 % (int) operand2 ); break;
  101.            case '=' : operand1 = (operand1 == operand2); break;
  102.            case '>' : operand1 = (operand1 > operand2); break;
  103.            case GOE : operand1 = (operand1 >= operand2); break;
  104.            case '<' : operand1 = (operand1 < operand2); break;
  105.            case LOE : operand1 = (operand1 <= operand2); break;
  106.            case NEQ : operand1 = (operand1 != operand2); break;
  107.           }
  108.  
  109.           operator2 = *string;
  110.         }
  111.  
  112.      if ( operator1 == '+' ) result += operand1;
  113.                         else result -= operand1;
  114.  
  115.      if ( (! *string) || (operator2 == ')') ) break;
  116.      operator1 = operator2;
  117.     }
  118.  
  119.  return result;
  120. }
  121.  
  122.  
  123.  
  124. /*******************************************************
  125.  *
  126.  * Function     : fetch_operand
  127.  * Topic        : fetch one operand or (...)
  128.  * Return       : value of the operand or (...)
  129.  * Input        : string pointer (static variable)
  130.  * Side-effects : string will begin after expression
  131.  *
  132.  *******************************************************
  133.  */
  134.  
  135. long double near fetch_operand( void )
  136. {
  137.  long double result;
  138.  char op_str[255] , *operand;
  139.  
  140.  if ( *string == '(' )
  141.     {
  142.      string++;
  143.      result = get_expr();
  144.      if ( (result == HUGE_VAL) || (*string != ')') ) return HUGE_VAL;  /* ) missing */
  145.      string++;
  146.     }
  147.  else
  148.     {
  149.      operand = op_str;
  150.      if ( *string == '-' ) *operand++ = *string++;
  151.  
  152.      while ( *string && (isxdigit(*string) || (*string == '.')) )
  153.         *operand++ = *string++;
  154.  
  155.      *operand = '\0';
  156.      if ( toupper(*string) == 'H' )
  157.         {
  158.          long hexa;
  159.          string++;
  160.          if ( sscanf(op_str, "%lx", &hexa) != 1 ) return HUGE_VAL;  /*  empty value or too large  */
  161.          result = hexa;
  162.         }
  163.      else if ( sscanf(op_str, "%Lf", &result) != 1 ) return HUGE_VAL;  /*  empty value or too large  */
  164.     }
  165.  
  166.  switch( *string )
  167.  {
  168.   case '\0':
  169.   case ')' :
  170.   case '+' :
  171.   case '-' :
  172.   case '^' :
  173.   case '*' :
  174.   case '/' :
  175.   case '%' :
  176.   case '<' :
  177.   case '>' :
  178.   case '!' :
  179.   case '=' : break;
  180.  
  181.   default  : return HUGE_VAL;   /*  Bad operator  */
  182.  }
  183.  
  184.  return result;
  185. }
  186.  
  187.  
  188.  
  189. /***
  190.  *  Function    :  strcalc
  191.  *
  192.  *  Description :  Mathematical expression evaluation 
  193.  *
  194.  *  Parameters  :  in/out   char *   calcul      expression to calculate
  195.  *
  196.  *  Values      :  Allowed operators : 
  197.  *                    + - * / () = < > <= >= <> (or !=)  on floats
  198.  *                    %                                  on ints
  199.  *
  200.  *  Return      :  result   if OK
  201.  *                 HUGE_VAL if error  
  202.  *
  203.  *  Remark      :  Hexadecimal numbers must be followed by 'H'
  204.  *
  205.  *  OS/Compiler :  All
  206.  ***/
  207.  
  208.  
  209. long double strcalc( char *calcul )
  210. {
  211.  long double result;
  212.  char *ptr1 , *ptr2;
  213.  
  214.  for ( ptr1 = ptr2 = calcul; *ptr1; *ptr1++ = *ptr2++ )
  215.     while ( *ptr2== ' ' || *ptr2== '\t' ) ptr2++;
  216.  
  217.  *ptr2 = '\0';
  218.  
  219.  string = calcul;
  220.  
  221.  result = get_expr();
  222.  
  223.  if ( result == HUGE_VAL ) *calcul = '\0';
  224.  else {
  225.        /*  suppress trailing '0' (and final '.')  */
  226.        sprintf( calcul , "%Lf" , result );
  227.        simplify( calcul );
  228.       }
  229.  
  230.  return result;
  231. }
  232.