{Brecher.pas - Bruchrechnen - Aufgabenblatt 5}
{Markus Schaber}
PROGRAM Brecher (input,output);

USES crt;

TYPE    TNenner=  1..MAXINT;
        TZaehler= INTEGER;
        TBruch=   PACKED RECORD
                     Nenner: TNenner;
                     Zaehler: TZaehler;
                  END;
        TOperation=PROCEDURE(a,b:TBruch;VAR c:TBruch);

VAR     a,b,c: TBruch;
        flag:  BOOLEAN;
        Taste: CHAR;

{Hilfsfunktionen:}

FUNCTION ggt(a, b : INTEGER) : INTEGER;
{rechnet ggt zweier Integer aus
 Euklidischer Algorithmus iterativ - geklaut aus ggt.pas}
VAR r : INTEGER;
BEGIN
   r := 1;
   REPEAT
      r := a MOD b;
      a := b;
      b := r;
   UNTIL r = 0;
   ggt := a
END { ggt3 };

PROCEDURE ReadBruch(VAR Zahl:TBruch);
{Liest einen Bruch vom Benutzer ein}
begin
     Write (' Zhler:');
     ReadLn(Zahl.Zaehler);
     Write (' Nenner:');
     ReadLn(Zahl.Nenner);
END;

PROCEDURE WriteBruch(Zahl:TBruch);
{gibt einen Bruch auf den Bildschirm aus}
begin
     WriteLn(Zahl.Zaehler,'/',Zahl.Nenner);
END;

{Hier kommen die eingentlichen Bruchrechenfungktionen:
 Leider gehen keine Funktionen vom Typ RECORD!
 Deshalb wurden VAR-Parameter bei Proceduren benutzt.}

PROCEDURE Kurze(VAR zahl:tbruch);
VAR Teiler: Integer;
BEGIN
   WITH zahl DO BEGIN
     if zaehler<>0 THEN BEGIN
        Teiler :=ggt(Nenner, abs(Zaehler));
        Nenner :=Nenner  DIV Teiler;
        Zaehler:=Zaehler DIV Teiler;
     END ELSE
        Nenner:=1; {0/3 = 0/1}
   END
END;

PROCEDURE plus(a,b:TBruch; VAR c:TBruch);
{Addiert die beiden Br…he a und b, gibt das Ergebnis in c zur…k!}
begin
     c.Nenner:=a.Nenner*b.Nenner;
     c.Zaehler:=a.Nenner*b.Zaehler+b.Nenner*a.Zaehler;
     kurze(c);
END;

PROCEDURE minus(a,b:TBruch; VAR c:TBruch);
{subtrahiert den Bruch b von a, gibt das Ergebnis in c zur…k!}
begin
     c.Nenner:=a.Nenner*b.Nenner;
     c.Zaehler:=b.Nenner*a.Zaehler-a.Nenner*b.Zaehler;
     kurze(c);
END;

PROCEDURE mal(a,b:TBruch; VAR c:TBruch);
{Multipliziert die beiden Br…he a und b, gibt das Ergebnis in c zur…k!}
begin
     c.Nenner:=a.Nenner*b.Nenner;
     c.Zaehler:=a.Zaehler*b.Zaehler;
     kurze(c);
END;

PROCEDURE geteilt(a,b:TBruch; VAR c:TBruch);
{Teilt den Bruch a durch b, gibt das Ergebnis in c zur…k!}
begin
     IF b.Zaehler=0 THEN BEGIN

        READLN; {Tastaturpuffer leeren}
        WRITELN('Division durch b=0 ist leider nicht zulгsig!');
        WRITELN('Bitte Return dr…ken');
        READLN;


     END ELSE IF b.Zaehler<0 THEN BEGIN

        c.Nenner :=-a.Nenner *b.Zaehler;
        c.Zaehler:=-a.Zaehler*b.Nenner;

     END ELSE BEGIN

        c.Nenner := a.Nenner *b.Zaehler;
        c.Zaehler:= a.Zaehler*b.Nenner;

     END;
     kurze(c);
END;

BEGIN
     FLAG:=FALSE;
     a.Nenner :=1; b.Nenner :=1; c.Nenner :=1;
     a.Zaehler:=1; b.Zaehler:=1; c.Zaehler:=1;
     REPEAT
           clrscr;
           WRITELN('Bruchrechner');
           WRITE('a=');WriteBruch(a);
           WRITE('b=');WriteBruch(b);
           WRITE('c=');WriteBruch(c);
           WRITELN('Tasten: a,b,c   = Variable setzen');
           WRITELN('        +,-,*,/ = Berechnen: c:=ab und c K〉zen');
           WRITELN('        A,B,C   = Zahl K〉zen');
           WRITELN('        q,Q     = Programm beenden');
           read(Taste);
           CASE Taste OF
                'a':     ReadBruch(a);
                'b':     ReadBruch(b);
                'c':     ReadBruch(c);
                '+':     plus(a,b,c);
                '-':     minus(a,b,c);
                '*':     mal(a,b,c);
                '/':     geteilt(a,b,c);
                'A':     Kurze(a);
                'B':     Kurze(b);
                'C':     Kurze(c);
                'q','Q': FLAG:=TRUE;
           END;
     UNTIL FLAG
END
.
