Intensivkurs C++ Formalien - ini.rub.de
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Rahmen Grundlagen Formalien Intensivkurs C++ Tag 1: Grundlagen Der Kurs besteht aus 10 Einheiten von je (maximal) 8 Stunden. Sebastian Houben Jeder Tag wird von einer Vorlesung eingeleitet, an die sich betreute Institut fürProgrammier Neuroinformatik übungen anschließen. In beiden Wochen stehen die Real-timeFreitage ComputerzurVision Wiederholung von Stoff zur Verfügung. Die Aufgaben können in Gruppen von bis zu drei Studierenden 18. Februar 2020 gelöst werden. Die Bearbeitung aller Aufgaben ist Voraussetzung für die erfolgreiche Teilnahme. Es gibt eine Liste, in der jeden Tag die erfolgreich bearbeiteten Aufgaben abgezeichnet werden. Alle Aufgaben sollten um 16:30 fertig bearbeitet sein, da der Raum pünktlich um 17:00 Uhr verlassen werden muss. Die Aufgaben werden benotet. Die Gesamtnote ergibt sich aus dem Durchschnitt der Tagesnoten. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 3
Rahmen Grundlagen Formalien Nicht vollständig bearbeitete Aufgaben können bis zum Freitag derselben Woche um 17 Uhr nachgereicht werden. Es ist möglich, bis zu 3 Tage entschuldigt zu fehlen. Dies betrifft sowohl Krankheit wie auch anderweitige Termine wie z.B. Klausuren. Bitte melden Sie sich dazu entweder persönlich am Tag vorher beim Dozenten oder per Mail über cplusplus@ini.rub.de ab. Die Aufgaben können nachgereicht werden (siehe oben). Es gibt eine Kurs-Homepage mit aktuellem Material auf http://ini.rub.de/courses/teaching /courses/intensive course c winter term 2019/ Zum Bestehen müssen mindestens 400 Punkte in den Präsenzaufgaben insgesamt und 30 Punkte an mindestens 7 Tagen erreicht werden Viel Spaß mit C++! Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 4
Rahmen Grundlagen Warum C++? Stärken: C++ ist schnell! C++ ist unglaublich flexibel. C++ ist typsicher. C++ ist gut organisiert; für sehr große Projekte geeignet. C++ ist ein weit verbreiteter Industriestandard. C++ ist extrem portabel. Schwächen: C++ erscheint (dem Anfänger) oft unnötig komplex. Relativ viel “boilerplate” code Teilweise kryptische Syntax (bei fortgeschrittenen Konzepten, z.B. Funktionszeiger) Teils schwer lesbare Fehlermeldungen Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 5
Rahmen Grundlagen Ziel dieses Kurses Einführung der Grundkonzepte der Programmiersprache C++ Es ist leicht, mit einer Darstellung von C++ ganze Regalwände zu füllen. C++ ist sehr umfangreich. Deshalb kann dieser Kurs keinen Anspruch auf Vollständigkeit haben. Ganz wichtig: Hands on! Dies ist ein Praktikum, keine Vorlesung! Learning by doing, sonst bleibt nur die Hälfte hängen. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 6
Rahmen Grundlagen Voraussetzungen Jeder Teilnehmer sollte Erfahrung mit einer halbwegs modernen (imperativen) Programmiersprache haben: Java, Javascript, Python, Lua, Pearl, PHP, C, Objective-C, C#, ... Erfahrung mit einer objektorientierten Sprache (z.B. Java oder Python) ist von Vorteil. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 7
Rahmen Grundlagen Verwandschaft zu C, Java und anderen Sprachen C++ ist (fast) eine Obermenge von C. Das heißt, dass fast aller C-Code in C++ gültig ist. Allerdings bietet C++ wesentlich bessere Möglichkeiten zur Strukturierung eines Programms und ermutigt deshalb zu einem besseren Stil (modularer, gut wartbarer Code). Java verfolgt ähnliche Ziele wie C++. Viele aus Java bekannte Konzepte übertragen sich auf die Programmierung in C++, aber C++ bietet generell mehr Möglichkeiten, mehr Kontrolle, und als Preis dafür leider oft weniger Komfort. Viele moderne Sprachen orientieren sich an C++, insbesondere an seiner Syntax. Wer eine andere Programmiersprache kennt, wird deshalb vieles wiedererkennen, aber mit Sicherheit auch neue Konzepte lernen, die er dann möglicherweise in anderen Sprachen vermisst. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 8
Rahmen Grundlagen Hello World Für die ganz Ungeduldigen - “Hello World” sieht in C++ so aus: helloworld.cpp #include using namespace std; int main() { cout
Rahmen Grundlagen Hello World Starten Sie Visual Studio Legen Sie ein neues Projekt an: Neues Projekt → Leeres Projekt; Name=“HelloWorld” Fügen Sie eine Datei hinzu: Projekt → Neues Element hinzufügen → Code → C++-Datei; Name=”main.cpp” (Menü Projekt Eigenschaften) → Konfigurationseigenschaften → Linker → System; Setzen Sie “Subsystem” auf “Konsole”. Tippen Sie das “Hallo-Welt”-Programm ein: #include using namespace std; int main() { cout
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Dateistruktur eines C++-Programms Ein typisches C++-Programm ist über mehrere Dateien (oft mit Endung .cpp) verteilt. Jede Datei kann einzeln vom Compiler in eine sogenannte Objektdatei übersetzt werden. In einem letzten Schritt bündelt der Linker die Objektdateien zu einem ausführbaren Programm. Beispiel: Ein Programm besteht aus den Dateien main.cpp, algo.cpp und tools.cpp. Daraus soll ein ausführbares Programm erstellt werden. Folgende Schritte sind notwendig: 1 Der Compiler übersetzt main.cpp in main.obj. 2 Der Compiler übersetzt algo.cpp in algo.obj. 3 Der Compiler übersetzt tools.cpp in tools.obj. 4 Der Linker setzt main.obj, algo.obj und tools.obj zum ausführbaren Programm (beispiel.exe) zusammen. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 11
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Q: Wie können Programmteile (Funktionen, Klassen) in verschiedenen Dateien von einander wissen, so dass sie sich gegenseitig aufrufen können? A: Meist gibt es zu jeder .cpp-Datei eine Header-Datei (.h oder .hpp). Die Header-Datei enthält ausschließlich Deklarationen, während die .cpp-Datei die zugehörige Implementierung enthält. Einer .cpp-Datei wird Wissen über andere Programmteile durch Einbinden der entsprechenden Header-Dateien mitgeteilt. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 12
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Q: Wo wird definiert, welche Dateien zusammengehören, um ein ausführbares Programm zu bilden? A: Das ist nicht Teil der Programmiersprache! Dies wird von jeder Programmierumgebung unterschiedlich gelöst. Visual Studio speichert diese Information in sogenannten Projektdateien (Solutions), die wiederum in Arbeitsbereiche organisiert sind. Jedes Projekt entspricht einer Bibliothek oder einem ausführbaren Programm. Ein Projekt definiert Quellen (.cpp) und Header (.h), sowie welche Bibliotheken verwendet werden sollen und wo diese zu finden sind. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 13
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor main.cpp #include "square.h" int main() { int s = square(7); } square.h #ifndef SQUARE_H #define SQUARE_H int square(int value); // Deklaration #endif square.cpp int square(int value) // Implementierung { return value * value; } Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 14
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Bibliotheken Niemand sollte das Rad neu erfinden. Für viele Standardaufgaben gibt es sehr gute Bibliotheken (z. B. die boost-Bibliotheken, Qt, usw.). Eine Bibliothek besteht aus zwei Teilen: Die eigentliche Bibliothek (Windows: .lib oder .dll; Linux: .a oder .so; Mac: .a oder .dylib) enthält die Implementierung, also das, was den .cpp-Dateien entspricht). Die Deklarationen zu einer Bibliothek stehen in den entsprechenden Header-Dateien. Diese gehören fest zur Bibliothek. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 15
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Beispiel: Unser Programm (main.cpp, algo.cpp, tools.cpp) verwendet die Bibliothek matrix, bestehend aus matrix.lib und matrix.h. Nehmen wir an, dass die Routinen aus matrix nur innerhalb von algo.cpp verwendet werden. 1 Der Compiler übersetzt algo.cpp in algo.obj. Er liest die Definitionen aus matrix.h ein, wobei ihm völlig egal ist, ob sich die Implementierungen zu den Definitionen in einer anderen .cpp-Datei oder in einer Bibliothek befinden. 2 Der Linker setzt main.obj, algo.obj, tools.obj und matrix.lib zum ausführbaren Programm (beispiel.exe) zusammen. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 16
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Präprozessor-Macros Alle Präprozessor-Macros beginnen mit dem Symbol #. #include "dateiname" wird durch den Inhalt der Datei ersetzt. Die Datei wird zuerst im aktuellen Projekt gesucht. So werden Dateien aus dem eigenen Projekt eingebunden. #include wird durch den Inhalt der Datei ersetzt. Die Datei wird im Include-Suchpfad gesucht. Diese Syntax wird für Header aus Bibliotheken verwendet. #define NAME oder #define NAME Wert, z.B. #define WIDTH 80. Definition einer Konstanten. #ifdef, #ifndef, #else und #endif werden zur bedingten Kompilierung verwendet. Beispiel: #ifdef DEBUG cout
Rahmen Grundlagen Dateistruktur, Compiler und Linker, Präprozessor Oft binden Header-Dateien weitere Header ein. Dies geschieht rekursiv, so dass ein einziges #include Statement eine große Menge an Headern einbinden kann. Deshalb ist oft unklar, ob ein Header bereits (implizit) eingebunden wurde oder nicht. Damit jeder Header nur maximal einmal in eine .cpp-Datei eingebunden wird, verwendet man sogenannte Include-Guards: #ifndef MEIN_HEADER_H #define MEIN_HEADER_H ...Inhalt... #endif Dabei ist MEIN HEADER H irgendein eindeutiger String, meist einfach der Dateiname. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 18
Rahmen Grundlagen Kommentare Zeilen-Kommentar: // Diese ganze Zeile ist ein Kommentar. int magic = 42; // siehe "Per Anhalter durch die Galaxis" ... Block-Kommentar: int magic = /*42*/ 1001; /* Als magische Zahl ist 1001 viel schoener als 42. Das liegt an ihrer Primfaktorzerlegung: 7 * 11 * 13 = 1001. */ Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 19
Rahmen Grundlagen Variablen und Funktionen Variablen: Typ Name; int a; int b = 7; int c, d = 3, e = f(b); Funktionen: Typ Name(Parameterliste) int f(int x); // Deklaration von f int f(int x) // Implementierung von f { return x * (1 - x); } int foo(int a, int b, float c, bool flag = true); Funktionsaufrufe int ergebnis = foo(f(7), d, 3.14159); foo(-42, 3, 3.14159, true); Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 20
Rahmen Grundlagen Vorwärtsdeklaration Beispiel: Rekursion über zwei Funktionen. void foo() { if (...) bar(); } void bar() { if (...) foo(); } Problem: Der Compiler arbeitet von vorn nach hinten und weiß deshalb nicht, was nach der aktuellen Stelle im Programm noch kommt. Innerhalb der Funktion foo ist bar noch nicht deklariert, wird aber aufgerufen. Fehler! Da hilft: die Vorwärtsdeklaration void bar(); // Vorwaertsdeklaration von bar void foo() { if (...) bar(); } void bar() { if (...) foo(); } Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 21
Rahmen Grundlagen Datentypen void: “kein Wert”, tritt oft als Rückgabetyp von Funktionen auf Logik: bool, mit Werten true, false, belegt 1 Byte Ganzzahl: char (8 Bit), int (meist 32 Bit). Konstanten: 42, -5, ’a’, ’\n’, ’\\’, ’\’’ Modifikatoren: unsigned, short, long, long long → unsigned long long int (= unsigned long long) Fließkomma: float (meist 32 Bit IEEE), double (meist 64 Bit IEEE) Konstanten: -1.0, 3.14159, .01, +5.77e-18 C-Strings: char s[256] = "Hallo, Welt"; (char-Array) C++-Strings: string s = "Hallo, Welt"; (String-Objekt) Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 22
Rahmen Grundlagen Datentypen Zeiger: int* Zeiger = Speicheradresse Referenz: int& Referenz = anderer Name für eine Variable void*: Zeiger auf untypisierten Speicher Konstante nullptr: ungültiger Zeiger Aufzählungen: enum FileFormat { wav, mp3, ogg }; Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 23
Rahmen Grundlagen Datentypen Zusammengesetzte Typen: class, struct, union C-Arrays: int a[20], bool b[64][64] STL-Container: vector, list, deque, set, multiset, map, multimap Alias-Namen für Typen: typedef Typ Name; Genauer: typedef [Variablendefinition mit neuem Namen als Variablennamen]; Es gibt viele weitere Typen, z.B. Funktionszeiger, STL-Iteratoren, Templates, ... Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 24
Rahmen Grundlagen Operatoren :: () [] . -> ++ -- dynamic cast static cast reinterpret cast const cast typeid ++ -- ∼ ! sizeof new delete * & + - (unary) (type) .* ->* * / % + - (binary) > < > = == != & ˆ | && || a ? b : c = *= /= %= += -= >>=
Rahmen Grundlagen Kontrollstrukturen Block { Kommando1; Kommando2; ... } Bedingte Ausführung 1 if (Bedingung) Kommando1; [else Kommando2]; Bedingte Ausführung 2 switch (Ausdruck) { case Konstante1: Kommandos1; break; case Konstante2: Kommandos2; break; ... default: KommandosN; } Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 26
Rahmen Grundlagen Kontrollstrukturen For-Schleife for (Kommando1; Bedingung; Kommando2) Kommando3; For-Schleife (range-based) for (Typ Variable : Container/Range) Kommando; While-Schleife while (Bedingung) Kommando; Do-While-Schleife do Kommando; while (Bedingung); Die Schlüsselwörter break und continue sind in allen Schleifen verfügbar. goto existiert (considered harmful, of course). Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 27
Rahmen Grundlagen Programm-Parameter Ein Konsolenprogramm kann mit Parametern aufgerufen werden: beispiel.exe -f 17 message=Hallo Diese Parameter stehen der main-Funktion zur Verfügung: int main(int argc, char** argv) { ... return 0; } argc: argument count - Anzahl der Parameter (+ 1) argv: argument values oder argument vector Der Typ von argv ist char**: Ein Zeiger auf einen Zeiger von Zeichen (Characters). Für heute reicht es aus zu wissen, dass argv[1] das erste Argument des Programms ist. Es ist gültig, falls argc > 1 erfüllt ist. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 28
Rahmen Grundlagen Konsolen-Ausgabe Das Objekt cout im Namensraum std ist ein sogenannter Stream (Datenstrom). Jedes Konsolenprogramm hat drei Standard-Streams: (Tastatur-)Eingabe (cin), Ausgabe (cout), und Fehler (cerr). Wir benutzen hier nur cout. Beispiel: #include using namespace std; cout
Rahmen Grundlagen Typumwandlung Beispiele statischer Typumwandlung: int a = 3; double b = a; // impliziter cast int -> double double c = 2.7; int d = c; // impliziter cast double -> int: Warnung oder Fehler! int e = (int)c; // expliziter cast (okay), setzt e = 2. int f = int(c); // expliziter cast, neue Syntax. int g = int(round(c)); // setzt g = 3. bool b1 = 17; // 0 -> false, Rest -> true bool b2 = nullptr; // nullptr -> false, alle anderen Zeiger -> true Typecasts elementarer Typen sind meist unkritisch Das Thema wird im Zusammenhang mit Klassen und Vererbung komplizierter. In altem C-Code werden oft Zeiger in Integers und zurück umgewandelt. Das ist sehr gefährlich, denn Zeiger auf 64bit-Systemen passen nicht in einen int! Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 30
Rahmen Grundlagen Typumwandlung Zahlen in Strings wandeln und zurück Umwandlung auf C-Art int wert = 42; char str[50]; sprintf(str, "%d", wert); // str = "42"; int wert2 = strtol(str, nullptr, 10); // wert2 = 42; Umwandlung auf C++-Art int wert = 42; stringstream ss; ss > wert2; // wert2 = 42; Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 31
Rahmen Grundlagen Debugging! HowTo Debug... Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 32
Rahmen Grundlagen Hilfe, Referenz, Dokumentation gutes Tutorial: http://www.cplusplus.com/doc/tutorial/ Referenz-Dokumentation: http://www.cplusplus.com/doc/ http://www.cplusplus.com/reference/ Linux/Mac: man-pages! Windows: MSDN Weitere Quellen: Programmierfragen, Fehlermeldungen: Google, Stack Overflow. Algorithmen: Wikipedia. Intensivkurs C++ 18. Februar 2020 — Sebastian Houben 33
Sie können auch lesen