Studiengang Elektrotechnik / Informationstechnik Skript Programmierung in C/C++ Teil 1 Sommersemester 2006 Dipl.-Phys. Michael Bauer Fachhochschule Pforzheim Programmierung in C/C++ Empfohlene Literatur: C-Programmierung lernen, André Willms, Addison-Wesley http://www.addison-wesley.de/katalog/item.asp?bnm=3827314054 C++-Programmierung, André Willms, Addison-Wesley http://www.addison-wesley.de/katalog/item.asp?bnm=3827311527 C++-Programmierung lernen, André Willms, Addison-Wesley http://www.addison-wesley.de/katalog/item.asp?bnm=3827313422 C/C++-Workshop, André Willms, Addison-Wesley http://www.addison-wesley.de/katalog/item.asp?bnm=3827312906 Objektorientiertes Programmieren, Claussen, Springer-Verlag http://www.springer.de/cgi-bin/search_book.pl?isbn=3-540-55748-2 C++ echt einfach, Oliver Böhm, Franzis http://www.franzis.de/_private/suche/std_result.asp Empfohlene Tools (alternativ): Borland C++ Builder 3 Standard http://www.borland.de/bcppbuilder/index.html Borland C++ Compiler 5.5 http://www.borland.com/bcppbuilder/freecompiler/ Microsoft Visual C++ 6.0 http://www.microsoft.com/germany/ Empfohlene Web-Seite http://community.borland.com/cpp/0,1419,2,00.html SS 2006 Programmierung in C/C++ SS 2006 Inhalt 1 Grundlagen der Programmiersprachen C und C++ (Teil1) ......................................................4 1.1 1.1.1 1.1.2 1.1.3 1.1.4 Die erste Win32-Konsolenanwendung mit einfacher Ein- und Ausgabe am Bildschirm ......... 4 Kommentare ................................................................................................................................................. 7 Ausdruck und Anweisung............................................................................................................................. 7 Einfache Ein- und Ausgaben am Bildschirm ................................................................................................ 8 Header-Dateien ............................................................................................................................................. 9 1.2 Datentypen ..................................................................................................................................... 11 1.3 Variablen ........................................................................................................................................ 12 1.4 Rechenoperatoren.......................................................................................................................... 13 1.5 Funktionen ..................................................................................................................................... 14 1.6 Eingabe und Ausgabe von Daten ................................................................................................. 18 1.6.1 1.6.2 Escape Sequenzen....................................................................................................................................... 18 Formatierte Eingabe und Ausgabe.............................................................................................................. 19 Programmierung in C/C++ SS 2006 1 Grundlagen der Programmiersprachen C und C++ (Teil1) Die Programmiersprache C bildete die Basis für C++, eine Programmiersprache die häufig auch als »C mit Klassen« bezeichnet wird. In heutigen C++-Programmen ist die Verwandtschaft zu C noch deutlich zu erkennen. C++ wurde nicht geschrieben, um C zu ersetzen, sondern um sie zu verbessern. Sind Sie bereits mit der C-Syntax vertraut, dann sollten Sie das folgende Kapitel als „warm-up“ verstehen und nutzen. Für Neueinsteiger in die C/C++-Programmierung stellt das folgende Kapitel eine Art Crash-Kurs für C bzw. C++ dar. Zur Unterstützung und Beschleunigung Ihrer Lernkurve empfehlen wir das Durcharbeiten des Buches „C-Programmierung lernen, André Willms, Addison-Wesley“. Die wichtigsten C-Syntaxelemente werden dort ausführlich beschrieben und von zahlreichen Programmbeispielen unterstützt. Wir empfehlen das Experimentieren mit den im Buch angegebenen Programmen und die Bearbeitung der Übungsaufgaben. 1.1 Die erste Win32-Konsolenanwendung mit einfacher Ein- und Ausgabe am Bildschirm In den nächsten Kapiteln werden Ihnen die Grundkenntnisse von C++ vermittelt. Nebenher werden Sie zum besseren Verständnis einige einfache Testprogramme schreiben. Diese Testprogramme werden am besten als Konsolenanwendungen erstellt, die in der Ausführung stark an die alten DOS-Programme erinnern. Es gibt jedoch einige wesentliche Unterschiede zwischen Win32-Konsolenanwendungen und DOS-Programmen, doch das soll Sie im Moment nicht bekümmern. Jetzt wollen wir zuerst ohne weitere Umschweife das Programm Hello World! als Win32-Konsolenanwendung erstellen. Eine Win32-Konsolenanwendung ist ein 32-Bit-Programm, das unter Windows 95 oder Windows NT in einem DOS-Fenster läuft. In unserem Beispiel erstellen wir das erste C++-Programm mit Microsoft Visual C++ 6.0. Sie können dies jedoch auch mit beliebig anderen C++-Tools erstellen. Nun wollen wir aus der Entwicklungsumgebung (IDE) heraus ein Konsolenprogramm erstellen. Rufen Sie Visual C++ auf. Falls nach dem Programmstart irgendwelche Quelldateien angezeigt werden oder bereits ein Arbeitsbereich geöffnet sein sollte, schließen Sie diese. Legen Sie einen Arbeitsbereich und ein Projekt an. Rufen Sie dazu den Befehl DATEI/NEU auf, und lassen Sie die Seite Projekte entsprechend Abbildung 1 anzeigen. Geben Sie einen NAMEN für das Projekt ein und wählen Sie ein im Feld PFAD übergeordnetes Verzeichnis für das Projekt aus. Visual C++ wird unter diesem Verzeichnis ein Unterverzeichnis für das Projekt anlegen, das den gleichen Namen wie das Projekt trägt. Anhand der per Voreinstellung ausgewählten Option NEUEN ARBEITSBEREICH ERSTELLEN können Sie erkennen, daß Visual C++ selbst dafür Sorge trägt, daß das neue Projekt einem Arbeitsbereich zugeordnet wird. Zur Einrichtung eines Projekts gehört auch die Angabe eines Projekttyps. Über den Projekttyp teilen wir dem Compiler mit, welche Art von Programm aus dem Projekt erstellt werden soll. Da wir eine Konsolenanwendung erstellen wollen, wählen wir aus der Liste im linken Bereich der Projektseite den Projekttyp WIN32-KONSOLENANWENDUNG aus. Drücken Sie zuletzt auf OK. Dipl.-Phys. Michael Bauer, Hochschule Pforzheim 4 Programmierung in C/C++ SS 2006 Abbildung 1 Anlegen eines neuen Projekts für WIN32-Konsolanwendungen Es erscheint ein Dialogfeld, in dem Sie auswählen können, wie weit Ihr Projekt von Visual C++ schon vorab konfiguriert und mit Code ausgestattet werden soll. Erliegen Sie nicht der Versuchung, die Option HALLO WELT-ANWENDUNG auszuwählen, sondern verzichten Sie auf jegliche weitere Unterstützung durch die IDE, und wählen Sie die Option EIN LEERES PROJEKT aus. Drücken Sie FERTIGSTELLEN. Es erscheint noch ein abschließendes Kontrollfenster, das Sie mit OK abschicken. Nehmen Sie eine Quelltextdatei in das Projekt auf. Ein leeres Projekt nutzt uns nicht viel; wir brauchen eine Textdatei, in die wir unseren Quelltext eingeben können. Um eine solche Quelltextdatei in Ihr Projekt aufzunehmen, rufen Sie den Menübefehl PROJEKT/DEM PROJEKT HINZUFÜGEN/NEU auf. Es erscheint folgendes Dialogfeld (siehe Abbildung 2): Dipl-Phys. Michael Bauer, Hochschule Pforzheim 5 Programmierung in C/C++ SS 2006 Abbildung 2 Hinzufügen einer Quelltextdatei zu einem Projekt Auf der Seite DATEIEN, geben Sie einen Namen für die hinzuzufügende Datei ein und wählen Sie als Dateityp C++-QUELLCODEDATEI aus der Liste aus. Klicken Sie auf OK. Nun können wir damit beginnen den Quellcode einzugeben. Bitte geben Sie entsprechend Abbildung 3 den Quellcode ein. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 6 Programmierung in C/C++ SS 2006 Abbildung 3 Programm Hello World 1.1.1 Kommentare Aber zuerst möchte ich Sie auf die Zeilen aufmerksam machen, die mit // beginnen. Dies sind Kommentarzeilen, die in diesem Programm dazu dienen, den Programmcode optisch zu gliedern. Normalerweise verwenden Sie Kommentarzeilen, um Ihr Programm zu dokumentieren. Beachten Sie, daß die einzige Anweisung in diesem Quelltext mit einem Semikolon endet. In C++Programmen werden alle Anweisungen mit Semikolon abgeschlossen. 1.1.2 Ausdruck und Anweisung Beim Erlernen der Programmiersprachen C bzw. C++ muß in der Software-Entwicklung schon sehr früh zwischen einem Ausdruck und einer Anweisung unterscheiden können. Die »offizielle« Definition einer Anweisung lautet: »ein Ausdruck, gefolgt von einem Semikolon«. Das Semikolon schließt einen Ausdruck ab und macht daraus quasi einen einzeiligen Quelltextblock. Bevor ich näher auf den Quelltextblock eingehe, sollten Sie wissen, daß ein Ausdruck eine Codeeinheit ist, die zu einem bestimmten Wert ausgewertet werden kann, während eine Anweisung einen abgeschlossenen Ausdruck darstellt. Betrachten wir uns die folgende Anweisung: ¾ c = a + b; In diesem Beispiel ist der Teil rechts des Gleichheitszeichens, a + b, ein Ausdruck. Die gesamte Zeile jedoch ist eine Anweisung. Im Moment reicht es zu wissen, daß eine Anweisung von einem Semikolon gefolgt wird und ein geschlossener Ausdruck ist. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 7 Programmierung in C/C++ SS 2006 Auffällig sind auch die geschweiften Klammern in dem Programm. In C++ beginnt ein Codeblock mit einer öffnenden ({) und endet mit einer schließenden geschweiften Klammer (}). Diese Klammern dienen dazu, den Beginn und das Ende der Codeblöcke von Schleifen, Funktionen, ifAnweisungen etc. zu markieren. In unserem Programm gibt es nur einen Satz Klammern, da es sich um ein sehr einfaches Programm handelt. 1.1.3 Einfache Ein- und Ausgaben am Bildschirm Um »Hello World!« auf dem Bildschirm anzeigen zu können, benötigen wir eine C++-Klasse namens iostream. Eine kurze Beschreibung dieser Klasse wäre also angebracht. Sie wissen zwar noch nicht, was Klassen sind, doch sollte Sie das nicht bekümmern. Die Klasse iostream verwendet streams (Ströme), um grundlegende Ein-/Ausgabeoperationen durchzuführen – beispielsweise die Ausgabe von Text auf dem Bildschirm oder das Einlesen der Benutzereingabe. Über den coutStrom werden Daten an den Standardausgabestrom gesendet. Für Konsolenanwendungen ist dies die Konsole oder der Bildschirm. Über den cin-Strom werden Daten von der Konsole, beispielsweise Benutzereingaben, eingelesen. Die Klasse iostream verwendet zwei spezielle Operatoren, um Informationen in einen Strom zu schreiben oder aus dem Strom zu lesen. Der Übergabeoperator (<<) wird verwendet, um Daten in einen Ausgabestrom zu leiten und der Übernahmeoperator (>>) dient dazu, Daten aus einem Eingabestrom herauszuziehen. Um also Informationen auf der Konsole auszugeben, würden Sie folgendes eingeben: cout << "Tue etwas!"; Damit teilen Sie dem Programm mit, den Text Tue etwas! in den Standardausgabestrom einzufügen. Wenn die Programmzeile ausgeführt wird, erscheint der Text auf Ihrem Bildschirm. cout wird nur in Konsolenanwendungen eingesetzt. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 8 Programmierung in C/C++ SS 2006 1.1.4 Header-Dateien Bevor Sie cout einsetzen können, müssen Sie dem Compiler mitteilen, wo die Beschreibung (Deklaration genannt) der iostream-Klasse zu finden ist. Die Klasse iostream ist in der Datei IOSTREAM.H deklariert. Diese Datei wird auch Header-Datei genannt. Um dem Compiler mitzuteilen, daß er in IOSTREAM.H nach der Klassendeklaration von iostream suchen muß, benutzen Sie die #include-Direktive: #include <iostream.h> Eine Deklaration ist ein Codeabschnitt, der eine Funktion oder eine Klasse beschreibt. Die Definition ist der eigentliche Code für die Funktion oder Klasse. In C und C++ ist die Unterscheidung zwischen diesen beiden Begriffen sehr wichtig. Allgemein gilt, daß eine Deklaration in einer Header-Datei und eine Definition in einer Quellcodedatei abgelegt wird. Jetzt ist der Compiler in der Lage, die Deklaration für die iostream-Klasse zu finden, und er weiß, was er machen muß, wenn er auf die cout-Anweisung stößt. Wenn Sie vergessen haben, für eine Klasse oder Funktion die dazugehörige Header-Datei in Ihr Programm mit aufzunehmen, ernten Sie einen Compiler-Fehler. Die Fehlermeldung des Compiler könnte beispielsweise lauten: Undefined symbol 'cout' . Wenn Sie diese Meldung erhalten, sollten Sie umgehend überprüfen, ob Sie alle für Ihr Programm benötigten Header mit aufgenommen haben. Sie können herausfinden, in welcher Header-Datei sich die Deklaration einer Funktion oder Klasse befindet, indem Sie auf den Funktions- oder Klassennamen klicken und die Funktionstaste F1 drücken. Dadurch wird die Windows-Hilfe gestartet, und das Hilfe-Thema zu dem Element, auf dem der Zeiger steht, wird angezeigt. Oben bei dem Hilfe-Thema befindet sich ein Verweis auf die Header-Datei, in der die Funktion oder Klasse deklariert ist. Auf eine Sache möchte ich noch näher eingehen, bevor wir mit dem Aufsetzen der Konsolenanwendung Hello World! beginnen. Die iostream-Klasse enthält spezielle Manipulatoren, mit denen die Behandlung der Ströme gesteuert werden kann. Der einzige Manipulator, mit dem wir uns im Moment befassen wollen, ist endl (end line), der dazu benutzt wird, eine neue Zeile in den Ausgabestrom ein zufügen. Wir verwenden endl, um eine neue Zeile einzufügen, nachdem wir den Text auf dem Bildschirm ausgegeben haben. Bitte beachten Sie, daß das letzte Zeichen von endl ein l und keine 1 ist. Nachdem wir uns nun mit der Klasse iostream vertraut gemacht haben, können wir darangehen, Hello World! als Konsolenanwendung aufzusetzen. Bearbeiten Sie nun Programm 1. // Hello World.CPP // Michael Bauer // 12.10.2001 #include <iostream.h> int main() { cout<<"Hello World!"<<endl; return 0; } Programm 1: Hello World.CPP In C++ werden Whitespace-Zeichen einfach ignoriert. Meistens ist es völlig unerheblich, wo Sie Leerzeichen oder neue Zeilen einfügen. Natürlich können Sie Leerzeichen nicht innerhalb von Schlüsselwörtern oder Variablennamen verwenden, aber ansonsten sind Sie nicht gebunden. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 9 Programmierung in C/C++ SS 2006 So sind die folgenden Quelltexte beispielsweise vollkommen äquivalent: int main() { cout<<"Hello World!"<<endl; return 0; } entspricht int main(){cout<<"Hello World!"<<endl; return 0;} Programm 2: Äquivalente Quelltexte Niemand wird leugnen, daß die erste Version wesentlich besser zu lesen ist und deshalb bevorzugt werden sollte. Welchen Programmierstil Sie sich letztendlich aneignen, bleibt Ihnen überlassen. Wenn Sie sich mit den Konventionen in diesem Buch vertraut machen, werden Sie bei der Erstellung größerer Anwendungen keine Schwierigkeiten haben. Klicken Sie jetzt in der Mauspalette auf die Schaltfläche mit dem roten !. Das Programm wird kompiliert und ausgeführt. Bei Ausführung des Programms springt ein DOS-Fenster auf und die Worte Hello World! erscheinen . Die Meldung <<Press any key to continue>> wird von der Visual C++ Entwicklungsumgebung hinzugefügt. Sie ist nicht Teil unserer Anwendung, sondern ist ein Service der Visual C++-IDE, der verhindert, daß das Konsolenfenster gleich wieder verschwindet. Wir starten deshalb unser Programm nicht aus der IDE sondern durch einen Doppelklick auf die Anwendung (Hello World.exe). Wahrscheinlich haben Sie die Anwendung nur für den Bruchteil einer Sekunde gesehen, bevor sie wieder verschwunden ist. Dies liegt daran, daß am Ende der main()-Funktion das Programm beendet und das Konsolenfenster direkt geschlossen wird. Wir können dies beheben, indem wir ein paar Zeilen in unser Programm aufnehmen, die verhindern, daß das Konsolenfenster geschlossen wird, bevor wir damit fertig sind. Die C-Bibliothek stellt uns dazu die Funktion getch() zur Verfügung, die auf eine Eingabe über die Tastatur wartet. Mit dieser Funktion werden wir verhindern, daß das Konsolenfenster geschlossen wird. Dazu müssen Sie zuerst Ihr Programm im Editorfenster überarbeiten, bis es dem Programm 3 entspricht. // Hello World 2.CPP // Michael Bauer // 12.10.2001 #include <iostream.h> #include <conio.h> int main() { cout<<"Hallo Ihr C++ Freaks!"; cout<<endl; getch(); //Eingabe über Tastatur return 0; } Programm 3: Hello World 2.CPP Jetzt läuft die Anwendung fehlerfrei, Hallo Ihr C++ Freaks! wird angezeigt und das Konsolenfenster bleibt geöffnet. Um das Programm abzubrechen und das Konsolenfenster zu schließen, können Sie jede beliebige Taste auf der Tastatur drücken. Ich möchte Ihr Augenmerk darauf richten, wie Visual C++ Konsolenanwendungen sichert. Wenn Sie das Projekt speichern, legt Visual C++ zwei Dateien an: eine Projektdatei mit der Extension .DSP, die alle Informationen enthält, die von Visual C++ zum Aufbau des Projekts benötigt werden, Dipl-Phys. Michael Bauer, Hochschule Pforzheim 10 Programmierung in C/C++ SS 2006 sowie eine Quelltextdatei mit der Extension .CPP, die den eigentlichen Programmcode enthält. Wenn Sie zum Beispiel das Projekt unter dem Namen Hello World abspeichern, werden auf Ihrer Festplatte zwei Dateien angelegt: Hello World.DSP und Hello World.CPP. Um das Projekt erneut anzuzeigen, öffnen Sie Hello World.dsp, aber im Fenster des Quelltexteditors wird Hello World.CPP erscheinen. Dies mag Sie zuerst etwas verwirren, aber nach einiger Zeit und etwas Übung, werden Sie sich daran gewöhnen. Visual C++ legt im Projektordner zusätzlich einen Unterordner mit der Bezeichnung Debug an. In diesem Ordner findet man die zu unserem Programm gehörende Anwendung mit der Extension .EXE. Nun haben Sie Ihr wahrscheinlich erstes C++-Programm mit Erfolg realisiert – mein Glückwunsch ! 1.2 Datentypen In C/C++ bestimmt ein Datentyp die Art, in der der Compiler die Informationen im Speicher ablegt. Die folgenden Tabelle enthält die Größen und die sich daraus ergebenden Bereiche für die grundlegenden Datentypen Typ unsigned char Größe (Bits) 8 char 8 short int 16 unsigned int int 32 32 unsigned long long 32 32 float 32 double 64 long double 80 bool 8 Zahlenbereich Beispielanwendungen 0 <= x <= 255 Kleine Zahlen und kompletter PC-Zeichensatz - 128 <= x <= 127 Sehr kleine Zahlen und ASCII-Zeichensatz, z.B. char zeichen = 'A'; - 32 768 <= x <= 32 767 Zähler, kleine Zahlen, Schleifensteuerung 0 <= x <= 4 294 967 295 Große Zahlen und Schleifen -2 147 483 648 <= x <= 2 147 483 Zähler, kleine Zahlen, 647 Schleifensteuerung 0 <= x <= 4 294 967 295 Astronomische Distanzen -2 147 483 648 <= x <= 2 147 483 Sehr große Zahlen, 647 statistische Grundgesamtheiten 1,18 10^-38 <= x <= 3,40 10^38 Wissenschaftlich, 7-stellige Genauigkeit 2,23 10^-308 <= x Wissenschaftlich, 15-stellige <=1.79 10^308 Genauigkeit 3,37 10^-4932 <= x <= Finanzrechnung, 18-stellige 1.18 10^4932 Genauigkeit „true“ (1) oder „false“ (0) Wahrheitswert abfragen Einige Datentypen gibt es als signed und unsigned. Ein signed-Datentyp umfaßt sowohl negative als auch positive Zahlen, während ein unsigned-Datentyp nur positive Zahlen enthält. Sie werden sich vielleicht fragen, warum es in C/C++ zwei gleiche Datentypen mit unterschiedlichen Namen gibt ? Dies ist ein Relikt aus alten Tagen. In 16-Bit-Programmierumgebungen belegt der Typ int einen Speicherplatz von 2 Byte und der Datentyp long 4 Byte. In einer 32-Bit-Programmierumgebung jedoch belegen beide 4 Byte Speicherplatz und verfügen über den gleichen Wertebereich. Da mit Dipl-Phys. Michael Bauer, Hochschule Pforzheim 11 Programmierung in C/C++ SS 2006 dem C++Builder nur 32-Bit-Programme erzeugt werden können, sind in diesem Fall int und long identisch. Nur die Datentypen double, long double und float akzeptieren Fließkommazahlen (Zahlen mit Dezimalstellen). Die anderen Datentypen arbeiten ausschließlich mit Integerwerten (ganzzahlig). Es ist zwar zulässig, einem Integer-Datentyp einen Wert mit Bruchanteil zuzuweisen, doch wird dann der Dezimalanteil nach dem Komma übergangen und nur der ganzzahlige Anteil zugewiesen. Beispiel: ¾ int x = 3.75; Der Variablen x wird der Wert 3 zugewiesen. Achtung: In C++-Programmen schreibt man Gleitkommazahlen mit Punkt und nicht mit Komma ! 1.3 Variablen Eine Variable ist ein bestimmter Bereich im Computerspeicher, der für die Aufnahme eines Werts freigehalten wird. Variablendeklaration Variablennamen können mit einem Unterstrich beginnen. In der Regel ist es jedoch keine gute Idee, einen Variablennamen mit einem Unterstrich zu beginnen, da viele Compiler besondere Variablen- und Funktionsnamen ebenfalls mit einem oder einem doppelten Unterstrich am Anfang kennzeichnen. Die maximale Länge eines Variablennamens ist von Compiler zu Compiler unterschiedlich. Soweit Sie im Rahmen von 31 Zeichen oder weniger bleiben, werden Sie keine Probleme bekommen. C/C++ unterscheidet bei Variablennamen zwischen Groß- und Kleinschreibung. Bei den folgenden Beispielen handelt es sich um zwei verschiedene Variablen: int Brutto; int BRUTTO; In C++ müssen Sie den Variablentyp (= Datentyp der Variablen) deklarieren, bevor Sie die Variable festlegen können. Der Variablentyp sagt aus, was in der Variablen abgelegt werden kann (z.B Text, Fließkommazahlen,..) Es wird zuerst der Datentyp angegeben, danach der Name der Variablen. Im folgenden sehen Sie einige Beispiele für gültige Variablennamen: ¾ ¾ ¾ ¾ ¾ int aVeryLongVariableName; int my_variable; int _x; int X; int Label2; // ein langer Variablenname // eine Variable mit einem Unterstrich // OK, aber nicht zu empfehlen // Variablenname in Großbuchstaben // ein Variablenname mit einer Zahl Die Festlegung des Variablentyps ermöglicht dem Compiler, eine Typenüberprüfung durchzuführen und sicherzustellen, daß alles korrekt ist, wenn das Programm ausgeführt wird. Die Verwendung eines falschen Datentyps löst einen Compiler-Fehler oder eine Fehlermeldung aus. Durch die Analyse und Korrektur dieser Fehler können Probleme behoben werden, bevor sie sich nachteilig auswirken. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 12 Programmierung in C/C++ SS 2006 Variableninitialisierung Mit der Initialisierung bekommt die Variable einen Wert zugewiesen. Eine Variable kann gleich bei ihrer Deklaration initialisiert werden. So ist beides zulässig: int Kontostand_Bank1; Kontostand_Bank1=100; oder int Kontostand_Bank2=150; Variablen, die deklariert, aber nicht initialisiert werden, enthalten Zufallswerte. Da der Speicher, auf den die Variable zeigt, nicht initialisiert wurde, kann auch nicht genau gesagt werden, was dieser Speicherplatz enthält. Beispiel: int x; int y; x = y + 10; //ACHTUNG! In obigem Beispiel kann die Variable x jeden beliebigen Wert enthalten, da y vor seiner Verwendung nicht initialisiert wurde. 1.4 Rechenoperatoren Operatoren dienen zur Manipulation von Daten. Mit Operatoren werden Berechnungen durchgeführt, Ausdrücke auf Gleichheit geprüft, Zuweisungen vorgenommen, Variablen manipuliert und noch etliche weitere Aufgaben erledigt. Übersicht über die wichtigsten Rechenoperatoren in C++ Tabelle 1: C++-Operatoren (C-Operatoren außer Klassenoperatoren) Operator Beschreibung ¾ Mathematische Operatoren + Addition Subtraktion • Multiplikation / Division ¾ Zuweisungsoperatoren = Zuweisung += Zuweisen und addieren -= Zuweisen und subtrahieren *= Zuweisen und multiplizieren \= Zuweisen und dividieren &= Zuweisen, Bit-weises AND |= Zuweisen, Bit-weises OR ¾ Logische Operatoren && Logisches AND || Logisches OR ¾ Gleichheitsoperatoren == Gleich != Nicht gleich < Kleiner als Dipl-Phys. Michael Bauer, Hochschule Pforzheim Beispiel x = y + z; x = y – z; x = y * z; x = y / z; x = 20; x += 20; (wie x = x + 20;) x -= 20; x *= 20; x \= 20; x &= 0x03; x |= 0x03; if (x && 0xFF) {...} if (x || 0xFF) {...} if (x == 20) {...} if (x != 20) {...} if (x < 20) {...} 13 Programmierung in C/C++ SS 2006 > Größer als <= Kleiner oder gleich >= Größer oder gleich ¾ Unäre Operatoren * Dereferenzierungsoperator & Referenzierungsoperator ~ Bit-weises NOT ! Logisches NOT ++ Inkrementoperator -Dekrementoperator ¾ Klassen- und Strukturoperatoren :: Gültigkeitsbereichoperator -> Indirekter Auswahloperator . Direkter Auswahloperator if (x > 20) {...} if (x <= 20) {...} if (x >= 20) {...} int x = *y; int* x = &y; x &= ~0x03; if (!gueltig) {...} x++; (entspricht x = x + 1;) x--; MeineKlasse::Funktion(); MeineKlasse ->Funktion(); MeineKlasse.Funktion Der Präinkrementoperator (++x) teilt dem Compiler mit, den Wert der Variable zu inkrementieren und dann erst weiterzuverwenden, während beim Postinkrementoperator (x++) die Variable zuerst verwendet und dann der Wert erhöht werden soll. Der Dekrementoperator (--) arbeitet analog. Aufgabe: Bestimmen Sie die Werte folgender Ausgabeanweisungen (Programm 7.CPP) int x = 10; cout << "x = " << x++ << endl; cout << "x = " << x << endl; cout << "x = " << ++x << endl; cout << "x = " x << endl; 1.5 Funktionen Funktionen sind Programmabschnitte, die getrennt vom Hauptprogramm stehen. Diese werden aufgerufen (ausgeführt), wenn sie in einem Programm für die Durchführung bestimmter Aktionen benötigt werden. Sie könnten zum Beispiel eine Funktion haben, die zwei Werte übernimmt, mit diesen eine komplexe mathematische Berechnung durchführt und dann das Ergebnis zurückliefert. Oder Sie brauchen vielleicht eine Funktion, die einen String aufnimmt, ihn parst und dann einen Teil des geparsten String zurückliefert. Funktionen sind ein wesentlicher Bestandteil einer jeden Programmiersprache, und C/C++ bilden da keine Ausnahme. Der einfachste Typ von Funktionen erfordert keine Parameter und liefert void zurück (das heißt, es wird nichts zurückgeliefert). Andere Funktionen erfordern einen oder mehrere Parameter und können auch einen Wert zurückliefern. Funktionen unterliegen den gleichen Namenskonventionen wie Variablen. Ein Parameter ist ein Wert, der einer Funktion übergeben wird und dazu dient, deren Ablauf zu beeinflussen oder das Ausmaß ihrer Operation anzuzeigen. In Abbildung 4 stellen wir Aufbau und Struktur einer Funktion vor. int funktion (int x, int y) { int z = (x + y); return z } //Datentyp des Rückgabewertes, Funktionsname, Parameterliste //Funktionskörper //Rückgabeanweisung mit Rückgabewert Abbildung 4 Aufbau einer C/C++-Funktion Bevor eine Funktion verwendet werden kann, muß sie erst einmal deklariert werden. Die Funktionsdeklaration (auch Prototyp genannt) teilt dem Compiler mit, wie viele Parameter die Dipl-Phys. Michael Bauer, Hochschule Pforzheim 14 Programmierung in C/C++ SS 2006 Funktion aufnimmt und welche Datentypen die einzelnen Parameter und der Rückgabewert der Funktion haben. Beispiel: #include <iostream.h> #include <conio.h> int multiply(int, int); void showResult(int); int main() { int x, y, result; cout << endl << "Bitte geben Sie den ersten Wert ein: "; cin >> x; cout << " Bitte geben Sie den zweiten Wert ein: "; cin >> y; result = multiply(x, y); showResult(result); getch(); return 0; } int multiply(int x, int y) { return x * y; } void showResult(int result) { cout << "Ergebnis der Multiplikation: " << result << endl; } Programm 8 Funktionen zur Multiplikation Erläuterungen: Dieses Programm fordert den Benutzer auf, zwei Zahlen einzugeben (über den Standardeingabestrom cin), ruft dann die Funktion multiply() auf, um die zwei Zahlen miteinander zu multiplizieren. Dann wird die Funktion showResult() aufgerufen, um das Ergebnis anzuzeigen. Die beiden Prototypen für die Funktionen multiply() und showResult() stehen direkt über dem Hauptprogramm main(). Der Prototyp gibt nur den Typ des Rückgabewerts, den Funktionsnamen und den Datentyp der Funktionsparameter an. Dies ist die Mindestanforderung an die Deklaration einer Funktion. Falls gewünscht, können im Funktionsprototyp auch Variablennamen mit aufgenommen werden, um die Arbeitsweise der Funktion besser zu dokumentieren. Die Funktion multiply() hätte auch wie folgt deklariert werden können: ¾ int multiply(int firstNumber, int secondNumber); In diesem Fall ist es zwar ziemlich offensichtlich, wozu die Funktion multiply() eingesetzt wird, aber es kann nicht schaden, Ihren Code durch Kommentare und durch den Code selbst zu dokumentieren. Die Definition der Funktion multiply() befindet sich außerhalb des Programmbereiches der mainFunktion. Die Funktionsdefinition enthält den eigentlichen Funktionskörper. Im Programm ist der Körper der Funktion minimal, da die Funktion lediglich zwei Funktionsparameter multipliziert und das Ergebnis zurückliefert. Die multiply()-Funktion aus Programm kann auf verschiedene Weisen aufgerufen werden. Sie können Variablen, Konstanten oder sogar die Ergebnisse von anderen Funktionsaufrufen übergeben: Beispiele: ¾ result = multiply(2, 5); ¾ result = multiply(x, y); ¾ showResult(multiply(x,y)); // Konstanten übergeben // Variablen übergeben // Rückgabewert dient als Parameter für eine andere Funktion Dipl-Phys. Michael Bauer, Hochschule Pforzheim 15 Programmierung in C/C++ ¾ multiply(x, y); SS 2006 // Rückgabewert wird ignoriert Funktionen können andere Funktionen aufrufen und sogar sich selbst aufrufen. Man spricht dann von Rekursion. Bei den in diesem Abschnitt vorgestellten Funktionen handelt es sich ausschließlich um alleinstehende Funktionen (alleinstehend insofern, als sie nicht Element einer Klasse sind). Die Anwendung alleinstehender Funktionen in C++ unterscheidet sich in keinster Weise von C, wenn auch in C++ das Leistungsspektrum der Funktionen etwas erweitert wurde. Regeln für Funktionen ¾ Eine Funktion kann keinen oder eine beliebige Anzahl von Parametern übernehmen. ¾ Eine Funktion kann so implementiert werden, daß sie einen Wert zurückliefert. Dies ist aber nicht obligatorisch. ¾ Definiert eine Funktion einen Rückgabewert vom Typ void, kann sie keinen Wert zurückliefern. Wenn Sie versuchen, einen Wert aus einer Funktion mit Rückgabetyp void zurückzuliefern, erhalten Sie einen Compiler-Fehler. Eine Funktion, die void zurückliefert, muß keine returnAnweisung enthalten, kann aber, falls dies gewünscht wird. Zulässig ist beides. Wurde keine return-Anweisung vorgesehen, kehrt die Funktion automatisch zurück, wenn das Ende des Funktionsblocks erreicht ist (die schließende geschweifte Klammer). ¾ Wird im Funktionsprototyp angegeben, daß die Funktion einen Wert zurückliefert, sollte der Funktionskörper eine return-Anweisung enthalten, die einen Wert zurückliefert. Ansonsten gibt der Compiler eine Warnung aus. ¾ Funktionen können eine beliebige Zahl von Parametern aufnehmen, können jedoch nur einen Wert zurückliefern. ¾ Variablen können den Funktionen als Wert, über Zeiger oder über Referenzen übergeben werden. Dipl-Phys. Michael Bauer, Hochschule Pforzheim 16 Programmierung in C/C++ SS 2006 Deklaration einer Funktionsanweisung (Prototyp) : ¾ ret_typ funktions_name(argtyp_1 arg_1, argtyp_2 arg_2, ..., argtyp_n arg_n); Die Funktionsdeklaration identifiziert eine Funktion, die in den Code mit aufgenommen werden soll. Sie gibt den Datentyp des Rückgabewerts (ret_typ) und den Funktionsnamen (funktions_name) an. Darüber hinaus legt sie die Reihenfolge (arg_1, arg_2, ..., arg_n) und Typen (argtyp_1, argtyp_2, ..., argtyp_n) der Datenargumente fest, die die Funktion erwartet. Definition einer Funktionsanweisung: ¾ ret_type function_name(argtype_1 arg_1, argtype_2 arg_2,..., argtype_n arg_n) { Anweisungen; return ret_type; } Die Funktionsdefinition identifiziert den Codeblock (Anweisungen), aus dem die Funktion besteht, und gibt den Datentyp des Rückgabewerts (ret_typ) an. Der funktions_name identifiziert die Funktion. Die Parameter, die der Funktion übergeben werden (arg_1, arg_2, ..., arg_n), und ihre Datentypen (argtype_1, argtype_2, ..., argtype_n) sind ebenfalls in der Definition enthalten. Die main()-Funktion Jedes C/C++-Programm muß über eine main()-Funktion verfügen. Diese Funktion stellt den Einstiegspunkt in das Programm dar. Jedes der bisher präsentierten Beispielprogramme hatte eine solche Funktion. Jedoch definieren nicht alle C++-Programme die traditionelle main()-Funktion. Windows-Programme, die in C oder C++ geschrieben sind, verwenden statt der traditionellen main()-Funktion die Eintrittsfunktion WinMain(). Die Funktion main() ist eine Funktion wie jede andere und hat auch den gleichen Aufbau. Sie haben bereits gesehen, daß Visual C++ für 32-Bit-Konsolenanwendungen eine vordefinierte int main()-Funktion anlegt, die den folgenden Prototyp aufweist: Beispiel: ¾ int main(); Hinweis: GUI-Anwendungen, die mit Visual C++ erzeugt wurden, haben ebenfalls eine WinMain()-Funktion. Visual C++ befreit Sie von allen Sorgen mit den Low-level-Problemen der WindowsProgrammierung, so daß Sie sich voll auf die Erstellung der Benutzerschnittstelle und den Rest des Programms konzentrieren können. Wie Sie bereits gelernt haben, werden den Funktionen die Werte beim Aufruf übergeben. Die main()-Funktion rufen Sie jedoch nicht selbst auf – sie wird automatisch ausgeführt, wenn das Programm startet. Woher erhält die main()-Funktion also ihre Parameter? Die Antwort lautet: aus der Befehlszeile. In den meisten Programmen spielt der Wert, der von main() zurückgeliefert wird, keine Rolle, da er in der Regel nicht weiter verwendet wird. Tatsächlich müssen Sie nicht einmal einen Wert in Ihrer main()-Funktion zurückliefern, denn auch für die main()-Funktion gibt es mehrere Möglichkeiten der Deklaration. So sind alle nachfolgenden Deklarationen gültig: ¾ main(); ¾ int main(); // das gleiche wie oben ¾ int main(void); // das gleiche wie oben ¾ int main(int argc, char** argv); ¾ void main(); ¾ void main(int argc, char** argv); Dipl-Phys. Michael Bauer, Hochschule Pforzheim 17 Programmierung in C/C++ 1.6 SS 2006 Eingabe und Ausgabe von Daten In C++ wird für die Ein-/Ausgabe von Daten eine Klassenbibliothek verwendet, die mit #include <iostream.h> zugeordnet werden muss. Der nächste Abschnitt 1.6.1 behandelt nur die einfachen vordefinierten Datentypen (ganzzahlig, reell und Zeichen) ohne Formatierung. In Abschnitt 1.6.2 werden weitere Möglichkeiten der formatierten Ein-/Ausgabe mit Hilfe von Funktionen und Manipulatoren beschrieben 1.6.1 Escape Sequenzen Zur Ausführung von Steuerfunktionen dienen die in Abbildung 5 zusammengestellten EscapeSequenzen, die mit einem Rückstrich (Backslash) eingeleitet werden. Sie erscheinen als einzelnes Zeichen zwischen Hochkommas oder als Bestandteil eines Textes zwischen Anführungszeichen. Zeichen \a \b \f \n \r \t \v \\ \‘ \‘‘ \xhh hexadezimal 0x07 0x08 0x0C 0x0A 0x0D 0x09 0x0B 0x5B 0x27 0x22 ASCII BEL BS FF LF CR HAT VT \ ‚ “ Wirkung Bell = Hupe = Alarm Backspace = Rücktaste Form Feed = Seitenvorschub (nur Drucker) Line Feed = Zeilenvorschub Carriage Return = Wagenrücklauf Horizontaler Tabulator (Tab-Taste) Vertikaler Tabulator Backslash = Rückstrich Apostroph = Hochkomma Anführungszeichen = Gänsefüße Hexadezimaler Zeichencode hh (ASCII) Abbildung 5 Escape-Sequenzen Formelzeichen des Zeichensatzes, die nicht auf der Tastatur zur Verfügung stehen, lassen sich über die ALT-Taste und die Ziffern des numerischen Tastenblocks als Textzeichen erzeugen oder werden mit hexadezimalen Escape-Sequenzen ausgegeben. Achtung! Plattformabhängig Dipl-Phys. Michael Bauer, Hochschule Pforzheim 18 Programmierung in C/C++ SS 2006 1.6.2 Formatierte Eingabe und Ausgabe Die Arbeit der Ein-/ausgabefunktionen in iostream wird von internen Variablen gesteuert, die mit Standardwerten für die Fließtextausgabe (Abschnitt 1.6.1) vorbesetzt sind und die der Benutzer durch den Aufruf von Funktionen und Manipulatoren einstellen kann. Die in Abbildung 6 zusammengestellten Funktionen liefern einen alten Wert zurück und stellen mit dem als Argument übergebenen Wert die Variablen neu ein. Bei einem Aufruf ohne Argument wird nur der alte Inhalt zurückgegeben. Ergebnis int int char long long long Funktion cout.width(int n) cout.precision(int n) cout.fill(char c) cout.flags(long f) cout.setf(long f) cout.unset(long f) Aufgabe nur folgende Ausgabe n Stellen breit alle reellen Ausgaben mit n Stellen legt Füllzeichen c fest legt Formatvariable (Abb. 7) fest setzt Einzelbits im Format (Abb. 7) löscht Einzelbits im Format (Abb. 7) Abbildung 6 Ausgabe-Formatierungsfunktionen (Auszug) Das folgende Beispiel stellt die Feldweite auf 10 Stellen und die reelle Genauigkeit auf 5 Stellen ein und vereinbart als neues Füllzeichen den Stern. Die Weite von 10 Stellen gilt nur für das erste cout <<x und wird für die beiden folgenden Ausdrücke auf 0 zurückgesetzt. double x = 123.456789; cout.width(10); cout.precision(5); cout.fill('*‘); cout<<x<<“==“<<x; Auf der Ausgabe erscheint: ****123.46==123.46 Abbildung 7 zeigt die in ios vordefinierten Bezeichner, die mit dem Vorsatz ios:: versehen weden müssen. Die standardmäßige Voreinstellung ist 0x2001 hexadezimal Dipl-Phys. Michael Bauer, Hochschule Pforzheim 19 Programmierung in C/C++ Bezeichner ios::skipws ios::left ios::right ios::internal ios::dec ios::oct ios::hex ios::showbase ios::showpoint ios::uppercase ios::showpos ios::scientific ios::fixed ios::unitbuf ios::stdio WS 2001/2002 Muster 0x0001 0x0002 0x0004 0x0008 0x0010 0x0020 0x0040 0x0080 0x0100 0x0200 0x0400 0x0800 0x1000 0x2000 0x4000 Wirkung Whitespace-Zeichen bei der Eingabe übergehen linksbündige Ausgabe rechtsbündige Ausgabe Füllzeichen nach Vorzeichen bzw. Basis dezimales Zahlensystem (immer Voreinstellen) oktales Zahlensystem (nur ganzzahlig) hexadezimales Zahlensystem (nur ganzzahlig) Zahlenbasis mit ausgeben (nur ganzzahlig) reelle Ausgabe immer mit Punkt und allen Stellen hexadezimale Ausgabe mit Großbuchstaben Vorzeichen + bei ganzzahliger Ausgabe reelle Ausgabe in Exponentendarstellung reelle Ausgabe in Festpunktdarstellung alle Streams nach Ausgabe leeren stdout und stderr nach Ausgabe leeren Abbildung 7 Die Formatierungsflags in ios Durch den logischen Operator | lassen sich mehrere Formatierungsflags in einem Funktionsaufruf einstellen. Beispiel zur ganzahligen hexadezimalen Ausgabe: cout.setf(ios::hex | ios::uppercase | ios:showbase); Manipulator dec hex endl setw(long n) setfill(int c) setprecision(int n) setiosflags(long f) resetiosflags(long f) Klasse iomanip iomanip iomanip iomanip iomanip Aufgabe dezimale Ein-/Ausgabe (voreingestellt) hexadezimale Ein-/Ausgabe Zeilenvorschub wie "\n" nur folgende Ausgabe mit n Stellen Füllzeichen c reelle Genauigkeit n Stellen Formatflags (Abb. 7) setzen Formatflags (Abb. 7) löschen Abbildung 8 Manipulatoren in <iomanip.h> (Auszug) Die in Abbildung 8 zusammengestellten Manipulatoren lassen sich wie ein Ausdruck in die Ausgabe mit cout einbauen. Manipulatoren, die Argumente übergeben, benötigen eine Zuordnung mit #include<iomanip.h>. Sie übernehmen Formatierungen, die sich auch mit Funktionen und Flags einstellen lassen. Beispiel für die Weite der folgenden Ausgabe statt cout.width(10): cout<< "\nx = " << setw(10) << x << endl; Man beachte, daß alle Einstellungen mit Ausnahme der Weite (width bzw. setw) so lange gültig sind, bis sie neu gesetzt bzw. zurückgesetzt werden. Die Genauigkeit (precision) bezieht sich bei der unformatierten (voreingestellten) Ausgabe auf die Anzahl aller Stellen, bei der Formatierung mit fixed und scientific nur auf die Nachpunktstellen. Dipl.-Phys. Michael Bauer, Hochschule Pforzheim 20 Programmierung in C/C++ WS 2001/2002 // Programm 9.CPP // Michael Bauer // 18.10.2001 #include <iostream.h> #include <conio.h> #include <iomanip.h> int main() { double x; cout<<"Bitte reelle Zahl x eingeben: x = "; cin>>x; cout.width(10); cout.precision(5); cout.fill('*'); cout<<x<<endl; cout<<"\n\n"; cout.setf(ios::fixed,ios::floatfield); cout.precision(8); cout<<x<<endl; getch(); return 0; } Programm 9 Test der Formatierung Dipl.-Phys. Michael Bauer, Hochschule Pforzheim 21