Share your repls and programming experiences

← Back to all posts
My first four-function calculator on C++
ZControls_Games (17)

I am an amateur at C++ so please do not expect it to function in all scenarios.

Commentshotnewtop
KelvinVerhey (33)

this is not an end all solution. cin is plagued with problems. a non-blocking key input and custom input functions should replace it for instant validation. this is just a basic example of using the cinful methods to sort of validate input. does a few checks for things like divide by zero and tries to prevent other overflows.

#include <iostream>
#include <cmath>
#include <cstdio>
#include <bits/stdc++.h>

using namespace std;

#define put(string) cout << string
#define nlput(string) cout << endl << string
#define putnl(string) put(string) << endl
#define nlputnl(string) nlput(string) << endl
#define nlputdnl(string) nlputnl(string) << endl

#define setMinMax(a, b)   \
  if (num1 < 0) {         \
    numMin = a - num1;    \
  } else if (num1 > 0) {  \
    numMax = b - num1;    \
  } break

#define cinReset() cin.clear(); cin.ignore(10000, '\n')

int readNumber(string num, int min, int max, int zeroValid) {
  int r = 0;
  int isValid = false;

  do {
    cinReset();
    
    nlput("Enter your " << num << " number");
    
    nlput("[" << min << " to ");
    if (!zeroValid) put(" -1 and 1 to ");
    putnl(max << "]:");

    cin >> r;

    if (!cin.fail() && (r >= min && r <= max)) {
      if (zeroValid == false) {
        if (r != 0) isValid = true;
      } else
        isValid = true;
    }

    if (!isValid) putnl("Not a valid number.");
  } while (!isValid);

  return r;
}

int main() {
  string name;
  nlputnl("Please enter your name:"); cin >> name;
  nlputnl("Hello " << name);

  const char *operations[] = {
    "Add", "Subtract", "Divide", "Multiply"
  };

  int option;
  while (true) {
    nlputdnl("Would you like to:");
    for (int i = 0; i < 4; ++i) {
      putnl((i + 1) << " - " << operations[i]);
    }
    put(endl);

    int isValid = false;
    do {
      cinReset();
      putnl("Select an operation [1-4]:"); cin >> option;
    
      if (!cin.fail())
        if (option > 0 && option < 5)
          isValid = true;
     
      if (!isValid) nlputnl("Invalid option. ");
    } while (!isValid);

    nlputnl(operations[option-1] << " has been confirmed.");

    int numMin = INT_MIN;
    int numMax = INT_MAX;
    int isZeroValid = true;

    int num1 = readNumber("first", numMin, numMax, isZeroValid);
    switch (option) {
      case 1: setMinMax(INT_MIN, INT_MAX);
      case 2: setMinMax(INT_MAX, INT_MIN);
      case 3: isZeroValid = false; break;
      case 4: {
        int t = INT_MAX / num1;
        t = abs(t);

        numMin = -t;
        numMax = t;
      } break;
    }

    int num2 = readNumber("second", numMin, numMax, isZeroValid);

    switch (option) {
      case 1: num1 += num2; break;
      case 2: num1 -= num2; break;
      case 3: {
        putnl("Integer maths is used. Rounding happens.");
        num1 /= num2;
      } break;
      case 4: num1 *= num2; break;
    }

    nlputnl("Your answer is " << num1);

    putnl("Calculate again? [Y]es or any other quits");
    cinReset();
    int playAgain; cin >> playAgain;
    if (playAgain != 'Y' && playAgain != 'y') break;
  }

  nlputnl("END OF LINE");
  return 0;
}
ZControls_Games (17)

Thanks I am going to test it out and try to comprehend
@KelvinVerhey

CowNationz (41)

@ZControls_Games
'In the C Programming Language, the #define directive allows the definition of macros within your source code. These macro definitions allow constant values to be declared for use throughout your code. Macro definitions are not variables and cannot be changed by your program code like variables.'

KelvinVerhey (33)

@ZControls_Games if you need help understanding any of this. I should be around a bit more. Life has just been a bit hectic tying me up. @CowNationz thanks for explaining #define.

ZControls_Games (17)

It's ok.
Peace be with you :D
Thanks! @KelvinVerhey

etian (22)

Nice! that was a project i've done before
:)

ZControls_Games (17)

Thanks!
I am sorry my reply was late, very busy with school
@etian

CowNationz (41)

A couple crituiques:
There is no need to ask for the user's name
Your indentation is all off. In some spots you use one space, in others you use 2, in another you use tabs and in others you use no indentation.
There is also an easier way to find out what operation they want to do. Have them enter an expression (e.g. 5*2). Have cin input 2 ints and 1 char (e.g. std::cin >> integer1 >> character1 >> integer2;) and it will automatically assign the numbers to each int and the symbol to the character and then you can just simply do the operation that the character tells you.

KelvinVerhey (33)

@CowNationz this method would be very hard for a novice to parse. especially for a divide by zero check. also multiplication overflow of ints. this is not a good method unless you can promote from a smaller bit width type to a larger one. cin also cannot be validated for input using this method for bad data put into either position. this is not recommended unless you are suggesting writing a full blown expression parser based on something like a shunting yard. there are deeper problems to address. lack of knowledge of flow control such as loops, functions, and cin validation.

MartinStavland (10)

Nice calculator. But one suggestion. Maybe don't ask for our name every time we calculate, maybe just the first time? But anyway, good job!

ZControls_Games (17)

I am trying to figure that out @ZControls_Games

KelvinVerhey (33)

@MartinStavland that is caused by code replication. as the main code block has been copy/pasted several times.