Kapitel 9
Alle Codedateien dieses Kapitels herunterladen
09_6_1_WieVielByte.cpp
/*
* Lösung für Übung 9.6.1 - Wie viel Byte
*
* Für die Lösung mussten Sie keinen Code schreiben. Hier
* folgt die ausgefüllte Tabelle, unten ist etwas Testcode dafür
*
* Element | Speicherbedarf | Erklärung
* ================================================================================================
* int a = 17; | 4 Byte |
* ------------------------------------------------------------------------------------------------
* size_t b = 17; | 8 Byte | size_t ist für größere Zahlen bestimmt
* ------------------------------------------------------------------------------------------------
* std::string c = "Hola"; | 29 Byte (mindestens)| 24 Byte für den leeren String (8 für den
* | | Zeiger, 8 für die Puffergröße, 8 für die Länge)
* | | + 4 Zeichen + 1 End-Of-String Zeichen
* ------------------------------------------------------------------------------------------------
* int* d = new int(17); | 12 Byte | 8 für den Zeiger, 4 für den int
* ------------------------------------------------------------------------------------------------
* struct Test { int a; }; | 4 Byte | 4 für den einzigen Member, das a
* ------------------------------------------------------------------------------------------------
* bool e = false; | 1 Bit / 1 Byte | True oder False braucht nur ein einziges Bit,
* | | Wenn Sie also "1 Bit" geantwortet haben, ist das
* | | richtig. In der Realität wird aber meistens wegen
* | | technischer Besonderheiten ein ganzes Byte reserviert
*/
#include <iostream>
struct Test
{
int a;
};
int main()
{
int a = 17;
std::cout << "int a = 17;\t\t" << sizeof(a) << std::endl;
size_t b = 17;
std::cout << "size_t b = 17;\t\t" << sizeof(b) << std::endl;
std::string c = "Hola";
// Hinweis: sizeof(std::string) ist implementationsabhängig.
// Für Fortgeschrittene gibt es hier eine ausgiebige Betrachtung: https://shaharmike.com/cpp/std-string/
std::cout << "std::string c = \"Hola\";\t" << (24 + 4 + 1) << std::endl;
int* d = new int(17);
std::cout << "int* d = new int(17);\t" << sizeof(d) + sizeof(*d) << std::endl;
delete d;
std::cout << "struct Test { int a; };\t" << sizeof(Test) << std::endl;
bool e = false;
std::cout << "bool e = false;\t" << sizeof(e) << std::endl;
return 0;
}
09_6_2_Zeigerfehler.cpp
/*
* Lösung für Übung 9.6.2 - Zeigerfehler
* Diese Datei enthält drei Teile:
* - Den auskommentierten fehlerhaften Code
* - Eine Korrektur mittels normaler Zeiger
* - Eine Korrektur mit Smart Pointern
*/
#include <iostream>
#include <string>
#include <memory>
int main()
{
/* FEHLERHAFTER CODE:
std::string* stringPointer;
bool* consoleOutput = new bool(false);
int* intPointer = new int(0);
if (consoleOutput)
{
std::cout << "consoleOutput ist wahr" << std::endl;
}
intPointer = 17;
if (intPointer + 1 == 18)
{
bool otherValue = true;
std::cout << "Diese Ausgabe sollte kommen";
consoleOutput = &otherValue;
}
delete stringPointer;
delete intPointer;
*/
// Korrektur ohne Smart Pointer:
{
// Der Pointer war nicht auf nullptr initialisiert!
// Das "delete stringPointer" später hätte zu einem riesen Problem geführt.
// Völlig zufälliger Speicher wäre freigegeben worden
std::string* stringPointer = nullptr;
bool* consoleOutput = new bool(false);
int* intPointer = new int(0);
// Das Dereferenzieren (Sternchen) wurde vergessen. Ohne das Sternchen
// war der Vergleich gleichbedeutend mit if (consoleOutput != nullptr) , was definitiv
// nicht der hier beabsichtigte Vergleich war
if (*consoleOutput)
{
std::cout << "consoleOutput ist wahr" << std::endl;
}
// Das Dereferenzieren des Zeigers wurde vergessen
*intPointer = 17;
// Hier ebenfalls.
if (*intPointer + 1 == 18)
{
// Spitzfindigerweise könnte man sagen, hier fehle noch das std::endl. Ist aber nicht so wichtig.
std::cout << "Diese Ausgabe sollte kommen" << std::endl;
// Hier gab es zwei Probleme: Erstens wurde der Zeiger consoleOutput auf die Variable
// otherValue umgebogen, die aber nach Verlassen des Bereichs ungültig wurde.
// Zweitens muss vor dem Umbiegen des Zeigers auf einen neuen Speicherbereich der alte
// erst mit delete aufgeräumt werden. Hier wurde das gemacht und danach dann mit new
// ein neuer Speicherbereich belegt
delete consoleOutput;
consoleOutput = new bool(true);
}
// Das Aufräumen von consoleOutput fehlte
delete intPointer;
delete consoleOutput;
// stringPointer ist zwar das ganze Programm hindurch nullptr geblieben,
// zur Sicherheit räumen wir es aber trotzdem auf.
delete stringPointer;
}
// Korrektur: mit Smart Pointern
{
std::shared_ptr<std::string> stringPointer;
std::shared_ptr<bool> consoleOutput = std::make_shared<bool>(false);
std::shared_ptr<int> intPointer = std::make_shared<int>(0);
if (*consoleOutput)
{
std::cout << "consoleOutput ist wahr" << std::endl;
}
*intPointer = 17;
if (*intPointer + 1 == 18)
{
std::cout << "Diese Ausgabe sollte kommen" << std::endl;
// Kein vorheriges delete notwendig - wird automatisch erledigt.
consoleOutput = std::make_shared<bool>(true);
}
// Keine delete Anweisungen notwendig - wird automatisch erledigt.
}
return 0;
}
09_6_3_Wiederholungstaeter.cpp
/*
* Lösung für Übung 9.6.3 - Wiederholungstäter
*
* - Sie können das einzelne Zeichen natürlich auch in ein
* char abspeichern, aber std::string ist einfacher zu benutzen.
* - Sie können auch eine while(true)-Schleife verwenden, die im Falle
* einer korrekten Eingabe mit break; verlassen wird.
*/
#include <exception>
#include <iostream>
#include <string>
int main()
{
std::string oneCharacter;
bool inputMissing = true;
while (inputMissing)
{
std::cout << "Geben Sie ein Zeichen ein: ";
std::getline(std::cin, oneCharacter);
inputMissing = (oneCharacter.size() != 1);
if (inputMissing)
{
// Hier sollten Sie keinen Fehler mit throw schmeißen sondern schlicht
// nach einer neuen Eingabe fragen.
std::cerr << "Sie haben mehr als ein Zeichen eingegeben!" << std::endl;
}
}
int number = 0;
inputMissing = true;
while (inputMissing)
{
std::cout << "Geben Sie die Anzahl von Wiederholungen ein: ";
std::string input;
std::getline(std::cin, input);
try
{
number = std::stoi(input);
inputMissing = false;
}
catch (std::exception& ex)
{
std::cerr << "Keine g\201ltige Zahl eingegeben!" << std::endl;
}
}
for (int i = 0; i < number; i++)
{
std::cout << oneCharacter;
}
return 0;
}
09_6_4_DeklarationenUndDefinitionen
Plant.cpp
/*
* Lösung für Übung 9.6.4 - Deklarationen und Definitionen
*
* Die hinzugefügten Zeilen sind mit ## markiert
*/
#include <iostream>
#include "Plant.h" // ## Fehlte in der Aufgabenstellung ##
// ## Fehlte in der Aufgabenstellung ##
Plant::Plant(const std::string& name)
: name(name)
{
}
// ## Fehlte in der Aufgabenstellung ##
std::string Plant::getName() const
{
return name;
}
void Plant::water()
{
moisture++;
}
int main()
{
Plant tulip("Tulpe");
std::cout << tulip.getName() << std::endl;
tulip.water();
return 0;
}
Plant.h
#pragma once // ## Fehlte in der Aufgabenstellung ##
#include <string>
class Plant
{
public:
Plant(const std::string& name);
std::string getName() const;
void water(); // ## Fehlte in der Aufgabenstellung ##
private:
const std::string name;
int moisture = 0;
};