-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCalculate.cpp
More file actions
executable file
·159 lines (137 loc) · 5.13 KB
/
Copy pathCalculate.cpp
File metadata and controls
executable file
·159 lines (137 loc) · 5.13 KB
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// -*- C++ -*-
// Honor Pledge:
//
// I pledge that I have neither given nor receieved any help
// on this assignment.
#include "Calculate.h"
Calculate::Calculate (void)
: infix ("NaN")
{
} // end default constructor
Calculate::Calculate (std::string & str)
: infix (str)
{
} // end initializing constructor
const int Calculate::result (void)
{
return receiver.top ();
} // end result
void Calculate::reset (void)
{
postfix.resize (0);
receiver.clear ();
} // end reset
void Calculate::set_infix (std::string & str)
{
infix = str;
} // end set_infix
/**
* reference to understand the method below
*
* PRIORITY OF COMMANDS: (larger = greater precedence)
* Numbers = 0 (not an operator)
* Paranthesis = -1 (for open paranthesis)
* -2 (for closed paranthesis)
* Addition = 1
* Subtraction = 1
* Multiplication = 2
* Division = 2
* Modulus = 2
*/
bool Calculate::infix_to_postfix (void)
{
// initializations
std::stringstream parser(infix);
parser.clear(); // clear the error state of the parser stream just in case
std::string token;
int number;
Stack_Expr_Command_Factory factory (receiver);
Stack <Expr_Command *> temp_stack; // stack where all the commands will be pushed temporarily
Expr_Command * command = 0;
size_t size_counter = 0; // counter to keep track of the size of the array and add elements
while (!parser.eof ()) {
// parsing
parser >> token;
if (std::isdigit (token[0]) || std::isdigit (token[1])) {
// the current token is a number
std::istringstream ss(token); // to convert from string to number
ss >> number;
command = factory.create_number_command (number);
} else {
// the current token is not a number
if (token == "+") {
command = factory.create_add_command ();
} else if (token == "-") {
command = factory.create_subtract_command ();
} else if (token == "*") {
command = factory.create_multiply_command ();
} else if (token == "/") {
command = factory.create_divide_command ();
} else if (token == "%") {
command = factory.create_modulus_command ();
} else if (token == "(") {
// create a command with precedence value -1 to distinguish open parathesis
command = new Expr_Command (-1);
} else if (token == ")") {
// create a command with precedence value -2 to distinguish closed parathesis
command = new Expr_Command (-2);
} else {
return false; // input not valid
} // end if-else
} // end if-else
// pushing the commands on the stack based on the infix to postfix algorithm
int precedence = command->precedence ();
if (precedence == 0) {
// command is either a number
if (postfix.size () <= size_counter) {
postfix.resize (size_counter + 5);
} // end if
postfix [size_counter] = command;
size_counter ++;
} else if (precedence == -1) {
// command is an open paranthesis
temp_stack.push (command);
} else if (precedence == -2) {
// command is a closed paranthesis
while (!temp_stack.is_empty () && temp_stack.top ()->precedence () != -1) {
// while a matching open paranthesis is not found, pop from the stack and add to the postfix array
if (postfix.size () <= size_counter) {
postfix.resize (size_counter + 5);
} // end if
postfix [size_counter] = temp_stack.pop ();
size_counter ++;
} // end while
// also pop the ( expression
temp_stack.pop ();
} else {
// other operators: +, -, *, /, %
while (!temp_stack.is_empty () && precedence <= temp_stack.top ()->precedence ()) {
if (postfix.size () <= size_counter) {
postfix.resize (size_counter + 5);
} // end if
postfix [size_counter] = temp_stack.pop ();
size_counter ++;
} // end while
// now push the current command
temp_stack.push (command);
} // end if-else
} // end while
// pop the remaining operators from the stack and add to postfix
while (!temp_stack.is_empty ()) {
if (postfix.size () <= size_counter) {
postfix.resize (size_counter + 5);
} // end if
postfix [size_counter] = temp_stack.pop ();
size_counter ++;
} // end while
postfix.resize (size_counter); // resize postfix to its true size i.e. how many commands
return true;
} // end infix_to_postfix
void Calculate::eval_postfix (void)
{
// execute each command to compute the result
typedef Expr_Command_Iterator <Expr_Command *> Iterator;
for (Iterator iter (postfix); !iter.is_done (); iter.advance ()) {
(*iter)->execute ();
} // end for
} // end eval_postfix