#include <iostream>

class Stos
  {
   private:
   class Element
     {
      private:
      double Dane;
      Element *Nastepny;
      public:
      Element(double Dane,Element *Nastepny);
      Element *Pobierz(double &Dane,Element *&Nastepny);
      friend Stos;
      friend ostream &operator<<(ostream &out,const Stos &S);
     } *Pierwszy;
   Element *ZnajdzOstatni()const;
   void Czysc();
   void Kopiuj(const Stos &S);
   public:
   class Pusty {};
   Stos():Pierwszy(0) {}
   Stos(const Stos &S):Pierwszy(0) { Kopiuj(S); }
   ~Stos() { Czysc(); }
   Stos &operator<<(double Dane);
   Stos &operator>>(double &Dane);
   operator bool()const { return Pierwszy; }
   void operator~() { Czysc(); }
   Stos &operator=(const Stos &S) { Czysc(); Kopiuj(S); return *this; }
   friend ostream &operator<<(ostream &out,const Stos &S);
  };

Stos::Element::Element(double Dane,Stos::Element *Nastepny):
  Dane(Dane),Nastepny(Nastepny)
  {
  }

Stos::Element *Stos::Element::Pobierz(double &Dane,Stos::Element *&Nastepny)
  {
   if(!this) throw Pusty();
   Dane=Stos::Element::Dane;
   Nastepny=Stos::Element::Nastepny;
   return this;
  }

Stos::Element *Stos::ZnajdzOstatni()const
  {
   Stos::Element *Ostatni=0;
   for(Stos::Element *i=Pierwszy;i;i=i->Nastepny) Ostatni=i;
   return Ostatni;
  }

void Stos::Czysc()
  {
   while(Pierwszy)
     {
      Stos::Element *Tmp=Pierwszy->Nastepny;
      delete Pierwszy;
      Pierwszy=Tmp;
     }
  }

void Stos::Kopiuj(const Stos &S)
  {
   Stos::Element *Ostatni=ZnajdzOstatni();
   for(Stos::Element *i=S.Pierwszy;i;i=i->Nastepny)
     {
      Ostatni=(Ostatni?Ostatni->Nastepny:Pierwszy)=new Stos::Element(i->Dane,0);
/*
      Stos::Element *Nowy=new Stos::Element(i->Dane,0);
      if(Ostatni) Ostatni->Nastepny=Nowy;
      else Pierwszy=Nowy;
      Ostatni=Nowy;
*/
     }
  }

Stos &Stos::operator<<(double Dane)
  {
   Pierwszy=new Element(Dane,Pierwszy);
   return *this;
  }

Stos &Stos::operator>>(double &Dane)
  {
   delete Pierwszy->Pobierz(Dane,Pierwszy);
   return *this;
  }

ostream &operator<<(ostream &out,const Stos &S)
  {
   out<<'{';
   bool F=false;
   for(Stos::Element *i=S.Pierwszy;i;i=i->Nastepny)
     {
      if(F) out<<',';
      out<<i->Dane;
      F=true;
     }
   return out<<'}';
  }

#define Wartosc(Var) #Var<<'='<<Var<<';'

int main()
  {
   Stos S;
   cout<<Wartosc(S)<<endl;
   double X=3,Y;
   S<<1<<2<<X;
   cout<<Wartosc(S)<<endl;
   Stos T(S);
   cout<<Wartosc(T)<<endl;
   S>>Y>>X;
   cout<<Wartosc(Y)<<endl;
   cout<<Wartosc(X)<<endl;
   cout<<Wartosc(S)<<endl;
   S=T;
   cout<<Wartosc(S)<<endl;
   if(S)
     {
      ~S;
      cout<<Wartosc(S)<<endl;
     }
   if(S) cout<<"Blad"<<endl;
   try
     {
      S>>X;
     }
   catch(Stos::Pusty)
     {
      cout<<"Stos jest pusty!"<<endl;
     }

   cin.get();
   return 0;
  }
