Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 1-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ Inhaltsverzeichnis Übersicht der Lehrseiten ...............................................................2 1. Grundlagen.....................................................................................3 1.1 Der C++Trainer als IDE..........................................................3 1.2 Das "Hello World"-Programm.................................................4 1.3 Variablen und Bezeichner........................................................5 1.4 Datentypen...............................................................................6 1.5 Einfache Ein-/Ausgabe............................................................7 2. Operatoren und Ausdrücke.............................................................8 2.1 Operatoren und Ausdrücke......................................................8 2.2 Numerische Ausdrücke............................................................9 2.3 Logische Ausdrücke..............................................................10 2.4 Spezielle Ausdrücke...............................................................11 3. Kontrollstrukturen........................................................................12 3.1 Sequenzen (Befehlsfolgen)....................................................12 3.2 Selektion (if-else)..................................................................13 3.3 Mehrfachauswahl (switch)....................................................14 3.4 For-Schleifen.........................................................................15 3.5 Kopfgesteuert (while)............................................................16 3.6 Fußgesteuerte(do-while)........................................................17 4. Funktionen....................................................................................18 4.1 Funktion, Parameter, Prototyp...............................................18 4.2 Die Hauptfunktion.................................................................19 4.3 Rekursionen...........................................................................20 4.4 Funktionsüberladung.............................................................21 5. Arrays, Zeiger und Strings...........................................................22 5.1 Arrays.....................................................................................22 5.2 Zeiger (Pointer)......................................................................23 5.3 Zeichenketten (Strings)..........................................................24 5.4 dynamische Arrays................................................................25 5.5 Sortierung..............................................................................26 6. Referenzen, Strukturen und Unions.............................................27 6.1 Referenzen.............................................................................27 6.2 Strukturen..............................................................................28 6.3 Unions....................................................................................29 7. OOP, Klassen................................................................................30 8. Arbeit mit Dateien........................................................................31 8.1 Textdateien, Filestreams........................................................31 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 2-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ Übersicht der Lehrseiten 1. Grundlagen 5. 11_idecp.rtf Der C++Trainer als IDE 12_hewld.rtf Das "Hello World"-Programm 13_varia.rtf Variablen und Bezeichner 14_datyp.rtf Datentypen 15_easea.rtf Einfache Ein-/Ausgabe Arrays, Zeiger 51_array.rtf 52_point.rtf 53_strng.rtf 54_dynam.rtf 55_sorti.rtf 2. Operatoren und Ausdrücke 21_opera.rtf Operatoren, Rangfolge 22_numau.rtf Numerische Ausdrücke 23_logau.rtf Logische Ausdrücke 24_spzau.rtf Spezielle Ausdrücke 6. Referenzen, Strukturen und Unions 61_refer.rtf Referenzen 62_struc.rtf Strukturen 63_union.rtf Unions 7. 3. Kontrollstrukturen 31_seqnz.rtf Sequenzen(Befehlsfolgen) 32_ifels.rtf Selektion(if-else) 33_switc.rtf Mehrfachauswahl(switch) 34_for__.rtf For-Schleifen 35_while.rtf Kopfgesteuert (while) 36_dowhi.rtf Fussgesteuerte(do-while) Objektorientierte Programmierung 71_class.rtf Klassen 72_erben.rtf Vererbung 73_ovloa.rtf Operatorüberladung 74_virtu.rtf Virtuelle Klassen, Templates 8. Arbeit mit Dateien 81_datei.rtf Textdateien,Filestreams 82_pfleg.rtf Dateipflege 83_start.rtf Dateistart 9. Listen 91_elist.rtf Einfach verkettet 92_dlist.rtf Doppelt verkettet 4. Funktionen 41_funkt.rtf Funktionen 42_main_.rtf Die Hauptfunktion 43_rekur.rtf Rekursionen 44_uelad.rtf Funktionsüberladung und Strings Arrays Zeiger Zeichenketten dynamische Arrays Sortierung Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 3-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 1. Grundlagen 1.1 Der C++Trainer als IDE Der Begriff IDE steht fuer integrated development environment, deutsch: Integrierte SoftwareentwicklungsUmgebung. Eine IDE ist ein Programmsystem, das die für eine effektive Softwareentwicklung notwendigen Programme der C++ -Sprachumgebung und passende Toolprogramme bequem durch den Programmierer ansteuerbar macht. Der C++Trainer ist eine Lern-IDE fuer die Programmiersprache C++. Eine Profi-IDE ist z.B. der Borland C++ Builder. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 4-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 1.2 Das "Hello World"-Programm Das einfachste denkbare C++ Programm wird wie auch in anderen Programmiersprachen mit dem sogenannten "Hello-world-Programm" vorgeführt. Der Hauptteil des Programms wird mit main( ) eingeleitet. Die zwischen den geschweiften folgenden Klammern angeordneten Anweisungen werden nach dem Programmstart ausgeführt. Das Erreichen der zugehörigen schließenden geschweiften Klammer beendet das Programm. Zur Ausgabe des kurzen Textes auf dem Bildschirm kann die C++ -Ausgabefunktion "cout" benutzt werden. C++ ist modularisiert, d.h. nicht alle Funktionen sind ohne zusätzliche Modul-Anforderung erreichbar. Die Bibliotheks-Funktion "cout" erfordert das Einfügen des Headers "iostream.h" mit der Präprozessor-Anweisung #include. Wird diese Einfügung vergessen, ist "cout" eine dem Compiler unbekannte Zeichenfolge. // Th.Cassebaum, 13.9.2003, all rights reserved #include <iostream.h> // Header für cout int main() { cout << "Hello world!"; getchar(); // Warten auf Tasteneingabe return 0; } Der Präprozessor ist ein Programm, das die Quellzeilen, die mit einer Raute # beginnen, schon vor dem Compiler auswertet. #include führt zum Einfügen aller Zeilen einer bliebigen Textdatei anstelle der #include-Zeile. Im Beispiel wird die Textdatei iostream.h eingefügt. Header ( *.h oder *.hpp) sind spezielle C- oder C++ - Quelltextdateien, die C/C++ -Fragmente enthalten, die vom Compiler mit übersetzt werden. Der Header iostream.h ermöglicht beispielsweise den Zugriff auf die E/A-StreamBibliothek ( in der neben cout noch andere E/A-Funktionen enthalten sind ) von C++ . Beispiel: 12_Hewld.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 5-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 1.3 Variablen und Bezeichner Eine Variable in C++ ist ein Datenobjekt mit veränderlichem Wert, das einen Namen und einen Datentyp besitzt und einen Speicherplatz einer festgelegten Länge belegt. Variablen müssen vor ihrer Verwendung für einen bestimmten Datentyp deklariert werden: datentyp Bezeichner [,Bezeichner[,...]]; z.B.: int x, y; Ein Bezeichner in C++ besteht aus einer Folge von Groß-/ Kleinbuchstaben, Ziffern oder der Unterstreichung '_'. Das erste Zeichen darf keine Ziffer sein. Der Bezeichner darf beliebig lang sein, nur 250 Zeichen werden zur Erkennung benutzt (gelten als "signifikant"). Schlüsselwörter der Sprache C++ (z.B. if, int, while, void, ...) dürfen nicht als Bezeichner genutzt werden. Bezeichner identifizieren C++ -Programmelemente (z.B. Variablen, Strukturen, Funktionen, ... ). C++ unterscheidet bei Bezeichnern streng zwischen Groß- und Kleinbuchstaben!! Variablen erhalten durch eine Zuweisung ("Ergibtanweisung") in der Form: <variable_typ1> = <Ausdruck_typ1>; einen Wert. Der Wert errechnet sich durch einen Ausdruck, der von gleichem Datentyp wie die Variable ist oder in diesen automatisch konvertiert werden kann. Die Zuweisung kann schon in der Deklaration erfolgen. void main(void) { int var,VAR,Meine_Lieblingsvariable = 0; var = -3; VAR = 4; Meine_Lieblingsvariable = var + VAR; cout << Meine_Lieblingsvariable; getchar(); } Beispiel: 13_Varia.cpp Im Beispiel werden drei Variablen im ganzzahligen Datentyp (int) deklariert. Die Variable "Meine_Lieblingsvariable" speichert nach der Addition var + VAR den Wert 1. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 6-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 1.4 Datentypen Typbezeichner in C++ sind z.B.: Bytes Typbezeichner geeignet für 10 8 4 4 4 2 4 1 ? 1 long double double float int long short int unsigned int char string bool Wertkonstante sehr genaue reelle Zahlen (18 Stellen) reelle Zahlen (15 Stellen) wenig genaue relle Zahlen (nur 7 Stellen) ganze Zahlen (-2.147.483.648...2.147.483.647) ganze Zahlen (-2.147.483.648...2.147.483.647) ganze Zahlen (-32.768...32.767) natürliche Zahlen (0...4.294.967.295) Zeichen (0...255) Zeichenketten logische Werte (true oder false) void main(void) { int x,y; bool a; double b; string s; x = 0xff; y = -34; b = 1.2-02; s = "\nHallo!"; c = 'v'; a = true; } 123456.789012345678 -0.123456789012345 0.2E02 -0x25 -0xFFFF +321 12 'a' "Zeichen abc" true char c; Zeichenketten werden in Anführungsstrichen eingeschlossen (z.B.: "Kette"). Für Ausgaben können spezielle Zeichenfolgen eine Steuerung (ESC-Sequenzen) veranlassen. ESC-Sequenzen sind z.B.: \n nächste Zeile einstellen \t Tabulatorabstand setzen \a Piepsignal ausgeben \“ Anführungszeichen innerhalb einer Zeichenkette setzen Beispiel: 14_Datyp.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 7-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 1.5 Einfache Ein-/Ausgabe Tastatureingaben werden mit cin >> eingeleitet und Bildschirmausgaben mit cout << . Mit cout << wird eine für den Bediener sichtbare Bildschirmdarstellung erzeugt. Als Ziel für Eingaben mit Hilfe von cin >> müssen Variablen vereinbart werden ( im Beispiel: s und t ). Die Variablen müssen mit einem Typkennzeichner definiert werden ( im Beispiel: double ). double s,t; cout << "\"Programm zur Geschwindigkeitsberechnung\"\n"; cout << "\nWeg s [in m] : "; cin >> s; cout << "Zeit t [in s] : "; cin >> t; cout << "\nGeschwindigkeit : " << s/t << " m/s" << " oder " << s/t * 3.6 << " km/h"; Beispiel: 15_easea_1.cpp Einzelzeichen (character) werden zur Ausgabe in Apostrophen eingeschlossen (z.B.: '$') und bei Eingaben in Variablen vom Datentyp char gespeichert. Zeichenketten (string) werden zur Ausgabe in Anführungsstrichen eingeschlossen (z.B.: "Kette") und bei Eingaben in Variablen vom Datentyp string gespeichert. Für Ausgaben können spezielle Zeichenfolgen innerhalb der Anführungszeichen einer auszugebenden Zeichenkette eine besondere Steuerung veranlassen. ESC-Sequenzen (Steuerfolgen) sind z.B.: ☞ \n nächste Zeile \t Tabulatorabstand \a Piepsignal \" Anführungsstriche Aus dem Header "iomanip.h" können Manipulatoren zur Ausgabeformatierung genutzt werden: 5 setw(n) left | right fixed scientific int x=12; Feldbreite auf n Zeichen setzen setfill(z) linksbündig | rechtsbündig dec | oct | hex Gleitkommadarstellung uppercase Exponentialdarstellung setprecision(n) cout<<"x = "<<setfill('.')<<setw(6)<<hex<<right<<x; Festlegung des Füllzeichens (z.B. setfill('_') ) Umwandlung in dec | oct | hex Kleinbuchstabendarstellung Feldbreite auf n Zeichen setzen // Es wird ausgegeben: x = .....c Beispiel: 15_easea_2.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 8-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 2. Operatoren und Ausdrücke 2.1 Operatoren und Ausdrücke Operatoren beziehen sich auf einen oder zwei Operanden und liefern ein operationstypisches Resultat. Größen (z.B. Variablen, Werte, ...) der Sprache C++, die mit Operanden einfach oder vielfach verknüpft wurden, nennt man Ausdruck. Die Operanden und das Operationsresultat besitzen einen operationsabhängigen Datentyp. Die Einteilung der Operatoren in Gruppen geschieht in Abhängig der nutzbaren Datentypen. Wichtige Operatoren: numerische Operatoren ++ (Inkrement) -- (Dekrement) * (Multiplikation) / (Division) + (Addition) - (Subtraktion) % (modulo / Rest der Ganzzahldivition) logische Operatoren ! (Negation) > (größer?) >= (größer gleich?) < (kleiner?) <= (kleiner gleich?) == (identisch/gleich?) != (ungleich/verschieden?) && (logisches "UND") || (logisches "ODER") bitweise Operatoren ~ (Komplement) >> (Rightshift) << (Leftshift) & (AND) ^ (XOR) | (OR) Zuweisungsoperatoren =(zuweisen/ergibt) +=(plus und zuweisen/ x+=3 → x=x+3) -=(minus u. zuweisen) *=(mal u. Zuweisen)../=(durch u. zuweisen) &=(und u. zuweisen) %=(modulo u. zuweisen) Operatoren sind in eine Rangfolge geordnet, die bedeutet, dass innerhalb eines Ausdrucks zunächst die vorrangigen Operatoren durch Operationen realisiert werden. Ausdrücke mit Operatoren können mit Rundklammern geklammert werden, um die Operatoren in der Klammer im Rang zu bevorzugen. ( z.B. 12/2+4 ergibt 10, aber 12/(2+4) = 2) Ohne gesetzte Klammern werden gleichrangige Operatoren von links nach rechts abgearbeitet. int x = 2,y = 11; x += 3 << 1; cout << x << endl; if(--y%10) cout << "True"; else cout << "False"; Beispiel: 21_opera.cpp // Ausgabe: 8 // Ausgabe: False Rangfolge aller Operatoren ( in [ .. ] sind gleichrangig) von links nach rechts absteigend: [ ( ) [ ] -> :: . ] [ ! ~ ++ -- sizeof new delete typeid (typumformer)] [ . * -> * ] [ * / % ] [ + - ] [ << >> ] [ < <= > >= ] [ == != ] [ & ] [ ^ ] [ | ] [ && ] [ || ] [ ?: ] [ = + = - = *= /= %= >>= <<= &= ^= ] Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 9-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 2.2 Numerische Ausdrücke Numerische Ausdrücke sind alle C++ Bestandteile, die einen Zahlenwert besitzen. Wichtige Beispiele für numerische Ausdrücke sind: (1) (2) (3) (4) (5) Logische Werte ( true besitzt den Wert 1, false besitzt den Wert 0 ), Zahlenwerte ( Konstanten, Zahlenliterale, ganzzahlig: 2, -4, 0xa, 027,... reell: 0., .23, 3e4, -3.2e-3,... ), C++ Größen (Variablen, Funktionsrufe, ...) mit numerischem Datentyp ( unsigned int, int, float, double, ... ) Werte, die mit Operatoren verknüpft sind und ein numerisches Resultat liefern. (z.B.: Verknüpfungen 3>7 0, 2!=3 1, 5/3 1, 7&12 4, ~1 -2, 5%3 2, 5e1/5 10.), Logische Ausdrücke, die mit logischen Operatoren verknüpft sind. (z.B.: 0 && true false, (2>3) || (0!=1) true, !(7==3) && 5 true), Beispiele für numerische Ausdrücke mit numerischem Ergebniswert: cout << "3 * 2 = " << 3*2; // 6 Beispiel: 22_numau.cpp cout << "\n3 / 2 = " << 3/2; // 1 cout << "\n3 / 2. = " << 3/2.; // 1.5 cout << "\ntrue = " << true; // 1 cout << "\nfalse = " << false; // 0 cout << "\n0xa = " << 0xa; // 10 cout << "\n0xa = " << hex << 0xa; // a cout << "\n027 = " << dec << 027; // 23 cout << "\n027 = " << oct << 027; // 27 int i=7&12; cout << dec << "\n7&12 = " << i; // 4 (Bit-Operator logisch UND) cout << "\n5%3 = " << 5%3; // 2 cout << "\n5e1/5 = " << 5e1/5; // 10 char s='n'; cout << "(s=='j')= " << (s=='j'); // 0 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 10-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 2.3 Logische Ausdrücke Logische Ausdrücke sind alle C++ Bestandteile, die einen Wert True oder False besitzen. Wichtige Beispiele für logische Ausdrücke sind: (1) (2) (3) (4) (5) Logische Werte (Die Konstanten true (1) oder false (0) ), Zahlenwerte (Ein Wert = 0 gilt per Definition false, alle Werte ungleich 0 sind true), C++Größen (Variablen, Funktionsrufe, ...) mit Datentyp bool (besitzen einen logischen Wert), Werte, die mit Operatoren verknüpft sind und ein logisches Resultat liefern (z.B.: Verknüpfungen 3>7 -> false, 2!=3 ->true, 7==3 ->false, "Hans">="Lutz" -> false), Logische Ausdrücke, die mit logischen Operatoren verknüpft sind (z.B.: 0 && true -> false, (2>3) || (0!=1) ->true, !(7==3) && 5 -> true). Beispiele für logische Ausdrücke mit logischem Ergebniswert: int i = 2; bool a = false; double x = 0.0; if (a) cout << "a ist true"; else cout << "a ist false"; if (i) cout << "i ist true"; else cout << "i ist false"; if (x) cout << "x ist true"; else cout << "x ist false"; if (i-2) cout << "i-2 ist true"; else cout << "i-1ist false"; if (!a) cout << "!a ist true"; else cout << "!a ist false"; if ((i==2)||(i==3)) cout << "(i==2)||(i==3) ist true"; else cout << "(i==2)||(i==3) ist false"; cout << endl; cout << endl; cout << endl; cout << endl; cout << endl; cout << endl; // true Beispiel: 23_logau.cpp // false // true // false // false // true Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 11-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 2.4 Spezielle Ausdrücke Die Ausdrucksbildung für einige besonders interessante C++ Operatoren wird betrachtet: (1) Der Fragezeichenoperator <log.Ausdruck> ? <Wert für true> : <Wert für false> wird für eine Wertbestimmung abhängig vom Wert eines logischen Ausdrucks verwendet. int y = 11,x = y>10?1:2; Beispiel: 24_spzau.cpp cout << "x = " << x; // Ausgabe: x = 1 (2) Der Kommaoperator <Anweisung|Ausdruck> , <Anweisung|Ausdruck> [[, <Anweisung|Ausdruck>]...] wird für zur Bildung einer Anweisungsfolge verwendet. Der Wert des Kommaausdrucks wird durch den Wert des Ausdrucks nach dem letzten Komma bestimmt. Die Abarbeitung erfolgt von links nach rechts. y = 15; x = ( y=y-5, 50/y ); cout << "\nx = " << x; // Ausgabe: x = 5 (3) Der Cast-Operator (<Datentyp>) <Ausdruck> erzwingt die Umwandlung eines Ausdruckswertes in einen Wert des angegebenen Datentyps. double z; z = (double) 10/3; cout << "\nz = " << z; // Ausgabe: z = 3.3333 (4) Die Bit-Operatoren (and) &, (or) |, (xor) ^, (Komplement) ~ verknüpfen zwei Ausdrücke Bit für Bit nach der gewählten Logik: x = 15&19; cout << "\nx = " << x; // Ausgabe: x = 3 x = ~1; cout << "\nx = " << x; // Ausgabe: x = -2 (5) Der Längen-Operator sizeof <C++ Größe> bestimmt den Speicherbedarf der Größe (z.B. Variable) in Byte und gibt diese ganzzahlig zurück : cout << "\nLänge int\t: " << sizeof x << " Bytes"; cout << "\nLänge double\t: " << sizeof z << " Bytes"; Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 12-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3. Kontrollstrukturen 3.1 Sequenzen (Befehlsfolgen) Sequenzen sind Programmstrukturen, die eine Folge von ausführbaren C++ Anweisungen enthalten. In C++ werden die Anweisungen grundsätzlich mit einem Semikolon (nicht mit dem Zeilenende!!) abgeschlossen. Anweisungen werden in den Reihenfolgen "von links nach rechts " und "von oben nach unten" ( ) abgearbeitet. Sequenzen in der Struktogrammdarstellung Mit der dargestellten Zeichnung wird bestimmt, dass der Block A vor dem Block B bearbeitet werden soll. Ausgabe der Eingabeaufforderung am Bildschirm Eingabe von Tastatur in der Variablen s speichern Ausgabe der Eingabeaufforderung am Bildschirm Eingabe von Tastatur in der Variablen t speichern Ausgabe des errechneten Ergebnisses am Bildschirm dito double s,t; cout << "Programm zur Geschwindigkeitsberechnung\n"; cout << "\nWeg s [in m] : "; cin >> s; cout << "Zeit t [in s] : "; cin >> t; cout << "\nGeschwindigkeit : " << s/t << " m/s" << " oder " << s/t * 3.6 << " km/h"; Beispiel: 31_Seqnz Mit cout << wird eine für den Bediener sichtbare Programmführung erzeugt. Als Ziel für Eingaben mit Hilfe von cin >> müssen Variablen vereinbart werden ( im Beispiel: s und t ). Die Variablen müssen mit einem Typkennzeichner definiert werden ( im Beispiel: double ) Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 13-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3.2 Selektion (if-else) Selektionen sind Programmstrukturen, die eine Verzweigung abhängig von logischen Ausdrücken enthalten. Eine einfache Selektion wird mit if ( log. Ausdruck ) Anweisung ; konstruiert. Eine Selektion mit else-Zweig wird mit if ( log. Ausdruck ) Anweisung im True-Fall; else Anweisung im False-Fall; bool a; char s; cout << "Ist es hell draussen? [j/n] : "; cin >> s; if(s=='j') cout << "\nGuten Tag!"; else cout << "\nGute Nacht!"; a=(s=='j'); if(a) { cout << "\nDie Antwort war: Ja!"; cout << "\nWas fuer eine Freude!"; } konstruiert. Beispiel: 32_ifels.cpp Nach "if(...) " oder "else" wird immer nur genau eine Anweisung bedingt realisiert (d.h. abhängig von dem logischen Ausdruck in der Klammer). Mehrere Anweisungen können durch Schaffung von Mehrfachanweisungen mit { ... } geklammert und damit gemeinsam bedingt ausgeführt werden. Sollen mehrere logische Ausdrücke geprüft werden dürfen die logischen Verknüpfungsoperatoren && (and), || (or), ! (not) genutzt werden. Vorrangregeln beachten! Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 14-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3.3 Mehrfachauswahl (switch) Eine Mehrfachauswahl ist eine Programmstruktur, die endlich viele Verzweigungen abhängig vom Wert eines ganzzahligen Ausdrucks enthalten. Sie wird konstruiert mit: switch ( <ganzzahliger Ausdruck> ) { case <ganzzahliger Wert>: Anweisung ;[ break ;] [ [ case <ganzzahliger Wert>: Anweisung ;[ break ;]] ...] [ default: Anweisung ;] } Die Anweisung nach einem case wird ausgeführt, wenn der in switch geklammerte ganzzahlige Ausdruck identisch mit dem ganzzahligen Wert des case ist. Danach werden alle folgenden Anweisungen bis zu der den switch-Block abschließenden geschweiften Klammer ausgeführt. Eine eingefügte break-Anweisung beendet diese Ausführung schon vorher. char s = 2; switch(s) { case 0: case 1: case 'c'-'a': case 3: case 4: case 'a': default: } Beispiel: 33_switc.cpp cout cout cout cout cout cout cout cout << << << << << << << << "\n0 "\n1 "\n2 "\n3 "\n3 "\n4 "\n5 "\nd kommt nicht"; kommt nicht"; kommt"; kommt"; kommt"; kommt"; break; kommt nicht"; kommt nicht"; Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 15-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3.4 For-Schleifen Die For-Anweisung konstruiert mit drei Parametern eine kopfgesteuerte Schleife (abweisende Schleife). for ( Anweisung 1 ; <log. Ausdruck> ; Anweisung 2 ) Anweisung 3 ; Zaehlschleife mit for v - Zaehlvariable (ganzzahlig) a - Anfangswert e - Endwert s - Schrittweite (1) Anweisung 1 wird zu Beginn genau einmal ausgeführt. (2) wenn der log. Ausdruck zum Schleifendurchlaufbeginn false ist, endet die Bearbeitung der for-Schleife sofort. (3) wenn der log. Ausdruck zum Schleifendurchlaufbeginn true ist, wird Anweisung 3 ausgeführt. (4) Nach dem Benden der Anweisung 3 (ohne break) wird Anweisung 2 ausgeführt. (5) Wenn auch Anweisung 2 kein break enthält beginnt ein neuer Schleifendurchlauf mit (2). int i, sum=0; for( i=1 ; i<=100 ; i++) sum += i; cout << "1+2+...+100 = " << sum; // Summe aller Zahlen von 1 bis 100 // v=i, a=1, e=100, s=1 // Ergebnisausgabe: 1+2+...+100 = 5050 Beispiel: 34_for__.cpp Die Anweisung 3 wird in den meisten Fällen als eine in geschweifte Klammern gesetzte Mehrfachanweisung auf gebaut. So besteht der Schleifenkern aus beliebig vielen Anweisungen, die wiederholt ausgeführt werden. Für die Anweisung 2 kann zum Einbau mehrerer Anweisungen an das Schleifenende auch mit dem Kommaoperator gearbeitet werden: for( i=1 ; i<=100 ; i++, k++, m+=2) sum += i; // Die Variablen k und m zählen mit ( m doppelt!) Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 16-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3.5 Kopfgesteuert (while) Die while-Anweisung konstruiert mit einem Parameter eine kopfgesteuerte Schleife (abweisende Schleife). while ( <log. Ausdruck> ) Anweisung ; (1) wenn der log. Ausdruck zum Schleifendurchlaufbeginn false ist, endet die Bearbeitung der Schleife sofort. (2) wenn der log. Ausdruck zum Schleifendurchlaufbeginn true ist, wird die Anweisung ausgeführt. (3) Nach dem Beenden der Anweisung (ohne break) beginnt ein neuer Schleifendurchlauf mit (1). #include <conio.h> // conio-Header für kbhit-Funktion int z=0; // Zählvariable Beispiel: 35_while.cpp while( ! kbhit() ) cout << z++ << " "; // Zählen bis Tastendruck, Ausgabe: 1 2 3... Die Anweisung wird in den meisten Fällen als eine in geschweifte Klammern gesetzte Mehrfachanweisung aufgebaut. So besteht der Schleifenkern aus beliebig vielen Anweisungen, die wiederholt ausgeführt werden. Die Schleife kann durch eine in eine Mehrfachanweisung eingefügte break, return n oder exit(n) -Anweisung abgebrochen werden. Im Normalfall wird diese Anweisung selektiv in einer if-Anweisung aufgerufen. z=1; while( z%3 ) { cout << "Gib eine Zahl ein [0 für Exit] : "; cin >> z; if( !z ) return 1; // Ende durch Eingabe von 0 } if (z) cout << z << " ist durch 3 teilbar!\n"; // reguläres Ende bei z>0 und z%3 == 0 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 17-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 3.6 Fußgesteuerte(do-while) Die do-while-Anweisung konstruiert mit einem Parameter eine fußgesteuerte Schleife (nicht abweisende Schleife). do Anweisung ; while ( <log. Ausdruck> ); (1) Ausführung der Anweisung (2) Nach dem Beenden der Anweisung (ohne break) wird der Wert des log.Ausdrucks ermittelt (3) wenn der Wert des log. Ausdruck false ist, endet die Bearbeitung der Schleife sofort. (4) wenn der Wert des log. Ausdruck true ist, beginnt ein neuer Schleifendurchlauf mit (1). int x; do { cout << "x: "; cin >> x; } while (x<=0); do { if (!(x%2)) cout << x << " "; } while (--x>0); // Ausgabe aller geraden Zahlen, // beginnend mit einer eingege// benen Zahl x (rückwärts bis 1) Beispiel: 36_dowhi.cpp Die Anweisung wird in den meisten Fällen als eine in geschweifte Klammern gesetzte Mehrfachanweisung aufgebaut. So besteht der Schleifenkern aus beliebig vielen Anweisungen, die wiederholt ausgeführt werden. Die Mehrfachanweisung kann durch eine continue-Anweisung abgebrochen werden. Die Schleife wird danach sofort mit der Überprüfung des logischen Ausdrucks fortgesetzt und beginnt im true-Fall erneut die Anweisung abzuarbeiten. Die Anwendung der do-while-Schleife sollte in den Fällen angewendet, wenn der erste Schleifendurchlauf in jedem Fall durchgeführt werden soll. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 18-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 4. Funktionen 4.1 Funktion, Parameter, Prototyp Die wesentlichsten ausführbaren Programmteile in C++ sind Funktionen, die von anderen (rufenden) Funktionen gestartet werden. Eine Funktion kann mit Hilfe von Parametern Steuerinformation von der rufenden (übergeordeneten) Funktion übernehmen und mit Hilfe eines Rückgabewertes Resultate an diese Funktion zurückgeben. Allgemein wird eine Funktion wie folgt definiert: <Datentyp der Funktion> <Funktionsname> ( [formaler Parameter 1[ ,formaler Parameter2[ ,...] ] ] ) { <Funktionskörper> [ return <Funktionswert im Datentyp der Funktion>; ] // nur wenn der Datentyp der Funktion nicht void ist } Die "formalen" Parameter in der Funktionsdefinition werden immer mit einem Datentyp und einem Namen definiert. Der Funktionskörper enthält die beim Funktionsaufruf auszuführenden Anweisungen, die die Parameter nutzen dürfen. Ist die Funktion nicht vom Datentyp void (steht für den "leer"), so gibt die Funktion mit der return-Anweisung einen datentypgerechten Funktionswert an die aufrufende Funktion zurück. Kennt eine Funktion den Namen einer anderen Funktion, so kann sie diese mit einem Funktionsaufruf starten. Im Funktionsaufruf werden die formalen Parameter durch aktuelle Parameter ersetzt. Die aktuelle Parameterliste des Funktionsaufrufs muss in Anzahl und Datentypen vollständig mit der formalen Parameterliste übereinstimmen. <Funktionsname> ( [aktueller Parameter 1[ ,aktueller Parameter2[ ,...] ] ] ); Eine im Quelltext später definierte Funktion ist in vorherigen Zeilen noch nicht bekannt. Ohne den Definitionsstandort im Quelltext zu ändern, kann man die Funktion schon mit einer Prototypzeile am Quelltextbeginn bekannt machen. Diese Zeile ist identisch mit der erste Zeile der Funktionsdefinition, die anstelle des Funktionskörpers nur ein Semikolon enthält. string Multistring(string s, int r); void main(void) { cout << Multistring("Tick",5); getchar(); } string Multistring(string s, int r) { while(r--) s+=s; return s; } // Prototypzeile Beispiel: 41_funkt.cpp // Funktionsaufruf // Preisfrage: Wie oft tickt es? // Funktionsdefinition Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 19-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 4.2 Die Hauptfunktion Ein C++ Programm wird mit Hilfe von Funktionen konstruiert, d.h. die wesentlichsten ausführbaren Programmteile sind Funktionen, die von anderen (aufrufenden) Funktionen gestartet werden. Der Start des gesamten Programmes wird vom Betriebssystem (z.B. in Windows durch Angabe des Namens der EXE-Datei) realisiert. Im C++ Programm startet danach zunächst die main-Funktion, die Hauptfunktion des Programmes. Wie jede andere Funktion kann sie Parameter von der startenden Funktion empfangen und einen Ergebniswert zurückgeben. Da die main-Funktion vom Betriebssystem gestartet wird, empfängt sie Kommandozeilen-Parameter von der Startzeile und gibt üblicherweise einen ganzzahligen Ergebniscode an das Betriebssystem zurück (z.B. 0 für erfolgreiche und 1 für erfolglose Abarbeitung). int main( int argc, char* argv[] ) // Argumentanzahl/ Argumente { // Programmzeilen getchar(); // Warten auf Tasteneingabe vor Programmende return 0; // Rückgabe des Erfolgscodes 0 und Funktion beenden } Angenommen, das gezeigte Programm heißt main1.exe und wird mit der Kommandozeile "main1.exe Hans Lisa" gestartet. Dann gilt argc=3 (3 Parameter) und argv[0]="C:\TEMP\CPPTRAIN\MAIN1.EXE", argv[1]="Hans", argv[2]="Lisa". In einer BAT-Kommandodatei kann der Rückkehrcode 0 (return 0;) z.B. in der Zeile "if errorlevel 1 goto error" ausgewertet werden. Sollten weder Rückkehrcodes noch Argumente beim Programmstart verwendet, so könnte die "return 0"-Zeile weggelassen werden und die erste Zeile der main-Funktion wie folgt aussehen: void main(void) Beispiel: 42_main_1 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 20-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 4.3 Rekursionen Kennt eine Funktion den Namen einer anderen Funktion, so kann sie diese mit einem Funktionsaufruf starten. Jede Funktion in C++ kennt sich selbst und kann sich deshalb auch selbst rufen. Gemeint ist, daß die Funktionsdefinition ihren eigenen Funktionsnamen für einen Funktionsaufruf in einer eigenen Definitionszeile enthält. z.B.: string Multistring(string s, int r) { return r?Multistring(s+s,r-1):s; } void main(void) { cout << Multistring("Tick",5); getchar(); } // Funktionsdefinition Beispiel: 43_rekur_1.cpp // Funktionsaufruf // Preisfrage: Wie oft tickt es? Die Funktion Multistring() sieht hier anders aus, als die rekursionsfreie Funktion im Kapitel 4.1. Die Rekursion arbeitet bei näherem Betrachten wie eine Schleife, deren Abbuch durch einen logischen Ausdruck in der Funktionsdefinition erklärt wird. Im obigen Beispiel führt r==false zur Rückgabe des Strings s, was die Rekursion beendet. int fak(int x) // Funktionsdefinition { return x?fak(x-1)*x:1; } Beispiel: 43_rekur_2.cpp void main(void) { cout << fak(5); // Funktionsaufruf getchar(); } Die Funktion fak() errechnet eine bekannte mathematische Funktion in nicht zu überbietenden Einfachheit. Es gibt insbesondere bei den sogenannten "divide and conqeur"-Verfahren Sortier-, Such- und Ordnungsalgorithmen, die äußerst effektiv (gemeint ist die Schnelligkeit) gerade wegen der rekursiven Lösung sind. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 21-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 4.4 Funktionsüberladung Wichtige äußere Eigenschaften einer Funktion sind die Anzahl, Reihenfolge und die einzelnen Datentypen der Parameter. Aus praktischen Gründen stellt man sich die Frage, ob es nicht vernünftig ist, unterschiedliche Parameterlisten für den gleichen Funktionsnamen zuzulassen. In C++ ist dies mit Hilfe des Overloading möglich. Der Begriff Overloading bezeichnet die Fähigkeit von C++, anhand der Parameterliste einen von mehreren existierenden Funktionsdefinitionen auszuwählen. double kreis(double radius) { return M_PI*radius*radius; } // Funktionsdefinition 1 double kreis(char* radius) { double rad=atof(radius); return M_PI*rad*rad; } // Funktionsdefinition 2 Beispiel 1: 44_uelad_1.cpp void main(void) { double r=3.1; char* rc="3.1"; cout << kreis(r) << endl; // Funktionsaufruf cout << kreis(rc); getchar(); } Die Funktion kreis() ist im Beispiel zweimal definiert. Die erste Definition benutzt einen double-Parameter und die zweite Definition eine char*-Parameter. Im den nachfolgenden Aufrufen erkennt C++ automatisch, welche der beiden Definitionen zur Anwendung kommt. Im zweiten Beispielprogramm wird die Umwandlung von Groß- in Kleinbuchstaben mit drei unterschiedlichen Funktionsüberladungen organisiert. Beispiel 2: 44_uelad_2.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 22-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 5. Arrays, Zeiger und Strings 5.1 Arrays Arrays erlauben es, große Datenmengen gleichen Datentyps zu definieren und zu verwalten. Ein Array a[n] besteht aus den n Arrayelementen gleichen Datentyps: a[0], a[1], ..., a[n-1]. Statischer Speicherplatz wird durch die Definition: <Datentyp> <Arrayname> [ <Elementanzahl> ] [ = {<wert_el_0>,<wert_el_1>,...,<wert_el_n-1>} ] ; Die Arraydefinitionen int a[5]={2,1,5,3,4}; führen zu folgendem Speicheraufbau: Das Array a[2][3] wird zweidimensional genannt. a[2][3]={{1,5,10},{4,2,3}} a[2]=5 a[1][2]=3 Die einzelnen Arrayelemente sind im Speicher auch beimehrdimensionalen Arrays in einer Reihe gespeichert. Die Vorstellung als Tabelle oder Matrix ist aber zur theoretischen Vorstellung der Werte recht praktikabel. Summation der Elemente einer 3,4 Matrix: int i,k; double m[3][4],s=0; for(i=0 ; i<3 ; i++) for(k=0 ; k<4 ; k++) s += m[i][k]; cout << "Summe: " << s; Füllung eines LottoTipp-Arrays mit Zufallswerten int i,k,a[10][6]; randomize(); Beispiel: for(i=0 ; i<10 ; i++) 51_array.cpp for(k=0 ; k<6 ; k++) a[i][k]=random(49)+1; Zufallswerte lassen sich mit den Funktionen randomize(), random() und rand() automatisch entwickeln. randomize() Stellt einen zufälligen Start zum Finden der Werte ein. random(n) Liefert einen ganzzahligen Zufallswert x mit 0 <= x < n, d.h. random(2) liefert nur 0 oder 1. rand() Liefert einen ganzzahligen Zufallswert x mit 0 <= x < 65536. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 23-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 5.2 Zeiger (Pointer) Zeiger(Pointer) sind C++Größen, die Adressen von Variablen, Arrays,... unter einem eigenen Namen speichern. Der Adressoperator * kennzeichnet eine zu definierende Größe als Zeiger. Der Operator & ruft die Adresse einer C++ Größe auf. Adressen werden bei Ausgaben standardmäßig hexadezimal angezeigt. Beispiel: 52_point_0 int *z_zahl, zahl, *z_a, a[4]={1,2,3,4}; z_zahl = &zahl; // Lies: z_zahl gleich Adresse von Zahl *z_zahl = 4; // Lies: Inhalt von z_zahl gleich 4 cout << z_zahl; // Ausgabe der Adresse von Zahl cout << &zahl; // dito cout << *z_zahl; // Ausgabe der Zahl (Inhalt der Adresse) z_a = &a[0]; // Adresse des 1. Arrayelements z_a = a; // dito cout << z_a[2]; // Ausgabe des 3.Datenelementes von a cout << *z_a++; cout << ++*z_a; // Zeigerarithmetik z_a = a; cout << z_a++; cout << ++z_a; Wird ein Pointer auf das Startelement eines Arrays gleichen Typs gesetzt, so kann mit diesem Pointer in der Syntax von Arrays genutzt werden (z.B. z_a[2] ). Die Addition oder Subtraktion von Zeigern mit ganzzahligen Größen wird Zeigerarithmetik genannt. Die gespeicherte Zeigeradresse wird dabei um des n-fache der Länge des Datentyps des Zeigers verändert. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 24-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 5.3 Zeichenketten (Strings) Strings sind Ketten von Zeichen, die gemeinsam verwaltbar sind. Für einzelne Zeichen kommt der Datentyp char zur Anwendung. (z.B. char z='A';) Die Idee der älteren Sprache C bestand darin, Strings in Arrays vom Typ char zu speichern. Um die Länge des Strings flexibel zu gestalten, wurde das Byte(0000 0000) als Null-Byte (Terminatorzeichen) benannt, das im Arrayelement nach dem letzten gültigen Zeichen des Strings gespeichert wird. Nullterminierter String Beispiel: 53_strng_1.cpp char s[7]; strcpy(s,"Turm"); cout<<"Text:"<<s; Die Definition char s[ ] ="Turm"; vereinbart einen String der Länge 4 inklusive Null-Byte in vereinfachter Form. Für die Einhaltung der Terminierung sind die strxxx-Funktionen zu nutzen. z.B. strcpy(x,"Otto"); anstelle von x="Otto"; Eine modernere Stringnutzung gestattet der Datentyp string. Eine String-Größe kann im Borland C++ Compiler 5.5 bis zu 4.294.967.281 Zeichen speichern. (Beispiel: 53_strng_3.cpp). Der Speicherplatzbedarf wird dynamisch angepaßt, d.h. die größte bisherige Verwendung bleibt als Speicherkapazität erhalten. string s; s = "Fenster"; s+="kreuz"; cout << s << " " << s.length(); // Ausgabe: Fensterkreuz 12 Es gibt ein große Zahl von interessanten String-Funktionen und -Operatoren. So können die bekannten Operatoren wie "=" und "+=" zur Zuweisung und "+" zur Verkettung zweier Zeichenketten verwendet werden. string <stri_a>.substr(s, p) int <stri_a>.compare(s2) string <stri_a>.append(s2) char* <stri_a>.c_str( ) string <stri_a>.insert( i, s2) int <stri_a>.max_size( ) int <stri_a>.capacity( ) int <stri_a>.length( ) int <stri_a>.resize( n [,c] ) int <stri_a>.reserve(n) liefert einen Teilstring von stri_a, der in der Länge s ab Position p beginnt. vergleicht stri_a mit s2, für stri_a<s2 : <0, stri_a==s2 : =0, stri_a>s2 : >0 hängt String s2 an stri_a an gibt stri_a nullterminiert zurück fügt ab i-Position s2 in stri_a ein. Beispiel: 53_strng_2.cpp liefert die Maximalkapazität liefert die Längenkapazität liefert die akt. Länge von stri_a setzt die Länge des Strings auf n, füllt bei Verlängerung mit dem Zeichen c auf. setzt die Kapazität des Strings auf n Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 25-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 5.4 dynamische Arrays Statische Arrays, deren Größe schon zur Programmentwicklungszeit bestimmt werden muß, erlauben es, große Datenmengen zu definieren und zu verwalten. Es besteht der Wunsch, die Größe des vereinbarten Speicherplatzes erst während der Laufzeit zu verändern. Dazu ist es erforderlich, Speicherplatz direkt vom Betriebssystem abzufordern. Das Betriebssystem gibt die Startadresse des zugeordneten Speicherplatzes im Erfolgsfall zurück. Ein solcher Bereich wird Heap oder dynamisches Array genannt. In C++ leistet der Operator new die Auslösung einer Speicherplatzanforderung. Falls die angeforderte Speicherplatzmenge nicht mehr verfügbar ist, wird der Wert 0 zurückgegeben. Der Aufruf benötigt zur Wertrückgabe einen typgerechten Pointer: <Pointer im Datentyp> = new <Datentyp> [ n ] ; Es wird Speicherplatz für n Arrayelemente im angegebenen Datentyp vom Betriebssystem angefordert. Der Pointer enthält 0 (bei Nichterfolg) oder die Adresse des bereitgestellten Speicherbereichs. int *ip,i; // Pointervereinbarung randomize(); ip = new int[10]; // Speicheranforderung für den Heap if(!ip) // Erfolgreich? { cout << "\nSpeicherfehler!"; return 1; } Beispiel: 54_dynam.cpp for(i=0 ; i<10 ; i++) { ip[i] = random(10) + 1; cout << "\nElement " << i << " = " << ip[i]; } delete ip; // Freigabe des Heaps Der angeforderte Speicherplatz kann mit delete <pointer>; wieder freigegeben werden. Dadurch wird erreicht, daß der zuvor angeforderte Speicherbereich wieder für andere Zwecke zur Verfügung steht. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 26-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 5.5 Sortierung Eines der Grundprobleme der Algorithmierung ist das der Sortierung von Arrays. Voraussetzung für eine Sortierung ist das Vorhandensein einer Norm für die Größeneinordnung der Elemente des Arrays. Somit muß die Frage, ob gilt: Norm(Element_1) > Norm(Element_2) eindeutig entscheidbar sein. Es gibt viele verschiedene Sortierverfahren, die hinsichtlich ihrer Komplexität unterschiedlich zu bewerten sind. Hier werden zwei Arten mit sehr verschiedener Qualität dargestellt: 1. Quicksort (divide and conquer) #define gr 20 unsigned int gr, T[gr]; void main(void) { quicksort(0,gr-1); } void quicksort(int l,int r) { int wert,t,i=l,j=r; wert=T[(l+r)/2]; do { while(T[i]<wert) i++; while(wert<T[j]) j--; if(i<=j) { t=T[i]; T[i++]=T[j]; T[j--]=t; } } while(i<=j); if(l<j) quicksort(l,j); if(i<r) quicksort(i,r); } 2. Insertion Sort #define gr 20 unsigned int mi,i,j,gr,T[gr]; void main(void) { for( i=0;i<=gr;i++); mi=T[i]; j=i; while((T[j-1]>mi) && (j>1)) { T[j]=T[j-1]; j=j-1; } T[j]=mi; } Beispiel (enthält weitere Verfahren): 55_sorti.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 27-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 6. Referenzen, Strukturen und Unions 6.1 Referenzen An untergeordnete Funktionen können zwei unterschiedliche Parameterübergabetypen übergeben werden: 1. call by value Der Parameter wird als Wert übergeben. Die Veränderung des Wertes kann vom rufenden Programm nicht ausgewertet werden. Ergebnisse können nur als Rückgabewert übergeben werden. 2. call by reference Der Parameter wird als Pointer oder als Referenz übergeben. Die Veränderung des Parameters ist vom rufenden Programm erkennbar. Ein Rückgabewert braucht nicht zwingend übergeben werden, wenn der Referenzparameter zur Ergebnisübergabe genutzt wird. Referenzen verweisen wie Zeiger(Pointer) auf Objekte, können jedoch nur einmal mit einem Objekt initialisiert werden und danach nicht mehr auf andere Objekte umgelenkt werden. Weiter entfällt für Referenzen die Nutzung der typischen Zeigersyntax, sie werden wie die Variable selbst behandelt, die sie referenzieren. Wegen dieser einfachen Arbeitsweise werden Referenzen auch als Aliase("Spitznamen") genannt. #include <iostream.h> double quad_v(double w){return w*w;} void quad(double& w){w*=w;} void quad(double* w){*w*=*w;} void main(void) { double x=12, *xp; x=12; quad(x); cout << "\n(1) 12*12= " << x; x=12; xp=&x; quad(xp); cout << "\n(2) 12*12= " << x; x=12; x=quad_v(x); cout << "\n(3) 12*12= " << x; getchar(); } // Wert als Parameter // Referenz als Parameter // Pointer als Parameter // call by value // call by reference // call by reference Beispiel: 61_refer.cpp Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 28-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 6.2 Strukturen Strukturen fassen C++Speichergrößen, wie Variablen, Arrays,... zu einem unter einem eigenen Namen verwaltbaren "Datentyp" zusammen. Die mit dem Schlüsselwort struct zusammengefassten Speichergrößen werden Attribute der Struktur genannt. Beispiel 62_struc_1: struct Brotsorte { string Bez; double Preis; // unsigned int stk; // } a[100]; // Brotsorte b[20]; // Brotsorte *p; b[0].Bez = "Roggenbrot"; p = new Brotsorte; // p->Bez = "Weizenbrot";// cout << b[0].Bez << endl // Attribut Bezeichnung Attribut Preis Attribut Stückzahl 100 Instanzen 20 weitere Instanzen // Zeiger auf die Struktur dynamische Strukturinstanz Attributzugriff mit Zeiger << p->Bez; Die Verwendung des Strukturnamens bei Speicherdeklarationen organisiert Speicherplatz, der alle Strukturattribute aufnehmen kann. Strukturen können auch für dynamischen Speicher instanziiert werden. Dazu werden Zeigern des Strukturtyps Speicheradressen mit der new-Anweisung zugewiesen. Der Zugriff auf die Attribute statisch gebildeter Strukturinstanzen erfolgt mit dem "Punktoperator ." z.B.: b[0].Bez Im Beispiel wird auf das Attribut "Bez" des ersten Elementes des Instanzarrays "b" zugegriffen. Mit einem Zeiger, der die Adresse einer Strukturinstanz enthält, kann mit dem "Pfeiloperator ->" auf ein Attribut zugegriffen werden. z.B.: p->Bez greift auf das Attribut Bez der Instanz, auf deren Adresse der Zeiger p zeigt. Beispiel für Substrukturen: 62_struc_2 Beispiel für Teststruktur: 62_struc_3 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 29-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 6.3 Unions Unions fassen C++Speichergrößen, wie Variablen, Arrays,... zu einem unter einem eigenen Namen verwaltbaren "Datentyp" zusammen. Das Besondere ist, dass alle Größen an der gleichen Speicheradresse beginnen. struct WORDREGS {unsigned short ax;}; struct BYTEREGS {unsigned char al,ah;}; union REGS { struct WORDREGS x; // Wortregister (16 Bit) struct BYTEREGS h; // Byteregister ( 8 Bit) } r; // Union-Instanz r r.x.ax = 0x0101; // Zuweisung zum Register ax cout << &r.x << " " << &r.h << endl; cout << (int)r.x.ax << endl; cout << (int)r.h.ah << " " << (int)r.h.al; Beispiel: 63_Union_1 Der Vorteil der Nutzung von Unions ist neben möglicher speicherplatzsparender Arbeitsweise der Zugriff auf einen Speicherplatz mit verschiedenen Größen. Im Beispiel Union_1.cpp wird eine Union für Prozessorregister beispielhaft am Wort-Register ax und den ByteRegistern al und ah dargestellt. Tatsächlich sind das al- und ah-Register jeweils Teile des ax-Registers eines IntelProzessors. Die Union liefert ein praktikables Hilfsmittel für die Zugriffe auf diese Register. Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 30-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 7. OOP, Klassen Klassen fassen C++ Speichergrößen (Attribute), wie Variablen, Arrays, Strukturen,... und C++Funktionen (Methoden) zu einem unter einem eigenen Namen verwaltbaren "Datentyp" zusammen. Es werden geschützte (private oder protected) und öffentliche (public) Attribute und Methoden unterschieden. class bruch { public: bruch(long z, long n = 1L); bruch Mul(bruch x); void Zeige(void); private: long zaehl,nenn; } a(3,4); int main() { bruch *p; p = new bruch(2,3); a.Zeige();cout<<" * ";p->Zeige(); cout<<" = "; a.Mul(*p).Zeige(); getchar(); return 0; } Beispiel: 71_Class_1 // Konstruktor // externen Methoden // private Attribute // Globalobjekt // // // // Klassenzeiger dynamisches Objekt Ausgabezeile: 3/4 * 2/3 = 6/12 Der Konstruktor ist die Methode, die wie die Klasse selbst benannt ist und zum Zeitpunkt der Objektbildung automatisch gestartet wird. Der Destruktor ist wie die Klasse selbst mit ~ benannt wird bei der Objektfreigabe gestartet. Klassen können auch für die Bildung dynamischer Objekte genutzt werden. Dazu werden Zeigern des Klassentyps Speicheradressen mit der new-Anweisung zugewiesen. Der Zugriff auf die Attribute oder Methoden statisch gebildeter Objekte (Klasseninstanzen) erfolgt mit dem "Punktoperator ." z.B.: a.Mul(*p); Im Beispiel wird auf die Methode "Mul()" des Objektes "a" zugegriffen und als aktueller Parameter das dynamische Objekt *p genutzt. Mit einem Zeiger, der die Adresse eines Objektes enthält, kann mit dem "Pfeiloperator ->" auf Klassenattribute oder .methoden zugegriffen werden. z.B.: p->Zeige( ) greift auf die Methode Zeige( ) des Objektes, auf deren Adresse der Zeiger p zeigt. Konstruktor-Beispiel: 71_Class_2 Assistenten für Automatisierungs- und Computertechnik IT-Werkstatt Stand 02.03.12 C++ Programmierung Grundlagen Seite 31-31 copyrights by Thomas Cassebaum C++ Trainer 2003, all rights reserved. Lehrseiten zur Programmierung in C++ 8. Arbeit mit Dateien 8.1 Textdateien, Filestreams Textdateien enthalten Folgen von ASCII-Zeichen. Besondere Zeichen sind in diesem Zusammenhang die Zeichen 0x0A (LF) und 0x0D (CR), die einen Zeilenumbruch bewirken. Unter C++ läßt sich die Arbeit mit Textdateien einfach mit Streams ("Strömen") realisieren. #include <fstream.h> // zusätzlicher Header Beispiel: 81_Datei_0 int main() { ofstream OU; char z; // ofstream für Ausgabeströme OU.open("\\temp\\cpptrain\\MeinText.txt"); // Öffnen if(!OU.is_open()){cerr<<"Fehler!";getchar();return 1;} cout << "Gib Zeichen ein: "; do // Eingabeschleife bis * { z=getchar(); // Zeichen von Tastatur if (z!='*') OU.put(z); // Ausgabe in Datei } while (z!='*'); OU << "\n<EOF>"; // Textausgabe in Datei OU.close(); // Schliessen der Datei return 0; } Zunächst muss ein Stream für Ein-(ifstream) oder Ausgabe(ofstream) definiert werden. Im Beispiel wird ein Ausgabestream OU vereinbart. Mit OU.open(char* File) wird dieser Stream eröffnet. Wenn die open-Methode eine 0 zurückgibt, war der Vorgang erfolgreich, ansonsten ist ein Fehler aufgetreten. Nach dem Öffnen können Zeichen entweder mit der put-Methode oder mit den Bitstreamoperator << in passende Grössen ausgegeben werden. Mit der get-Methode oder mit den Bitstreamoperator >> kann aus einem geöffneten ifstream eingegeben eingegeben werden. Zum Abschluss müssen geöffnete Dateien wieder geschlossen werden: OU.close(); Beispiel: 81_Datei_1 (Dateikopie)