/*
 * 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);
}
