Block 4 - Zeiger und Datenstrukturen
Initialisierung von Datenstrukturen
Übungen
1.) Bodenfeuchtigkeit
Definieren Sie ein Struct, welches die Bodenfeuchtigkeit (float) sowie die X- und Y-Koordinaten (int) speichert.
2.) Raumtemperatur
Definieren Sie ein Struct, welches die Raumnummer (String) sowie die Temperatur (float) speichert.
3.) Person
Es sollen folgende Daten einer Person gespeichert werden:
Name (String)
Raumnummer (String)
Alter (unsigned int)
Einstellungsjahr (int)
Definieren Sie das passende Struct.
4.) Datenzugriff
Wir verwenden nun das Struct aus der vorherigen Aufgabe (Person). Sie haben bereits eine Instanz davon definiert und „meyer“ genannt. Diese Person ist nun ein Jahr älter geworden. Wie ändern Sie das Alter (nur das Alter)?
5.) Strings in Strukturen Initialisieren
Wenn Sie strings in einem struct verwenden, müssen Sie diese etwas komplizierter initialisieren. Dafür benutzt man oft die Funktion strcnpy()
. Recherchieren Sie selbstständig, wie man diese nutzt. Initialisieren Sie nun den kompletten struct „meyer“.
6.) String
Eine andere Möglichkeit, strings zu erzeugen, ist String zu benutzen. Das ist strenggenommen eine Klasse, die wir erst im zweiten Semester behandeln werden, aber man kann sie hier gut nutzen, auch ohne die komplette Theorie dahinter zu kennen. Recherchieren Sie selbstständig, wie man sie nutzt und schreiben Sie Ihr Code von der vorherigen Aufgabe damit um. Sie müssen auch die Definition der Struktur ändern.
7.) Komplexe Zahlen
Definieren Sie ein Struct, in dem Sie eine komplexe Zahl (re, im: int) speichern können.
8.) Temperaturdaten
Erstellen Sie eine Datenstruktur, die folgende Angaben zu Temperaturdaten enthält: • Ort der Messung (String, z.B. „Bremen“) • Datum (vorzeichenlose 32-Bit-Ganzzahl, z.B. 20191120 für den 20. November 2019) • Uhrzeit (vorzeichenlose 16-Bit-Ganzzahl, z.B. 1430 für 14:30 Uhr) • Temperatur in Grad Celsius (Fließkommazahl)
Lösungen
Lösung zu Aufgabe 1.):
Lösung zu Aufgabe 2.):
Lösung zu Aufgabe 3.):
Lösung zu Aufgabe 4.):
Lösung zu Aufgabe 5.):
Lösung zu Aufgabe 6.):
Lösung zu Aufgabe 7.):
Datenstrukturen programmieren
Video einfügen: "Code Beispiel: Struct"
Kommentiertes Beispiel
Unten sehen Sie ein Beispiel, wie mit Datenstrukturen programmiert wird. Schauen Sie sich das Beispiel an und verstehen Sie, wie der Code funktioniert.
Übungsaufgaben
1.) Menschen
Erzeugen Sie ein Struct, welches das Geburtsjahr (int) sowie den Namen (String) eines Menschen enthält. Erzeugen Sie folgende Menschen:
Lieschen Müller, Geboren 1999
Max Mustermann, Geboren 1980
Willi Wolff, Geboren 2010
Geben Sie Namen und Geburtsjahr über den Seriellen Monitor aus.
2.) Menschen mit Funktion
Basierend auf der vorherigen Übung: Schreiben Sie eine Funktion, die Name und Alter der Personen ausgibt. Diese Funktion soll als Parameter das Struct vom Type Mensch erhalten und keinen Rückgabewert liefern. Nennen Sie die Funktion „printMensch“ und nutzen Sie diese, um die Structs erneut auszugeben.
3.) Menschen im Array
Sie können auch ein Array bestehend aus Structs erstellen. Ändern Sie das Programm aus dem vorhergegangenen Beispiel wie folgt ab:
Die drei Menschen werden in einem Array gespeichert.
Die Namen und die Geburtsdaten werden in einer
for
-Schleife ausgegeben.
4.) Menschen altern
Ändern Sie das Beispiel aus der vorherigen Übung wie folgt ab:
Statt des Geburtsjahres wird nun das aktuelle Alter ausgegeben
Alle Menschen altern in der
loop()
-Funktion 1 Jahr pro Sekunde. Geben Sie das Alter entsprechend aus.
5.) Menschen sterben...
Wir nehmen an, dass alle Menschen genau 100 Jahre alt werden. Passen Sie das vorherige Programm so an, dass Menschen über 100 Jahre nicht mehr ausgegeben werden. Markieren Sie diese als tot, indem Sie das Geburtsjahr auf -1 setzten.
6.) Menschen sterben 2.0
Passen Sie das vorherige Beispiel so an, dass der Zustand des Menschen in einer zusätzlichen Variable im Struct gespeichert wird. Das Geburtsjahr soll dabei erhalten bleiben.
7.) Komplexe Zahlen
Berechnen Sie das Quadrat der komplexen Zahl 4+j3 in Arduino. Nutzen Sie ein Struct zur Speicherung der Werte.
8.) Koordinaten
Erzeugen Sie ein Struct, welches eine X- und eine Y-Koordinate (beides int) speichert. Erzeugen Sie 4 Koordinaten und speichern Sie diese in einem Array:
X= 7, Y=12
X=2, Y=10
X=15, Y=1
X=1, Y=2
Geben Sie die Koordinaten aus. Schreiben Sie die Funktion printKoordinate für die Ausgabe. Der Parameter der Funktion ist die jeweilige Koordinate. Geben Sie alle Koordinaten in der loop()- Funktion aus.
9.) Distanz zwischen Koordinaten
Basierend auf dem vorherigen Beispiel: Schreiben Sie eine Funktion, welche die Distanz zwischen zwei Koordinaten bestimmt (Pythagoras). Geben Sie die Distanzen zwischen allen Koordinaten aus.
Hinweis: Die Distanz kann eine Nachkommastelle enthalten.
10.) Höchste Temperatur suchen
Gegeben ist ein Array mit 10 Elementen. Jedes Element enthält jeweils die Datenstruktur, die in Aufgabe 4.1erstellt wurde. a) Wie wird das Array deklariert? b) Schreiben Sie einen Codeschnipsel, der die Elemente als Tabelle auf dem seriellen Monitor ausgibt. EineTabellenzeile soll z.B. so aussehen: Bremen 20191120 1430 -1.6 Sie müssen kein vollständiges Programm schreiben, sondern nur den Code angeben, der die 10 Elementeausgibt. Verwenden Sie für den Zugriff auf das Array den im Aufgabenteil a) deklarierten Arraynamen.
Lösungen
Lösung zu Aufgabe 1.):
Lösung zu Aufgabe 2.):
Lösung zu Aufgabe 3.):
Lösung zu Aufgabe 4.):
Lösung zu Aufgabe 5.):
Lösung zu Aufgabe 6.):
Lösung zu Aufgabe 7.):
Lösung zu Aufgabe 8.):
Lösung zu Aufgabe 9.):
Zeiger Grundlagen
Übungsaufgaben
1.) Zeiger 1
Was ist der Wert von b
nach Ausführung des Codes?
2.) Zeiger 2
Gegeben sei folgendes Codefragment:
Was ist der Wert von c
nach Ausführung des Codes?
3.) Zeiger 3
Was ist der Inhalt der Speicherstelle, auf die der Zeiger my_pointer
nach Ausführung des Codes zeigt?
4.) Zeiger
Gegeben ist folgendes Programm. Füllen Sie die Lücken [ ]:
5.) Zeiger
Gegeben ist folgendes Programm. Füllen Sie die Lücken [ ]:
6.) Zeiger
Gegeben ist folgendes Programm. Füllen Sie die Lücken [ ]:
7.) Zeiger
Gegeben ist folgendes Programm. Füllen Sie die Lücken [ ]:
8.) Arrays und Zeiger
Schreiben Sie ein folgendes Programm:
Ein Array enthält die Zahlen von 1 bis 10
Ein Array enthält die Pointer auf die Elemente von ersten Array
Geben Sie beide Arrays aus
9.) Zeiger
Gegeben ist folgender Codeschnipsel:
Welcher Wert steht am Ende der Codeausführung in der Variablen?
a) die Adresse von a
b) die Zahl 2
c) die Adresse von b
Lösungen
Lösung zu Aufgabe 8.):
Zeigerarithmetik
Übungsaufgaben
1.) Arrays und Zeiger 1
Gegeben sei folgendes Codefragment:
Was ist der Wert von a
nach Ausführung des Codes?
2.) Arrays und Zeiger 2
Gegeben sei folgendes Codefragment:
Was ist der Wert von
a
nach Ausführung des Codes?Was ist der Wert von
b
nach Ausführung des Codes?
Der Operator ++
inkrementiert seinen Operanden erst nachdem sein Wert in a
gespeichert wurde. Das heisst, der Wert von pointer wird zuerst in a
gespeichert und erst dann inkrementiert. Wenn man andersrum haben möchte, dann muss man entweder a = (pointer++)
oder a = ++pointer
angeben.
3.) Arrays und Zeiger 3
Gegeben sei folgendes Codefragment:
a) Was ist der Wert von a
nach Ausführung des Codes?
b) Was ist der Wert von b
nach Ausführung des Codes?
c) Was ist der Wert von c
nach Ausführung des Codes?
4.) Zugriff auf die Werte eines Arrays
Geben Sie das 6. Element des Arrays „numbers
“ aus. Welche Beispiele sind korrekt?
5.) Größe eines Arrays
Wie können Sie die Größe eines statisch definierten Arrays "numbers
" vom Typ int
bestimmen?
6.) Iterieren
Sie haben ein Array „numbers
“ vom Typ int der Größe NUMBERS_SIZE
. Mit welchen der folgenden Schleifen können Sie über die Ergebnisse iterieren?
7.) Zeigerarithmetik
Das folgende Programm soll ein Array mit 2-Byte-Integern auslesen. In jedem Schleifendurchlauf soll ein Element ausgegeben werden.
Welche der unten angegebenen Zeilen muss für XXXXX eingesetzt werden?
a) liste_ptr = liste + 2*i;
b) liste_ptr = liste + i;
c) liste_ptr = liste * i;
Array of Arrays / Array of Strings
Übungsaufgaben
Im folgenden wird folgendes Stringarray betrachtet:
1.) Dimension eines Arrays
Welche Werte müssen für die Dimensionen des Arrays angegeben werden?
Erster Index: Zweiter Index:
2.) "fuenf"
Vom Element "fuenf
" soll der letzte Buchstabe mit folgendem Code ausgelesen werden:
Was sind die Werte für stringlaenge
, zeile
und spalte
?
3.) "drei"
Der String "drei
" aus dem Array mystringarray
soll in den Speicherbereich kopie kopiert werden. Welche Codefragmente erfüllen diese Funktion? a), b), c), d) oder e)?
4.) Array of Arrays
Ein Array ist deklariert als
a) Wie viele Dimensionen hat das Array?
b) Wie viele Elemente hat das Array?
c) Ein Element des Arrays soll ausgelesen werden. Welche der drei folgenden Zeilen ist richtig?
a=my_array[[3][5][6]];
a=my_array[3
5
6];
a=my_array[3][5][6];
Funktionen: Pass by Value, Pass by Reference
Übungsaufgaben
1.) Funktionen
Es gibt zwei Funktionen, denen die Zahl „zahl“ übergeben werden soll. Die Funktion „passValue
“ erwartet „zahl
“ als Wert, die Funktion „passReference
“ entsprechend als Referenz. Vervollständigen sie den folgenden Codeausschnitt entsprechend:
2.) Pass by Value
Implementieren Sie die Funktion „passValue
“. Sie soll die übergebene Zahl „zahl
“ um um eins erhöhen und anschließend ausgeben.
3.) Gültigkeit
Welche Zahlenfolge gibt das folgende Programm aus?
4.) Arrays und Referenzen 1
Schreiben Sie eine Funktion, die immer den ersten Wert eines übergebenen Arrays ausgibt.
5.) Arrays und Referenzen 2
Wie rufen Sie die Funktion auf, wenn sie die erste Position des Arrays int werte[2];
ausgeben möchten?
6.) Arrays und Referenzen 3
Nun möchten Sie die zweite Position des Arrays ausgeben, jedoch ohne die Funktion printValue
zu verändern. Welche zwei Möglichkeiten haben Sie die Referenz entsprechend zu übergeben?
7.) Summe
Schreiben Sie eine Funktion, die die Summe über ein Array (int) erzeugt. Diese Funktion hat zwei Parameter: Das Array sowie die Zahl der Felder, über die die Summe berechnet werden soll. Die Funktion gibt die Summe (int) zurück.
8.) Komplette Summe
Schreiben Sie ein Programm, welches die Summe eines Array berechnet. Das Array enthält folgende Zahlen: 1, 5, 4, 90. Nutzen Sie die Funktion der vorherigen Aufgabe.
9.) Funktionen und Zeiger
Gegeben sei folgender Codeausschnitt
Was ist der Wert von b
nach Ausführung des Codes?
Lösungen
Lösung zu Aufgabe 2.):
Lösung zu Aufgabe 3.):
6544
Lösung zu Aufgabe 4.):
Lösung zu Aufgabe 5.):
Lösung zu Aufgabe 6.):
Lösung zu Aufgabe 7.):
Lösung zu Aufgabe 8.):
Stack mit Zeigern
Im Video wurde die Grundfunktion eines Stacks erklärt. Im Beispiel fehlte jedoch die Fehlerbehandlung.
Übungsaufgaben
1.) Fehler bei push()
push()
Welcher Fehler kann im Falle der Funktion push()
auftreten?
Der Stack ist voll, es können keine Werte gespeichert werden.
Der Stack ist voll, weitere Werte können im Überlauf gespeichert werden.
Der Stack ist leer: Es können keine gültigen Werte zurück gegeben werden
Der Stack ist leer: Es wird der jeweils letzte Wert zurück gegeben
2.) Fehler bei pop()
pop()
Welcher Fehler kann im Falle der Funktion pop()
auftreten?
Der Stack ist voll, es können keine Werte gespeichert werden.
Der Stack ist voll, weitere Werte können im Überlauf gespeichert werden.
Der Stack ist leer: Es können keine gültigen Werte zurück gegeben werden
Der Stack ist leer: Es wird der jeweils letzte Wert zurück gegeben
3.) Implementation des Stacks
Implementieren Sie den Stack wie im Video gezeigt. Behandeln Sie dabei die möglichen Fehler für push()
und pop()
. Im Erfolgsfall sollen die Funktionen Wahr (true), im Fehlerfall Falsch (false) zurück geben.
4.) Test des Stacks
Nutzen Sie die loop()
-Funktion, um Ihre Implementierung zu testen. Achten Sie dabei besonders auf die Fehlerfälle.
5.) Top
Im Video wurde besprochen, dass es auch eine Funktion geben kann, die den obersten Wert zurück gibt, ohne diesen vom Stack zu entfernen. Implementieren Sie diese Funktion.
Lösungen
Lösung zu Aufgabe 3.):
Lösung zu Aufgabe 4.):
Lösung zu Aufgabe 5.):
6.) Stack mit Zeigern
Gegeben sei das array int stack[20]
und der Stackzeiger int *stack_ptr
.
a) Bei der Initialisierung des Stackzeigers soll dieser auf den Anfang des Arrays (das Element mit derniedrigsten Speicheradresse) zeigen. Welche der folgenden Codezeilen kann hierfür verwendet werden? (mehrere Antworten möglich).
stack_ptr = stack;
stack_ptr = stack[0];
stack_ptr = &(stack[0]);
stack_ptr = stack+20;c
b) Es soll eine pop-Funktion implementiert werden, mit der ein Element aus dem Stack entfernt wird. Wie muss stack_ptr
aktualisiert werden, vorausgesetzt, es befinden sich noch Elemente im Stack? (mehrere Antworten möglich)
stack_ptr++;
stack_ptr--;
stack_ptr = stack[stack_ptr-1];
stack_ptr = stack_ptr – 1;
Liste (Queue) mit Zeigern
Übungsaufgaben
1.) Warteschlange
Im Video haben Sie die Funktionsweise einer Queue (Warteschlange) kennen gelernt sowie eine Beispielimplementierung erhalten. Warteschlangen werden in der Informatik häufig dort verwendet, wo Ein- und Ausgabe von Daten voneinander entkoppelt sein müssen. Wir nehmen an, dass Sie Temperaturmesswerte ereignisgesteuert als Struct erhalten:
Passen Sie die Queue so an, dass dort Werte vom Typ struct messwert gespeichert werden. Testen Sie die Queue anschließend auf ihre Funktionalität. Implementieren und verwenden Sie folgende Hilfsfunktionen:
getMesswert()
gibt einen Messwert als Struct zurück:
print_messwert()
gibt den Inhalt eines Structs vom Typ messwert zurück:
2.) Queue - Übung
Warteschlangen werden nicht nur zum Zwischenspeichern von Messwerten, sondern auch z.B. zum Verwalten von Druckaufträgen auf einem großen Abteilungsdrucker verwendet. Diesem ist ein Rechner (Print-Server genannt) vorgeschaltet, der Auträge entgegenimmt und in einer Queue speichert. Wenn der Drucker an den Server meldet, dass ein Auftrag abgeschlossen wurde, schickt der Server den nächsten Auftrag an den Drucker. Die Druckerwarteschlange kann nur eine begrenzte Zahl an Aufträgen speichern.Es gibt zwei Funktionen für die Verwaltung der Warteschlange, die jeweils am Anfang der Queue die Auftrangsannahme und am Ende die Weitergabe an den Drucker freigeben oder sperren.Wie sollten diese Funktionen in den folgenden Fällen eingesetzt werden? a) Die Warteschlange ist voll. b) Der Drucker signalisiert an den Printserver, dass kein Papier mehr vorhanden ist – es wird davon ausgegangen, dass kurzfristig Paper nachgelegt werden kann. c) Der Drucker wird in Kürze für Wartungsarbeiten abgeschaltet, bereits in der Queue befindiche Aufträge sollen aber noch abgearbeitet werden.
3.) Queue - Übung
Vergleichen Sie die Eigenschaften von Stacks und Warteschlangen. a) Wieviel Speicherplatz wird jeweils für das Speichern von n Elementen benötigt? b) In welcher Reihenfolge werden die Elemente entnommen, bezogen auf die Reihenfolge des Einschreibens in den Stack oder die Queue? c) Wie viele Zeiger werden für die Implementierung benötigt? Unter welchen Bedingungen und auf welche Werte werden die Zeiger erhöht bzw. erniedrigt?
4.) Warteschlangen
Ergänzen Sie den Lückentext:
Für die Implementierung von Warteschlangen benötigt man zwei Zeiger, die auf _____ und _____ derWarteschlange zeigen. Sind beide Zeiger gleich, ist die Warteschlange ______.
Lösungen
Lösung zu Aufgabe 1.):
Fortgeschrittene Aufgaben
Bei der Auswertung eine Reihe von Messungen ist man oft weniger an den einzelnen Werten interessiert, sondern an den statistischen Eigenschaften der Messwerte. Wetterdienste bestimmen beispielsweise die Durchschnitts-, Höchst- und Tiefsttemperaturen innerhalb eines Tages oder Jahres. Verwenden Sie als Grundlage für die Hackathon-Vorbereitung den Code, den Sie im Selbsttest zum Thema Warteschlangen geschrieben haben. Erstellen Sie Funktionen, mit denen die in der Queue gespeicherten Werte untersucht werden können. Nehmen Sie an, dass einmal pro Stunde ein Messwert aufgenommen wird und die Queue die Messwerte für eine Woche (7x24 Messungen) speichert.
Erstellen Sie Funktionen, die das Maximum und das Minimum bestimmen und zusammen mit Datum und Uhrzeit zurückgeben.
Erstellen Sie eine Funktion, die den Durchschnitt berechnet.
Erweitern Sie die Funktionen aus den Punkten 1 und 2 so, dass die dort erwähnten Statistikwerte für einen der letzten 6 vergangenen Tage ausgegeben werden können. Der Beonbachtungszeitraum ist in diesem Fall 0-24 Uhr des betreffenden Tages. Sie können z.B. der Funktion einen Parameter übergeben, bei dem 1 gestern bedeutet, 2 vorgestern usw. Ist der Parameter 0, ist die ganze Woche der Beobachtungszeitraum.
Erstellen Sie Funktionen, die den Tag mit der höchsten oder niedrigsten Durchschnittstemperatur bestimmen und diese Temperatur zusammen mit dem Datum zurückgeben.
Erstellen Sie eine zweite Warteschlange, die parallel zur ersten arbeitet und die Tages-Maximal-. Minimal- und Durchschnittswerte für einen Monat speichert. Am Ende eines jeden Tages (nach der letzten Messung um 23:00h) werden die betreffenden Werte berechnet und in die zweite Queue geschrieben. Zum Testen des Programms können Sie z.B. den Zufallswert eines offenen Analogeingans in kurzen zeitlichen Abständen einlesen.
Zusatz: Unix Epoche
Übungsaufgaben
Hinweis: Die Unix Epoche nutzt die Zahl der Sekunden seit dem 1.1.1970 als 32 oder 64 bit Integer -Wert (long / long long). Da Arduinos in der Regel keine Echtzeituhr besitzen sowie in Millisekunden rechnen, gibt es folgende Einschränkungen:
Die Zeit wird bei jedem Neustart zurück gesetzt
Die Zeit wird durch die Funktion
millis()
in Millisekunden seit Start zurück gegeben.Der Dateityp ist hier unsigned long.
Unabhängig davon lässt sich mit diesen Zeiten ähnlich wie mit dem Unix Timestamp rechnen.
50.) 1 Tag
Welchen Wert gibt millis()
nach einem Tag zurück?
51.) Überlauf
Die Zeit im Arduino wird in Millisekunden seit Systemstart in einer Variable vom Typ unsigned long gespeichert. Nach wievielen Tagen kommt es hier zu einem Überlauf?
Lösungen
Lösung zu Aufgabe 50:
1000*60*60*24=86400000
Lösung zu Aufgabe 51:
unsigned long entspricht 32 bit, also maximal 232=4294967296 ms. Dies entspricht 49,7 Tagen.
Zusatz: Ringpuffer
Übungen
1.) Theorie Ringpuffer 1
In einen Ringpuffer mit 3 Speicherplätzen, die beginnend mit 0 nummeriert sind, werden Werte geschrieben. Der Schreibvorgang beginnt mit Speicherplatz 0. Die Werte 9, 7, 2, 8, 5 werden geschrieben.
Was ist der Inhalt des Speicherplatzes 0, nachdem alle Werte geschrieben wurden?
Was ist der Inhalt des Speicherplatzes 1, nachdem alle Werte geschrieben wurden?
Was ist der Inhalt des Speicherplatzes 2, nachdem alle Werte geschrieben wurden?
2.) Theorie Ringpuffer 2
Ausgehend von der vorherigen Übung. Der Schreibvorgang wird mit den Werten 3, 1, 4, 0, 6 fortgesetzt. Der Ringpuffer befindet sich vor Beginn des Schreibvorgangs im Zustand nach Beendigung von Aufgabe 1.
Was ist der Inhalt des Speicherplatzes 0, nachdem alle Werte geschrieben wurden?
Was ist der Inhalt des Speicherplatzes 1, nachdem alle Werte geschrieben wurden?
Was ist der Inhalt des Speicherplatzes 2, nachdem alle Werte geschrieben wurden?
3.) Ausgabe Puffer
Wir haben einen Puffer / Buffer mit dem Namen times
vom Typ unsigned long
der Länge BUFFER_SIZE
. Schreiben Sie eine Funktion printBuffer()
, welche die Werte des Buffers sowie die Position des Wertes im Buffer ausgibt. times
und BUFFER_SIZE
sind hierbei global definiert.
4.) Speichern von Werten
Speichern Sie den aktuellen Wert von millis()
ein mal pro Sekunde in diesem Buffer. Überschreiben hierbei den jeweils ältesten Wert. Geben Sie die Werte von times
regelmäßig aus.
Lösungen
Lösung zu Aufgabe 3.):
Lösung zu Aufgabe 4.):
Last updated