PLACE
spec
solutions
C#

RPN Calculator in C#

This implementation is not unlike the one in Java, as C#'s design was heavily based on that language. A class is created to accomodate the definitions of the needed functions. Only the Main function (method) is visible outside the class. It reads lines from the standard input until there are no more (null received). Each line is tokenized by calling Split and the resulting list is stored in a Stack<string> container, tks. Unless stk is empty, it is passed to evalrpn for evaluation of the RPN expression. Note that, as stk is a stack, the sequence of tokens is being consumed by evalrpn in reverse order. Upon returning from evalrpn tks must be empty – no token must have remained unused.

evalrpn is recursive on the sequence of tokens. It removes an item tk from the stack and tries to parse it as a number. If that succeeds, the number is returned. Otherwise tk is probably an operator character, in which case evalrpn tries to obtain the arguments for the operation by calling itself twice. If tk is neither a number nor an operator, an exception is raised (‘thrown’). An exception also occurs implicitly within evalrpn when it calls itself with an empty stack tks, as Popping a current token off tks then fails.

All exceptions take place in the dynamic context of the Main's try block where they get caught and an error message is printed. Thus all RPN syntax errors are properly handled.

using System;
using System.Collections.Generic;

class Rpn {
  public static void Main() {
    char [] sp = new char [] {' ','\t'};
    for (;;) {
      string s = Console.ReadLine();
      if (s==null) break;
      Stack<string> tks = new Stack<string>
           (s.Split(sp,StringSplitOptions.RemoveEmptyEntries));
      if (tks.Count==0) continue;
      try {
        double r = evalrpn(tks);
        if (tks.Count!=0) throw new Exception();
        Console.WriteLine(r);
      }
      catch (Exception e) {Console.WriteLine("error");}
    }
  }

  private static double evalrpn(Stack<string> tks) {
    string tk = tks.Pop();
    double x,y;
    if (!Double.TryParse(tk, out x)) {
      y = evalrpn(tks);  x = evalrpn(tks);
      if      (tk=="+") x += y;
      else if (tk=="-") x -= y;
      else if (tk=="*") x *= y;
      else if (tk=="/") x /= y;
      else throw new Exception();
    }
    return x;
  }
}

boykobbatgmaildotcom