C-Kurs/Zahlen sagen/Musterlösung
< C-Kurs | Zahlen sagen
Version vom 11. September 2010, 13:06 Uhr von P.brodmann (Diskussion | Beiträge)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <limits.h> /** Größe des Puffers für den Ergebnisstring */ #define BUFFER_SIZE 1000 /** Einerstellen zur allgemeinen Zusammensetzung. */ const char* EINER[] = {NULL, "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun"}; /** Zehnerstellen zur allgemeinen Zusammensetzung */ char* ZEHNER[] = {NULL, "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig"}; /** Anzahl der vorhandenen Ausnahmen */ #define ANZAHL_AUSNAHMEN 18 /** Ausnahmen, die sich nicht zusammensetzen lassen. */ char* AUSNAHMEN[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "elf", "zwölf", NULL, NULL, NULL, "sechzehn", "siebzehn"}; /** Anzahl der vorhandenen 1000er-Potenzen */ #define ANZAHL_POTENZEN 4 /** 1000er-Potenzen in ihrer Einzahl */ char* POTENZEN_SINGULAR[] = {"", "tausend", " Million ", " Milliarde ", " Billion "}; /** 1000er-Potenzen in ihrer Mehrzahl */ char* POTENZEN_PLURAL[] = {"", "tausend", " Millionen ", " Milliarden ", " Billionen "}; /** * Kopiert die übergebene Zahl 0 < x < 1000 als Zahlwort * in den übergebenen Puffer. */ void say_short_number(long int x, char *buffer, int bufsize) { /* Hunderterstelle ausrechnen */ int hunderter = x/100; if (hunderter > 0) { /* an den Pufferstring anhängen */ if (hunderter == 1) { /* Ausnahme: "einhundert" statt "einshundert" */ strncat(buffer, "ein", bufsize-strlen(buffer)-1); } else { strncat(buffer, EINER[hunderter], bufsize-strlen(buffer)-1); } strncat(buffer, "hundert", bufsize-strlen(buffer)-1); /* Hunderterstelle entfernen */ x %= 100; } if ((x < ANZAHL_AUSNAHMEN) && (AUSNAHMEN[x] != NULL)) { /* eine Ausnahme wie "zwölf", oder */ strncat(buffer, AUSNAHMEN[x], bufsize - strlen(buffer) - 1); } else { /* Rest aus Einer- und Zehnerstelle zusammensetzen */ int zehner = x/10, einer = x%10; if (einer > 0) strncat(buffer, EINER[einer], bufsize - strlen(buffer) - 1); if (zehner > 0) { if ((zehner > 1) && (einer > 0)) strncat(buffer, "und", bufsize - strlen(buffer) - 1); /* ab 20 ein "und" einfügen */ strncat(buffer, ZEHNER[zehner], bufsize - strlen(buffer) - 1); } } } /** * Generiert die natürlichsprachliche Repräsentation (Zahlwort) der * übergebenen Zahl und kopiert diese in den angegebenen Puffer. */ void say_number(long int x, char* buffer, int bufsize) { int i; /* Der Null kommt wie immer eine Sonderbehandlung zugute */ if (x == 0) { strncat(buffer, "null", bufsize - strlen(buffer) - 1); return; } /* Alle relevanten 1000er-Potenzen durchgehen */ for (i=ANZAHL_POTENZEN-1; i>=0; i--) { /* Potenz für relevante Stellen ausrechnen */ long int power = floor(pow(10, i*3) + 0.5); /* Stellen für diese Potenz extrahieren */ int value = x/power; if (value > 0) { if ((value == 1) && (i >= 1)) { if (i == 1) { /* Ausnahme: "eintausend" statt "einstausend" */ strncat(buffer, "ein", bufsize - strlen(buffer) - 1); } else { /* Ausnahme: "eine Million" etc. statt "eins Million" */ strncat(buffer, "eine", bufsize - strlen(buffer) - 1); } /* Einzahl von Million etc. berücksichtigen */ strncat(buffer, POTENZEN_SINGULAR[i], bufsize - strlen(buffer) - 1); } else { say_short_number(value, buffer, bufsize); strncat(buffer, POTENZEN_PLURAL[i], bufsize - strlen(buffer) - 1); } /* bereits ausgegebene Stellen abschneiden */ x %= power; } } } int main(int argc, char **argv) { long int number; char *buffer; /* überprüfen, ob notwendige Kommandozeilenparameter angegeben wurden */ if (argc != 2) { printf("Usage: %s NUMBER \n", argv[0]); exit(1); } /* numerischen String zu Ganzzahl konvertieren */ number = atol(argv[1]); if (number <= 0 || number == LONG_MAX) { printf("Invalid number.\n"); exit(1); } /* Puffer für Ergebnisstring allozieren */ buffer = malloc(BUFFER_SIZE); if (!buffer) { printf("Unable to allocate memory.\n"); exit(1); } /* Speicher mit Nullbyte initialisieren (= leerer String) */ buffer[0] = '\0'; /* Zahlwort in den Puffer schreiben */ say_number(number, buffer, BUFFER_SIZE); /* und ausgeben */ printf("%s\n", buffer); /* Speicher freigeben */ free(buffer); /* Alles ok, Fehlercode 0 */ return 0; }