I am building a Calculator in C++ OOP style. I made 3 Classes:
- UserInterface, which is responsible for Input and Output of the User.
- Calculation, which is responsible for the logic of the Calculator.
- AdvancedCalculation, which inherits from Calculation and adds more operations to the Calculator.
The Calculator is functional; however I wanted to be able to write good code and not just functional code.
I was wondering if there is a way to change the Calculation Class so adding new operation types like: pow(), sqrt, log, sin, etc., is going to be easier and more convenient, mainly the switch statement in the Calculation Class.
Here is the Code for all 3 Classes:
#pragma once
#include "AdvancedCalculation.h"
class UserInterface {
private:
AdvancedCalculation C;
protected:
double num1;
double num2;
string op;
double result;
char input;
public:
void baseProgram() {
using namespace std;
do {
cout << "Enter the first number: " << endl;
cin >> num1;
C.setNum1(num1);
cout << "Enter an Operator: " << endl;
cin >> op;
C.setOp(op);
cout << "Enter the second number: " << endl;
cin >> num2;
C.setNum2(num2);
C.logic();
cout << C.getResult();
cout << "\nPress A to continue. Press any Key To Exit" << endl;
cin >> input;
system("cls");
} while (input == 'A' || input == 'a');
}
};
#pragma once
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
class Calculation
{
public:
void logic() {
simplifiyOp();
BaseCalculator();
}
void setNum1(double num1) {
this->num1 = num1;
}
void setNum2(double num2) {
this->num2 = num2;
}
void setOp(string op) {
transform(op.begin(), op.end(), op.begin(), ::tolower);
this->op = op;
}
double getResult() {
return result;
}
protected:
double num1;
double num2;
string op;
double result;
vector<vector<string>> listOfOperators = {
{
{"+", "plus", "add"},
{"-", "minus"},
{"*", "multiply", "multiply by", "multiplied by"},
{"/", "divide"},
{"^", "power", "power to"},
{"s", "squareroot", "square root", "square root of"}
}
};
void Addition() {
result = num1 + num2;
}
void Subtraction() {
result = num1 - num2;
}
void Multiplication() {
result = num1 * num2;
}
void Division() {
result = num1 / num2;
}
void simplifiyOp() {
for (auto operatorType : listOfOperators) {
for (string wording : operatorType) {
if (op == wording) {
op = operatorType[0];
break;
}
}
}
}
private:
void BaseCalculator() {
switch (op[0]) {
case '+':
Addition();
break;
case '-':
Subtraction();
break;
case '*':
Multiplication();
break;
case '/':
Division();
break;
default:
break;
}
}
};
#pragma once
#include "Calculation.h"
class AdvancedCalculation : public Calculation
{
public:
void logic() {
simplifiyOp();
BaseCalculator();
}
protected:
void Powers() {
result = pow(num1, num2);
}
void Square() {
result = pow(num1, 1 / num2);
}
void BaseCalculator() {
switch (op[0]) {
case '+':
Addition();
break;
case '-':
Subtraction();
break;
case '*':
Multiplication();
break;
case '/':
Division();
break;
case '^':
Powers();
break;
case 's':
Square();
break;
default:
break;
}
}
};
I tried to use memcpy() so I could copy op[0] and use it in a function that could take every operator, but it didn't really work as expected. I watched some OOP tutorials, hoping there is some function that could help me get the desired result, but no use.
3 + 2 * 4, for example) and parentheses (example:pow(pow(3,2),2)) will basically illustrate the point I made in the previous comment. With the approach your current code takes, you will go crazy trying to get the new feature to work without breaking something else, and/or making the code so horrific that it becomes almost impossible to maintain the code. Using formal techniques like the shunting-yard algorithm, or some other algorithm (even using the "operator/operand stack approach with precedence level checking') is the way to write such code. \$\endgroup\$2+3or4*5, etc.), but to go beyond that is a whole different task. \$\endgroup\$using namespace std;\$\endgroup\$