tyrion

calc.c

Jan 5th, 2012
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.28 KB | None | 0 0
  1. /*
  2.  * calc.c : Simple command line calculator.
  3.  * calc executes simple operations read from an input string.
  4.  * The string can be supplied either as the first command line argument or by
  5.  * calling "calc_parse" manually.
  6.  *
  7.  * EBNF for math:
  8.  * <expression> ::= ( <expression> <operator> <expression> ) |
  9.  *                  ( <number> <operator> <number> )
  10.  * <operator> ::= "+" | "-" | "/" | "*"
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16.  
  17. // The macro _WIN32 must be defined when compiling for windows (gcc -D _WIN32 1).
  18. #ifdef _WIN32
  19.   #define SEP '\\'
  20. #else
  21.   #define SEP '/'
  22. #endif
  23.  
  24.  
  25. typedef enum { CALC_OK, CALC_ESYNTAX, CALC_EOPER } CalcError_t;
  26.  
  27.  
  28. void calc_strerror( CalcError_t errno ) {
  29.     switch (errno) {
  30.         case CALC_ESYNTAX:
  31.             return (void) fputs("CALC: Syntax Error", stderr);
  32.         case CALC_EOPER:
  33.             return (void) fputs("CALC: Invalid Operator", stderr);
  34.     }
  35. }
  36.  
  37. CalcError_t calc_parse(char *string, double *result) {
  38.     int count, pos = -1;
  39.     double res, a;
  40.     char op;
  41.     CalcError_t error = CALC_OK;
  42.  
  43.    
  44.     count = sscanf(string, " %lf %c %lf%n", &res, &op, &a, &pos);
  45.  
  46.     if (count == EOF) return CALC_OK;
  47.     if (count != 3) return CALC_ESYNTAX;
  48.  
  49.     do {
  50.         switch (op) {
  51.             case '+':
  52.                 res += a; break;
  53.             case '-':
  54.                 res -= a; break;
  55.             case '*':
  56.                 res *= a; break;
  57.             case '/':
  58.                 res /= a; break;
  59.             default:
  60.                 return CALC_EOPER;
  61.         }
  62.         string += pos;
  63.         count = sscanf(string, " %c %lf%n", &op, &a, &pos);
  64.     } while (count == 2);
  65.  
  66.  
  67.     if (count != EOF) return CALC_ESYNTAX;
  68.     *result = res;
  69.     return CALC_OK;
  70.  
  71. }
  72.  
  73. int main(int argc, char *argv[]) {
  74.  
  75.     if (argc == 1) {
  76.         char *name = strrchr(argv[0], SEP);
  77.         name = name != NULL ? ++name : argv[0];
  78.         fprintf(stderr, "Usage: %s expressions...\n"
  79.                 "Example: %s \"12.2 * 73 - 4.5\"\n", name, name);
  80.         return 1;
  81.     }
  82.  
  83.     double res = 0;
  84.     CalcError_t error;
  85.  
  86.     error = calc_parse(argv[1], &res);
  87.  
  88.     if (error != CALC_OK) {
  89.         calc_strerror( error );
  90.         return 1;
  91.     }
  92.    
  93.     printf("Result: %g", res);
  94.     return 0;
  95.  
  96. }
Advertisement
Add Comment
Please, Sign In to add comment