#include <iostream>
using namespace std;
// stack이필요하다.
// 1. type을만들지않은경우
//    단점: Stack 2개이상필요한경우복잡해진다.
int buf[10];
int top = 0;
void push( int a )
{
        buf[top++] = a;
}
int pop()
{
        return buf[--top];
}
void main()
{
        push( 10 );
        push( 20 );
        cout << pop() << endl;
        cout << pop() << endl;
}
// 2. Stack이라는Type을먼저만들자- 구조체사용
struct Stack
{
        int buf[10];
        int top;
};
void init( Stack* s )         { s->top = 0; }
void push( Stack* s, int n)   { s->buf[s->top++] = n; }
int  pop( Stack* s )           { return s->buf[--s->top]; }
int main()
{
        Stack s1;
        Stack s2;
        init( &s1 );
        push( &s1, 10 );
        cout << pop( &s1 ) << endl;
        return 0;
}
// 3. 함수와Data를묶어서표현하자.
// Type 설계의원칙: 잘못사용하기어렵게만들어라.
struct Stack
{
private:                      // 멤버함수만접근할수있다.
        int buf[10];
        int top;
public:                       // 모든곳에서접근할수있다.
        // 멤버함수: 멤버Data에바로접근할수있다.
        //void init() { top = 0; }            //생성자역할.
        Stack() { top = 0; }
        void push( int n ) { buf[top++] = n; }
        int  pop() { return buf[--top]; }
};
void main()
{
        Stack s1;
        Stack s2;
        //s1.init();
        s1.push(10);
        //s1.top = 100;               // private: 영역!!
        cout << s1.pop() << endl;
}
// 4. 동적메모리할당사용
struct Stack
{
private:                      
        int* buf;
        int top;
public:                       
        // 생성자: 객체를생성하면자동으로호출되는함수
        Stack( int sz = 10 )
        {
               top = 0;
               buf = new int[sz];
        }
        // 객체가파괴될때자동으로호출된다.
        ~Stack() { delete[] buf; }
        void push( int n ) { buf[top++] = n; }
        int  pop() { return buf[--top]; }
};
void main()
{
        Stack s1;
        Stack s2(30);
        s1.push(10);
        cout << s1.pop() << endl;
}
// 5. Template 기반의Stack
template <typename T>
struct Stack
{
private:                      
        T* buf;
        int top;
public:                       
        // 생성자: 객체를생성하면자동으로호출되는함수
        Stack( int sz = 10 )
        {
               top = 0;
               buf = new T[sz];
        }
        // 객체가파괴될때자동으로호출된다.
        ~Stack() { delete[] buf; }
        void push( T n ) { buf[top++] = n; }
        T    pop() { return buf[--top]; }
};
void main()
{
        Stack<int> s1;       // template class( struct )의객체를생성하는방법
        Stack<double> s2(30);
        s1.push(10);
        cout << s1.pop() << endl;
}
template <typename T>
struct List
{
        T buf;
        List* link;
        List()
        {
               link = NULL;
        }
};
template <typename T>
struct Stack
{
private:                      
        List<T>* pList;
        int tail;
public:                       
        // 생성자: 객체를생성하면자동으로호출되는함수
        Stack()
        {
               tail = 0;
        }
        // 객체가파괴될때자동으로호출된다.
        ~Stack()
        {
        }
        void push( T n )
        {
               pList = new pList;
               pList->buf = n;
        }
        T pop()
        {
               return buf[--top];
        }
};
void main()
{
        Stack<int> s1;   // template class( struct )의객체를생성하는방법
        s1.push(10);
        cout << s1.pop() << endl;
}
#include <iostream> using namespace std; template <typename T> class List { public:         T m_Data;         List* m_pNext;         List(T n, List* next) : m_Data(n), m_pNext(next)         {}         ~List()         {                if( m_pNext != NULL )                        delete m_pNext;         } }; template <typename T> class Stack {         List<T>* m_pList; public:         Stack();         ~Stack();         bool IsEnd();         void push( T n );         T pop(); }; template<typename T> Stack<T>::Stack() : m_pList(NULL) {} template<typename T> Stack<T>::~Stack() {} template<typename T> bool Stack<T>::IsEnd() {         return (m_pList == NULL); } template<typename T> void Stack<T>::push( T n ) {         m_pList = new List<T>( n , m_pList );  } template<typename T> T Stack<T>::pop() {         if( IsEnd() )         {                cout << "Stack is End" << endl;                return -1;         }                  List<T>* temp = m_pList;         T data  = m_pList->m_Data;         m_pList = m_pList->m_pNext;         temp->m_pNext = NULL;         delete temp;         return data; } void main() {         Stack<int> s1;         s1.push( 10 );         s1.push( 20 );         s1.push( 30 );         cout << s1.pop() << endl;         cout << s1.pop() << endl;         cout << s1.pop() << endl;         Stack<double> s2;         s2.push( 4.20 );         s2.push( 5.560 );         cout << s2.pop() << endl;         cout << s2.pop() << endl; //      Stack<char*> s3; //      s3.push("문자열??"); //      s3.push("출력가능??"); //      cout << s3.pop() << endl; //      cout << s3.pop() << endl; //      cout << s3.pop() << endl; }
6. Single linked list 기반의 template Stack