1
1
/* *
2
2
* @file
3
- * @brief Evaluation of [Postfix Expression](https://en.wikipedia.org/wiki/Reverse_Polish_notation)
3
+ * @brief Evaluation of [Postfix
4
+ * Expression](https://en.wikipedia.org/wiki/Reverse_Polish_notation)
4
5
* @author [Darshana Sarma](https://github.com/Darshana-Sarma)
5
6
* @details
6
7
* Create a stack to store operands (or values).
11
12
* When the expression is ended, the number in the stack is the final answer
12
13
*/
13
14
#include < algorithm> // for all_of
14
- #include < array> // for std::array
15
15
#include < cassert> // for assert
16
16
#include < iostream> // for io operations
17
+ #include < stack> // for std::stack
17
18
#include < string> // for stof
19
+ #include < vector> // for std::vector
18
20
19
21
/* *
20
22
* @namespace others
@@ -26,36 +28,6 @@ namespace others {
26
28
* @brief Functions for Postfix Expression algorithm
27
29
*/
28
30
namespace postfix_expression {
29
- /* *
30
- * @brief Creates an array to be used as stack for storing values
31
- */
32
- class Stack {
33
- public:
34
- std::array<float , 20 > stack{}; // /< Array which will be used to store numbers in the input
35
- int stackTop = -1 ; // /< Represents the index of the last value added to array. -1 means array is empty
36
- };
37
-
38
- /* *
39
- * @brief Pushing operand, also called the number in the array to the stack
40
- * @param operand float value from the input array or evaluation
41
- * @param stack stack containing numbers
42
- * @returns none
43
- */
44
- void push (float operand, Stack *stack) {
45
- stack->stackTop ++;
46
- stack->stack [stack->stackTop ] = operand;
47
- }
48
-
49
- /* *
50
- * @brief Popping operand, also called the number from the stack
51
- * @param stack stack containing numbers
52
- * @returns operand float on top of stack
53
- */
54
- float pop (Stack *stack) {
55
- float operand = stack->stack [stack->stackTop ];
56
- stack->stackTop --;
57
- return operand;
58
- }
59
31
60
32
/* *
61
33
* @brief Checks if scanned string is a number
@@ -74,28 +46,29 @@ bool is_number(const std::string &s) {
74
46
* @param stack containing numbers
75
47
* @returns none
76
48
*/
77
- void evaluate (float a, float b, const std::string &operation, Stack *stack) {
49
+ void evaluate (float a, float b, const std::string &operation,
50
+ std::stack<float > &stack) {
78
51
float c = 0 ;
79
52
const char *op = operation.c_str ();
80
53
switch (*op) {
81
54
case ' +' :
82
- c = a + b; // Addition of numbers
83
- others::postfix_expression:: push (c, stack );
55
+ c = a + b; // Addition of numbers
56
+ stack. push (c);
84
57
break ;
85
58
86
59
case ' -' :
87
- c = a - b; // Subtraction of numbers
88
- others::postfix_expression:: push (c, stack );
60
+ c = a - b; // Subtraction of numbers
61
+ stack. push (c);
89
62
break ;
90
63
91
64
case ' *' :
92
- c = a * b; // Multiplication of numbers
93
- others::postfix_expression:: push (c, stack );
65
+ c = a * b; // Multiplication of numbers
66
+ stack. push (c);
94
67
break ;
95
68
96
69
case ' /' :
97
- c = a / b; // Division of numbers
98
- others::postfix_expression:: push (c, stack );
70
+ c = a / b; // Division of numbers
71
+ stack. push (c);
99
72
break ;
100
73
101
74
default :
@@ -104,47 +77,54 @@ void evaluate(float a, float b, const std::string &operation, Stack *stack) {
104
77
}
105
78
}
106
79
80
+ namespace {
81
+ float remove_from_stack (std::stack<float > &stack) {
82
+ if (stack.empty ()) {
83
+ throw std::invalid_argument (" Not enough operands" );
84
+ }
85
+ const auto res = stack.top ();
86
+ stack.pop ();
87
+ return res;
88
+ }
89
+ } // namespace
90
+
107
91
/* *
108
92
* @brief Postfix Evaluation algorithm to compute the value from given input
109
93
* array
110
- * @tparam N number of array size
111
- * @param input Array of characters consisting of numbers and operations
94
+ * @param input vector of strings consisting of numbers and operations
112
95
* @returns stack[stackTop] returns the top value from the stack
113
96
*/
114
- template <std::size_t N>
115
- float postfix_evaluation (std::array<std::string, N> input) {
116
- Stack stack;
117
- int j = 0 ;
97
+ float postfix_evaluation (const std::vector<std::string> &input) {
98
+ std::stack<float > stack;
118
99
119
- while (j < N) {
120
- std::string scan = input[j];
100
+ for (const auto &scan : input) {
121
101
if (is_number (scan)) {
122
- push (std::stof (scan), &stack );
102
+ stack. push (std::stof (scan));
123
103
124
104
} else {
125
- float op2 = pop (& stack);
126
- float op1 = pop (& stack);
105
+ const auto op2 = remove_from_stack ( stack);
106
+ const auto op1 = remove_from_stack ( stack);
127
107
128
- evaluate (op1, op2, scan, & stack);
108
+ evaluate (op1, op2, scan, stack);
129
109
}
130
- j++;
131
110
}
132
111
133
- std::cout << stack.stack [stack.stackTop ] << " \n " ;
134
-
135
- return stack.stack [stack.stackTop ];
112
+ const auto res = remove_from_stack (stack);
113
+ if (!stack.empty ()) {
114
+ throw std::invalid_argument (" Too many operands" );
115
+ }
116
+ return res;
136
117
}
137
118
} // namespace postfix_expression
138
119
} // namespace others
139
120
140
-
141
121
/* *
142
122
* @brief Test function 1 with input array
143
123
* {'2', '3', '1', '*', '+', '9', '-'}
144
124
* @returns none
145
125
*/
146
126
static void test_function_1 () {
147
- std::array <std::string, 7 > input = {" 2" , " 3" , " 1" , " *" , " +" , " 9" , " -" };
127
+ std::vector <std::string> input = {" 2" , " 3" , " 1" , " *" , " +" , " 9" , " -" };
148
128
149
129
float answer = others::postfix_expression::postfix_evaluation (input);
150
130
@@ -153,24 +133,80 @@ static void test_function_1() {
153
133
154
134
/* *
155
135
* @brief Test function 2 with input array
156
- * {'1 ', '2 ', '+', '2', '/', '5', '*', '7', '+'}
136
+ * {'100 ', '200 ', '+', '2', '/', '5', '*', '7', '+'}
157
137
* @returns none
158
138
*/
159
139
static void test_function_2 () {
160
- std::array <std::string, 9 > input = {" 100" , " 200" , " +" , " 2" , " /" ,
161
- " 5" , " *" , " 7" , " +" };
140
+ std::vector <std::string> input = {" 100" , " 200" , " +" , " 2" , " /" ,
141
+ " 5" , " *" , " 7" , " +" };
162
142
float answer = others::postfix_expression::postfix_evaluation (input);
163
143
164
144
assert (answer == 757 );
165
145
}
166
146
147
+ static void test_function_3 () {
148
+ std::vector<std::string> input = {
149
+ " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" ,
150
+ " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" , " 1" ,
151
+ " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" ,
152
+ " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" , " +" };
153
+ float answer = others::postfix_expression::postfix_evaluation (input);
154
+
155
+ assert (answer == 22 );
156
+ }
157
+
158
+ static void test_single_input () {
159
+ std::vector<std::string> input = {" 1" };
160
+ float answer = others::postfix_expression::postfix_evaluation (input);
161
+
162
+ assert (answer == 1 );
163
+ }
164
+
165
+ static void test_not_enough_operands () {
166
+ std::vector<std::string> input = {" +" };
167
+ bool throws = false ;
168
+ try {
169
+ others::postfix_expression::postfix_evaluation (input);
170
+ } catch (std::invalid_argument &) {
171
+ throws = true ;
172
+ }
173
+ assert (throws);
174
+ }
175
+
176
+ static void test_not_enough_operands_empty_input () {
177
+ std::vector<std::string> input = {};
178
+ bool throws = false ;
179
+ try {
180
+ others::postfix_expression::postfix_evaluation (input);
181
+ } catch (std::invalid_argument &) {
182
+ throws = true ;
183
+ }
184
+ assert (throws);
185
+ }
186
+
187
+ static void test_too_many_operands () {
188
+ std::vector<std::string> input = {" 1" , " 2" };
189
+ bool throws = false ;
190
+ try {
191
+ others::postfix_expression::postfix_evaluation (input);
192
+ } catch (std::invalid_argument &) {
193
+ throws = true ;
194
+ }
195
+ assert (throws);
196
+ }
197
+
167
198
/* *
168
199
* @brief Main function
169
200
* @returns 0 on exit
170
201
*/
171
202
int main () {
172
203
test_function_1 ();
173
204
test_function_2 ();
205
+ test_function_3 ();
206
+ test_single_input ();
207
+ test_not_enough_operands ();
208
+ test_not_enough_operands_empty_input ();
209
+ test_too_many_operands ();
174
210
175
211
std::cout << " \n Test implementations passed!\n " ;
176
212
0 commit comments