Beruflich Dokumente
Kultur Dokumente
Seite 2
a) Welche der folgenden Aussagen über die C++-Programmiersprache sind wahr? (w=wahr,
f=falsch)? (2P., 2 zutreffende Antworten)
w f
C ist eine Erweiterung von C++.
C++ ist größtenteils zu C kompatibel. Deshalb können in C geschriebene Programme
meist auch mit einem C++-Compiler übersetzt werden.
Im Gegensatz zu C müssen sich C++-Entwickler nie selbst um dynamische Speicherver-
waltung kümmern, denn C++ hat wie z.B. Java einen Garbage-Collector, der nicht mehr
benötigten Speicher automatisch frei gibt.
In C++ geschriebene Programme sind schneller als in C geschriebene Programme.
b) p1, p2 und p3 seien bereits initialisierte Zeiger auf Integer. Geben Sie für jede der folgenden
Operationen an, ob sie erlaubt (=w) ist oder nicht (=f) sind. (2P., 1 zutreffende Antwort)
w f w f
*p3 = p1; p2 = p1 + 3.0;
p3 = p2 + p1; *p3 = *p2 **p1;
c) Es gilt: double d; float f; short s; Tritt bei nachfolgenden Zuweisungen in der Regel
Informationsverlust auf (j=ja, n=nein)? (3P., 3 zutreffende Antworten)
j n j n j n
d = f; d = s; f = s;
f = d; s = d; s = f;
w f
Abstrakte Datentypen gibt es in C und C++.
Klassen in C++ vereinen Daten und Funktionen zum Zugriff und zur Bearbeitung dieser
Daten in einer Struktur.
Funktionen in C entsprechen Attributen in C++.
Klassen in C++ haben weniger Funktionalität wie strukturierte Datentypen in C.
Methoden in C++ erlauben es den Zugriff auf Daten ausschließlich über eine Funktion
zu realisieren.
Geben Sie für jede der nachfolgenden Operationen an, ob sie äquivalent zu x = TP->d; ist.
(2P., 2 richtige Antworten)
r f r f
x = *TP.d; x = (&TP)->d;
x = T.d; x = TP[0].d;
f) Wer gilt als Erfinder der Programmiersprache C? (w=wahr, f=falsch)? (1P., 1 zutreffende
Antwort)
w f
Kenneth Thompson und Dennis Ritchie
George Bush und Barack Obama
Walter Bright und Guido van Rossum
Brendan Eich und Rasmus Lerdorf
Larry Wall und Perl Porter
g) Geben Sie für die nachfolgenden Aussagen an, für welche Methode der Parameterüberga-
be (v=„Call by Value“, r=„Call by Reference“) sie jeweils zutreffen. (3P., 3 „Call by Va-
lue“Antworten)
v r
Eine Kopie der Variablen muss im Speicher angelegt werden.
Die Menge der übergebenen Daten in Byte variiert mit dem Variablentyp.
Es werden nicht die Variablen selbst, sondern deren Adresse im Speicher übergeben.
Die aufgerufene Funktion kann Variablen beim Aufrufer nicht direkt ändern.
In der Regel die effizientere Methode der Parameterübergabe.
Array-Variablentypen können so übergeben werden.
a) Präprozessor (2P.)
Geben Sie die Ausgabe des Programmes in Zeile 11 und Zeile 12 an.
Gegeben ist folgender Quelltext, wobei die Standardbibliothek <stdio.h> eingebunden ist:
1 static int a = 1;
2
3 int func (int* x) {
4 static int b = 1;
5 b=b+1;
6 *x=*x+b;
7 return b;
8 }
9 int main() {
10 printf("%i\n",a);
11 printf("%i\n",func(&a));
12 printf("%i\n",a);
13 return 0;
14 }
Geben Sie die Ausgabe des Programmes für folgende Zeilen mit kurzer Begründung an:
Zeile 10-12:
Zeile 13:
Zeile 14:
Gegeben ist folgender Quelltext, wobei die Standardbibliothek <stdio.h> eingebunden ist:
1 int main() {
2 int i = 3;
3 float j = 2;
4 j=i/j;
5 i=j/i;
6 printf("j:%f\n",j);
7 printf("i:%i\n",i);
8 return 0;
9 }
Geben Sie die Ausgabe des Programmes für folgende Zeilen mit kurzer Begründung an:
Zeile 6-7:
Zeile 8:
Gegeben sei das Programm auf der linken Seite. Das Diagramm auf der rechten Seite stellt
den Stack (Kellerspeicher) dar. Der Anfang des Stacks sei die unterste Zelle. Das Programm
wird ausgeführt und es werden in main mehrere Variablen auf dem Stack angelegt. Das
Programm befinde sich nun innerhalb der while-Schleife in der 3. Iteration in Zeile 16 und
hat die Anweisungen in dieser Zeile bereits ausgeführt. Vervollständigen Sie das Diagramm,
indem Sie in die Kästchen die Werte der jeweiligen Variablen schreiben. Schreiben Sie
rechts neben die Kästchen die Variablen. Beispielhaft ist die Variable r mit Wert 0 bereits
eingetragen.
Hinweis: Die Adressierung des Stacks erfolgt über eine Blockgröße von 4 Bytes. Deshalb
belegt int r auch genau ein Kästchen.
1 struct Data {
2 int a, b, c;
0x049A6
3 };
4
0x049A2
5 int main(void) {
6 int r = 0;
0x0499E
7 int i = 0;
8
0x0499A
9 struct Data data = {0, 0, 0};
10 0x04996
11 while (i < 10) {
12 int inc = 3 * i; 0x04992
13 data.a += inc;
14 data.b += inc; 0x0498E
15 data.c += inc;
16 i++; 0x0498A
17 }
18 0x04986
19 return r;
20 } 0x04982 0 r
21
a) Fibonacci (5P.)
Schreiben Sie eine Funktion int fibonacci_recursive(int n), welche für eine ganze Zahl
n die n-te Fibonacci-Zahl zurückgibt.
fn = fn−1 + fn−2 , f1 = 1, fn = 0 | n ≤ 0
definiert.
(i) Schreiben Sie die Funktion zunächst als Rekursion (ohne Schleifen). (2P. von 5P.)
(ii) Schreiben Sie die Funktion nun als Iteration (int fibonacci_iterative(int n) ,verwen-
den Sie dazu eine while-Schleife). (3P. von 5P.)
b) Vektor (7P.)
Gegeben ist folgender Code-Ausschnitt in C, der einen Vektor implementiert. Dieser ist im
Grunde ein dynamisches Array, welches seine Größe mitführt. Sollen Elemente hinzugefügt
oder entfernt werden, passt sich die Größe des Arrays entsprechend an. Das Array data soll
immer nur genau so viel Speicher belegen, wie für die Elemente des Vektors benötigt wird.
Datei vector.h
#ifndef VECTOR_H
#define VECTOR_H
#include <stdlib.h>
#include <stdio.h>
int vec_get;
#endif // VECTOR_H
Datei vector.c
#include "vector.h"
return v->data[index];
}
}
(ii) void vec_remove(vector *v, unsigned int index) (4P. von 7P.)
Diese Funktion entfernt das index-te Element aus dem Vektor. Die restlichen Elemen-
te bleiben unverändert, wobei alle Elemente hinter index einen Eintrag nach vorne
rutschen. Dazu muss wieder die Größe des Arrays angepasst werden. Fangen Sie auch
hier mögliche Fehler ab. index = 0 bezeichne das erste Element des Vektors.
void vec_remove(vector *v, unsigned int index)
{
}
Allokieren Sie Speicher für einen Zeiger vom Typ int. Schreiben Sie den Wert “5” in den
allokierten Speicherbereich, und geben Sie den Speicher danach wieder frei.
// 1. Speicher allokieren
int * n =
// 3. Speicher freigeben
Gegeben ist folgender Quelltextausschnitt, der eine 2 × 3-Matrix vom Typ int darstellt:
int m[6];
(i) Initialisieren Sie alle Matrix-Elemente mit 1 in gültiger C-Syntax. (1P. von 2P.)
(ii) Der Speicherbereich der Matrix m wird nun wie folgt dargestellt: (1P. von 2P.)
Nehmen Sie an, dass nun m[i] = 1 für alle i = 0, ..., 5 gilt. Nun wird folgender
Quelltext ausgeführt:
m[m[0]] = 2;
m[2 * m[1]] = 5;
m[2] = m[4] - 2;
m[3] = (m[2] + m[4]) / 2;
m[m[4]] = 6;
Welche Werte befinden sich nun in der Matrix?
Antwort:
m =
b) Template-Programmierung (2P.)
Gegeben ist folgender Quelltext, der die Maximum-Funktion für die Datentypen int und
double implementiert:
int max(int v1, int v2) {
return v1 > v2 ? v1 : v2;
}
(ii) Wie wird Ihre Template-Funktion für den Typ float aufgerufen? Geben Sie ein Beispiel.
c) Vererbung (4P.)
// weitere Klassenfunktionen...
protected:
double x;
double y;
};
// weitere Klassenfunktionen...
private:
float r;
float g;
float b;
};
(i) Welche Ausgabe bewirkt die Ausführung von p->reset(); in Zeile 4? Begründen Sie
kurz. (1P. von 4P.)
(ii) Welche Ausgabe bewirkt die Ausführung von delete p; in Zeile 5? Begründen Sie
ausführlich. (3P. von 4P.)
Implementieren Sie eine Funktion void setPunkt(double x, double y);, die die beiden
Klassenvariablen x und y auf die übergebenen Werte setzt. Überladen Sie weiterhin die
Funktion setPunkt, sodass die Überladung nur einen Parameter vom Typ const Punkt & p
akzeptiert. Machen Sie deutlich, in welchen Zeilen Ihre Erweiterungen in der Header-Datei
bzw. in der .cpp-Datei hinzugefügt werden.
Zusätzliches Lösungsblatt: