/* Copyright (C) 2014 by Alexandru Cojocaru */ /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #define STRINGIZE(m) #m #define STRINGIZE2(m) STRINGIZE(m) #define N_MAXDIGS 10 enum { STMAXDEPTH = 100, }; static double stack[STMAXDEPTH]; static int stackind = 0; static int checkargs (int needed) { if (stackind < needed) error (1, 0, "stack underflow: args present %d, args needed %d\n", stackind, needed); } static int skipws (FILE *in) { int c; do c = getc (in); while (isspace (c)); ungetc (c, in); } static int getnum (FILE *in) { double v; char buf[N_MAXDIGS + 1]; char *tailp = NULL; char *p = buf; int c; fscanf (in, "%" STRINGIZE2 (N_MAXDIGS) "s", buf); errno = 0; v = strtod (buf, &tailp); if (errno != 0 || (tailp != NULL && *tailp != '\0')) error (1, errno, "can't decode number: `%s'\n", buf, tailp); printf ("v: %f\n", v); stack[stackind] = v; return 1; } /* return: EOF on EOF, 0 on failure, 1 on success */ static int next (FILE *in) { int c; int r = 1; if (stackind == STMAXDEPTH) error (1, 0, "exceded stack limit of %u\n", STMAXDEPTH); skipws (in); c = getc (in); switch (c) { case '0' ... '9': ungetc (c, in); r = getnum (in); break; case '+':; case '-':; int nextc = getc (in); ungetc (nextc, in); if (isdigit (nextc)) { r = getnum (in); break; } case '*': case '/': /* fail trough */ checkargs (2); double res; switch (c) { case '+': res = stack[stackind - 2] + stack[stackind - 1]; break; case '-': res = stack[stackind - 2] - stack[stackind - 1]; break; case '*': res = stack[stackind - 2] * stack[stackind - 1]; break; case '/': res = stack[stackind - 2] / stack[stackind - 1]; break; } stackind -= 2; stack[stackind] = res; break; case EOF: return EOF; default: printf ("unknown character: %c\n", c); break; } ++stackind; return r; } int main (void) { int r; while ((r = next (stdin)) == 1) ; if (r == EOF) puts ("EOF"); if (stackind == 0) error (1, 0, "the stack must contain at least one element\n"); printf ("%f\n", stack[stackind-1]); }