C++/Tutorial: 4. Container
Arrays und Container
Mittlerweile können wir relativ gut mit einzelnen Variablen umgehen, aber meistens variieren nicht nur die Daten, sondern auch die Datenmenge. Als Beispiel könnte man so ziemlich jedes Programm nehmen, aber besonders anschaulich wäre in anbetracht der RPG-lastigkeit von Scientia ein RPG. Nehmen wir zum Beispiel Gegner in einem RPG. Die Anzahl der Gegner variiert in einem RPG und es reicht auch nicht die Anzahl als Variable zu speichern, da jeder Gegner selbst über bestimmte Eigenschaften wie zum Beispiel Lebenspunkte verfügt, die ebenfalls in Variablen gespeichert werden müssen. Was wir nun also zum Beispiel wollen, wäre zu sagen "Ich hätte gerne 5 Gegner, der erste soll über 100HP verfügen, der zweite über 200 u.s.w.", sodass man die Werte später natürlich noch auf genau die selbe Weise abrufen und modifizieren kann. Um das zu erreichen gibt es (neben anderen Varianten) Arrays. Ein Array ist eine Variable, die man als eine Art Tabelle ansehen kann. Zunächst wird ein Array mit einer bestimmten Größe erzeugt und dann wird über einen Index, der auch eine Variable sein kann(der wievielte Gegner?) auf die zugrunde liegende Variable zugegriffen(die dann den HP-Wert für diesen Gegner enthält). Genau das was wir wollten tut folgender Beispielcode:
#include <iostream> //macht cin und cout verfügbar #include <vector> //macht vector verfügbar #include <limits> //macht numeric_limits verfügbar using namespace std; int main() { //Lies die Anzahl der Gegner ein cout << "Wie viele Gegner?" << endl; int number_of_enemies; cin >> number_of_enemies; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); //Lies die HP Werte ein cout << "Geben sie die HP-Werte ein" << endl; vector<int> enemy_hp(number_of_enemies); for(int i(0); i < number_of_enemies; i++) { cin >> enemy_hp[i]; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); } //Ziehe einem ausgewähltem Gegner 10 HP ab und zeige die aktuellen HP an cout << "Welcher Gegner soll geschlagen werden?" << endl; int attacked_enemy_id; cin >> attacked_enemy_id; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); attacked_enemy_id--; enemy_hp[attacked_enemy_id] -= 10; cout << "Gegner " << (attacked_enemy_id + 1) << " hat nun noch " << enemy_hp[attacked_enemy_id] << "HP" << endl; cin.get(); }
An diesem Code werden wir uns wie bisher entlanghangeln, wobei in diesem Code kein Array (direkt) zum Einsatz kommt, sondern der vector-Container, der in C++ anstelle von Arrays verwendet werden sollte, da er einige Dinge vereinfacht. Im Gegensatz zu arrays ist vector allerdings kein eingebauter Typ und lässt sich problemlos selbst nachbauen.
Der vector-container
Der erste Abschnitt des Codes enthält noch nichts neues, interessant wird es erst im zweiten Teil, indem der vector erstellt und mit Werten versehen wird.
vector<int> enemy_hp(number_of_enemies);
erstellt den vector. Die allgemeine Form eine vector-Variable anzulegen lautet wie folgt
vector<TYP> IDENTIFIER([optional]GRÖßE, [optional]DEFAULTWERT_DER_ELEMENTE);
Beim Typ handelt es sich um den Typ aller enthaltenen Variablen, verschiedene Typen sind nicht möglich. Beim Identifier handelt es sich wie üblich um einen Bezeichner, über den auf die Variable(der vector selbst ist gemeint) zugegriffen wird. Das würde schon reichen, aber damit könnten wir noch nicht viel anfangen, da dieser vector die Größe 0 hätte und keinerlei Elemente enthält. In Klammern dahinter sollten wir zumindest die Größe angeben, was auch duch eine Variable geschehen kann, wie zum Beispiel in unserem Beispiel, wo die Größe direkt eingegeben wird(number_of_enemies). Durch Komma getrennt kann man anschließend noch einen Ausgangswert definieren. Da wir im Anschluss noch alle Werte einlesen und manuell belegen brauchen wir das nicht, wir könnten aber mit
vector<int> enemy_hp(number_of_enemies, 100);
alle Elemente des vectors von vornerein mit dem Wert 100 versehen.
Im Anschluss lesen wir in einer Schleife die Lebenspunkte der Gegner von der Konsole ein. Der Schleifenzähler i wird hierbei als index für den vector verwendet. Nochmal zur Erläuterung: i wird bei jedem Schleifendurchlauf um eins hochgezählt, ist zunächst 0 und beim letzten Durchlauf number_of_enemies-1. Der Zugriff auf die Lebenspunkte der Gegner geschieht mit dem Indexoperator, in dem Beispiel steht
enemy_hp[i]
für die HP des i.ten Gegners. Wie bereits erwähnt beginnt i bei 0, was schon zeigt, dass die Indizes von vectoren nicht mit 1 beginnen, sondern mit 0, sprich wir beginnen mit dem "nulltem" Gegner. Wenn wir nun also enemy_hp mit der Größe 3 erstellen, dann gibt es enemy_hp[0], enemy_hp[1] und enemy_hp[2], nicht aber enemy_hp[3].
Im folgendem Programm folgen keinerlei neue Dinge, es sollte nun möglich sein es zu verstehen(wenn nicht, sollten die letzten Kapitel nochmal durchgegangen werden).