FB Informatik Prof. Dr. R.Nitsch Programmieren 1 - Grundlagen Programmiersprachen Entwicklungsumgebung Bestandteile eines Programmierprojekts C++ Programm Ein- und Ausgabe Integrierte Datentypen Container vector und string Operatoren Gültigkeit und Sichtbarkeit von Variablen Was geschieht beim Ausführen eines Programms FB Informatik Prof. Dr. R.Nitsch Ein Programm ist eine Datei, die Befehle enthält, die der Computer ausführen kann. Wird eine ausführbare Datei (.exe) gestartet, wird sie zunächst von der Festplatte in den Hauptspeicher geladen. Nur dort kann das Programm gestartet werden. werden die Befehle vom Prozessor (CPU) abgearbeitet. Ein gestartetes Programm nennt man Prozess. Die CPU hat einen Programmzeiger. Der zeigt auf den nächsten Befehl, der ausgeführt wird. Beim Starten des Prozesses wird dieser Zeiger auf den ersten Befehl des Programms gesetzt. Jeder Befehl weist die CPU an, Datenwerte aus dem Speicher zu lesen zu schreiben oder zu berechnen. Datenwerte in Speicherstellen zu vergleichen und in Abhängigkeit davon mit der Abarbeitung an einer anderen Stelle fortzufahren. Die Befehle, die von der CPU derart interpretiert werden, bilden den Befehlssatz der Maschinensprache dieser CPU. Der Hauptspeicher enthält sowohl die Befehle als auch die Daten Die Befehle und die Datenwerte sind binär kodiert Die verschiedenen Prozessoren unterscheiden sich im Umfang ihrer Befehlssätze und in den Binärcodes für die einzelnen Befehle. Deshalb laufen Programme auch nur auf dem Prozessor, dessen Befehlssatz bei der Erstellung des Programms verwendet wurde. 10.04.2013 C++ Grundlagen 2 Programmiersprachen - Machschinensprachen FB Informatik Prof. Dr. R.Nitsch sind die Muttersprache des jeweiligen Prozessors sind definiert durch sein Hardwaredesign (total maschinenabhängig) bestehen aus Bitgruppen (Wörtern) sind für Menschen schwer nachvollziehbar sind deshalb für Programmierzwecke völlig ungeeignet Höhere Programmiersprachen sind besser geeignet. Beispiel: Code B17D41C3 B18D41C7 4FCA472A DC7E23BA 10.04.2013 Kommentar Lade Wert in Adresse 41C3 in Reg. 1 Lade Wert in Adresse 41C7 in Reg. 2 Addiere die Registerinhalte und speichere das Ergebnis in Reg. 1 Speichere Inhalt von Register 1 unter der Speicheradresse 23BA C++ Grundlagen 3 Programmiersprachen - Assembler-Sprachen FB Informatik Prof. Dr. R.Nitsch sind für Menschen leichter merkbar und lesbar sind ideal für zeitkritische Algorithmen durch optimale Ausnutzung des Befehlssatzes sind sparsam im Speicherplatzbedarf (Hohe Speicherplatzökonomie) sind ebenfalls total maschinenabhängig (Jeder CPU-Typ hat seine eigene Assemblersprache). sind ungeeignet für größere Softwareprojekte Beispiel: LOAD R1, LOAD R2, ADD R1, STORE R1, #41C3h #41C7h R2 #23BAh Assembler B17D41C3 B18D41C7 4FCA472A DC7E23BA müssen zur Ausführung in die Maschinensprache übersetzt werden Die Übersetzung erfolgt 1:1 (s. Abb.) Das Übersetzungsprogramm wird Assembler genannt. 10.04.2013 C++ Grundlagen 4 Programmiersprachen - Hochsprachen FB Informatik Prof. Dr. R.Nitsch fassen mehrere Maschinenbefehle zu Anweisungen (statements) zusammen Anweisungen enden in C++ immer mit einem Semicolon (;) benutzen Elemente der Alltagssprache und bekannte mathematische Notationen Beispiel: int number1, number2, sum; sum = number1 + number2; Anweisung 1 Anweisung 2 benötigen Compiler bzw. Interpreter die die Anweisungen in ausführbaren Maschinencode übersetzen. sind für Menschen leicht versteh- und anwendbar sind maschinenunabhängig Weit verbreitete Hochsprachen sind (C, C++, Java, Fortran, Cobol, ...) 10.04.2013 C++ Grundlagen 5 Eigenschaften von C++ FB Informatik Prof. Dr. R.Nitsch Hybride Sprache: Enthält den Sprachumfang von C als Teilmenge (modular, effizient, maschinennah, portabel, formatfrei) Unterstützt Konzepte der objektorientierten Programmierung (kurz: OOP) Abstraktion: Trennung des WAS vom WIE ETWAS gemacht wird (black box). Kapselung: Kontrollierter Zugriff auf Zustand und Funktion von Objekten. Vererbung: Vereinfachte Bildung von ähnlichen Objekten mit modifizierten Eigenschaften und/oder Verhalten wie die Ursprünglichen bei der Übersetzung. Polymorphie (griech. Vielgestaltigkeit): Objekte können zur Laufzeit ihre Eigenschaften und/oder Verhalten verändern. Getypte Sprache (strenge Typkontrolle durch Compiler) Erweiterungen ohne Bezug zur OOP Referenzen Templates Ausnahmebehandlung (Exception-handling) Standard Library (STL) 10.04.2013 C++ Grundlagen 6 All 84 C++ keywords FB Informatik Prof. Dr. R.Nitsch Cannot be used as identifiers or variable names alignas (C++11) alignof (C++11) and and_eq asm auto(1) bitand bitor bool break case catch char char16_t (C++11) char32_t (C++11) class compl const constexpr (C++11) const_cast continue decltype (C++11) default(1) delete(1) do double dynamic_cast else enum explicit export extern false float for friend goto if inline int long mutable namespace new noexcept (C++11) not not_eq nullptr (C++11) operator or or_eq private protected public register reinterpret_cast return short signed sizeof static static_assert (C++11) static_cast struct switch template this thread_local (C++11) throw true try typedef typeid typename union unsigned using(1) virtual void volatile wchar_t while xor xor_eq (1) Bedeutung in C++1 geändert. 10.04.2013 C++ Grundlagen 7 Der Algorithmus FB Informatik Prof. Dr. R.Nitsch Anders als ein Mensch hat ein Computer keine Fantasie und keine Erfahrungen. Die Programmbefehle müssen ihm kleinschrittig vorschreiben, was er tun soll, und dabei keine Missverständnisse zulassen. Alle Vorbedingungen (preconditions) für das Funktionieren des Algorithmus müssen kontrolliert werden. Eine solche Verfahrensbeschreibung nennt man einen Algorithmus Es ist schwieriger als man denkt, ein Verfahren so zu beschreiben, dass der Ausführende zwingend zu einem bestimmten Ergebnis kommt. Beispiel: Kochbucheintrag für ein 3-Minuten-Ei: Lege ein Ei für 3 Minuten in kochendes Wasser. Wie lautet die Befehlsfolge für einen Computer oder Menschen ohne Erfahrung und Fantasie? 10.04.2013 C++ Grundlagen 8 Algorithmus für 3-min-Ei FB Informatik Prof. Dr. R.Nitsch Nehme ein Ei aus dem Kühlschrank (PRE: Ei und Kühlschrank sind vorhanden). Nehme einen Wasserhahn (PRE: Wasserhahn existiert) Nehme einen Kochtopf mit 17 cm Durchmesser und Höhe 9 cm (PRE: Kochtopf existiert). Halte den Kochtopf unter den Wasserhahn und drehe das Ventil nach links. Solange nicht 1 Liter Wasser im Kochtopf, tue nichts. Danach drehe Ventil nach rechts bis zum Anschlag. Nehme eine Herdplatte und schalte sie auf Stufe 3 (PRE: Herdplatte existiert) Stelle den Kochtopf auf die Herdplatte. Solange Wassertemperatur im Kochtopf kleiner 100° tue nichts. Lege Ei in Kochtopf. Merke dir die aktuelle Zeit als Startzeit. Solange aktuelle Zeit kleiner Startzeit plus 3 min tue nichts. Danach schalte Herdplatte aus. Nimm Ei heraus. 10.04.2013 C++ Grundlagen 9 Das erste Programm in C++ Quellcode: "Arbeitslos" /31-43/ FB Informatik Prof. Dr. R.Nitsch C++ Programme bestehen u.a. aus Funktionen. ACHTUNG: Dies sind keine Funktionen im mathematischen Sinne, sondern: Eine Funktion definiert einen Algorithmus, der EINE wohldefinierte Aufgabe löst (z.B. 3Min-Ei kochen). Steht ein Ergebnis am Ende eines Algorithmus, kann dieses zurück gegeben werden (z.B. das 3-Min-Ei). Jedes C++ Programm muss genau eine Funktion 'main' enthalten Beim Programmstart sucht der Computer die Funktion 'main' und beginnt dort mit der Ausführung. int main() { // Keine Anweisungen, d.h. arbeitslos! return 0; Es ist eine Programmiererkonvention, 0 zurückzugeben, Es bedeuten: } wenn das Hauptprogramm ohne besondere Vorkommnisse endet. int Platzhalter für ganze Zahl zur Ergebnis-Rückgabe main Name der Funktion ( hier: Reservierter Name für Hauptprogramm) ( ) Innerhalb dieser Klammern können dem Hauptprogramm Informationen mitgegeben werden (z.B. 1 Ei und 3 Min. Kochzeit). Leere Klammern, wenn der Algorithmus keinen Input braucht. { } Block (enthält die Anweisungen an den Rechner) /*...*/ Kommentar, der über mehrere Zeilen gehen kann //... Kommentar bis Zeilenende 10.04.2013 C++ Grundlagen 10 Der C++ Klassiker: Die Begrüßung // File: HalloUffHessisch.cpp #include <iostream> using namespace std; FB Informatik Prof. Dr. R.Nitsch // Macht dem Computer die Ein- und Ausgabefunktionen zugänglich // iostream: Name einer C++ Header-Datei // Diese Zeile zunächst immer hinter die #include-Zeilen schreiben. // Erklärung folgt später. // This program outputs the greeting "Ei Guude, wie?" to the monitor int main() // All C++ programs start by executing the function main { // Ausgabe: cout (Abkürzung für "character out") ist die Standardausgabe zum Monitor. // Der Doppelpfeil deutet an, dass alles, was rechts davon steht, zur Ausgabe cout gesendet wird. cout << "Ei Guude, wie?\n"; // output "Ei Guude, wie?" (ohne "") Steuerzeichen für "neue Zeile" (später mehr) Die Begrenzerzeichen (") müssen jede Zeichenkette umschließen. return 0; Unser Programm läuft einwandfrei; es gibt daher 0 zurück. Diese Anweisung kann fehlen, dann wird automatisch 0 zurückgegeben. } // Ein ';' schliesst jede Anweisung (statement) und jede Definition ab 10.04.2013 C++ Grundlagen 11 Vom Quellcode zum Objektcode /31/ FB Informatik Prof. Dr. R.Nitsch C++ ist eine Compilersprache: d.h. zuerst muss ein C++ Compiler den Programmcode in für den Computer verständliche Sprache übersetzen. Quellcode (.cpp) g++.exe -c HalloUffHessisch.cpp 10.04.2013 Compiler Objektcode (.obj) compilieren (HalloUffHessisch.obj wird erzeugt) (bzw. HalloUffHessisch.o bei anderen Compilern) C++ Grundlagen 12 Vom Objektcode zum ausführbaren Programm FB Informatik Prof. Dr. R.Nitsch Ein Programm besteht meist aus mehreren Teilen (translation units) Beispiel: "Ei Guude, wie?" besteht aus Hauptprogramm "main" und dem Header "iostream" Jedes Teil wird separat compiliert Die verschiedenen Objectcode-Dateien müssen durch ein weiteres Programm, den Linker, miteinander zum ausführbaren Programm verknüpft werden. HalloUffHessisch.obj Linker HalloUffHessisch.exe Libraries (z.B. iostream.obj) Beispiel: g++.exe -o HalloUffHessisch.exe HalloUffHessisch.obj iostream.obj binden. Das Programm wird durch Eintippen von HalloUffHessisch.exe gestartet 10.04.2013 C++ Grundlagen 13 Integrated Development Environment (IDE) /37/ FB Informatik Prof. Dr. R.Nitsch Integrierte Entwicklungsumgebung (IDE) Editor Quellcode (.cpp) Header (.h) Präprozessor Übersetzen in Maschinencode Compiler Objektcode (.obj) Linker Standard-Bibliothek Externe Bibliotheken Binden der Objektdateien Ausführbare Datei (.exe) Debugger Schnelleinstieg in Microsoft Visual C++ Express 2010 siehe Anhang Loader RAM 10.04.2013 C++ Grundlagen 14 Der Präprozessor, der Compiler und der Fehlerteufel FB Informatik Prof. Dr. R.Nitsch Präprozessor bereitet den Quellcode für den Compiler vor wird u.a. gesteuert durch Präprozessor-Anweisungen die mit '#' beginnen Die Anweisung #include <DieseDatei> bzw. #include "DieseDatei" fordert den Präprozessor auf, diese Anweisung durch den Inhalt der Datei DieseDatei zu ersetzen. Entfernt Kommentare aus dem Quellcode Der Compiler achtet auf korrekte Syntax und Grammatik ist dabei sehr pingelig, beschwert sich selbst über kleinste Details, hat aber immer Recht. Beispiele für häufige Fehler: #include Anweisung fehlt Tippfehler, z.B. #include "DieseDatei (Abschließendes " fehlt) integer statt int < statt << oder = statt == ' statt " ; an der falschen Stelle usw... 10.04.2013 C++ Grundlagen 15 Systematische Programmentwicklung FB Informatik Prof. Dr. R.Nitsch Wie werden Programme entwickelt? Schritt 1: Problemanalyse Schritt 2: Programmdesign Schritt 3: Implementation Schritt 4: Testen Schritt 1: Analysis - Formulierung der Aufgabe (aus Benutzersicht) -> OOAD Beispiel: Addition zweier Zahlen 1. Das Programm fordert den Benutzer auf, 2 Zahlen einzugeben 2. Benutzer gibt 2 Zahlen auf der Tastatur ein 3. Das Programm liest die Zahlen und berechnet die Summe 4. Das Programm gibt die Summe auf dem Bildschirm aus Schritt 2: Design - Zerlegung der Aufgabe in Teilaufgaben -> OOAD Beispiel: Addition zweier Zahlen Ausgabe der Benutzeraufforderung (prompt) "Gib 2 Zahlen ein: " Lies 2 Zahlen in 2 Variablen summand1 und summand2 ein Berechne die Summe beider Zahlen und speichere das Ergebnis in der Variablen summe Gib das Ergebnis auf dem Ausgabegerät (Konsole) aus: "Summe = <Ergebnis>" 10.04.2013 C++ Grundlagen 16 Systematische Programmentwicklung FB Informatik Prof. Dr. R.Nitsch Schritt 3: Implementation - Umsetzen der Teilaufgaben in C++ Code Die Kommentare bleiben zur Dokumentation erhalten // Datei: summe.cpp // Die erste Zeile dokumentiert den zugehörigen Dateinamen. #include <iostream> using namespace std; int main() { // Addition zweier Zahlen int summe; // Definition von Variablen: Weist den Compiler an, int summand1; // (1) Speicherplatz zu reservieren, int summand2; // (2) diesem Speicherplatz einen Namen (z.B. summe) zu geben. // Variablennamen sind symbolische Adressen für Speicherbereiche // Ausgabe der Benutzeraufforderung (Prompt) cout << "Gib 2 Zahlen ein: "; // Zeichenkette mit Anführungszeichen als Anfangs- und Ende-Kennung 10.04.2013 C++ Grundlagen 17 Systematische Programmentwicklung FB Informatik Prof. Dr. R.Nitsch // Lies 2 Zahlen in 2 Objekte summand1 und summand2 ein cin >> summand1; Hier werden zwei Werte von der Tastatur eingelesen! cin >> summand2; Eingabe: Der Doppelpfeil zeigt hier in Richtung des Datenflusses. Die Daten fließen von der Eingabe cin zu den Objekten summand1 bzw. summand2. // Die Summe beider Zahlen berechnen und in Objekt summe speichern summe = summand1 + summand2; Zuweisungsoperator (=): Das Ergebnis der Addition auf der rechten Seite wird dem Objekt auf der linken Seite des Gleichheitszeichens zugewiesen, d.h. das Ergebnis wird in den Objekt-Speicherplatz "summe" kopiert. // summe auf dem Monitor ausgeben: "Summe = <Ergebnis>" cout << "Summe= " << summe; return 0; // Unser Programm läuft einwandfrei; es gibt daher 0 zurück. } 10.04.2013 C++ Grundlagen 18 Genauer hingeschaut: Objekt, Typ, Variable FB Informatik Prof. Dr. R.Nitsch Objekte sind "Orte" (Speicherbereiche) in denen Daten gespeichert werden. Objekte enthalten Daten in Binärform. Um die Daten korrekt interpretieren zu können, benötigen Objekte einen Typ. Ein Typ bestimmt welche Daten an dem Ort (in dem Objekt) abgelegt werden, die Regeln, nach denen die Daten vor dem Speichern in Binärdaten umcodiert werden und den beanspruchten Speicherplatz die Operationen, die mit den Daten ausgeführt werden können (s.Seite 29) Beispiele: Typ int: kann einen Ganzzahlwert wie 123 aufnehmen. Werte dieses Typs können u.a. miteinander multipliziert und addiert werden (123*12, 123+12) Typ string: kann Zeichenketten wie "Ei " und "Guude, wie?" aufnehmen. Werte dieses Typs können u.a. miteinander verkettet werden ("Ei " + "Guude wie" ergibt "Ei Guude wie"). Multiplizieren ist nicht definiert. Um auf ein Objekt zugreifen zu können, benötigt man seine Adresse im Speicher oder als Ersatz dafür einen Namen, weil man sich Adressen schlecht merken kann. Variablen sind Objekte, d.h. sie haben einen Speicherplatz, denen ein Name bzw. eine Adresse und ein Typ zugeordnet sind. 10.04.2013 C++ Grundlagen 19 Genauer hingeschaut: Speicherkonzept bei Variablen FB Informatik Prof. Dr. R.Nitsch Variablen bzw. Objekte (Speicherbereiche für Werte) müssen vor erster Benutzung definiert werden sind u.a. gekennzeichnet durch Namen (symbolische Adresse), Datentyp (type), Adresse im Speicher und Wert (value) ihr Name bzw. ihre Adresse referenziert das erste Byte des Speicherbereichs für den Wert schreibender Zugriff überschreibt (löscht) den bisherigen Wert cin >> summand1; // Angenommen Benutzer gibt 5 ein cin >> summand2; // Angenommen Benutzer gibt 6 ein summe = summand1 + summand2; // Addition und Zuweisung Lesender Zugriff verändert den aktuellen Wert nicht cout << summe; Adresse Name 10124 summand1 10128 summand2 10132 summe 10.04.2013 C++ Grundlagen Wert ? 5 ? 6 11 ? 20 C++ Namenskonventionen FB Informatik Prof. Dr. R.Nitsch Funktions-, Variablen- und andere Namen (Bezeichner) unterliegen der folgenden Konvention: Ein Bezeichner besteht aus einer Folge von Buchstaben, Ziffern und Unterstrich (_). beginnt stets mit einem Buchstaben oder einem Unterstrich. dürfen nicht mit den vordefinierten C++-Schlüsselwörtern /673/ übereinstimmen (zum Beispiel for, int, main...). kann prinzipiell beliebig lang sein. In den Compilern ist die Länge jedoch begrenzt, zum Beispiel auf 31 oder 255 Zeichen. sollte unbedingt selbsterklärend sein. sollte nicht mit '_' oder '__' beginnen (wird systemintern benutzt) Achtung: C++ unterscheidet zwischen Groß- und Kleinschreibung (ist case-sensitive) Beispiele int int int int 1_summand; summand 1; summand1; summand_1; 10.04.2013 falsch! (Ziffer am Anfang) falsch! (Name enthält Leerzeichen) richtig! AndereMöglichkeit: richtig! C++ Grundlagen 21 Syntaxgraph für Bezeichner FB Informatik Prof. Dr. R.Nitsch Syntaxgraphen erlauben eine sehr kompakte Darstellung der Syntaxregeln. Die Regeln werden eingehalten solange man den Linien in Pfeilrichtung folgt. Dabei stößt man auf ovale oder kreisförmige Felder, sogenannte Terminale. Diese sind elementar, d.h. sie können nicht weiter verfeinert werden. rechteckige Felder, sogenannte Nichtterminale. Diese Syntaxbestandteile bedürfen noch der näheren Beschreibung, z.B auch durch einen Syntaxgraphen oder durchText. Beispiel: Syntaxgraph für Namen Buchstabe _ a 0 Buchstabe b 1 Ziffer : z 2 A 9 _ B : Syntaxgraph für Namen : Syntaxgraph für Buchstabe und Ziffer Z 10.04.2013 C++ Grundlagen 22 C++ Standarddatentypen für Variablen FB Informatik Prof. Dr. R.Nitsch int: summand1: ? int: summand2: 100 int summand1; int summand2 = 100; string name("Maria"); /*alternativ*/ string name="Maria"; string: name: Maria Ganzahl-Variable ohne Anfangswert Ganzahl-Variable mit Anfangswert Zeichenketten-Variable mit Anfangswert C++ ist typsicher, d.h. Variable akzeptieren keine Werte vom falschen Typ: string name = 30; int summand1 = "Maria"; // Fehler: 30 ist kein string // Fehler: "Maria" ist kein int C++ stellt viele Standarddatentypen bereit. Die wichtigsten sind int steps double price char point string name bool is_even = = = = = 30 ; 3.50 ; '.' ; "Maria"; true ; // int für Ganzzahlen // double für Gleitkommazahlen // char für Zeichen // string für Zeichenketten // bool für logische Variable Alternative Syntax int steps(30); double price(3.5); char point(3.50); string name("Maria"); bool is_even(true); Literale: jeder Typ hat seinen eigenen Stil! s. nächste Seite Gleitkommazahlen approximieren das mathematische Konzept reeller Zahlen! 10.04.2013 C++ Grundlagen 23 Literale FB Informatik Prof. Dr. R.Nitsch Literale sind fest in den Quell-Code geschriebene Werte, die nicht geändert werden können. Sie werden meist zur Initialisierung von Variablen verwendet. Man unterscheidet Ganzzahl-Literal Gleitkomma-Literal Zeichen-Literal Zeichenkette-Literal Beispiele für Literale 34 13L 3.5 3.5f 2.3e-01 'A' "Maria" 10.04.2013 Ganzzahl-Literal vom Typ int Ganzzahl-Literal vom Typ long Gleitkomma-Literal vom Typ double Gleitkomma-Literal vom Typ float Gleitkomma-Literal vom Typ float Zeichen-Literal vom Typ char Zeichenkette-Literal vom Typ const char* (wird später behandelt) C++ Grundlagen 24 Typableitung mit auto (C++11) FB Informatik Prof. Dr. R.Nitsch Beim Schlüsselwort auto ermittelt der Compiler den Typ bei der Variablen aus dem Typ des Initialisierungsobjektes (Variable oder Literal)! Beispiele von vorheriger Seite: auto auto auto auto auto steps = 30; price(3.50); point = '.'; is_even = true; name = "Maria"; // Typ int für steps // Typ double für price // Typ char für point // bool für is_even // Achtung: jetzt Typ const char* für name, // weil das Literal genau diesen Typ hat. Wirklich hilfreich ist auto erst bei komplexeren Typen! 10.04.2013 C++ Grundlagen 25 Standard-Datentypen - Ganze Zahlen (Selbststudium) 26.3.2013 FB Informatik Prof. Dr. R.Nitsch C++ kennt short, int, long und long long mit Bits(short) ≤ Bits(int) ≤ Bits(long) ≤ Bits(long long) Der sizeof-Operator liefert die Größe Tatsächliche Anzahl Bits abhängig von Plattform. des benötigten Speichers: Typische Werte cout << sizeof(int) << ' ' short [int] 16 Bits << sizeof(short) << ' ' int 32 Bits (oder 16 Bits) << sizeof(long) << ' ' long [int] 64 Bits (oder 32 Bits) << sizeof(long long) long long [int] 64 Bits << ' ' << endl; Ausgabe: 4 2 4 8 1 Bit reserviert für Vorzeichen Alternativ: unsigned short, unsigned int, unsigned long long kein Vorzeichenbit, dafür doppelter Wertebereich Wertebereiche mit Vorzeichenbit: 16 Bits -215…215-1 = -32 768 bis 32 767 -2 147 483 648 bis 2 147 483 647 32 Bits -231…231-1 = 64 Bits -263…263-1 = –9 223 372 036 854 775 808 bis 9 223 372 036 854 775 807 Wertebereiche ohne Vorzeichenbit: 16 Bits 0 bis 216-1 = 0 bis 65 535 32 Bits 0 bis 232-1 = 0 bis 4 294 967 295 64 Bits 0 bis 264-1 = 0 bis to 18 446 744 073 709 551 615 Aktuelle Werte in Datei <climits>; z.B. INT_MIN, INT_MAX, UINT_MAX, … 10.04.2013 C++ Grundlagen 26 Ganzzahlen - Probleme mit der Ungenauigkeit (Selbststudium) FB Informatik Prof. Dr. R.Nitsch Es gibt unendlich viele Ganzzahlen. Aber: Für die C++-Ganzzahltypen steht nur eine begrenzte Wertemenge zur Verfügung (z.B. int 32Bit -> 232 Werte < ∞ ) short int a=100, b=1000, c; // Falsche Ausgabe -31072 c = a * b; // statt 100 000! cout << c; Grund: Ergebnis > 32767 Überlauf (overflow) Abhilfe: "Größerer" Datentyp Wird durch Compiler nicht gemeldet! int a=100, b=1000; c = a * b; cout << c; // Richtige Ausgabe 100000! aber Nicht sinnvoll: int a=10000, b=1000000; "Sicherheitshalber" immer c = a * b; größten Datentyp wählen! cout << c; // Falsche Ausgabe 1 410 065 408 mehr Speicherplatz // statt 10 000 000 000! mehr Rechenzeit Problem grundsätzlich nicht lösbar! 10.04.2013 C++ Grundlagen 27 Reelle Zahlen - Probleme mit der Ungenauigkeit /49/ FB Informatik Prof. Dr. R.Nitsch Numerische Auslöschung: Die Differenz float f1 = 1e8f, f2; zweier fast gleich großer Werte wird 0, f2 = f1 + 4.0f; weil sich die signifikanten Ziffern cout << f2–f1 << endl; Ausgabe: aufheben. Überlauf (overflow) bei Division durch zu kleine Werte FLT_MAX: 3.402823466e+38F Unterschreitung (underflow), wenn Ergebnis zu klein ist. FLT_MIN: 1.175494351e-38F Ergebnisse können von der Reihenfolge der Berechnungen abhängen Achtung Bei sicherheitskritischen Berechnungen immer auf Genauigkeit achten. 10.04.2013 0 f2 = 1e23f / 1e-16f cout << f2 << endl; Ausgabe: 1.#INF f2 = 1e-23f/1e23f cout << f2 << endl; Ausgabe: 0 float k = 7.654321e-7, e = 1.0f,s1,s2; Ausgabe: s1 = k+e; 7.15256e-007 s1 = s1-e; // =k+e-e 7.65432e-007 s2 = k+e-e; cout << s1 << endl << s2 << endl; C++ Grundlagen 28 Operatoren (unvollständig) Zuweisung Addition Verkettung Subtraktion Multiplikation Division Modulo (Rest) Inkrement um 1 Dekrement um 1 Inkrement um n Anhängen Dekrement um n Multiplizieren und zuweisen Dividieren und zuweisen Modulo und zuweisen Von cin in x einlesen Von x nach cout schreiben Gleich Nicht gleich Größer als Größer als oder gleich Kleiner als Kleiner als oder gleich 10.04.2013 FB Informatik Prof. Dr. R.Nitsch bool = char = + + int = + double = + * / % ++ -+=n * / string = + + ++ -+=n += cin>>x cout<<x == != > >= < <= -=n -=n *= *= /= /= %= cin>>x cin>>x cin>>x cout<<x cout<<x cout<<x == == == != != != > > > >= >= >= < < < <= <= <= C++ Grundlagen cin>>x cout<<x == != > >= < <= 29 Einfache Datentypen und Operatoren (Selbststudium) FB Informatik Prof. Dr. R.Nitsch Ganzzahlen und ihre Operatoren /44-48/ Gleitkommazahlen und ihre Operatoren /48-52/ Zeichen und ihre Operatoren /53-56/ logischer Datentyp bool und seine Operatoren /56/ 10.04.2013 C++ Grundlagen 30 Übungsaufgabe: Rechteckfläche berechnen FB Informatik Prof. Dr. R.Nitsch Implementieren Sie ein Programm RectangleArea.cpp, das den Benutzer Länge und Breite eines Rechtecks eingeben lässt und das daraus die Fläche berechnet und auf dem Monitor ausgibt. Hinweis: Benutzen Sie summe.cpp als Ausgangspunkt und passen Sie den Code an. // Datei: summe.cpp #include <iostream> using namespace std; int main() { // Addition zweier Zahlen int summe; int summand1; long summand2; cout << "Gib 2 Zahlen ein: "; // Prompt cin >> summand1; cin >> summand2; summe = summand1 + summand2; cout << "Summe= " << summe; return 0; } 10.04.2013 C++ Grundlagen 32 Implizite Typumwandlung ("casting") in den größeren Typ 5/2.0 und 5.5/2 sind ohne expliziten cast immer Gleitkommadivisionen. Begründung: C++ macht bei gemischten Ausdrücken automatisch einen Cast in den jeweils größeren Typ (s. Hierarchie der Typen). Beispiele: 5 + intlong Hierarchie der Typen long double double 2L long 5 / 2 2 int int long 5 / 2.0 2.5 intdouble double long long 'a'>'A' // Ergebnis: true weil 'a' 97 und 'A' 65 (ASCII) 2*( 'a'>'A' ) boolint 1 2 int i; i = '5' - '0'; // Ergebnis: 2 float double int Ganzzahldivision int 2* FB Informatik Prof. Dr. R.Nitsch long int true 1 false 0 Aufzählungen char short bool // Ergebnis: 5 (Anwendung: Umwandlung von Ziffer in Zahl) charint charint 53 – 48 5 10.04.2013 (Differenz der ASCII-Codes) C++ Grundlagen Explizite Typkonvertierung 33 Implizites Casten in kleineren Typ bei Zuweisung implizit in kleineren Typ bei Zuweisungen int i; float x = 2e9f; i = x; int float i = 3e9; int // Compiler-Warnung: Verkürzung // von float in int !=0 true ==0 false int bool 3 true Hierarchie der Typen long double double // 3e9 ist zu groß für int, Ergebnis undefiniert bool b; b = 3; FB Informatik Prof. Dr. R.Nitsch float long long long int char short bool 10.04.2013 C++ Grundlagen Explizite Typkonvertierung 34 Ausgabe-Formatierung mit Escape Sequenzen /54/ FB Informatik Prof. Dr. R.Nitsch cout << "Ei Guude wie\n"; Escape Zeichen '\' kündigt Steuerzeichen für Ausgabe an. \n positioniert Cursor am Anfang der nächsten Zeile (newline) \t bewegt Cursor zum nächsten Tabstop \r Cursor zum Zeilenanfang ohne Zeilenvorschub \a erzeugt Hinweiston \\ gibt backslash '\' aus \" gibt Anführungszeichen aus … es gibt noch mehr cout << "Diese Zeichenkette enthaelt \"Anfuehrungsstriche\"." erzeugt diese Ausgabe auf Bildschirm: 10.04.2013 Diese Zeichenkette enthaelt "Anfuehrungsstriche". C++ Grundlagen 35 Formatierte Ausgabe mit Manipulatoren /373-376/ (Selbststudium) FB Informatik Prof. Dr. R.Nitsch Der Operator << wandelt automatisch die internen Datenformate in eine Textdarstellung um und gibt diese formatiert auf dem Bildschirm aus. Die Formatsteuerung übernehmen Flags (Schalter) des Objekts cout. Ein Flag ist ein Merkmal, das entweder vorhanden ist ( Flag ist gesetzt) oder nicht vorhanden ist ( Flag ist nicht gesetzt) . Die voreingestellten Formatierungsflags (linksbündig, Feldweite 0, +-Zeichen unterdrückt, 10er Zahlenbasis) können angepasst werden, indem sog. Manipulatoren in den Ein-/Ausgabestrom eingefügt werden (z.B. << hex). Beispiele zur Formatierung von Ganzzahlen cout cout cout cout cout cout << << << << << << showpos << 166 <<endl; noshowpos << 166 endl; hex << 166 << endl; uppercase << 166 << endl; 166 << endl; nouppercase << dec << 166 << endl; 10.04.2013 // Ausgabe // Ausgabe // Ausgabe // Ausgabe // Ausgabe // Ausgabe C++ Grundlagen +166 166 a6 A6 A6 Wirkung persistent (=anhaltend) 166 Formatierte Ausgabe von Gleitpunkzahlen 36 Formatierte Ausgabe mit Manipulatoren (Selbststudium) FB Informatik Prof. Dr. R.Nitsch Beispiele zur Formatierung von Gleitkommazahlen cout cout cout cout cout cout cout cout cout cout cout cout cout << << << << << << << << << << << << << 4./3 << endl; 3./2 << endl; setprecision(3); 4./3 << endl; 3./2 << endl; 4./2 << endl; showpoint ; 4./2 << endl; 3./2 << endl; noshowpoint; 3./2 << endl; 333. << endl; 3333. << endl; cout << fixed; cout cout cout cout cout cout cout cout << << << << << << << << 4./3 << endl; 3./2 << endl; 6.1234567e17 << scientific; 4./3 << endl; 3./2 << endl; defaultfloat; 4./3 << endl; 10.04.2013 // Ausgabe 1.33333 (Voreingestellte Genauigkeit: 6 Stellen) // Ausgabe 1.5 (Überflüssige Nullen unterdrückt) // Genauigkeit 3 Ziffern (#include <iomanip>) // Ausgabe 1.33 (Beachte: Keine 3 Nachkommastellen) // Ausgabe 1.5 (Überflüssige Nullen unterdrückt) // Ausgabe 2 // Dezimalpunkt mit abschließenden Nullen erzwingen // Ausgabe 2.00 // Ausgabe 1.50 // Ausgabe 1.5 // Anzeige 333 // Anzeige 3.33e+003 (Stellenzahl zu groß -> autom. Exponentialschreibweise) // Dieses "Autom. mixed Format" ist Standardeinstellung // Nie Ausgabe in Exponentialschreibweise. // Eingestellte Genauigkeit bestimmt die Zahl der Nachpunktstellen // Ausgabe 1.333 // Ausgabe 1.500 endl; // Ausgabe 612345670000000000.000 // Immer Ausgabe in Exponentialschreibweise // Ausgabe 1.333e+000 // Ausgabe 1.500e+000 // wieder autom. mixed Format (C++11) // Ausgabe 1.33 (Beachte: Keine 3 Nachkommastellen) C++ Grundlagen 37 Steuerung der Feldbreite, Ausrichtung und Füllzeichen Formatierte Ausgabe mit Manipulatoren (Selbststudium) FB Informatik Prof. Dr. R.Nitsch Beispiele für die Steuerung der Feldbreite, Ausrichtung und Füllzeichen cout << 166 << endl; cout << 1 << setw(5) << 166 << endl; cout << 1 << 166 << endl; cout << left << 1 << setw(5) << 166 << endl; cout << setfill('*') << setw(5) << 166 << endl; cout << right << setw(5) << 166 << endl; cout << internal << setfill('0') << showpos << setw(5) << 166 << endl; // Ausgabe 166 // Setzt Feldbreite einmalig (nicht anhaltend) auf 5 // Ausgabe 1 166 (Voreinstellung: rechtsbündig) // Ausgabe 1166 Jetzt wieder Feldbreite 0 (Standard) cout << right; // Rückkehr zur Voreinstellung hebt internal auf cout << setw(5) << 166 << endl; cout << setfill(' ') << setw(5) << 166 << endl; // Ausgabe 0+166 // wieder voreingestelltes Füllzeichen // Ausgabe +166 10.04.2013 // Ausgabe 1166 (linksbündig) // '*' als Füllzeichen setzen (Voreinstellung: ' ') // Ausgabe 166** // wieder rechtsbündig // Ausgabe **166 // setzt Vorzeichen linksbündig und Wert rechtsbündig // Ausgabe +0166 C++ Grundlagen Formatierte Eingabe von Zahlen 38 Eingabe und Typ 5.4.2013 FB Informatik Prof. Dr. R.Nitsch Eigenschaften des Eingabeoperators >> Die Eingabeoperation cin>> ("get from cin") ist typbewusst, d.h. sie liest die Eingabe so vom Eingabepuffer, wie der Typ es verlangt. R1: Führende Zwischenraumzeichen (ZRZ; engl. whitespace) werden ignoriert. Zwischenraumzeichen sind Leerzeichen ' ', Tabulatorzeichen '\t', Zeilensprung '\v', Seitenvorschub '\f' und Zeilenendekennung '\n'. Andere Zeichen werden entsprechend dem Ziel-Datentyp interpretiert. R2: Die Entnahme von Zeichen endet R2a: mit dem ersten ZRZ (ZRZ = Endekennung der Eingabe = Normalfall) bzw. R2b: mit dem ersten nicht zum Typ "passenden" Zeichen int s1=0,s2=0,sum; while(true) { std::cin >> s1 >> s2; sum=s1+s2; } Eingabe s1 int: s1: 0 s2: 0 s2 sum Kommentar 12\n 1 2 3 R1, R2a s1=1; R1, R2as2=2; "\n" im Puffer (fehlerfreie Eingabe) 34.0\n 3 4 7 R1, R2a s1=3; R1, R2bs2=4; ".0\n" im Puffer 5.56\n 5.56\n 3 4 7 R2b da noch ".0\n" im Puffer ( cin reset: cin.clear; cin.sync();) 5 4 7 R1, R2b s1=5; ".56\n" im Puffer; R2bs2 unverändert; ".56\n" im Puffer 10.04.2013 C++ Grundlagen 39 Fehler beim Einlesen FB Informatik Prof. Dr. R.Nitsch Das Objekt cin merkt sich besondere Vorkommnisse beim Einlesen. Das "Gedächtnis" von cin kann wie folgt ausgelesen werden: cin.good() cin.fail() cin.bad() cin.eof() Keine besonderen Vorkommnisse true false false false Nicht erwartetes Zeichen gefunden false true false false Dateiende oder Eingabe ctrl-z false true false true Angegebene Resource nicht verfügbar false false true false Das cin-Gedächtnis kann mit cin.clear() gelöscht werden. Nach fehlerhaften Eingaben verbleiben oft noch störende Eingabereste im Eingabepuffer. Diese werden entfernt durch die Anweisung cin.sync() Nach fehlerhaften Eingaben, die nur die Programmlogik entdeckt (z.B. "out of range"), kann dieses Ereignis mit der Anweisung cin.setstate(ios::failbit); ins Gedächtnis von cin geschrieben werden. Danach liefert eine Gedächtnisabfrage dasselbe Ergebnis wie oben bei "Nicht erwartetes Zeichen gefunden" 10.04.2013 C++ Grundlagen 40 Der Bedingungsoperator ?: /68/ FB Informatik Prof. Dr. R.Nitsch Ist der einzige Operator mit 3 Operanden ( ternärer Operator) Wählt einen von 2 Ausdrücken abhängig von der Bedingung Syntaxdiagramm: Bedingung ? Ausdruck1 : Ausdruck2 ; Falls die Bedingung zutrifft, ist der Wert des gesamten Ausdrucks der Wert von Ausdruck1, ansonsten der Wert von Ausdruck2 Beispiele: int zahl1 = -3, zahl2 = 5, min, max, betrag; min = zahl1 > zahl2 ? zahl2 : zahl1; // Ergebnis: min(zahl1,zahl2) max = zahl1 > zahl2 ? zahl1 : zahl2; // Ergebnis: max(zahl1,zahl2) betrag = zahl1 >= 0 ? zahl1 : -zahl1; // Ergebnis: abs(zahl1,zahl2) 10.04.2013 C++ Grundlagen Zuweisung 41 Konstanten FB Informatik Prof. Dr. R.Nitsch Konstanten sind Objekte, die bei der Definition sofort initialisiert werden müssen und danach nicht mehr geändert werden können (read-only Variablen). Beispiele: const const const const const int TAGE_PRO_WOCHE = 7; string GEBURTSTAG = "12. August 2011"; double PI = 3.14159; Point origin; origin.x=0; origin.y=0; … // FALSCH Point CORNER = { 2, 3, Color::RED }; // RICHTIG: Initialisierungsliste Besonderheiten: const-Variablen müssen bei der Definition initialisiert werden Beispiel: const double PI; // FALSCH: Muss initialisiert werden können danach nicht mehr geändert werden Beispiele: PI = 3.14; // geht nicht -> Syntaxfehler ++CORNER.x; // FALSCH: nur lesender Zugriff erlaubt! haben in der Regel Namen, die ausschließlich aus Großbuchstaben gebildet sind (Konvention) 10.04.2013 C++ Grundlagen 42 C++ Standardtyp vector FB Informatik Prof. Dr. R.Nitsch Im Alltag beschäftigen wir uns oft mit Tabellen: Bundesliga-, Gehalts-, Kalorien-, Noten-, Entfernungstabelle, Kontoauszug, Tilgungsplan, Kassenbon ... Der C++ Datentyp vector ist ein Container für eine Sequenz von Elementen beliebigen aber gleichen Typs. Homogener Datentyp vector<int> v(6,0); // 6 Elemente vom Typ int, alle mit Wert 0 initialisiert cout << v.size() << endl; // Ausgabe: 6 size() v: 6 v's Elements v[0] v[1] v[2] v[3] v[4] v[5] 0 0 0 0 0 0 vector<double> vd(1000, -3.5); // 1000 Elem. vomTyp double, alle mit -3.5 initialisiert size() v: 1000 v's Elements v[0] v[1] v[2] v[3] … v[999] -3.5 -3.5 -3.5 … … -3.5 vector<string> personal(5,""); // 5 Elemente vom Typ string, alle mit "" initialisiert 10.04.2013 C++ Grundlagen 44 FB Informatik Prof. Dr. R.Nitsch Auf die Elemente wird über eine Positionsangabe (Index) zugegriffen, d.h. das 1. Element hat Index 0, das Zweite Index 1 usw. v[0]=5; v[1]=7; v[2]=2; v[3]=8; v[4]=7; v[5]=3; personal[0]="Kai"; personal[1]="Leon" personal[2]="Ina"; personal[3]="Thea"; v[5]="Bernd"; personal[4]=007; int index i; cin >> index; v[index] =42; 10.04.2013 size() v: 6 v[0] v[1] v[2] v[3] v[4] v[5] 5 7 2 8 7 3 v's Elements // Compilezeitfehler: Ein vector akzeptiert nur den vereinbarten Typ // Laufzeitfehler: Zugriff auf nicht existierendes Element // Eingabe: 20000 C++ Grundlagen 45 Initialisierungsliste (C++11) FB Informatik Prof. Dr. R.Nitsch Mit einer Initialisierungsliste können die Elemente individuelle Anfangswerte zugeteilt bekommen: // C++11 vectors std::vector<char> cpp11vector1 = {'A', 'B'}; std::vector<double> cpp11vector2 = {32.0, 6.003, -0.1}; std::vector<string> cpp11vector5 = {"Hergenroether", "Altenbernd", "Lange", "Nitsch"}; // or... std::vector<char> cpp11vector3{'A', 'B'}; std::vector<double> cpp11vector4{32.0, 6.003, -0.1}; std::vector<string> cpp11vector5{"Hergenroether", "Altenbernd", "Lange", "Nitsch"}; Ist noch nicht in Visual C++ 2012 implementiert! Einen Überblick über bereits implementierte C++11-Features findet man hier: http://msdn.microsoft.com/de-de/library/vstudio/hh567368.aspx 10.04.2013 C++ Grundlagen 46 Zeichenketten: Der C++ Standardtyp string FB Informatik Prof. Dr. R.Nitsch Die C++ Standard Template Library (STL) stellt den Datentyp string zum komfortablen Umgang mit Zeichenketten bereit. Wie heissen Sie? Merkel // Anwendung des Datentyps string ------------------------------#include <iostream> Hallo Merkel #include <string> Ihr Name ist 6 Zeichen lang! using namespace std; ------------------------------int main() { // 4 string-Objekte definieren Bildschirmausgabe string prompt("Wie heissen Sie? "); // mit Initialisierung string name; // leerer String string line(30, '-'); // String aus 30 '-' string greeting( "Hallo " ); cout << prompt; cin >> name; // Einzelnes Wort von Tastatur nach name einlesen greeting = greeting + name; // Strings verketten cout << line << endl // Linie ausgeben und Für den Datentyp string sind u.a. << greeting << endl; // Gruss ausgeben folgende Operatoren definiert: cout << "Ihr Name ist " + += (Verkettung) << name.length() // Anzahl Zeichen im String < <= > >= == != (Vergleiche) << " Zeichen lang!" << endl; = (Zuweisung) cout << line << endl; << (Ausgabe) return 0; } (10.04.2013) Einfache Ein- und Ausgabe 49 C++ Standardtyp string FB Informatik Prof. Dr. R.Nitsch string-Variable können noch mehr: std::string name = "lori"; name = 'G' + name; // Verkettung zu "Glori" char c = 'a'; name = name + c; // Verkettung zu "Gloria" c = name[0]; // Lesender Zugriff mit Index-Operator []: c hat Wert 'G' c = 'F'; name[0] = c; // Schreibender Zugriff mit Operator []: jetzt name="Floria" name[6] = 'n'; // Fehler: Index-Operator [] kann nur auf bereits // vorhandene Elemente zugreifen name = name + 'n'; // so geht's: "Florian" // Umwandlung eines Wertes in seine Darstellung als Zeichenkette (C++11) std::string text = std::to_string(2*7*3) + " ist keine Primzahl!"; cout << text << '\n'; // Ausgabe: 42 ist keine Primzahl! Was sonst noch geht ist hier beschrieben: www.cplusplus.com 10.04.2013 C++ Grundlagen 50 Benutzerdefinierte Datentypen: Struktur /89/ FB Informatik Prof. Dr. R.Nitsch Häufig möchte man logisch zusammengehörige Daten zusammenfassen, die nicht vom selben Typ sind, z.B. die Personendaten Name (string), Alter (int), Gewicht (float) oder die Daten eines Punktes auf dem Monitor: seine x und y Koordinaten, seine Farbe und ggf. ob er sichtbar ist. Für diesen Zweck stellt C++ die Struktur als benutzerdefinierten Typ bereit Eine Struktur kann beliebig viele Elemente (auch Felder oder Komponenten genannt) beliebigen Typs enthalten. Syntaxdiagramm einer struct-Definition: struct Typname Beispiel: Struktur Punkt { Elemente } Variablenliste ; Anwendung der Struktur 'Point' // Def. von p, Initialisierung mit Initialisierungsliste Point p={1,2,1}; struct Point { // Lesender Zugriff auf Elemente von p int x; cout<<p.x<<' '<<p.y<<' '<<p.color; int y; // Elemente ändern (schreibender Zugriff) short color; // 1=rot, 2=grün, 3=gelb p.x = 5; p.y = 10;p.color=3; }; Punktoperator "." (Wählt Elemente aus) 51 10.04.2013 C++ Grundlagen Deklaration der Struktur 'Point' Benutzerdefinierte Datentypen: enum classes (C++11) /80/ FB Informatik Prof. Dr. R.Nitsch bieten Unterstützung bei nicht-numerischen Wertebereichen sind typsicher ("strongly typed") Beispiele: Klassische Lösung Nachteile: int color; // rot =0, grün =1, gelb =2 int wochentag; // Sonntag=0, Montag =1, usw. Syntaxdiagramm einer enum-Deklaration enum class Typname { •Kommentar notwendig •nicht eindeutig: 0=rot oder 0=Sonntag •schlechte Lesbarkeit: if(farbe==2) … •Fehleranfällig: if(farbe==5)//Nicht definiert Werteliste } Variablenliste ; Anwendung: =0 =1 =2 // Werden intern wie int-Objekte gespeichert enum class Color { ROT, GELB, GRUEN }; // Typdeklaration Color color = Color::ROT; // Definition und Initialisierung einer Variablen enum class Day { SONNTAG, MONTAG, DIENSTAG, MITTWOCH, DONNERSTAG, FREITAG, SAMSTAG } heute, gestern; heute = Day::MONTAG; gestern = Day::SONNTAG; // Definition mit Initialisierung enum class Coin { CENT=1, FUENFER=5, GROSCHEN=10 }; // Abweichende Bewertungen int i = static_cast<int>(Coin::GROSCHEN); // i=10 Coin money = static_cast<Coin>(10); // money=Coin::GROSCHEN money = 10; // ERROR wegen Typkonflikt 10.04.2013 C++ Grundlagen 52 Ausdruck FB Informatik Prof. Dr. R.Nitsch Ein Ausdruck besteht aus einem oder mehreren Operanden, die mit einander durch Operatoren verknüpft sind. Die Auswertung eines Ausdrucks resultiert in einem Wert, der an die Stelle des Ausdrucks tritt. 10.04.2013 C++ Grundlagen 53 Regeln zum Bilden von Ausdrücken /41/ /59/ FB Informatik Prof. Dr. R.Nitsch a + b * c Punkt vor Strichrechnung (a + b) * c Klammern werden zuerst ausgewertet (von innen nach aussen) Auswertung von links nach rechts (linksassoziativ) a + b + c a * b * c Beispiel: mit Klammern: z = 2 * 3 % 4 + 6 / 2 - 5 1. z = 2. z = 2 + 6 / 2 - 5 3. z = 2 + 4. z = 5. z = 6. z = 0 10.04.2013 6 z = ((((2*3) % 4) + (6/2)) – 5) % 4 + 6 / 2 - 5 5 3 - 5 - 5 0 Ergebnis 0 in z speichern C++ Grundlagen Implizite Typkonvertierung 54 Vorrangtabelle für C++-Operatoren /862/ 9.4.2013 Priorität Operator 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Assoziativität :: . -> [ ] ++ ("Postfix") -- ("Prefix") typeid() dynamic_cast<> static_cast<> const_cast<> reinterpret_cast<> sizeof f() (Fkt-Aufruf) ! ~ + ("unär") - ("unär") ++ ("Präfix") -- ("Präfix") & ("Adresse") * ("Verweis") new delete .* ->* * / % + ("binär") - ("binär") << >> < > <= >= == != & ("bitweises UND") ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= throw , 10.04.2013 FB Informatik Prof. Dr. R.Nitsch C++ Grundlagen von links von rechts von links von links von links von links von links von links von links von links von links von links von links von rechts von rechts von rechts von links 55 Gültigkeits- und Sichtbarkeitsbereich von Variablen FB Informatik Prof. Dr. R.Nitsch Bisher: Variablen sind gekennzeichnet durch Name (name), Typ (type), Wert (value) und Adresse. Neu: Zusätzlich sind Variable charakterisiert durch ihren Gültigkeitsbereich ihren Sichtbarkeitsbereich Gültigkeitsbereich (GB) einer Variablen ist der Programmtextblock, in dem für die Variable ein Speicherplatz reserviert ist. Der Sichtbarkeitsbereich (SB) einer Variablen ist der Programmtextblock, in dem eine Variable über ihren Namen gelesen oder geändert werden kann. 10.04.2013 C++ Grundlagen 56 Regeln zur Gültigkeit und Sichtbarkeit von Variablen FB Informatik Prof. Dr. R.Nitsch R1: Variable, die außerhalb von Blöcken definiert sind, bezeichnet man als externe oder globale Variablen. Sie gehören zur Speicherklasse "Statisch". Ihr Sichtbarkeitsbereich ist die Datei. Ihr Gültigkeitsbereich ist das gesamte Programm, das oft aus mehreren Dateien besteht. R2: Innerhalb eines Anweisungsblocks ({…}) definierte Variablen werden automatische oder lokale Variable genannt. Sie gehören zur Speicherklasse "Automatisch". Ihr Gültigkeitsbereich beginnt nach der Deklaration und endet mit dem Block, in dem sie eingebettet sind. R3: Anweisungsblöcke können verschachtelt werden ({…{…}…}). Variablennamen sind auch gültig und sichtbar in eingeschachtelten Blöcken (Sub-Blöcke). R4: Die Sichtbarkeit (visibility) einer Variablen (global oder lokal) wird eingeschränkt, wenn in einem Block bzw. Sub-Block eine Variable gleichen Namens definiert wird. Im Sichtbarkeitsbereich der inneren Variablen ist die äußere Variable unsichtbar (d.h. sie kann nicht mehr über ihren Namen angesprochen werden) bleibt aber immer noch gültig (d.h. ihr Speicherplatz ist noch reserviert und enthält den aktuellen Wert; siehe R3). 10.04.2013 C++ Grundlagen 57 Gültigkeits- und Sichtbarkeitsbereich von Namen Beispiel #include <iostream> using namespace std; int a=3, b=10; int gib_a() { return a;} int gib_c() { return c; } int main () { cout << a << endl; int a = 10; cout << a << endl; cout << ::a << endl; FB Informatik Prof. Dr. R.Nitsch // externe (globale) Variable (R1: SB=Datei, GB=Programm) // Fehler: c nicht definiert // hier beginnt ein Anweisungsblock // Ausgabe 3; globales a (R3) auto gibt explizit die Speicherklasse "Automatisch" an! // lokales a; // Ausgabe 10; lokales a (R4) // Ausgabe 3; globales a // Gültigkeitsbereich-Auswahloperator { // Subblock beginnt (R3) auto int b = 20; // lokales b sichtbar; globales b gültig, aber unsichtbar (R4) // lokales c; int c = 30; cout << b << c << ::b << endl; // Ausgabe 20 30 10 } // hier endet Gültigkeitsbereich von lok. b und c // Ausgabe 10; globales b wieder sichtbar cout << b << endl; cout << c << endl; // Fehler: c nicht mehr gültig (R2) cout << a << endl; // Ausgabe 10; lokales a wieder sichtbar (R4) // Ausgabe 3; globales a cout << ::a << endl; return 0; } // lokales a wird unsichtbar und ungültig 10.04.2013 C++ Grundlagen 59 namespace std /61/ FB Informatik Prof. Dr. R.Nitsch C++ ermöglicht die Schaffung eigener Sichtbarkeitsbereiche mit Namen (sogenannte Namensräume oder namespaces) Namensbereiche spielen bei der Benutzung verschiedener Libraries eine Rolle So sind alle Bestandteile der C++-Standardbibliothek im Namensraum std definiert. Will man Elemente eines Namensraumes benutzen, muss man "qualifizierte Namen" (solche mit vorangestelltem Bezeichner des Namensraums) verwenden, um das Element sichtbar zu machen. std::cout << name << ", " << age << std::endl; float y = std::sin(x); Alternativ kann man dem Compiler mit using-Deklarationen mitteilen "Mit cout meine ich immer std::cout und mit sin immer std::sin" using std::cout; using std::endl; using std::sin; cout << name << ", " << age << endl; float y = sin(x); Eine noch weitergehende Alternative ist eine using directive. Sie sagt dem Compiler: "Findest Du einen Namen nicht im aktuellen Sichtbarkeitsbereich, dann suche ihn im Namensraum std" using namespace std; cout << name << ", " << age << endl; float y = sin(x); 10.04.2013 C++ Grundlagen Wichtig: Anweisung using namespace std; nie in Header-Dateien verwenden. 60