Skip to content

Commit

Permalink
[Stack] Fix stack
Browse files Browse the repository at this point in the history
  • Loading branch information
deunlee committed Jun 1, 2020
1 parent f19f548 commit 6fbdcfa
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 81 deletions.
28 changes: 9 additions & 19 deletions Stack/ArrayStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ namespace Deun {
public:
/**
* 스택 생성자
* @param {int} size 스택의 최대 크기
* @throw {StackError}
* @param size 스택의 최대 크기
* @throw StackError (크기 오류 또는 메모리 할당 실패)
*/
ArrayStack(int size = 1000);

Expand All @@ -30,58 +30,48 @@ namespace Deun {

/**
* 스택의 최대 크기를 반환합니다.
* @return {int}
*/
int getSize();

/**
* 현재 스택에 들어있는 원소의 개수를 반환합니다.
* @return {int}
*/
int getCount();

/**
* 스택이 비어있는지의 여부를 반환합니다.
* @return {bool}
*/
bool isEmpty();

/**
* 스택이 가득 차있는지의 여부를 반환합니다.
* @return {bool}
*/
bool isFull();

/**
* 스택에 원소를 삽입하고 성공 여부를 반환합니다.
* @param {T} element 원소
* @return {bool}
* @param element 원소
*/
bool push(const T& element);

/**
* 스택에서 마지막 원소를 반환하고 삭제합니다.
* @return {T}
* @throw {StackError}
* 스택의 마지막 원소를 삭제하고 성공 여부를 반환합니다.
*/
T pop();
bool pop();

/**
* 스택에서 마지막 원소를 반환합니다.
* pop()과 다르게 원소를 삭제하지 않습니다.
* @return {T}
* @throw {StackError}
* 스택의 마지막 원소를 반환합니다.
* @throw StackError (스택이 빈 경우)
*/
const T& peek();
T& peek();

/**
* 스택을 출력합니다.
*/
void print();

/**
* 스택을 초기화합니다.
* 모든 원소가 삭제됩니다.
* 스택을 초기화합니다. (모든 원소가 삭제됩니다.)
*/
void clear();
};
Expand Down
27 changes: 16 additions & 11 deletions Stack/ArrayStack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ namespace Deun {
if (size <= 0) {
throw StackError::SIZE_IS_TOO_SMALL;
}

array = new (std::nothrow) T[size];
//array = new (std::nothrow) T[size];
array = static_cast<T*>(::operator new(sizeof(T) * size, std::nothrow));
// new는 메모리 할당 후 생성자를 호출하지만 operator new는 메모리만 할당한다. (C의 malloc()와 동일)
// (new 사용시 기본 생성자가 없는 클래스는 컴파일 오류가 발생한다.)
if (!array) {
throw StackError::MEMORY_ALLOCATION_FAILED;
}
}

template <typename T>
ArrayStack<T>::~ArrayStack() {
delete[] array;
//delete[] array;
clear();
::operator delete(array);
}

template <typename T>
Expand Down Expand Up @@ -46,26 +50,24 @@ namespace Deun {
if (isFull()) {
return false;
}

array[count++] = element;
array[count++] = element; // 값만 복사 (TODO)
return true;
}

template <typename T>
T ArrayStack<T>::pop() {
bool ArrayStack<T>::pop() {
if (isEmpty()) {
throw StackError::ELEMENT_NOT_FOUND;
return false;
}

return array[--count];
array[--count].~T(); // 명시적 소멸자 호출 (문제 있음)
return true;
}

template <typename T>
const T& ArrayStack<T>::peek() {
T& ArrayStack<T>::peek() {
if (isEmpty()) {
throw StackError::ELEMENT_NOT_FOUND;
}

return array[count - 1];
}

Expand All @@ -89,6 +91,9 @@ namespace Deun {

template <typename T>
void ArrayStack<T>::clear() {
for (int i = 0; i < count; i++) {
array[i].~T(); // 명시적 소멸자 호출
}
count = 0;
}
}
Expand Down
23 changes: 7 additions & 16 deletions Stack/LinkedListStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,53 +34,44 @@ namespace Deun {

/**
* 현재 스택에 들어있는 원소의 개수를 반환합니다.
* @return {int}
*/
int getCount();

/**
* 스택이 비어있는지의 여부를 반환합니다.
* @return {bool}
*/
bool isEmpty();

/**
* 스택이 가득 차있는지의 여부를 반환합니다.
* 연결 리스트로 구현된 스택에서는 항상 false를 반환합니다.
* @return {bool}
*/
bool isFull();

/**
* 스택에 원소를 삽입하고 성공 여부를 반환합니다.
* @param {T} element 원소
* @return {bool}
* @param element 원소
*/
bool push(const T& element);

/**
* 스택에서 마지막 원소를 반환하고 삭제합니다.
* @return {T}
* @throw {StackError}
* 스택의 마지막 원소를 삭제하고 성공 여부를 반환합니다.
*/
T pop();
bool pop();

/**
* 스택에서 마지막 원소를 반환합니다.
* pop()과 다르게 원소를 삭제하지 않습니다.
* @return {T}
* @throw {StackError}
* @throw StackError (스택이 빈 경우)
*/
const T& peek();
T& peek();

/**
* 스택을 출력합니다.
*/
void print();

/**
* 스택을 초기화합니다.
* 모든 원소가 삭제됩니다.
* 스택을 초기화합니다. (모든 원소가 삭제됩니다.)
*/
void clear();
};
Expand Down
17 changes: 7 additions & 10 deletions Stack/LinkedListStack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Deun {
template <typename T>
LinkedListStack<T>::LinkedListStack() : Stack(0), head(nullptr) {}
LinkedListStack<T>::LinkedListStack() : Stack(0), head(nullptr) { }

template <typename T>
LinkedListStack<T>::~LinkedListStack() {
Expand Down Expand Up @@ -34,34 +34,31 @@ namespace Deun {
if (!front) {
return false;
}
front->data = element;
front->data = element; // 클래스 내부 값만 복사 (얕은 복사)
front->next = head;
head = front;
count++;
return true;
}

template <typename T>
T LinkedListStack<T>::pop() {
// 스택의 맨 앞 노드를 반환하고 삭제한다.
bool LinkedListStack<T>::pop() {
// 스택의 마지막 원소를 삭제한다.
if (isEmpty()) {
throw StackError::ELEMENT_NOT_FOUND;
return false;
}

StackNode<T>* front = head;
T data = front->data;
head = front->next;
delete front;
count--;
return data;
return true;
}

template <typename T>
const T& LinkedListStack<T>::peek() {
T& LinkedListStack<T>::peek() {
if (isEmpty()) {
throw StackError::ELEMENT_NOT_FOUND;
}

return head->data;
}

Expand Down
123 changes: 105 additions & 18 deletions Stack/Playground.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,118 @@ using namespace std;
#include "Stack.h"
using namespace Deun;

class Point {
private:
int x, y;

public:
// Default Constructor
Point() {
x = y = 0;
cout << "<DC-Point(0, 0)@" << this << ">";
}

// Parameterized Constructors
Point(int x, int y) : x(x), y(y) {
cout << "<PC-Point(" << x << ", " << y << ")@" << this << ">";
}

// Copy Constructor
Point(const Point& ref) : x(ref.x), y(ref.y) {
x = ref.x;
y = ref.y;
cout << "<CC-Point(" << x << ", " << y << ")@" << this << ">";
}

// Destructor
~Point() {
//cout << endl;
cout << "<D-Point(" << x << ", " << y << ")@" << this << ">";
}

int getX() { return x; }
int getY() { return y; }
void setX(int x) { this->x = x; }
void setY(int y) { this->y = y; }

friend ostream& operator<<(ostream& os, const Point& obj) {
os << "Point(" << obj.x << ", " << obj.y << ")@" << &obj;
return os;
}
};

using MyType = int;

int main() {
Stack<int>* stack = new Deun::LinkedListStack<int>;
Stack<MyType>* stack = nullptr;
int menu, data;

cout << boolalpha;
cout << "< Stack Playground >" << endl << endl;

cout << "isEmpty(): " << stack->isEmpty() << endl;
cout << endl;
cout << "push(1): " << stack->push(1) << endl;
cout << "push(2): " << stack->push(2) << endl;
cout << "push(3): " << stack->push(3) << endl;
cout << "isFull(): " << stack->isFull() << endl;
cout << "push(4): " << stack->push(4) << endl;
cout << endl;
cout << "pop(): " << stack->pop() << endl;
cout << "pop(): " << stack->pop() << endl;
cout << "pop(): " << stack->pop() << endl;
cout << ">>> Select stack type (ArrayStack=1, LinkedListStack=2) : ";
cin >> menu;

switch (menu) {
case 1:
stack = new ArrayStack<MyType>(5);
break;

case 2:
stack = new LinkedListStack<MyType>;
break;

try {
cout << "pop(): " << stack->pop() << endl;
default:
cout << ">>> Unknown type.";
return 0;
}
catch (StackError err) {
cout << "pop(): ErrorCode " << (int)err << endl;

cout << endl;

while (1) {
stack->print();
cout << ">>> push=1, pop=2, peek=3, exit=4 : ";
cin >> menu;

switch (menu) {
case 1:
cout << ">>> data : ";
cin >> data;
cout << ">>> push(" << data << "): " << stack->push(1);//Point(data, data*2)
break;

case 2:
cout << ">>> pop(): ";
try {
cout << stack->pop();
}
catch (StackError err) {
cout << "Error Code " << (int)err;
}
break;

case 3:
cout << ">>> peek(): ";
try {
cout << stack->peek();
}
catch (StackError err) {
cout << "Error Code " << (int)err;
}
break;

case 4:
cout << ">>> Exit..." << endl;
delete stack;
while (1);
return 0;

default:
cout << ">>> Unknown command.";
}

cout << endl << "==================================================" << endl;
}

cout << "isEmpty(): " << stack->isEmpty() << endl;

return 0;
}
Loading

0 comments on commit 6fbdcfa

Please sign in to comment.