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

/* Prüft, ob der übergebene String nur aus '0' und '1' besteht (also eine Dualzahl ist). Gibt 1 zurück, wenn ja, sonst 0.*/
int ist_dual(const char *s) {
    while (*s)
        if (*s != '0' && *s != '1')
            return 0; // Nicht erlaubt, also keine Dualzahl
        else
            s++; // Nächstes Zeichen prüfen
    return 1; // Passt, Dualzahl
}

/*Gibt die 32-Bit-Binärdarstellung einer Zahl aus.
Beginnt beim höchsten Bit (31) und prüft jedes Bit.
Gibt für jedes Bit ‘1’ oder ‘0’ aus (auch führende Nullen).*/
void print_bin(int n) {
    for (int i = 31; i >= 0; i--)
        putchar((n >> i) & 1 ? '1' : '0');
}

/*Erwartet 3 Argumente:
  1. Operand (als Dualzahl, z.B. "1011")
  2. Operator (als einzelnes Zeichen: + - * / & ^)
  3. Operand (als Dualzahl)
  Führt die Operation aus und gibt das Ergebnis als Binärzahl und Hexadezimalzahl aus.*/
int main(int argc, char *argv[]) {
    // Prüfen, ob genau 3 Argumente übergeben wurden (Programmname + 3 = 4)
    if (argc != 4) {
        printf("Richtiger Aufruf: %s <operand> <operator> <operand>\n", argv[0]);
        return 1;
    }

    // Argumente zuweisen
    /*a: erster Operand (als String)
    op: Operator (als String)
    b: zweiter Operand (als String)
    ok: Flag, ob alles gültig ist*/
    char *a = argv[1], *op = argv[2], *b = argv[3];
    int ok = 1;

    // Prüfen, ob beide Operanden gültige Dualzahlen sind
    if (!ist_dual(a)) {
        printf("....... %s ist keine erlaubte Dualzahl\n", a);
        ok = 0;
    }
    if (!ist_dual(b)) {
        printf("....... %s ist keine erlaubte Dualzahl\n", b);
        ok = 0;
    }

    // Prüfen, ob der Operator ein erlaubtes Zeichen ist
    if (strlen(op) != 1 || strchr("+-*/&^", op[0]) == NULL) {
        printf("....... %s ist kein erlaubter Operator\n", op);
        ok = 0;
    }

    // Falls etwas ungültig war, Programm beenden
    if (!ok) return 1;

    // Dualzahlen in int umwandeln (Basis 2)
    int x = strtol(a, NULL, 2), y = strtol(b, NULL, 2), r = 0;

    // Division durch 0 abfangen
    if (*op == '/' && y == 0) {
        printf("Fehler: Division durch 0\n");
        return 1;
    }

    // Die gewünschte Operation ausführen
    switch (*op) {
        case '+': r = x + y; break;
        case '-': r = x - y; break;
        case '*': r = x * y; break;
        case '/': r = x / y; break;
        case '&': r = x & y; break; // Bitweises UND
        case '^': r = x ^ y; break; // Bitweises XOR
    }

    // Ergebnis ausgeben: Eingabe, Operator, Ergebnis in Binär- und Hexadezimaldarstellung
    printf("%s %s %s =\n....... ", a, op, b);
    print_bin(r);
    printf(" (0x%X)\n", r);

    return 0;
}