Compare commits
8
Commits
dc6284a432
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6857d28b1 | ||
|
|
923049e6a1 | ||
|
|
7f836d6689 | ||
|
|
77c0ef9e04 | ||
|
|
fc0ecd6b27 | ||
|
|
d48bacbae7 | ||
|
|
6da144e049 | ||
|
|
7b6de3d556 |
No files matched your search
@@ -0,0 +1,193 @@
|
||||
/**********************************************************************\
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "automat.h"
|
||||
|
||||
typedef enum {A=0,B,C,D,E,F,G,H,I} state_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
int input;
|
||||
|
||||
int mask;
|
||||
|
||||
state_t nxtstate;
|
||||
|
||||
} fsm_state_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
const fsm_state_t * transitions;
|
||||
|
||||
int nrOfTransitions;
|
||||
|
||||
state_t defaultNxtState;
|
||||
|
||||
} fsm_full_state_t;
|
||||
|
||||
#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a)))
|
||||
|
||||
#define NR_OF_STATES (I-A + 1)
|
||||
|
||||
static state_t s_curstate = A;
|
||||
|
||||
static const fsm_state_t s_transitions_A[] = {
|
||||
|
||||
{0x002, ~0x004, B},
|
||||
|
||||
{0x003, ~0x004, C}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_B[] = {
|
||||
|
||||
{0x002, ~0x004, C},
|
||||
|
||||
{0x003, ~0x004, D}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_C[] = {
|
||||
|
||||
{0x002, ~0x004, D},
|
||||
|
||||
{0x003, ~0x000, F},
|
||||
|
||||
{0x007, ~0x000, H}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_D[] = {
|
||||
|
||||
{0x002, ~0x000, F},
|
||||
|
||||
{0x003, ~0x004, E},
|
||||
|
||||
{0x006, ~0x000, H}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_E[] = {
|
||||
|
||||
{0x006, ~0x000, H},
|
||||
|
||||
{0x002, ~0x004, F},
|
||||
|
||||
{0x003, ~0x004, G}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_F[] = {
|
||||
|
||||
{0x006, ~0x000, H}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_G[] = {
|
||||
|
||||
{0x006, ~0x000, I}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_H[] = {
|
||||
|
||||
{0x000, ~0x000, A}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_state_t s_transitions_I[] = {
|
||||
|
||||
{0x000, ~0x000, A}
|
||||
|
||||
};
|
||||
|
||||
static const fsm_full_state_t s_state_table[NR_OF_STATES] = {
|
||||
|
||||
{ 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 },
|
||||
|
||||
{ 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 }
|
||||
|
||||
};
|
||||
|
||||
static const fsm_action_t s_out_table[NR_OF_STATES] = {
|
||||
|
||||
{ false, false, false, 0, "Warten" }, // A
|
||||
|
||||
{ false, false, false, 1, "1 Euro" }, // B
|
||||
|
||||
{ false, false, false, 2, "2 Euro" }, // C
|
||||
|
||||
{ false, false, false, 3, "3 Euro" }, // D
|
||||
|
||||
{ true, false, false, 3, "3 Euro + M" }, // E
|
||||
|
||||
{ true, false, false, 4, "4 Euro" }, // F
|
||||
|
||||
{ true, true, false, 4, "4 Euro + M" }, // G
|
||||
|
||||
{ true, false, true, 4, "Kaffee" }, // H
|
||||
|
||||
{ false, false, false, 0, "Kaffee + M" } // I
|
||||
|
||||
};
|
||||
|
||||
void automat_reset(void) {
|
||||
|
||||
s_curstate = A;
|
||||
|
||||
}
|
||||
|
||||
void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert) {
|
||||
|
||||
int input = ((becher & 0x1) << 2) | ((muenze & 0x1) << 1) | (muenz_wert & 0x1);
|
||||
|
||||
const fsm_full_state_t *current = &s_state_table[s_curstate];
|
||||
|
||||
for (int i = 0; i < current->nrOfTransitions; ++i) {
|
||||
|
||||
if ((input & ~current->transitions[i].mask) == (current->transitions[i].input & ~current->transitions[i].mask)) {
|
||||
|
||||
s_curstate = current->transitions[i].nxtstate;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s_curstate = current->defaultNxtState;
|
||||
|
||||
}
|
||||
|
||||
fsm_action_t automat_output(void) {
|
||||
|
||||
return s_out_table[s_curstate];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**********************************************************************\
|
||||
* Kurzbeschreibung: automat.h
|
||||
* 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:
|
||||
*
|
||||
*
|
||||
\**********************************************************************/
|
||||
#ifndef AUTOMAT_H
|
||||
#define AUTOMAT_H
|
||||
#define true 1
|
||||
#define false 0
|
||||
typedef int BOOL;
|
||||
typedef struct {
|
||||
BOOL display;
|
||||
BOOL muenz_rueck;
|
||||
BOOL kaffee_los;
|
||||
int guthaben;
|
||||
const char * display_string;
|
||||
} fsm_action_t;
|
||||
extern void automat_reset(void);
|
||||
extern void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert);
|
||||
extern fsm_action_t automat_output(void);
|
||||
#endif /* AUTOMAT_H */
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="kaffee_automat" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin/Debug/kaffee_automat" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-Llib -lkaffee_automat" />
|
||||
<Add option="-Lbin/Debug -lQt5Core -lQt5Gui -lQt5Widgets -pthread" />
|
||||
<Add option="-lstdc++-6 -lgcc_s_dw2-1" />
|
||||
</Linker>
|
||||
<Unit filename="automat.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="automat.h" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
<lib_finder disable_auto="1" />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
@@ -0,0 +1,21 @@
|
||||
# Aufruf linux: make -f makefilename
|
||||
# Aufruf win: mingw32-make -f makefilename
|
||||
# -B: Build all; Alle Ziele ohne Bedingungen erstellen
|
||||
#
|
||||
automat.exe: automat.o checker.o view.o io.o main.o
|
||||
gcc -o automat.exe automat.o checker.o view.o io.o main.o
|
||||
|
||||
automat.o: automat.c automat.h
|
||||
gcc -c -Wall automat.c
|
||||
|
||||
checker.o: checker.c checker.h automat.h s_transaction_list.h
|
||||
gcc -c -Wall checker.c
|
||||
|
||||
view.o: view.c view.h automat.h io.h
|
||||
gcc -c -Wall view.c
|
||||
|
||||
io.o: io.c io.h
|
||||
gcc -c -Wall io.c
|
||||
|
||||
main.o: main.c view.h automat.h checker.h
|
||||
gcc -c -Wall main.c
|
||||
@@ -0,0 +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 <stdlib.h>
|
||||
#include "automat.h"
|
||||
|
||||
/*--- #defines -------------------------------------------------------*/
|
||||
/* Macro zur Ermittlung der Array Groesse */
|
||||
#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a)))
|
||||
|
||||
#define NR_OF_STATES (I-A + 1)
|
||||
|
||||
/*--- 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)
|
||||
{
|
||||
printf("---- automat_reset ----\n");
|
||||
|
||||
/* TODO go into IDLE state */
|
||||
|
||||
s_curstate = A;
|
||||
|
||||
}
|
||||
|
||||
/*--- Funktionsdefinition --------------------------------------------*/
|
||||
void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert)
|
||||
{
|
||||
// Ausgabe der aktuellen Eingabewerte zur Fehlersuche
|
||||
printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n",
|
||||
becher, muenze, muenz_wert);
|
||||
|
||||
// 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);
|
||||
|
||||
// Hole die Übergangsinformationen des aktuellen Zustands aus der Zustandstabelle.
|
||||
// 's_curstate' enthält den aktuellen Zustand, und 's_state_table' liefert die
|
||||
// Übergangsdetails für jeden Zustand.
|
||||
const fsm_full_state_t * full_transition = &s_state_table[s_curstate];
|
||||
|
||||
// Hole das Array der Übergänge für den aktuellen Zustand.
|
||||
// Jeder Übergang spezifiziert eine Eingabebedingung, eine Maske und einen Folgezustand.
|
||||
const fsm_state_t * transition = full_transition->transitions;
|
||||
int i;
|
||||
|
||||
// Iteriere über alle definierten Übergänge für den aktuellen Zustand.
|
||||
for(i = 0; i < full_transition->nrOfTransitions; i++)
|
||||
{
|
||||
// Überprüfe, ob die aktuelle Eingabe die Übergangsbedingung erfüllt.
|
||||
// Die Bedingung ist erfüllt, wenn die Eingabe, maskiert durch die Übergangsmaske,
|
||||
// dem spezifizierten Eingabewert des Übergangs entspricht.
|
||||
if(transition[i].input == (in & transition[i].mask))
|
||||
{
|
||||
// Wenn ein passender Übergang gefunden wird, aktualisiere den aktuellen Zustand
|
||||
// auf den im Übergang spezifizierten Folgezustand.
|
||||
s_curstate = transition[i].nxtstate;
|
||||
// Beende die Schleife, da der Übergang erfolgreich angewendet wurde.
|
||||
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)
|
||||
{
|
||||
return s_out_table[s_curstate];
|
||||
}
|
||||
|
||||
//gcc automat.c view.c main.c io.c checker.c -o console_automat
|
||||
@@ -0,0 +1,44 @@
|
||||
/**********************************************************************\
|
||||
* Kurzbeschreibung: automat.h
|
||||
* 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:
|
||||
*
|
||||
*
|
||||
\**********************************************************************/
|
||||
#ifndef AUTOMAT_H
|
||||
#define AUTOMAT_H
|
||||
|
||||
/*--- #defines -------------------------------------------------------*/
|
||||
#define true 1
|
||||
#define false 0
|
||||
/*--- Datentypen (typedef) -------------------------------------------*/
|
||||
typedef int BOOL;
|
||||
|
||||
typedef struct {
|
||||
BOOL display;
|
||||
BOOL muenz_rueck;
|
||||
BOOL kaffee_los;
|
||||
int guthaben;
|
||||
const char * display_string;
|
||||
} fsm_action_t;
|
||||
|
||||
/*--- Prototypen globaler Funktionen ---------------------------------*/
|
||||
/*--------------------------------------------------------------------*
|
||||
* Setzt den Automat in IDLE state *
|
||||
*--------------------------------------------------------------------*/
|
||||
extern void automat_reset(void);
|
||||
|
||||
/*--------------------------------------------------------------------*
|
||||
* Fuehrt Zustandsuebergaenge durch *
|
||||
*--------------------------------------------------------------------*/
|
||||
extern void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert);
|
||||
|
||||
/*--------------------------------------------------------------------*
|
||||
* Gibt Informationen ueber aktuellen Zustand zurueck *
|
||||
*--------------------------------------------------------------------*/
|
||||
extern fsm_action_t automat_output(void);
|
||||
|
||||
#endif /* AUTOMAT_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "checker.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
BOOL reset;
|
||||
BOOL muenz_wert;
|
||||
BOOL muenze;
|
||||
BOOL becher;
|
||||
} fsm_input_t;
|
||||
|
||||
typedef struct {
|
||||
fsm_input_t input;
|
||||
fsm_action_t output;
|
||||
} fsm_transaction_t;
|
||||
|
||||
#include "s_transaction_list.h"
|
||||
|
||||
static const int s_transaction_list_size =
|
||||
sizeof(s_transaction_list) / sizeof(*s_transaction_list);
|
||||
|
||||
#define ERROR_STRING_SIZE 1000
|
||||
static char s_error_string[ERROR_STRING_SIZE] = { 0 };
|
||||
|
||||
static void checker_propagate_input(fsm_input_t input);
|
||||
static BOOL checker_compare(fsm_action_t o1, fsm_action_t o2);
|
||||
static void checker_write_error_string(
|
||||
fsm_action_t current, fsm_input_t input,
|
||||
fsm_action_t actual, fsm_action_t expected);
|
||||
static void checker_clear_error_string(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* implementation of extern functions ****************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
BOOL checker_check()
|
||||
{
|
||||
fsm_action_t last_out;
|
||||
fsm_action_t new_out;
|
||||
int i;
|
||||
|
||||
automat_reset();
|
||||
|
||||
for (i = 0; i < s_transaction_list_size; i++) {
|
||||
|
||||
last_out = automat_output();
|
||||
|
||||
checker_propagate_input(s_transaction_list[i].input);
|
||||
|
||||
new_out = automat_output();
|
||||
|
||||
if (!checker_compare(new_out, s_transaction_list[i].output)) {
|
||||
checker_write_error_string(last_out, s_transaction_list[i].input,
|
||||
new_out, s_transaction_list[i].output);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
checker_clear_error_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char * checker_error_string() { return s_error_string; }
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* implementation of static functions ****************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void checker_propagate_input(fsm_input_t input)
|
||||
{
|
||||
if (input.reset) automat_reset();
|
||||
else automat_transition(input.becher, input.muenze, input.muenz_wert);
|
||||
}
|
||||
|
||||
BOOL checker_compare(fsm_action_t o1, fsm_action_t o2)
|
||||
{
|
||||
return o1.display == o2.display &&
|
||||
o1.muenz_rueck == o2.muenz_rueck &&
|
||||
o1.kaffee_los == o2.kaffee_los &&
|
||||
o1.guthaben == o2.guthaben;
|
||||
}
|
||||
|
||||
void checker_write_error_string(
|
||||
fsm_action_t current, fsm_input_t input,
|
||||
fsm_action_t actual, fsm_action_t expected)
|
||||
{
|
||||
if (input.reset) {
|
||||
/* actually wanna use snprintf, but it's defined in c99 */
|
||||
sprintf(s_error_string,
|
||||
"Ausgangsvektor enthält nicht die erwarteten Werte:\n"
|
||||
"Letzter Zustand: disp:%d rueck:%d los:%d guthaben:%d \"%s\"\n"
|
||||
"Eingang: Reset\n"
|
||||
"Ausgang: disp:%d rueck:%d los:%d guthaben:%d \"%s\"\n"
|
||||
"Erwartet: disp:%d rueck:%d los:%d guthaben:%d",
|
||||
current.display, current.muenz_rueck, current.kaffee_los,
|
||||
current.guthaben, current.display_string,
|
||||
actual.display, actual.muenz_rueck, actual.kaffee_los,
|
||||
actual.guthaben, actual.display_string,
|
||||
expected.display, expected.muenz_rueck, expected.kaffee_los,
|
||||
expected.guthaben);
|
||||
} else {
|
||||
/* actually wanna use snprintf, but it's defined in c99 */
|
||||
sprintf(s_error_string,
|
||||
"Ausgangsvektor enthält nicht die erwarteten Werte:\n"
|
||||
"Letzter Zustand: disp:%d rueck:%d los:%d guthaben:%d \"%s\"\n"
|
||||
"Eingang: becher:%d muenze:%d muenz_wert:%d\n"
|
||||
"Ausgang: disp:%d rueck:%d los:%d guthaben:%d \"%s\"\n"
|
||||
"Erwartet: disp:%d rueck:%d los:%d guthaben:%d",
|
||||
current.display, current.muenz_rueck, current.kaffee_los,
|
||||
current.guthaben, current.display_string,
|
||||
input.becher, input.muenze, input.muenz_wert,
|
||||
actual.display, actual.muenz_rueck, actual.kaffee_los,
|
||||
actual.guthaben, actual.display_string,
|
||||
expected.display, expected.muenz_rueck, expected.kaffee_los,
|
||||
expected.guthaben);
|
||||
}
|
||||
}
|
||||
|
||||
void checker_clear_error_string()
|
||||
{
|
||||
s_error_string[0] = '\0';
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef __CHECKER_H__
|
||||
#define __CHECKER_H__
|
||||
|
||||
#include "automat.h"
|
||||
|
||||
extern BOOL checker_check(void);
|
||||
extern const char * checker_error_string(void);
|
||||
|
||||
#endif /* __CHECKER_H__ */
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
#include "io.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/* Module intern macros *******************************************************/
|
||||
/******************************************************************************/
|
||||
/* unfortunatly can't write this code as function, because of stack management
|
||||
* => use makro instead */
|
||||
#define DO_PRINTING(output_str) \
|
||||
do { \
|
||||
if (output_str != NULL) { \
|
||||
va_list args; \
|
||||
va_start(args, output_str); \
|
||||
vprintf(output_str, args); \
|
||||
va_end(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Implementations ************************************************************/
|
||||
/******************************************************************************/
|
||||
char * io_read_string(char * read_buffer, size_t buffer_size,
|
||||
const char * output_str, ...)
|
||||
{
|
||||
char * ret, * ptr;
|
||||
|
||||
DO_PRINTING(output_str);
|
||||
ret = fgets(read_buffer, buffer_size, stdin);
|
||||
if (ret == NULL) return NULL;
|
||||
|
||||
/* search for \n */
|
||||
ptr = strchr(read_buffer, '\n');
|
||||
/* if found write \0 instead of \n */
|
||||
if (ptr) *ptr = '\0';
|
||||
/* else buffer is not read completly => clear buffer */
|
||||
else while (getchar() != '\n');
|
||||
|
||||
return read_buffer;
|
||||
}
|
||||
|
||||
int io_read_signed_number(const char * output_str, ...)
|
||||
{
|
||||
int number;
|
||||
|
||||
while (1) {
|
||||
int ret;
|
||||
|
||||
DO_PRINTING(output_str);
|
||||
|
||||
ret = scanf("%d", &number);
|
||||
/* clear buffer */
|
||||
while (getchar() != '\n');
|
||||
|
||||
if (ret == 1) break;
|
||||
else printf("Eingabefehler!!!\n");
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
unsigned int io_read_unsigned_number(const char * output_str, ...)
|
||||
{
|
||||
unsigned int number;
|
||||
|
||||
while (1) {
|
||||
int ret;
|
||||
|
||||
DO_PRINTING(output_str);
|
||||
|
||||
ret = scanf("%u", &number);
|
||||
/* clear buffer */
|
||||
while (getchar() != '\n');
|
||||
|
||||
if (ret == 1) break;
|
||||
else printf("Eingabefehler!!!\n");
|
||||
}
|
||||
return number;
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#ifndef __IO_H__
|
||||
#define __IO_H__
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
/* prints the given string (if not NULL) and reads a string from stdin and
|
||||
* removes \n
|
||||
* the functions returns the value of fgets */
|
||||
extern char * io_read_string(char * read_buffer, size_t buffer_size,
|
||||
const char * output_str, ...);
|
||||
|
||||
/* prints the given string (if not NULL) and reads signed number from stdin */
|
||||
extern int io_read_signed_number(const char * output_str, ...);
|
||||
|
||||
/* prints the given string (if not NULL) and reads unsigned number from stdin */
|
||||
extern unsigned int io_read_unsigned_number(const char * output_str, ...);
|
||||
|
||||
#endif /* __IO_H__ */
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include "view.h"
|
||||
#include "automat.h"
|
||||
#include "checker.h"
|
||||
|
||||
void insert_1_euro(void)
|
||||
{
|
||||
view_set_coin(1);
|
||||
automat_transition(view_has_cup(), true, false);
|
||||
}
|
||||
|
||||
void insert_2_euro(void)
|
||||
{
|
||||
view_set_coin(2);
|
||||
automat_transition(view_has_cup(), true, true);
|
||||
}
|
||||
|
||||
void toggle_cup(void)
|
||||
{
|
||||
view_set_coin(0);
|
||||
view_toggle_cup();
|
||||
automat_transition(view_has_cup(), false, false);
|
||||
}
|
||||
|
||||
void check(void)
|
||||
{
|
||||
printf("\n");
|
||||
|
||||
if (checker_check()) {
|
||||
|
||||
printf("Der Zustandsautomat ist correct\n");
|
||||
|
||||
} else {
|
||||
|
||||
printf("%s\n", checker_error_string());
|
||||
|
||||
}
|
||||
|
||||
printf("\nWeiter mit Return ...");
|
||||
while (getchar() != '\n');
|
||||
|
||||
automat_reset();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int finished = 0;
|
||||
|
||||
automat_reset();
|
||||
view_reset();
|
||||
|
||||
while (!finished) {
|
||||
view_menu_t selection;
|
||||
|
||||
view_show(automat_output());
|
||||
selection = view_menu();
|
||||
|
||||
switch (selection) {
|
||||
case VIEW_1_EURO: insert_1_euro(); break;
|
||||
case VIEW_2_EURO: insert_2_euro(); break;
|
||||
case VIEW_CUP: toggle_cup(); break;
|
||||
case VIEW_RESET: automat_reset(); view_reset(); break;
|
||||
case VIEW_CHECK: check(); break;
|
||||
case VIEW_EXIT: finished = 1; break;
|
||||
case VIEW_INVALID: break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+100002
File diff suppressed because it is too large.
Load diff
+115
@@ -0,0 +1,115 @@
|
||||
#include "view.h"
|
||||
#include "io.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define S_MACHINE_HEAD \
|
||||
" /-----------------------------------\\\n" \
|
||||
" | %33s |\n" \
|
||||
" \\-----------------------------------/\n" \
|
||||
" \n" \
|
||||
" /~~~~~~~~~~~/| \n" \
|
||||
" / /#########/ / |\n" \
|
||||
" / /_________/ / |\n" \
|
||||
" =============== /||\n" \
|
||||
" | %03d EUR |/ ||\n" \
|
||||
" |_____________|/ ||\n" \
|
||||
" | \\___..___/ ||\n" \
|
||||
" | || ||\n"
|
||||
|
||||
|
||||
#define S_MACHINE_NO_COFFEE \
|
||||
" | ||\n" \
|
||||
" | ||\n" \
|
||||
" | ||\n"
|
||||
|
||||
#define S_MACHINE_COFFEE \
|
||||
" | ) ( ||\n" \
|
||||
" | ( ) ) ||\n" \
|
||||
" | ) ( ( ||\n" \
|
||||
|
||||
#define S_MACHINE_NO_CUP \
|
||||
" _________ | ||\n" \
|
||||
" .-'---------| |_______________||\n" \
|
||||
" ( C|/\\/\\/\\/\\/| | / |\n" \
|
||||
" '-./\\/\\/\\/\\/| _|_ _ _ _ _ _ _/ |\n" \
|
||||
" '_________' | | / \n" \
|
||||
" '-------' |_______________|/ \n" \
|
||||
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
|
||||
|
||||
#define S_MACHINE_CUP \
|
||||
" | _________ ||\n" \
|
||||
" .-'---------|___||\n" \
|
||||
" ( C|/\\/\\/\\/\\/| / |\n" \
|
||||
" _'-./\\/\\/\\/\\/|_/ |\n" \
|
||||
" | '_________' | / \n" \
|
||||
" |____'-------'__|/ \n" \
|
||||
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
|
||||
|
||||
#define S_MACHINE_NO_COIN_RETURN "\n"
|
||||
|
||||
#define S_MACHINE_INVALID_COIN_RETURN \
|
||||
" -> keine Muenze verfuegbar !!!\n"
|
||||
|
||||
#define S_MACHINE_COIN_RETURN \
|
||||
" -> %0d Euro zurueck\n"
|
||||
|
||||
|
||||
/* machine status variables */
|
||||
static int s_has_cup = 0;
|
||||
static int s_coin_value = 0;
|
||||
|
||||
/* function implementations */
|
||||
void view_show(fsm_action_t out_vector)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 100; i++) printf("\n");
|
||||
|
||||
printf(S_MACHINE_HEAD, out_vector.display_string, out_vector.guthaben);
|
||||
|
||||
if (out_vector.kaffee_los) printf(S_MACHINE_COFFEE);
|
||||
else printf(S_MACHINE_NO_COFFEE);
|
||||
|
||||
if (s_has_cup) printf(S_MACHINE_CUP);
|
||||
else printf(S_MACHINE_NO_CUP);
|
||||
|
||||
if (out_vector.muenz_rueck) {
|
||||
if (s_coin_value) printf(S_MACHINE_COIN_RETURN, s_coin_value);
|
||||
else printf(S_MACHINE_INVALID_COIN_RETURN);
|
||||
} else {
|
||||
printf(S_MACHINE_NO_COIN_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
view_menu_t view_menu()
|
||||
{
|
||||
int read = io_read_signed_number(
|
||||
"\n"
|
||||
" 0) Einwurf 1 Euro\n"
|
||||
" 1) Einwurf 2 Euro\n"
|
||||
" 2) Becher verstellen\n"
|
||||
" 3) Reset\n"
|
||||
" 4) Automatischer Testlauf\n"
|
||||
" 5) Programm beenden\n"
|
||||
"\n"
|
||||
" Auswahl: ");
|
||||
|
||||
switch (read) {
|
||||
case 0: return VIEW_1_EURO;
|
||||
case 1: return VIEW_2_EURO;
|
||||
case 2: return VIEW_CUP;
|
||||
case 3: return VIEW_RESET;
|
||||
case 4: return VIEW_CHECK;
|
||||
case 5: return VIEW_EXIT;
|
||||
default: return VIEW_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void view_toggle_cup() { s_has_cup = s_has_cup ? 0 : 1; }
|
||||
int view_has_cup() { return s_has_cup; }
|
||||
void view_set_coin(int value) { s_coin_value = value; }
|
||||
|
||||
void view_reset()
|
||||
{
|
||||
s_has_cup = 0;
|
||||
s_coin_value = 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "automat.h"
|
||||
|
||||
typedef enum { VIEW_1_EURO, VIEW_2_EURO, VIEW_CUP, VIEW_RESET, VIEW_CHECK, VIEW_EXIT, VIEW_INVALID } view_menu_t;
|
||||
|
||||
extern void view_show(fsm_action_t out_vector);
|
||||
|
||||
extern view_menu_t view_menu(void);
|
||||
|
||||
extern void view_toggle_cup(void);
|
||||
extern int view_has_cup(void);
|
||||
|
||||
extern void view_set_coin(int value);
|
||||
|
||||
extern void view_reset(void);
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
#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;
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**********************************************************************\
|
||||
* Kurzbeschreibung:
|
||||
* Realisiert das Josephus Spiel zum Test einer Queue
|
||||
*
|
||||
* Datum: Autor:
|
||||
* 30.9.2015 Prof. Dr. Helmut Herold
|
||||
*
|
||||
\**********************************************************************/
|
||||
/*--- #includes ------------------------------------------------------*/
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <stdio.h>
|
||||
#include "queue.h"
|
||||
/*--- #defines -------------------------------------------------------*/
|
||||
/*--- Datentypen (typedef) -------------------------------------------*/
|
||||
/*--- Prototypen lokaler Funktionen ----------------------------------*/
|
||||
/*--- main -----------------------------------------------------------*/
|
||||
int main(void)
|
||||
{
|
||||
int n, z, i=1, nr; // Variablen für Personenanzahl, Schrittweite, Zähler, Rückgabewert scanf
|
||||
do {
|
||||
printf("Wie viele Personen: "); // Benutzer nach Anzahl der Personen fragen
|
||||
nr = scanf("%d", &n); getchar(); // Eingabe lesen, Rückgabewert speichern, Zeilenumbruch entfernen
|
||||
} while (nr != 1 || n < 0); // Wiederholen, falls ungültige Eingabe
|
||||
|
||||
do {
|
||||
printf("Wie vielte ist auszusondern: "); // Benutzer nach Schrittweite fragen
|
||||
nr = scanf("%d", &z); getchar(); // Eingabe lesen, Rückgabewert speichern, Zeilenumbruch entfernen
|
||||
} while (nr != 1 || z < 0); // Wiederholen, falls ungültige Eingabe
|
||||
|
||||
for (i = 1; i <= n; i++) // Queue füllen
|
||||
put(i); // Personen mit Nummer 1 bis n in die Queue einfügen
|
||||
|
||||
while (!isEmpty()) { // Solange noch Personen in der Queue sind
|
||||
for (i = 1; i < z; i++) { // z-1 Personen überspringen
|
||||
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()); // Die z-te Person aus der Queue nehmen und ausgeben (ausscheiden)
|
||||
// Diese Person wird nicht mehr eingefügt
|
||||
}
|
||||
printf("\n"); // Zeilenumbruch nach Ausgabe aller ausgeschiedenen Personen
|
||||
return 0;
|
||||
}
|
||||
|
||||
//gcc -c queue.c -o queue.o
|
||||
//ar rcs libqueue.a queue.o
|
||||
//gcc josephus.c -L. -lqueue -o josephus
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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) {
|
||||
printf("Bitte Dateinamen als erstes Argument angeben.\n");
|
||||
return 1; // Fehlercode zurückgeben und Programm beenden
|
||||
}
|
||||
|
||||
// Datei im Lesemodus ("r") öffnen
|
||||
FILE *datei = fopen(argv[1], "r");
|
||||
if (datei == NULL) {
|
||||
// Fehler beim Öffnen der Datei, z.B. Datei existiert nicht
|
||||
perror("Fehler beim Öffnen der Datei");
|
||||
return 1; // Fehlercode zurückgeben und Programm beenden
|
||||
}
|
||||
|
||||
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) {
|
||||
// Zeilennummer und Inhalt der Zeile ausgeben
|
||||
// %4d: Zeilennummer rechtsbündig mit mindestens 4 Stellen
|
||||
printf("%4d: %s", zeilennummer, zeile);
|
||||
zeilennummer++; // Zeilennummer erhöhen
|
||||
}
|
||||
|
||||
// Datei schließen
|
||||
fclose(datei);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**********************************************************************\
|
||||
* Kurzbeschreibung:
|
||||
* queue.c - realisiert eine Queue (Warteschlange)
|
||||
*
|
||||
* Datum: Autor:
|
||||
*
|
||||
\**********************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "queue.h"
|
||||
|
||||
/*--- 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 {
|
||||
int value;
|
||||
struct Node *next;
|
||||
} Node_t;
|
||||
|
||||
/*--- Modulglobale Variablen: Zeiger auf Kopf und Ende der Liste -----*/
|
||||
|
||||
/*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 ------------------------------*/
|
||||
/*Fügt eine neue Zahl am Ende der Queue ein.
|
||||
Rückgabewert: TRUE bei Erfolg, FALSE bei Speicherfehler.*/
|
||||
Bool put(int zahl) {
|
||||
// Speicher für neues Element reservieren
|
||||
Node_t *newNode = (Node_t *)malloc(sizeof(Node_t));
|
||||
if (newNode == NULL) {
|
||||
fprintf(stderr, "Speicher konnte nicht freigegeben werden.\n");
|
||||
return FALSE; // Fehler: kein Speicher verfügbar
|
||||
}
|
||||
newNode->value = zahl; // Wert setzen
|
||||
newNode->next = NULL; // Am Ende zeigt next auf NULL
|
||||
|
||||
if (tail != NULL) {
|
||||
// Es gibt schon Elemente: neues Element ans Ende anhängen
|
||||
tail->next = newNode;
|
||||
} else {
|
||||
// Die Liste war leer: head zeigt jetzt auf das neue Element
|
||||
head = newNode;
|
||||
}
|
||||
// tail zeigt immer auf das letzte Element
|
||||
tail = newNode;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*--- 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) {
|
||||
if (head == NULL) {
|
||||
// Die Queue ist leer
|
||||
fprintf(stderr, "Fehler: Queue ist leer.\n");
|
||||
return QLEER;
|
||||
}
|
||||
Node_t *tmp = head; // Temporärer Zeiger auf das erste Element
|
||||
int value = tmp->value; // Wert des ersten Elements speichern
|
||||
head = head->next; // Kopf auf das nächste Element setzen
|
||||
if (head == NULL) {
|
||||
// Nach dem Entfernen ist die Queue leer, also tail auch auf NULL setzen
|
||||
tail = NULL;
|
||||
}
|
||||
free(tmp); // Speicher des entfernten Elements freigeben
|
||||
return value; // Wert zurückgeben
|
||||
}
|
||||
|
||||
/*--- isEmpty(): Prüft, ob Liste leer ist ----------------------------*/
|
||||
/*
|
||||
* Gibt TRUE zurück, wenn die Queue leer ist, sonst FALSE.
|
||||
*/
|
||||
Bool isEmpty(void) {
|
||||
return head == NULL ? TRUE : FALSE;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**********************************************************************\
|
||||
* Kurzbeschreibung:
|
||||
* queue.h - realisiert eine Queue (Warteschlange) als verkettete Liste
|
||||
*
|
||||
* Datum: Autor:
|
||||
* 30.9.2015 Prof. Dr. Helmut Herold / angepasst von OpenAI
|
||||
\**********************************************************************/
|
||||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
/*--- #includes ------------------------------------------------------*/
|
||||
#include <limits.h>
|
||||
/*--- #defines -------------------------------------------------------*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define QLEER INT_MIN // Rückgabewert bei leerer Queue
|
||||
/*--- Datentypen -----------------------------------------------------*/
|
||||
typedef int Bool;
|
||||
/*--- Funktionsprototypen --------------------------------------------*/
|
||||
/*--------------------------------------------------------------------*\
|
||||
* put()
|
||||
* Fügt eine Zahl ans Ende der Warteschlange.
|
||||
* Rückgabewert:
|
||||
* TRUE, wenn erfolgreich
|
||||
* FALSE, wenn kein Speicher verfügbar
|
||||
\*--------------------------------------------------------------------*/
|
||||
Bool put(int zahl);
|
||||
/*--------------------------------------------------------------------*\
|
||||
* get()
|
||||
* Entfernt die erste Zahl aus der Warteschlange und gibt sie zurück.
|
||||
* Rückgabewert:
|
||||
* Wert aus der Warteschlange oder QLEER bei leerer Queue
|
||||
\*--------------------------------------------------------------------*/
|
||||
int get(void);
|
||||
/*--------------------------------------------------------------------*\
|
||||
* isEmpty()
|
||||
* Prüft, ob die Warteschlange leer ist.
|
||||
* Rückgabewert:
|
||||
* TRUE, wenn leer
|
||||
* FALSE, wenn nicht leer
|
||||
\*--------------------------------------------------------------------*/
|
||||
Bool isEmpty(void);
|
||||
#endif /* QUEUE_H */
|
||||
Reference in new issue
Block a user