// Ganz einfacher Taschenrechner mit Brüchen (als Struktur)
// + - * / von links nach rechts ohne Vorrang
// Primitiv-Version ohne Kürzen usw.
// 
// Aufruf: bruch bruch1 op1 bruch2 op2 bruch3 ...
//
// Klaus Kusche, 2012

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct bruch {
  int z;
  int n;
};

typedef struct bruch bruch;

bruch Plus(bruch l, bruch r);
bruch Minus(bruch l, bruch r);
bruch Mal(bruch l, bruch r);
bruch Durch(bruch l, bruch r);
void Ausgabe(bruch a);
bruch Eingabe(const char *str);

bruch Plus(bruch l, bruch r)
{
  bruch ergeb;
  ergeb.z = l.z * r.n + r.z * l.n;
  ergeb.n = l.n * r.n;
  return ergeb;
}

bruch Minus(bruch l, bruch r)
{
//  bruch ergeb;
//  ergeb.z = l.z * r.n - r.z * l.n;
//  ergeb.n = l.n * r.n;
// Alternative Variante mit Initialisierung statt Zuweisung:
  bruch ergeb = { l.z * r.n - r.z * l.n, l.n * r.n };
  return ergeb;
}

bruch Mal(bruch l, bruch r)
{
//  bruch ergeb;
//  ergeb.z = l.z * r.z;
//  ergeb.n = l.n * r.n;
//  return ergeb;
// Alternative Variante mit Compound Literal
// Geht nur, solange wir nicht kürzen wollen
  return (bruch) { l.z * r.z, l.n * r.n };
}

bruch Durch(bruch l, bruch r)
{
  bruch ergeb;
  ergeb.z = l.z * r.n;
  ergeb.n = l.n * r.z;
  return ergeb;
}

void Ausgabe(bruch a)
{
  if (a.n != 1) {
    printf("%d/%d\n", a.z, a.n);
  } else {
    printf("%d\n", a.z);
  }
}

bruch Eingabe(const char *str)
{
  bruch ergeb;
  
  ergeb.z = atoi(str);
  const char *slash = strchr(str, '/');
  if (slash == NULL) {          // Kein / gefunden
// Alternative zu atoi + strchr:
// strtol speichert einen Pointer auf das erste nicht-Ziffern-Zeichen in slash
//  char *slash;
//  ergeb.z = strtol(str, &slash, 10);
//  if (*slash != '/') {
    ergeb.n = 1;
  } else {
    ergeb.n = atoi(slash + 1);  // Der Nenner beginnt 1 Zeichen hinter dem /
  }
  return ergeb;
}

int main(int argc, const char *argv[])
{
  // 1, 3, 5, ... Eingabeworte (+1 für den Programmnamen) sind ok
  if (argc % 2 != 0) {
    fprintf(stderr, "%s: Die Anzahl der Eingabeelemente stimmt nicht!\n",
            argv[0]);
    exit(EXIT_FAILURE);
  }

  bruch result = Eingabe(argv[1]);       // erster/linker Bruch
  // Schleife in Zweierschritten ab erstem Rechenzeichen
  for (int i = 2; i < argc; i += 2) {  
    bruch input = Eingabe(argv[i + 1]);  // nächster/rechter Bruch
    switch (argv[i][0]) {                // Rechenzeichen dazwischen
      case '+':
        result = Plus(result, input);
        break;
      case '-':
        result = Minus(result, input);
        break;
      case 'x':
         result = Mal(result, input);
        break;
      case '/':
        result = Durch(result, input);
        break;
      default:
        fprintf(stderr, "%s: %c: Kein Rechenzeichen?\n", argv[0], argv[i][0]);
        exit(EXIT_FAILURE);
    }
  }

  Ausgabe(result);
  
  exit(EXIT_SUCCESS);
}
