Compare commits
6
Commits
6da144e049
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6857d28b1 | ||
|
|
923049e6a1 | ||
|
|
7f836d6689 | ||
|
|
77c0ef9e04 | ||
|
|
fc0ecd6b27 | ||
|
|
d48bacbae7 |
No files matched your search
+215
-73
@@ -1,98 +1,240 @@
|
|||||||
|
/**********************************************************************\
|
||||||
|
* Kurzbeschreibung: automat.c
|
||||||
|
* Stellt Funktionen zur Realisierung eines Automaten zur Verfügung,
|
||||||
|
* die über die in der automat.h vorgegebene C-Schnittstelle
|
||||||
|
* mit einer grafischen Schnittstelle kommunizieren.
|
||||||
|
*
|
||||||
|
* Datum: Autor: Grund der Aenderung:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
\**********************************************************************/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdlib.h>
|
||||||
#include "automat.h"
|
#include "automat.h"
|
||||||
|
|
||||||
typedef enum {A=0, B, C, D, E, F, NR_OF_STATES} state_t;
|
/*--- #defines -------------------------------------------------------*/
|
||||||
|
/* Macro zur Ermittlung der Array Groesse */
|
||||||
|
#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a)))
|
||||||
|
|
||||||
static state_t s_curstate = A;
|
#define NR_OF_STATES (I-A + 1)
|
||||||
static int s_guthaben = 0;
|
|
||||||
static bool s_kaffee_los = false;
|
|
||||||
static bool s_muenz_rueck = false;
|
|
||||||
static bool s_display = false;
|
|
||||||
static const char* s_display_string = "Warten";
|
|
||||||
|
|
||||||
|
/*--- Datentypen (typedef) -------------------------------------------*/
|
||||||
|
/* Definition der Zustaende */
|
||||||
|
typedef enum {A=0,B,C,D,E,F,G,H,I} state_t;
|
||||||
|
|
||||||
|
/* Definition der fsm-spezifischen Variablen */
|
||||||
|
/* Struktur zur Beschreibung eines Uebergangs mit "Don't Care"-Moeglichkeit */
|
||||||
|
typedef struct {
|
||||||
|
int input;
|
||||||
|
int mask;
|
||||||
|
state_t nxtstate;
|
||||||
|
} fsm_state_t;
|
||||||
|
|
||||||
|
/* Struktur zur Beschreibung aller Uebergaenge eines Zustands */
|
||||||
|
typedef struct {
|
||||||
|
const fsm_state_t * transitions;
|
||||||
|
int nrOfTransitions;
|
||||||
|
state_t defaultNxtState;
|
||||||
|
} fsm_full_state_t;
|
||||||
|
|
||||||
|
/*--- Modulglobale static Variablen ----------------------------------*/
|
||||||
|
/* Definition der Zustandsvariablen */
|
||||||
|
static state_t s_curstate = A; /* Initialisierung */
|
||||||
|
|
||||||
|
/* Definition aller Zustandsuebergaenge fuer jeden Zustand */
|
||||||
|
static const fsm_state_t s_transitions_A[] =
|
||||||
|
{ /* input mask nxtstate */
|
||||||
|
// Wenn 1?-Münze eingeworfen (muenze=1, muenz_wert=0), egal ob Becher steht oder nicht (weil mask ~0x004, also becher-Bit egal)
|
||||||
|
{ 0x002, ~0x004, B }, // A -> B: 1? eingeworfen
|
||||||
|
// Wenn 2?-Münze eingeworfen (muenze=1, muenz_wert=1), egal ob Becher steht oder nicht
|
||||||
|
{ 0x003, ~0x004, C } // A -> C: 2? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_B[] =
|
||||||
|
{ /* input mask nxtstate */
|
||||||
|
// Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal
|
||||||
|
{ 0x002, ~0x004, C }, // B -> C: 1? dazu, jetzt 2?
|
||||||
|
// 2? eingeworfen (muenze=1, muenz_wert=1), becher egal
|
||||||
|
{ 0x003, ~0x004, D } // B -> D: 2? dazu, jetzt 3?
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_C[] =
|
||||||
|
{ /* input mask nxtstate */
|
||||||
|
// Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal
|
||||||
|
{ 0x002, ~0x004, D }, // C -> D: 1? dazu, jetzt 3?
|
||||||
|
// Becher steht (becher=1), egal was mit Münze, weil mask ~0x000 (alle Bits relevant)
|
||||||
|
{ 0x003, ~0x000, F }, // C -> F: Becher untergestellt (becher=1, muenze=1, muenz_wert=1)
|
||||||
|
// Becher steht (becher=1), muenze=1, muenz_wert=1 (also 2?), mask ~0x000
|
||||||
|
{ 0x007, ~0x000, H } // C -> H: Becher steht, 2? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_D[] =
|
||||||
|
{ /* input mask nxtstate */
|
||||||
|
// Becher steht (becher=1), egal was mit Münze, mask ~0x000
|
||||||
|
{ 0x002, ~0x000, F }, // D -> F: Becher untergestellt
|
||||||
|
// 2? eingeworfen (muenze=1, muenz_wert=1), becher egal
|
||||||
|
{ 0x003, ~0x004, E }, // D -> E: 2? dazu, jetzt 5? (Überzahlung)
|
||||||
|
// Becher steht (becher=1), muenze=1, muenz_wert=0 (1?), mask ~0x000
|
||||||
|
{ 0x006, ~0x000, H } // D -> H: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_E[] =
|
||||||
|
{
|
||||||
|
// Becher steht (becher=1), egal was mit Münze
|
||||||
|
{ 0x002, ~0x000, F }, // E -> F: Becher untergestellt
|
||||||
|
// 2? eingeworfen, becher egal
|
||||||
|
{ 0x000, ~0x005, D }, // E bleibt E: weitere Überzahlung
|
||||||
|
// Becher steht (becher=1), muenze=1, muenz_wert=0 (1?)
|
||||||
|
{ 0x006, ~0x000, H } // E -> H: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_F[] =
|
||||||
|
{
|
||||||
|
// Becher steht, 1? eingeworfen (becher=1, muenze=1, muenz_wert=0), mask ~0x001 (muenz_wert egal)
|
||||||
|
{ 0x002, ~0x001, G }, // F -> G: Becher steht, Münze eingeworfen
|
||||||
|
// Becher steht, 2? eingeworfen (becher=1, muenze=0, muenz_wert=1)
|
||||||
|
{ 0x004, ~0x001, H }, // F -> H: Becher steht, 2? eingeworfen
|
||||||
|
// Becher steht, 1? eingeworfen (becher=1, muenze=1, muenz_wert=0)
|
||||||
|
{ 0x006, ~0x001, I } // F -> I: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_G[] =
|
||||||
|
{
|
||||||
|
// Becher steht, 1? eingeworfen
|
||||||
|
{ 0x000, ~0x001, F }, // G bleibt G: Becher steht, Münze eingeworfen
|
||||||
|
// Becher steht, 2? eingeworfen
|
||||||
|
{ 0x004, ~0x001, H }, // G -> H: Becher steht, 2? eingeworfen
|
||||||
|
// Becher steht, 1? eingeworfen
|
||||||
|
{ 0x006, ~0x001, I } // G -> I: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_H[] =
|
||||||
|
{
|
||||||
|
// Kein Becher, keine Münze, kein Wert (alles 0)
|
||||||
|
{ 0x000, ~0x001, A }, // H -> A: Reset, alles leer
|
||||||
|
// Becher steht, keine Münze, kein Wert
|
||||||
|
{ 0x002, ~0x000, B }, // H -> B: Becher steht, 1? eingeworfen
|
||||||
|
// Becher steht, 2? eingeworfen
|
||||||
|
{ 0x003, ~0x000, C }, // H -> C: Becher steht, 2? eingeworfen
|
||||||
|
// Becher steht, 1? eingeworfen
|
||||||
|
{ 0x006, ~0x001, I } // H -> I: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
static const fsm_state_t s_transitions_I[] =
|
||||||
|
{ // Kein Becher, keine Münze, kein Wert (alles 0)
|
||||||
|
{ 0x000, ~0x001, A }, // I -> A: Reset, alles leer
|
||||||
|
// Becher steht, keine Münze, kein Wert
|
||||||
|
{ 0x002, ~0x000, B }, // I -> B: Becher steht, 1? eingeworfen
|
||||||
|
// Becher steht, 2? eingeworfen
|
||||||
|
{ 0x003, ~0x000, C }, // I -> C: Becher steht, 2? eingeworfen
|
||||||
|
// Becher steht, 1? eingeworfen
|
||||||
|
{ 0x004, ~0x001, H} // I bleibt I: Becher steht, 1? eingeworfen
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Definition der Uebergangstabelle */
|
||||||
|
/* Die Reihenfolge der Zustaende in der enum Definition muss der
|
||||||
|
* Reihenfolge der Zustaende in der Uebergangstabelle entsprechen
|
||||||
|
* [Zeile] [Spalte] */
|
||||||
|
static const fsm_full_state_t s_state_table[NR_OF_STATES] =
|
||||||
|
{
|
||||||
|
/* transitions nrOfTransitions defaultNxtState */
|
||||||
|
{ s_transitions_A, SIZE_OF(s_transitions_A), A },
|
||||||
|
{ s_transitions_B, SIZE_OF(s_transitions_B), B },
|
||||||
|
{ s_transitions_C, SIZE_OF(s_transitions_C), C },
|
||||||
|
{ s_transitions_D, SIZE_OF(s_transitions_D), D },
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
{ s_transitions_E, SIZE_OF(s_transitions_E), E },
|
||||||
|
{ s_transitions_F, SIZE_OF(s_transitions_F), F },
|
||||||
|
{ s_transitions_G, SIZE_OF(s_transitions_G), G },
|
||||||
|
{ s_transitions_H, SIZE_OF(s_transitions_H), H },
|
||||||
|
{ s_transitions_I, SIZE_OF(s_transitions_I), I }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Definition der Ausgaenge */
|
||||||
|
static const fsm_action_t s_out_table[NR_OF_STATES] =
|
||||||
|
{
|
||||||
|
/* display muenz_rueck kaffee_los guthaben, display_string */
|
||||||
|
{ false, false, false, 0, "Warten" }, /* state A */
|
||||||
|
{ false, false, false, 1, "1 Euro" }, /* state B */
|
||||||
|
{ false, false, false, 2, "2 Euro" }, /* state C */
|
||||||
|
{ false, false, false, 3, "3 Euro" }, /* state D */
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
{ false, true, false, 3, "3 Euro + M" }, /* state E */
|
||||||
|
{ true, false, false, 4, "4 Euro" }, /* state F */
|
||||||
|
{ true, true, false, 4, "4 Euro + M" }, /* state G */
|
||||||
|
{ true, false, true, 0, "Kaffe kommt" }, /* state H */
|
||||||
|
{ true, true, true, 0, "Kaffe + M" } /* state I */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*--- Funktionsdefinition --------------------------------------------*/
|
||||||
void automat_reset(void)
|
void automat_reset(void)
|
||||||
{
|
{
|
||||||
|
printf("---- automat_reset ----\n");
|
||||||
|
|
||||||
|
/* TODO go into IDLE state */
|
||||||
|
|
||||||
s_curstate = A;
|
s_curstate = A;
|
||||||
s_guthaben = 0;
|
|
||||||
s_kaffee_los = false;
|
|
||||||
s_muenz_rueck = false;
|
|
||||||
s_display = false;
|
|
||||||
s_display_string = "Warten";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- Funktionsdefinition --------------------------------------------*/
|
||||||
void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert)
|
void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert)
|
||||||
{
|
{
|
||||||
s_kaffee_los = false;
|
// Ausgabe der aktuellen Eingabewerte zur Fehlersuche
|
||||||
s_muenz_rueck = false;
|
printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n",
|
||||||
s_display = false;
|
becher, muenze, muenz_wert);
|
||||||
|
|
||||||
int wert = muenz_wert ? 2 : 1;
|
// Kombiniere die Eingabewerte zu einem einzigen Integer mittels Bitoperationen.
|
||||||
|
// Die Eingaben werden wie folgt kombiniert:
|
||||||
|
// - 'becher' wird um 2 Bits nach links verschoben (belegt die dritte Bitposition)
|
||||||
|
// - 'muenze' wird um 1 Bit nach links verschoben (belegt die zweite Bitposition)
|
||||||
|
// - 'muenz_wert' bleibt in der ersten Bitposition
|
||||||
|
// Dies ergibt einen 3-Bit-Integer, der den aktuellen Eingabestatus darstellt.
|
||||||
|
int in = (becher << 2) | (muenze << 1) | (muenz_wert << 0);
|
||||||
|
|
||||||
switch (s_curstate) {
|
// Hole die Übergangsinformationen des aktuellen Zustands aus der Zustandstabelle.
|
||||||
case A: case B: case C: case D: case E:
|
// 's_curstate' enthält den aktuellen Zustand, und 's_state_table' liefert die
|
||||||
// Münzeinwurf
|
// Übergangsdetails für jeden Zustand.
|
||||||
if (muenze) {
|
const fsm_full_state_t * full_transition = &s_state_table[s_curstate];
|
||||||
if (s_guthaben + wert > 4) {
|
|
||||||
s_muenz_rueck = true;
|
|
||||||
s_display = true;
|
|
||||||
s_display_string = "Zu viel! Münze zurück";
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
s_guthaben += wert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guthaben prüfen
|
// Hole das Array der Übergänge für den aktuellen Zustand.
|
||||||
if (s_guthaben < 4) {
|
// Jeder Übergang spezifiziert eine Eingabebedingung, eine Maske und einen Folgezustand.
|
||||||
if (s_guthaben == 0) { s_curstate = A; s_display_string = "Warten"; }
|
const fsm_state_t * transition = full_transition->transitions;
|
||||||
else if (s_guthaben == 1) { s_curstate = B; s_display_string = "1 Euro"; }
|
int i;
|
||||||
else if (s_guthaben == 2) { s_curstate = C; s_display_string = "2 Euro"; }
|
|
||||||
else if (s_guthaben == 3) { s_curstate = D; s_display_string = "3 Euro"; }
|
|
||||||
// Kein Display aktivieren!
|
|
||||||
} else if (s_guthaben == 4) {
|
|
||||||
if (becher) {
|
|
||||||
s_curstate = F;
|
|
||||||
s_kaffee_los = true;
|
|
||||||
s_display = true;
|
|
||||||
s_display_string = "Kaffee wird ausgegeben";
|
|
||||||
s_guthaben = 0;
|
|
||||||
} else {
|
|
||||||
s_curstate = E;
|
|
||||||
s_display = true;
|
|
||||||
s_display_string = "Bitte Becher unterstellen!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case F:
|
// Iteriere über alle definierten Übergänge für den aktuellen Zustand.
|
||||||
s_display = true;
|
for(i = 0; i < full_transition->nrOfTransitions; i++)
|
||||||
s_display_string = "Becher entnehmen";
|
{
|
||||||
if (!becher) {
|
// Überprüfe, ob die aktuelle Eingabe die Übergangsbedingung erfüllt.
|
||||||
s_curstate = A;
|
// Die Bedingung ist erfüllt, wenn die Eingabe, maskiert durch die Übergangsmaske,
|
||||||
s_display = false;
|
// dem spezifizierten Eingabewert des Übergangs entspricht.
|
||||||
s_display_string = "Warten";
|
if(transition[i].input == (in & transition[i].mask))
|
||||||
}
|
{
|
||||||
break;
|
// Wenn ein passender Übergang gefunden wird, aktualisiere den aktuellen Zustand
|
||||||
|
// auf den im Übergang spezifizierten Folgezustand.
|
||||||
default:
|
s_curstate = transition[i].nxtstate;
|
||||||
s_curstate = A;
|
// Beende die Schleife, da der Übergang erfolgreich angewendet wurde.
|
||||||
s_guthaben = 0;
|
|
||||||
s_display = false;
|
|
||||||
s_display_string = "Warten";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wenn nach Überprüfung aller Übergänge kein passender Übergang gefunden wurde,
|
||||||
|
// setze den aktuellen Zustand auf den Standard-Folgezustand für den aktuellen Zustand.
|
||||||
|
// Dies behandelt Fälle, in denen die Eingabe keinem spezifischen Übergang entspricht.
|
||||||
|
if(i == full_transition->nrOfTransitions)
|
||||||
|
{
|
||||||
|
s_curstate = full_transition->defaultNxtState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--- Funktionsdefinition --------------------------------------------*/
|
||||||
fsm_action_t automat_output(void)
|
fsm_action_t automat_output(void)
|
||||||
{
|
{
|
||||||
return (fsm_action_t){
|
return s_out_table[s_curstate];
|
||||||
.display = s_display,
|
|
||||||
.muenz_rueck = s_muenz_rueck,
|
|
||||||
.kaffee_los = s_kaffee_los,
|
|
||||||
.guthaben = s_guthaben,
|
|
||||||
.display_string = s_display_string
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//gcc automat.c view.c main.c io.c checker.c -o console_automat
|
//gcc automat.c view.c main.c io.c checker.c -o console_automat
|
||||||
+59
-10
@@ -1,38 +1,87 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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) {
|
int ist_dual(const char *s) {
|
||||||
while (*s) if (*s != '0' && *s != '1') return 0; else s++;
|
while (*s)
|
||||||
return 1;
|
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) {
|
void print_bin(int n) {
|
||||||
for (int i = 31; i >= 0; i--) putchar((n >> i) & 1 ? '1' : '0');
|
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
// Prüfen, ob genau 3 Argumente übergeben wurden (Programmname + 3 = 4)
|
||||||
if (argc != 4) {
|
if (argc != 4) {
|
||||||
printf("Richtiger Aufruf: %s <operand> <operator> <operand>\n", argv[0]);
|
printf("Richtiger Aufruf: %s <operand> <operator> <operand>\n", argv[0]);
|
||||||
return 1;
|
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];
|
char *a = argv[1], *op = argv[2], *b = argv[3];
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
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 beide Operanden gültige Dualzahlen sind
|
||||||
if (strlen(op) != 1 || strchr("+-*/&^", op[0]) == NULL) {
|
if (!ist_dual(a)) {
|
||||||
printf("....... %s ist kein erlaubter Operator\n", op); ok = 0;
|
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;
|
if (!ok) return 1;
|
||||||
|
|
||||||
|
// Dualzahlen in int umwandeln (Basis 2)
|
||||||
int x = strtol(a, NULL, 2), y = strtol(b, NULL, 2), r = 0;
|
int x = strtol(a, NULL, 2), y = strtol(b, NULL, 2), r = 0;
|
||||||
if (*op == '/' && y == 0) { printf("Fehler: Division durch 0\n"); return 1; }
|
|
||||||
|
// Division durch 0 abfangen
|
||||||
|
if (*op == '/' && y == 0) {
|
||||||
|
printf("Fehler: Division durch 0\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Die gewünschte Operation ausführen
|
||||||
switch (*op) {
|
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;
|
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;
|
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);
|
printf("%s %s %s =\n....... ", a, op, b);
|
||||||
print_bin(r);
|
print_bin(r);
|
||||||
printf(" (0x%X)\n", r);
|
printf(" (0x%X)\n", r);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
+21
-18
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
\**********************************************************************/
|
\**********************************************************************/
|
||||||
/*--- #includes ------------------------------------------------------*/
|
/*--- #includes ------------------------------------------------------*/
|
||||||
#define _CRT_SECURE_NO_WARNINGS //VC++: keine scanf() Warnungen
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
/*--- #defines -------------------------------------------------------*/
|
/*--- #defines -------------------------------------------------------*/
|
||||||
@@ -16,28 +16,31 @@
|
|||||||
/*--- main -----------------------------------------------------------*/
|
/*--- main -----------------------------------------------------------*/
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int n, z, i=1, nr;
|
int n, z, i=1, nr; // Variablen für Personenanzahl, Schrittweite, Zähler, Rückgabewert scanf
|
||||||
do {
|
do {
|
||||||
printf("Wie viele Personen: ");
|
printf("Wie viele Personen: "); // Benutzer nach Anzahl der Personen fragen
|
||||||
nr = scanf("%d", &n); getchar();
|
nr = scanf("%d", &n); getchar(); // Eingabe lesen, Rückgabewert speichern, Zeilenumbruch entfernen
|
||||||
} while (nr != 1 || n < 0);
|
} while (nr != 1 || n < 0); // Wiederholen, falls ungültige Eingabe
|
||||||
|
|
||||||
do {
|
do {
|
||||||
printf("Wie vielte ist auszusondern: ");
|
printf("Wie vielte ist auszusondern: "); // Benutzer nach Schrittweite fragen
|
||||||
nr = scanf("%d", &z); getchar();
|
nr = scanf("%d", &z); getchar(); // Eingabe lesen, Rückgabewert speichern, Zeilenumbruch entfernen
|
||||||
} while (nr != 1 || z < 0);
|
} while (nr != 1 || z < 0); // Wiederholen, falls ungültige Eingabe
|
||||||
for (i = 1; i <= n; i++) // Queue füllen
|
|
||||||
put(i);
|
for (i = 1; i <= n; i++) // Queue füllen
|
||||||
while (!isEmpty()) {
|
put(i); // Personen mit Nummer 1 bis n in die Queue einfügen
|
||||||
for (i = 1; i < z; i++) { // z-1 Zahlen aus Queue lesen
|
|
||||||
if (put(get()) == FALSE) { // und wieder am Ende der Queue einfügen
|
while (!isEmpty()) { // Solange noch Personen in der Queue sind
|
||||||
fprintf(stderr, "Fehler beim Einfügen\n");
|
for (i = 1; i < z; i++) { // z-1 Personen überspringen
|
||||||
return 1;
|
if (put(get()) == FALSE) { // Erste Person aus der Queue nehmen und wieder hinten einfügen
|
||||||
|
fprintf(stderr, "Fehler beim Einfügen\n"); // Fehlerausgabe, falls put fehlschlägt
|
||||||
|
return 1; // Programm mit Fehlercode beenden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("%d, ", get()); // z. Zahl aus Queue lesen und ausgeben
|
printf("%d, ", get()); // Die z-te Person aus der Queue nehmen und ausgeben (ausscheiden)
|
||||||
// Diese Zahl nicht mehr einfügen
|
// Diese Person wird nicht mehr eingefügt
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n"); // Zeilenumbruch nach Ausgabe aller ausgeschiedenen Personen
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,34 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
|
int main(int argc, char *argv[]) { //Kommandozeilenargumente und Array der Argumente als strings
|
||||||
|
// Prüfen, ob ein Dateiname als Argument übergeben wurde
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("Bitte Dateinamen als erstes Argument angeben.\n");
|
printf("Bitte Dateinamen als erstes Argument angeben.\n");
|
||||||
return 1;
|
return 1; // Fehlercode zurückgeben und Programm beenden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Datei im Lesemodus ("r") öffnen
|
||||||
FILE *datei = fopen(argv[1], "r");
|
FILE *datei = fopen(argv[1], "r");
|
||||||
if (datei == NULL) {
|
if (datei == NULL) {
|
||||||
|
// Fehler beim Öffnen der Datei, z.B. Datei existiert nicht
|
||||||
perror("Fehler beim Öffnen der Datei");
|
perror("Fehler beim Öffnen der Datei");
|
||||||
return 1;
|
return 1; // Fehlercode zurückgeben und Programm beenden
|
||||||
}
|
}
|
||||||
char zeile[1024];
|
|
||||||
int zeilennummer = 1;
|
char zeile[1024]; // Puffer für eine Zeile (max. 1023 Zeichen + '\0')
|
||||||
|
int zeilennummer = 1; // Startwert für die Zeilennummerierung
|
||||||
|
|
||||||
|
// Solange noch Zeilen gelesen werden können
|
||||||
while (fgets(zeile, sizeof(zeile), datei) != NULL) {
|
while (fgets(zeile, sizeof(zeile), datei) != NULL) {
|
||||||
|
// Zeilennummer und Inhalt der Zeile ausgeben
|
||||||
|
// %4d: Zeilennummer rechtsbündig mit mindestens 4 Stellen
|
||||||
printf("%4d: %s", zeilennummer, zeile);
|
printf("%4d: %s", zeilennummer, zeile);
|
||||||
zeilennummer++;
|
zeilennummer++; // Zeilennummer erhöhen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Datei schließen
|
||||||
fclose(datei);
|
fclose(datei);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3,52 +3,81 @@
|
|||||||
* queue.c - realisiert eine Queue (Warteschlange)
|
* queue.c - realisiert eine Queue (Warteschlange)
|
||||||
*
|
*
|
||||||
* Datum: Autor:
|
* Datum: Autor:
|
||||||
* 11.06.2025 OpenAI (auf Basis von Prof. Herold)
|
*
|
||||||
\**********************************************************************/
|
\**********************************************************************/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
/*--- Struktur eines Listenelements ----------------------------------*/
|
/*--- Struktur eines Listenelements ----------------------------------*/
|
||||||
|
|
||||||
|
/*Ein Listenelement (Node) besteht aus:
|
||||||
|
- value: dem gespeicherten Wert (hier ein int)
|
||||||
|
- next: Zeiger auf das nächste Element in der Liste
|
||||||
|
*/
|
||||||
typedef struct Node {
|
typedef struct Node {
|
||||||
int value;
|
int value;
|
||||||
struct Node *next;
|
struct Node *next;
|
||||||
} Node;
|
} Node_t;
|
||||||
|
|
||||||
/*--- Modulglobale Variablen: Zeiger auf Kopf und Ende der Liste -----*/
|
/*--- Modulglobale Variablen: Zeiger auf Kopf und Ende der Liste -----*/
|
||||||
static Node *head = NULL;
|
|
||||||
static Node *tail = NULL;
|
/*head: Zeigt auf das erste Element der Queue (Kopf)
|
||||||
|
tail: Zeigt auf das letzte Element der Queue (Ende)
|
||||||
|
Sind beide NULL, ist die Queue leer.*/
|
||||||
|
static Node_t *head = NULL;
|
||||||
|
static Node_t *tail = NULL;
|
||||||
|
|
||||||
/*--- put(): Einfügen am Ende der Liste ------------------------------*/
|
/*--- put(): Einfügen am Ende der Liste ------------------------------*/
|
||||||
|
/*Fügt eine neue Zahl am Ende der Queue ein.
|
||||||
|
Rückgabewert: TRUE bei Erfolg, FALSE bei Speicherfehler.*/
|
||||||
Bool put(int zahl) {
|
Bool put(int zahl) {
|
||||||
Node *newNode = (Node *)malloc(sizeof(Node));
|
// Speicher für neues Element reservieren
|
||||||
|
Node_t *newNode = (Node_t *)malloc(sizeof(Node_t));
|
||||||
if (newNode == NULL) {
|
if (newNode == NULL) {
|
||||||
fprintf(stderr, "Speicher konnte nicht allokiert werden.\n");
|
fprintf(stderr, "Speicher konnte nicht freigegeben werden.\n");
|
||||||
return FALSE;
|
return FALSE; // Fehler: kein Speicher verfügbar
|
||||||
}
|
}
|
||||||
newNode->value = zahl;
|
newNode->value = zahl; // Wert setzen
|
||||||
newNode->next = NULL;
|
newNode->next = NULL; // Am Ende zeigt next auf NULL
|
||||||
|
|
||||||
if (tail != NULL) {
|
if (tail != NULL) {
|
||||||
|
// Es gibt schon Elemente: neues Element ans Ende anhängen
|
||||||
tail->next = newNode;
|
tail->next = newNode;
|
||||||
} else {
|
} else {
|
||||||
head = newNode; // Liste war leer
|
// Die Liste war leer: head zeigt jetzt auf das neue Element
|
||||||
|
head = newNode;
|
||||||
}
|
}
|
||||||
|
// tail zeigt immer auf das letzte Element
|
||||||
tail = newNode;
|
tail = newNode;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--- get(): Entfernt das erste Element ------------------------------*/
|
/*--- get(): Entfernt das erste Element ------------------------------*/
|
||||||
|
|
||||||
|
/*Entfernt das erste Element (Kopf) der Queue und gibt dessen Wert zurück.
|
||||||
|
Ist die Queue leer, wird QLEER zurückgegeben und eine Fehlermeldung ausgegeben.*/
|
||||||
int get(void) {
|
int get(void) {
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
|
// Die Queue ist leer
|
||||||
fprintf(stderr, "Fehler: Queue ist leer.\n");
|
fprintf(stderr, "Fehler: Queue ist leer.\n");
|
||||||
return QLEER;
|
return QLEER;
|
||||||
}
|
}
|
||||||
Node *tmp = head;
|
Node_t *tmp = head; // Temporärer Zeiger auf das erste Element
|
||||||
int value = tmp->value;
|
int value = tmp->value; // Wert des ersten Elements speichern
|
||||||
head = head->next;
|
head = head->next; // Kopf auf das nächste Element setzen
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
tail = NULL; // Liste ist jetzt leer
|
// Nach dem Entfernen ist die Queue leer, also tail auch auf NULL setzen
|
||||||
|
tail = NULL;
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp); // Speicher des entfernten Elements freigeben
|
||||||
return value;
|
return value; // Wert zurückgeben
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--- isEmpty(): Prüft, ob Liste leer ist ----------------------------*/
|
/*--- isEmpty(): Prüft, ob Liste leer ist ----------------------------*/
|
||||||
|
/*
|
||||||
|
* Gibt TRUE zurück, wenn die Queue leer ist, sonst FALSE.
|
||||||
|
*/
|
||||||
Bool isEmpty(void) {
|
Bool isEmpty(void) {
|
||||||
return head == NULL ? TRUE : FALSE;
|
return head == NULL ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user