1
- /* *
2
- * @file
3
- * @brief Implementation of a stack data structure
4
- * @details
5
- * This implementation provides functionalities to push, pop, and view elements
6
- * of the stack. It also includes a self-test method to ensure proper
7
- * functionality.
8
- */
9
-
10
- #include < cassert> // / For assert
11
- #include < iostream> // / For IO operations
12
- #include < stdexcept> // / For std::out_of_range
1
+ #include < cassert>
2
+ #include < iostream>
3
+ #include < memory>
4
+ #include < stdexcept>
13
5
14
- /*
15
- * @namespace
16
- * @brief Data structures
17
- */
18
6
namespace data_structures {
19
7
/* *
20
8
* @brief Class representation of a stack
@@ -23,8 +11,8 @@ namespace data_structures {
23
11
template <typename T>
24
12
class Stack {
25
13
private:
26
- T* stack; // /< Pointer to the stack array
27
- int stackSize; // /< Maximum size of the stack
14
+ std::unique_ptr<T[]> stack; // /< Smart pointer to the stack array
15
+ int stackSize; // /< Maximum size of the stack
28
16
int stackIndex; // /< Index pointing to the top element of the stack
29
17
30
18
public:
@@ -33,40 +21,32 @@ class Stack {
33
21
*
34
22
* @param size Maximum size of the stack
35
23
*/
36
- Stack (int size) : stackSize(size), stackIndex(0 ) { stack = new T[size]; }
37
-
38
- /* *
39
- * @brief Destroys the Stack object
40
- */
41
- ~Stack () { delete[] stack; }
24
+ Stack (int size) : stackSize(size), stackIndex(-1 ), stack(new T[size]) {}
42
25
43
26
/* *
44
27
* @brief Checks if the stack is full
45
28
*
46
29
* @return true if the stack is full, false otherwise
47
30
*/
48
- bool full () const { return stackIndex == stackSize; }
31
+ bool full () const { return stackIndex == stackSize - 1 ; }
49
32
50
33
/* *
51
34
* @brief Checks if the stack is empty
52
35
*
53
36
* @return true if the stack is empty, false otherwise
54
37
*/
55
- bool empty () const { return stackIndex == 0 ; }
38
+ bool empty () const { return stackIndex == - 1 ; }
56
39
57
40
/* *
58
41
* @brief Pushes an element onto the stack
59
42
*
60
43
* @param element Element to push onto the stack
61
- * @return true if the element was successfully pushed onto the stack, false
62
- * otherwise
63
44
*/
64
- bool push (T element) {
45
+ void push (T element) {
65
46
if (full ()) {
66
- return false ;
47
+ throw std::out_of_range ( " Stack overflow " ) ;
67
48
} else {
68
- stack[stackIndex++] = element;
69
- return true ;
49
+ stack[++stackIndex] = element;
70
50
}
71
51
}
72
52
@@ -78,17 +58,16 @@ class Stack {
78
58
*/
79
59
T pop () {
80
60
if (empty ()) {
81
- throw std::out_of_range (" Stack is empty" );
82
- } else {
83
- return stack[--stackIndex];
61
+ throw std::out_of_range (" Stack underflow" );
84
62
}
63
+ return stack[stackIndex--];
85
64
}
86
65
87
66
/* *
88
67
* @brief Displays all elements in the stack
89
68
*/
90
- void show () {
91
- for (int i = 0 ; i < stackIndex; i++) {
69
+ void show () const {
70
+ for (int i = 0 ; i <= stackIndex; i++) {
92
71
std::cout << stack[i] << " \n " ;
93
72
}
94
73
}
@@ -101,10 +80,9 @@ class Stack {
101
80
*/
102
81
T topmost () const {
103
82
if (empty ()) {
104
- throw std::out_of_range (" Stack is empty" );
105
- } else {
106
- return stack[stackIndex - 1 ];
83
+ throw std::out_of_range (" Stack underflow" );
107
84
}
85
+ return stack[stackIndex];
108
86
}
109
87
110
88
/* *
@@ -115,10 +93,9 @@ class Stack {
115
93
*/
116
94
T bottom () const {
117
95
if (empty ()) {
118
- throw std::out_of_range (" Stack is empty" );
119
- } else {
120
- return stack[0 ];
96
+ throw std::out_of_range (" Stack underflow" );
121
97
}
98
+ return stack[0 ];
122
99
}
123
100
};
124
101
} // namespace data_structures
@@ -130,21 +107,35 @@ class Stack {
130
107
static void test () {
131
108
data_structures::Stack<int > stack (5 );
132
109
133
- // Test push, pop, topmost, bottom, full, and empty operations
110
+ // Test empty and full operations
134
111
assert (stack.empty () == true );
135
112
assert (stack.full () == false );
136
113
137
- assert (stack.push (10 ) == true );
138
- assert (stack.push (20 ) == true );
139
- assert (stack.push (30 ) == true );
140
- assert (stack.push (40 ) == true );
141
- assert (stack.push (50 ) == true );
142
- assert (stack.push (60 ) == false );
114
+ // Test pushing elements and checking topmost
115
+ stack.push (10 );
116
+ assert (stack.topmost () == 10 );
143
117
118
+ stack.push (20 );
119
+ assert (stack.topmost () == 20 );
120
+
121
+ stack.push (30 );
122
+ stack.push (40 );
123
+ stack.push (50 );
124
+ assert (stack.full () == true );
125
+
126
+ // Test stack overflow
127
+ try {
128
+ stack.push (60 );
129
+ } catch (const std::out_of_range& e) {
130
+ assert (std::string (e.what ()) == " Stack overflow" );
131
+ }
132
+
133
+ // Test popping elements
144
134
assert (stack.pop () == 50 );
145
135
assert (stack.pop () == 40 );
146
136
assert (stack.pop () == 30 );
147
137
138
+ // Check topmost and bottom elements
148
139
assert (stack.topmost () == 20 );
149
140
assert (stack.bottom () == 10 );
150
141
@@ -154,17 +145,23 @@ static void test() {
154
145
assert (stack.empty () == true );
155
146
assert (stack.full () == false );
156
147
157
- // Test for exceptions when stack is empty
148
+ // Test stack underflow
149
+ try {
150
+ stack.pop ();
151
+ } catch (const std::out_of_range& e) {
152
+ assert (std::string (e.what ()) == " Stack underflow" );
153
+ }
154
+
158
155
try {
159
156
stack.topmost ();
160
157
} catch (const std::out_of_range& e) {
161
- assert (std::string (e.what ()) == " Stack is empty " );
158
+ assert (std::string (e.what ()) == " Stack underflow " );
162
159
}
163
160
164
161
try {
165
162
stack.bottom ();
166
163
} catch (const std::out_of_range& e) {
167
- assert (std::string (e.what ()) == " Stack is empty " );
164
+ assert (std::string (e.what ()) == " Stack underflow " );
168
165
}
169
166
}
170
167
@@ -174,5 +171,6 @@ static void test() {
174
171
*/
175
172
int main () {
176
173
test (); // run self-test implementations
174
+ std::cout << " All tests passed!" << std::endl;
177
175
return 0 ;
178
176
}
0 commit comments