Tutorium #2
Softwareentwicklung Praktikum
Gruppe 4 – Michael Schwarz
prog-tutor-michael@iicm.tugraz.at
Gruppe 5 – Anja Karl
prog-tutor-anja@iicm.tugraz.at
Gruppe 8 – Thomas Neff
prog-tutor-thomas@iicm.tugraz.at
Ablauf des Tutoriums
- STL - Standard Template Library
- Vektoren
- Strings
- Maps
- Makefiles
- Ass1
STL - Standard Template Library
- std::string
- Zeichenketten
- std::vector
- Arrays
- std::list
- Doppelt-verkettete Liste
- std::set
- Menge von eindeutigen Objekten
- std::map
- Assoziatives Array (Key-Value)
- std::array

- Array mit zusätzlichen Funktionen
...
- Generische Datentypen für unterschiedliche
Einsatzzwecke (z.B. std::vector<int> oder std::vector<std::string>)
- Automatisches Speichermanagement
- Iteratoren zum Durchlaufen der
Container, unabhängig von der Datenstruktur
- Vorgefertigte Algorithmen (copy, sort, transform, etc.)
http://www.liamdevine.co.uk/code/images/container.png
Vector
#include <vector>
Erstellen eines Vektors
using std::vector;
...
vector<int> int_vector;
oder
std::vector<int> int_vector;
Wichtigste Methoden
- Anzahl der Element im Vektor
int len = int_vector.size();
- Wert 3 an Position 0 einfügen
int_vector.insert(0, 3);
- Wert 3 an letzter Stelle einfügen
int_vector.push_back(3);
- Wert an Position 0
int element = int_vector[0];
Vector
std::vector<int> int_vector;
int_vector.push_back(42);
int_vector.push_back(13);
int_vector.push_back(37);
Zugriff auf alle Elemente durch Index...
int i;
for(i = 0; i < int_vector.size(); i++)
std::cout << int_vector[i] << std::endl;
...oder durch Iterator
for(vector<int>::iterator it = int_vector.begin(); it != int_vector.end(); it++)
std::cout << *it << std::endl;
...oder mit C++2011
for(auto it = int_vector.begin(); it != int_vector.end(); it++)
std::cout << *it << std::endl;
String: Text
#include <string>
Erstellen eines Strings
using std::string;
...
string hallo_str = "Hallo Welt!";
...
char* char_array = "Hallo Welt!";
string char_str (char_array);
Wichtigste Methoden
- Länge des Strings
int len = hallo_str.length();
- Zwei Strings aneinander hängen
hallo_str += char_str;
- liefert 0 wenn gleich
hallo_str.compare(char_str);
- Buchstabe an Position 0
char letter = hallo_str[0];
Schreiben auf stdout
#include <iostream>
int main()
{
std::cout << "Hallo Welt!\n";
return 0;
}
Verketten von Strings und anderen Datentypen möglich
std::cout << "The answer to life, the universe and everything is " << 42 << std::endl;
std::cout << "string1 is " << string1 << ", it's length is " << string1.length() << std::endl;
Ausgabe von Hexadezimalen Werten
int value = 32;
std::cout << value << " = 0x" << std::hex
<< value << std::endl;
Für Fortgeschrittene: Map
#include <map>
Eine Liste von Key-Value Paaren von einem beliebigen Datentyp. Erst Key-, dann Value-Datentyp.
std::map<std::string, int> grades_;
Direkter Zugriff auf Value über Key. Fügt ein Element ein, falls noch nicht vorhanden.
grades_["SEP"] = 1;
Beispiel:
int groesse = grades_.size();
std::map<std::string,int>::iterator it = grades_.find("SEP");
for(it = grades_.begin(); it != grades_.end(); it++)
std::cout << "Key: " << it->first << "Value: " << it->second << std::endl;
Prädikate testen 
- Testet, ob eine Eigenschaft auf ein (std::any_of), alle (std::all_of) oder kein (std::none_of) Element eines Containers zutrifft.
- Beispiel: Test, ob eine durch 5 teilbare Zahl in einem Vector vorkommt
#include <iostream>
#include <vector>
#include <algorithm>
bool is_div5(int x) { return (x % 5 == 0); }
int main() {
std::vector<int> numbers {1, 3, 5, 7, 9, 11, 13};
if(std::any_of(numbers.begin(), numbers.end(), is_div5)) {
std::cout << "Durch 5 teilbare Zahl gefunden" << std::endl;
}
}
Einfache Klasse II (ball.h)
#ifndef BALL_H_INCLUDED
#define BALL_H_INCLUDED
#include <string>
class Ball
{
private:
float x_, y_, speed_;
int direction_;
std::string name_;
public:
Ball(float x, float y, float speed, int direction,
std::string name);
void move();
float getSpeed();
void setSpeed(float speed);
std::string getName();
void setDirection(float direction);
float getDirection();
};
#endif
Konstruktor und move
(ball.cpp)
#include <math.h>
#include "ball.h"
Ball::Ball(float x, float y, float speed, int dir,
std::string name) : x_(x), y_(y), speed_(speed)
{
direction_ = dir * M_PI / 180.0;
name_ = "Ball '" + name + "'";
}
void Ball::move()
{
x_ = x_ + cos(direction_) * speed_;
y_ = y_ + sin(direction_) * speed_;
if(x_ < 0 || x_ > 800)
direction_ = atan2(sin(direction_), -cos(direction_));
if(y_ < 0 || y_ > 600)
direction_ = atan2(-sin(direction_), cos(direction_));
}
Getter und Setter
float Ball::getSpeed()
{
return speed_;
}
void Ball::setSpeed(float speed)
{
speed_ = speed;
}
std::string Ball::getName()
{
return name_;
}
float Ball::getDirection()
{
return direction_;
}
void Ball::setDirection(float direction)
{
direction_ = direction;
}
- Neuer Getter getName() liefert Namen des Balls zurück
- Neuer Getter getDirection() und Setter setDirection() für die Richtung des Balls
Das main
-Programm
#include <vector>
#include "ball.h"
int main()
{
std::vector<Ball> balls;
Ball b1(200, 225, 5, 10, "#1");
balls.push_back(b1);
while(1)
{
int i;
for(i = 0; i < balls.size(); i++)
{
if(balls[i].getName().compare("Ball #2") == 0)
balls[i].setDirection(balls[i].getDirection() + 1);
balls[i].move();
}
drawWindow(); // some magic...
}
}
|
|
Gruppenfindung
Exkurs Makefile
Aufbau:
Ziel: Abhängigkeit1 (Abhängigkeit2 ...)
<tab> (Befehl 1)
<tab> (Befehl 2)
...
Beispiel:
all: ass1
ass1: ass1.cpp
g++ ass1.cpp -Wall -o ass1
Exkurs Makefile
- Ass1
EXECUTABLE = ass1
OBJECT_DIR = objects
SOURCES = $(wildcard *.cpp)
OBJECTS = $(patsubst %,
$(OBJECT_DIR)/%,${SOURCES:.cpp=.o})
all: $(EXECUTABLE)
$(OBJECT_DIR)/%.o: %.cpp
$(CC) $(CCFLAGS) $@ $< -MMD -MF ./$@.d
$(EXECUTABLE) : $(OBJECTS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(OBJECT_DIR)/*.o $(OBJECT_DIR)/*.o.d
rm -f $(EXECUTABLE)
- $(CC)
- Compiler: g++
- $(CCFLAGS)
- Compilerflags: -Wall -g -c -o
- $@
- Zielname
- $<
- Namen der Abhängigkeiten
- $^
- Alle Quellen
- %.o: %.cpp
- generische Regel um .o Dateien aus .cpp Dateien zu erzeugen
- -MMD -MF ./$@.d
- Automatische Erkennung von Abhängigkeiten
Exkurs Makefile
Ass1 Makefile aufgelöst:
all: ass1
objects/Tower.o: Tower.cpp
g++ -Wall -g -c -o Tower.o Tower.cpp -MMD -MF ./Tower.o.d
[...]
objects/main.o: main.cpp
g++ -Wall -g -c -o main.o main.cpp -MMD -MF ./main.o.d
ass1 : objects/Tower.o objects/main.o [...]
g++ -o ass1 objects/Tower.o objects/main.o [...]
clean:
rm -f objects/Tower.o objects/main.o [...] objects/Tower.o.d [...]
rm -f ass1
# ass1 erstellen
make
# ass1 und alle *.o löschen
make clean
Ass1
- Grundlage für "Tower Defense"
- main.cpp wird vorgegeben
- 3 Klassen zu schreiben: SpeedRatio, Tower& Monster
Ass1 - SpeedRatio
SpeedRatio |
- events_ : unsigned int
- ticks_ : unsigned int
|
- currentEvents(unsigned int)
|
Ass1 - Tower
Tower |
- name_: string
- damage_: unsigned int
- range_: unsigned int
- shoot_ratio_: SpeedRatio
- game_: Game*
|
|
Ass1 - Monster
Monster |
- name_: string
- speed_ratio_: SpeedRatio
- damage_: unsigned int
- life_: unsigned int
- attribute_: unsigned int
- game_: Game*
|
|
Ass1 - Abgabe
Deadline: 19.03.2014 - 19:00
- main.cpp
- .cpp files
- .h files
Abgabe Archiv erstellen:
make submission
Freiwillige Übung
http://misc0110.net/lab
Viel Glück für Ass1
Nächstes Tutorium: 1. April