I am currently in the process of learning C++ from C++ Primer. I have found the exercises in this book to be somewhat dull in that they only test syntax and not reasoning. As such, I have recently written a somewhat advanced C++ calculator. It is advanced in that it can interpret more complex ideas than a simple operation on two numbers. It is only somewhat advanced in that it doesn't understand more complex operations.
It works by asking for an equation and then shows somewhat condensed steps to solve it.
For example, an input of 1024*2+2048*4
yields the following steps to solve:
1024*2+2048*4
2048+8192
10240
Entering illegal equations causes the program to crash. Based on my Java knowledge, having the equation parsing function throw and exception on illegal inputs would be best. But, since I have not yet learned the syntax for C++ exceptions, I have decided to simply leave it as is. I would, however, be interested to know about bugs that occur with legal input.
Input should consist of a number and then an operation alternating as many times as the user wants. The only legal operations are addition (+
), subtraction (-
), multiplication (*
), and division (/
). Input should also not contain any spaces.
I would like to know if my design decisions (ie. where ranged for and iterators are used) is good. If not, how I can improve upon it and why the other method is better. I would also like to know of any bugs that are not related to parsing illegal input.
The code:
So the code can be read easier (multiple tabs, line numbers, etc.) here is an offsite link to the code: https://gist.github.com/john01dav/44e2afc51d608c84ee45
For those who would prefer to read the code in the question:
main.cpp:
#include <iostream>
#include <vector>
#include "term.h"
using std::cout;
using std::endl;
using std::cin;
using std::vector;
using std::string;
int main(){
string equationString;
vector<Term> equation;
cout << "Enter an equation: " << endl;
cin >> equationString;
equation = parseEquation(equationString);
cout << endl;
printEquation(equation);
cout << endl;
while(equation.size() > 1){
simplifyEquation(equation);
printEquation(equation);
cout << endl;
}
cout << endl << "Final Answer: ";
printEquation(equation);
cout << endl;
return 0;
}
term.h:
#ifndef TERM_H
#define TERM_H
#include <vector>
#include <string>
struct Term{
double number;
char operation;
};
std::vector<Term> parseEquation(std::string equationString);
void simplifyEquation(std::vector<Term> &equation);
void simplifyEquation(std::vector<Term> &equation, const char &operation);
void printEquation(const std::vector<Term> &equation);
#endif //TERM_H
term.cpp:
#include <vector>
#include <string>
#include <iostream>
#include "term.h"
using std::vector;
using std::string;
using std::stod;
using std::cout;
using std::endl;
vector<Term> parseEquation(string equationString){
string::size_type location = 0;
vector<Term> equation;
while(true){
Term term;
term.number = stod(equationString, &location);
if(location <= equationString.size()){
term.operation = equationString[location];
}else{
term.operation = '\0';
}
equation.push_back(term);
if(term.operation == '\0'){
return equation;
}else{
equationString = equationString.substr(location + 1);
}
}
}
void simplifyEquation(vector<Term> &equation){
auto originalSize = equation.size();
simplifyEquation(equation, '*'); if(equation.size() != originalSize) return;
simplifyEquation(equation, '/'); if(equation.size() != originalSize) return;
simplifyEquation(equation, '+'); if(equation.size() != originalSize) return;
simplifyEquation(equation, '-'); if(equation.size() != originalSize) return;
}
void simplifyEquation(vector<Term> &equation, const char &operation){
vector<Term> result;
for(auto i=equation.begin();i != equation.end();i++){
if(i->operation == operation){
Term currentTerm = *i;
Term nextTerm = *(++i);
Term newTerm;
if(operation == '+'){
newTerm.number = currentTerm.number + nextTerm.number;
}else if(operation == '-'){
newTerm.number = currentTerm.number - nextTerm.number;
}else if(operation == '*'){
newTerm.number = currentTerm.number * nextTerm.number;
}else if(operation == '/'){
newTerm.number = currentTerm.number / nextTerm.number;
}
newTerm.operation = nextTerm.operation;
result.push_back(newTerm);
}else{
result.push_back(*i);
}
}
equation = result;
}
void printEquation(const vector<Term> &equation){
for(const Term &term : equation){
cout << term.number;
if(term.operation == '\0'){
return;
}else{
cout << term.operation;
}
}
}