Finish Workbook
This commit is contained in:
parent
c436c18637
commit
1ea3bec7cd
1 changed files with 273 additions and 20 deletions
|
@ -1,12 +1,11 @@
|
|||
#+title: Workbook
|
||||
#+AUTHOR: Laskar Alexander Theuer/11378947
|
||||
|
||||
* Workbook für das Praktikum Algorithmen und Programmierung 1
|
||||
** Fachfragenkatalog
|
||||
*** Was ist der Unterschied zwischen ~Float~ und ~Double~?
|
||||
* Fachfragenkatalog
|
||||
** Was ist der Unterschied zwischen ~Float~ und ~Double~?
|
||||
~Float~ und ~Double~ werden beide genutzt, um Fließkommazahlen zu speichern. Der Unterschied liegt darin, dass ~Double~, wie der Name schon sagt, doppelte Genauikeit hat. Bei modernen Systemen hat ein ~float~ üblicherweise 32 bit, ein Double ~64~ bit.
|
||||
|
||||
*** Wofür werden ~structs~ verwendet, und welche Bestandteile werden benötigt?
|
||||
** Wofür werden ~structs~ verwendet, und welche Bestandteile werden benötigt?
|
||||
~Structs~ werden verwendet, um zusammenhängende Daten an einem Ort zu speichern. Genauer gesagt wird der Code im Computer dadurch in direkt nebeneinander liegenden Teilen des Arbeitsspeichers gespeichert. Structs bestehen immer aus dem Keyword ~struct~, gefolgt von den Namen, einer geöffneten geschweiften Klammer ~{~, Inhalten des struct, getrennt durch Kommata, einer schließenden geschweiften Klammer ~}~, abgeschlossen mit einem Semikolon. Struct selbst können, anders als Klassen, keine Methoden oder Funktionen enthalten, wohl aber function pointers. Hier ein Beispiel:
|
||||
#+begin_src C
|
||||
#include <stdbool.h> // Für den bool typedef, sowie true und false
|
||||
|
@ -26,7 +25,7 @@ void lebe_Person(struct Person* person) { // Implementation der Lebe Funktion au
|
|||
#+end_src
|
||||
Oft wird auch ein ~typedef struct StructName StructName~ verwendet, damit man nicht immer struct davor schreiben muss.
|
||||
|
||||
*** Was ist der Unterschied zwischen Syntax und Semantik?
|
||||
** Was ist der Unterschied zwischen Syntax und Semantik?
|
||||
Syntax bezeichnet die korrekte Formulierung von Code auf einer rein Formellen Basis. Sind alle Semikolons da, wo sie sein sollen? Sind alle (geschweiften) Klammern richtig gesetzt? Wurden korrekte Typen angegeben? Diese Dinge werden überprüft während das Programm kompiliert wird. Bei Fehlern wird der Compiler die Kompilation beenden und einen Fehler ausgeben.
|
||||
Semantik hingegen bezeichnet die Logik, die das Programm ausführt. Werden die richtigen Konditionen überprüft? Werden Variablen oder Konstanten die richtigen Werte zugewiesen? Werden die richtigen Funktionen aufgerufen?
|
||||
Beispiel für ein Programm mit einem Syntaxfehlern:
|
||||
|
@ -68,7 +67,7 @@ int main() {
|
|||
#+end_src
|
||||
Dieser Code würde ~Es ist keine Zahl.~ ausgeben, obwohl es definitiv eine Zahl ist. Die meisten bugs werden durch Semantikfehler verursacht, selten sind diese auch in der Standardbibliothek vorhanden. Durch Semantikfehler entstehen auch größere Probleme, wie z. B. NULL-ptr dereference, free-after-use etc.
|
||||
|
||||
*** Was versteht man unter dem ~fall-through~? Wie ist diese verhalten zu verhindern, wann könnte es nützlich sein?
|
||||
** Was versteht man unter dem ~fall-through~? Wie ist diese verhalten zu verhindern, wann könnte es nützlich sein?
|
||||
~fall-through~ beschreibt ein Verhalten bei ~switch~ statements, wenn nach einem ~case~ Block kein ~break;~ kommt und dadurch der nächste Fall bis zu einem ~break~ ausgeführt wird. Als Beispiel:
|
||||
#+begin_src c
|
||||
#include <stdio.h>
|
||||
|
@ -126,7 +125,7 @@ Man könnte diesen Code zwar grundsätzlich anders einfacher formulieren, aber d
|
|||
Oft sind ~fall-throughs~ unabsichtlich. Ein Entwickler hat ein ~break;~ vergessen, weshalb sie in solchen Fällen /Semantikfehler/ sind.
|
||||
Dies ist aber nicht immer der Fall. ~Fall-throughs~ sind eine durchaus nützliche Programmierpraxis, wenn der geswitchte Wert als Einstiegspunkt verstanden wird und damit in eine Menge von immer gleich bleibende Operationen auch erst an einem späteren Punkt eingestiegen werden kann, zum Beispiel wenn bestimmte Bedingungen bereits erfüllt sind.
|
||||
|
||||
*** Erklären Sie den konditionalen (ternären) Operator Anhand eines Beispieles.
|
||||
** Erklären Sie den konditionalen (ternären) Operator Anhand eines Beispieles.
|
||||
Der /ternäre Operator/ folgt der Syntax ~Bedingung ? ausdruck_wenn_war : ausdruck_wenn_falsch;~. Hier ein Beispiel, wo zugewiesen wird, ob jemand Erwachsen oder Minderjährig ist, abhängig vom Alter.
|
||||
#+BEGIN_SRC C
|
||||
#include <stdio.h>
|
||||
|
@ -142,7 +141,7 @@ int main() {
|
|||
#+END_SRC
|
||||
In diesem Beispiel gibt der Nutzer ein numerisches Alter ein und Mithilfe des ternären Operators wird dem Nutzer entweder Erwachsener oder Minderjähriger zugewisen. Minderjähriger falls Alter < 18 ist, in allen anderen Fällen Erwachsener.
|
||||
|
||||
*** Was ist der Unterschied zwischen Pre- und Postinkrementation und wie werden sie notiert?
|
||||
** Was ist der Unterschied zwischen Pre- und Postinkrementation und wie werden sie notiert?
|
||||
Beide nutzen den /Inkrementationsoperator/, das ~++~. Bei der Preinkrementation wird Die Variable sofort inkrementiert, und der alte Wert kann nicht noch anderswo zwischengespeichert werden. Pre, also vor, steht dabei für /vor dem zuweisen/. Sie wird mit ~++a~ notiert, wenn a die Variable ist, die inkrementiert werden soll. Bei der Postinkrementation, post steht hier für nach, wird die Variable inkrementiert, *nachdem* der Wert einer anderen Variable zugewiesen wurde, wenn man das machen möchte. Die Notation hierfür ist ~a++~, wenn a die Variable ist, die inkrementiert werden soll. Zur Verdeutlichung kann dieser Code helfen:
|
||||
#+BEGIN_SRC C
|
||||
#include <stdio.h>
|
||||
|
@ -168,7 +167,7 @@ D: 6
|
|||
#+END_SRC
|
||||
Daran kann man das Verhalten gut erkennen.
|
||||
|
||||
*** Was ist der Unterschied zwischen einer ~while~ und einer ~do-while~ Schleife?
|
||||
** Was ist der Unterschied zwischen einer ~while~ und einer ~do-while~ Schleife?
|
||||
Beide Schleifen führen Bedingungen aus, solange eine bestimmte Bedingung erfüllt ist. Der große Unterschied dabei ist, dass bei der while-Schleife, der Code unter Umständen gar nicht ausgeführt wird, wenn die Eingangsbedingung nicht wahr ist. Bei der do-while Schleife wird der Code mindestens einmal ausgeführt. Hier beide Schleifen in einem Code Beispiel:
|
||||
#+BEGIN_SRC C
|
||||
#include <stdio.h>
|
||||
|
@ -184,21 +183,21 @@ int main() {
|
|||
}
|
||||
#+END_SRC
|
||||
|
||||
*** Welche Probleme können bei einer rekursiven Implementation einer Funktion auftreten?
|
||||
** Welche Probleme können bei einer rekursiven Implementation einer Funktion auftreten?
|
||||
Rekursive Implementation können verschiedene Probleme aufweisen. Ein häufiges Problem ist eine extrem lange Laufzeit (große Zeitkomplexität). in gutes Beispiel hierfür ist eine rekursive Berechnung einer Zahl aus der Fibonacci Reihe (ohne caching). Hierbei werden häufig immer wieder die gleichen Zahlen als Zwischenschritt berechnet, weshalb die Laufzeit für die Berechnung vom 100sten Element viele Jahre dauert. Dadurch sind rekursive Ansätze für große Berechnungen meist aus Performance gründen nicht sinnvoll. Ein anderes Problem wäre unendliche Laufzeit, wenn ein bestimmte Bedingung gar nicht erfüllt werden kann, in welchem Fall sich die Funktion selbst immer wieder aufruft und dadurch nie endent. So etwas kann in der Implementation verhindert werden.
|
||||
|
||||
*** Was ist der Unterschied zwischen einer Call-by-Reference und einer Call-by-Value Funktion? Nennen Sie für beide Arten Beispielfunktionen aus der C-Standardbibliothek.
|
||||
** Was ist der Unterschied zwischen einer Call-by-Reference und einer Call-by-Value Funktion? Nennen Sie für beide Arten Beispielfunktionen aus der C-Standardbibliothek.
|
||||
Bei einer Call-by-Value funktion, wird direkt ein Wert in die Funktion gegeben. Dieser wird dann kopiert und alle Modifikationen dieses Wertes passieren in der Kopie, statt in dem Wert (z. B. einer Variable), die der Funktion direkt gegeben wurde. Eine Call-By-Reference Funktion bekommt stattdesssen einen pointer zu einer Variable. Dadurch das statt einem Wert eine Speicheradresse gegeben wird, wird der Wert der Variable direkt modifiziert. Dementsprechend sind call-by-reference Funktionen genau dann sinnvoll, wenn der Wert der Variable in der Funktion selbst modifiziert werden soll.
|
||||
Ein Besispiel für eine Call-By-Reference Funktion wäre zum Beispiel ~scanf()~ auf ~stdio.h~, welche eine Speicheradresse zu dem Buffer bekommt, in den geschrieben werden soll.
|
||||
Ein Beispiel für eine Call-By-Value Funktion ist z. B. ~strcmp()~ aus ~string.h~, in der zwei Strings verglichen werden. Da die strings hier selbst nicht bearbeitet werden müssen, sondern nur die Werte verglichen werden, ist dieser Ansatz hier sinnvoller.
|
||||
|
||||
*** Aus welchem Grund sollte die ~goto~-Anweisung bei der Programmierung grundsätzlich vermieden werden?
|
||||
** Aus welchem Grund sollte die ~goto~-Anweisung bei der Programmierung grundsätzlich vermieden werden?
|
||||
Code, der über ~goto~ strukturiert ist, neigt dazu sehr unleserlich, unübersichtlich und schwer verständlich zu werden. Es gibt allerdings Ausnahmefälle, in denen ~goto~ die Leserlichkeit verbessern kann, diese sind jedoch selten. ~goto~ Kann außerdem dazu genutzt werden, um die Struktur des C codes ähnlicher zu der von Assembly code zu machen, was in seltenen Niechenfällen nützlich sein kann.
|
||||
|
||||
*** Wodurch wird ein Character-Array zu einem String?
|
||||
** Wodurch wird ein Character-Array zu einem String?
|
||||
Strings sind ~char~ arrays, die mit einem Besondern byte, also ~char~, dem sogenannten Null-Terminator (~'\0'~), beendet werden. Dadurch können Funktionen, die mit den strings arbeiten, erkennen, das a) der gegebene Array tatsächlich ein String ist und b) der String am Ende tatsächlich beendet ist.
|
||||
|
||||
*** Welche Informationen befinden sich in einer Deklarationsdatei (Header)?
|
||||
** Welche Informationen befinden sich in einer Deklarationsdatei (Header)?
|
||||
Ein Header enthält hauptsächlich leere Implementation von Funktionen (Nur die Kopfzeile wo Name, typ und Parameter spezifiziert werden), ~structs~, aber keine Implementationen von structs, d. H. in dem struct werden keine Werte zugeordnet, und außerdem Deklarationen von globalen Variablen (aber nur namentlich, ohne Wertzuweisung), Makros und typedefs. Zudem findet in headern oft das inkludieren von Bibliotheken statt, die dann in dem Progran genutzt werden. Die Funktionen werden dann in Dateien mit dem gleichen Namen (Mit der Dateiendung .c) implementiert. Diese Datei inkludiert den Header. Ferner gibt es in header Dateien oft sogenannte /include guards/, welche dazu dienen, redundaten imports zu vermeiden. Ein Beispiel für eine Header Datei wäre zum Beispiel:
|
||||
#+BEGIN_SRC C
|
||||
// Code aus library.h
|
||||
|
@ -260,7 +259,7 @@ int main(){
|
|||
}
|
||||
#+END_SRC
|
||||
|
||||
*** Was ist der Prä-Prozessor, wie wird er angesprochen und welche Aufgaben erledigt er?
|
||||
** Was ist der Prä-Prozessor, wie wird er angesprochen und welche Aufgaben erledigt er?
|
||||
Der Präprozessor in C ist ein Teil des Kompilierungsvorgangs jedes C-Programms. Er übernimmt im wesentlichen drei Aufgaben:
|
||||
1. Macro Substitutionen: Alle Konstanten, die mit ~#define~ definiert wurden, werden textbasiert ersetzt. So wird zum Beispiel ~ENOMOM~, der Errorcode für wenn kein Speicher mehr verfügbar ist, durch die Zahl 12 ersetzt, vorrausgesetzt ~errno.h~ wurde inkludiert.
|
||||
2. Datei Inklusion: Alle aussagen die mit ~#include~ beginnen, werden ausgeführt, bedeutet die Header files werden direkt in den Source Code der Datei kopiert und dann wird weiter kompiliert.
|
||||
|
@ -275,8 +274,8 @@ Wenn in der Kernel Konfiguration also die erweiterte Sicherheit aktiviert wurde
|
|||
|
||||
Allgemein sprechen also alle Aussagen die mit ~#~ beginnen den Präprozessor an. Dieser macht dann, wie er Name schon sagt, vor der tatsächlichen Kompilierung Änderungen am Code, zum Beispiel werden Makros erweitert oder bestimmte Codesegmente werden entfernt oder hinzugefügt, Quellcode aus anderen Dateien wird in die Datei hinzugefügt oder es werden Anweisungen an den Compiler für debugging an den Compiler weitergegeben.
|
||||
|
||||
** Vorbereitungsaufgaben
|
||||
*** 1. Vorbereitungsaufgabe
|
||||
* Vorbereitungsaufgaben
|
||||
** 1. Vorbereitungsaufgabe
|
||||
#+BEGIN_SRC C
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -310,16 +309,270 @@ int main() {
|
|||
}
|
||||
#+END_SRC
|
||||
|
||||
*** 2. Vorbereitungsaufgabe
|
||||
** 2. Vorbereitungsaufgabe
|
||||
#+BEGIN_SRC C
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define ERRORRETURN 10787253
|
||||
#define ARRSIZE 4096
|
||||
#define EXITVAL 15326
|
||||
#define ENOCUSTOMER 692137
|
||||
#define ENOPRODUCT 691337
|
||||
|
||||
struct Product {
|
||||
int id;
|
||||
char* name;
|
||||
double price;
|
||||
int amount;
|
||||
};
|
||||
|
||||
struct Customer {
|
||||
char* name;
|
||||
int id;
|
||||
};
|
||||
|
||||
int find_first_free_customer(struct Customer* array[]) {
|
||||
for (int i = 0; i < ARRSIZE; i++) {
|
||||
if (array[i] == NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_first_free_product(struct Product* array[]) {
|
||||
for (int i = 0; i < ARRSIZE; i++) {
|
||||
if (array[i] == NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_product_index(int id, struct Product* array[]) {
|
||||
for (int i = 0; i < ARRSIZE; i++) {
|
||||
if (array[i] != NULL && array[i]->id == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
errno = ENOPRODUCT;
|
||||
printf("Mit der eingegeben Produktnummer konnte kein Produkt gefunden werden.\n");
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
int find_customer_index(int id, struct Customer* array[]) {
|
||||
for (int i = 0; i < ARRSIZE; i++) {
|
||||
if (array[i] != NULL && array[i]->id == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
errno = ENOCUSTOMER;
|
||||
printf("Mit der eingegeben Kundennummer konnte kein Kunde gefunden werden.\n");
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
int add_product(struct Product* products[]) {
|
||||
int id, amount;
|
||||
char name[100];
|
||||
double price;
|
||||
|
||||
printf("**********************\n");
|
||||
printf("* WWS Produkteingabe *\n");
|
||||
printf("**********************\n");
|
||||
printf("Bitte geben Sie eine Produktnummer ein: ");
|
||||
scanf("%d", &id);
|
||||
printf("Bitte geben Sie einen Produktnamen ein: ");
|
||||
scanf("%99s", name);
|
||||
printf("Bitte geben Sie einen Preis für das Produkt ein: ");
|
||||
scanf("%lf", &price);
|
||||
printf("Bitte geben Sie die aktuelle Anzahl im Inventar: ");
|
||||
scanf("%d", &amount);
|
||||
|
||||
struct Product* new_product = (struct Product*)malloc(sizeof(struct Product));
|
||||
if (!new_product) {
|
||||
printf("Fehler beim Speicher zuweisen.");
|
||||
errno = ENOMEM;
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
new_product->id = id;
|
||||
new_product->name = strdup(name); // Duplicate string to avoid issues.
|
||||
new_product->price = price;
|
||||
new_product->amount = amount;
|
||||
|
||||
int index = find_first_free_product(products);
|
||||
if (index == -1) {
|
||||
free(new_product);
|
||||
printf("Kein freier Platz für Produkte.");
|
||||
errno = ENOMEM;
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
products[index] = new_product;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_customer(struct Customer* customers[]) {
|
||||
int id;
|
||||
char name[100];
|
||||
|
||||
printf("*********************\n");
|
||||
printf("* WWS Kundeneingabe *\n");
|
||||
printf("*********************\n");
|
||||
printf("Bitte geben Sie eine Kundennummer ein: ");
|
||||
scanf("%d", &id);
|
||||
printf("Bitte geben Sie einen Kundennamen ein: ");
|
||||
scanf("%99s", name);
|
||||
|
||||
struct Customer* new_customer = (struct Customer*)malloc(sizeof(struct Customer));
|
||||
if (!new_customer) {
|
||||
printf("Fehler beim Speicher zuweisen.");
|
||||
errno = ENOMEM;
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
new_customer->id = id;
|
||||
new_customer->name = strdup(name); // Duplicate string to avoid issues.
|
||||
|
||||
int index = find_first_free_customer(customers);
|
||||
if (index == -1) {
|
||||
free(new_customer);
|
||||
printf("Kein freier Platz für Kunden.");
|
||||
errno = ENOMEM;
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
customers[index] = new_customer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_product(struct Product* products[]) {
|
||||
int id;
|
||||
|
||||
printf("**********************\n");
|
||||
printf("* WWS Produktausgabe *\n");
|
||||
printf("**********************\n");
|
||||
printf("Bitte geben Sie die gesuchte Produktnummer ein: ");
|
||||
scanf("%d", &id);
|
||||
|
||||
int index = find_product_index(id, products);
|
||||
if (index == ERRORRETURN) {
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
struct Product* product = products[index];
|
||||
printf("======================\n");
|
||||
printf("Produktnummer: %d\n", product->id);
|
||||
printf("Name: %s\n", product->name);
|
||||
printf("Einzelpreis: %.2lf\n", product->price);
|
||||
printf("Anzahl: %d\n", product->amount);
|
||||
printf("Gesamtpreis: %.2lf\n", product->price * product->amount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_customer(struct Customer* customers[]) {
|
||||
int id;
|
||||
|
||||
printf("*********************\n");
|
||||
printf("* WWS Kundenausgabe *\n");
|
||||
printf("*********************\n");
|
||||
printf("Bitte geben Sie die gesuchte Kundennummer ein: ");
|
||||
scanf("%d", &id);
|
||||
|
||||
int index = find_customer_index(id, customers);
|
||||
if (index == ERRORRETURN) {
|
||||
return ERRORRETURN;
|
||||
}
|
||||
|
||||
struct Customer* customer = customers[index];
|
||||
printf("=====================\n");
|
||||
printf("Kundennummer: %d\n", customer->id);
|
||||
printf("Name: %s\n", customer->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int menu(struct Customer* customers[], struct Product* products[]) {
|
||||
int input;
|
||||
|
||||
printf("**********************\n");
|
||||
printf("* TH Warenwirtschaft *\n");
|
||||
printf("**********************\n");
|
||||
printf("Optionen:\n");
|
||||
printf("1. Produkteingabe\n");
|
||||
printf("2. Kundeneingabe\n");
|
||||
printf("3. Produktausgabe\n");
|
||||
printf("4. Kundenausgabe\n");
|
||||
printf("5. Verlassen\n");
|
||||
printf("Eingabe: ");
|
||||
scanf("%d", &input);
|
||||
|
||||
errno = 0;
|
||||
|
||||
switch (input) {
|
||||
case 1:
|
||||
add_product(products);
|
||||
if (errno != 0) {return ERRORRETURN;}
|
||||
break;
|
||||
case 2:
|
||||
add_customer(customers);
|
||||
if (errno != 0) {return ERRORRETURN;}
|
||||
break;
|
||||
case 3:
|
||||
print_product(products);
|
||||
if (errno != 0) {return ERRORRETURN;}
|
||||
break;
|
||||
case 4:
|
||||
print_customer(customers);
|
||||
if (errno != 0) {return ERRORRETURN;}
|
||||
break;
|
||||
case 5:
|
||||
return EXITVAL;
|
||||
default:
|
||||
printf("Ungültige Eingabe. Bitte erneut versuchen.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
errno = 0;
|
||||
int menuval = 0;
|
||||
struct Customer* customers[ARRSIZE] = {NULL};
|
||||
struct Product* products[ARRSIZE] = {NULL};
|
||||
|
||||
while (menuval == 0) {
|
||||
menuval = menu(customers, products);
|
||||
}
|
||||
|
||||
return errno;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** 3. Vorbereitungsaufgabe:
|
||||
*** Call-By-Reference
|
||||
Call-By-Reference wird immer dann verwendet, wenn Variablen direkt berbeitet werden müssen, zum Beispiel dann, wenn direkt in ein Array geschrieben wird. An einigen anderen Stellen wird Call-By-Reference auch zur Effizienz benutzt, um Dinge wie die Struct arrays nicht neu in den Speicher kopieren zu müssen (ähnlich wie Java diese Dinge handhabt).
|
||||
*** Call-By-Value
|
||||
Call-By-Value wird dann benutzt, wenn die Werte von Variablen nur gelesen werden müssen. Hier kurz zu allen verwendeten Funktionen, ob diese Call-By-Value oder Call-By-Reference verwenden, und warum.
|
||||
*** Funktionsbeispiele
|
||||
~printf~ verwendet Call-By-Value, weil nur einzelne Variablen kopiert und nur zur Ausgabe gelesen werden müssen.
|
||||
~scanf~ verwendet Call-By-Reference, weil direkt in die Speicheradressen der jeweiligen Variable geschrieben wird.
|
||||
~malloc~ verwendet Call-By-Value. Das Argument ist nur eine Zahl, die angibt wie viel Speicher zugewiesen werden soll. Dafür wird ein Pointer zur Speicheradresse zurückgegeben.
|
||||
~sizeof~ verwendet ebenfalls Call-By-Value. Hier wird ein Datentyp und keine Variable selbst angegeben.
|
||||
~free~ ist eine Call-By-Reference Funktion. Der Speicherplatz an der Speicheradresse der gegebenen Variable wird freigegeben, von daher ist nur die Speicheradresse wichtig, der Wert der Variable uninteressant.
|
||||
~find_first_free_customer~ Benutzt für bessere Effizienz beim Aufruf Call-By-Referene.
|
||||
~find-first-free_product~ Benutzt für bessere Effizienz beim Aufruf Call-By-Referene.
|
||||
~find_product_index~ Benutzt Call-By-Value für die ID, da hier nur der Wert der Variable wichtig ist, und Call-By-Reference für den Array, weil das effizienter ist.
|
||||
~find_customer_index~ Siehe oben.
|
||||
~add_product~ verwendet Call-By-Reference, da direkt in das Array geschrieben werden muss.
|
||||
~add customer~ siehe oben.
|
||||
~print_product~ verwendet Call-By-Reference, da innerhalb der Funktion Call-By-Reference Aufrufe zum gleichen Array passieren, hier ist die Begründung auch wieder Effizienz.
|
||||
~print_customer~ siehe oben.
|
||||
~menu~ Benutzt Call-By-Reference, da aus der Funktion diverse Call-By-Reference Aufrufe gemacht werden müssen, und Dinge wie das Schreiben in Arrays für die gesamte Laufzeit des Programs bestehen müssen.
|
||||
~main~ hat keine Parameter.
|
||||
|
|
Loading…
Reference in a new issue