Beruflich Dokumente
Kultur Dokumente
a) Welche Aussagen bezüglich der Unterteilung der Programmiersprachen C und C++ sind
wahr (w=wahr, f=falsch)? (2 Punkte, 2 zutreffende Antworten)
w f
⊠ C++ ist eine objektorientierte Skriptsprache.
⊠ C ist eine Compilersprache.
⊠ C++ ist eine deklarative, logische Programmiersprache.
⊠ C ist eine deklarative, funktionale Programmiersprache.
⊠ C++ ist eine imperative, objektorientierte Programmiersprache.
b) Welche der folgenden Aussagen bezüglich der unterschiedlichen Stufen des Kompiliervor-
ganges sind wahr (w) oder falsch (f)? (2P., 2 wahre Antworten)
w f
⊠ Der Präprozessor liest die Präprozessor-Direktiven, um eine Mehrfacheinbindung von
Objekt-Dateien zu verhindern.
⊠ Präprozessor-Direktiven sind in C++ und in C zu verwenden.
⊠ Makros werden vom Linker (Binder) im Programmcode ersetzt.
⊠ Speicherzugriffsfehler werden vom Compiler erkannt und als Fehler ausgegeben.
c) Geben Sie für jede Deklaration an, ob sie wahr (w) oder falsch (f) ist. Achten Sie auf
Schlüsselwörter, sowie auf Groß- und Kleinschreibung! (2P., 1 wahre Antwort)
w f
⊠ int 2a, 2b, 2c;
⊠ double da[2], de[3], do[4];
⊠ int a, float b, double c;
⊠ int goto1, ELSE, _if;
Geben Sie für jede der nachfolgenden Operationen an, ob sie äquivalent zu x = TP->d; ist.
(2P., 2 wahre Antworten)
w f w f
⊠ x = *TP.d; ⊠ x = (&TP)->d;
⊠ x = T.d; ⊠ x = TP[0].d;
Geben Sie an, welche der nachfolgenden Operationen zulässig sind. (2P., 2 wahre
Antworten)
w f w f
⊠ pointer = array; ⊠ pointer = array[1];
⊠ array = pointer; ⊠ array[1] = *pointer;
w f
⊠ Eine Variable wird nur vorrübergehend benötigt, ist aber relativ groß.
⊠ Eine dynamische Verwaltung verhindert hängende Zeiger (dangling pointer).
⊠ Die Größe einer Variablen ist erst zur Laufzeit bekannt und soll zur Laufzeit verändert
werden.
⊠ Call-by-Reference ist nur mit dynamischer Speicherverwaltung möglich.
g) Welche Aussagen zu Namespaces sind wahr (w) oder falsch (f)? (2P., 2 wahre Antworten)
w f
⊠ Namespaces können nicht, verteilt über beliebig viele Dateien, erweitert werden.
⊠ Die using-Direktive gibt alle Namen eines Namensraumes zur Benutzung frei.
⊠ Mit einer using-Deklaration können einzelne Variablen aus Namespaces sichtbar ge-
macht werden.
⊠ Die using-Direktive darf nur in Header-Dateien verwendet werden.
h) Wer sind die Erfinder der Programmiersprachen C und C++? (w=wahr, f=falsch)? (1P., 1
wahre Antwort)
w f
⊠ Kenneth Thompson, Dennis Ritchie und Bjarne Stroustrup
⊠ George Bush, Barack Obama und Lance Armstrong
⊠ Walter Bright, Guido van Rossum
⊠ Brendan Eich, Rasmus Lerdorf und Linus Torvalds
⊠ arry Wall, Perl Porter und Bill Gates
a) Präprozessor (2P.)
Geben Sie die Ausgabe des Programmes in Zeile 11 und Zeile 12 an.
Die Funktion printHello() ist dem Compiler bei Aufruf der main-Routine noch nicht
bekannt. Sie muss vorher folgendermaßen deklariert werden: void printHello();
Geben Sie die Ausgabe des Programmes mit kurzer Begründung für folgende Zeilen an:
Zeile 13: 2, da die Funktion func die globale Variable b=1 um eins er-
höht und zurückgibt.
Zeile 14: 3, da der Funktion func die Adresse der globalen Variable a=1
übergeben wird und der Wert von a mit dem Wert von b=2 erhöht wird.
Mit welchem Wert ist der Name Gelb belegt? Begründen Sie kurz Ihre Antwort.
Antwort: Bitfeld
Geben Sie an, wieviel Bits im Speicher von dem strukturierten Datentyp Roboter effektiv
benutzt werden und wieviel Bits tatsächlich bei einem 32 Bit System reserviert werden.
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); // 1 Punkt
7 printf("i:%i\n",i); // 1 Punkt
8 return 0;
9 }
✝ ✆
Geben Sie die Ausgabe des Programmes für folgende Zeilen mit kurzer Begründung an:
Zeile 7:
Antwort: j=1.5, da auf der rechten Seite ein float von 1.5 steht und dann auf ein float zuge-
wiesen wird.
Zeile 8:
Antwort: i=0, da auf der rechten Seite ein float von 1.5/3=0.5 steht und dann auf ein int
gecastet wird.
Folgende Codeausschnitte sind von einem Anfänger programmiert worden. Für alle Code-
ausschnitte gilt: int i = 1, j = 2; Welche Ausgabe erfolgt für diese Werte bei den unten
angegebenen Bedingungen? Wenn keine Ausgabe erfolgt, schreiben Sie bitte Keine Ausgabe.
✞ ☎
if (i < j) printf("kleiner");
✝ ✆
kleiner
✞ ☎
if (i = j) printf("gleich");
✝ ✆
Keine Ausgabe, da die Bedingung if (i < 1) nicht erfüllt ist und alle weiteren Abfragen
innerhalb dieser Bedingung liegen und deshalb nicht bearbeitet werden.
✞ ☎
switch(i) {
case 1: printf("eins");
case 2: printf("zwei");
default: printf("weder␣eins␣noch␣zwei");
}
✝ ✆
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 i mit Wert 2 bereits
eingetragen.
Hinweis: Die Adressierung des Stacks erfolgt über eine Blockgröße von 4 Bytes. Deshalb
belegt int i 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 6 inc
11 while (i < 10) {
12 int inc = 3 * i; 0x04992 9 c
13 data.a += inc;
14 data.b += inc; 0x0498E 9 b
15 data.c += inc;
16 i++; 0x0498A 9 a
17 }
18 0x04986 3 i
19 return r;
20 } 0x04982 0 r
✝ ✆
Vervollständigen Sie die Funktion void arrange(char str[]), welche die Zeichen des \0-
terminierten Strings str alphabetisch sortiert. Ergänzen Sie untenstehenden Code in den
Zeilen 3, 11, 13, 15, 17 und 19 an den freien Stellen, die mit Unterstrichen ______
gekennzeichnet sind.
Hinweis: C++-Funktionen sind nicht erlaubt. Prüfen Sie str auf Gültigkeit.
✞ ☎
void arrange(char str[]) {
if (str == NULL) {
return;
}
int changed;
do {
changed = 0;
int i = 1;
while (str[i] != ’\0’) {
if (str[i - 1] > str[i]) {
char tmp = str[i];
str[i] = str[i - 1];
str[i - 1] = tmp;
changed = 1;
}
i++;
}
} while (changed);
}
✝ ✆
Beschreiben Sie, welche Aufgabe die Funktion rechtschreibmod(char* satz) erfüllt und
welche Ausgabe bei unten angegebener main-Routine erfolgt. Erklären Sie zusätzlich die
einzelnen Schritte in Zeile 6, Zeile 9-23, Zeile 24-27 und Zeile 28.
Hinweis: Das Postfix Inkrement ++ hat eine niedrigere Priorität wie die eckigen Klammern
[]. Die Assoziativität ist bei beiden von links nach rechts.
✞ ☎
1 #include <stdio.h>
2 void rechtschreibmod(char* satz)
3 {
4 int lesezaehler = 0, schreibzaehler = 0;
5 char zeichen;
6 while (satz[lesezaehler])
7 {
8 zeichen = satz[lesezaehler];
9 if (zeichen == ’h’ && lesezaehler)
10 {
11 if (satz[lesezaehler-1]==’P’)
12 {
13 satz[schreibzaehler-1]=’F’;
14 }
15 else if (satz[lesezaehler-1]==’p’)
16 {
17 satz[schreibzaehler-1]=’f’;
18 }
19 else
20 {
21 satz[schreibzaehler++]=satz[lesezaehler];
22 }
23 }
24 else
25 {
26 satz[schreibzaehler++]=satz[lesezaehler];
27 }
28 lesezaehler++;
29 }
30 satz[schreibzaehler]=’\0’;
31 }
32 int main()
33 {
34 char satz[] = "phantastisch";
35 rechtschreibmod(satz);
36 printf("%s\n",satz);
37 return 0;
38 }
✝ ✆
Der Funktion wird ein String übergeben, in welchem alle vorkommenden ph durch f
und alle Ph durch F ersetzt werden.
Solange der Inhalt des Feldes bei Index lesezaehler nicht 0 ist wird die while-
Schleife ausgeführt.
Falls der Inhalt des Feldes ein h und der lesezaehler nicht 0, dann wird, falls vor
dem h ein P oder p steht, das P oder p durch ein F oder f ersetzt und der schreibzaehler
nicht erhöht. Falls vor dem h kein P oder p steht, dann wird der Buchstabe von Index
lesezaehler auf Index schreibzaehler kopiert und danach der schreibzaehler um 1
erhöht.
Falls der Inhalt des Feldes kein h ist, wird das Zeichen an Index lesezaehler auf
Index schreibzaehler kopiert und dann der schreibzaehler um 1 erhöht.
Die Funktion f(double *a, int i) kann zum Beispiel wie folgt aufgerufen werden:
✞ ☎
double a[] = {3,6,4,12,5};
int laenge = 5;
double ergebnis = f(a, laenge - 1);
✝ ✆
wobei die Variable laenge offensichtlich als Wert die Länge des Feldes a enthält.
(i) Wie sieht die Anfangsbedingung f (a0 ) =? der rekursiven Funktion für Felder der
Länge eins aus, wobei a0 dem ersten Element des Feldes entspricht? (1P. von 5P.)
f (a0 ) = a0
(ii) Wie sieht die Formel für f (a1 ) =? in Abhängigkeit von f (a0 ), sowie von a1 und a0 für
ein Feld der Länge zwei aus? (1P. von 5P.)
(iii) Wie sieht die Formel für f (a2 ) =? in Abhängigkeit von f (a1 ), sowie von a2 , a1 und a0
für ein Feld der Länge drei aus? (1P. von 5P.)
(iv) Wie sieht die allgemeine rekursive Formel für f (ai ) =? in Abhängigkeit von ai , f (ai−1 )
und i für ein Feld der Länge i + 1 aus? (1P. von 5P.)
(v) Welcher Kennwert wird aus den double-Werten des Feldes double a[] mit der
rekursiven Funktion f(double *a, int i) implementiert? (1P. von 5P.)
(i) Implementieren Sie eine Funktion max_pointer, welcher die Adressen von zwei Integer-
Werten a und b als Pointer übergeben werden und die das Maximum der beiden Werte
zurückgibt. Benutzen Sie für die Berechnung des Maximums den Ternären Operator!
(1P. von 4P.)
✞ ☎
int max_pointer(int* a, int* b) {
return (*a >= *b) ? *a : *b;
}
✝ ✆
(ii) Wie muss die Funktion max_pointer in der main-Routine aufgerufen werden, wenn dieser
Funktion zwei initialisierte Werte int a = 2; und int b = 3; übergeben werden sollen,
und die Funktion das Ergebnis an die definierte Variable int ergebnis; zurückgeben soll?
(1P. von 4P.)
✞ ☎
ergebnis = max_pointer(&a, &b);
✝ ✆
(i) Implementieren Sie nun eine Funktion max_reference, welcher die Referenzen auf zwei
Integer-Werte a und b übergeben werden und die das Maximum der beiden Werte zurück-
gibt. Benutzen Sie für die Berechnung des Maximums wieder den Ternären Operator!
(1P. von 4P.)
✞ ☎
int max_reference(int& a, int& b) {
return (a >= b) ? a : b;
}
✝ ✆
(ii) Wie muss diese Funktion max_reference in der main-Routine aufgerufen werden, wenn
dieser Funktion zwei initialisierte Werte int a = 2; und int b = 3; übergeben werden
sollen, und die Funktion das Ergebnis an die definierte Variable int ergebnis; zurückgeben
soll? (1P. von 4P.)
✞ ☎
ergebnis = max_reference(a, b);
✝ ✆
(i) Legen Sie dynamisch Speicher für eine 3 × 4-Matrix von Integern an, welche über
einen Doppelzeiger int **matrix1 angesprochen wird und der Zugriff auf die Elemente
matrix1[m][n] über die Indizes m, n erfolgt. Hinweis: Ein Zeigerfeld der Länge n auf
Integer wird mit dem Befehl new int*[n] angelegt, und ein Integer-Feld der Länge n
wird mit dem Befehl new int[n] angelegt. (3P. von 6P.)
✞ ☎
✝ ✆
(ii) Legen Sie jetzt dynamisch Speicher für eine 3 × 4-Matrix von Integern an, welche über
einen Einfachzeiger int *matrix2 angesprochen wird und der Zugriff auf die Elemente
matrix2[n*4+m] über die Indizes m, n erfolgt. (1P. von 6P.)
✞ ☎
✝ ✆
(iii) Wieviele Zeiger werden in (i) mehr als in (ii) abgelegt? (1P. von 6P.)
Antwort: Im Fall (i) werden 4 Zeiger angelegt, im Fall (ii) nur einer, also wer-
den drei Zeiger mehr in Fall (i) als in Fall (ii) angelegt.
(iv) Skizzieren Sie die dynamischen Speicherzellen (als Rechtecke) und die Zeigerstruktur
des Doppelzeigers und der Einfachzeiger (als Pfeile) für die allokierte Matrix aus (i).
Unterscheiden Sie den Inhalt der Speicherzellen durch W für Matrixwerte und A für
Adresswerte. (1P. von 6P.)
Welche Ausgabe produziert dieses Programm bei Ausführung der Zeilen 20, 21 und 22?
✞ ☎
// Zeile 20:
30
// Zeile 21:
10
// Zeile 22:
20
//
✝ ✆
b) Vererbung (7P.)
Datei point.h
✞ ☎
1 class Point {
2 public:
3 Point();
4 Point(const float x, const float y);
5 ~Point();
6 void setPoint(const float x, const float y);
7 void setPoint(const Point &p);
8
9 protected:
10 float x;
11 float y;
12 };
✝ ✆
Datei point.cpp
✞ ☎
1 Point::Point() : x(0.0), y(0.0) {}
2 Point::Point(const float x, const float y) : x(x), y(y) {}
3 Point::~Point() {}
4 void Point::setPoint(const float x, const float y)
5 {
6 this->x = x;
7 this->y = y;
8 }
9 void Point::setPoint(const Point &p)
10 {
11 this->x = p.x;
12 this->y = p.y;
13 }
✝ ✆
Geben Sie an, welche Methoden in dieser Klasse überladen oder überschrieben werden und
begründen Sie warum. (1P. von 7P.)
Schreiben Sie eine Klasse Pixel, welche von Point erbt. Die Funktion setPoint soll dabei
auch auf Instanzen der Klasse Pixel aufrufbar sein. Die Klasse Pixel soll drei Farbwer-
te als int speichern können. Auf die Farbwerte soll nur von innerhalb der Klasse Pixel
zugegriffen werden können. Es soll einen Konstruktor geben, welcher die Farbwerte und Ko-
ordinaten über eine Initialisierungsliste zu null initialisiert und einen Konstruktor, welcher
die Farbwerte und Koordinaten als Argumente übergeben bekommt und entsprechend setzt.
Zusätzlich soll eine Funktion setColor(const int r, const int g, const int b) zum
Setzen des Farbwertes vorhanden sein, die auch von außerhalb der Klasse verwendet werden
kann. (6P. von 7P.)
✞ ☎
private:
int r;
int g;
int b;
};
✝ ✆