# Show me your calculator program.

After readingthis thread in the pit, I’m curious as to what a “simple command line calculator program that will do basic arithmetic(±/*^())” would look like in the various languages available today. Most respondants in that thread seemed to think that this was a trivial excercise, so I want to see some code!

I’ll start, and as I’m a sysprog on a z/OS mainframe with not very much exposure to C, C++, VB, etc., I’m going to fall back on what I know, which is REXX. This program will do exactly what is asked for.

I don’t propose this to be a contest or anything like that, but I’m genuinely interested in how this problem is solved in different languages.

My contribution:

``````

/*=============================== Rexx ===============================*/
true = (0 = 0)
false = (0 = 1)
continue? = true
Say 'Enter Expression:'
Parse External expr

Call Get_next_char
result = Expression()
If nextchar = '' & continue? Then
Say 'The Result is: ' result
Else
Say 'Syntax Error'

Exit

/*====================================================================*/
Get_next_char:
nextchar = ' '
Do Until nextchar ¬= ' ' | Length(expr) = 0
Parse Var expr nextchar 2 expr
End

Return

/*====================================================================*/
Expression: Procedure Expose nextchar continue? expr true false
value = Term()
Do Forever
Select
When nextchar = '+' Then
Do
Call Get_next_char
value = value + Term()
End
When nextchar = '-' Then
Do
Call Get_next_char
value = value - Term()
End
Otherwise
Leave
End
End

Return value

/*====================================================================*/
Term: Procedure Expose nextchar continue? expr true false
value = Factor()
Do Forever
Select
When nextchar = '*' Then
Do
Call Get_next_char
value = value * Factor()
End
When nextchar = '#' Then
Do
Call Get_next_char
value = value ** Term()
End
When nextchar = '/' Then
Do
Call Get_next_char
divisor = Factor()
If divisor ¬= 0 Then
value = value / divisor
Else
Do
Say 'Division by Zero'
Exit
End
End
Otherwise
Leave
End
End

Return value

/*====================================================================*/
Factor: Procedure Expose continue? nextchar expr true false
value = 0
count = 0
decimal_point? = false

If (nextchar <= 9) & (nextchar >= 0) Then
Do
Do While (nextchar <= 9 & nextchar >= 0)
value = value * 10 + nextchar
Call Get_next_char
If decimal_point? Then
count = count + 1
If nextchar = '.' Then
Do
Call Get_next_char
decimal_point? = true
End
End

Do i = 0 By 1 While i < count
value = value / 10
End
Return value
End
Else
Select
When nextchar = '-' Then
Do
Call Get_next_char
Return -1 * Factor()
End
When nextchar = '(' Then
Do
Call Get_next_char

value = Expression()
If nextchar ¬= ')' Then
Do
Say 'Mismatched Parentheses'
Exit
End
Else
Do
Call Get_next_char
Return value
End
End
When nextchar = '.' Then
decimal_point? = true
Otherwise
continue? = false
End

Return 0

``````

Mine would look like this

``````

#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

int main(int argc, char* argv[])
{
char  s[1];
cout << "enter what you want to do:";
cin >> s;
double a,b;
cout << "enter first number:"  ;
cin >> a;
cout << "enter second number:";
cin >> b;

if (s == '*') cout <<  "answer is :" << a*b << "Hit any key to end";
//same thing for the rest.
//might not be able to use == for char*. Might have to use strcmp() or something.
getch();

return 0;
}

``````

That’s pretty trivial. I’d probably not be able to remember all of the proper headers, or if I needed the “strcmp” call. That shouldn’t make or break you, though.

``````

perl -e 'print eval <>'

``````

Yeah, I’m a dick.

Technically, eval(“your expression here”), would work from the Python command line.

However, to make things a little more fun, I’ll ignore the eval command (except for converting numbers into strings):

``````

operators = ["+","-","*","/","^"]
leftbrackets = ["(","{","["]
rightbrackets = [")","}","]"]

def tgeval(expression):
while 1 <> 2:
a = -1
b = -1
for j in range(len(expression)):
if leftbrackets.count(expression[j:j+1]) == 1:
a = j
if rightbrackets.count(expression[j:j+1]) == 1:
b = j
break
if a == -1 and b == -1:
expression = str(arith(expression))
return expression
elif a == -1 or b == -1:
return "Error: Mismatched Parentheses"
else:
expression = replace(expression,a,b+1,str(arith(expression[a+1:b])))

def arith(chunk):
for k in range(len(chunk)-1):
if operators.count(chunk[k+1:k+2]) == 1:
if operators.count(chunk[k+2:len(chunk)]) == 1:
arith(chunk[k+2:len(chunk)])
else:
if chunk[k+1:k+2] == "+":
return eval(chunk[0:k+1])*1.0 + eval(chunk[k+2:len(chunk)])*1.0
if chunk[k+1:k+2] == "-":
return eval(chunk[0:k+1])*1.0 - eval(chunk[k+2:len(chunk)])*1.0
if chunk[k+1:k+2] == "*":
return eval(chunk[0:k+1])*1.0 * eval(chunk[k+2:len(chunk)])*1.0
if chunk[k+1:k+2] == "/":
if eval(chunk[k+2:len(chunk)]) == 0:
return "Error: Divide by Zero"
return eval(chunk[0:k+1])*1.0 / eval(chunk[k+2:len(chunk)])*1.0
if chunk[k+1:k+2] == "^":
return (eval(chunk[0:k+1])*1.0) ** (eval(chunk[k+2:len(chunk)])*1.0)

def replace(rstring,rstart,rend,newchunk):
rstring = rstring[0:rstart] + newchunk + rstring[rend:len(rstring)]
return rstring

``````

Expressions are then evaluated from the command line using tgeval(your expression here)

It’s not 100%, since it ignores the order of operations. An expression like 7*2+3 would be evaluated incorrectly as 35, instead of 17. This is because it takes an ambiguous string of commands like a?b?c?d?e and simply turns it into (a?(b?(c?(d?e)))). Additionally, it doesn’t check for people entering non-mathematical stuff. I could get it to work properly, but I need to get to sleep!

Something I initially overlooked was the potential ambiguity between “–” where it denotes a negative number, and “–” as an operator.

That took just over an hour, and that’s with the ability to test the whole time. There are likely to be errors in there. I’ve done things that would probably amuse, and perhaps even scare a real programmer. But I do this as a hobby - I’m not pretending I can program, and I’m definitely not applying for software engineering jobs!