a2 Quelltext Dokumentation

This commit is contained in:
2021-10-14 16:21:48 +02:00
parent 63a2a864f3
commit ba25632650
2 changed files with 65 additions and 12 deletions

View File

@ -4,72 +4,125 @@
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
// der Makro "panicio" gibt einen Ein-/ Ausgabefehler aus und beendet das Programm mit einem Fehlercode.
#define panicio {\ #define panicio {\
perror(*filepath);\ perror(*filepath);\
return 1;\ return 1;\
} }
/* Ein Makro, der die nächste Zahl der Eingabedatei zurückgibt.
* In der Eingabedatei werden die Zahlen immer durch ein anderes Zeichen getrennt (Leerzeichen, newline-character, Punkt).
* Da die Funktion "strtol" den Zeiger "nextnumber" immer auf das erste Zeichen nach der verarbeiteten Zahl zeigen lässt,
* muss "nextnumber" um eins erhöht werden, um auf die nächste Zahl zu zeigen.*/
#define getNumber strtol(nextnumber + 1, &nextnumber, 10) #define getNumber strtol(nextnumber + 1, &nextnumber, 10)
// Struktur, die ein Hotel darstellt.
struct hotel { struct hotel {
uint_least16_t minutes; uint_least16_t minutes;
uint_least8_t rating; uint_least8_t rating;
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Schleife iteriert über die Argumente, die Dateipfade sind.
for(char **filepath = argv + 1; filepath - argv < argc; ++filepath) { for(char **filepath = argv + 1; filepath - argv < argc; ++filepath) {
printf("%s:\n", *filepath);
uint_least16_t numberHotels, totalMinutes; uint_least16_t numberHotels, totalMinutes;
struct hotel *hotels; struct hotel *hotels;
printf("%s:\n", *filepath);
{ {
char *inputText; char *inputText;
{ {
FILE *inputFile = fopen(*filepath, "rb"); FILE *inputFile = fopen(*filepath, "r"); // öffnet die Datei
if(inputFile == NULL) panicio; if(inputFile == NULL) panicio; // gibt möglichen Fehler aus
bool success; bool success;
/* Die Funktion "acl_ReadTextFile" liest die Datei aus und gibt den Inhalt als String zurück.
* Die Variable "success" wird je nach Erfolg modifiziert.*/
inputText = acl_ReadTextFile(inputFile, &success); inputText = acl_ReadTextFile(inputFile, &success);
if(!success) panicio; if(!success) panicio;
fclose(inputFile); fclose(inputFile); // schließt die Datei
} }
{ {
char *nextnumber; char *nextnumber;
/* Die Anzahl der Hotels muss noch den Makro "getNumber" verarbeitet werden,
* da dieser vorraussetzt, das der Zeiger "nextnumber" bereits definiert ist.
* Zudem wird noch Eins addiert, weil noch ein "Hotel" hinzugefügt wird,
* das den Zielpunkt darstellt.*/
numberHotels = strtol(inputText, &nextnumber, 10) + 1; numberHotels = strtol(inputText, &nextnumber, 10) + 1;
totalMinutes = getNumber; totalMinutes = getNumber; // gesamte Fahrzeit
// belegt den Speicher für ein Array mit allen Hotels
hotels = malloc(numberHotels * sizeof *hotels); hotels = malloc(numberHotels * sizeof *hotels);
// jedem Hotel des Arrays werden die jeweiligen Werte zugewiesen
for(uint_least16_t i = 0; i < numberHotels; ++i) { for(uint_least16_t i = 0; i < numberHotels; ++i) {
hotels[i].minutes = getNumber; hotels[i].minutes = getNumber;
/* "strtol" verarbeitet nur ganze Zahlen. Deshalb werden die beiden Ziffern einzeln
* verarbeitet. Da für die Bewertung ein Integer-Typ verwendet wird,
* ist die resultierende Bewertung das zehnfache der Bewertung in der Eingabedatei.
* Diese wird bei der Ausgabe wieder umgewandelt.*/
hotels[i].rating = 10 * getNumber; hotels[i].rating = 10 * getNumber;
hotels[i].rating += getNumber; hotels[i].rating += getNumber;
} }
hotels[numberHotels - 1] = (struct hotel){ .minutes = totalMinutes, .rating = 50};
} }
free(inputText); free(inputText); // freigeben des Speichers der ausgelesenen Textdatei
/* fügt den Zielort als "Hotel" hinzu, da der Algorithmus ein Hotel erst dann berücksichtigt,
* wenn das nächste Hotel außer Fahrtreichweite ist. Es gibt allerdings kein nächstes Hotel
* vom letzten Hotel, weshalb das letzte Hotel als Haltepunkt nicht in Betracht gezogen wird.
* Also wird der Zielort als "Hotel" hinmzugefügt, damit auch das letzte richtige Hotel
* verwendet werden kann.*/
hotels[numberHotels - 1] = (struct hotel){ .minutes = totalMinutes, .rating = 50};
} }
{ {
struct hotel hotelRoute[4]; struct hotel hotelRoute[4]; // speichert die Hotels, an denen gehalten wird
uint_least8_t stoppedHotels; uint_least8_t stoppedHotels; // Anzahl der gemachten Stops
/* In der Schleife wird versucht eine Route mit der Bewertung von mindestens 50 zu bilden.
* Wenn dies nicht erfolgrecih ist, wird es mit 49, 48, ... versucht bis eine Route gefunden wurde.*/
{ {
uint_least8_t rating = 50; uint_least8_t rating = 50;
do { do {
// Minuten die das letzte Hotel, bei dem angehalten wurde, vom Start entfertn ist
uint_least16_t lastHotelMinutes = 0; uint_least16_t lastHotelMinutes = 0;
// Zeiger zum letzten Hotel, dessen Bewertung mindestens "rating" ist.
struct hotel *possibleStop = NULL; struct hotel *possibleStop = NULL;
stoppedHotels = 0; stoppedHotels = 0; // setzt Anzahl der Stops zurück
// iteriert über die Hotels
for(struct hotel *currentHotel = hotels; currentHotel - hotels < numberHotels; ++currentHotel) { for(struct hotel *currentHotel = hotels; currentHotel - hotels < numberHotels; ++currentHotel) {
/* Wenn das aktuelle Hotel mehr als 360 Minuten vom letzten Hotel entfernt ist,
* muss das letzte Hotel verwendet werden an dem das Halten möglich war.*/
if(currentHotel->minutes - lastHotelMinutes > 360) { if(currentHotel->minutes - lastHotelMinutes > 360) {
/* Wenn das Halten nicht möglich ist oder bereits schon viermal
* gehalten wurde, muss es mit einer niedrigeren Bewertung versucht
* werden.*/
if(possibleStop == NULL || stoppedHotels >= 4) break; if(possibleStop == NULL || stoppedHotels >= 4) break;
// hängt das Hotel der Route an
hotelRoute[stoppedHotels] = *possibleStop; hotelRoute[stoppedHotels] = *possibleStop;
lastHotelMinutes = possibleStop->minutes; lastHotelMinutes = possibleStop->minutes;
// springt in der Schleife zurück zum Hotel, an dem gestoppt wurde
currentHotel = possibleStop; currentHotel = possibleStop;
++stoppedHotels; ++stoppedHotels;
} }
// Wenn die Bewertung hoch genug ist, kann gestoppt werden.
if(currentHotel->rating >= rating) possibleStop = currentHotel; if(currentHotel->rating >= rating) possibleStop = currentHotel;
} }
--rating; --rating;
/* Schleife läuft solange "rating" mindestens Eins ist, da es keine niedrigeren Bewertungen
* gibt. Wenn das letzte Hotel höchtens 360 Minuten vom Zielort entfernt ist, wurde
* erfolgreich eine Route gefunden und die Schleife wird beendet. Allerdings wird dies nur
* überprüft, wenn überhaupt an einem Hotel gehalten wurde, um den Zugriff auf nicht
* definierten Speicher zu vermeiden.*/
} while(rating && (!stoppedHotels || totalMinutes - hotelRoute[stoppedHotels - 1].minutes > 360)); } while(rating && (!stoppedHotels || totalMinutes - hotelRoute[stoppedHotels - 1].minutes > 360));
} }
// gibt die Hotels der Route aus.
for(struct hotel *hotelPrint = hotelRoute; hotelPrint - hotelRoute < stoppedHotels; ++hotelPrint) { for(struct hotel *hotelPrint = hotelRoute; hotelPrint - hotelRoute < stoppedHotels; ++hotelPrint) {
printf("Entfernung vom Start: %" PRIuLEAST16 " Minuten, Bewertung: %" PRIuLEAST8 "\n", hotelPrint->minutes, hotelPrint->rating); printf("Entfernung vom Start: %" PRIuLEAST16 " Minuten, Bewertung: %.1f\n", hotelPrint->minutes, (double)hotelPrint->rating / 10);
} }
} }
free(hotels); free(hotels); // gibt den Speicher des Hotelarrays frei
} }
} }