Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am new to c++ and have been making the good old Calculator. I have gone forward from a 2 value calculator to a 3 value calculator and wondered.. How is it possible to make a 10 digit calculator (purely using +,-,*,/) that doesn't forever to code.. I have a if statement which returns what happens if the operators are + and + or + and - etc.. and if i was to go to 4 value, i would be writing 64 ifs, and 5 value would be 256 if statements.

Is there a way to change this such that it wouldn't require writing out so many if statements?

Here is my the important parts of the code:

Calculator.cpp:

#include "stdafx.h"
#include <iostream>
#include "headers.h"
using namespace std;

int main()
{
int nInput1 = GetUserInput();
char chOperation = GetMathematicalOperation();
{
    if (chOperation == '=')
    {
        cout << "The answer is: " << nInput1 << endl;
        return 0;
    }
}
int nInput2 = GetUserInput();
char chOperation2 = GetMathematicalOperation();
{
    if (chOperation2 == '=')
    {
        int nResult = CalculateResult(nInput1, chOperation, nInput2);
        cout << "The answer is: " << nResult << endl;
        return 0;
    }
}

int nInput3 = GetUserInput();

int nResult = CalculateResult2(nInput1, chOperation, nInput2, chOperation2, nInput3);

PrintResult(nResult);
}

CalculateResult.cpp:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


int CalculateResult(int nX, char chOperation, int nY)
{
if (chOperation == '+')
    return nX + nY;
if (chOperation == '-')
    return nX - nY;
if (chOperation == '*')
    return nX * nY;
if (chOperation == '/')
    return nX / nY;

return 0;
}

GetMathematicalOperation.cpp:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

char GetMathematicalOperation()
{
cout << "Please enter an operator (+,-,*,/ or =): ";

char chOperation;
cin >> chOperation;
return chOperation;
}

CalculateResult2.cpp:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


int CalculateResult2(int nX, char chOperation, int nY, char chOperation2, int nZ)
{
if (chOperation == '+' && chOperation2 == '+')
    return nX + nY + nZ;
if (chOperation == '+' && chOperation2 == '-')
    return nX + nY - nZ;
if (chOperation == '+' && chOperation2 == '*')
    return nX + nY * nZ;
if (chOperation == '+' && chOperation2 == '/')
    return nX + nY / nZ;

if (chOperation == '-' && chOperation2 == '+')
    return nX - nY + nZ;
if (chOperation == '-' && chOperation2 == '-')
    return nX - nY - nZ;
if (chOperation == '-' && chOperation2 == '*')
    return nX - nY * nZ;
if (chOperation == '-' && chOperation2 == '/')
    return nX - nY / nZ;

if (chOperation == '*' && chOperation2 == '+')
    return nX * nY + nZ;
if (chOperation == '*' && chOperation2 == '-')
    return nX * nY - nZ;
if (chOperation == '*' && chOperation2 == '*')
    return nX * nY * nZ;
if (chOperation == '*' && chOperation2 == '/')
    return nX * nY / nZ;

if (chOperation == '/' && chOperation2 == '+')
    return nX / nY + nZ;
if (chOperation == '/' && chOperation2 == '-')
    return nX / nY - nZ;
if (chOperation == '/' && chOperation2 == '*')
    return nX / nY * nZ;
if (chOperation == '/' && chOperation2 == '/')
    return nX / nY / nZ;
return 0;
}
share|improve this question
    
Look into translating your formula into a tree structure and traversing it. Google infix traversal for more info. –  James McLeod Dec 27 '13 at 14:16
    
Seems like a good conceptual design question to me, even if it happens to already include some code. The question isn't "How do I fix this code?" It's, "How do I design a calculator without tons of if statements? This is what I've tried so far." –  Karl Bielefeldt Dec 27 '13 at 14:21
    
@KarlBielefeldt Community seems to agree. I'll leave as is. –  World Engineer Dec 27 '13 at 14:23
    
@Frost Engineer The code works fine (except if you enter something wrong it goes funny, but i'm not that good yet so haven't added anything to 'redo' a question if entered something wrong). –  Matt Dec 27 '13 at 14:23
add comment

2 Answers

up vote 11 down vote accepted

Programming is all about data structures and algorithms. In your example, there is no apparent data strcture: your functions are working with raw user input and directly provide the answer, without introducing any intermediary structure to represent the logic of the computation.

As a practical consequence of the well-known equation

programs = data structures + algorithms

the absence of adequate data structure forces you to represent the logic of the computation in the algorithms part, that is, in your code. This is why your code looks so complicated, with that large number of ifs. And your instinct is right, whenever your code looks complicated, it shall ring a bell yelling there is something wrong and that something is typically that you are using the wrong data structure.

The abstraction you are missing here is what is called an algebraic expression, which you can think of as an unevaluated expression. So now, I will answer your question on how to write your calculator—but I strongly suggest you change the problem instead, and write another type of calculator.

Here are the steps to write a calculator supporting arbitrarily complicated expressions:

  1. Implement Binary expression trees as an abstract class Expression having two concrete descendants, one Leaf for the numbers (leaves) and one other Node for the operations (nodes).

  2. Follow the so called Visitor pattern to write an evaluator for your expressions. You want to write an evaluator taking an Expression and evaluating it, the Visitor pattern is the common way to tell if the Expression is actually a Leaf or a Node.

  3. Write a parser to transform user input into an expression. This is a tedious task, but there is automatic tools to help you there, such as Bison.

If you are a beginner, these three steps are challenging because they will expose you to many new concepts of programming simultaneously: abstract data structures, input/output and parsers. A much more tractable exercise is to write a reverse polish notation (RPN) calculator: with such a calculator, instead of telling the computer to compute 3 + 4 * 5 you tell it to compute 4 5 * 3 + which greatly simplifies the logic of the program:

  1. Instead of working with binary expression trees and thus with abstract and concrete classes, you only work with a stack of numbers: the data structure used is much simpler.

  2. Because of 1., there is no need to use the contorted visitor pattern.

  3. Reading input and evaluate it is much easier in RPN than in the usual infix notation, because there is no need to pay attention to priority rules.

Once you are satisfied with your example, you can look for the program bc(1) on a Linux box, it is a complete reverse polish notation calculator, you may want to study its features or its code (in C) to find more challenges!

share|improve this answer
3  
Actually, its dc(1) that is the RPN calculator... and bc(1) was originally implemented as an infix to RPN compiler coupled with dc (you send 5 + 4 to bc and bc would send 5 4 + to dc and return the results - ref: directory.fsf.org/wiki/Bc ). –  MichaelT Dec 27 '13 at 15:54
    
@michaelT Thank you for pointing that out! –  user40989 Dec 30 '13 at 8:22
add comment

Probably what you want to try first is an RPN calculator. With RPN, you push the numbers onto a stack, then pop them off when someone enters an operator. It's easier to implement than an infix calculator, but lets you write arbitrarily long expressions and evaluate them as you go along.

The next step would be to use the shunting yard algorithm to convert an infix expression into an RPN expression. It's too long to include the details here, but it is a well-known algorithm.

The next step would be to write a full expression parser, which is quite an advanced topic, but extremely flexible and useful. There are many tools available to help you do this.

Either way, you probably want to do some research on stacks, queues and trees, and maybe try out a couple test programs using a stack before tackling a calculator again. C++ has a stack implementation in its standard library that would be a good starting point to learn.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.