/*
MODYFIKACJA: teraz używamy referencji
Podstawowe operacji na ułamkach.
Program prosi o podanie wyrazu z udziałem ułamków (tylko + - * /),
sprowadza podane wyrażenie do jednego ułamku.
np: po wprowadzeniu wyrażenia: 2/6+1/6
program wypisuje: 1/3+1/6=1/2
struktury, przekazywanie struktur do funkcji
cin.clear(ios::badbit);
instrukcja sterująca switch(...) { case: break; default: }















*/
#include <iostream>
#include <limits>

using namespace std; // w starszych kompilatorach trzeba zakomentować ten wiersz

struct Ulamek { int Licznik,Mianownik; };

long NWD(long a,long b);

void Drukuj(const Ulamek &U) { cout<<U.Licznik<<'/'<<U.Mianownik; }

Ulamek ULAMEK(long Licznik,long Mianownik)
  {
   Ulamek U;
   U.Licznik=Licznik;
   U.Mianownik=Mianownik;
   return(U);
  }

Ulamek Skroc(long Licznik,long Mianownik)
  {
   int n=NWD(Licznik,Mianownik);
   if((n<0)^(Mianownik<0)) n=-n; // aby mianownik był zawsze dodatni
   return(ULAMEK(Licznik/n,Mianownik/n));
  }

Ulamek Wprowadz()
  {
   long Licznik,Mianownik;
   char Lamana;
   cin>>Licznik>>Lamana>>Mianownik;
   if((cin)&&(Lamana!='/')) cin.clear(ios::badbit);
   return(Skroc(Licznik,Mianownik));
  }

Ulamek Dodaj(const Ulamek &A,const Ulamek &B)
  {
   return(Skroc(A.Licznik*B.Mianownik+B.Licznik*A.Mianownik,A.Mianownik*B.Mianownik));
  }

Ulamek Odejmij(const Ulamek &A,const Ulamek &B)
  {
   return(Skroc(A.Licznik*B.Mianownik-B.Licznik*A.Mianownik,A.Mianownik*B.Mianownik));
  }

Ulamek Mnoz(const Ulamek &A,const Ulamek &B)
  {
   return(Skroc(A.Licznik*B.Licznik,A.Mianownik*B.Mianownik));
  }

Ulamek Dziel(const Ulamek &A,const Ulamek &B)
  {
   return(Skroc(A.Licznik*B.Mianownik,A.Mianownik*B.Licznik));
  }

int main()
  {
   while(true)
     {
      cout<<"Podaj wyraz ulamkowy (!-koniec): ";
      Ulamek A,B;
      char Operacja;
      A=Wprowadz();
      cin>>Operacja;
      B=Wprowadz();
      if(cin)
        {
         Ulamek U;
         switch(Operacja)
           {
            case '+': U=Dodaj(A,B);   break;
            case '-': U=Odejmij(A,B); break;
            case '*': U=Mnoz(A,B);    break;
            case ':': U=Dziel(A,B);   break;
            default: Operacja=0;      break;
           }
         if(Operacja)
           {
            Drukuj(A);
            cout<<Operacja;
            Drukuj(B);
            cout<<'=';
            Drukuj(U);
            cout<<endl;
           }
         else cout<<"Dozwolone operacje to: + - * :"<<endl;
        }
      else
        {
         cin.clear();
         if(cin.get()=='!') break;
         cout<<"Blad wprowadzenia"<<endl;
        }
      cin.ignore(INT_MAX,'\n');
      cout<<endl;
     }
   return 0;
  }

long NWD(long a,long b)
  {
   if(a)
     {
      if(!b) return(a);
      while(b) { int r=a%b; a=b; b=r; }
      return(a);
     }
   return(b?b:1);
  }


