fork download
  1. /* ===========================================================
  2.  * DUMMY CALC 1.0, by migf1
  3.  *
  4.  * A dummy calculator, just to demonstrate the use of a jump-table
  5.  * consisting of function pointers, in ANCI C. No overflow checks, no
  6.  * operator priorities, no parentheses... just dummy cumulative calcs
  7.  * with an operator and an operand per line (some operators are unary
  8.  * so they ignore the operand and are applied to the previous result.
  9.  *
  10.  * 15 Supported Operators:
  11.  *
  12.  * addition (+)
  13.  * subtraction (-)
  14.  * multiplication (*)
  15.  * division (/)
  16.  * modulus (%)
  17.  * power (^)
  18.  * exponent of e (e) unary
  19.  * square root (@) unary
  20.  * cube root (#) unary
  21.  * negation (~) unary
  22.  * factorial (!) unary
  23.  * natural log (') unary
  24.  * base-10 log (") unary
  25.  * integral part (_) unary
  26.  * fractional part (.) unary
  27.  *
  28.  * Type h inside the program for help
  29.  * ===========================================================
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <math.h>
  35.  
  36. // -- Macros ----------------
  37.  
  38. #define MAXINBUF (255+1)
  39. #define MAXOPS 15 // max number of supported ops
  40.  
  41. // --- Custom Types ----------
  42.  
  43. typedef enum { FALSE=0, TRUE } Bool; // our custom boolean type
  44. typedef enum { // operator codes
  45. ADD, SUB, MUL, DIV, MOD, POW, EXPO, SQRT, CBRT, NEG,
  46. FACT, LOGE, LOGTEN, TRUNC, FRAC
  47. } OpCode;
  48.  
  49. typedef struct opstruct { // operator structure
  50. char symbol; // a single char
  51. OpCode code; // corersponding code
  52. Bool unary; // UNUSED: is unary operator?
  53. } OpStruct;
  54.  
  55. // -------------------------------------------------------------------------------------
  56. void help( void )
  57. {
  58. puts("\n\tcommands are case sensitive");
  59. puts("\tx\t: exit");
  60. puts("\tc\t: clear result");
  61. puts("\t~\t: -result\t\tNegation");
  62. puts("\t!\t: result!\t\tFactorial");
  63. puts("\t_\t: trunc( result )\tTruncate Integral Part");
  64. puts("\t.\t: fractional( result )\tFractional Part of Result");
  65. puts("\te\t: exp( result )\t\tExponent of Result");
  66. puts("\t'\t: log( result )\t\tNatural Logarithm");
  67. puts("\t\"\t: log10( result )\tBase 10 Logarithm");
  68. puts("\t@\t: sqrt( result )\tSquare Root");
  69. puts("\t#\t: cbrt( result )\tCube Root");
  70. puts("\t+ num\t: result + num\t\tAddition");
  71. puts("\t- num\t: result - num\t\tSubtraction");
  72. puts("\t* num\t: result * num\t\tMultiplication");
  73. puts("\t/ num\t: result / num\t\tDivision");
  74. puts("\t% num\t: result % num\t\tModulus (remainder)");
  75. puts("\t^ num\t: result ^ num\t\tPower");
  76. putchar('\n');
  77.  
  78. return;
  79. }
  80.  
  81. // Functions for Supported Operations (some of them only use their first argument)
  82.  
  83. // -------------------------------------------------------------------------------------
  84. double add( const double x, const double y ) // addition
  85. { return x + y; }
  86. // -------------------------------------------------------------------------------------
  87. double sub( const double x, const double y ) // subtraction
  88. { return x - y; }
  89. // -------------------------------------------------------------------------------------
  90. double mul( const double x, const double y ) // multiplication
  91. { return x * y; }
  92. // -------------------------------------------------------------------------------------
  93. double over( const double x, const double y ) // division
  94. { return y != 0 ? x/y : 0; }
  95. // -------------------------------------------------------------------------------------
  96. double modulus( const double x, const double y ) // x modulus y
  97. { return y != 0 ? fmod(x, y) : 0; }
  98. // -------------------------------------------------------------------------------------
  99. double pwr( const double x, const double y ) // power: x at y
  100. { return pow(x, y); }
  101. // -------------------------------------------------------------------------------------
  102. double expo( const double x, const double y ) // power: e at x
  103. { return exp(x); }
  104. // -------------------------------------------------------------------------------------
  105. double sqroot( const double x, const double y ) // square root of x
  106. { return x < 1 ? 0 : sqrt(x); }
  107. // -------------------------------------------------------------------------------------
  108. double cbroot( const double x, const double y ) // cube root of x
  109. { return cbrt(x); }
  110. // -------------------------------------------------------------------------------------
  111. double neg( const double x, const double y ) // negation of x
  112. { return x != 0 ? -x : 0; }
  113. // -------------------------------------------------------------------------------------
  114. double fact( const double x, const double y ) // factorial of x
  115. { return x < 2 ? 1 : x * fact(x-1, 0.0); }
  116. // -------------------------------------------------------------------------------------
  117. double loge( const double x, const double y ) // natural log of x
  118. { return x < 1 ? 0 : log(x); }
  119. // -------------------------------------------------------------------------------------
  120. double logten( const double x, const double y ) // base-10 log of x
  121. { return x < 1 ? 0 : log10(x); }
  122. // -------------------------------------------------------------------------------------
  123. double truncate( const double x, const double y ) // integral part of x
  124. { return trunc(x); }
  125. // -------------------------------------------------------------------------------------
  126. double frac( const double x, const double y ) // fractional part of x
  127. { return x - trunc(x); }
  128.  
  129. // -------------------------------------------------------------------------------------
  130. // Return the operator code that corresponds to sym, or -1 on failure
  131. //
  132. OpCode sym2opcode( const char sym, const OpStruct *tabops )
  133. {
  134. int i;
  135. for (i=0; i < MAXOPS; i++)
  136. if ( sym == tabops[i].symbol )
  137. return tabops[i].code;
  138.  
  139. return -1;
  140. }
  141.  
  142. // -------------------------------------------------------------------------------------
  143. // Read the input line and assign appropriate values to x, opsym and opcode
  144. // (return the number of input tokens read)
  145. //
  146. int get_input( double *x, char *opsym, OpCode *opcode,
  147. const OpStruct tabops[], const double res )
  148. {
  149. char inbuf[MAXINBUF] = ""; // our input buffer
  150. int ntokens; // # of tokens to return
  151.  
  152. do {
  153. printf("%9lg: ", res); // show prompt
  154. fgets(inbuf, MAXINBUF, stdin); // read input line
  155. ntokens = sscanf(inbuf, "%c %lg", opsym, x); // extract opsym & x
  156.  
  157. if ( ntokens == 0 ) // no tokens read
  158. continue;
  159. // opsym was a command
  160. if ( *opsym == 'x' || *opsym == 'c' || *opsym == 'h') {
  161. *opcode = -1; // invalidate opcode
  162. return 1; // exit function
  163. }
  164. // opsym was operator
  165. *opcode = sym2opcode(*opsym, tabops); // assign valid opcode
  166.  
  167. } while ( ntokens == 0 || *opcode == -1);
  168.  
  169. return ntokens; // # of tokens read
  170. }
  171. // -----------------------------------------------------------------------
  172. int main( void )
  173. {
  174. double x=0.0, res=0.0; // x from input, res for result
  175. char opsym; // operator symbol from input
  176. OpCode opcode; // operator code (from opsym)
  177.  
  178. // table of operator structures
  179. const OpStruct tabops[ MAXOPS ] = { // (.unary inited but not used)
  180. {'+', ADD, FALSE}, {'-', SUB, FALSE}, {'*', MUL, FALSE},
  181. {'/', DIV, FALSE}, {'%', MOD, FALSE}, {'^', POW, FALSE},
  182. {'e', EXPO, TRUE}, {'@', SQRT, TRUE}, {'#', CBRT, TRUE},
  183. {'~', NEG, TRUE }, {'!', FACT, TRUE}, {'\'', LOGE, TRUE},
  184. {'\"', LOGTEN, TRUE}, {'_', TRUNC, TRUE}, {'.', FRAC, TRUE}
  185. };
  186. // jump-table of func pointers
  187. double (*pf[MAXOPS])(const double, const double) = {
  188. &add, &sub, &mul, &over, &modulus, &pwr, &expo, &sqroot, &cbroot,
  189. &neg, &fact, &loge, &logten, &truncate, &frac
  190. };
  191.  
  192. puts("\tDUMMY CALC 1.0 by migf1\n\t\tprompt is the result, type h for help\n");
  193. do { // our main loop
  194. // read opsym, x and opcode
  195. get_input(&x, &opsym, &opcode, tabops, res);
  196. if ( opsym == 'x') // exit program
  197. break;
  198. if ( opsym == 'c' ) { // clear the result
  199. res = 0.0;
  200. continue;
  201. }
  202. if (opsym == 'h') { // show help
  203. help();
  204. continue;
  205. }
  206.  
  207. // at this point opcode != -1
  208. res = (*pf[opcode])(res, x); // do the requested operation
  209. } while ( 1 );
  210.  
  211. exit( EXIT_SUCCESS );
  212. }
  213.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty