In diesem Kapitel haben Sie gelernt, was Container-Klassen sind und wie sie angewendet werden können. Im Folgenden gibt es einige praktische Übungen und Verständnisfragen, mit denen Sie überprüfen können, ob Sie das Gelernte korrekt anwenden können.
In diesem Teil soll das Gelernte praktisch anwendet und somit das
Train-Beispiel erweitert werden. Konkret werden Sie die
Klasse Station aus den vorangegangen Aufgaben bearbeiten,
sodass verschiedene Bahnhöfe miteinander verbunden werden.
Legen Sie in Station einen Vector
p_pNeighbors vom Typ shared_ptr an, in dem benachbarte
Stationen gespeichert werden.
Jetzt sollen verschiedene Funktionen implementiert werden. Schreiben
Sie eine Funktion vAddNeighbor, die den Returntyp
void hat, einen Nachbar zu dem aktuellen Bahnhof übergeben
bekommt und ihn in dem Vector p_pNeighbors speichert. Um zu
kontrollieren, dass Ihre Implementierung richtig ist, legen Sie
ebenfalls eine Funktion vPrintNeighbors an, die den Vector
ausgibt.
Zum Schluss legen Sie eine Funktion isNeighbor an, die
überprüft, ob ein anderer Bahnhof mit dem aktuellen verbunden ist. Die
Funktion soll 1 zurückgeben, wenn die Stationen miteinander verbunden
sind und 0, wenn sie nicht verbunden sind.
Fügen Sie Ihre Implementierungen von Train,
PassengerTrain und FreightTrain aus den
vorherigen Aufgaben an passender Stelle ein. Die Funktion
vSetStation ist für diese Aufgabe nicht relevant, kann also
weggelassen werden. Compilieren Sie anschließend alles und führen Sie
die main()-Funktion aus, um zu überprüfen, ob alles korrekt
gemacht wurde.
#include <iostream>
#include <string>
#include <memory>
#include <vector>
//Station.h
class Station{
//hier Ihre Erweiterungen einfügen
private:
std::string p_sName;
public:
Station(std::string station);
std::string getName() const;
}
//Station.cpp
//Konstruktor für Station
Station::Station(std::string station)
: p_sName(station){
}
//Getter-Funktion für p_sName
std::string Station::getName() const {
return p_sName;
}
//hier: Funktion Station::vAddNeighbor
//hier: Funktion Station::vPrintNeighbors
//hier: Funktion Station::isNeighbor
//hier: Train.h einfügen
//hier: Train.cpp
//Destruktor einfügen
//hier: Funktion Train::vGoto einfügen
//hier: Funktion Train::vPrintProperties einfügen
//hier: PassengerTrain.h einfügen
//hier: PassengerTrain.cpp
//Konstruktor einfügen
//hier: PassengerTrain::vPrintProperties einfügen
//hier: Funktion PassengerTrain::fStation einfügen
//hier: FreightTrain.h einfügen
//hier: FreightTrain.cpp
//Konstruktor einfügen
//hier: Funktion FreightTrain::vPrintProperties einfügen
//hier: Funktion FreightTrain::vLoadCharge einfügen
#define OPERATOR operator<< //Diese Zeile kann in jeder IDE weggelassen werden, sie ist nur für Jupyter notwendig
std::ostream & OPERATOR(std::ostream& out, const Train& train)
{
train.vPrintProperties(out);
return out;
}
#undef OPERATOR //Diese Zeile kann in jeder IDE weggelassen werden, sie ist nur für Jupyter notwendig
// Test
std::unique_ptr<PassengerTrain> aTrain;
aTrain = std::make_unique<PassengerTrain>();
auto bTrain = std::make_unique<FreightTrain>(2, "tons of wood");
std::cout << std::endl << "Eigenschaften 'aTrain':" << std::endl;
std::cout << *aTrain;
std::cout << std::endl << "Eigenschaften 'bTrain':" << std::endl;
std::cout << *bTrain;
auto berlin = std::make_shared<Station>("Berlin");
auto hamburg = std::make_shared<Station>("Hamburg");
auto frankfurt = std::make_shared<Station>("Frankfurt");
auto koeln = std::make_shared<Station>("Koeln");
auto muenchen = std::make_shared<Station>("Muenchen");
berlin->vAddNeighbor(hamburg);
berlin->vAddNeighbor(frankfurt);
hamburg->vAddNeighbor(berlin);
hamburg->vAddNeighbor(koeln);
// Strecke nur in eine Richtung
koeln->vAddNeighbor(frankfurt);
frankfurt->vAddNeighbor(koeln);
frankfurt->vAddNeighbor(berlin);
frankfurt->vAddNeighbor(muenchen);
muenchen->vAddNeighbor(frankfurt);
// Zeige Liste der bekannten Nachbarn
berlin->vPrintNeighbors();
hamburg->vPrintNeighbors();
koeln->vPrintNeighbors();
frankfurt->vPrintNeighbors();
muenchen->vPrintNeighbors();
std::cout<< "\n\n\nZuege fahren lassen: \n\n";
aTrain->vGoTo(berlin);
aTrain->vGoTo(hamburg);
aTrain->vGoTo(koeln);
aTrain->vGoTo(hamburg); // Fehlermeldung: keine Verbindung
Hier finden Sie die Lösungen zu den Aufgaben zu Station.
Bitte beachten Sie, dass es mehrere Möglichkeiten gibt, die Aufgaben zu
lösen, hier wird lediglich eine Variante aufgezeigt. Solange Ihre
Implementierung funktioniert wie gefordert, ist sie wahrscheinlich
richtig!
class Station
{
private:
std::string p_sName;
std::vector<std::shared_ptr<Station>> p_pNeighbors;
public:
Station(std::string station);
void vAddNeighbor(std::shared_ptr<Station> neighbor);
std::string getName() const;
void vPrintNeighbors() const;
bool isNeighbor(std::shared_ptr<Station> request) const;
}
Station::Station(std::string station) : p_sName(station)
{}
bool Station::isNeighbor(std::shared_ptr<Station> request) const
{
if(std::find(p_pNeighbors.begin(), p_pNeighbors.end(), request) != p_pNeighbors.end()) {
return 1;
}
return 0;
}
void Station::vPrintNeighbors() const
{
std::cout << std::endl << "Folgende Bahnhoefe koennen von " << p_sName << " aus angefahren werden: ";
for (auto n : p_pNeighbors) {
std::cout << n->getName() << ", ";
}
}
std::string Station::getName() const
{
return p_sName;
}
void Station::vAddNeighbor(std::shared_ptr<Station> neighbor)
{
p_pNeighbors.push_back(neighbor);
}
Dieser Teil ist eher theoretischer Natur. Er besteht aus 3 kleinen
Aufgaben, bei denen Sie auf Fehlersuche in kleinen Codesnippets gehen
sollen. Bitte führen Sie die unten aufgeführten
include-Befehle als erstes aus, damit es nicht zu
Zusatzfehlern kommt ;-).
#include <iostream>
#include <vector>
#include <map>
#include <array>
#include <string>
#include <iterator>
Folgender vector wurde angelegt. Er soll die Zahlen 7, 7, 7, 256, 4 in dieser Reihenfolge beinhalten. Finden Sie die Fehler.
{
vector<int> vec(3,7);
vec.push_back(256);
vec.insert(4,4);
for(auto it: vec){
cout << it << " ";
}
}
Es wurde ein Array angelegt mit 4 Elementen. An der vierten Stelle soll der Wert verändert werden. Warum funktioniert das nicht? Finden Sie den Fehler.
{
std::array<float, 4> arr = {1.1, 2.2, 3.3};
arr.at(4) = 4.4;
for(auto i: arr){
std::cout << i << " ";
}
}
In der Folgenden Map soll das gefundene Element ausgegeben werden.
Wenn die gesuchte Person (hier: Ernst Schmachtenberg) nicht in dieser
Map gespeichert ist, soll eine Meldung erscheinen. Finden Sie die
Fehler.
Zusatz: Warum ist eine Map nicht geeignet, um Vor- und Nachnamen
zueinander zu speichern?
{
std::map<std::string, std::string> people;
people["Schmachtenberg"] = "Ernst";
people["Rüdiger"] = "Ulrich";
people["Lankes"] = "Stefan";
people["Sauer"] = "Dirk";
people["Monti"] = "Antonello";
auto wanted = people.find("Ernst");
if(wanted != people.end()){
std::cout << wanted->first << ", " << wanted->second;
} else {
std::cout << "Person not found.";
}
}
Person not found.
Die erste 4 in dem insert-Befehl ist kein Iterator, dementsprechend
wird nicht die passende Sstelle zurück geliefert. Mögliche Lösungen
wären, entweder vec.insert(vec.end(), 4) oder
vec.push_back(4) zu benutzen. Alternativ kann man den
ganzen vector auch von vornherein mit den korrekten Werten
initialisieren. Zusätzlich fehlt das 'std::' vor
vector<int> bei der Initialisierung und vor
cout. Diesen Fehler könnte man auch durch die Zeile
using namespace std vor den geschweiften Klammern beheben,
dies ist aber keine gängige Praxis (mehr).
Hier sollten Sie sich an den Satz "Array index starts at 0" erinnern
(Dieser Satz ist i.A. gültig, es gibt aber einige wenige Ausnahmen, wie
Sie vielleicht aus Matlab etc. wissen). Um auf die vierte Stelle des
Arrays zuzugreifen, wird der Index 3 benutzt. Korrekt würde der Befehl
also lauten arr.at(3) = 4.4.
Wenn find() den Iterator end() liefert,
heißt das, dass kein Eintrag mit diesem Schlüssel in der Map existiert.
Der erste Fehler ist also, dass es in der if-Bedingung !=
statt == heißen müsste (oder die beiden Anweisungen
getauscht werden müssten). Der zweite Fehler ist, dass Key (deutsch:
Schlüssel) und Value (deutsch: Wert) in der Funktion verwechselt wurden.
Es wurde also nach dem Wert gesucht und nicht nach dem Schlüssel.
Richtig ist also
auto wanted = people.find("Schmachtenberg");.