I made a cool calculator

Hey, I'm currently taking a introductory class for C++, I feel proud that I wrote a calculator program. Is there anything I can do to make my calculator more compact?

#include <iostream>
#include <string>
using namespace std;

int main()
{
start:
char what_is;
double num1, num2, num3, final, numbers;
int restart;
cout << "Pick an operation: +, -, *, /.\n";
start2:
cin >> what_is;
if (what_is == '+' || what_is == '-' || what_is == '*' || what_is == '/') {
cout << "Do you want to use 2 or 3 numbers?\n";
cin >> numbers;
}
else {
cout << "Please pick an operation.\n";
goto start2;
}

switch(what_is) {
case '*':
if(numbers <= 2) {
cout << "\nYou chose multiplication with 2 numbers, choose 2 numbers to multiply.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
final = num1 * num2;
cout << num1 << " * " << num2 << " = " << final;
}
else {
cout << "\nYou chose multiplication with 3 numbers, choose 3 numbers to multiply.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
cout << "Number 3: ";
cin >> num3;
final = num1 * num2 * num3;
cout << num1 << " * " << num2 << " * " << num3 << " = " << final;
}
break;

case '/':
if(numbers <= 2) {
cout << "\nYou chose division with 2 numbers, choose 2 numbers to divide.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
final = num1 / num2;
cout << num1 << " / " << num2 << " = " << final;
}
else {
cout << "\nYou chose divison with 3 numbers, choose 3 numbers to divide.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
cout << "Number 3: ";
cin >> num3;
final = num1 / num2 / num3;
cout << num1 << " / " << num2 << " / " << num3 << " = " << final;
}
break;

case '+':
if(numbers <= 2) {
cout << "\nYou chose addition with 2 numbers, choose 2 numbers to add.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
final = num1 + num2;
cout << num1 << " + " << num2 << " = " << final;
}
else {
cout << "\nYou chose addition with 3 numbers, choose 3 numbers to add.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
cout << "Number 3: ";
cin >> num3;
final = num1 + num2 + num3;
cout << num1 << " + " << num2 << " + " << num3 << " = " << final;
}
break;

case '-':
if(numbers <= 2) {
cout << "\nYou chose subtraction with 2 numbers, choose 2 numbers to subtract.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
final = num1 - num2;
cout << num1 << " - " << num2 << " = " << final;
}
else {
cout << "\nYou chose subtraction with 3 numbers, choose 3 numbers to subtract.";
cout << "\nNumber 1: ";
cin >> num1;
cout << "Number 2: ";
cin >> num2;
cout << "Number 3: ";
cin >> num3;
final = num1 - num2 - num3;
cout << num1 << " - " << num2 << " - " << num3 << " = " << final;
}
break;
}
cout << "\n" << "\nType 1 to start over or type anything else to end program. ";
cin >> restart;
if(restart == 1) {
cout << "------------------------------------------------------------\n";
goto start;
}
else {
cout << "Ending Program.";
}

return 0;
}
Something really cool to consider:

PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
The general strategy is to look at each of your branches, and identify the things they have in common. Factor out the things that are common into a function, and provide the things that aren't common as arguments to the function.

Have an array of size 3. Pass in the number of numbers that the user wishes to compute with. If the user chooses to compute with less than 3 numbers, you simply don't use the last element of the array. This will reduce your code from 8 branches to 4 branches.

If you want to get even fancier, you can pass a string + function pointer/functor combo that prints and does the specified calculation type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Example program
#include <iostream>

using std::cout;
using std::cin;

typedef double(*Func)(double, double);

void get_user_input_and_compute(int n, const char* operation_noun, const char* operation_verb, char operation_symbol, Func func)
{
    // sanity check, maybe print error or throw exception, return early, etc.
    if (n < 2) { return; }
    if (n > 3) { return; }
    
    cout << "\nYou chose " << operation_noun << " with " << n << " numbers, choose " << n << " numbers to " << operation_verb << ".\n";
    
    double numbers[3];
    
    // input
    for (int i = 0; i < n; i++)
    {
        cout << "Number " << (i + 1) << ": ";
        cin >> numbers[i];
    }
    
    // computation
    double result = numbers[0];
    for (int i = 1; i < n; i++)
    {
        result = func(result, numbers[i]);
    }
    
    // output
    for (int i = 0; i < n-1; i++)
    {
        cout << numbers[i] << " " << operation_symbol << " ";
    }
    cout << numbers[n-1] << " = " << result << '\n';
}

double division(double n1, double n2)
{
    return n1 / n2;   
}
double subtraction(double n1, double n2)
{
    return n1 - n2;   
}

int main()
{
    get_user_input_and_compute(3, "division", "divide", '/', division);
}

You chose division with 3 numbers, choose 3 numbers to divide.
Number 1: 10
Number 2: 5
Number 3: 3
10 / 5 / 3 = 0.666667


PS: I see you're using goto. This is a bad habit in general, and you should avoid this. Use proper loop constructs such a while loop.
Last edited on
compact code isn't always a goal, it needs to be readable too.
Ganado gave you a great start on a happy medium between too much bloat and too compact to comprehend. The whole thing can be done in a few lines, but it would be gibberish. If you used recursion, for example, you can hide the # of numbers you want to process (you allow 3 currently) in the call stack and do N without asking the user for them.

one thing to do is look at other similar software. if you fire up windows calc, you will see...
- it does not prompt you for anything
- it does not spew text along with the results
- all it does is show what you typed in or the result of your last operation.

you may find all that spew useful, and that is fine, but most calculators are pretty minimal.

some general tips..
- try to keep the user interface (here, that is cin and cout) distinct from the work being done. Next week, if you learn to write a GUI program, can you pull the calculator part out and just have a new input/output interface using the GUI code? No, it is all intertwined... keep this in mind and eventually it will be second nature as you write more code.

- case statements should usually call a function. Large case statements are hard to track and follow... this is just style, but consider:
case a: foo(); break;
case b: bar(); break;
it is easy to see if you miss a break, or leave one out intentionally, or forgot the default, and what each case does is self documented with the good function names (not foo and bar obviously).

I did a calculator a few years ago when win 10 came out because their built in one was so ugly and annoying. Its exactly like yours.. a big switch statement with fat cases and the interface mixed in with the work -- and I know better, I just was terribly lazy about the style and all. If I had known I would use it for so many years... I treated it like a throw-away :(

Do NOT feel bad about any suggestions or criticisms etc... if it works, that is already a great start, and asking for suggestions to improve it is a rarely seen (great) attitude.
Last edited on
Good points, jonnin. Less compact code that separates the back-end logic from the UI is often better than compact code that clumps it all together.

And in real life, strings often need to be translated into multiple languages, so my solution would not extend well to that because it couples the function logic and the strings presented to the user too much.

KennyV2, a fun little project I would recommend is making your own command-line calculator that can handle order of operations, exponentiation, and parentheses. You can use the Shunting Yard algorithm as the basis for this. I find myself still using it when I want to do a small calculation.
whereas I avoided that and used reverse polish. It naturally eliminates the () and input parsing needed for standard input calculators.


It offloads the parsing onto the human :)
[I kid, I suppose RPN can be easy to use if you're used to it. I personally will never use it. Or Lisp.]
Last edited on
that is correct, the human has to mentally adjust the input. you get used to it... my first calculator was RPN ... so its not even a thought anymore. Well, not counting a do-nothing one with an = button, that could only +-*/
Last edited on
Topic archived. No new replies allowed.