Einsteig in die Programmierung mit Cpp
Transcrição
Einsteig in die Programmierung mit Cpp
C++ Vorwort Dieses Skript befindet sich noch unter Bearbeitung sowie unter Korrektur. Gruß Konstantin Rink. ©Konstantin Rink 1|Seite C++ Inhalt BEVOR ES LOS GEHT. 4 1.0 WIE AUS EINEM QUELLCODE EIN AUSFÜHRBARES PROGRAMM WIRD 5 2.0 SYNTAXDIAGRAMME 7 2.1 NASSI-SHNEIDERMAN-DIAGRAMM 10 2.1.1 DER LINEARE ABLAUF 2.1.2 KONTROLLSTRUKTUREN(VERZWEIGUNGEN) EINFACHE AUSWAHL (IF-ABFRAGE) MEHRFACH AUSWAHL (IF-ELSE-ABFRAGE) VERSCHACHTELTE AUSWAHL FALLAUSWAHL (WIRD MEIST BEI SWITCH-CASE VERWENDET) 2.1.3 WIEDERHOLUNGEN (SCHLEIFEN) KOPFGESTEUERTE SCHLEIFE FUßGESTEUERTE SCHLEIFE ENDLOSSCHLEIFE SCHLEIFE MIT AUSTRITTSBEDINGUNG AUSSPRUNG (BREAK) 10 10 10 11 11 11 12 12 12 12 12 12 3.0 SOFTWARE EINRICHTEN 14 3.1 ERSTER START 17 4.0 DER ALLGEMEINE AUFBAU EINES C++ PROGRAMMES 18 DER INCLUDE-BEFEHL 19 AUSGABE 20 ZEILENUMBRÜCHE 22 VARIABLEN 23 DER TYP DER NAME DER WERT DEKLARATION UND INITIALISIERUNG VON VARIABLEN GELTUNGSBEREICH VON VARIABLEN 23 24 24 25 25 KONSTANTE 27 ZEIGER/POINTER 28 OPERATOREN 29 ©Konstantin Rink 2|Seite C++ DIE EINGABE IN C++ 31 ABSCHLIEßEND MÖCHTEN WIR UNS NOCH DEN EINGABEWERT, ALSO DEN WERT DER VARIABLE ZAHL AM BILDSCHIRM MITHILFE VON COUT AUSGEBEN LASSEN (Z. 11).KONTROLLSTRUKTUREN 31 KONTROLLSTRUKTUREN 32 DIE WENN DANN (IF/ELSE)-FUNKTION DIE ELSE IF FUNKTION DIE SWITCH AND CASE FUNKTION 32 33 34 MATHEMATISCHE FUNKTIONEN 36 SCHLEIFEN 37 DIE WHILE-SCHLEIFE DIE FOR-SCHLEIFE DIE DO-WHILE-SCHLEIFE EINE SCHLEIFE VORZEITIG ABBRECHEN/PROZEDUR IN EINER SCHLEIFE ÜBERSPRINGEN WANN VERWENDE ICH WELCHE SCHLEIFE? 38 39 40 41 42 EINDIMENSIONALE FELDER (ARRAYS) 43 D EFINITION UND INITIALISIERUNG VON EINDIMENSIONALEN ARRAYS EINLESEN /AUSGEBEN VON EINDIMENSIONALEN ARRAYINHALTEN MIT SCHLEIFEN EINEN BESTIMMTEN WERT VON EINEM ARRAY AUSGEBEN 43 44 46 MEHRDIMENSIONALE ARRAYS 47 EINLESEN /AUSGEBEN VON MEHRDIMENSIONALEN ARRAYINHALTEN MIT SCHLEIFEN EINEN BESTIMMTEN WERT VON EINEM MEHRDIMENSIONALEN ARRAY AUSGEBEN 48 49 BUBBLESORT UND DREIECKSTAUSCH 50 DREIECKSTAUSCH BUBBLESORT 50 52 ARBEITEN MIT ARRAYS 54 LÖSUNGEN 55 FUNKTIONEN 57 RÜCKGABEWERT CALL BY VALUE CALL BY REFERENCE 59 60 62 ©Konstantin Rink 3|Seite C++ Bevor es los geht… Möchte ich Sie über den Aufbau dieses Skripts und wie man am besten damit arbeitet informieren. Wenn man möchte kann man dieses Skript in drei Teile aufteilen, in einen Teil indem Ihnen die theoretischen Methoden der Programmierung näher gebracht werden, in einen Teil in dem Ihnen die Syntax von einzelnen Befehlsfunktionen erklärt werden und in einen Übungsteil indem Sie das Wissen aus den gelernten Befehlsfunktionen und Transferwissen anwenden. Die einzelnen Kapitel sind so erstellt, dass man dieses Skript auch als Nachschlagwerk benutzen kann, sofern man schon erste Erfahrungen mit der Programmiersprache gemacht hat. Andernfalls sollte man die Kapitel in chronologischer Reihenfolge abarbeiten, denn die Kapitel greifen ineinander über und setzten das dementsprechende Wissen aus dem vorherigen Kapitel voraus. ©Konstantin Rink 4|Seite C++ 1.0 Wie aus einem Quellcode ein ausführbares Programm wird In C++ wenn man so möchte, gibt es drei Arten von Dateitypen mit denen wir arbeiten werden. Standartbibliothekdateien: In C++ gibt es die sog. Standardbibliothek, in ihr befinden sich Headerdateien in denen unsere Standartfunktionen deklariert sind. Um diese Headerdateien in unsere Hauptdatei einbinden zu können, verwenden wir den include-Befehl (Kapitel XX). Headerdateien: Neben den Headerdateien in der Standartbibliothek unseres Compilers hat man die Möglichkeit auch eigene Headerdateien zu schreiben um beispielsweise eigene Funktionen zu deklarieren. Normale Quelldateien: In dieser Datei schreiben wir unser eigentliches Programm. Diese Quelldatei bindet mithilfe des include-Befehls die Headerdateien ein und kann so auf die deklarierten Funktionen zugreifen. Um aus unseren Quelldateien bzw. unserem geschriebenen Quelltext ein ausführbares Programm zu machen, werden noch einige Schritte durchlaufen. Zuerst tritt der sogenannte Präprozessor in Kraft, dieser hat zum einen die Aufgabe die Head-Dateien die in den #include-Befehlen der .cpp-Dateien stehen, einzufügen (Abbildung 1). Zum anderen werden noch weitere Aufgaben erfüllt wie Kommentare durch Leerzeichen zu ersetzen. iostream #include #include z.B. math.h #include Präprozessor int main() XYZ.cpp XYZ.cpp Abbildung 1 ©Konstantin Rink 5|Seite C++ Als zweites übernimmt der Compiler, dessen Aufgabe es ist ausschließlich die C++-Quelldateien(an den Headerdateien ist er nicht interessiert, diese sind schon vom Präprozessor inkludiert worden) in Objektdateien zu übersetzen(Abbildung 2). Diese enthalten eine Sprache die schon relativ der Maschinensprache ähnelt. Wird zum Beispiel in der main-Funktion eine Funktion aus der C++-Datei XYZ aufgerufen so steht an dieser Stelle ein Platzhalter für diese Funktion(Abbildung 3). int main() XYZ.cpp XYZ.cpp Compiler Platzhalter XXXXX für Funktion aus anderer Datei .cpp Datei int main(){ … fkt123(); … … … } Abbildung 2 .o Datei main: … jmp XXXXX … … weitere Platzhalter Ersetzen durch Platzhalter Abbildung 3 Im letzten Schritt ist es die Aufgabe des sog. Linkers diese Platzhalter aufzulösen, er verbindet (eng. to link) diese Dateien quasi zusammen(Abbildung 4). Als Endergebnis hat man dann eine ausführbare Datei. Linker Abbildung 4 ©Konstantin Rink 6|Seite C++ 2.0 Syntaxdiagramme Das Syntaxdiagramm ist eine Methode um eine Regelmenge grafisch darzustellen. In einem Beispiel möchten wir eine Regel für eine Zahl aufstellen, welche vorher festgelegte Werte enthalten darf. Jedes Syntaxdiagramm wird von links nach rechts gelesen, aus diesem Grund müssen wir auch keine Pfeilsymbole oder ähnliches verwenden. Als erste Regel möchten wir festlegen, dass die Werte von 1-6 vorkommen dürfen: 1….6 Umgesetzt würde das bedeuten unsere Zahl darf einen Wert von 1-6 annehmen. Zum Beispiel hat unsere Zahl dann den Wert 3. Nun möchten wir, dass die Werte von 1-6 auch mehrfach vorkommen dürfen. 1….6 Jetzt kann unsere Zahl beliebig viele Werte im Bereich von 1 bis 6 annehmen, entweder nur eine Zahl mit einem Durchlauf oder auch 2,3,4,n-stellige Zahlen im Wertebereich von 1-6 da man jetzt die Möglichkeit hat, mehrere Durchläufe zu starten. Im nächsten Schritt möchte ich aus meiner einfachen Zahl gerne eine Gleitkommazahl machen, also benötigte ich ein Komma bzw. im englischen und auch in C++ verwendet man anstatt eines Kommas einen Punkt. Zudem sind wir die ganze Zeit nur von positiven Werten ausgegangen, eine Zahl kann auch ein negatives Vorzeichen haben, aus diesem Grund möchten wir das noch zusätzlich mit realisieren. 1….6 . Jetzt kann unsere Gleitkommazahl negative Werte annehmen oder positive. ©Konstantin Rink 7|Seite C++ Was uns jetzt noch in diesem Beispiel fehlt sind die Nachkommastellen, denn momentan ist es nur möglich vor dem Komma Werte anzunehmen zudem ist es noch nicht möglich Werte wie 0.2 anzunehmen. 1….6 . . 1-6 1-6 Betrachten wir nun das Syntaxdiagramm. Unsere Zahl kann ein negatives Vorzeichen annehmen, beliebig viele Werte zwischen 1 und 6 annehmen und Nachkommastellen haben oder auch keine. Die Zahl kann auch erst mit einem Komma und beliebig vielen Nachkommastellen beginnen. Dies ist selbstverständlich nur eine Schreibweise von vielen, es wäre auch möglich, das gleiche Vorhaben in einem ähnlichen Syntaxdiagramm zu realisieren. Nach diesem Beispiel als Einleitung gewöhnen wir uns ein paar Fachbegriffe für den späteren Gebrauch an. In dem obigen Beispiel haben wir ovale Symbole verwendet, im Syntaxdiagramm nennt man diese auch terminale Symbole. Neben den terminalen Symbolen gibt es auch noch non-terminale/nicht-terminale Symbole. Diese drückt man grafisch mit einem Viereck aus. Um den Unterschied zwischen terminalen und non-terminalen Symbolen aufzuzeigen, hier ein einfaches Beispiel: Farben rot blau gelb „Farben“ ist in diesem Beispiel die Wortgruppe also ein non-terminales Symbol(=es lässt sich weiter unterteilen) und die einzelnen Wörter (rot, blau, gelb) stellen die endgültigen (terminierten) Symbole da, diese lassen sich nicht weiter unterteilen. Unbewusst haben wir im obigen Beispiel schon einige Grammatikregeln angewandt, nun möchten wir diesen auch noch Namen geben. Folgen mehrere non-terminale aufeinander so nennt man dies eine Sequenz. Syntaxdiagramm zu einer Sequenz: A ©Konstantin Rink B C 8|Seite C++ Möchte man eine Auswahl haben ob man A mit B oder mit C verbindet nennt man dies eine Alternative. Syntaxdiagramm zu einer Alternative: B A C Möchte man, dass sich eine oder mehrere non-terminale wiederholen, nennt man dies eine Iteration(zu Deutsch Wiederholung). Diese unterscheidet man noch einmal in eine rückläufige(rekursive) Wiederholung und in eine iterative Wiederholung. Syntaxdiagramm zu einer iterativen Wiederholung: A B Syntaxdiagramm zu einer iterativen rückläufigen Wiederholung: A B A In dem Fall einer iterativen rückläufigen Wiederholung ist es wie man sieht möglich, das A den Wert B annehmen kann oder nicht. Möchten wir aber, dass es diese Möglichkeit nicht gibt und nach dem A den Wert B annimmt wiederholend den Wert A annimmt dann sprechen wir von einer (normalen) Rekursion. Syntaxdiagramm zu einer Rekursion: A B A Wie man hier nun erkennen kann, nimmt A erst die Werte von B mit an und danach nochmals/wiederholend von A. ©Konstantin Rink 9|Seite C++ 2.1 Nassi-Shneiderman-Diagramm Bevor wir ein Programm schreiben, müssen wir uns überlegen, welche Funktionen unser Programm haben bzw. ausführen soll. Da evtl. wir nicht direkt mit der Programmierung später beschäftigt sein werden, bzw. mehrere Personen an diesem Projekt arbeiten, bräuchten wir also eine Art Norm die uns hilft anderen Personen die Vorgehensweise unseres Programmes näher zu bringen. Eine Möglichkeit ist ein Struktogramm. Mithilfe des Nassi-Shneiderman-Diagramms setzen wir die Vorgehensweise grafisch und ohne eine Programmiersprache zu verwenden um. Der Vorteil ist, dass mithilfe dieses Struktogrammes unser Programm von Dritten verstanden werden kann, ohne dass diese eine Programmiersprache beherrschen müssen. Ein weiterer Vorteil ist, dadurch dass keine Programmiersprache in diesem Struktogramm verwendet wird, können Programmierer unser Programm auch in anderen Programmiersprachen z.B. in Java umsetzen. Dieses Kapitel greift jetzt vorab auf Funktionen zurück die in C++ existieren, aus diesem Grund würde ich Sie bitten, dieses Kapitel als Nachschlagwerk zu verwenden. Wenn Sie später an einem Kapitel angekommen sind, z.B. bei Kontrollstrukturen können Sie die gewünschte grafische Vorgehensweiße nachschlagen. 2.1.1Der lineare Ablauf Anweisungen(z.B. Initialisierung von Variablen) werden in sog. rechteckige Strukturblöcke geschrieben. Dabei ist zu beachten, dass diese Blöcke nicht neben sondern immer untereinander geschrieben werden. Das Struktogramm wird immer von Oben nach Unten gelesen. Anweisung 1 Initialisierung Funktionsaufruf 2.1.2 Kontrollstrukturen(Verzweigungen) Einfache Auswahl (If-Abfrage) Bedingung Trifft zu Anweisung 1 ©Konstantin Rink Trifft nicht zu Trifft die oben festgelegte Bedingung zu (true) wird Anweisung 1 ausgeführt, ist dies nicht der Fall (false) wird nichts ausgeführt. 10 | S e i t e C++ Mehrfach Auswahl (If-Else-Abfrage) Bedingung true false Anweisung 1 Anweisung 2 Trifft die oben festgelegte Bedingung zu (true) wird Anweisung 1 ausgeführt, ist dies nicht der Fall (false) wird Anweisung 2 ausgeführt. Verschachtelte Auswahl Es kann vorkommen, dass wenn beispielsweiße eine Bedingung false sein sollte, eine weitere Auswahl ausgeführt werden soll anstatt einer Anweisung. Bedingung true false Bedingung Anweisung 1 true Anweisung2 false Anweisung3 Trifft die oben festgelegte Bedingung zu (true) wird Anweisung 1 ausgeführt, ist dies nicht der Fall (false) wird eine weitere Bedingung geprüft, trifft diese zu (true) wird Anweisung2 ausgeführt, trifft diese nicht zu (false) wird Anweisung3 ausgeführt. Fallauswahl (wird meist bei Switch-Case verwendet) Variable Bedingung1 Bedingung2 Anweisung1 Anweisung2 Bedingung3 Anweisung3 Bedingung n Anweisung n ansonsten Alternat. Anweisung Eine Variable wird auf verschiedene Bedingungen geprüft, trifft eine dieser Bedingungen zu, wird eine Anweisung ausgeführt, optional kann man auch festlegen, wenn keine der Bedingungen zutrifft (ansonsten) wird eine Anweisung ausgeführt. ©Konstantin Rink 11 | S e i t e C++ 2.1.3 Wiederholungen (Schleifen) Kopfgesteuerte Schleife Diese Wiederholung bzw. nennen wir sie Schleife, führt solange die Anweisung aus, bis die Bedingung false ist. Bedingung Anweisung Anweisung Fußgesteuerte Schleife Bei dieser Schleife wird die Bedingung erst nach Ausführung der Anweisung geprüft. Aus diesem Grund wird die Anweisung mindestens einmal ausgeführt ehe die Bedingung false ist. Anweisung Bedingung Endlosschleife Endlosschleife, das sollte Ihnen nicht passieren, es sei denn es ist explizit von Ihnen gewünscht. Anweisung Schleife mit Austrittsbedingung Bedingung Anweisung Bedingung True false Diese Schleife hat eine Austrittsbedingung, ist die Austrittsbedingung true wird die Schleife beendet, ansonsten werden die Anweisungen weiter ausgeführt. Anweisung Aussprung (break) ©Konstantin Rink Falls Sie sich einen Punkt weiter oben gefragt haben, was dieses Objekt hier bedeutet, hier die Antwort: Es wird verwendet um den Aussprung (break;) zu realisieren. 12 | S e i t e C++ Abschließend möchte ich an einem Beispiel die Umsetzung eines Nassi-Shneidermann-Diagrammes in einen C++ Quellcode zeigen. Die Bezeichnung der einzelnen Blöcke steht frei, ich empfehle aber überwiegend Pseudocode zu verwenden bzw. klar verständliche Formulierungen. Als Struktogramm Zahl: INTEGER i: INTEGER Daten[5] :INTEGER := 1,2,3,4,5 Eingabeaufforderung :=Zahl Zähle i von 0 bis 5, Erhöhung pro Durchlauf +1 Bedingung True False „Die Zahl ist dabei“ Umgesetzt in C++ ©Konstantin Rink 13 | S e i t e C++ 3.0 Software einrichten Bevor wir nun jetzt zum praktischen Teil dieses Skripts übergehen und beginnen zu programmieren müssen wir vorher noch einen Editor in dem wir C++ schreiben und einen Compiler mit dem wir den Quellcode in eine ausführbare Datei umwandeln installieren. Da sich dieses Skript ausschließlich mit dem Einstieg in die Programmierung beschäftigt ist es nicht zwingend notwendig Programme zu verwenden mit denen man meist größere Projekte realisiert. Aus diesem Grund empfehle und verwende ich das Programm Dev++ da es neben dem Editor einen Compiler integriert hat. Installation Die Installation erfolgt einfach und ist in XX Schritte unterteilt: Schritt 1 Zu Beginn bekommen wir einen Hinweis indem wir gebeten werden andere bereits installierte Versionen dieses Programmes nicht mit der aktuellen Installation zu überschreiben. Wir bestätigen mit einem Klick auf den OK-Button um fortzufahren. Schritt 2 Im nächsten Schritt wählen wir die Sprache Deutsch aus und fahren fort. ©Konstantin Rink 14 | S e i t e C++ Schritt 3 Wir bestätigen das Lizenzabkommen indem wir auf den Annehmen-Button klicken. Schritt 4 In diesem Schritt können wir den Installations-Typ bestimmen. Ich empfehle „Full“ zu selektieren und mit „Weiter“ forzufahren. ©Konstantin Rink 15 | S e i t e C++ Schritt 5 Im letzten Schritt vor der Installation bestimmen wir das Zielverzeichnis unseres Programmes. Mit dem Klick auf „Installieren“ wird die Installation von Dev-C++ durchgeführt. Schritt 6 Nachdem Dev-C++ erfolgreich installiert wurde klickt man auf „Fertig stellen“ um die Installation abzuschließen und den Editor zu starten. ©Konstantin Rink 16 | S e i t e C++ 3.1 Erster Start Bei jedem Start des Programmes werden wir zur Begrüßung mit dem „Tip des Tages“ empfangen. Diese Tipps sind für Anfänger, die sich mit dem Editor näher beschäftigen wollen bzw. Shortcuts und Kniffe erlernen möchten nicht schlecht. Durch einen Klick auf das Kästchen unterhalb der Nachricht kann man diese Begrüßungen jedoch deaktivieren. Durch einen Klick auf den Menüpunkt Datei >Neu>Quelldatei[1] oder durch den Shortcut STRG+N öffnen wir eine neue Quelldatei in der wir unser erstes Programm schreiben können[2]. Zur Sicherheit sollten Sie die Quelldatei speichern indem Sie entweder im Menü auf Datei>Speichern unter gehen oder kurz STRG+S auf Ihrer Tastatur drücken. Abb. 1 ©Konstantin Rink Abb. 2 17 | S e i t e C++ 4.0 Der Allgemeine Aufbau eines C++ Programmes Bevor ich Ihnen nun erkläre wie wir in unserem Editor eine Quelldatei kompilieren kommen wir nun zum allgemeinen Aufbau eines Programmes bzw. einer Quelldatei in C++. Bevor wir die einzelnen Begrifflichkeiten und Ausdrücke klären, vorne weg hier ein Quellcodeauszug zu dem Standardaufbau. Auf den ersten Blick mag der Quellcode etwas kryptisch und unverständlich aussehen, jedoch ist ein sehr logisches und festes System dahinter. Jeder Quellcode beginnt mit einem Einfügen/Inkludieren einer Datei. (Z. 1) Dies geschieht mit dem include-Befehl, die genaue Syntax von diesem Befehl wird in einem Kapitel weiter erklärt. Dieser Befehl fügt, wie man sieht, eine Datei namens iostream ein. In dieser Datei sind Funktionen (wie z.B. Kontrollstrukturen, Schleifen, etc.) definiert die wir später beim Programmieren benötigen. Aus diesem Grund ist es wichtig, dass diese Datei als erstes in jedem unserer Quellcodes inkludiert wird. Der nächste Befehl der uns ins Auge sticht ist in Zeile 2 „using namespace std;“ Dieser Befehl wird uns das Programmieren etwas schöner gestalten. Um auf eine Funktion zuzugreifen, sei es z.B. der Befehl für die Bildschirmausgabe, macht man dies über ihren namespace, zu Deutsch Namensraum. Im Kapitel mit der Bildschirmausgabe und unserem ersten „Hallo Welt“, werde ich noch einmal darauf zurück kommen und anhand eines Beispiels zeigen was genau der Vorteil ist. Nun haben wir quasi den Kopf unseres Quellcodes besprochen und kommen nun zur Hauptfunktion, der main()-Funktion. Diese Funktion ist der Einstiegspunkt unseres Programmes, das bedeutet, dass wenn wir später mit anderen Funktionen außerhalb der main()-Funktion arbeiten, die Befehle die später in unserer main()-Funktion stehen immer als erstes ausgeführt werden. Möchte man eine Funktion später aufrufen/ausführen muss dies immer über die main()-Funktion geschehen, da es anders keinen Sinn macht. Innerhalb der geschweiften Klammern werden wir in den kommenden Kapiteln unsere ersten Befehle schreiben. Wichtig ist auf die genaue Syntax zu achten. Würden wir beispielsweise in Zeile 11 die geschweifte Klammer weglassen, würden wir einen Fehler von unserem Compiler erhalten. ©Konstantin Rink 18 | S e i t e C++ Der include-Befehl Include-Befehle stehen immer in den ersten Zeilen unseres Quellcodes, schließlich würde es wenig Sinn machen eine Funktion aus einer Datei aufrufen zu wollen die wir erst viel weiter unten in unserem Quellcode inkludieren. Syntax: #include <dateiname(.h)> Hier muss man beachten, und aus diesem Grund auch das (.h), ob es sich um eine Header-Datei aus der Programmbibliothek handelt(z.B. iostream) oder um eine Header-Datei die wir selbst erstellt haben. Handelt es sich um eine Datei aus der Programmbibliothek so lässt man das .h weg, handelt es sich um eine eigene bzw. eine die nicht aus der Programmbibliothek stammt, schreibt man diese mit .h. Ein Beispiel hierzu: ©Konstantin Rink 19 | S e i t e C++ Ausgabe Nachdem wir uns mit dem Grundriss und dem Kopf eines C++ Programmes beschäftigt haben, kommen wir nun zur main()-Funktion und zu unserem ersten Befehl, der Bildschirmausgabe. Vorneweg hier der Quellcode: Wie man erkennen kann, wird der Befehl cout verwendet danach folgen zwei Pfeilsymbole und in Anführungszeichen unser Ausgabetext. Als allgemeine Syntaxregel lässt es sich so darstellen: Syntax: cout << <Wert>; Möchten wir Text auf dem Bildschirm ausgeben so schreibt man diesen in Anführungszeichen, handelt es sich aber um Zahlen, Variablen oder Funktionen so verwendet man keine Anführungszeichen. Nun möchte ich wie in Kapitel XX besprochen auf den using namespace std; Befehl zurück kommen. Wie schon erwähnt, benötigt man den Namensraum(namespace) um auf eine Funktion zuzugreifen zu können. Würde ich diesen Befehl nicht verwenden, sähe unsere Syntax so aus: Syntax: std::cout << <Wert>; Es ist Ihnen überlassen für welchen Weg Sie sich entscheiden, ich werde in diesem Skript using namespace std; nutzen, damit ich mir jedes mal das „std::“ spare. Möchte man mehrere Werte ausgeben, kann man dies realisieren indem man einfach zwei weitere Pfeilsymbole verwendet und diese „anhängt“. Syntax: cout << <Wert> << <Wert2> << <Wert3>; ©Konstantin Rink 20 | S e i t e C++ Nachdem wir nun ein Programm geschrieben haben welches uns etwas ausgibt und man somit etwas am Bildschirm sehen kann, möchten wir nun unsere Quelldatei kompilieren und ausführen um zu sehen ob alles geklappt hat. Hierzu klicken wir auf das Fenstersymbol in der dritten Symbolleiste von oben [1]. Oder verwenden den Shortcut F9. Nun sollte für einen sehr kurzen Augenblick sich ein Fenster geöffnet und wieder geschlossen haben. Um dieses Problem zu lösen, schließlich wollen wir ja gerne auch unser Ergebnis sehen, schreiben wir ab jetzt immer den „system(„pause“)-Befehl“ an das Ende bzw. vor die geschweifte Klammer, jedes von uns geschriebenen Quellcodes. Umgesetzt sieht es so aus: Drücken wir erneut das Fenstersymbol bzw. die F9-Taste wird das Fenster offen bleiben und wir werden „Hallo Welt“ angezeigt bekommen. Im Folgenden werden einige Beispiele der Bildschirmausgabe gezeigt: Würden wir das Programm jetzt kompilieren und ausführen, würden wir die Bildschirmausgabe in einer Zeile erhalten, bzw. er würde keine Zeilenumbrüche machen, da schließlich keine von uns im Quelltext angeordnet wurden. ©Konstantin Rink 21 | S e i t e C++ Zeilenumbrüche Zeilenumbrüche kann man mit zwei Befehlen realisieren, zum einen durch „\n“ zum anderen durch den Befehl endl; Der Unterschied zwischen den Befehlen ist, dass bei dem endl-Befehl zusätzlich das alle zwischengespeicherten Daten ausgegeben werden(Synchronisation) . Aus diesem Grund ist der endlBefehl auch aufwendiger/langsamer. Möchten wir also unsere Sätze mit Zeilenumbruch ausgeben würde man es so realisieren: ©Konstantin Rink 22 | S e i t e C++ Variablen Bisher kennen wir Variablen nur aus der Mathematik, diese verwenden wir als Platzhalter (auch Stellvertreter genannt), für einen Wert den wir errechnen oder in Abhängigkeit davon ausrechnen. Um es relativ simpel zu halten, würde ich gerne das Wort „Platzhalter“ in „Behälter“ umtaufen. Stellen wir uns also eine Variable in der Programmierung wie einen Behälter vor. Der Behälter besitzt folgende Eigenschaften: • • • Einen Typ Einen eindeutigen Namen Einen Wert Der Typ Unser Programm wird später mit Werten arbeiten. Diese Werte werden vorübergehend in den Arbeitsspeicher unseres Computers geschrieben um logischerweise mit ihnen schnell arbeiten zu können. Da unser Arbeitsspeicher allerdings begrenzt ist, müssen wir angeben wie viel Speicher für unsere Variable reserviert/frei gehalten werden soll. In C++ unterscheidet man zwischen folgenden Typen: Typ Speicherplatz Wertebereich Verwendung bool 1 Byte true, false (signed) char 1 Byte -128 bis +127 Kann den Wert 1 für true und den Wert 0 für false erhalten. Wir für Zeichen(A,B,C,..) verwendet. unsigned char (signed )int* 1 Byte 4 Byte 0 bis 255 -2.147.483.648 bis +2.147.483.647 unsigned int 4 Byte 0 bis 4.294.967.295 short int long unsigned long float 4 Byte 4 Byte 4 Byte 4 Byte -32.768 bis 32.767 -2.147.483.648 bis 2.147.483.647 0 bis 4.294.967.295 3,4E-38 bis 3,4E+38 (7 Nachkommastellen) double 8 Byte 1,7E-308 bis 1,7E+308 (15 Nachkommastellen) long double 10 Byte 3,4-4932 bis 1,1E+4932 *Die Größe ist Systemabhängig, wir gehen von einem 32Bit OS aus. Ganzzahl mit Vorzeichen (also auch negativen Werte) Ganzzahl ohne Vorzeichen (also nur positive Werte) Fließkommazahl Fließkommazahl bei sehr genauen Werten. Fließkommazahl Float oder Double wo sind die Unterschiede? Wenn es wichtig ist, bei Berechnungen ein sehr genaues Ergebnis zu erzielen, verwendet man double, da double, wie der Name schon sagt, die doppelte Genauigkeit hat wie float. ©Konstantin Rink 23 | S e i t e C++ Der Name C++ ist keysensitive, das bedeutet, dass C++ zwischen Groß- und Kleinschreibung unterscheidet. Die Variable mit den Namen kleinerApfel ist nicht gleich die Variable kleinerapfel. Sprich für C++ sind das zwei völlig verschiedene Variablennamen. Zudem existieren Wörter bzw. Begriffe die schon von C++ aus vordefiniert sind und deswegen nicht als Variablennamen verwendet werden dürfen. Folgende Wörter dürfen nicht verwendet werden: and bitand case compl default dynamic_cast export for inline namespace operator protected return static template try union void xor and_eq bitor catch const delete else extern friend int new or public short static_cast this typedef unsigned volatile xor_eq asm bool char const_cast do enum false goto long not or_eq register signed struct throw typeid using wchar_t auto break class continue double explicit float if mutable not_eq private reinterpret_cast sizeof switch true typename virtual while Ansonsten ist Ihnen die Namenswahl frei überlassen. Bedenken Sie aber bitte, dass Sie Ihren Variablen sinnvolle Namen geben sollten, um bei einem etwas größeren Quelltext nicht die Übersicht zu verlieren. Der Wert Hier muss man auf keine großen Besonderheiten achten, außer natürlich, dass der Wert der Variablen mit dem richtigen Datentyp deklariert ist. Nachdem wir uns mit dem theoretischen Teil der Variablen befasst haben, kommen wir nun zum praktischen Teil. ©Konstantin Rink 24 | S e i t e C++ Syntax: <Datentyp> <Variablenname> = <Wert der Variable> Deklaration und Initialisierung von Variablen Unter einer Deklaration einer Variablen versteht man, dass wir bestimmen von welchem Datentyp unsere Variable ist. Von einer Initialisierung spricht man, wenn man einer Variablen einen Wert zuweist. Dabei wird der Zuweisungsoperator „=“ verwendet. Im Folgenden werden einige Beispiele und Möglichkeiten der Deklaration und Initialisierung von Variablen gezeigt. Geltungsbereich von Variablen In dem bisherigen Beispiel wurden unsere Variablen innerhalb der main-Funktion deklariert und initialisiert. Das bedeutet, und hier muss man leider vorgreifen, dass diese Variablen ihre Gültigkeit nur in der main-Funktion haben. Möchten andere Funktionen mit dieser Variable arbeiten bzw. auf den Wert der Variablen zugreifen könnte man dies nur durch eine Parameterübergabe realisieren. Aus diesem Grund gibt es die Möglichkeit seine Variablen global zu deklarieren und initialisieren. Ein Beispiel hierfür: ©Konstantin Rink 25 | S e i t e C++ Zu Beachten ist, dass bei globalen Variablen die Deklaration und Initialisierung in einer Zeile erfolgen muss, andere Schreibweisen sind nicht erlaubt. Der Nachteil den globale Variablen haben ist, dass jede Funktion globale Variablen neu initialisieren kann und somit die Werte von diesen ändern kann wie man in diesem Beispiel hier sieht: Möchten wir eine Variable erstellen die einen konstanten Wert und ihre Gültigkeit den ganzen Programmablauf über hat, verwenden wir sog. Konstante, dazu mehr im nächsten Kapitel. ©Konstantin Rink 26 | S e i t e C++ Konstante Syntax: const <Datentyp> <Konstantenname> = <Wert der Konstanten> Im folgenden Beispiel möchten wir nun eine lokale Konstante deklarieren und initialisieren und dabei sehen, was passiert wenn wir dieser Konstanten später an irgendeiner Stelle im Quellcode einen neuen Wert zuweisen möchten. Selbstverständlich ist es auch möglich globale Konstanten zu erstellen wie man in diesem Beispiel hier sieht: ©Konstantin Rink 27 | S e i t e C++ Zeiger/Pointer ©Konstantin Rink 28 | S e i t e C++ Operatoren C++ stellt uns eine große Menge von Operatoren für die unterschiedlichsten Anwendungen zur Verfügung. Auf diese möchten wir nun in diesem Kapitel eingehen. Unbewusst haben wir schon 3 Operatoren verwendet, den Zuweisungsoperator („=“) um Variablen zu initialisieren, den *Operator und den &-Operator für die Werteübergabe mit Zeigern. Vorzeichen-Operatoren - Minus int zahl1= -5 Die Variable zahl1 erhält einen negativen Wert -5. + Plus int zahl2 = -zahl1 int zahl3 = 5 Die Variable zahl2 erhält einen positiven Wert 5. Die Variable zahl3 erhält einen positiven Wert 5. int zahl4 = +zahl3 Die Variable zahl4 erhält einen Positiven Wert 5. Arithmetische Operatoren + Addition int zahl1= 3 int zahl2 = zahl1+4 - Subtraktion * Multiplikation / Division % Modulo int zahl3 = 5 int zahl4 = zahl3-4 int zahl5 = 4 int zahl6 = zahl5*8 int zahl7 = 64 int zahl8 = zahl7/8; int zahl9 = 10; int zahl10 = zahl9%3 Dividiert die Werte seiner Operanden und gibt den Rest zurück. Kann nur auf ganzzahlige Operanden angewendet werden. Vergleichs Operatoren == Gleichheit zahl1 == zahl2 Gibt true zurück, wenn beide Operanten gleich sind, ansonsten false. != Ungleichheit zahl3 != zahl4 <= kleiner oder gleich >= größer oder gleich < kleiner zahl5<=zahl6 Gibt true zurück, wenn beide Operanten ungleich sind, ansonsten false. Gibt true zurück, wenn der Linke Operant kleiner oder gleich dem Rechten ist, ansonsten false. >größer zahl11>zahl12 ©Konstantin Rink zahl7>=zahl8 Gibt true zurück, wenn der Linke Operant größer oder gleich dem Rechten ist, ansonsten false. zahl9<zahl10 Gibt true zurück, wenn der Linke Operant kleiner als der Rechte ist. Gibt true zurück, wenn der Linke Operant größer als der Rechte ist. 29 | S e i t e C++ Zuweisungs-Operatoren ++ Inkrement zahl1=1; zahl1++; Erhöht den Wert des Operanten um 1. -- Dekrement zahl2=1; zahl2--; zahl5=3; Vermindert den Wert des Operanten um 1 = Zuweisung Weist den linken Operanten den Wert des rechten Operanten zu. Kombinierte Zuweisungsoperatoren += -= *= /= %= ©Konstantin Rink zahl1+=zahl2 Der Linke Operant wird mit dem Rechten addiert. Andere Schreibweise: zahl1= zahl1+zahl2 zahl3-=zahl4 Der Linke Operant wird mit dem Rechten subtrahiert. Andere Schreibweise: zahl3=zahl3-zahl4 zahl5*=zahl6 Der Linke Operant wird mit dem Rechten multipliziert. Andere Schreibweise: zahl5=zahl5*zahl6. zahl7/=zahl8 Der Linke Operant wird mit dem Rechten dividiert. Andere Schreibweise: zahl7=zahl7/zahl8. zahl9%=zahl10 Der Linke Operant wird mit dem Rechten dividiert und es wird der Rest zurückgegeben. Andere Schreibweise: zahl9=zahl9%zahl10. 30 | S e i t e C++ Die Eingabe in C++ Nachdem wir jetzt alle notwendigen Voraussetzungen besitzen und bereits Werte am Bildschirm ausgeben lassen können, kommen wir nun zur Eingabe von Werten. Syntax: cin >> <Variable>; Dies geschieht wie man sieht sehr einfach mit dem Befehl cin. Ähnlich wie bei cout verwendet man die Pfeilsymbole. Jedoch zeigen diese bei cin in die entgegengesetzte Richtung. Man kann sich als Eselsbrücke merken, dass der Wert den der Benutzer eingeben soll, in der Variable gespeichert wird, deswegen die Pfeilchen nach rechts. Möchte man stattdessen einen Wert auf dem Bildschirm ausgeben lassen, wandern die Pfeile bei cout nach links. Im folgenden Quellcode möchten wir den Benutzer um eine Eingabe bitten. Der Wert der Eingabe wird in einer Variablen gespeichert und soll am Bildschirm ausgegeben werden: Erläuterung Bevor wir uns an die Eingabeaufforderung wagen, deklarieren wir eine Variable in der der Eingabewert gespeichert werden soll. (Zeile 7) Damit der Benutzer dieses Programmes auch weiß, dass er etwas eingeben muss und nicht nur einen blinkenden Cursor sieht, lassen wir zunächst mit cout am Bildschirm eine Eingabebitte ausgeben(Z.8). Im Anschluss folgt der eigentliche Akt, hier wird der Eingabewert, in diesem Fall eine Ganzzahl in die Variable zahl gespeichert (Z.9). Abschließend möchten wir uns noch den Eingabewert, also den Wert der Variable zahl am Bildschirm mithilfe von cout ausgeben lassen (Z. 11). ©Konstantin Rink 31 | S e i t e C++ Kontrollstrukturen Die Wenn Dann (if/else)-Funktion Wenn Sie schon einmal mit Microsoft Excel Funktionen programmiert haben, kennen Sie sicherlich die „wenn-Dann“-Funktion. Nichts anderes ist es in C++. Syntax: if(<Bedingung>){ < Ereignis1>; } else{ < Ereignis2>; } Ist die Bedingung erfüllt so wird das Ereignis1 ausgeführt, ist die Bedingung nicht erfüllt, so wird Ereignis2 ausgeführt. Oder anders formuliert; wenn Bedingung erfüllt ist, dann führe Ereignis1 aus, ansonsten führe Ereignis2 aus. Ein simples Codebeispiel soll die Anwendung dieser Funktion erläutern: Es sei noch gesagt, dass else nicht zwingend notwendig ist, sprich man kann auch den nur den if-Teil, sofern erforderlich, verwenden. Ein häufiger Leichtsinnsfehler der passiert ist, dass man den Zuweisungsoperator(„=“) mit dem Vergleichsoperator(„==“) im Kopf der if-Funktion verwechselt, aus diesem Grund gilt hier Aufmerksamkeit. ©Konstantin Rink 32 | S e i t e C++ Die else if Funktion Haben wir mehrere Ereignisse die zu unterschiedlichen Bedingungen ausgeführt werden, können wir auf die else if-Funktion in C++ zurückgreifen, deren Syntax folgendermaßen aussieht: Syntax: if(<Bedingung>){ < Ereignis1>; } else if{ < Ereignis2>; } else if{ < Ereignis3>; } else if{ < Ereignis4>; } else{ <Ereignis n>; } Im folgenden Beispiel wird unsere Variable untersucht in welchem Wertebereich sie sich befindet. Bildschirmausgabe in der Konsole: Die Variable liegt im Wertebereich von 20 bis 30. Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 33 | S e i t e C++ Die switch and case Funktion -Too many ifs I think I switch ;-) - Bisher haben wir größere Kontrollstrukturen immer nur mit der else if-Funktion realisiert. Jedoch gestaltet sich das beispielsweise bei 30,100 Bedingungen als recht unpraktisch. Aus diesem Grund gibt es in C++ die switch and case-Funktion. Diese erfüllt im Endeffekt denselben Zweck wie die else if- Funktion. Jedoch kommt es immer auf die individuelle Aufgaben-/Problemstellung an, denn man kann zum Beispiel mit der switch and case-Funktion nicht überprüfen in welchem Wertebereich eine Variable liegt. Syntax: switch(<Ausdruck auf den die Bedingungen geprüft werden sollen>){ case <Bedingung1>: <Ereignis1>; break; case <Bedingung2>: <Ereignis2>; break; case <Bedingung3>: <Ereignis3>; break; case <Bedingung4>: <Ereignis4>; break; case <Bedingung5>: <Ereignis5>; break; } Ein Codebeispiel soll uns Klarheit bringen: In diesem Beispiel wird untersucht welchen Wert die Variable zahl besitzt. Im Kopf der switch and case-Funktion tragen wir den Namen der zu prüfenden Variablen ein. Im Schleifenkörper werden mit case beginnend die einzelnen Bedingungen geschrieben und mit einem Doppelpunkt beendet. Danach folgt das Ereignis welches bei Eintreten der Bedingung ausgeführt werden soll. Zuletzt wird nach jedem Ereignis der break-Befehl geschrieben. Der Sinn des break-Befehls ist es, nachdem die Bedingung wahr und das Ereignis eingetreten ist, die Kontrollstruktur zu verlassen. Geschieht dies nicht werden alle weiteren Ereignisse ausgeführt ohne sie auf ihre Bedingung zu prüfen. ©Konstantin Rink 34 | S e i t e C++ Bildschirmausgabe in der Konsole: Die Variable liegt im Wertebereich von 20 bis 30. Drücken Sie eine beliebige Taste . . . Soll eine Bedingung eintreten, wenn keine der case-Bedingungen wahr (true) ist oder möchte man eine Bedingung die in jedem Fall eintritt, so verwendet man den Befehl default. Der Befehl ist optional und muss nicht zwingend in einer switch-Kontrollstruktur vorkommen. Quellcodebeispiel: Beachte: In diesem Beispiel verwendet man den default-Befehl, wenn keine der Bedingungen wahr ist. Aus diesem Grund steht er auch am Ende unserer Kontrollstruktur. Möchten wir den default-Befehl aber dazu verwenden, dass er in jedem Fall eintritt, so kann man diesen auch zu Beginn oder je nach Anforderung in die Mitte der Struktur schreiben. Jedoch sollte man diesen dann nicht mit dem break-Befehl kombinieren, denn dann würde, sobald der default-Befehl ausgeführt, ist die weiteren Überprüfungen abbrechen und die Kontrollstruktur verlassen. ©Konstantin Rink 35 | S e i t e C++ Mathematische Funktionen In diesem Kapitel möchten wir uns kurz mit ein paar häufig benötigten mathematischen Funktionen beschäftigen. Es kann vorkommen, dass wir z.B. mit Potenzen, Wurzeln, Logarithmen, etc. rechnen müssen. Aus diesem Grund gibt es die Datei math.h die wir zu Beginn unseres Quellcodes neben der iostream-Datei inkludieren. Im Folgenden nun Beispiel zu einigen Funktionen der math.h : Wie schon erwähnt war dies nur ein sehr kurzer Ausschnitt aus der math.h eine ausführliche Dokumentation finden Sie unter: http://www.cplusplus.com/reference/clibrary/cmath/ Da wir nun mit Variablen umgehen können und etwas von mathematischen Funktionen in C++ gehört haben, kommen wir zu unserer ersten Aufgabe: Aufgabe #1: Der Benutzer soll eine quadratische Gleichung mithilfe unserer Anwendung lösen können. Der Benutzer wird aufgefordert zuerst die Werte für a, b und c einzugeben, dann soll mithilfe einer programmierten Mitternachtsformel (𝑥 = entsprechende(n) Lösung(en) ausgegeben werden. −𝑏±√𝑏 2 −4𝑎𝑐 2𝑎 ) die Hinweis: a steht immer für x² und b für die x-Werte. Um festzustellen wie viele Lösungen existieren berechnet man zuerst die Diskriminante (b²-4ac) und wertet nach ihr aus. Wer sich noch unsicher bei der Berechnung ist, sollte einen Blick in die Formelsammlung wagen. ©Konstantin Rink 36 | S e i t e C++ Schleifen Wir werden in der Programmierung früher oder später an einen Punkt kommen, wo wir ohne Schleifen nicht mehr weiter kommen. In der Programmierung versteht man unter Schleifen Kontrollstrukturen, die einen Anweisungs-/Ereignisblock solange durchlaufen, bis ihre Laufbedingung ungültig wird bzw. ihre Abbruchbedingung eintritt. Ist keine Laufbedingung gegeben bzw. tritt keine Abbruchbedingung ein, so redet man von einer Endlosschleife. Kurz gesagt, Schleifen wiederholen ein bestimmtes Ereignis bis sie ihre Gültigkeit verlieren oder sie durch einen Befehl abgebrochen werden. Man verwendet Schleifen also um eine Anzahl von bestimmten Ereignissen ausführen zu können. Vor allem beim Arbeiten mit Arrays (Kapitel XX) finden Schleifen ihre Verwendung. Hier die einzelnen Arten zur Verdeutlichung als Nassi-Shneiderman Diagramm: Um aber möglichst praxisnah in das Thema eintauchen zu können hier eine Beispielaufgabe. Folgende Aufgabenstellung zur Einleitung: Der Benutzer soll eine Ganzzahl eingeben, der Wert der Zahl, z.B. 6 soll in Form von Rauten am Bildschirm ausgegeben werden, in diesem Fall ######. Insgesamt gibt es drei Schleifentypen in C++. Mit allen lässt sich diese Beispielaufgabe realisieren, jedoch wird man feststellen, dass einige Typen besser dafür geeignet sind als andere. Aus diesem Grund möchte ich nun jeweils die einzelnen Schleifentypen erklären und mit jedem dieser die Beispielaufgabe lösen. ©Konstantin Rink 37 | S e i t e C++ Die while-Schleife Syntax: } while(<Bedingung>){ <sich wiederholendes Ereignis>; Der Kopf der while-Schleife ist simpel aufgebaut, man gibt lediglich die gewünschte Bedingung an. Der Inhalt der Schleife (<sich wiederholendes Ereignis>) wird solange durchlaufen bzw. ausgeführt, bis die Bedingung im Schleifenkopf ihre Gültigkeit verloren(false) hat. Lösung des Beispiels mit der while-Schleife: Erläuterung Was Ihnen sicher aufgefallen ist, ist die Variable counter. Die Variable ist eine Zählervariable die dafür sorgt, dass unsere Schleife nicht endlos läuft. Würde man sie weglassen, wäre die Bedingung dafür, dass die Schleife läuft, nur die Zahl die der Benutzer eingibt, sprich die Bedingung wäre die ganze Zeit wahr(true) und wir würden Unmengen von Rauten auf dem Bildschirm sehen. counter hat einen Startwert von 0 (Z.10) und wird immer um 1 pro Schleifendurchlauf erhöht(Z.13) Irgendwann, je nach dem welchen Wert der Anwender eingegeben hat, wird die Bedingung false werden und die Schleife abbrechen, da der Wert der Variable counter größer wäre als der Wert der Variable zahl. Und wir werden unser gewünschtes Ergebnis auf dem Bildschirm sehen. Mit dem Beispiel der Zahl 6 sollte unsere Konsolenausgabe so aussehen: Bitte geben Sie eine Zahl ein: 6 ######Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 38 | S e i t e C++ Die for-Schleife Syntax: for(<Zähler>;<Bedingung>;<Zähler erhöhen/erniedrigen>){ <sich wiederholendes Ereignis>; } Im Vergleich mit der Syntax der while-Schleife sieht man, dass ein paar Parameter mehr dazu gekommen sind. Erinnern wir uns an die Zählervariable counter, diese wurde vor der Schleife definiert und wurde im Schleifenkörper immer um eins erhöht. Dieses etwas umständliche hin und her nimmt uns die for-Schleife ab. Hier wird alles im Schleifenkopf festgelegt. Im ersten Parameter legen wir unsere Zählervariable fest, im Zweiten wie gewohnt unsere Bedingung und bei dem Dritten legen wir fest um wie viel unsere Zählervariable erhöht/erniedrigt werden soll. Unsere Lösung nach dem Beispiel würde dann so aussehen: ©Konstantin Rink 39 | S e i t e C++ Die do-while-Schleife Syntax: do{<Ereignis>; }while(<Bedingung>) Unser letzter Kandidat ist die do-while-Schleife. Die Funktion verwendet auch die gleichen Parameter wie die while-Schleife. Aber die Besonderheit dieses Typs ist, dass zuerst das Ereignis ausgeführt wird und erst danach die Bedingung geprüft wird. Sprich, beim ersten Durchlauf der Schleife wird nicht überprüft ob die Bedingung wahr(true) ist sondern es wird einfach das Ereignis ausgeführt. Für unsere Beispielaufgabe spielt es keine Rolle, dass das Ereignis vor der Bedingung ausgeführt wird. Jedoch werden Sie auf Problemstellungen treffen, an denen die Vorteile dieses Schleifentyps wichtig sind und es einen Unterschied macht, ob erst das Ereignis ausgeführt und erst danach die Bedingung geprüft wird. Lösung: ©Konstantin Rink 40 | S e i t e C++ Eine Schleife vorzeitig abbrechen/Prozedur in einer Schleife überspringen Manchmal ist man gezwungen eine Schleife vorzeitig abbrechen zu lassen. In C++ gibt es daher den Befehl break. break bewirkt, dass die Schleife sofort verlassen wird. Bemerkung: Wird der break-Befehl in verschachtelten Schleifen angewandt, wird nur die unmittelbare Schleife verlassen. Hier ein Beispiel indem ein Wertebereiche untersucht werden soll, befindet sich die Eingabe des Anwenders im Zahlenbereich von 0 bis 4, so wird die Schleife abgebrochen, ansonsten läuft sie durch. Bildschirmausgabe wenn Zahl innerhalb des Wertebereichs liegt: Bitte Zahl eingeben: 2 Drücken Sie eine beliebige Taste . . . Bildschirmausgabe wenn Zahl außerhalb vom Wertebereich liegt: Bitte Zahl eingeben: 5 0 1 2 3 4 5 6 7 8 9 Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 41 | S e i t e C++ Möchte man allerdings nur eine gewisse Prozedur in einer Schleife überspringen, verwendet man den Befehl continue. Die continue-Anweisung springt dann wieder zum Anfang der Schleife und überspringt somit die Ereignisse die zwischen dem Schleifenkopf und dem continue-Befehl liegen. Im Vergleich zu break wird die Schleife somit nicht verlassen. Hierzu auch ein Anwendungsbeispiel in dem ich alle Werte außer 5 ausgeben lassen möchte: Bildschirmausgabe: 12346789 Drücken Sie eine beliebige Taste . . . Wann verwende ich welche Schleife? Zum Teil ist die Anwendung von den jeweiligen Schleifentypen Geschmackssache, jedoch kann man teils auch klare Unterscheidungen treffen. Die while-Schleife wird gerne verwendet, wenn die Anzahl der Daten mit denen man Arbeitet unbekannt ist. Die for-Schleife findet gerne ihre Anwendung, wenn die Anzahl der Daten wiederum bekannt ist. Die do-while-Schleife wird verwendet, wenn man den Schleifenkörper mindestens 1x ausführen möchte. ©Konstantin Rink 42 | S e i t e C++ Eindimensionale Felder (Arrays) Nachdem wir die Kapitel Variablen und Schleifen bearbeitet haben, kommen wir nun zu den Feldern, im englischen arrays genannt. Ein Array ist sozusagen eine Variable, in der mehrere Variable abgespeichert werden und deren Werte durch einen jeweils eindeutigen Index angesprochen werden können. Eine sehr gute Hilfe ist es, sich eindimensionale Arrays wie ein eindimensionale Tabellen vorzustellen. Jedem Wert wird ein Index von 0 aufsteigend zugewiesen. Möchte man später mit einem bestimmten Wert arbeiten, so kann man ihn über seinen Index ansteuern. Index 0 1 2 3 Werte Wert 1 Wert 2 Wert 3 Wert 4 Definition und Initialisierung von eindimensionalen Arrays Syntax: <Datentyp> <Name des Arrays>[<Größe des Arrays> bzw. <Anzahl der Zeilen>]; Codebeispiel: ©Konstantin Rink 43 | S e i t e C++ Vorgang: 1. Bestimmen welche Art von Daten mein Array enthalten wird (int, float, double, etc.) 2. Dem Array einen Namen geben und festlegen wie viel Werte es maximal aufnehmen kann. 3. Initialisierung meines Arrays, indem ich jedem Wert einen Index zuweise. Einlesen /Ausgeben von eindimensionalen Arrayinhalten mit Schleifen In diesem Unterkapitel möchten wir uns mit dem Einlesen und Ausgeben von Arrayinhalten beschäftigen. Wie bei der Einleitung von Kapitel XX –Schleifen kurz erwähnt, werden Schleifen verwendet, sobald man mit mehreren Arrayinhalten arbeiten möchte. Im folgenden Quellcode-Beispiel möchte ich zeigen wie man mithilfe einer for-Schleife ein Array durch eine Eingabeaufforderung befüllt. Bildschirmausgabe: Bitte Wert 0 festlegen: 1 Bitte Wert 1 festlegen: 2 Bitte Wert 2 festlegen: 3 Bitte Wert 3 festlegen: 4 Bitte Wert 4 festlegen: 5 Drücken Sie eine beliebige Taste . . . Erläuterung Zu Beginn legen wir fest wie groß unser Array zahlen maximal sein darf (Z.6), danach legen wir die Bedingung für unsere Schleife fest. Die Schleife wird 5 Runden durchlaufen, danach wird ihre Bedingung ungültig (false) werden, da die Zählervariable counter je Runde um 1 erhöht wird (Z.9) Im Schleifenkörper wird der Benutzer pro Durchlauf gebeten eine Zahl einzugeben. Die eingegebene Zahl wird dem jeweiligen Index unseres Arrays zugeteilt (Z.12) Nachdem wir nun unser Array durch eine Eingabeaufforderung befüllt haben, kommen wir nun zur Ausgabe. Hierzu verwenden wir wieder eine for-Schleife. ©Konstantin Rink 44 | S e i t e C++ Codebeispiel: Bildschirmausgabe: Bitte Wert 0 festlegen: 1 Bitte Wert 1 festlegen: 2 Bitte Wert 2 festlegen: 3 Bitte Wert 3 festlegen: 4 Bitte Wert 4 festlegen: 5 1 2 3 4 5 Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 45 | S e i t e C++ Einen bestimmten Wert von einem Array ausgeben Möchte ich nun einen bestimmten Wert in einem Array ansteuern und diesen z.B. auf dem Bildschirm ausgeben, geschieht dies indem ich den gewünschten Index des Arrays in die eckigen Klammern ([X]) schreibe. In diesem Beispiel habe ich ein Array mit den Buchstaben von A-K. Möchte ich mir nun den Buchstaben G ausgeben lassen geschieht dies folgender Maßen: Erläuterung: Zuerst definieren und initialisieren wir unser Array mit Werten, in diesem Fall mit Buchstaben. Aus diesem Grund verwenden wir auch den Typ char. (Z. 7) In Zeile 10 lassen wir unseren gewünschten Buchstaben auf dem Bildschirm ausgeben, indem wir den jeweiligen Wert (in diesem Fall „G“) über seine Indexnummer 0 A ansprechen. 1 B 2 C Der Index beginnt immer mit 0 aufsteigend, deswegen 3 D steht auch die Indexnummer 6 und nicht die 7 in den eckigen Klammern. 4 E 5 F Zum besseren Verständnis kann man sich das Array auch als 6 G eindimensionale Tabelle vorstellen: 7 H 8 I 9 J 10 K ©Konstantin Rink 46 | S e i t e C++ Mehrdimensionale Arrays Bisher haben wir uns nur mit eindimensionalen Feldern bzw. Arrays beschäftigt, in Tabellenform würde das bedeutet, dass wir bisher immer nur eine Spalte und x-beliebige Zeilen zur Verfügung hatten. Die mehrdimensionalen Arrays bieten uns die Möglichkeit für x-beliebige Spalten und Zeilen. Syntax: <Datentyp> <Name des Arrays>[<Anzahl der Zeilen>][<Anzahl der Spalten>]; Wie man sehen kann, ist ein neuer Ausdruck ([<Anzahl der Spalten>]) hinzugekommen. Nehmen wir als Beispiel ein Array namens „Tabelle“ mit 5 Zeilen und 3 Spalten, in C++ würde das dann so aussehen: Tabelle[5][3]; In Tabellenform dürfen wir uns das dann so vorstellen: Wert 1 Wert 2 Wert 3 Wert 4 Wert 5 Wert 6 Wert 7 Wert 8 Wert 9 Wert 10 Wert 11 Wert 12 Wert 13 Wert 14 Wert 15 Die Initialisierung sieht wie folgt aus: Die Initialisierung würde in Tabellenform so aussehen. 1.5 1.7 5.2 6.1 7.8 2.5 2.7 5.3 6.8 7.6 ©Konstantin Rink 3.5 3.7 5.8 6.4 7.4 Wie man erkennen kann, werden Arrays in C++ zeilenweiße initialisiert. Der letzte Index [3] ändert sich also schneller wie der erste Index [5]. 47 | S e i t e C++ Einlesen /Ausgeben von mehrdimensionalen Arrayinhalten mit Schleifen Im folgenden Beispiel möchten wir den Benutzer auffordern ein zweidimensionales (2 Spalten XZeilen) Array mit jeweils Stückzahl und Stückpreis zu befüllen. Erläuterung: Im Prinzip ähnlich wie bei den eindimensionalen Arrays. Nur möchten wir in diesem Beispiel ein Array mit 2 Spalten verwenden. In der ersten Spalte möchten wir unsere Stückzahlen eingeben in die zweite die Stückpreise. In Zeile 12 steuern wir deshalb die Spalte 0 und in Zeile 15 die Spalte 1 an. Durch die Zählervariable i werden die Zeilen zu den jeweiligen Spalten fortlaufend vom Benutzer beschrieben. Die Ausgabe sieht auch wieder ähnlich wie bei den eindimensionalen Arrays aus: ©Konstantin Rink 48 | S e i t e C++ Bildschirmausgabe mit zufällig eingegebenen Werten: Bitte geben Sie die Stueckzahl ein: 200 Bitte geben Sie den Stueckpreis ein: 1.48 Bitte geben Sie die Stueckzahl ein: 500 Bitte geben Sie den Stueckpreis ein: 0.49 Bitte geben Sie die Stueckzahl ein: 200 Bitte geben Sie den Stueckpreis ein: 5.69 Bitte geben Sie die Stueckzahl ein: 800 Bitte geben Sie den Stueckpreis ein: 1.89 Danke fuer Ihre Eingabe. Stueckzahl || Stueckpreise 200 || 1.48 500 || 0.49 200 || 5.69 800 || 1.89 Drücken Sie eine beliebige Taste . . . Einen bestimmten Wert von einem mehrdimensionalen Array ausgeben Möchte man nun beispielsweise den Wert7 ansprechen, stellt man sich am besten eine Tabelle vor: Unser gesuchter Wert befindet sich also in Spalte 1 (da der Index immer mit 0 beginnt) und Zeile 1. In der C++ sähe es dann so aus: Wert 1 Wert 2 Wert 3 Wert 4 Wert 5 Wert 6 Wert 7 Wert 8 Wert 9 Wert 10 Wert 11 Wert 12 Wert 13 Wert 14 Wert 15 Parallel dazu als Tabellenform: 1.5 1.7 5.2 6.1 7.8 ©Konstantin Rink 2.5 2.7 5.3 6.8 7.6 3.5 3.7 5.8 6.4 7.4 49 | S e i t e C++ Bubblesort und Dreieckstausch Je nach Problemstellung werden wir irgendwann an den Punkt kommen, wo wir Werte in einem Array sortieren oder vertauschen möchten. Hierfür soll der Sortieralgorithmus Bubblesort und das Verfahren des Dreieckstauschs Abhilfe schaffen. Dreieckstausch Beim Dreieckstausch hilft uns eine Hilfsvariable, Werte in einem Array zu vertauschen. Dabei wird der Wert des Arrays der zuerst überschrieben wird, in einer Hilfsvariablen zwischengespeichert. Folgendes Beispiel soll uns den Problemfall erläutern: Bevor wir uns an die Arbeit machen, hier der Dreieckstausch als Pseudocode zum besseren Verständnis: temp := v1 // Die Hilfsvariable nimmt den Wert der zu vertauschenden Variable an. v1 := v2 // Variable 1 wird jetzt der Wert der Variable 2 zugewiesen. v2 := temp // Zum Schluss erhält Variable 2 den Anfangswert der Variable 1 Umgesetzt in unsere C++ Sprache würde es dann so aussehen: ©Konstantin Rink 50 | S e i t e C++ Abschließend möchte ich noch eine weitere Aufgabenstellung zeigen. Diesmal möchten wir, dass der Benutzer die Möglichkeit hat selbst zu bestimmen an welcher Stelle der erste Wert durch-getauscht werden soll. Erläuterung: Anfangs mag der Dreieckstausch noch etwas kompliziert aussehen, man muss aber einfach nur zwischen aktuellen Wert und aktuellen Index unterscheiden. Schauen wir uns die Schleife mal im ersten Durchlauf an: Unsere Hilfsvariable hilf bekommt den Wert der Indexnummer 0 unseres Arrays zugewiesen, also 1. Danach bekommt unser Array an die Stelle mit der Indexnummer 0 den Wert der Indexnummer 1 zugewiesen, also 2. Im letzten Schritt bekommt die Stelle mit der Indexnummer 1 mit Hilfe der Hilfsvariablen den ehemaligen Wert mit der Indexnummer 0 zugewiesen. An der Indexnummer 0 steht jetzt der Wert der Indexnummer 1 und umgekehrt. Bildschirmausgabe mit dem eingegebenen Wert 5: An welche Stelle soll unser erstes Array getauscht werden: 5 23456178910 Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 51 | S e i t e C++ Bubblesort Der Bubblesort Algorithmus wird verwendet, wenn man Werte in einem Array sortieren möchte. Um einen guten Einstieg in diesen Algorithmus zu erhalten, nehmen wir ein Kartenbeispiel zur Hand. Wie wir sehen sind die Karten der ihrer Wertung nach aufsteigend sortiert. Jetzt vermischen wir die Karten willkürlich. Der Bubblesort Algorithmus soll uns jetzt helfen, diese Karten wieder in die richtige Reihenfolge zu bringen. Dabei macht der Algorithmus folgendes: Er vergleicht immer die linke Karte mit seinem rechten Nachbarn, in unserem Fall vergleicht er also Pik 8 mit Pik 7. Ist die linke Karte größer wie sein Nachbar, werden die beiden Karten vertauscht: Dieses Vertauschen wird solange durchgeführt, bis die Karten der Größe nach in der richtigen Reihenfolge sortiert sind. Bevor wir nun zur eigentlichen Programmierung in C++ kommen, sollten wir uns den Algorithmus als Struktogramm ansehen: ©Konstantin Rink 52 | S e i t e C++ Die Quellcodeversion: Erläuterung Wir gehen von einem Array namens zahlen aus, welches Werte von 1-10 in nicht sortierter Reihenfolge enthält. Um zu verstehen, was jede einzelne Schleife macht, schauen wir uns die ersten 3 Durchläufe an. Wir betrachten die innere for-Schleife: Erster Durchlauf: Zahlen[0] < zahlen[0] // 6<6 Zweiter Durchlauf: Zahlen[0]<zahlen[1] //6<3 Dritter Durchlauf: Zahlen[0]<zahlen[2] //6<7 An dieser Stelle ist unsere if-Funktion wahr und er vertauscht die Werte 6 und 7. ©Konstantin Rink 53 | S e i t e C++ Arbeiten mit Arrays In diesem Kapitel sind einige Aufgaben zu bearbeiten, in denen die Basics von Arrays und Schleifen Voraussetzung sind. Diese Aufgaben sollten den Grundumgang mit Arrays abdecken. Die Lösungen sind auf der nächste Seite zu finden. Aufgabe #1: Schreiben Sie ein Programm, welches die Summe aus 3 eigegebenen Fließkommawerten berechnen soll. Aufgabe #2: Schreiben Sie ein Programm, welches zuerst 5 Messwerte in ein Array einlesen soll und danach den Durchschnitt aus dieser Messwerte berechnet. Aufgabe #3: Schreiben Sie eine Anwendung in der unsere wissenschaftlichen Mitarbeiter den Wochentag(in den Zahlen 1-6) und ihr jeweiliges Messergebnis für eine Woche (6 Arbeitstage) eintragen können. Nach ihrer Eingabe sollen sie in einer Spalte die Wochentage und in einer anderen die Messwerte ausgegeben bekommen. Zum Beispiel: Wochentag || Messwert 1 || 34,5 Aufgabe #4: - Noch keine Lösung Schreiben Sie eine Anwendung für ein Kassensystem. Der Verkäufer gibt die Stückzahl und den Verkaufspreis ein und bekommt den zu Zahlenden Betrag zurückgeliefert. (Wir gehen von Maximal 10 Artikeln pro Einkauf aus) Aufgabe #5: Etwas Mathematik gefällig? Unter einer Spur versteht man die Quersumme einer Matrix. Schreiben Sie für eine 3x3 Matrix eine Anwendung, die die Quersumme bzw. die Spur errechnet. Die Werte der 3x3 Matrix können Sie mit beliebigen Werten initialisieren. ©Konstantin Rink 54 | S e i t e C++ Lösungen In der Programmierung gibt es meist immer mehrere Lösungsmöglichkeiten, aus diesem Grund kann es sein, das Ihr Quellcode von dem der Musterlösung abweichen kann. Aufgabe #1: Aufgabe #2: ©Konstantin Rink 55 | S e i t e C++ Aufgabe #3: Aufgabe #5: In diesem Fall wäre das Ergebnis 15. Um sich den Verlauf der Schleife besser vorzustellen, sollte man wieder mit einer Tabellen-Skizze arbeiten und einen einzelnen Schleifendurchlauf analysieren. ©Konstantin Rink 56 | S e i t e C++ Funktionen Bisher haben wir unsere Berechnungen immer in der main-Funktion durchgeführt. Jedoch werden wir schnell in der Programmierung an einen Punkt kommen, wo wir z.B. gewisse Rechenoperationen (z.B. die Berechnung von Quadratmeter) häufiger als nur einmal durchführen möchten. Nach unseren bisherigen Wissenstand müssten wir also immer wieder, wenn wir den Term benötigen, diesen in unserem Quellcode schreiben. Zugegeben, bei der Berechnung von Quadratmetern würde uns das noch wenig ausmachen, jedoch ist dies nur ein sehr simples Beispiel. Viel einfacher wäre es doch, diesen Term auszulagern und bei Bedarf einfach die benötigten Parameterwerte (z.B. Länge und Breite) ihm zu übergeben und das Ergebnis zurück geliefert bekommen. Und genau an diesem Punkt kommen die Funktionen ins Spiel. Syntax: } <Datentyp> <Name der Funktion>(<Datentyp><Parameter1>,<Datentyp><Parameter2>){ <Ereignisse>; Wie Sie sicher festellen werden, hat die Syntax von Funktionen den gleichen syntaktischen Aufbau wie unsere main-Funktion. Selbstverständlich, schließlich ist die main-Funktion prinzipiell auch nichts anderes wie eine normale Funktion. Doch wie in Kapitel XX erwähnt, hat die main-Funktion die Besonderheit, dass sie quasi die Einstiegsfunktion unseres Programmes ist. Sie ist sozusagen die Funktion auf die beim Start unseres Programmes als erstes zugegriffen wird und die jeweiligen Befehle in ihr ausgeführt werden. Folgender Quellcode als Beispiel: Bevor wir auf die einzelnen Begrifflichkeiten wie return eingehen, möchten wir uns die Schreibweise der Funktionen genauer ansehen. In diesem Beispiel wird unser Programm funktionieren, schreiben wir jedoch die Funktion quadratmeter nicht ober- sondern unterhalb der main-Funktion werden wir eine Fehlermeldung von unserem Compiler erhalten. Da unser Compiler immer von oben nach unten liest, wüsste er in Zeile 17 somit nicht, dass überhaupt eine Funktion quadratmeter existiert. ©Konstantin Rink 57 | S e i t e C++ Später werden wir mit mehr als nur einer Funktion arbeiten und evtl. möchten wir, dass die Funktionen jeweils aufeinander zugreifen können (z.B. eine Funktion berechnet die Längen, eine andere übernimmt diese Werte und berechnet den Flächeninhalt). Dann müssten wir uns an eine gewisse Hierarchie halten, da wir genau wissen müssten, welche Funktion wir zuerst deklarieren und definieren, sonst würden wir wieder eine Fehlermeldung vom Compiler bekommen, dass die gewünschte Funktion noch nicht existiert. Um das zu vermeiden, werden wir zu Beginn immer unsere Funktionen deklarieren und später an beliebiger Stelle definieren. Syntax: <Datentyp> <Name der Funktion>(<Datentyp>,<Datentyp>); // Deklaration ... … <Datentyp> <Name der Funktion>(<Datentyp><Parameter1>,<Datentyp><Parameter2>){ <Ereignisse>; } // Definition Somit ist es jetzt egal an welche Stelle wir in unserem Programm unsere Funktion definieren. Unser Codebeispiel würde dann so aussehen: Unser Compiler liest immer von oben nach unten, kommt er an Zeile 4 an, springt er zu Zeile 16 um dort unsere Funktion quadratmeter einzulesen. So kann man diese beliebig später im Quellcode verwenden. ©Konstantin Rink 58 | S e i t e C++ Rückgabewert Sicher haben Sie sich schon gefragt, was der return-Befehl zu bedeutet hat. Der return-Befehl beendet die Funktion und liefert den jeweiligen Wert (in unserem Beispiel den Wert der Variable ergebnis) zurück. Wichtig ist, dass wir wissen, welchen Typ von Wert uns unsere Funktion zurückgeben soll. Sprich, ob es sich beispielsweise um eine Ganzzahl oder Fließkommazahl handelt. Mit dieser jeweiligen Art müssen wir unsere Funktion deklarieren (Z.4, Z.16). In unserem Fallbeispiel wird also eine Ganzzahl (int)zurückgeliefert. Hier noch einige Schreibweisen wie man sich Werte in C++ zurückliefern lassen kann: Es gibt auch Funktionen, die uns keinen Wert zurückliefern sondern lediglich z.B. einen Wert ausgeben sollen. Diese Funktionen deklariert man dann mit void und kann auf den return-Befehl verzichten bzw. der return-Wert wäre 0. Ein Beispiel hierzu: Nun wissen wir, wie wir eine neue Funktion erstellen und wie wir uns Werte aus Funktionen mit return zurückliefern lassen. Sollte man einen return vergessen ist der Rückgabewert der Funktion undefiniert und zufällig. Manche Compiler geben dann dementsprechend eine Fehlermeldung über den fehlenden Rückgabewert aus. Kommen wir nun dazu wie wir Parameterwerte an Funktionen übergeben. Hierzu gibt es die Möglichkeiten call by value und call by reference. ©Konstantin Rink 59 | S e i t e C++ Call by value -Der Standardfall- In den bisherigen Beispielen haben wir den Standartfall call by value schon unbewusst verwendet. Wenn wir eine Funktion aufrufen, werden nur die Werte der einzelnen Parameter übergeben („call by value“). Das heißt, unsere Funktion kann nur lesend, aber nicht schreibend auf die übergebenen Parameter zugreifen. Der Vorteil dieser Parameterübergabe ist es, das keine unbeabsichtigten Änderungen von Variablenwerten durch diese Aufrufe in anderen Funktionen(z.B. der mainFunktion) auftreten können. Beachte: Ausgenommen von dieser Regel sind Vektoren, Strings und Arrays. Werden sie an eine Funktion übergeben, kann die Funktion auch übergreifend schreibend auf die Parameter zugriff nehmen. Ein Beispiel soll uns den Fall erläutern: Wir möchten zu den Variablen a und b jeweils 2 hinzuaddieren, danach a und b multiplizieren und uns das Ergebnis ausgeben lassen. Bildschirmausgabe: a hat den Wert: 2 b hat den Wert: 4 Das Ergebnis lautet: 24 Drücken Sie eine beliebige Taste . . . Obwohl wir in unserer Funktion addition zu den Variablen a und b +2 hinzuaddiert haben, hat sich ihr Wert in der main-Funktion nicht geändert, sondern lediglich in unserer Funktion addition. Das ist der Vorteil der Parameterübergabe call by value. ©Konstantin Rink 60 | S e i t e C++ In diesem Beispiel möchten wir uns nun ansehen, was passiert wenn wir Arraywerte an eine Funktion übergeben. Bildschirmausgabe: 0--5 Drücken Sie eine beliebige Taste . . . Wie wir gelernt haben, liefert uns unsere Funktion immer nur das zurück, was mit dem return-Befehl zurückgegeben wird. Jedoch wurde auch unser Array verändert. Normalerweise hat unser Array an der Stelle [0] den Wert 1. Jedoch passierte bei der Werteübergabe an die Funktion addition folgendes: Bei Arrays wird auch bei der call by value Übergabe die Speicheradresse des Arrays übermittelt. Die Funktion hat dann auch schreibzugriff auf den Array und kann dessen Werte dauerhaft verändern. Aus diesem Grund sollte man aufpassen, wenn man Arraywerte an eine Funktion übergibt. Wie wir es realisieren, dass die Speicheradressen von Variablen mit übergeben werden und eine Funktion somit auch schreibzugriff auf Variablen erhält sehen wir im nächsten Unterkapitel. ©Konstantin Rink 61 | S e i t e C++ Call by reference Diese Parameterübergabe ist das Gegenstück zur call by value-Übergabe. Die Speicheradressen von Variablen(siehe Kapitel XX) werden mithilfe von Zeigern (siehe Kapitel XX) als Funktionsparameter an die Funktion übergeben. Damit ist es der Funktion möglich auch funktionsübergreifend schreibend auf die Variablen Zugriff zu nehmen. Syntax: <Datentyp> <Name der Funktion>(<Datentyp> Zeiger,<Datentyp> Zeiger); ... … <Datentyp> <Name der Funktion>(<Datentyp>Zeiger auf<Parameter1>,<Datentyp>Zeiger auf<Parameter2>){ <Ereignisse>; } Ein Quellcodebeispiel zum Verständnis: Bildschirmausgabe: b hat den Wert: 5 c hat den Wert: 11 Drücken Sie eine beliebige Taste . . . ©Konstantin Rink 62 | S e i t e C++ Erläuterung: Wie in der Syntax schon angegeben, wird bei der call by reference-Übergabe mit Zeigern(=Pointer) gearbeitet. In Zeile 5 bei der Deklaration werden die Parameter als „Zeiger auf int“ deklariert. In Zeile 11 werden der Funktion die Speicheradressen der Variablen mithilfe des Adressoperators & übergeben. In Zeile 24 und 25 greift man jetzt mithilfe von Zeigern auf die Werte der Variablen zu und verändert diese dauerhaft, da die Funktion schreibend Zugriff auf die Speicheradressen der Variablen hat. Man hätte die Funktion veraendern auch als void deklarieren können, da diese Funktion uns nichts (0) zurückliefert. ©Konstantin Rink 63 | S e i t e C++ Grafikquellen: Designer Iconshock License: Free for personal use (Buy commercial license at Iconshock) Icon set Brilliant Designer Julian Turner License: Creative Commons (Attribution-Share Alike 2.0 Generic) Icon set Still life Designer Alexandre Moore License: GPL Icon set Vista Inspirate Designer Harwen Zhang License: Free for personal use only Icon set Simple http://lipidity.com/wordpress/wp-content/uploads/2007/04/obj-c-header.png by Alexandre Moore | Vista Inspirate Application, Executable, Script, X icon by Oliver Scholtz (and others) ©Konstantin Rink 64 | S e i t e