• Keine Ergebnisse gefunden

1.1Grundlagen 1C-Programmierung

N/A
N/A
Protected

Academic year: 2022

Aktie "1.1Grundlagen 1C-Programmierung"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

1 C-Programmierung

Dieser Text soll kein C-Buch ersetzen, sondern lediglich die für „Algorithmen und Daten- strukturen“ notwendigen Grundlagen für rekursive Programmierprobleme auf Listen bzw.

Bäumen liefern.

1.1 Grundlagen

1.1.1 Kontrollstrukturen

DaC eine imperative Programmiersprache ist, wird der Programmablauf im wesentlichen durch (bedingte) Sprünge gesteuert.

If-Anweisung

Eine Wenn-dann-sonst-Aussage ist inC mit einer if-Anweisung realiserbar:

1 i f( x ) {

2 // Anweisungen f ü r den F a l l , d a s s x wahr i s t 3 }

4 e l s e {

5 // Anweisungen , f a l l s x f a l s c h i s t 6 }

Dabei istx eine Zahl, welche als „falsch“ interpretiert wird, wenn sie gleich 0 ist. In allen anderen Fällen (also z.B. auch bei negativem Wert) istx „wahr“.

Der else-Zweig (alles ab einschließlich Zeile 4) kann bei Bedarf auch weggelassen werden.

Die geschweiften Klammern sind nur notwendig, wenn mehr als ein Statement (also eine mit Semikolon abgeschlossene Anweisung) bearbeitet werden soll.

Schleifen

Sind in (unseren) rekursiven Algorithmen nicht notwendig und sollen daher hier nicht besprochen werden.

1.1.2 Funktionen

Funktionen werden für Modularisierung (und damit wiederverwendbarkeit) benötigt. Sie entsprechen im Wesentlichen den mathematischen Funktionen, können allerdings auch den Speicherinhalt direkt verändern, so dass nicht zwangsläufig Parameter oder Rückgabewerte nötig sind.

Eine minimale Funktion hat keinen Rückgabewert und keinen Parameter. InC gibt es für dieses Fall den leeren Typvoid. Die Funktion könnte dann folgendermaßen lauten:

1 void f u n c t i o n (void) {

2 p r i n t f ( " v o i d−f u n c t i o n " ) ; // Ausgabe

3 return; // s o f o r t i g e Beendigung d e r Funktion 4 p r i n t f ( " ende " ) ; // w i r d NIE a u s g e g e b e n 5 }

(2)

Die Anweisung return beendet den Ablauf der Funktion sofort und gibt einen Wert zu- rück. Da hier der Rückgabewertvoid ist, wird kein Wert übergeben. Im Falle einer void- Funktion kann return auch fehlen - die Funktion wird dann einfach an der letzten Zeile beendet. Wird allerdings ein Rückgabewert erwartet (in AuDint), mussreturn<wert>;

jeden möglichen Abarbeitungspfad abschließen (d.h. Bei einer If-Anweisung sollte sich returnbei if undelsebefinden oder zentral am Ende für beide zusammmen.)

Wertparameter

Bei einem Wertparameter wird der Wert der übergebenen Variablen (oder einer Konstante) in die Variable des Parameter kopiert:

1 void wertparam (i n t x ) {

2 x = 5 ; // nur d i e Kopie x w i r d v e r ä n d e r t 3 }

4 . . .

5 i n t v a r = 0 ; // I n i t i a l i s i e r e n e i n e r V a r i a b l e n

6 wertparam ( v a r ) ; // v a r i s t auch nach dem F u n k t i o n s a u f r u f 0

Referenzparameter

Bei einem Referenzparameter werden Zeiger benutzt. Da hier das Wissen über die ge- naue Funktionweise irrelevant ist, soll nur die Wirkung beschrieben werden: Mittels eines Referenzparameters ist es möglich, die übergebene Variable direkt zu verändern:

1 void r e f p a r a m (i n t ∗x ) {

2 ∗x = 5 ; // d e r Parameter w i r d v e r ä n d e r t 3 }

4 . . .

5 i n t v a r = 0 ; // I n i t i a l i s i e r e n e i n e r V a r i a b l e n

6 wertparam ( v a r ) ; // v a r i s t nach dem F u n k t i o n s a u f r u f 5

Da die orginial-Variable verändert wird, ist es nicht möglich diese Funktion mit einer konstanten Zahl aufzurufen. Zu Beachten ist, dass der Name der lokalen Variablen immer noch x ist. Dies ist bei eigenen Datentypen relevant, bei Integern genügt es darauf zu achten, dass immer nur die *-Variante im Quelltext benutzt wird. (Also *x statt x in der Funktion).

1.1.3 Eigene Datentypen

Eigene Datentypen sind in AuD für Listen oder Bäume notwendig. Daher sollte man sich folgende Grundstruktur (eines ternären Baums) einprägen:

1 typedef s t r u c t e l e∗ BPtr ; 2 typedef s t r u c t e l e {

3 i n t s c h l u e s s e l ;

4 BPtr l i n k s , m i t t e , r e c h t s ; 5 } b_ele ;

Wird der mittlere Zeiger (BPtr mitte) auf NULL gesetzt, erhält man einen Binärbaum,

(3)

Der Zugriff der Elemente kann folgendermaßen erfolgen:

1 b_ele b ; // e n t s p r i c h t : s t r u c t e l e b ; 2 BPtr bp ; // e n t s p r i c h t : s t r u c t e l e∗ bp ; 3 . . .

4 b . s c h l u e s s e l = 5 ; // Z u g r i f f ü b e r .

5 bp−>s c h l u e s s e l = 5 ; // e n t s p r i c h t : (∗bp ) . s c h l u e s s e l = 5 ;

Wird einer Funktion also ein Parameter vom Typ BPtr übergeben, ist dies eigentlich ein Referenzparameter! (Da BPtr nur eine andere Schreibweise für struct ele* ist.)

Operatoren

Folgende Operatoren sind wichtig:

Zuweisung: =

Vergleich:==, >=, <=, >, <,! = Mathematik: *,+,/,-,%

Zeiger: *, &

Wichtig ist z.B. der Modulooperator, welcher den Rest bei ganzzahliger Division zurück- gibt. Der häufig gebrauchte Test, ob eine gerade oder ungerade Zahl vorliegt, kann mit dem Rest bei Division durch 2 bewerkstelligt werden:

1 i f( x % 2 == 1 ) { 2 // x i s t u n g e r a d e 3 }

4 e l s e {

5 // x i s t g e r a d e 6 }

Die Zeigeroperatoren sind sehr wichtig, sobald Zeiger auf Zeiger ins Spiel kommen. Dann kann durch Anwendung von * (Dereferenzierung, es wird also ein Zeiger „weniger“) bzw. von

& (Referenzierung, d.h. es wird ein Zeiger „mehr“) die benötigte Typgleichheit geschaffen werden.

1 void f u n c t i o n ( BPtr ∗b ) { 2 BPtr neu ;

3 . . .

4 ∗b = neu ; //b i s t Z e i g e r a u f BPtr

5 //=> D e r e f e r e n z i e r u n g => ∗b i s t BPtr

6 f u n c t i o n (&neu ) ; // f u n c t i o n e r w a r t e t Z e i g e r a u f BPtr 7 //=> R e f e r e n z i e r u n g => &b i s t Z e i g e r a u f BPtr 8 }

1.2 Praktische Tipps

In der Klausur werden rekursive Algorithmen auf Listen oder Bäumen abgeprüft. Prinzipiell sind zwar auch iterative Verfahren möglich, diese sind aber meist komplizierter, sodass die Klausurzeit zur Entwicklung kaum ausreicht.

(4)

1.2.1 Wahl der Parameter

Häufig sind die Parameter der zu schreibenden Funktion nicht vorgegeben. Wenn nur die Typen unbekannt sind, hilft folgende Regel: Sobald die Funktion den Kopf der Liste bzw.

das Wurzelelement des Baumes ändert, wird ein Zeiger auf einen Zeiger auf das Kopfelement benötigt. Nach der Notation der Grundstruktur des eigenen Datentyps benötigt man also BPtr* x. In allen anderen Fällen (nur eine Eigenschaft der Datenstruktur bestimmen), genügt ein einfacher Zeiger, also BPtr x.

Zusätzlich kann es passieren, dass Hilfsparameter benötigt werden. Diese speichern in der Regel einen „Zustand“. Bei einer Liste z.B. die aktuelle Position und bei einem Baum die Pfadlänge oder ob es sich um einen linken oder rechten Knoten handelt. Geht also aus der Aufgabenstellung hervor, dass die zu erledigende Aufgabe von einem solchen „Zustand“

abhängt, sollte dieser einfach als Hilfsparameter mitgeführt werden.

1.2.2 rekursive Lösungsidee

Um die rekursive Lösungsidee zu finden, sollte man sich ein entsprechendes Beispiel auf- schreiben (Beispielliste oder Beispielbaum). Im Wesentlichen sind immer drei Fälle nötig:

1. Abbruchbedingung (leere Liste oder leerer Baum) 2. rekursive Berechnung von Teilproblemen

3. Lösung des Gesamtproblems mit Hilfe der Teilproblemlösungen und des aktuellen Knotens

Sind die rekursiven Aufrufe und die Operation mit dem aktuellen Knoten voneinander unabhängig, so können die rekursiven Aufrufe auch zu anderen Zeitpunkten stattfinden – zum Beispiel nachdem die Operation am aktuellen Knoten ausgeführt wurde. Dadurch erhält man in solchen Fälle verschiedene Möglichkeiten, die Datenstruktur zu durchlaufen (Traversierung).

Beispiel

Es soll die Summe aller Schlüsselwerte eines Baums berechnet werden (Liste ist nur ein Spezialfall des Problems). Der Funktionskopf muss offenbar eine Zahl zurückliefern (Rück- gabetypint) und benötigt einen Baum. Dieser Baum soll nicht verändert werden, sondern es werden nur die Eigenschaften untersucht, also ist nur ein BPtr notwendig. Der Funkti- onskopf muss also lauten:int summe(BPtr t).

Die rekursive Lösungsidee ergibt:

1. Abbruch beim leeren Baum (d.h. t == NULL); Die Summe ist dann 0 2. Berechnung der Summe der Teilbäume durch rekursive Aufrufe

3. Berechnung der Gesamtsumme durch Addition der ermittelten Teilsummen sowie des eigenen Wertes

1 i n t summe ( BPtr t ) {

2 i f( t == NULL) return 0 ; // 1 .

3 return w e r t + summe ( t−>l i n k s ) + // 2 . und 3 . 4 summe ( t−>m i t t e ) + summe ( t−>r e c h t s ) ; // 2 . und 3 .

(5)

1.2.3 Grundaufgaben append, delete auf Listen

(In ähnlicher Form ist das Verfahren auch auf Baumaufgaben sowie die geordnet-einfügen- Aufgaben übertragbar.)

Folgende alte Klausuraufgaben beschäftigen sich (unter anderem) mit diesem Thema: 3.16, 3.18, 3.21, 3.24.

TreeToList

Folgende alte Klausuraufgaben beschäftigen sich (unter anderem) mit diesem Thema:

3.25,3.27,3,31,3.34.

Hier sollte vor allem darauf geachtet werden, welche Traversierungsstrategie angewendet werden soll. Von Links nach Rechts bedeutet immer in-Order, d.h. erst folgt der rekursive Aufruf für den linken Teilbaum, dann die eigentliche Berechnung (Abspalten Listenele- ment) und am Schluss der rekursive Aufruf für den rechten Teilbaum.

Referenzen

ÄHNLICHE DOKUMENTE

Dies muss beim Verwenden der aus der Queue entnommen Objekte dann auch angegeben werden. Der Cast (Double) stellt gewissermaßen die „verloren

Man kennzeichnet die Richtung einer Zonen- achse (Kristallkante), indem man diese durch den Anfangspunkt des Achsenkreuzes geführt denkt und für einen auf ihr gelegenen Punkt das

nicht innerhalb des Dieelektrikums liegt ist k=1.. Das erste Minuszeichen ergibt sich aus dem Skalarprodukt, da Feldvektor und Flächennormale in diesem Fall entgegengesetzt sind. e)

e) Wie groß ist die Potentialdifferenz V zwischen den Kondensatorplatten, nachdem das Dielektrikum eingeschoben wurde?.. f) Wie groß ist die Kapazität des Kondensators

Wenn wir bei der Abbildung 2 links und rechts je ein halbes Quadrat abschneiden, ergibt sich eine Figur aus Halbkreisen und Kreisen im DIN-Rechteck (Abb.. 3:

Prüfe jedoch zuerst, ob sich etwas

[r]

[r]