Skip to content
xenforo

76800 - Einführung in die Programmiersprache C++

Content

76800 - Einführung in die Programmiersprache C++

Hallo ich habe dieses Semster den CBT Kur "Einführung in C++" belegt. Wer ist noch dabei? Vielleicht kann man sich austauschen? Hat jemand schon die Klausur geschrieben und kann sagen, was verlangt wird oder hat sogar noch die Fragen im Kopf?

Comments

Klausuraufgaben in C++

Hallo Mitstreiter des C++-Kurses,

für März 2009 plane ich, die Wiederholungsprüfung abzulegen.

Meiner Meinung sind die Klausurfragen an einigen Stellen schwer verständlich formuliert und es ist nicht immer klar, was der Prüfling genau bearbeiten und codieren soll. Besonders die Aufgaben 4, 5 und 7 empfinde ich als "hart". Ich versuche bereits seit einigen Tagen, mich mit diesen Klausuraufgaben auseinander zu setzen - bisher ohne Erfolg. Vielleicht hat jemand einen Ansatz. Vielen Dank für Eure Hilfe.

4. Aufgabe: Deklarieren Sie eine Klasse ort, die aus vier Elementen besteht:
- Zeiger auf einen variabel langen Ortsnamen (char) - name
- die geografische Breite in Grad (float) - breite
- die geografische Länge in Grad (float) - laenge
- die Höhe des Ortes über Normal Null in Metern (short) - hoehe
Deklarieren Sie die Klasse ort mit einer Konstruktorfunktion, einer Standardkonstruktorfunktion und einer Destruktorfunktion.
Die Konstruktorfunktion soll aus der Parameterliste alle vier Werte übernehmen und das Datenobjekt entsprechend initialisieren, wobei für den Ortsnamen ein dynamischer Speicherplatz im Heap angefordert werden soll, auf dem der Ortsname gespeichert wird.
Der Standardkonstruktor soll alle Datenelemente auf null setzen.
Die Destruktorfunktion soll, falls der Zeiger auf den Ortsnamen ungleich Null ist, den entsprechenden dynamischen Speicherbereich wieder freigeben.
Zum Berechnen der Länge der Zeichenkette (ohne Null-Byte) kann die Funktion strlrn() benutzt werden, die folgenden Funktionsprototyp hat und im Headerfile string definiert ist:
unsigned int strlen(const char* s)
Der Funktionswert ist die Länge der Zeichenkette s in Bytes.
Benutzen Sie zum Kopieren von Zeichenketten die Funktion strcpy(), die ebenfalls im Headerfile string definiert ist und wobei die Parameter s1 den Zielbereich und s2 die Quellzeichenkette spezifizieren:
char* strcpy(char* s1, const char* s2)
Der Funktionswert ist die Adresse der Zielzeichenkette s1.

