Beispielprogramme in C/Strukturiertes Programmieren mit C
Aus C64-Wiki
Zur Navigation springenZur Suche springen
Leicht erweiterte C-Version des Beispiels im Artikel Strukturiertes Programmieren mit BASIC
/*
Program: struct.c (cough cough)
URL: http://www.c64-wiki.de/index.php/Strukturiertes_Programmieren_mit_BASIC
Compiler: cc65, gcc
100 INPUT "NAME DES 1. KANDIDATEN "; A$
110 INPUT "STIMMENANZAHL "; A
120 INPUT "NAME DES 2. KANDIDATEN "; B$
130 INPUT "STIMMENANZAHL "; B
140 INPUT "NAME DES 3. KANDIDATEN "; C$
150 INPUT "STIMMENANZAHL "; C
160 LET S = A+B+C
170 LET A1 = A*100/S
180 LET B1 = B*100/S
190 LET C1 = C*100/S
200 PRINT "KANDIDAT ";A$; " ERHIELT";A1;"%"
210 PRINT "KANDIDAT ";B$; " ERHIELT";B1;"%"
220 PRINT "KANDIDAT ";C$; " ERHIELT";C1;"%."
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
struct Kandidat_s
{
uint8_t Name[200];
uint32_t Stimmen;
};
struct Kandidat_s Kandidat;
struct Kandidat_s *Kandidat_p;
uint8_t String[200];
uint16_t anzahlKandidaten, Zaehler;
uint32_t abgegebeneStimmen = 0;
void p_reset()
{
for (Zaehler = 0; Zaehler < anzahlKandidaten; ++Zaehler) --Kandidat_p;
}
void aufraeumen()
{
p_reset();
free(Kandidat_p);
}
void KandidatenEingabe(uint16_t Zaehler, struct Kandidat_s *Kandidat_p)
{
printf("\r\nName des %d. Kandidaten? ", Zaehler+1);
fgets(String, 200, stdin);
String[strcspn ( String, "\n\r" )] = '\0';
strcpy(Kandidat_p->Name, String);
printf("\r\nStimmenanzahl? ");
fgets(String, 16, stdin);
Kandidat_p->Stimmen = atol(String);
abgegebeneStimmen += Kandidat_p->Stimmen;
}
void Stimmerfassung()
{
printf("\r\nAnzahl der Kandidaten: ");
fgets( String, 3, stdin );
anzahlKandidaten = (uint8_t) atoi(String);
Kandidat_p = malloc(anzahlKandidaten * sizeof(Kandidat));
for (Zaehler = 0; Zaehler < anzahlKandidaten; ++Zaehler)
{
KandidatenEingabe(Zaehler, Kandidat_p);
++Kandidat_p;
}
}
void Stimmauszaehlung()
{
p_reset();
printf("\r\nAbgegebene Stimmen %ld: \r\n",abgegebeneStimmen);
for (Zaehler = 0; Zaehler < anzahlKandidaten; ++Zaehler)
{
printf("Kandidat %s erhielt %ld%%\r\n", Kandidat_p->Name,
Kandidat_p->Stimmen*100/abgegebeneStimmen);
++Kandidat_p;
}
}
void main(void)
{
Stimmerfassung();
Stimmauszaehlung();
aufraeumen();
}
Nochmal etwas erweitertes Beispiel mit Fehlerbehandlung, sortierter Kandidatenausgabe und Prozentausgabe mit einer Nachkommastelle:
/**
* Beispiel eines Stimmenauszähl-Programms.
*
* Die Anzahl der Kandidaten ist flexibel — der Speicher wird zur
* Laufzeit verwaltet.
*
* Es wird gezeigt, wie man auch ohne Gleitkommatypen Prozentzahlen mit
* einer Nachkommastalle realisieren kann.
*
* Ferner werden die Kandidaten vor der Ausgabe absteigend nach Stimmen
* sortiert.
*
* Ausserdem wurde versucht, auf Fehleingaben vom Benutzer zu reagieren,
* damit das Programm nicht abstürzt oder unsinnige Werte anzeigt.
*
* \TODO Es wird nicht überprüft, ob ein eingegebener Name leer ist oder
* bereits in den Kandidaten enthalten ist.
*/
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
/*
* Die Stimmen werden mit 1000 multipliziert, um eine Nachkommastelle
* zu bekommen, deshalb darf die Anzahl pro Kandidat nicht so gross werden,
* dass dadurch ein Überlauf entsteht.
*/
#define MAX_STIMMEN_PRO_KANDIDAT (INT32_MAX / 1000)
#if ((INT32_MAX / MAX_STIMMEN_PRO_KANDIDAT) < 256)
#error "Aufsummieren koennte zu Ueberlauf von Gesamtstimmen fuehren"
#endif
typedef int (*compare_func_t)(const void*, const void*);
/**
* \invariant stimmen <= MAX_STIMMEN_PRO_KANDIDAT
*/
typedef struct {
char name[MAX_NAME_LENGTH];
int32_t stimmen;
} Kandidat;
typedef struct {
uint8_t anzahl;
Kandidat *data;
} Kandidaten;
void remove_trailing_newline(char *s)
{
char *ptr = s + strlen(s);
if (ptr != s && ptr[-1] == '\n') ptr[-1] = '\0';
}
int Kandidat_compare(const Kandidat *a, const Kandidat *b)
{
int32_t result = b->stimmen - a->stimmen;
if (!result) return strcmp(a->name, b->name);
return result < 0 ? -1 : 1;
}
Kandidaten* Kandidaten_init(Kandidaten *kandidaten, uint8_t anzahl)
{
if ((kandidaten->data = calloc(anzahl, sizeof(*kandidaten->data)))) {
kandidaten->anzahl = anzahl;
return kandidaten;
} else {
kandidaten->anzahl = 0;
return NULL;
}
}
void Kandidaten_free(Kandidaten *kandidaten)
{
assert(kandidaten);
kandidaten->anzahl = 0;
free(kandidaten->data);
}
_Bool Kandidaten_eingabe(Kandidaten *kandidaten)
{
uint8_t i;
int16_t anzahl;
int32_t stimmen;
Kandidat *kandidat;
char buffer[20];
assert(kandidaten);
printf("Anzahl der Kandidaten: ");
fgets(buffer, sizeof(buffer), stdin);
anzahl = atoi(buffer);
putchar('\n');
if (anzahl < 1) {
puts("Weniger als 1 Kandidat ist sinnlos.");
return false;
}
if (!Kandidaten_init(kandidaten, anzahl)) {
puts("Konnte Kandidaten nicht initialisieren.");
return false;
}
for (i = 0; i < kandidaten->anzahl; ++i) {
kandidat = &kandidaten->data[i];
printf("\nName des %d. Kandidaten: ", i + 1);
fgets(kandidat->name, sizeof(kandidat->name), stdin);
remove_trailing_newline(kandidat->name);
while (true) {
printf("\nStimmenanzahl: ");
fgets(buffer, sizeof(buffer), stdin);
stimmen = atol(buffer);
if (stimmen < 0) {
puts("\nStimmanzahl muss >=0 sein!");
continue;
}
if (stimmen > MAX_STIMMEN_PRO_KANDIDAT) {
printf(
"\nPro Kandidat max %"PRIu32" Stimmen!",
MAX_STIMMEN_PRO_KANDIDAT
);
continue;
}
kandidat->stimmen = stimmen;
break;
}
putchar('\n');
}
return true;
}
void Kandidaten_sort(Kandidaten *kandidaten)
{
assert(kandidaten);
qsort(
kandidaten->data,
kandidaten->anzahl,
sizeof(*kandidaten->data),
(compare_func_t) Kandidat_compare
);
}
void Kandidaten_auswerten(Kandidaten *kandidaten)
{
uint8_t i;
int32_t stimmen, gesamt_stimmen;
div_t percent;
Kandidat *kandidat;
assert(kandidaten);
for (i = 0; i < kandidaten->anzahl; ++i) {
stimmen = kandidaten->data[i].stimmen;
assert(stimmen <= MAX_STIMMEN_PRO_KANDIDAT);
gesamt_stimmen += stimmen;
}
assert(gesamt_stimmen >= 0);
printf("\nAbgegebene Stimmen: %"PRIu32"\n", gesamt_stimmen);
if (gesamt_stimmen) {
Kandidaten_sort(kandidaten);
for (i = 0; i < kandidaten->anzahl; ++i) {
kandidat = &kandidaten->data[i];
percent = div(kandidat->stimmen * 1000 / gesamt_stimmen, 10);
assert(
percent.quot >= 0 && percent.quot <= 100
&& percent.rem >= 0 && percent.rem <= 9
);
printf(
" %2d.%01d%% fuer %s\n",
percent.quot,
percent.rem,
kandidat->name
);
}
}
}
int main(void)
{
Kandidaten kandidaten;
if (Kandidaten_eingabe(&kandidaten)) {
Kandidaten_auswerten(&kandidaten);
Kandidaten_free(&kandidaten);
}
return 0;
}