[class ort {
private:
char *name; // Deklaration eines Zeigers auf char-Variable
// alternative Schreibweise: char* name;
float breite, laenge;
short hoehe;
public:
// Konstruktoren und Destruktor
ort(); // Standardkonstruktor
ort(char *name, float breite, float laenge, short hoehe, const int zaehler); // Konstruktorfunktion
~ort(); // Destruktor
};

// Standardkonstruktor
ort::ort():
// Initialisierung
breite(0),
laenge(0),
hoehe(0),
zaehler(0),
name('\0')
{
}

ort::ort(char *name, float breite, float laenge, short hoehe)
{
}

ort::~ort() {
if (name != '\0') {
delete name;
}
else {
cout << "Ortsname ist nicht belegt!" << endl;
}
}

Mir stellen sich mehrere Fragen: Wie übernehme ich die Werte aus der Paraemterliste und initialisiere sie mit einem Wert? Benutze ich wie für den Standardkonstruktor eine Initialisierungsliste? Wozu ist die Länge der Zeichenkette zu berechnen? Bezieht sich die Berechnung der Länge auf das Datenelement [B]name[/B]? Erfolgt die Berechnung der Zeichenkettenlänge in einer eigenen Methode? Wofür ist es erforderlich, mit strcpy() Zeichenketten zu kopieren, wenn es doch lediglich darum geht, die Länge einer Zeichenkette zu ermitteln?

5. Aufgabe: Definieren Sie für die Klasse ort einen Zuweisungsoperator operator=.

Bei dieser Aufgabe weiss ich überhaupt nicht, wie ich einen Ansatz finden soll.

7. Aufgabe: Schreiben Sie für die Klasse ort eine Funktion operator-, die die annähernde Entfernung in km zwischen zwei Orten aus der Differenz der geografischen Breite, B1 bzw. B2, und geografischen Länge, L1 bzw. L2, der Orte berechnet. Der mittlere Radius der Erde soll dazu mit 6370 km angenommen werden. Höhenunterschiede zwischen den Orten sollen vernachlässigt werden. Unter Vernachlässigung der Erdkrümmung kann aus der vertikalen Entfernung EB und horizontalen Entfernung EL über den Satz des Pythagoras näherungsweise die Entfernung E zwischen den Orten berechnet werden. Dazu implementieren Sie die folgenden Formeln:

EB = 6370 * (B2-B1)/180 * 3.1416
EL = 6370 * cos(B1) * (L2-L1)/180 * 3.1416
E = sqrt(EL * EL + EB * EB)

Die Funktion sqrt ist im Headerfile cmath wie folgt definiert: double sqrt(const double r)[

Leider helfen mir die auf der CD zum CBT-Kurs enthaltenen Lektionen nicht weiter. Wie die Prüfungsaufgaben ist auch der Text zum CBT-Kurs recht schwer verständlich. Das Buch [B]C++ von A bis Z[/B] von Jürgen Wolf vermittelt zwar einige Themen (z.B. Konstruktoren, Destruktoren, Zeiger, Referenzen und Überladen) recht anschaulich, doch bezogen auf die o.g. Klausuraufgaben ist es leider auch keine Hilfe.

Gibt es ähnliche Prüfungsfragen aus früheren Semestern oder ein Buch, das mir dabei helfen kann, die Aufgaben zu lösen?

Viele Grüße
-- G.

gery wrote:

Hallo Mitstreiter des C++-Kurses

Hallo, ich bin zwar kein solcher, aber vielleicht kann ich trotzdem helfen.


// Standardkonstruktor
ort::ort():
// Initialisierung
breite(0),
laenge(0),
hoehe(0),
zaehler(0),
name('\0')
{
}

ort::ort(char *name, float breite, float laenge, short hoehe)
{
}

ort::~ort() {
if (name != '\0') {
delete name;
}
else {
cout << "Ortsname ist nicht belegt!" << endl;
}
}\

Dazu muss ich schonmal ein paar Worte sagen. Du benutzt hier den Wert '\0', also das Zeichen mit dem Wert 0, als Zeigerwert. Das ist aber eigentlich ein Typfehler und funktioniert nur aufgrund der impliziten Typumwandlung. Besser 0 oder das Makro NULL (definiert in <cstddef>) benutzen, wobei 0 bevorzugt wird.

In der Initialisiererliste sollten die Klassenelemente in derselben Reihenfolge aufgeführt werden, in der sie in der Klasse stehen, denn sie werden ohnehin in Deklarationsreihenfolge ausgewertet. Man schützt sich dadurch vor späteren Überraschungen.

Dann machst du es dir ziemlich schwer dadurch, dass deine Datenelemente genauso heißen wie die Parameter des Konstruktors. Dein Konstruktor würde implementiert ungefähr so aussehen:

ort::ort(char *name, float breite, float laenge, float hoehe)
: breite(breite), laenge(laenge), hoehe(hoehe)
{... }

Wenn du da an jeder Stelle noch weißt, was was ist, kein Problem, das kann auch Stil sein :) Ansonsten nennt man die Klassenelemente ganz gerne anders, z.B. m_Breite, _breite oder breite_.


Mir stellen sich mehrere Fragen: Wie übernehme ich die Werte aus der Paraemterliste und initialisiere sie mit einem Wert? Benutze ich wie für den Standardkonstruktor eine Initialisierungsliste?

Genau, habe ich oben schon gezeigt. name kann (bzw. sollte) man nicht so initialisieren, dazu gleich mehr.

Wozu ist die Länge der Zeichenkette zu berechnen? Bezieht sich die Berechnung der Länge auf das Datenelement name? Erfolgt die Berechnung der Zeichenkettenlänge in einer eigenen Methode? Wofür ist es erforderlich, mit strcpy() Zeichenketten zu kopieren, wenn es doch lediglich darum geht, die Länge einer Zeichenkette zu ermitteln?

Das hängt damit zusammen, dass dynamisch Speicherplatz angefordert werden soll, in dem der Name gespeichert werden soll. Dazu ist es nötig, dass man die Größe dieses Speicherplatzes bestimmt und dann den Namen dort hinein kopiert:

// im Konstruktor:
unsigned laenge = strlen(name);
m_Name = new char[laenge] + 1; //+1 wegen dem abschließenden Nullzeichen
strcpy(m_Name, name);

(ich hab hier mal das Klassenelement in m_Name umbenannt, sonst müsste man dafür this->name schreiben, um es nicht mit dem Parameter zu verwechseln). Das gehört in den Konstruktor. Man kann das auch mit der Initialisiererliste machen:

ort::ort(char* name, /* ... */)
: m_Name(new char[strlen(name)+1]), // ...
{
strcpy(m_Name, name);
}


5. Aufgabe: Definieren Sie für die Klasse ort einen Zuweisungsoperator operator=.

Bei dieser Aufgabe weiss ich überhaupt nicht, wie ich einen Ansatz finden soll.

Dazu sollte es aber im Script etwas geben. Der Zuweisungsoperator muss etwa diese Form haben:

ort& operator=(const ort& rhs);

Die Rückgabe sollte eine Referenz auf ein nichtkonstantes Objekt sein, damit man wie üblich a = b = c schreiben kann.

In der Implementierung kommt es auf einige wichtige Sachen an, die aber immer dieselben sind:

ort& ort::operator=(const ort& rhs) {
if (this != &rhs) { // Selbstzuweisung abfangen
delete[] m_Name; // alten Namen löschen, um Speicherlecks zu verhindern
m_Name = new char[strlen(rhs.m_Name)+1]; // alles rüberkopieren
strcpy(m_Name, rhs.m_Name);
m_Breite = rhs.m_Breite;
m_Laenge = rhs.m_Laenge;
m_Hoehe = rhs.m_Hoehe;
}
return *this; // Referenz auf *this zurückgeben
}

(Das ist zumindest die traditionell übliche Form, das düfte für den Kurs ausreichend sein.)


7. Aufgabe:

Ich finde deine Frage dazu nicht.

Der operator- kann entweder als Elementfunktion der Klasse oder als freie Funktion implementiert werden. Ich mach mal die erste Version:

float ort::operator-(const ort& rhs)
{
float EB = 6370 * (rhs.m_Breite - m_Breite)/180 * 3.1416;
float EL = 6370 * cos(m_Breite) * (rhs.m_Laenge - m_Laenge)/180 * 3.1416;
float E = sqrt(EL*EL + EB*EB);
return E;
}

Das ist nur um das Prinzip zu verdeutlichen. Interessant wird es, wenn der operator- ein Objekt derselben Klasse zurückgeben soll, weil man z.B. eine Matrixklasse hat und die Differenz von zwei Matrizen ausrechnen will, dann implementiert man i.d.R zuerst einen operator-= in der Klasse und baut darauf den operator- als freie Funktion auf...

Das sind übrigens alles recht einfache, aber wichtige Sachen, das sollte in absolut jedem C++-Lehrbuch und -Kurs an prominenter Stelle behandelt werden.