62
Cassebaum, Skript zur Programmierung mit C++ 1 Programmierung mit C++ Skript für Schüler in Kursen an Fachgymnasien mit dem Schwerpunkt Informationstechnik Thomas Cassebaum Berufsbildende Schulen III Magdeburg 10. Mai 2004 Fehlerbereinigte Version vom 22. August 2011

Prrooggrraammmmiieeruunngg mmiitt CC++++cassebaum.bplaced.net/download/c++_scpt.pdf · EasyCode EasyCase® (C++) ist eine geschützte Bezeichnung der BKR Software Beratung und –

Embed Size (px)

Citation preview

Cassebaum, Skript zur Programmierung mit C++

1

PPrrooggrraammmmiieerruunngg mmiitt CC++++

Skript für Schüler

in Kursen an Fachgymnasien

mit dem Schwerpunkt Informationstechnik

Thomas Cassebaum

Berufsbildende Schulen III Magdeburg

10. Mai 2004

Fehlerbereinigte Version vom 22. August 2011

Cassebaum, Skript zur Programmierung mit C++

2

Quellenverzeichnis

[ 1 ] Schulgesetz des Landes Sachsen-Anhalt in der Fassung vom 27.08.1996 „Verordnung zur Gestaltung der gymnasialen Oberstufe in der Sekundarstufe II" Beschluss der Kultusministerkonferenz vom 07.07.1972 i.d.F. vom 22.10.1999

[ 2 ] Einheitliche Prüfungsanforderungen in der Abiturprüfung (Beschluss der Kultusministerkonfe-renz vom 01.06.1979 i.d.F. vom 01.12.1989)

[ 3 ] Rd. Erl. des MK vom 25. 05. 1994-3-83200-202: „Leistungsbewertung an allgemeinbildenden Schulen und Schulen des zweiten Bildungsweges", MBl. LSA NR. 40/94, S. 200

[ 4 ] Bannach, Cassebaum, Hering, Jung, Richter, Rumpf, Wüstemann Rahmenrichtlinien [RRL] Fachgymnasium Informationstechnik Land Sachsen-Anhalt, Kultusministerium, Magdeburg 2003

[ 5 ] Bannach, Cassebaum, Hering, Jung, Richter, Rumpf, Wüstemann Einheitliche Prüfungsanforderungen in der Abiturprüfung Informatik Beschluss vom 1.12.1989

[6 ] P.Prinz, U.Kirch-Prinz C++, Lernen und Professionell anwenden, Mitp-Verlag, Bonn 2003, ISBN 3-8266-0824-0

[ 7 ] P.Prinz, U.Kirch-Prinz C++, Das Übungsbuch, Testfragen mit Aufgaben und Lösungen Mitp-Verlag, Bonn 2003, ISBN 3-8266-0998-0, 2.Auflage

[ 8 ] Sedgewick, Robert Algorithmen in C Addison Wesley, Bonn-München-Paris 1992, ISBN 3-89319-669-2

[ 9 ] Schildt, Herbert C/C++ gepackt Mitp-Verlag, Bonn 2001, ISBN 3-8266-0684-1

[ 10 ] Louis, Dirk C/C++ new reference Markt & Technik, München 2001, ISBN 3-8272-6121-X

[ 11 ] Cassebaum, Thomas C++ Trainer 2.1, C++ Entwicklungsumgebung für Lernzwecke Magdeburg, 2000...2005

[ 12 ] Cassebaum, Thomas Lehrscript zur C++ Programmierung, Grundlagen der Softwareentwicklung BbS III Magdeburg, 1999

Borland® C++, Borland Delphi®, Turbo Pascal® sind Warenzeichen der Borland Inc. USA, MS Windows® 98, NT®, Me®, 2000®, XP® , MS Internet Explorer®, MS Word®, MS Office®, MS Excel®, MS Visual C++®, MS Visual Basic® sind Warenzeichen der Microsoft Inc. USA, EasyCode EasyCase® (C++) ist eine geschützte Bezeichnung der BKR Software Beratung und –entwicklung GmbH, Deutschland, Pentium® ist ein Warenzeichen der Intel Inc. USA.

Cassebaum, Skript zur Programmierung mit C++

3

Inhaltsverzeichnis

VORWORT ...................................................................................................................................................5

1 GRUNDLAGEN DER PROGRAMMIERUNG ...........................................................................................6

1.1 PROGRAMME UND PROGRAMMIERSPRACHEN ......................................................................................... 6 1.1.1 Programmbegriff ........................................................................................................................ 6 1.1.2 Programmzustände, Tools und Entwicklungstätigkeiten .......................................................... 6 1.1.3 Maschinenorientierte Programmiersprachen ........................................................................... 7 1.1.4 Problemorientierte Programmiersprachen ............................................................................... 8

1.2 DIE INTEGRIERTE ENTWICKLUNGSUMGEBUNG C++ TRAINER 2.X ................................................................ 9 1.2.1 Bedienelemente des C++ Trainers ............................................................................................. 9 1.2.2 Die Entwicklungsumgebung SSmmaallllCCpppp ..................................................................................... 10 1.2.3 Erstes Übungsprogramm ......................................................................................................... 11

1.3 VARIABLEN UND DATENTYPEN ............................................................................................................ 12 1.3.1 Variablen .................................................................................................................................. 12 1.3.2 Datentypen .............................................................................................................................. 12 1.3.3 Tastaturein- und Bildschirmausgaben ..................................................................................... 13

1.4 OPERATOREN UND AUSDRÜCKE .......................................................................................................... 14 1.4.1 Operatoren .............................................................................................................................. 14 1.4.2 Numerische Ausdrücke ............................................................................................................ 15 1.4.3 Logische Ausdrücke.................................................................................................................. 15 Übungsaufgaben .................................................................................................................................. 16

1.5 STRUKTURANWEISUNGEN .................................................................................................................. 17 1.5.1 Sequenz .................................................................................................................................... 17 1.5.2 Selektion .................................................................................................................................. 17 1.5.3 Mehrfachauswahl (Fallunterscheidung) .................................................................................. 19 1.5.4 Kopfgesteuerte Schleifen ......................................................................................................... 20 1.5.5 Fußgesteuerte Schleife ............................................................................................................ 22

1.6 ALLGEMEINE PROBLEME ZUR SOFTWAREENTWICKLUNG .......................................................................... 24 1.6.1 Wasserfallmodell für den Lebenszyklus einer Software .......................................................... 24 1.6.2 Struktogramme ........................................................................................................................ 25 1.6.3 Trockentests ............................................................................................................................. 26

2 ELEMENTARE EINFÜHRUNG IN C/C++ ............................................................................................. 28

2.1 FUNKTIONEN ................................................................................................................................... 28 2.1.1 Funktionsdefinition .................................................................................................................. 28 2.1.2 Prototypen ............................................................................................................................... 28 2.1.3 Funktionsparameter ................................................................................................................ 29 2.1.4 Die main() - Funktion ............................................................................................................... 29 2.1.5 Datenkapseln ........................................................................................................................... 30 2.1.6 „call by value“ und „call by reference“ .................................................................................... 30 2.1.7 Rekursionen ............................................................................................................................. 31 2.1.8 Funktionsüberladung ............................................................................................................... 32

Cassebaum, Skript zur Programmierung mit C++

4

2.2 ARRAYS .......................................................................................................................................... 33 2.2.1 Ein- und mehrdimensionale Arrays (Felder) ............................................................................ 33 2.2.2 Zufallszahlen ............................................................................................................................ 33 2.2.3 Strings ...................................................................................................................................... 34

2.3 ADRESSEN UND ZEIGER ...................................................................................................................... 36 2.3.1 Adressen .................................................................................................................................. 36 2.3.2 Zeiger (Pointer) ........................................................................................................................ 36 2.3.3 Zeiger und Strings .................................................................................................................... 38 2.3.4 Mehrfachzeiger ........................................................................................................................ 39 2.3.5 Zeigerarrays ............................................................................................................................. 39

3 GRUNDLEGENDE ALGORITHMEN .................................................................................................... 41

3.1 DYNAMISCHER SPEICHER („HEAP“) ..................................................................................................... 41 3.1.1 Speicherzuweisung .................................................................................................................. 41 3.1.2 Beispiel für dynamischen Speicher .......................................................................................... 42

3.2 EINIGE EINFACHE ALGORITHMEN ......................................................................................................... 43 3.2.1 Sortierung ................................................................................................................................ 43 3.2.2 Vertauschen zweier Werte ...................................................................................................... 43 3.2.3 Fakultät (Rekursion) ................................................................................................................. 44 3.2.4 Näherungswertbestimmung für den Sinus .............................................................................. 44 3.2.5 Euklidischer Algorithmus (ggT) ................................................................................................ 44 3.2.6 Sieb des Erastothenes (Primzahlen) ........................................................................................ 44

4 OBJEKTORIENTIERTE PROGRAMMIERUNG ...................................................................................... 45

4.1 STRUKTUREN UND UNIONS (OHNE „OOP“) .......................................................................................... 45 4.1.1 Strukturen ................................................................................................................................ 45 4.1.2 Unions ...................................................................................................................................... 46

4.2 KLASSEN ......................................................................................................................................... 47 4.2.1 Objekt und Klasse .................................................................................................................... 47 4.2.2 Klassendefinition in C++ ........................................................................................................... 48 4.2.3 Objektbildung und –zugriff ...................................................................................................... 48 4.2.4 Konstruktor und Destruktor..................................................................................................... 49 4.2.5 Vererbung und Aggregation .................................................................................................... 49 4.2.6 Textdateien/ Streams .............................................................................................................. 51

4.3 LISTEN ............................................................................................................................................ 51 4.3.1 Liste, einfach verkettet ............................................................................................................ 51 4.3.2 Liste, doppelt verkettet............................................................................................................ 53

5 AUFGABEN ZUR PRÜFUNGSVORBEREITUNG ................................................................................... 55

5.1 THEORETISCHE FRAGEN, OHNE PC SCHRIFTLICH ZU LÖSEN ....................................................................... 55

5.2 PRAKTISCHE, AM PC ZU LÖSENDE AUFGABE .......................................................................................... 56

Index ......................................................................................................................................................... 56

KURZÜBERSICHT ....................................................................................................................................... 59

Cassebaum, Skript zur Programmierung mit C++

5

Vorwort

Liebe Leser,

das vorliegende Skript habe ich zur Unterstützung des Unterrichts im Programmierungsteil zum Profil-fach „Informationstechnik“ im Fachgymnasium Technik geschaffen.

Das Skript ist keinesfalls als Ersatz für ein umfassendes Lehrbuch zum gewählten Thema gedacht. Es soll vielmehr eine Gesprächsgrundlage zwischen Lehrer und Schüler darstellen, die dem Lehrer die Unterrichtsführung erleichtert und gleichzeitig das Lernen der Schüler auch bei der Vorbereitung von Klausuren oder Prüfungen vereinfachen soll.

Die Idee dazu entstand parallel zu meiner Arbeit als Lehrer an der Berufsbildenden Schule „Otto von Guericke“ in Magdeburg und als langjähriges Mitglied der Arbeitsgruppe zur Erstellung der Rahmen-richtlinien und der Aufgaben für die schriftlichen Abiturprüfung im genannten Profilfach für das Fach-gymnasium im Auftrag des Kultusministeriums des Landes Sachsen-Anhalt seit 1999.

In diesem Skript werden nur die Themen zu den Profilfachbestandteilen der Kursstufen besprochen, die sich mit dem Thema „C++-Programmierung“ beschäftigen. Die Themen „Systemanalyse“, „Techni-sche Kommunikation und Netzwerke“ und „Datenbanken“ werden nicht behandelt.

Ausdrücklich sei gesagt, dass die von mir benutzte Programmiersprache C/C++ in den Rahmenricht-linien für Fachgymnasien der meisten Bundesländer empfohlen oder gar vorgeschrieben wurden. Nach Gesprächen mit Vertretern der Praxis und meinen eigenen gesammelten Unterrichtserfahrungen be-grüße ich diese Entscheidung.

Ich verwende für die Durchführung von praktischen Schülerübungen und als Hilfsmittel für die Lösung der gestellten Programmieraufgaben die IDE „C++ Trainer“ in der aktuellen Version (August 07: 2.3.1). Diese auf dem freien Borland-C++ Compiler 5.5 basierende vollwertige C++ Entwicklungsumgebung mit didaktischen Unterstützungselementen für Lernende ist besonders leicht bedienbar und kann von meiner Webseite www.t-cassebaum.de im Download-Verfahren beschafft werden. Bitte beachten Sie vor der Installation die Lizenzbedingungen!

Für Besitzer von 64-Bit-Computern ist der C++ Trainer leider ungeeignet. Deshalb nutze ich für diese Technik die noch im Aufbau befindliche Software „SmallCpp“. Es handelt sich um eine sehr kleine, aber trotzdem leistungsfähige Entwicklungsumgebung, die für den Unterricht und die Vorbereitung sinnvoll eingesetzt werden kann.

Am Ende des Skripts finden Sie schliesslich eine kurze Übersicht zu den behandelten C- und C++-Anweisungen, die auf zwei DIN A4 Doppelseiten Platz findet.

Thomas Cassebaum 2011

Cassebaum, Skript zur Programmierung mit C++

6

1 Grundlagen der Programmierung

1.1 Programme und Programmiersprachen

1.1.1 Programmbegriff

Ein Computer besitzt aus der Sicht der Hardware die Fähigkeit, Maschinenprogramme abzuarbeiten. Das Maschinenprogramm besteht aus einer Folge von Prozessorbefehlen (Bitmuster), deren Reali-sierung durch den technischen Aufbau der Hardware (insbesondere des Prozessors) gewährleistet ist.

Ein MMaasscchhiinneennbbeeffeehhll oder

PPrroozzeessssoorrbbeeffeehhll ist eine dua-le Codierung, die den Prozes-sor zu einer bestimmten Tä-tigkeit veranlasst.

Ein PPrrooggrraammmm ist eine Verfahrensfestlegung mit Hilfe einer Befehlsfolge.

1.1.2 Programmzustände, Tools und Entwicklungstätigkeiten

Ein Programm wird zunächst z.B. zeichnerisch als Struktogramm eennttwwoorrffeenn. Dann wird der ccooddiieerrttee Programmtext (QQuueellllee) über Tasteneingabe mit einem EEddiittoorr erfasst („eeddiittiieerrtt“). Der CCoommppiilleerr üübbeerr--

sseettzztt den Text in Maschinencode, es entsteht das OObbjjeekktt. Der LLiinnkkeerr bbiinnddeett dieses Objekt mit anderen notwendigen Objekten zum TTaasskk. Mit dem DDeebbuuggggeerr tteesstteett man das Programm.

Nach dem Start belegt das Programm als „PPrroozzeessss“ Teile des Arbeitspeichers, von denen das Betriebs-system (z.B. Windows) die Programmabarbeitung leitet.

Tools Tätigkeiten Zustände Hilfstools

EEddiittoorr EErrffaassssuunngg/ Bearbeitung des Quelltextes QQuueellllee (.cpp) Struktogramm- Editor

(EEnnttwweerrffeenn) CCoommppiilleerr

LLiinnkkeerr

DDeebbuuggggeerr

ÜÜbbeerrsseettzzuunngg des Quelltextes (Borland 5.5) OObbjjeekktt (.obj)

TTaasskk (.exe)

PPrroozzeessss

Fehler?

VVeerrbbiinndduunngg mit C++Umgebungsmoduln

ja nein

Texteditor

(DDookkuummeennttiiee--

rreenn) Fehler?

ja nein

Fehler? ja nein

SSttaarrtt Tafel 1

Abb. 1

TTeesstteenn und Fehler finden

Befehl 1

Befehl 2

Befehl 3

Befehl n

PPrrooggrraammmm

Sof tware

Hardware

PPrroozzeessssoorr

Cassebaum, Skript zur Programmierung mit C++

7

1.1.3 Maschinenorientierte Programmiersprachen

Eine Programmiersprache, die genau eine MMnneemmoonniikk (sprachliches Kürzel. z.B. „MOV“) für jeden Pro-zessorbefehl besitzt, bezeichnet man als AAsssseemmbblleerrsspprraacchhee. Maschinen- und Assemblersprachen wer-den in der Informatik mmaasscchhiinneennoorriieennttiieerrttee PPrrooggrraammmmiieerrsspprraacchheenn genannt.

Eine QQuueellllee ist ein Text (Folge von ASCII-Zeichen), der symbolische Befehle (meist in englischer Sprach-anlehnung) enthält. Die Quelle wird in einer QQuueellllddaatteeii auf einem Datenträger gespeichert.

Ein AAsssseemmbblleerr ist ein Übersetzungsprogramm, das einen symbolischen Befehl im Verhältnis 1:1 in ei-nen binären Maschinenbefehl übersetzt.

Das Ergebnis der Übersetzung ist das OObbjjeekktt, dessen Inhalt, eine Folge von binären Prozessorbefehlen, als Binärdatei („OObbjjeekkttddaatteeii“) auf einem Datenträger (z.B. Festplatte) gespeichert wird.

Beim LLiinnkkeenn werden weitere für die Verarbeitung notwendige Objekte aus der Entwicklungsumgebung (z.B. Borland C++ Builder) zu einer gemeinsamen, startbaren Datei verbunden. Man nennt ein solche startfähige Datei “TTaasskk“, "EXE-File", "ausführbares Programm", „executable binary file“ oder "startba-res Programm". Sie wird auf einem Datenträger mit einem Namen gespeichert und von dort gestartet.

Menschliche Sprache Programmiersprache Maschinensprache

Addieren, Sortieren, Ver-gleichen, Suchen, ...

Cout, cin, if, while, then, do, k++, k=k+12, ...

1100111100001011, 0011101111000011, ...

Beispiel einer mnemonischen Befehlsfolge im Assembler einer Registermaschine:

Operationsteil Operandenteil (hexadezimal)

LD (Laden in den Akku) 1000 (Speicherstelle der zu lesenden Größe) ADD (Addieren zum Akku) 1004 (Speicherstellen der Summanden) STORE (Speichern des Akkus) 1008 (Angabe der Speicherstelle des Ziels)

Um vom Prozessor ausgeführt werden zu können, müssen - da der Computer nur die Zustände 0 und 1 unterscheiden kann - auch die Befehle in binärer Form angegeben sein. Sind die Anweisungen in Binär-codes dargestellt, spricht man von einer Maschinensprache. Sie kann vom Prozessor unmittelbar (di-rekt) verstanden werden.

BBeeffeehhllssmmnneemmoonniikk (8086 -Assembler) MOV AX , x

Beispiel für einen Maschinenbefehl: 00010100 00011101 11101111 Operationsteil 1. Operand 2. Operand Der Beispielbefehl füllt das 16-Bit-Register AX („Akku“) mit dem Inhalt des Speicherplatzes, der durch die symbolische Adresse x erkannt wird.

Ein RReeggiisstteerr ist ein kleiner Speicherbe-reich direkt im Prozessor.

Die binären Codes der Maschinenbefehle sind durch den benutzten Prozessortyp vorgegeben. Jeder Prozessortyp besitzt eine eigene, nur ihm verständliche Befehlsliste. Die Gesamtheit dieser Befehls-codes für einen Prozessortyp wird auch "MMaasscchhiinneennsspprraacchhee" genannt.

Es ist zwar möglich, mit Hilfe der binären Codes der Maschinensprache Programme zu codieren. Eine Codierung mit binären Befehlscodes durch den Menschen ist jedoch vergleichsweise schwierig und umständlich zu bewerkstelligen, weil die binären Zahlenfolgen der menschlichen Kommunikations-struktur recht fremd sind.

Prozessor

CX-Register

Arbeitsspeicher (RAM)

x (Adresse)

Speicherplatz „x“ (16 Bits)

BX-Register

AX-Reg. Akku

Cassebaum, Skript zur Programmierung mit C++

8

1.1.4 Problemorientierte Programmiersprachen

Programmiersprachen, deren Befehlssymbole vorrangig am zu lösenden Problem orientiert und damit für Menschen besser fassbar sind, bezeichnet man als pprroobblleemmoorriieennttiieerrttee PPrrooggrraammmmiieerrsspprraacchheenn.

Ein symbolischer Befehl wird bei der Übersetzung in mehrere Maschinenbefehle - im Verhältnis 1:n – verwandelt. Populäre problemorientierte Programmiersprachen sind: ADA, (VISUAL-) BASIC, C, C++, Cobol, Delphi, Fortran, Java, (Turbo-)Pascal, Python, usw...

Es existieren zwei Prinzipien zur Übersetzung eines problemorientierten Quelltextes:

1. Bei Verwendung eines IInntteerrpprreetteerrss wird jeder symbolische Befehl des Quellprogramms unmittelbar vor seiner echten Realisierung einzeln durch den Prozessor übersetzt.

Vom Interpreter wird also keine Objektdatei mit einer Folge von Prozessorbefehlen erzeugt und ge-speichert. Damit verlängert sich die Abarbeitungszeit um die benötigte Übersetzungszeit. Programmie-rer arbeiten gern mit diesem Verfahren bei der Softwareentwicklung, weil die zu entwickelnden Pro-gramme nach Quelltextänderungen zur Beseitigung von Programmfehlern besonders schnell wieder ausgeführt werden können. Nach Fertigstellung der Software wird aber zur Optimierung der endgülti-gen Programmgeschwindigkeit dennoch ein Compiler zur Übersetzung eingesetzt.

2. Ein CCoommppiilleerr ist ein Übersetzungsprogramm, das die symbolischen Befehle einer problemorien-tierten Sprache aus einer Quelldatei vollständig in eine Folge binärer Maschinenbefehle einer abzu-speichernden Objektdatei verwandelt.

Die Vorteile des Einsatzes von problemorientierten Sprachen sind die günstige, vereinfachte Program-mentwicklung und die PPoorrttiieerrbbaarrkkeeiitt (Überführbarkeit in andere Systeme) der Lösungen. Lösungen mit maschinenorientierten Sprachen besitzen meist eine bessere rreecchheenntteecchhnniisscchhee QQuuaalliittäätt (kurze Laufzeit, geringer Speicherplatzbedarf), weil sie der Maschinenstruktur besser angepasst sind.

HHyybbrriiddpprrooggrraammmmee werden auf Basis problemorientierter Sprachen hergestellt, in denen einzelne re-chentechnisch besonders relevante Bestandteile maschinenorientiert programmiert werden. Damit wird versucht, alle Vorteile der jeweiligen Sprachfamilien zu nutzen und deren Nachteile zu vermeiden.

Übungsaufgaben

1. Nennen Sie Ihnen bekannte dreibuchstabige Programmdateitypen bei der Softwareentwicklung! Ordnen Sie dabei die Begriffe Quelle, Objekt, Task und Prozess zu!

2. Nennen Sie 3 allgemeine Übersetzertypen und erläutern Sie deren verschiedene Funktionsweisen!

3. Inwieweit unterscheidet sich die Arbeit des Linkers von der eines Compilers?

4. Erläutern Sie Unterschiede der problem- und maschinenorientierten Programmiersprachen!

5. Ist die Assemblersprache eine maschinenorientierte oder eine Maschinensprache?

6. Erklären Sie die Begriffe Datei, Verzeichnis, Programm, Maschinenbefehl, Befehlsbreite, modular, Projekt, Sequenz, Selektion, Iteration, E-V-A, Portierbarkeit und Hybridprogramm!

7. Welche Teilprozesse müssen bei der Entwicklung eines lauffähigen Programms durchlaufen wer-den? Erklären Sie die Ergebniszustände des zu entwickelnden Programms und die möglichen Fehler! In welcher Form (Speicherort und Codierung) liegen die Zustände vor?

8. Was sind syntaktische und was logische Programmfehler bei der Implementierung?

9. Nennen Sie mindestens 5 problemorientierte Programmiersprachen! Was sind „Dialekte“ und was „Versionen“ von Programmiersprachen?

10. Versuchen Sie, die Bedeutung des Begriffes „Skriptsprache“ durch Literatur- und/oder Internet-Recherche selbst zu erkennen. Erklären Sie die Vor- und Nachteile dieser Sprachfamilie.

Cassebaum, Skript zur Programmierung mit C++

9

1.2 Die integrierte Entwicklungsumgebung C++ Trainer 2.x 1

Für eine Softwareentwicklung empfiehlt sich der Einsatz eines speziellen Softwaresystems, das abge-kürzt als „IIDDEE“ bezeichnet wird. Der Begriff IIDDEE steht für IInntteeggrraatteedd DDeevveellooppmmeenntt EEnnvviirroonnmmeenntt, deutsch: IInntteeggrriieerrttee SSooffttwwaarree--EEnnttwwiicckklluunnggss--UUmmggeebbuunngg.

Es handelt sich um eine Sammlung von zueinander passenden Programmen, die für eine effektive Soft-wareentwicklung notwendig sind. Bei der Sprache C++ sind das Programme der C++ -Sprachumgebung, passende Toolprogramme und das sogenannte „front end“, das alles bequem durch den Programmie-rer ansteuerbar macht.

Profi-IDE’s sind z.B. der Borland C++ Builder, MS Visual C++, Borland Delphi, MS Visual Basic die im Softwarehandel wie jede andere kommerzielle Software erhältlich sind.

Die Lern-IDE CC++++ TTrraaiinneerr 22..33 kann frei unter http://www.t-cassebaum.de heruntergeladen werden. Empfehlenswert ist als weiterer Download von dieser Seite die ebenfalls freie Demoversion des Struktogramm-Tools Easycode EasyCase (C++) 6.8. Dieses Tool entwickelt aus gegebenen C/C++ Pro-grammen Struktogrammzeichnungen oder schreibt umgekehrt automatisch generierte C/C++ Quellen anhand mit diesem Tool gefertigter Struktogramme.

1.2.1 Bedienelemente des C++ Trainers

Neue Quelldatei Struktogramm zeigen Quelle drucken Breakpoints Quelle öffnen/ speichern Starten Debugger Hilfe ein/aus

Bookmark- Snippets finder für C++ zeigen Einrücken der Snippets C++Zeilen Text klein Easycode - groß Beamerein- Hinweise stellung und ein/ aus Fehlermel- dungen Assembler- quelle Status- zeile

Abb. 2 Wichtige Bedienfunktionen der IDE „C++ Trainer 2.3“

Mit dem C++Trainer können C/C++/Assembler- Quellen eingegeben, übersetzt, getestet, gedruckt, gespeichert und wieder geöffnet werden. Für den Test stehen sofort nach der Installation geeignete Debugger für C++ und Assembler startbar zur Verfügung.

1 Cassebaum, Thomas, C++ Trainer 2.x, C++ Entwicklungsumgebung für Lernzwecke, Magdeburg, 2000...2007

Cassebaum, Skript zur Programmierung mit C++

10

Als didaktische Bestandteile besitzt diese IDE sogenannte SSnniippppeettlliisstteenn, die als Seitenleisten einfach die C++ Grundbestandteile erklären und rufen lassen. Viele der Snippets lassen sich mit HHoottKKeeyyss (z.B. Strg/F fügt in den Quelltext eine for-Anweisung ein) aufrufen. Als weiterer Zusatz existiert ein Ver-zeichnis „Lehre“, das neben ausgewählten Tafelbildern („Lehrseiten“) auch verlinkte Beispiele, Übungsaufgaben und deren Lösungen enthält.

Wie die Programmhilfen werden die Fehler- und Warnmeldungen in deutscher Sprache gegeben. Die Darstellung mit dem Beamer wird in der Software „C++ Trainer“ mit einem Spezialbutton unterstützt, das alle Programmtextzeichen in vergrößerter, dicker und gut lesbarer Schriftart zeigt.

Neben der C/C++ Syntax werden auch Quellen in Intel-Assembler, HTML, PHP, XML und DOS-Batches farbig syntax-highlighted dargestellt und können geändert und getestet werden. Einfache Texte lassen sich als RTF-Files speichern und mit Textformaten leicht austauschen.

Es werden alle in den Rahmenrichtlinien geforderten Programmiertechniken unterstützt. Der C++-Trainer kann aber auch echte Windows-Lösungen, OpenGl-Grafikprogramme und alle anderen C++ Programme schaffen, die durch den freien Compiler „CC++++ BBuuiillddeerr 55..55 ffrreeee ccoommmmaanndd lliinnee ttoooollss“ erstellt werden können.

1.2.2 Die Entwicklungsumgebung SSmmaallllCCpppp

Diese noch neue Möglichkeit, besonders einfach C++-Entwick-lungen durchzuführen, kann auch an 64-Bit-Systemen genutzt werden. Es gibt viele Ähnlichkeiten mit dem C++ Trainer.

Abb. 3

Auch die Mini-IDE SSmmaallllCCpppp läßt sich von der Download-Seite http://www.t-cassebaum.de kostenfrei herunterladen.

Nach der fertigen Eingabe eines Quelltextes im Editorfenster sollte er zunächst mit einem neuen Namen abgespeichert werden. Danach erfolgt Übersetzen, Lin-ken und Start des Programmes in einem Schritt. Sollte das Programm nicht starten, werden im Aus-gabefenster FFeehhlleerr und WWaarrnnuunnggeenn angezeigt.

TempSrc.cpp 10: Call to undefined function 'IF' in function main()

In diesem Fall wurde in der Zeile 10 eine Anweisung falsch mit Großbuchstaben eingegeben. Die FFeehhlleerr müssen alle durch Änderung des Quelltextes beseitigt werden. Erst danach kann der erste Programm-start gelingen. WWaarrnnuunnggeenn weisen auf eine ungenaue Programmierung hin, die erst nach tieferen Kenntnissen zur Sprache C++ erkannt und verbessert werden können.

Mit der rechten Maustaste kann in das Editorfenster geklickt ein Menü aktiviert werden und das Aus-gabefenster sichtbar und wieder unsichtbar gemacht werden.

Drucken des aktuellen Quelltextes

Neue Quelle mit Template öffnen

Gespeicherte Quelldatei öffnen

Speichern der aktuellen Quelle

Speichern akt. Quelle an neuem Ort

Alle offenen Quellen speichern

Markierten Text ausschneiden

Markierten Text kopieren

Einfügen der Zwischenablage

Markierten Text löschen

Letzte Aktion rückgängig machen

Letzte rückgäng. Aktion wiederholen

Suchen und Ersetzen

Lesezeichen in Cursorzeile setzen

Lesezeichen in Cursorzeile entfernen

Vor/Zurück zum nächsten Lesezeichen

Ausgabefenster zeigen/ verbergen

Schrift vergrößern/ verkleinern

Debugger starten

Übersetzen, Linken und Starten

Hilfe zu C/ C++

Aufdecken versteckter Kommentare Lesezeichen („Bookmark“)

Zeilennummern ein-/ ausschalten Alle Kommentare zeigen/ verstecken

Editorfenster Ausgabefenster

Cassebaum, Skript zur Programmierung mit C++

11

1.2.3 Erstes Übungsprogramm

Das denkbar einfachste CC++++ PPrrooggrraammmm wird, wie auch in anderen Programmiersprachen, mit dem so genannten "Hello-world-Programm" vorgeführt. Der Hauptteil des Programms wird HHaauuppttffuunnkkttiioonn als bezeichnet und mit main() eingeleitet. Die folgenden, zwischen geschweiften Klammern angeordne-ten Anweisungen, werden unmittelbar nach dem Programmstart mit dem ersten Befehl beginnend nacheinander ausgeführt.

Falls keine „return“-Anweisung zum Programmabbruch führt, wird das Erreichen der zur main()-Funktion gehörigen schließenden geschweiften Klammer das Programm beenden.

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" (Standardausgabe) erfordert das Einfügen des Headers "iostream" mit der Präprozessor-Anweisung #include. Wird diese Einfügung vergessen, ist "cout" eine dem Compiler unbekannte Zeichenfolge.

// Th.Cassebaum, 13.8.2011, all rights reserved #include <iostream> // Header für cout using namespace std; int main() { cout << "Hello world!"; getchar(); // Warten auf Tasteneingabe return 0; // Programm beenden mit Code 0 } // Ende der main()-Funktion

Der PPrrääpprroozzeessssoorr ist ein Programm, das die Quellzeilen, die mit einer Raute # beginnen, schon vor dem Compiler automatisch auswertet. #include führt zum Einfügen aller Zeilen einer beliebigen Textdatei anstelle der #include-Zeile. Im Beispiel wird die Textdatei „iostream.h“ eingefügt, die für nahezu jedes C++-Programm erforderlich wird. Die Anweisung using namespace std; stellt den Standard-Namensraum „std“ ein.

HHeeaaddeerr (*.h / *.hpp) sind Textdateien, die C/C++ -Zeilen enthalten, die vom Compiler übersetzt wer-den. Der Header iostream.h ermöglicht beispielsweise den Zugriff auf die E/A-Stream-Bibliothek ( in der neben cout noch andere E/A-Funktionen enthalten sind ) von C++. Wird der Headername in <…> eingeschlossen, wird die Datei im include-Verzeichnis des Compilers gesucht. Falls er in “…“ einge-schlossen ist, wird sie im Verzeichnis der .cpp - Quelldatei gesucht.

Beispielaufgabe 1

Das Programm fordert zur Eingabe eines Namens auf, speichert diesen Namen und begrüßt den Nutzer mit seinem Namen. z.B. „Guten Tag Paul. Wie geht’s?“ Kommentieren Sie jede Programmzeile.

Aus- und Eingaben des Programmes nach dem Start:

01 /* Thomas Cassebaum 2011, all rights reserved 02 Mehrzeiliger Kommentar wird nicht vom Compiler bearbeitet 03 beginnt mit: /* und endet mit: */ 04 #include <iostream> // Zeile mit # ist für den Präprozessor, lädt Header "iostream" 05 // Einzeiliger Kommentar beginnt mit // und endet am Zeilenende 06 using namespace std; // Stellt den Standard-Namensraum "std" ein 07 int main() // Erste Zeile der main-Funktion (Hauptfunktion) 08 { string s; // Variable: s vom Datentyp: string 09 cout << "Name: "; // Ausgabe der Ausschrift mit Leerzeichen am Ende 10 cin >> s; // Eingabe von Tastatur wird in der Variablen s gespeichert 11 cout << "Guten Tag " << s << ". Wie geht's?"; // Ausgabe des Antwortsatzes 12 getchar(); // Wartet auf die Eingabe einer beliebigen Taste 13 return 0; // Liefert Rückkehrcode der main-Funktion (0 bedeutet: Ablauf gut) 14 } // Eine schließende geschweifte Klammer schließt die Funktion ab

Name: Tim Guten Tag Tim. Wie geht’s?

Hello world!

Cassebaum, Skript zur Programmierung mit C++

12

1.3 Variablen und Datentypen

1.3.1 Variablen

In C/C++ ist eine VVaarriiaabbllee ein Datenobjekt mit veränderlichem WWeerrtt, das einen NNaammeenn und einen DDaa--

tteennttyypp besitzt, sowie einen SSppeeiicchheerrppllaattzz einer festgelegten Länge belegt. Variablen müssen vor ihrer ersten Verwendung für einen bestimmten Datentyp ddeekkllaarriieerrtt werden:

<datentyp><Bezeichner>[,<Bezeichner>[,...]]; // z.B.: int x, y;

Ein BBeezzeeiicchhnneerr in C++ besteht aus einer Folge von Groß-/ Kleinbuchstaben, Ziffern oder der Unterstrei-chung _ . Das erste Zeichen darf keine Ziffer sein. Der Bezeichner darf beliebig lang sein, nur 250 Zei-chen werden zur Erkennung benutzt und 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 ZZuuwweeiissuunngg ("Ergibtanweisung") in der Form:

<variable_typ1> = <Ausdruck_typ1>; einen WWeerrtt.

Der Wert errechnet sich durch einen AAuussddrruucckk, 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() { int var, VAR, Meine_Lieblingsvariable= 0; var = -3; VAR = 4; Meine_Lieblingsvariable = var + VAR; cout << Meine_Lieblingsvariable; getchar();

}

Im Beispiel werden drei Variablen im ganzzahligen Datentyp (int) deklariert. Die Variable "Mei-ne_Lieblingsvariable" speichert nach der Addition var + VAR den Wert

1.3.2 Datentypen

Jede Variable besitzt einen Datentyp, der die Art der Inhaltswerte und die Bytelänge klärt. Die Bytelän-ge ist die Anzahl der Bytes, die eine gespeicherte Variable dieses Datentyps im Speicher belegt.

TTyyppbbeezzeeiicchhnneerr in C++ sind z.B.: Tafel 2

Bytes Typ geeignet für Wertkonstante

10 long double sehr genaue reelle Zahlen (bis 18 Stellen) 123456.789012345678 8 double reelle Zahlen (bis 15 Stellen) -0.123456789012345 4 float wenig genaue reelle Zahlen (bis 7 Stellen) 1.234567E02 4 int ganze Zahlen (-2.147.483.648...2.147.483.647) -0x25 (0x: hexadezimal) 2 short int ganze Zahlen (-32.768...32.767) +321 4 unsigned int natürliche Zahlen (0...4.294.967.295) 12 1 char Zeichen (0...255) 'a' ? string Zeichenketten (Klasse string) "Zeichen abc" 1 bool logische Werte (true oder false) true 0 void leer (ohne Wertrückgabe, main() ohne return)

int x, y; bool a; double b; string s; char c; x = 0xff; a = true; b = 1.2-02; s = "\nJa"; c = 'v'; y = x;

Variablen dürfen auch schon in ihrer Definition initialisiert werden. z.B. char w='a'; int x=7; Nicht initialisierte Variablen behalten die zufälligen vorherigen Werte der Speicherbytes.

1

Cassebaum, Skript zur Programmierung mit C++

13

1.3.3 Tastaturein- und Bildschirmausgaben

Tastatureingaben werden mit „cin >>“und Bildschirmausgaben mit „cout <<“eingeleitet. Mit cout << wird eine für den Bediener sichtbare Bildschirmdarstellung erzeugt. Als Ziel für Eingaben mit Hilfe von cin >> werden Variablen vereinbart (Beispiel: s und t). Die Variablen erhalten einen Typkenn-zeichner in der Definitionszeile (Beispiel: double).

Beispielaufgabe 2

Das Programm fordert zur Eingabe eines Weges in Metern und einer Zeit in Sekunden auf, speichert diese in Variablen passenden Typs. Danach wird die Geschwindigkeit errechnet und in m/s und km/h auf dem Bildschirm kommentiert ausgegeben.

Einzel-Zeichen (engl.: character) werden in Apostrophen eingeschlossen (z.B.: '$') und bei Eingaben in Variablen vom Datentyp char gespeichert. C++ - Zeichenketten werden in Anführungsstrichen ein-geschlossen (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 Zei-chenkette eine besondere Steuerung veranlassen. Steuerfolgen sind z.B.:

\n → Nächste Zeile einstellen \t → Tabulatorabstand setzen \a → Piepsignal ausgeben \" → auszugebende Anführungsstriche " \\ → auszugebendes Einzel-Backslash \

Übungsaufgaben

11. Benennen Sie den Datentyp zur Speicherung folgender Wertvorgaben: a) natürliche Zahlen im Bereich von 0...25334 b) Ganze Zahlen (z.B. –3452, 0, +23, ...) c) die reellen Zahlen 12.1234567890123 bis zur letzten Stelle d) Nachnamen von Personen (z.B.“Krause“, “Lehmann“, ... Einzelne Buchstaben (z.B. ’a’,’b’,’c’,...) e) Logische Aussagen (true oder false) f) Ganze Zahlen (z.B. –3452, 0, +23, ...) g) In Größe soll nichts gespeichert oder zurückgegeben werden. h) Ganze Zahlen (z.B. –3452, 0, +23, ...)

12. Sie sehen eine Liste von insgesamt zehn C-Datentypen: a) long int b) int c) unsigned int d) signed int e) char f) string g) real h) long double i) float j) bool. Bestimmen Sie für alle 10 Typ-Buchstaben die richtige Datentyp-Zahl als Wertepaar. (Beispiel: a-3)

(1) vorzeichenbehafteter Ganzzahlentyp (6) Arraydatentyp (11) einfacher Ganzzahltyp (2) einfacher reeller Typ (7 Stellen genau) (7) Zeichentyp (12) logischer Datentyp (3) doppelt genau reell (15 Stellen genau) (8) Ganzzahl (8Byte Länge) (13) Zeichenkettentyp (4) Zahlentyp der Reallogik (9) unsichtbarer Datentyp (14) Kommafolgentyp (5) langer Zeichenkettentyp (10) Typ für natürliche Zahlen (15) kein C-Datentyp

13. Geben Sie den C-Datentyp an, der zur Speicherung folgender Daten am besten geeignet ist:

a) Alter eines Menschen b) Rauminhalt eines Hauses c) Kapazität eines Kondensators d) Kfz-Kennzeichen e) Telefonnummer (mit Fernwahl) f) Namen der Schüler einer Klasse

g) Möglichst genaue Speicherung der Zahl (Pi) h) Geschlecht einer Person i) Das Geburtsdatum einer Person k) genaueste mögliche Zeitdauer

01 #include <iostream> 02 using namespace std; 03 int main() 04 { double s,t; 05 cout << "\"Geschwindigkeitsberechnung\"\n"; 06 cout << "\nWeg s [in m] : "; cin >> s; 07 cout << "Zeit t [in s] : "; cin >> t; 07 cout << "\nGeschwindigkeit : " << s/t << " m/s" 08 << "\noder " << s/t * 3.6 << " km/h"; 09 getchar(); // Wartet auf die Eingabe einer beliebigen Taste 10 return 0; // Liefert Rückkehrcode der main-Funktion (0 bedeutet: Ablauf gut) 11 } // Eine schließende geschweifte Klammer schließt die Funktion ab

Geschwindigkeitsberechnung Weg s [in m] : 30 Zeit t [in s] : 5 Geschwindigkeit : 6 m/s oder 21.6 km/h

Cassebaum, Skript zur Programmierung mit C++

14

1.4 Operatoren und Ausdrücke

1.4.1 Operatoren

OOppeerraattoorreenn beziehen sich auf einen oder zwei OOppeerraannddeenn und liefern ein operationstypisches Resul-tat. Größen (z.B. Variablen, Werte, ...) der Sprache C++, die mit Operanden einfach oder vielfach ver-knüpft wurden, nennt man OOppeerraattiioonn oder AAuussddrruucckk.

x = y+3; „y“ und „3“ sind Operanden, „+“ ist ein Operator, „y+3“ ist eine Operation.

Die Operanden und das Resultat besitzen einen operationsabhängigen Datentyp. Die Einteilung der Operatoren in Gruppen geschieht in Abhängigkeit der nutzbaren Datentypen. Wichtige Operatoren:

nnuummeerriisscchhee OOppeerraattoorreenn

++ (Inkrement) -- (Dekrement) * (Multiplikation) / (Division) % (modulo) + (Addition) - (Subtraktion)

llooggiisscchhee OOppeerraattoorreenn

! (Negation) > (größer?) >= (größer gleich?) < (kleiner?) <= (kleiner gleich?) == (gleich?) != (ungleich?) && (logisches "UND") || (logisches "ODER")

bbiittwweeiissee OOppeerraattoorreenn

~ (Komplement) >> (Rightshift) << (Leftshift) & (AND) ^ (XOR) | (OR)

ZZuuwweeiissuunnggssooppeerraattoorreenn

= (ergibt) += (plus gleich) -= (minus gleich) *= (mal gleich) /= (durch gleich) &= (und gleich) %= (modulo gleich)

ssoonnssttiiggee OOppeerraattoorreenn

sizeof (Bytelänge) new (dynam. Speicher erstellen) delete[] (dynam. Speicher freigeben) typeid (Typidentifikation) (cast) (expliziter Typumwandler) <log.Ausdruck> ? <true-Wert> : <false-Wert> (Fragezeichenoperator)

Beispiele: int x=2; x+=3<<1; cout << x; // Ausgabe: 8 int y=11; cout << (--(y%5)); // Ausgabe: 0 int x=5; cout << ((x-5)?5+x:x>>1); // Ausgabe: 2 char x='A'; cout << x << "-" << (int)x; // Ausgabe: A-65

Operatoren sind in eine RRaannggffoollggee geordnet, so dass innerhalb eines Ausdrucks zunächst die vorrangi-gen Operatoren realisiert werden. Ausdrücke mit Operatoren können mit Rundklammern ggeekkllaammmmeerrtt werden, um die Operatoren in der Klammer im Rang zu bevorzugen.

[()[]-> :: .][! ~ ++ -- sizeof new delete typeid (typumformer)] [.* ->* ][ * / % ][ + - ]

[<< >> ][ < <= > >= ][ = = != ] RRaannggttaabbeellllee ddeerr OOppeerraattoorreenn [ & ][ ^ ][ | ][ && ][ || ][ ?: ] [= += - = *= /= %= >>= <<= &= ^= ]

Rangfolge aller Operatoren in eckigen Klammern [ … ] sind gleichrangig.

Der Rang der Klammergruppen ist von oben nach unten absteigend, d.h. es gilt: „oben vor unten“.

Der Rang der Klammergruppen ist von links nach rechts absteigend, d.h. es gilt: „links vor rechts“.

Ohne Rundklammern werden gleichrangige Operatoren von links nach rechts abgearbeitet.

Beispiele: 12/2+4 ergibt 10, aber: 12/(2+4) ergibt 2. 3+(x&&0) ergibt 3, aber: 3+x&&0 ergibt 4.

Cassebaum, Skript zur Programmierung mit C++

15

1.4.2 Numerische Ausdrücke

Numerische Ausdrücke <NA> sind alle C++ Bestandteile, die einen Zahlenwert besitzen. Wichtige Bei-spiele für numerische Ausdrücke sind:

(1) Logische Werte ( true besitzt den Wert 1, false besitzt den Wert 0 ),

(2) Zahlenwerte (Zahlkonstanten, ganzzahlig: 2, -4, 0xa, ... reell: 0., .3, 3.1e4,... ),

(3) C++Größen (Variablen, u.a.) mit numerischem Datentyp (int, float, double, ... )

(4) Werte, die mit Operatoren verknüpft sind und ein numerisches Resultat liefern. (z.B.: 3>7 →0, 2!=3 →1, 5/3 →1, 7&12 →4, ~1 →-2, 5%3 →2, 5e1/5 →10.)

(5) Ausdrücke, die mit logischen Operatoren verknüpft sind und numerische Werte besitzen. (z.B.: 0&&true →false →0, (2>3)||(0!=1) →true →1, !(7==3)&&5 →true →1)

Beispiele für numerische Ausdrücke mit numerischem Ergebniswert:

cout << "3 * 2 = " << 3 * 2; // 6 cout << "\n3 / 2 = " << 3 / 2; // 1 (1 Rest 1) cout << "\n3 / 2. = " << 3 / 2.; // 1.5 cout << "\ntrue = " << true; // 1 cout << "\nfalse = " << false; // 0 cout << "\n0xa = " << 0xa; // 10 (hex a = dec 10) cout << "\n0xa = " << hex << 0xa; // a (hex a = hex a) cout << "\n027 = " << dec << 027; // 23 (oct 27 = dec 23) cout << "\n027 = " << oct << 027; // 27 (oct 27 = oct 27) cout << dec << "\n7&12 = " << (7 & 12); // 4 (0111 & 1100 = 0100) cout << "\n5&3 = " << 5%3; // 2 (5/3 = 1 Rest 2) cout << "\n5e1/5 = " << 5e2/50; // 10 (5*10²/50 = 10)

1.4.3 Logische Ausdrücke

Logische Ausdrücke <LA> sind alle C++ Bestandteile, die einen Wert true oder false besitzen. Wichtige Beispiele für logische Ausdrücke sind:

(1) Logische Werte (Die Konstanten true (1) oder false (0) ),

(2) Zahlenwerte (Ein Wert = 0 gilt per Definition false, alle Werte ungleich 0 sind true),

(3) C++Größen (Variablen, Funktionsrufe, ...) mit Datentyp bool (besitzen einen log. Wert),

(4) Werte, die mit Operatoren verknüpft sind und ein logisches Resultat liefern

( z.B.: 3>7→false, 2!=3→true, 7==3→false, "Hans">="Lutz" → false )

(5) Logische Ausdrücke, die mit logischen Operatoren verknüpft sind ( z.B.: 0&&true → false, (2>3)||(0!=1) → true, !(7==3)&&5 → true ).

And && 1 0 Or || 1 0 not !

1 1 0 1 1 1 1 0

0 0 0 0 1 0 0 1

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"; // false if (i) cout << "i ist true"; else cout << "i ist false"; // true if (x) cout << "x ist true"; else cout << "x ist false"; // false if (i-2) cout << "i-2 ist true"; else cout << "i-1ist false"; // false if (!a) cout << "!a ist true"; else cout << "!a ist false"; // true cout<<"i==2||i==3 ";if(i==2||i==3)cout<<"true";else cout <<"false"; // true

Cassebaum, Skript zur Programmierung mit C++

16

Beispielaufgabe 3

Das Programm untersucht einen C++-Ausdruck hinsichtlich seines numerischen und logischen Wertes. Der numerische Wert wird als reelle Zahl und der logische als „true“ oder „false“ ausgegeben.

Beispielaufgabe 4

Das Programm untersucht die drei als Variablen a, b, c gegebenen möglichen Seitenlängen eines Drei-ecks. Stellen Sie mit den Dreiecksungleichungen fest, ob die 3 Seiten ein Dreieck bilden können. Geben Sie das Ergebnis auf dem Bildschirm mit „Dreieck“ oder „kein Dreieck“ aus.

Übungsaufgaben

Für die Lösung der folgenden Aufgaben wird vorausgesetzt, dass folgende Vereinbarungen vorher vor-genommen wurden: int a=2, x=0; bool b=true; double c=-2.4, d=3.1;

14. Schreiben Sie ein C++ Programm das die numerischen und logischen Werte der Variablen a, b, c, d und x auf dem Bildschirm ausgibt.

15. Welcher der folgenden Ausdrücke ist ein numerischer Ausdruck? Bestimmen Sie den numerischen Wert für alle numerischen Ausdrücke!

a) main() b) x c) x + 2 d) // Berechnung e) a * 2 / 3 f) a > x g) (i==2) || (i==3) h) a % 5 i) true j) float k) a * 3 / 2 % 4 l)((3>4)-(3<4))*2 m) b + 7 n) "Willi" o) 5 + ’2’ p) 3++ q) { } r) d + b - 1.5 s) (a+b+d) /3 *2 t) !x u) iostream.h v) 2 ^ ( 1 / 2 ) w) 3.14 * a % 3 x) endl

16. Welche der Ausdrücke aus Aufgabe 15 sind logische Ausdrücke? Bestimmen Sie den logischen Wert für diese Ausdrücke!

17. Wenn im dezimalen Ausdruck 111.111 der Dezimalpunkt um eine Position nach rechts verschoben wird, verzehnfacht sich der numerische Wert. Bei einer Verschiebung nach links entsteht ein Aus-druck, der einem Zehntel des Ursprungswertes entspricht. Schreiben Sie diese beiden Sätze für

a) hexadezimale und b) duale Werte auf !

18. Erklären Sie die Begriffe a) Operator, b) Operation und c) Operand!

19. Beschreiben Sie die Bedeutung eines cast-Operators! Geben Sie drei Beispiele!

20. Definieren Sie eine passende Ergebnisvariable und weisen Sie dieser einen passenden Ausdruck zu!

a) Die numerisch exakte Hälfte vom 5-fachen der Variablen a, b) falls c/x wahr ist, den vierfachen, sonst den zehnfachen Wert des Ausdrucks d+c , c) a und d sind die Katheten eines rechtwinkligen Dreiecks, gesucht ist die Hypotenusenlänge, d) das Produkt der Variablen c und b dividiert durch die Summe der Variablen a, b und x, e) der ASCII-Code des im Alphabet folgenden Buchstabens nach ’A’, f) das Zeichen mit dem ASCII-Code, der dem 12fachen des Ausdrucks (123%6) entspricht.

01 #include <iostream> 02 using namespace std; 03 int main() 04 { string s = ((63/5)%7)?"true":"false"; 05 cout << "numerisch: " << (double)((63/5)%7); 06 cout << "\n logisch: " << s; 07 getchar(); 08 return 0; 09 }

numerisch: 5 logisch: true

01 #include <iostream> 02 using namespace std; 03 int main() 04 { float a=6, b=3, c=2.5; string s = (a+b>c)&&(a+c>b)&&(b+c>a)?"Dreieck":"Kein Dreieck"; 05 cout << s; 06 getchar(); 07 return 0; 08 }

Kein Dreieck

Cassebaum, Skript zur Programmierung mit C++

17

1.5 Strukturanweisungen

1.5.1 Sequenz

SSeeqquueennzzeenn sind Programmstrukturen, die eine Folge von ausführbaren Anweisungen enthalten. In C/C++ werden die Anweisungen grundsätzlich mit einem Semikolon (nicht mit dem Zeilenende!!) abge-schlossen. Anweisungen werden in den Reihenfolgen "von links nach rechts" und "von oben nach un-ten" abgearbeitet.

Sequenzen in der SSttrruukkttooggrraammmm-Darstellung:

Mit der in Abb.4 dargestellten Zeichnung wird bestimmt, dass der Block A vor dem Block B abgearbeitet wird.

Ausgabe der Eingabeaufforderung am Bildschirm (BS).

Eingabe von Tastatur (Tas) in der Variablen U speichern.

Ausgabe der Eingabeaufforderung am Bildschirm (BS)

Eingabe von Tastatur (Tas) in der Variablen I speichern.

Ausgabe des errechneten Ergebnisses am Bildschirm (BS)

double U, I; // Variablen U und I definieren cout << "Programm zur Widerstandsberechnung\n"; // Ausgabe Titel cout << "\nSpannung U [in V] : "; cin >> U; // Ausgabe und Eingabe U cout << "Stromstärke I [in A] : "; cin >> I; // Ausgabe und Eingabe I cout << "\nGeschwindigkeit : " << U/I << " Ohm"; // Ausgabe Ergebnis U/I

Übungsaufgaben

21. Sie lassen sich über Tastatur Name und Alter einer Person eingeben. Anschließend geben Sie über Bildschirm den Satz aus: In 10 Jahren bist Du schon <xx> Jahre alt, <Name>! Für <xx> wird das um 10 Jahre erhöhte, eingegebene Alter ersetzt, für <Name> der eingegebene Vorname!

22. Über Tastatur sollen drei Temperaturangaben a, b, c (mit 2 Kommastellen, <1000°C) eingegeben werden. Sie geben das arithmetische Mittel e mit folgendem Ergebnissatz aus: Das arithmetische Mittel der gegebenen Temperaturwerte … °C, … °C und … °C ist … °C!

23. Über Tastatur sollen die Kilometerstände von zwei vollen Betankungen eingegeben werden. Weiter werden der Rechnungsbetrag der 2.Betankung und der Literpreis des Kraftstoffs in Euro eingegeben. Bestimmen Sie den durchschnittlichen Verbrauch in Liter pro 100 km!

1.5.2 Selektion

Eine SSeelleekkttiioonn (auch: Auswahl, Wahlstruktur, Alternative) ist eine Programmstruktur, die eine Ver-zweigung abhängig von einem logischen Ausdruck (abgekürzt <LA>, kann „wahr“→true oder „falsch“ →false sein) enthält.

Eine einfache Selektion wird in C/C++ mit if (<lloogg.. AAuussddrruucckk>) <AAnnwweeiissuunngg>; konstruiert.

Die AAnnwweeiissuunngg wird nur ausgeführt wird, wenn der <llooggiisscchhee AAuussddrruucckk> den Wert true enthält.

Einfache Selektion in der Struktogramm - Darstellung

Mit der Zeichnung in Abb. 5 wird erklärt, dass wenn der logische Ausdruck <LLAA> = true ist, der Block AA ausgeführt und anderen-falls nichts geschieht.

A:(BS) : "Spannung U[V]:"

E:(Tas) : U

A:(BS) : "Stromstärke I[A]:"

E:(Tas) : I

A:(BS) : U / I, "Ohm"

A

B Abb.4

J N

AA

<LLAA> ?

Abb. 5

Cassebaum, Skript zur Programmierung mit C++

18

Für eine zweiseitige Selektion muss eine Anweisung „else“ unmittelbar nach der „if“-Anweisung eingefügt werden. Die else-Anweisung zeigt die auszuführende Anweisung für den „false“-Fall.

if (<LA>) < AAnnwweeiissuunngg AA im Fall <LA>=true >; else < AAnnwweeiissuunngg BB im Fall <LA>=false >;

Zweifache Selektion in der SSttrruukkttooggrraammmm-Darstellung

Mit der Zeichnung in Abb. 6 wird erklärt, dass wenn der logische Ausdruck <LA> = true ist, der Block AA ausgeführt wird. Für den Fall, dass der logische Ausdruck <LA> den Wert „false“ besitzt, wird der Block BB realisiert.

bool a; char s; cout << "Ist es hell draussen? [j/n] : "; cin >> s; if(s = = 'j') cout << "\nGuten Tag!"; // true-Fall else cout << "\nGute Nacht!"; // false-Fall a=(s = = 'j') ; // logische Wertzuweisung if(a) // einfache Selektion ohne else { cout << "\nDie Antwort war: Ja!"; // mit Mehrfachanweisung a = false ; }

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

MMeehhrrffaacchhaannwweeiissuunnggeenn mit {…} geklammert und damit gemeinsam bedingt ausgeführt werden.

Beispiel: if(x<2) { x++; cout << "x wurde inkrementiert"; }

Sollen mehrere logische Ausdrücke geprüft werden, dürfen die logischen Verknüpfungsoperatoren && (and), || (or), ! (not) genutzt werden.

Beispiel: if( (x>=0) && (x<130) ) cout << "x ist eine mögliche Altersangabe";

Eine einfache Wertzuweisung kann ebenfalls bedingt (d.h. abhängig vom Wert eines logischen Aus-drucks) erfolgen. Man benutzt den FFrraaggeezzeeiicchheennooppeerraattoorr in der Form:

<D> = <LA> ? <W1> : <W2>;

Dem Datenobjekt <D> (z.B. x) wird der Wert <W1> (z.B. 0) zugewiesen, wenn der logische Ausdruck <LA> (z.B.(a<2)) wahr ist. Anderenfalls wird der <W2> (z.B. 4) zugewiesen.

z.B.: int x = (a<2)?0:4; // x wird 0 für (a<2)=true, sonst 4

Übungsaufgaben

24. Geben Sie die gefahrenen Meter (k) und die benötigten Sekunden (s) für eine Fahrstrecke ein! Zei-gen Sie über Bildschirm die Geschwindigkeit für den Fall k<1000 in m/s und sonst in km/h an!

25. Geben Sie die Nummer einer Ampelleuchte ein und antworten Sie mit deren Farbe! (z.B.: Eingabe: 2, Antwort: “gelb!“, Eingabe: 4, Antwort: “falsch!“)

26. Geben Sie drei Zahlen ein und geben Sie diese in aufsteigender Reihenfolge aus!

27. Antworten Sie auf eine Tasteneingabe passend mit „Buchstabe“, „Ziffer“ oder „Sonderzeichen“!

28. Geben Sie eine Tages-, eine Monats- und eine Jahreszahl ein. Entscheiden Sie, ob die Angabe ein gültiges Datum nach dem gregorianischen Kalender sein könnte.

Hinweis: Jedes durch 4 teilbare Jahr ist ein Schaltjahr (29 Tage im Februar) mit Ausnahme aller durch 100 und nicht durch 400 teilbaren Jahreszahlen.

29. Welchem numerischen Wert entsprechen die Ausdrücke, wenn int a=4; bool b=true; vorlief?

a) (!b)?a:b b) a?6:!b c) ((a<5)&&a)?a:3 d) (b||a)?a^6:11 e) ('e'-'a')?a&6:(~a)

J N

AA BB

<LA> ?

Abb. 6

Cassebaum, Skript zur Programmierung mit C++

19

1.5.3 Mehrfachauswahl (Fallunterscheidung)

Eine MMeehhrrffaacchhaauusswwaahhll (auch: FFaalllluunntteerrsscchheeiidduunngg) ist eine Programmstruktur, die abhängig vom Wert eines ganzzahligen Ausdrucks <GA> endlich viele Verzweigungen enthalten.

Fallunterscheidung in der SSttrruukkttooggrraammmm-Darstellung:

In Abb. 7 wird aufgezeigt, dass der abzuarbeitende Block x abhängig vom Wert des ganzzahligen Ausdrucks <GA> aus-geführt wird. Ist <GA> = 1, so wird Block A, für <GA> = 2 Block B, für <GA> = 3 Block C, ansonsten wird Block D aus-geführt.

Die Mehrfachauswahl wird in C/C++ konstruiert mit:

switch ( <ganzzahliger Ausdruck> ) { case <ganzzahliger Ausdruck 1> : Anweisung 1 ;[ break ;]

[[ case <ganzzahliger Ausdruck 2> : Anweisung 2 ;[ break ;]] ...]

[ default : Anweisung 3 ;]

}

Die Anweisung nach einem case wird ausgeführt, wenn der in switch geklammerte ganzzahlige Aus-druck identisch mit dem Ausdruckswert des case ist. Danach werden alle folgenden Anweisungen bis zu der den switch-Block abschließenden geschweiften Klammer ausgeführt.

Eine break-Anweisung beendet diese Ausführung schon vorher. Gerade diese Form der Beendigung eines case-Falles wird besonders häufig benötigt, weil ohne break alle nachfolgenden case-Fälle bis zum Auftreten eines break’s oder bis zur schließenden geschweiften Klammer der switch-Anweisung abgearbeitet werden!

01 char s = 2;

02 switch(s) 03 { case 0: cout << "\n0 kommt nicht"; 04 case 1: cout << "\n1 kommt nicht"; 05 case 'c'-'a': cout << "\n2 kommt"; 06 case 3: cout << "\n3 kommt"; 07 cout << "\n3 kommt"; 08 case 4: cout << "\n4 kommt"; break; 09 case 'a': cout << "\n'a' kommt nicht"; 10 default: cout << "\n kommt nicht"; 11 }

Was wird im dargestellten Beispiel ausgegeben? Betrachten Sie die Ausgaben nach einer Änderung der Zeile 01 für die Fälle s = { 0, 1, 2, 3, 4, 'a', …} !

Übungsaufgaben

30. Lösen Sie die Aufgabe 25 (Ampelaufgabe) noch einmal, aber diesmal mit switch/case!

31. Für einzugebende Dezimalziffern 0,…,9 soll wahlweise die englische oder die deutsche Wortschrift der Ziffer gezeigt werden. ( z.B.: Ziffer: 3 Sprache[d/e]: e Antwort: three)

32. Zeigen Sie den englischen Countdown in Wortschrift ab einer eingegebenen Dezimalziffer 0,…,9! (z.B.: Ziffer: 5 Ausgabe: five four three two one zero )

33. Antworten Sie für die Buchstaben a, o, u, A, O, U mit den passenden deutschen Umlauten! (z.B.: Buchstabe: o Umlaut: ö)

Abb. 7

1 2 3 sonst

A B C D

<GA> ?

Cassebaum, Skript zur Programmierung mit C++

20

1.5.4 Kopfgesteuerte Schleifen

Eine Mehrfachausführung einer Anweisung (eines Anweisungsblockes) wird

SScchhlleeiiffee ( auch: ZZyykklluuss, WWiieeddeerrhhoollssttrruukkttuurr, IItteerraattiioonn ) genannt.

Die Eigenschaft „kkooppffggeesstteeuueerrtt“ steht dafür, dass die AArrbbeeiittssbbeeddiinngguunngg (ein logischer Ausdruck) schon vor Ausführung des „Schleifenkörpers“ auf den Inhalt „true“ überprüft wird. Der SScchhlleeiiffeennkköörrppeerr ist die Anweisung oder der Anweisungsblock in geschweiften Klammern { } der zyklisch auszuführenden Anweisungen.

Wenn die Arbeitsbedingung den Wert „false“ enthält, wird die Schleifenbearbeitung beendet. Durch das Erreichen einer Anweisung „break“ kommt es ebenfalls zum Schleifenende. Wird im Schleifen-körper eine Anweisung „continue“ erreicht, wird die Bearbeitung der Anweisungen des Schleifen-körpers unterbrochen und die Schleife mit der erneuten Überprüfung der Arbeitsbedingung fortge-setzt.

1.5.4.1 WHILE

Kopfgesteuerte Schleife in der SSttrruukkttooggrraammmm-Darstellung:

Mit der dargestellten Zeichnung wird bestimmt, dass solange der logi-sche Ausdruck <LA> = true ist, die Anweisung(en) des Schleifen-körpers ausgeführt werden. Sollte <LA> niemals false werden, so handelt es sich um eine unendliche Schleife.

Die while-Anweisung konstruiert mit einem Parameter eine kkooppffggee--

sstteeuueerrttee Schleife (aabbwweeiisseennddee Schleife).

while ( <log. Ausdruck> ) AAnnwweeiissuunngg ;

while ( <log. Ausdruck> ) { AA; BB; CC; }

(1) Wenn der logische Ausdruck zum Schleifenbeginn false ist, endet die Bearbeitung der Schleife.

(2) Wenn der logische Ausdruck zum Schleifenbeginn true ist, wird Anweisung(-sblock) ausgeführt.

(3) Nach dem Beenden der Anweisung (ohne break) beginnt ein neuer Schleifenlauf mit (1).

Anstelle einer einzelnen Anweisung nach „while(…)“ wird in den meisten Fällen eine in geschweifte Klammern gesetzter Block mehrerer Anweisungen aufgebaut („Mehrfachanweisung“). So besteht der Schleifenkörper aus beliebig vielen Anweisungen, die als Gesamtheit wiederholt ausgeführt werden. Die Schleife kann durch eine eingefügte break, return oder exit() -Anweisung abgebrochen wer-den. Normalerweise werden diese Anweisungen selektiv in einer if-Anweisung aufgerufen.

Die Anweisung return beendet die Funktion und die Standardfunktion exit() beendet das gesamte Programm, in denen sie sich befinden.

01 #include <conio.h> // conio-Header für kbhit-Funktion 02 int z=0; // Zählvariable 03 while(!kbhit()) // kbhit() ist true, wenn eine Taste gedrückt wurde 04 cout << z++ << " "; // Zähle bis Tastendruck, Ausgabe: 1 2 3...

Der logische Ausdruck „!kbhit()“ im Programmbeispiel ist eine asynchrone Arbeitsbedingung für eine while-Schleife. Eine Arbeitsbedingung wird dann aassyynncchhrroonn genannt, wenn die Gesamtzahl der Schleifendurchläufe für das ausführende System nicht vorhersehbar ist. Sie heißt ssyynncchhrroonn, wenn die Schleifendurchlaufzahl berechenbar ist.

Beispiele für eine synchrone Schleifen:

int i=5; while(i--) cout << i; // gibt aus: 43210 (5 Schleifendurchläufe) int i=5; while(i>2) cout << i--; // gibt aus: 543 (3 Schleifendurchläufe) int i=5; while(i) {cout << i; i-=2; } // gibt aus: 531... (∞ Schleifendurchläufe) int i=5; while(i) cout << " "; // Ausgabe unsichtbar (∞ Schleifendurchläufe)

Schleifenkörper

wwhhiillee (<LLAA>)

Abb. 8

Cassebaum, Skript zur Programmierung mit C++

21

Eine oft benötigte Anwendung einer Schleife mit synchroner Arbeitsbedingung ist die ZZäähhllsscchhlleeiiffee, die für eine festzulegende Anzahl von Schleifendurchläufen konstruiert wird. In C/C++ gibt es eine zweite Form der kopfgesteuerten Schleife, die für die Konstruktion von Zählschleifen besonders gut geeignet ist. Sie wird im folgenden Kapitel betrachtet.

1.5.4.2 FOR

Die for-Anweisung konstruiert mit 3 Parametern eine kkooppffggeesstteeuueerrttee (aabbwweeiisseennddee) Schleife.

Kopfgesteuerte Schleifen in SSttrruukkttooggrraammmmeenn:

Mit der dargestellten Zeichnung wird bestimmt, dass solange der logische Ausdruck <LA> = true ist, die Anweisung(en) des Schleifenkörpers ausgeführt werden. Sollte <LA> niemals false werden, so handelt es sich um eine unendliche Schleife.

for (<Anweisung 1>;<log.Ausdruck>;<Anweisung 2>) Anweisung 3;

(1) In jedem Fall erfolgt die Ausführung von Anweisung 1 genau einmal vor der Arbeitsbedingungsprüfung.

(2) Arbeitsbedingungsprüfung: wenn der log.Ausdruck zum Schleifenbeginn false ist, wird die Schleife beendet, sonst wird mit (3) fortgesetzt.

(3) Ausführung der Anweisung 3 und nachfolgend Anwei-sung 2. Anschliessend wird mit (2) zyklisch fortgesetzt.

In Abb. 10 wird als Struktogramm und als Programmablaufplan – „PAP“ gezeigt, in welcher Reihenfolge die Schrittfolge einer for-Anweisung abläuft. Mit etwas Überlegung wird erkennbar, dass jedes „for“-Konstrukt auch als „while“-Konstrukt geschrieben werden kann. Die nachfolgenden Beispiele zeigen zwei im Ablauf identische Programmkonstrukte:

int i = 0; // <A1> while(i<4) // <LA>? { cout << i; // <A3> i++; } // <A2>

int i; for(i=0;i<4;i++) // <A1>,<LA>,<A2> cout << i; // <A3>

Es handelt sich bei diesen Beispielen um je eine Zählschleife, die eine LLaauuffvvaarriiaabbllee i zur Zählung der Schleifendurchläufe vom SSttaarrttwweerrtt 0 bis zum nicht erreichten EEnnddwweerrtt 4 mit der SScchhrriittttwweeiittee 1 ver-wenden. Es kommt zu 4 Zyklen { i= 0, 1, 2, 3 }.

Anweisungen im Schleifenkörper werden auch hier meist als eine in geschweifte Klammern gesetzte Mehrfachanweisung aufgebaut. Für die Anweisung <A2> kann zum Einbau mehrerer Anweisungen an das Schleifenende auch mit dem KKoommmmaaooppeerraattoorr gearbeitet werden:

01 int sum=0, m=0, k=0; 02 for(int i=1 ; i<=100 ; i++,k++,m+=2 ) sum+=i; 03 cout << sum << endl << m << endl << k;

Eine oft erforderliche Technik ist die Konstruktion von vveerrsscchhaacchhtteelltteenn SScchhlleeiiffeenn. Im folgenden Bei-spiel wird eine Multiplikationstabelle mit zwei Zählschleifen zur Anzeige des „kleinen Einmaleins“ auf dem Bildschirm dargestellt:

01 for(int i=1;i<10;i++) // äußere for-Schleife 02 { for(int j=1;j<10;j++) // innere for-Schleife 03 cout << i*j << “\t“; // Schleifenkörper der inneren Schleife 04 cout << endl; // Teil des Schleifenkörpers der äußeren Schleife 05 } // Ende des Schleifenkörpers der äußeren Schleife

Wie die while-Anweisung ist auch die for-Anweisung durch continue unterbrechbar, oder mit break, return oder exit()endgültig abbrechbar.

<A1>

<LA>?

<A3>

<A2>

Schleifenkörper <A3>

for (<A1>;<LA>;<A2>)

Abb. 9

<A1>

while <LA>

<A2>

<A3>

Abb. 10

Cassebaum, Skript zur Programmierung mit C++

22

1.5.5 Fußgesteuerte Schleife

Die do-while-Anweisung konstruiert eine ffuußßggeesstteeuueerrttee Schleife (nniicchhtt aabbwweeiisseennddee Schleife).

(1) Ausführung der Anweisung(en) im Schleifenkörper

(2) Nach dem Beenden der Anweisung (ohne break) wird der Wert des log. Ausdrucks ermittelt. Wenn der Wert false ist, endet die Schleife sofort, sonst beginnt ein neuer Durchlauf mit (1).

Abb. 11 do Anweisung; while ( <log. Ausdruck> );

01 int x; // Ausgabe aller geraden Zahlen, 02 do { cout << "x: "; cin >> x; // beginnend mit einer eingege- 03 } while(x<=0); // benen Zahl x (rückwärts bis 2) 04 do { if(!(x%2)) cout << x << " "; 05 } while (--x>0);

Der Anweisungsblock {…} des Schleifenkörpers kann durch eine continue-Anweisung vorzeitig un-terbrochen werden. Die Schleife wird danach sofort mit der Überprüfung des logischen Ausdrucks fortgesetzt und beginnt im true-Fall erneut die Anweisung abzuarbeiten. Wie die while-Anweisung ist auch die do-while-Anweisung durch break, return oder exit()endgültig abbrechbar. Die An-wendung der do-while-Schleife sollte in Fällen angewendet werden, wenn der erste Schleifendurch-lauf in jedem Fall durchgeführt werden soll.

Beispielaufgabe 5

Das Programm gibt auf dem Bildschirm eine Tabelle des kleinen Einmaleins für die Produkte der Zahlen von 1 bis 10 vollständig und geordnet aus.

Der Header iomanip erlaubt zusätzliche Ein-/ Ausgabemanipulationen. Bei dieser Aufgabe wird für jede ausgegebene Zahl mit setw(4) eine Ausgabebreite von gleichbleibend 4 Zeichen bewirkt.

Beispielaufgabe 6

Bestimmen Sie den Wert des Binomialkoeffizienten .

do

Schleifen-körper

while (<LA>);

01 #include <iostream> 02 #include <iomanip> 03 using namespace std; 04 int main() 05 { for( int i=1; i<=10; i++, cout<<endl ) 06 for( int j=1; j<=10; j++ ) 07 cout << setw(4) << i*j; 08 getchar(); 09 return 0; 10 }

1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100

01 #include <iostream> 02 using namespace std; 03 int main() 04 { float m=7, n=2, b=1; 05 cout << "Binomial(" << m << "," << n << ") = "; 06 if( m >= n ) 07 while(n) // n!=0 ist true, n==0 ist false 07 b *= m-- / n--; // erst nach Multiplikation und Division folgen die Dekremente -- 08 cout << b; 09 getchar(); 10 return 0; 11 }

Binomial(7,3) = 21

)!(!

!

nmn

m

n

m

Cassebaum, Skript zur Programmierung mit C++

23

Übungsaufgaben

34. Geben Sie über Bildschirm 30 mal das Wort „Software“ aus! Lösen Sie das Problem mit den Schlei-fenkonstruktionstypen a) for, b) while, c) do while!

35. Geben Sie Zahlenwerte nacheinander über Tastatur ein, bestimmen Sie das Maximum, das Mini-mum und das arithmetische Mittel und geben Sie die Ergebnisse kommentiert aus!

36. Es ist eine natürliche Zahl x über Tastatur einzugeben. Errechnen Sie die Summe aller ungeraden Zahlen u, für die gilt u<x und u>0! Bei Eingabefehlern wird eine Ausschrift gegeben (z.B. „x ist keine natürliche Zahl!“, „x ist zu groß oder zu“).

37. Der Bediener gibt eine Ziffer n und ein Zeichen ein. Geben Sie das Zeichen n mal aus!

38. Geben Sie über Tastatur 10 Werte ein und geben Sie diese absteigend sortiert über Bildschirm aus!

39. Geben Sie das Alphabet mit großen und kleinen Buchstaben (zyklisch!) aus!

40. Geben Sie alle geraden Zahlen zwischen a und b aus (Die ganzen Zahlen a und b sind vorher über Tastatur einzugeben).

41. Geben Sie dauerhaft Sternchen (*) über Bildschirm aus, bis eine beliebige Taste betätigt wird!

42. Errechnen Sie für ein Lottospiel anhand der einzugebenden höchstmöglichen Tippzahl (z.B.: tmax=49) und der Anzahl der Tippzahlen (z.B.: tz=6), wie viel verschiedene Tipps es gibt! Mathe-matisch: [tmax*(tmax-1)*(tmax-2)*…*(tmax-tz)*tmax-(tz+1)+ / *1*2*…*(n-2)*(n-1)*n]

43. Erzeugen Sie eine Potenzierungstabelle mit allen Werten des Ausdrucks xy für alle x,yЄ,1;2;…;9} !

44. Benennen Sie eine C++ Anweisung zur Realisierung folgender Schritte:

a) Definition zweier reeller Variablen doppelter Genauigkeit; b) Selektion nach dem Inhalt der ganzzahligen Variablen x für mehr als zwei Fälle; c) Verminderung des Inhaltes der ganzzahligen Variablen x um 1; d) Tastatureingabe einer reellen Zahl zur Speicherung in der Variablen a; e) Erhöhung der ganzzahligen Variablen x um 5, wenn die logische Variable y den Wert true besitzt; f) 6000-malige Bildschirmausgabe des Wortes „Test“; g) Die int-Variable x erhält Wert 1, wenn die float-Variable v<π ist. Sonst wird x=0 gesetzt; h) Summenbildung aller ganzen Zahlen von 300 bis 2000;

45. Schreiben Sie C++ - Programme und zeichnen Sie zu jeder der Lösungen ein Struktogramm!

a) Geben Sie die ersten 6 Zeilen des Pascalschen Dreiecks auf dem Bildschirm aus!

b) Geben Sie ein einzugebendes Wort gesperrt(Leerzeichen zwischen die Zeichen setzen) aus!

c) Es geben 5 Personen ihr Körpergröße (in Meter) ein. Speichern Sie die einzugebenden Körper-größen in einem Array! Bestimmen Sie die Körpergröße der größten, die der kleinsten Person und das arithmetische Mittel aller fünf Größenangaben.

d) Verfassen Sie eine C++ - Funktion „Sum“, die einen Parameter p (natürliche Zahl) übernimmt und einen Ergebniswert s (natürliche Zahl) zurückgibt. Der Ergebniswert ist die Summe aller ge-

raden Zahlen x, für die gilt: x p (x kleiner oder gleich p). Die Funktion Sum wird von einem Hauptprogramm aufgerufen, das vom Bediener die Eingabe eines aktuellen Parameters für die-se Funktion abfordert und anschließend das Funktionsergebnis über Monitor ausgibt.

e) Versuchen Sie mit beliebigen Zeichenausgaben eine Figur darzustellen, die einem Schachbrett nahe kommt!

f) Schreiben Sie ein Programm, das bei Eingabe von Kleinbuchstaben immer Großbuchstaben zeigt. Alle anderen Zeichen erscheinen wie immer.

Cassebaum, Skript zur Programmierung mit C++

24

1.6 Allgemeine Probleme zur Softwareentwicklung

1.6.1 Wasserfallmodell für den Lebenszyklus einer Software

Das Wasserfallmodell stellt die einzelnen Tätigkeiten, die bei einer Software-Entwicklung anfallen, in einer zeitlichen Reihenfolge. Der jeweilige Folgeschritt kann nur mit Rückbezug auf die vorher laufen-den Folgeschritte und einer gleichzeitigen eventuellen Nachbesserung aufgebaut werden.

Abb. 12

Die Ist-Analyse beschreibt den Zustand des Prozesses vor dem Einsatz der neu zu entwickelnden Soft-ware. Sie stellt die Voraussetzung für die Schaffung der Soll-Analyse, die eine AAuuffggaabbeennsstteelllluunngg zur neuen Software mit einem zugehörigen Pflichtenheft dar.

Die drei in der Zeichnung rroott gekennzeichneten Tätigkeiten stellen die HHaauuppttpprroozzeessssee der Entwicklung dar. Sie werden EEnnttwwuurrff, IImmpplleemmeennttiieerruunngg und TTeesstt genannt.

Im EEnnttwwuurrff wird die Aufgabenstellung in relevante Teile zerlegt. Es gibt eine Reihe von Methoden, die unter dem Oberbegriff „SSyysstteemmaannaallyyssee“ zusammengefasst werden. Besonders interessant ist die Zer-legung der künftigen Software in die drei Grundstrukturen SSeeqquueennzz, SSeelleekkttiioonn und IItteerraattiioonn, die be-reits im vorhergehenden ↑Kapitel 1.5 behandelt wurden. Dabei wird eine zeichnerische, sprachunab-hängige Programmdarstellung als SSttrruukkttooggrraammmmee (↑nachfolgendes Kapitel1.6.2) geschaffen.

Die IImmpplleemmeennttiieerruunngg übernimmt den Entwurf und setzt ihn zu einer uunnggeetteesstteetteenn PPrrooggrraammmmllöössuunngg zusammen. Dazu werden die in dem ↑Kapitel1.1.2 erläuterten Teilschritte der Programmentwicklung benötigt. Gemeint sind die CCooddiieerruunngg in einer Programmiersprache, die ÜÜbbeerrsseettzzuunngg, das LLiinnkkeenn und der SSttaarrtt des Tasks.

Der TTeesstt dient der Prüfung und Nachbesserung des Ergebnisses der Implementierung. Es wird dabei getestet, ob das geschaffene Programmergebnis der vorgegebenen Ziel- und Aufgabenstellung ent-spricht, die im Pflichtenheft dokumentiert wurde. Dazu werden TTeessttddaatteenn genutzt, die möglichst si-cher alle auftretetenden Praxissituationen nachbilden.

Die DDookkuummeennttaattiioonn fasst die Schritte der Entwicklung mit allen Teilschritten schriftlich zusammen und wird gemeinsam mit den Programmdateien und Testdaten abschließend aarrcchhiivviieerrtt. Übungsaufgaben

46. Erklären Sie die Begriffe Testdaten, Codierung, Sequenz, Implementierung, Iteration, Test, Pro-jekt, Grundstruktur, Selektion, Struktogramm, Soll-Analyse, Pflichtenheft und Hybridprogramm!

47. Nennen Sie die Schnittstellen zwischen den einzelnen Tätigkeiten der Softwareentwicklung. Nen-nen Sie für jede Tätigkeit geeignete Software, die den Entwicklungsprozess verbessern könnte.

IIsstt--AAnnaallyyssee

SSoollll--AAnnaallyyssee

EEnnttwwuurrff

IImmpplleemmeennttiieerruunngg

TTeesstt

DDookkuummeennttaattiioonn,, AArrcchhiivviieerruunngg

Cassebaum, Skript zur Programmierung mit C++

25

1.6.2 Struktogramme

Die Struktogramme stellen eine zeichnerische Methode zur Darstellung von Programmentwürfen dar, die den Entwickler zwingt, seinen Entwurf auf die drei Grundstrukturen Sequenz, Selektion und Iterati-on zu beschränken. Gleichzeitig wird das Programm in Strukturblöcke zerlegt, die alle nur einen Ein- und einen Ausgang besitzen („BBlloocckkkkkkoonnzzeepptt“).

Die Struktogrammtechnologie hat sich durch diese beschriebenen Vorteile zur bekanntesten Entwurfs-technologie in der Programmierung entwickelt und dabei die heute veralteten Methode des Pro-grammablaufplans („PAP“) abgelöst. Die wichtigsten zeichnerischen Blockarten werden hier gezeigt:

Sequenz, Folge Selektion, Alternative

Fallunter- scheidung

Kofgesteuerte Schleife

Fußgesteuerte Schleife

Break, Abbruch

A; B;

if(b) A; else B;

switch(x){ case 1:A;… }

while(b) { A; }

do{ A; } while(b);

{ break; }

B wird nach A verarbeitet.

Wenn b==true, dann arbeitet A, sonst B.

Wenn x=1,dann arbeitet A,wenn x=2, dann B, …

Wiederhole A, solange b==true.

Starte A und wiederh. A, so- lange b==true.

Abbruch des Blockes an der break-Position.

Der äußere Halbrahmen des Struktogramms dient dem Eintrag zur Autoren- und Titelinformation. Die sprachlichen Inhalte der rechteckigen Strukturblöcke sind frei zum Zweck wählbar. Die grafische Form und deren Sinn sind aber zwingend vorgeschrieben. Das gesamte Struktogramm bildet immer ein vol-les Rechteck. Struktogramme werden im Normalfall ohne Farben gezeichnet.

Beispielaufgabe 7

Fordern Sie den Bediener auf, eine reelle Zahl einzugeben. Geben Sie auf dem Bildschirm für eine posi-tive Zahl das Zeichen ‚+‘, für eine negative ‚-‘ und für Null ‚0‘ aus. Zeichnen Sie das Struktogramm und erstellen Sie ein C++ Programm.

Beispielaufgabe 8

Bestimmen Sie n! = 1 ⋅ 2 ⋅ … ⋅ n für eine einzugebene natürliche Zahl n. Zeichnen Sie das Struktogramm und erstellen Sie ein C++ Programm.

A

B

while b

A

J b? N

A B

01 #include <iostream> 02 using namespace std; 03 int main() 04 { float x; 05 cout << "Zahl: "; cin >> x; 06 if(x>0) cout << "+"; 07 else { if(x<0) cout << "-"; 08 else cout << "0"; } 09 getchar(); 10 return 0; }

do while b

A

01 #include <iostream> 02 using namespace std; 03 int main() 04 { int n; double f=1; 05 do { cout << "Nat.Zahl: "; cin >> n; 06 } while(n<0); 07 while(n) f*=n--; 08 cout << f; 09 getchar(); 10 return 0; }

Fakultät, 22.7.2011 Th. Cassebaum

do while ( n<0 )

O:Scr "Nat.Zahl:"

f := 1

I:Kbd n

while ( n ) f := f * n

n := n - 1

O:Scr f

BREAK

Vorzeichen, 04.09.2011 Th. Cassebaum

O:Scr "Reelle Zahl: "

I:Kbd x

J x>0 ? N

O:Scr "+"

J x<0 ? N O:Scr "-"

O:Scr "0"

1 2 3 x

A B C D E

Cassebaum, Skript zur Programmierung mit C++

26

Der äußere Halbrahmen des Struktogramms dient dem Eintrag zur Autoren- und Titelinformation. Die sprachlichen Inhalte der rechteckigen Strukturblöcke sind frei zum Zweck wählbar. Die grafische Form und deren Sinn sind aber zwingend vorgeschrieben. Das gesamte Struktogramm bildet immer ein vol-les Rechteck. Struktogramme werden im Normalfall ohne Farben gezeichnet. Übungsaufgabe

48. Schreiben Sie C++ - Programme und zeichnen Sie zu jeder der Lösungen ein Struktogramm!

a) Geben Sie die ersten 6 Zeilen des Pascalschen Dreiecks auf dem Bildschirm aus!

b) Geben Sie ein einzugebendes Wort gesperrt (Leerzeichen zwischen die Zeichen setzen) aus!

c) Es geben 5 Personen ihr Körpergröße (in Meter) ein. Speichern Sie die einzugebenden Körper-größen in einem Array! Bestimmen Sie die Körpergröße der größten, die der kleinsten Person und das arithmetische Mittel aller fünf Größenangaben.

d) Stellen Sie mit Zeichenausgaben eine Figur dar, die einem Schachbrett nahe kommt.

e) Schreiben Sie ein Programm, das bei Eingabe von Kleinbuchstaben immer Großbuchstaben zeigt. Alle anderen Zeichen erscheinen wie immer.

f) Geben Sie alle nat. Zahlen n<1000, die durch 3 oder 5 teilbar sind, auf dem Bildschirm aus.

1.6.3 Trockentests

Die Methode der TTrroocckkeenntteessttss („Schreibtischtests“) wird genutzt, um kleine Programmabschnitte oh-ne Computer testen zu können. Die dabei verwendeten Daten werden „TTeessttddaatteenn“ genannt.

Beispielaufgabe 9

Es soll folgendes C++ -Programmstück mit Hilfe eines Trockentests auf Richtigkeit kontrolliert werden. Es soll für einen vorgegebenen Wert x die mathematische Fakultätsfunktion f = !x errechnet werden. Als Menge der Testdaten wird gewählt: X = { 2; 1; 0 } . 01 unsigned x, f=1; 02 cout << "x = "; 03 cin >> x; 04 while(x) f *= x--; 05 cout << "x! = " << f;

2) Zeile x f 1) Zeile x f 0) Zeile x f 01 1 01 1 01 1 03 2 03 1 03 0 04 1 2 04 0 1 05 out→ x! =1 04 0 05 out→ x! = 1 05 out→ x! = 2

Bei der Auswahl der Testdaten sollte auf Eckdaten des Algorithmus zurück gegriffen werden, die Son-derfälle oder Schwachstellen des zu prüfenden Programmstückes testen.

Im Beispiel hat der Trockentest gezeigt, dass in den Fällen 2) und 1) die letzte Multiplikation mit einer 1 unnötig und somit uneffektiv ist. Das Programmstück wird effektiver, wenn die Zeile 04 in die folgende Zeile verändert wird: [ 04 while(x>1) f *= x--; ]. Führen Sie mit der neuen Zeile alle Trocken-tests für die Testdatenmenge X = { 3; 1; 0 } durch!

Übungsaufgaben

49. Bestimmen Sie den Wert der Variablen x nach dem Ablauf der folgenden C++ Programmstücke:

a) int main() { int x=2, a=4; if(x<a) x+=a;

b) int main() { int x=14%3, a=1; if(a--) x=x+a;

Cassebaum, Skript zur Programmierung mit C++

27

c) int main() { int x=3, a=4; do { a-=2; x+=a; } while(a);

d) int main() { int i,x= 'd'-'b'; for(i=0; i<2; i++) { x--; } if(x) x++;

e) int main() { double x=2.2; i=3; while(i) { x+=2; i--; }

f) int main() { int x=6, i=-3; while(i) { x-=2; i+=2;}

g) int main() { int x=0, a[]={3,2,1,4}, i=3; while(i) x+=a[i--];

h) int main() { int a[3], i=0, x; for( ; i<3; i++) a[i]=i; x= a[0]+a[1]*(a[2]-1);

i) bool fkt(int a){ return !a; } int main() { int x=2; if(fkt(x)) x++; else x--; x+=x;

j)unsigned fkt(unsigned c) { unsigned e=1; while(c) e+=c--; return e; } int main() { unsigned x=fkt(5)-fkt(4);

50.Bestimmen Sie den Wert der Variablen x nach dem Ablauf der folgenden Struktogramme:

a) b) c)

Geben Sie für die Aufgaben 46…49 den Wert der Variablen x nach Abarbeitung aller zur Teilaufgabe zugehörigen Anweisungen an:

51. a) int a, x=0; b) int a=0, x; c) int a=3, x=4; d) int a, x=4; a= x+2; x=a-3; a=a*a*a/x++; a= (++x)+4; x += a; x-=3; x++; x++; x= a%2;

52. a) double x,a=0.6; b) bool x=!true; c) int x=0,i=3; x= 2+a--; if(!x)x=!(x||x); switch(i) x= a*a/a-1; else x-=1; { case 1: x=2; break; case 2: x++; default:--x; }

53.a) int x=2,a; b) bool a, x=-3; c) int x=0,i; bool b; for(a=3;a>1;a--) for(a=0; x; x++) if(i){for(i=-3; i<0; i++) --x;} { x*=a; } { x+=a; a++; else if(b&&i) x++; x*=x;} ++x; if(!b||i) x*=2;

54.a) int x=2; while(x<17) x *= 3;

b)int i=0,x=-2; do { x+=i; i+=x; } while(i>=-8);

c)int x=0; for(;!x;x-=2) x+=3;

d)int x=0,i=0; for(;i<=3;i++,x--) x *= i;

55. Zeichnen Sie den Bildschirmaufbau nach dem Programmteilablauf! Es wird vorausgesetzt, dass die notwendigen Header vorher mit #include <iostream> gerufen wurden.

a) int a=4; b) int i=1, a=1; c) int x=1; bool b; clrscr(); clrscr(); clrscr(); for(;a;a--) while(i<5) b=(x!=1); cout << "++"; { cout << a++; i++;} for(; !b; b=!b){cout << "###"}

x = 2

while (x > 0) a = a + 3

a = 0

x = x - 1 x = a + 1

x = 2

while (a > 0)

x = x * 2

a = 2

a = a - 1 x = a / 2

x = 6

do

while ( x )

while (x > 0)

x%2

a = 0

x = x - 1 a = a + x J N

Cassebaum, Skript zur Programmierung mit C++

28

2 Elementare Einführung in C/C++

2.1 Funktionen

Die wesentlichsten ausführbaren Programmteile in C++ sind (ggeerruuffeennee, ggeessttaarrtteettee) Funktionen, die wiederum von anderen (rruuffeennddeenn) Funktionen gestartet werden. Eine Funktion kann mit „PPaarraammee--tteerrnn“ Steuerinformation von der rufenden („übergeordneten“) Funktion übernehmen und mit einem „RRüücckkggaabbeewweerrtt“ ein Resultat an die übergeordnete zurückgeben.

2.1.1 Funktionsdefinition

Allgemein wird eine Funktion wie folgt definiert:

<Datentyp><Funktionsname>([formaler Parameter1[,formaler Parameter2[,...]]]) { <Funktionskörper> [ return <Rückgabewert im Datentyp der Funktion>; ] } (nur wenn der Datentyp der Funktion nicht void ist)

Der FFuunnkkttiioonnsskköörrppeerr enthält die C/C++Anweisungsfolge, die die Arbeitsweise nach dem Funktionsauf-ruf erklären.

Eine Funktion des Datentyps void wird „AAuuffttrraaggssffuunnkkttiioonn“ genannt. Eine solche Funktion führt Tätig-keiten aus, besitzt aber kein Ergebnis in Form eines Wertes. Jeder andere Datentyp macht eine return-Anweisung in der Definition erforderlich, weil mit (return x; ) das datentypgerechte Wertergebnis an die rufende Funktion übergeben wird. Funktionen mit Wertrückgabe werden „AAnnffrraaggeeffuunnkkttiioonn“ ge-nannt.

void aus(int x) // Auftrag { cout << x; } int main() { aus(8); // Aufruf ... }

int doppel(int x) // Anfrage { return t+t; } int main() { cout << doppel(5); // Aufruf ... }

Eine Funktion muss vor Ihrem ersten Aufruf in der Reihefolge der Quellzeilen definiert worden sein, d.h. die Reihenfolge der Funktionsdefinitionen ist von Bedeutung für deren spätere Ausführbarkeit.

2.1.2 Prototypen

Die erste Zeile der Funktionsdefinition mit einem abschließenden Semikolon wird PPrroottoottyypp genannt. Der Prototyp wird zum Modulbeginn eingefügt, damit die zugehörige Funktion schon vor der Definition für den Compiler als bekannt gilt.

01 void aus(int, int); // Prototypen 02 int mult(int, int); 03 int main() 04 { aus(3,4); // Funktionsaufruf 05 getchar(); 06 return 0; 07 } 08 void aus(int a, int b) 09 { cout <<a <<“*“ <<b <<“=“ <<mult(a,b); 10 } 11 int mult(int x, int y) 12 { return x*y; }

Ohne Prototypzeilen würde der Compiler für Zeile 09 einen Fehler anzeigen, weil die Funktion „mult()“ in dieser Zeile noch unbekannt ist. Der Compiler wertet Zeile für Zeile aus, so dass bei der Auswertung der Zeile 09 die Zeile 11 noch nicht be-kannt ist.

Durch den Prototyp in Zeile 02 ist die nebenstehende Variante fehlerfrei compilierbar.

Cassebaum, Skript zur Programmierung mit C++

29

2.1.3 Funktionsparameter

PPaarraammeetteerr sind die Angaben in der nach dem Funktionsnamen folgenden Klammer. Sie besitzen einen Datentyp und werden anhand ihrer Position Parameterreihenfolge unterschieden.

Die „ffoorrmmaalleenn“ Parameter in der Funktionsdefinition werden immer mit einem Datentyp und einem Namen definiert. Der FFuunnkkttiioonnsskköörrppeerr enthält die beim Funktionsaufruf auszuführenden Anweisun-gen, 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 rufen-de Funktion zurück. Kennt eine Funktion den Namen einer anderen Funktion, so kann sie diese mit einem Funktionsaufruf starten.

Im FFuunnkkttiioonnssaauuffrruuff werden die formalen Parameter durch „aakkttuueellllee“ Parameter ersetzt. Die aktuelle Parameterliste des Funktionsaufrufs muß hinsichtlich der Parameteranzahl, -Reihenfolge und Datenty-pen vollständig mit der formalen Parameterliste harmonieren.

<Funktionsname>([aktueller Parameter_1[,aktueller Parameter_2[,...]]]);

string Multistring(string s, int r); // Prototypzeile void main(void) { cout << Multistring("Tick",5); // Funktionsaufruf getchar(); } string Multistring(string s, int r) { while(r--) s+=s; return s; // Rückgabewert }

2.1.4 Die main() - Funktion

Ein C++ Programm wird mit Hilfe von Funktionen konstruiert, d.h. die wesentlichsten ausführbaren Programmteile sind Funktionen, die von anderen (rufenden) 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 danch zunächst die mmaaiinn-FFuunnkkttiioonn, die Hauptfunktion des Programmes.

Wie jede andere Funktion kann sie Parameter von der startenden Funktion empfangen und einen Er-gebniswert zurückgeben. Da die main-Funktion vom Betriebssystem gestartet wird, empfängt sie Kommandozeilen-Parameter von der Startzeile und gibt üblicherweise einen ganzzahligen Ergebnis-code 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 heisst myprog.exe und wird mit der Kommandozeile "myprog.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 1 ( return 1;) 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 xx"-Zeile weggelassen werden und die erste Zeile der main-Funktion wie folgt aussehen: void main(void) .

Gibt aus:

TickTickTick… Wie viele Tick’s werden sichtbar?

Cassebaum, Skript zur Programmierung mit C++

30

2.1.5 Datenkapseln

Als Datenkapsel wird ein C++-Konstrukt bezeichnet, das eigene „lokale“ Größen (z.B. Variablen) defi-niert. In verschiedenen Datenkapseln dürfen gleiche Bezeichner für unterschiedliche Daten genutzt werden.

Funktionen sind Datenkapseln und besitzen damit eigene, nur ihnen zugeordnete Speicherbereiche. Ohne den Definitionszusatz „static“ werden die im Funktionskörper definierte Größen beim Aufruf der Funktion dynamisch im lokalen Stack der Funktion (rückwärts zählend) aufgebaut und zum Beenden der Funktion wieder freigegeben. Bei einem erneuten Aufruf der Funktion stehen die Wertinhalte des vorherigen Funktionslaufs somit nicht mehr zur Verfügung.

Werden die lokalen Größen mit dem „static“-Zusatz definiert, bleiben deren Werte erhalten. Sie werden nicht beim Beenden der Funktion zerstört.

Wird der Operator :: vor einen Datenbezeichner gesetzt (z.B. ::x=0;), so wird eine außerhalb von allen Funktionen definierte „gglloobbaallee“ Größe über ihren Bezeichner angesprochen. Globale Größen sind mit :: in allen Funktionen erreichbar und können deshalb auch als primitive Form der Wertübergabe von einer Funktion zu einer anderen benutzt werden.

int x=5; // globale Variable x (ausserhalb der Funktionen) void aend(void) { int x=1; // lokale, dynamische Variable x in aend() static int y=1; // lokale, statische Variable y cout << ++x << “ “ << ++y << “ “ << ++::x << endl; } int main() { int x=12; // lokale Variable x in main() cout << x << “ “ << ::x << endl; aend(); aend(); // zweimaliger Aufruf cout << x << “ “ << ::x; getchar(); }

2.1.6 „call by value“ und „call by reference“

Wie bereits bekannt, werden Parameter benötigt, um Daten aus der rufenden Funktion an die gerufe-ne Funktion zu übergeben. Es werden bei der Parameterübergabe zwei grundsätzliche Formen unter-schieden. Zum einen können die Parameter als „WWeerrtt“ (ccaallll bbyy vvaalluuee), aber andererseits auch als „RRee--

ffeerreennzz“ (ccaallll bbyy rreeffeerreennccee) übergeben werden.

Bei Übernahme von Wertparametern wird in der gerufenen Funktion neuer Speicherplatz zur Aufnah-me der übernommenen Parameterwerte bereitgestellt. Eine Änderung dieses funktionsinternen Spei-cherplatzes führt bei einer Änderung des Parameterinhaltes nicht gleichzeitig zur Änderung der Positi-on im rufenden Programm.

Ein Referenzparameter ist an einem vorangestellten & erkennbar.

void aend(int x) { cout << ++x;} int main() { int x=1; cout << x << endl; aend(x); aend(x); cout << endl << x; getchar(); }

void aend(int &x) { cout << ++x;} int main() { int x=1; cout << x << endl; aend(x); aend(x); cout << endl << x; getchar(); }

Gibt aus:

12 5 2 2 6 2 3 7 12 7

Abb. 11

Gibt aus:

1

22 1

Gibt aus:

1

23 3

Cassebaum, Skript zur Programmierung mit C++

31

Der Parameter im rechten Beispiel wird als RReeffeerreennzz ü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.

RReeffeerreennzzeenn verweisen 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 Nut-zung der typischen Zeigersyntax, sie werden wie die Variable selbst behandelt, die sie referenzieren. Wegen dieser einfachen Arbeitsweise werden Referenzen auch Alias ("Spitzname") genannt.

#include <iostream.h> double quad_v(double w){return w*w;} // Wert als Parameter void quad_r(double &w){w*=w;} // Referenz als Parameter void main(void) { double x=12.; x=quad_v(x); // call by value cout << "\n(1) 12*12= " << x; x=12.; quad_r(x); // call by reference cout << "\n(2) 12*12= " << x; getchar(); }

2.1.7 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. Ruft eine Funktion in ihrer Definition sich selbst auf, wird sie rreekkuurrssiivv ge-nannt. z.B.:

string Multistring(string s, int r) // Funktionsdefinition { return r?Multistring(s+s,r-1):s; } void main(void) { cout << Multistring("Tick",5); // Funktionsaufruf getchar(); }

Die Funktion Multistring sieht hier anders aus, als die rekursionsfreie Funktion im Kapitel 2.2.3 (S.26). 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; } void main(void) { cout << fak(5); // Funktionsaufruf getchar(); }

Die Funktion fak errechnet eine bekannte mathematische Funktion in nicht zu überbietenden Einfach-heit. 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.

Gibt aus:

(1) 12*12= 144 (2) 12*12= 144

Gibt aus:

TickTickTick… Wie viele Tick’s werden sichtbar?

Cassebaum, Skript zur Programmierung mit C++

32

2.1.8 Funktionsüberladung

Wichtige äußere Eigenschaften einer Funktion sind die Anzahl, Reihenfolge und die einzelnen Datenty-pen der Parameter. Aus praktischen Gründen stellt man sich die Frage, ob es nicht vernünftig ist, un-terschiedliche Parameterlisten für den gleichen Funktionsnamen zuzulassen.

In C++ ist dies mit Hilfe des Overloading möglich. Der Begriff OOvveerrllooaaddiinngg oder ÜÜbbeerrllaadduunngg bezeichnet die Fähigkeit von C++, anhand der Parameterliste einen von mehreren existierenden Funktionsdefiniti-onen auszuwählen.

double kreis(double radius) // Funktionsdefinition 1 { return M_PI * radius * radius; } double kreis(char* radius) // Funktionsdefinition 2 { double rad = atof(radius); return M_PI * rad * rad; }

void main(void) { double r=3.1; char* rc = "3.1"; cout << kreis(r) << endl; // Funktionsaufrufe nach Def.1 cout << kreis(rc); // Funktionsaufrufe nach Def.2 getchar(); }

Die Funktion kreis() ist im Beispiel zweimal definiert. Die erste Definition benutzt einen double-Parameter und die zweite Definition eine char*-Parameter. In den nachfolgenden Aufrufen erkennt C++ automatisch, welche der beiden Definitionen zur Anwendung kommt.

Übungsaufgaben Verfassen Sie Funktionen für C++!

56. „Zins(K,S)“, die für ein Kapital K (in €) und einen Zinssatz Z (in %) den Zins (in €) errechnet!

57. „ZzKapital(K,S,J)“, die unter Nutzung der Funktion Zins(K,S) und der Zahl der Jahre J das Kapital errechnet, was sich unter Berücksichtigung des Zinseszinses ergibt!

58. „Ganz“, die prüft, ob eine reelle Zahl ganzzahlig ist. Wenn die Zahl ganzzahlig ist wird der Boolwert „true“, sonst „false“ zurückkgegeben.

59. Erklären Sie mit kurzen Worten, was die Funktion fkt berechnet:

long fkt(int w) { w -= w%2; if(w<2) return 0; else return fkt(w-2)+w; }

long fkt(int w) { int p=1; if(w<0) return 0; for(;w>0;p*=w--); return p; }

void fkt(int w) { int p=0; for(p=0;p<w;p++) cout<<p; }

bool fkt(int w) { if(w) return false; else return true; }

Cassebaum, Skript zur Programmierung mit C++

33

2.2 Arrays

2.2.1 Ein- und mehrdimensionale Arrays (Felder)

Arrays erlauben es, große Datenmengen gleichen Datentyps zu verwalten. Ein eindimensionales Array a[n] besteht aus den n Arrayelementen gleichen Datentyps: a[0], a[1], ..., a[n-1]. Speicherplatz für die n Elemente wird durch die Definitionszeile reserviert:

<Datentyp><Arrayname>[<Elementanzahl>][={<wertel0>,...,<werteln-1>}];

Eine besondere Form ist das mehrdimensionale Array, das mehr als eine eckige Indexklammer benutzt. Die Anzahl der Indexklammern zur Arraydefinition oder zur Elementnutzung wird Dimension des Ar-rays genannt.

Das mit float a[2][3]; definierte Array a ist ein zweidimensionales Array. Der Bezeichner b[0][0][0] greift auf das physikalisch erste Element des dreidimensionalen Arrays b zu. (1) int a[5]={2,1,5,3,4}; (2) int a[2][3]={{1,5,9},{4,2,3}};

Die Arraydefinitionen (1) und (2) führen zu folgendem Speicheraufbau:

Die einzelnen Arrayelemente sind im Speicher auch bei mehrdimensionalen Arrays physisch zusammen-hängend (in lückenloser Folge) gespeichert. Die Vor-stellung des Arrays als Tabelle oder Matrix ist zur the-oretischen Vorstellung der Werte recht praktikabel.

Summation der Elemente einer 3,4 Matrix: Füllung eines Lotto-Arrays mit Zufallswerten

int i,k; double m[3][4], s=0; int i,k,a[10][6]; for(i=0;i<3;i++) randomize(); for(k=0;k<4;k++) for(i=0;i<10;i++) s += m[i][k]; for(k=0;k<6;k++) cout << "Summe: " << s; a[i][k]=random(49)+1;

S =

2

0

3

0,

i kkim

2.2.2 Zufallszahlen

Zufallswerte lassen sich mit randomize(), random(n) und rand() automatisch entwickeln.

randomize() Stellt einen zufälligen Start zum Finden der Werte ein. random(n) Liefert ganzen Zufallswert x mit 0 <= x < n, d.h. random(2) liefert nur 0 oder 1. rand() Liefert ganzen Zufallswert x mit 0 <= x < 65536. randomize(); int a = random(201)-100; // Zufallswert -100, ..., +100 int b = rand()-32768; // Zufallswert -32768, ..., +32767 float c = random(100)/10.; // reeller Zufallswert 0.0, ..., 9.9 char d = random(’Z’-’A’+1)+’A’; // Zufallsbuchstabe A, ..., Z

2 1 5 3 4 1 5 9 4 2 3

1 5 9

4 2 3

0 1 2

0

1

a[0][1]=5; a[1][0]=4; a[1][2]=3;

Abb. 12 Abb. 13

Cassebaum, Skript zur Programmierung mit C++

34

2.2.3 Strings

Strings sind Ketten von Zeichen, die gemeinsam verwaltbar sind und als Hauptanwendung Texte oder einzelne Worte speichern sollen. In C/C++ Programmen arbeitet man mit Stringkonstanten in der Form “xxx“.

Zur Speicherung von Strings werden in C/C++ Arrays mit char-Elementen benutzt. Es gibt für Strings in C und in C++ zwei unterschiedliche Ansätze, die im folgenden in eigenen Kapiteln dargestellt werden.

2.2.3.1 C-STRINGS („NULLTERMINIERTE STRINGS“)

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 Endekennung („Nullterminator“) benannt, das im Arrayelement nach dem letzten gültigen Zeichen des Strings gespeichert wird.

Nullterminierter String, 8 Bytes reserviert, 4 Bytes belegt

char s[7]; strcpy(s,"Turm");

Nullterminierter String, 5 Byte reserviert, 4 Bytes belegt char s[]= "Turm"; oder: char *s= "Turm";

Die Definition char s[]= "Turm"; (oder mit *s) vereinbart einen String der Länge 4 inklusive Null-terminator in vereinfachter Form. Einzelne Zeichen innerhalb eines Arrays werden als Arrayelemente erreicht. So enthält im Beispiel das Element s[2] den Wert ’r’.

Für die Einhaltung der Terminierung sind die strxxx-Funktionen zu nutzen. z.B. strcpy(x,"Otto"); fehlerhaft wäre allerdings: x="Otto"; Die nachfolgende Tabelle enthält eine Auswahl der strxxx-Funktionen, die im Header string.h definiert sind.

strcat(e,q) An den String e (vor dem 1.Komma) wird der String q angehängt. strcmp(e,q) Der String e wird mit dem String q verglichen. Es werden Ergebniswerte zurück-

gegeben: <0 für s<q , =0 für s=q, >0 für s>q strcpy(e,q) Der Quellstring q wird in die Stringgröße e kopiert. Für Strings ist die

Ergibtanweisung z=s; unzulässig. Stattdessen wird strcpy(z,s); genutzt. strlen(e) Liefert die Länge des Strings e (in Klammern) als int-Wert zurück. strlwr(e) Im String e werden alle Groß- in Kleinbuchstaben verwandelt. strstr(e,q) Liefert einen Zeiger auf die Position des ersten Vorkommens des Strings q im

String e. ( Zeiger werden in einem späteren Kapitel erklärt) strupr(e) Im String e werden alle Klein- in Großbuchstaben verwandelt. string(e) Liefert einen C++-String gleichen Inhalts wie e zurück.

Die Ein-/Ausgaben über cin/cout können vereinfacht durch Weglassen der Indexangabe realisiert wer-den. In diesem Fall wird die cout-Ausgabe bis zum Nullterminator durchgeführt und die cin-Eingabe im Zielstring automatisch mit dem Nullterminator ergänzt.

char s[20];

cin >> s; // Textinput bis Leerzeichen in s mit Nullterminator cin.get(s,127); // Textinput bis Ende in s mit Nullterminator setzen cout << s; // String s wird bis Nullterminator ausgegeben cout << s[1]; // Ausgabe des 2.Zeichens im String s s[2]= ’a’; // Zuweisung eines ASCII-a als 3.Zeichen im String s for(int i=0; i<strlen(s); i++) cout < s[i]; //Ausgabe aller Zeichen von s

’T’ ’u’ ’r’ ’m’ 0 ? ? ?

0 1 2 3 4 5 6 7

’T’ ’u’ ’r’ ’m’ 0

0 1 2 3 4

Cassebaum, Skript zur Programmierung mit C++

35

2.2.3.2 C++-STRINGS ( STRINGS DER KLASSE „string“ )

Eine modernere Stringnutzung als die nullterminierten Strings gestattet der Datentyp string. Eine string-Größe kann im Borland C++ Compiler 5.5 bis zu 4.294.967.281 Zeichen speichern. Der Speicher-platzbedarf wird dynamisch angepaßt, d.h. die größte Verwendungslänge eines Strings bleibt als seine Speicherkapazität erhalten.

string s; s="Fenster"; s+="kreuz"; cout << s << " " << s.length(); // Ausgabe: Fensterkreuz 12

Es gibt eine große Zahl interessanter Stringfunktionen und -operatoren. So können die bekannten Ope-ratoren wie "=" und "+=" zur Zuweisung und "+" zur Verkettung zweier Strings verwendet werden.

string s.substr(p,l) liefert einen Teilstring von s, der in Länge l ab Position p beginnt

int s.compare(s2) vergleicht s mit s2, für s<s2: <0, s==s2: ==0, s>s2: >0

string s.append(s2) hängt String s2 an s an

char* s.c_str() gibt nullterminierten C-String gleichen Inhalts wie s zurück

string s.insert(i,s2) fügt ab i-Position s2 in s ein.

int s.length() liefert die aktuelle Länge von s

Auf die Einzelzeichen eines C++-Strings kann wie auf die Elemente eines char-Arrays zugegriffen wer-den. Wichtig ist allerdings, dass der Index nur kleiner als die Längenkapazität des Strings gewählt wer-den darf.

string s = "Gut Holz!"; for(int i=0;i<s.length();i++) if((s[i]>=’a’) && (s[i]<=’z’))// Ausgabe: alle Kleinbuchstaben in s cout << s[i]; // Ausgabe: utolz

Übungsaufgaben

60. Füllen Sie ein ganzzahliges Array mit 100 Zufallswerten zwischen 1 und 49. Bestimmen Sie den größten Wert, die Zahl der Einsen und das arithmetische Mittel aller geraden Zahlen!

61. Füllen Sie ein ganzzahliges Array mit allen Primzahlen, die kleiner als 1000 sind!

62. Füllen Sie 1000 zufällige Buchstaben in einen String! Ermitteln Sie, wie oft "ei" vorkommt!

63. Schaffen Sie ein vierdimensionales Array, das Name, Alter und Gewicht von max. 100 Personen speichern könnte! Speichern Sie Phantasiedaten für 5 Personen ab und geben Sie die Daten aus!

64. Speichern Sie 10 zufällige Lottotipps in einem Array! Drucken Sie diese Tipps geordnet aus! Beach-ten Sie, dass ein Lottotipp je 6 Zahlen (1..49) enthält und keine Zahl mehrfach vorkommen darf!

65. Speichern Sie in einem dreidimensionalen Zahlenfeld (10x10x10) die Multiplikationsergebnisse a*b*c für alle möglichen Zahlentripel a,b,c für a (1,..,10), b (1,..,10), c (1,..,10). Geben Sie alle Er-gebnisse für a=n als Tabelle auf dem Bildschirm aus! Die natürliche Zahl n ist vorher abzufragen und vom Bediener einzugeben.

66. Schreiben Sie eine Funktion „int pos(char *s,char *sub);“ für nullterminierte Strings, die beim Aufruf von „pos(s,sub)“ die Positionsnummer des 1.Zeichens des Teilstrings „sub“ im String „s“ zurückliefert. Sollte „sub“ nicht in „s“ enthalten sein, wird eine 0 zurückgeliefert.

67. Schaffen Sie eine Funktionsüberladung für Aufgabe 58, die die Funktion pos für C++-Strings löst.

68. Schreiben Sie Programme a) für C-Strings, b) für C++-Strings -, die die Eingabe von maximal 100 Strings nacheinander abfordern! Nach jeder Eingabe wird geprüft, ob die aktuelle Zeichenkette be-reits Teil einer zuvor eingegebenen war. Wenn dies der Fall ist, wird die vorherige Zeichenkette mit einer passenden Ausschrift auf dem Bildschirm angezeigt und das Programm abgebrochen.

Cassebaum, Skript zur Programmierung mit C++

36

2.3 Adressen und Zeiger

2.3.1 Adressen

Eine Adresse ist eine Größe im Computersystem, die die Position (d.h. die „Nummer“ der Speicherpo-sition) einer gespeicherten Größe darstellt. Eine Adresse wird meist hexadezimal aufgeschrieben ( z.B. in C++, 32 Bit: 0x0012FF84 )

Abb. 14

In C/C++ werden die (static -) Speicherbereiche in der Reihenfolge der Quellzeilen beginnend mit einer Basisadresse gefüllt. Ohne den static -Zusatz werden die Bereiche rückwärts zählend ab einer vom Linker festgelegten Basisadresse (im „Stacksegment“) gefüllt.

Größen mit dem static-Zusatz werden in Funktionen beim Wiederaufruf unverändert bereitgestellt. Ansonsten befinden sich die Größen im Urzustand. Der static -Bereich wird vom Betriebssystem in einem gesonderten Adress-Segment eingerichtet („Datensegment“).

#include <iostream.h> func() { int i=1; static int j=1; cout << i++ << " " << j++ << endl;} int main() { func(); func(); func(); getchar(); return 0; Abb.15 }

2.3.2 Zeiger (Pointer)

Zeiger (Pointer) sind Größen, die Adressen von Variablen, Arrays,... unter einem eigenen Namen spei-

chern. Der Operator * kennzeichnet eine zu definierende Größe als Zeiger. Der Operator & ruft die Adresse einer C++-Grösse auf. Für &x spricht man: „Adresse von x“. Adressen werden bei Ausgaben standardmäßig hexadezimal angezeigt.

int a, *ptr; ptr = &a; Abb. 16

Ein Zeiger speziell für einen bestimmten Datentyp gebildet, weil die Bytelängen der Typobjekte unter-schiedlich sind. Ein mit „double *b;“ definierter Zeiger b zeigt auf einen double-typspezifischen Da-tenbereich mit 8 Byte Länge. Ein mit „int *a;“definierter Zeiger a zeigt auf einen int-typspezifischen Datenbereich mit 4 Byte Länge.

00 12 FF 88 00 00 00 03

z.B.Adresse 0012FF84

z.B.Adresse

0012FF88

Adresse

00000000

Adresse (Speicherende)

FFFFFFFF

ppttrr

„„DDeerr ZZeeiiggeerr ((PPooiinntteerr)) ppttrr

zzeeiiggtt aauuff ddiiee VVaarriiaabbllee aa““

00 00 00 00 00 00 00 00

z.B.Adresse

0012FF84

Adresse

00000000

Adresse („Speicherende“)

FFFFFFFF

SSppeeiicchheerr

aa

Gibt aus:

1 1 1 2 1 3

z.B.Adresse

0012FF88

Cassebaum, Skript zur Programmierung mit C++

37

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, d.h.: zahl=4 cout << z_zahl; // Anzeige der Adresse von „zahl“ cout << &zahl; // dito cout << *z_zahl; // Anzeige Inhalt der Größe, auf die z_zahl zeigt z_a = &a[0] ; // Adresse des 1. Arrayelements des Arrays „a“ z_a = a; // dito (Zeiger „z_a“ wird Aliasname von „a“) cout << z_a[2]; // Ausgabe des 3.Arrayelements von „a“(mit Alias) cout << *z_a++; cout << ++*z_a; // Zeigerarithmetik z_a = a; cout << z_a++; cout << ++z_a;

Zeigt ein Pointer auf das Startelement eines Arrays gleichen Typs, so kann mit diesem Pointer in der Arraysyntax gearbeitet werden (z.B. z_a[2] ). Ein gesetzter Zeiger auf ein Array kann wie ein zweiter Bezeichner (Alias) genutzt werden, d.h.:

int *p, a[4]; p = &a[0]; p[0]=1; p[1]=5;

…bewirkt, dass a[0] und a[1] mit 1 bzw. 5 gefüllt werden.

Die Addition oder Subtraktion von Zeigern mit ganzzahligen Größen n wird Zeigerarithmetik genannt. Die gespeicherte Zeigeradresse wird dabei um des n-fache der Länge des Datentyps des Zeigers verän-dert.

01 double *pd, d[11]; 02 int *pi, i[11]; 03 pd = d; 04 pi = i; 05 *pd = 21.34; 06 *pi = 5; 07 cout <<pd <<" " <<pi <<endl; 08 pd++; 09 pi+=3; 10 *pd = 33.99; 11 *pi = 6; 12 cout <<pd <<" " <<pi <<endl 13 <<d[0] <<" " <<d[1] <<endl 14 <<i[0] <<" " <<i[3];

Im Beispiel wird in Zeile 08 der Zeiger „pd“ mit pd++; passend zum double-Array um eine Elementlänge (d.h. um 8 Byte) erhöht.

Der Zeiger „pi“ des int-Arrays wird in Zeile 09 mit pi+=3; um drei Element-längen (d.h. 3 * 4 = 12 Byte) passend zum Datentyp int erhöht.

Aufbau und Initialisierung zweier Arrays mit Zufallswerten.

Das Array „double d[11]“ wird mit reellen Zufallswerten <100 mit 2 Nachkommastellen gefüllt.Das Array „int i[11]“ wird mit gan-zen Zufallswerten zwischen -100 und +100 initialisiert.

01 double *pd,d[11]; 02 int *pi,i[11]; 03 pd = d; pi = i; 04 randomize(); 05 do 05 { *pd = random(10000)/100.; 06 *pi = random(201)-100; 07 pd++; pi++; 08 } while(pd <= &d[10]);

p a[0] (p[0])

aa pp

00 12 FF 88 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 00

Abb. 17

Cassebaum, Skript zur Programmierung mit C++

38

Übungsaufgaben

69. Füllen Sie Arrays verschiedener Datentypen mit Zufallswerten! Setzen Sie je einen Zeiger auf das erste Arrayelement und geben Sie danach die Arrayelemente nur mit Hilfe dieser Zeiger aus!

70. Zwei int- Variablen x und y definieren und mit beliebigen Werten initialisieren. Weiter werden die -int-Zeiger px und py definiert und passend die Adressen von x und y eingetragen. Lassen Sie sich die Adressen und die Inhalte der Größen x, y, px und py anzeigen!

71. Ergänzen Sie die Aufgabe 62! Tauschen Sie mit einem Hilfszeiger die Eintragungen in px und py! Lassen Sie sich danach die Adressen und die Inhalte der Größen x, y, px und py noch einmal anzei-gen! Interpretieren Sie die Unterschiede zur Anzeige aus Aufgabe 62!

72. Schreiben Sie eine Funktion PtrToStr(…), die einen String zurückgibt, der den Inhalt und die Adresse der Variablen , auf den der über Funktionsparameter p bereitgestellte Pointer zeigt, als kommen-tierten Text enthält.

Beispielprogrammauszug für die Funktion PtrToStr(…):

string PtrToStr(int *p); // Prototyp, später zu definieren int main() { int x, *px = &x; cout << endl << PtrToStr(px); // Adress-/ Inhaltsausgabe getchar(); return 0; }

73. Bilden Sie ein Array vom Typ double mit 5 Elementen und initialisieren Sie alle Elemente mit belie-bigen reellen Zahlen! Lassen Sie sich die Adressen und die Inhalte aller Elemente auf dem Bild-schirm mit Hilfe der Zeigerarithmetik anzeigen!

74. Rechnen Sie x aus: a) b) c) d) int a[2],*Pa; int i,x=2; a[0]=2; a[1]=5; Pa=&a[0]; for(i=0;i<2;i++) {x*=*Pa;Pa++; }

int x=22; char a[3]={61,62,0}; char *Pa; Pa=&a[1]; Pa++; x+=*Pa-x;

int fkt(int x) { if(x) return fkt(--x)+x; else return 0; } int main() { int x = fkt(4); }

int x; char *a="Halle"; x=a[5]+4; cout << x;

2.3.3 Zeiger und Strings

Ein Zeiger auf einen nullterminierten String unterliegt einer Sonderbehandlung.

char *p = “Zeiger“; cout << p[0]; cout << p;

Diese Anweisungs-folge bewirkt, dass an einer Position im Speicher, deren Ad-resse in p gespei-chert wurde, für sechs Zeichen mit dem Inhalt „Zeiger“ und einen Nullterminator Speicherplatz bereitge-stellt wurde. Der Zeiger p kann wie ein als char-Array definierter nullterminierter String verwendet werden.

00 12 FF 88 ‘Z‘

p a[0] (p[0])

aa pp

‘e‘

‘i‘ ‘g‘

‘e‘

‘r‘ 00

Abb. 18

Cassebaum, Skript zur Programmierung mit C++

39

2.3.4 Mehrfachzeiger

Ein Mehrfachzeiger ist ein Zeiger, dessen Inhalt auf einen Zeiger niederer Ordnung zeigt. In der Zeiger-definition erklärt die Anzahl der Sternchen * die Ordnung des Zeigers.

Der Zeiger p zeigt über den Zeiger p1 auf das Objekt a.

#include <iostream.h> int main() { int a=3,b[2]={5,6},**p,*p1,*p2; p1= &a; p2= b; p= &p1; cout <<"\nZeiger p zeigt auf " <<p <<" Inhalt: " << *p <<" und weiter auf " <<**p; cout <<"\nZeiger p1 zeigt auf " <<p1 <<" Inhalt: " <<*p1; getchar(); return 0; }

2.3.5 Zeigerarrays

Ein Zeigerarray ist eine Folge von Zeigern gleichen Datentyps und gleicher Ordnung.

#include <iostream.h> int main() { int a= 1, b= 2, c= 3; int *p[3], **pp= p; p[0]= &a; p[1]= &b; p[2]= &c; while( pp <= &p[2] ) { cout <<**pp++ <<endl; } getchar(); return 0; }

Zeigersituation vor dem while…

Im Beispiel zeigt der Zeiger 2.Ordnung „pp“ auf ein Array „p“ für Zeiger 1.Ordnung mit drei Elementen. Der Zeiger pp zeigt vor dem Beginn der while-Schleife auf p[0]. Es wird somit über **pp der Inhalt von a ausgegeben. Durch das zusätzliche ++ wird der Zeiger pp im Sinne der Zeigerarithmetik auf den nächsten Zeiger des p-Zeigerarrays gesetzt und daher b ausgegeben, usw…

**pp

*p[0] *p[1] *p[2]

a b c

00 12 FF 80 00 00 00 03

Adresse 0012FF84

Adresse 0012FF88

00 12 FF 84 00 12 FF 88

Adresse 0012FF80

Adresse 0012FF7C

aa pp pp11 pp22

00 00 00 03 00 00 00 03

bb

Adresse 0012FF8C

Abb. 19

Abb. 20

Cassebaum, Skript zur Programmierung mit C++

40

Übungsaufgaben

75. Bilden Sie ein Array von 10 Strings! Speichern Sie mit Pointerarithmetik in jedem der Arrayelemente einen automatisch erzeugten Zufallstext mit einer Länge von mindestens 5 und maximal 30 Buch-staben! Der Text beginnt in jedem Element mit einem Großbuchstaben enthält dann ausschließlich Kleinbuchstaben! Lösen Sie die Aufgabe a) für C++- und b) für C++-Strings!

76. Erstellen Sie eine Funktion Gross(char *t), die alle Kleinbuchstaben im nulterminierten String „t“ in Großbuchstaben umwandelt! Wandeln Sie mit dieser Funktion und einer Schleifenbildung mit Zei-gerarithmetik alle Arrayelemente aus Aufgabe 66 um! Lassen Sie sich das Ergebnis auf dem Bild-schirm anzeigen!

77. Es ist bekannt: Die Nummer des Zugangscodes steht als int-Wert gespeichert. Die Adresse „a“ der Adresse dieses int-Wertes wird einer Funktion „… Code(…)“ als Parameter übergeben. Die Funktion „Code“ gibt den dezimalen Zugangscode als String zurück. Schreiben Sie die Funktion Code(…) und einen passenden main()-Testrahmen!

78. Speichern Sie 56 Punkte und 8 mal den Buchstaben x in einem 8*8-Feld! Die x‘e sollen zufällig mit den Punkten gemischt sein. Geben Sie das gesamte Feld zweimal nebeneinander so aus, dass genau eines der x‘e um eine Position versetzt erscheint (Richtung zufällig). Benutzen Sie Zeigerzugriffe und -arithmetik bei Änderungen und Ausgaben!

79. Erstellen Sie ein Array „good“ von 10 guten und ein Array „bad“ von 10 schlechten menschlichen Eigenschaften ihrer Wahl! Legen Sie weiter ein Zeigerarray mit 2 Elementen an, die die Adressen von good und bad enthalten! Fragen Sie den Bediener nach seinem Namen und antworten Sie mit einem Satz der eine beliebige gute und eine beliebige schlechte Eigenschaft aus den Listen anzeigt! Sorgen Sie dafür, dass bei einer späteren erneuten gleichen Namenseingabe wieder der gleiche Satz angezeigt wird! ( z.B.: Traudi, Du bist wirklich schön, aber hinterlistig!)

80. Erstellen Sie zwei überladene Versionen der Funktion:

a) Replik(s) String s auf dem Bildschirm ausgeben b) Replik(s,n) String s auf dem Bildschirm n mal ausgeben und eine Zusatzversion: c) Replik2(s,n) n-malige Verkettung des Strings s als String zurückgebe

Cassebaum, Skript zur Programmierung mit C++

41

3 Grundlegende Algorithmen

3.1 Dynamischer Speicher („Heap“)

3.1.1 Speicherzuweisung

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 verein-barten 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 Speicher- platzmenge 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; } 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. Da-durch wird erreicht, daß der zuvor angeforderte Speicherbereich wieder für andere Zwecke zur Verfü-gung steht.

Betriebs- system

<typ> *p;

Nutzung des Heaps

p = new <typ>[n];

delete p;

Anforderung des dynam. Speichers

Rückgabe Der Adresse im Zeiger p

Freigabe des nicht mehr be-nötigten Heaps.

„Heap“…

Speicher

Adresse des Heaps

Programmsequenz… Abb. 21

Cassebaum, Skript zur Programmierung mit C++

42

3.1.2 Beispiel für dynamischen Speicher

#include <iostream.h> int main() { string **q,*z[100],*pk; // Zeiger int i = 0; char a; do { z[i] = new string[32]; // Heap pk = z[i]; do{ cout << "Name: "; cin >> *pk; if(*pk++ == "#") break; } while(pk <= &z[i][31]); cout <<"\nNeue Klasse?[j/n]:"; cin >> a; i++; if(a=='n') break; } while(i<=99); z[i] = 0; q = z; while(*q) { pk = *q; while((*pk) != "#") cout << *pk++ << " "; cout << endl; delete[] *q++; // Freigabe } getchar(); return 0; }

Es sollen die Schülerna-men von beliebig vielen Schulklassen gespeichert werden. Vor der Eingabe der Namen einer weite-ren Schulklasse wird Heap für 32 Namen an-gefordert.

Maximal dürfen 100 Klassen gespeichert werden

Übungsaufgaben

81. Speichern Sie in einem aufzubauenden dynamischen Speicherbereich eine zufällige Anzahl (5…5000) reeller Zahlen. Die per Zufallszahlen zu bestimmenden reellen Zahlen besitzen maximal zwei Nachkommastellen und sind aus dem Bereich -2000.00, …, +1999.99 . Errechnen Sie die Summe und den Mittelwert aller reellen Zah-len im dyn. Array und geben Sie das Ergebnis über Bildschirm aus!

82. Es sollen die Kennzeichen von maximal 1000 Fahrzeugen gespeichert werden. Für jeweils 10 eingebenen Kennzeichen wird dynamischer Speicher angefordert. Geben Sie nach dem letzten einzugebenden Fahrzeug ein ‚#‘-Zeichen als Endeerkennung ein. Listen Sie danach alle Fahrzeugkennzeichen aus, die mit „MD “ begin-nen!

83. Geben Sie auf dem Bildschirm ein im Heap erzeugtes rechteckiges Zahlenfeld zufälliger natürlicher Zahlen (0,…,99) aus! Das Zahlenfeld besitzt die Länge x und die Höhe von y Werten. x und y sind zufällig aus dem Wertebereich (3,…,8) zu bestimmen. Geben Sie danach das Zahlenfeld sortiert auf dem Bildschirm aus!

84. Erfassen und ausgeben von beliebig vielen Strings in einem dynamischen Stringarray. Erfassen und ausgeben von beliebig vielen Strings in einem dynamischen Char-Array als C-Strings mit max. Speichersparsamkeit.

85. Es soll eine Matrix im Format (m,n) dynamisch aufgebaut und mit natürlichen Zufallszahlen (0..99) gefüllt werden. Die Matrix im Heap wird in Zeilen/Spalten geordnet über Display ausgegeben und danach freigege-ben.

86. Es werden die Quadrate von 10000 reellen Werten errechnet. Die reellen Werte sind gleichmässig über den Bereich von xa bis xe verteilt. xa und xe wurden vorher eingegeben. Angezeigt werden nur ausgewählte je 10 Werte der beiden dynamischen Arrays p[0] und p[1]. (Werte werden z.B. für eine Parabelgrafik gebraucht.)

87. Das Programm erlaubt es, für maximal 10000 Schulklassen die Klassenbezeichnung und die Namen von ma-ximal 50 Schülern pro Klasse zu speichern und danach auszugeben. Es soll möglichst wenig Speicher (als null-terminierte Strings) passend zur aktuellen Datenmenge im Heap angefordert werden.

Cassebaum, Skript zur Programmierung mit C++

43

3.2 Einige einfache Algorithmen

3.2.1 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 be-werten sind. Hier werden zwei Arten mit sehr verschiedener Qualität dargestellt:

Quicksort (divide and conquer) Insertion Sort

#define gr 20 #define gr 20 unsigned int gr, T[gr]; unsigned int mi,i,j,gr,T[gr]; void main(void) void main(void) { quicksort(0,gr-1); { for( i=2;i<=gr;i++); } { mi=T[i]; void quicksort(int l,int r) j=i; { int wert,t,i=l,j=r; while((T[j-1]>mi)&&(j>1)) wert=T[(l+r)/2]; { T[j]=T[j-1]; do j=j-1; { while(T[i]<wert) i++; } while(wert<T[j]) j--; } if(i<=j) T[j]=mi; { 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); }

Die Präprozessoranweisung #define gr 20 definiert den Namen „gr“, der im folgenden Modul anstelle von „20“ in den Programmtext gesetzt werden kann. Es wird damit erreicht, dass Textteile mehrmals im Programm mit symbolischen Bezeichnern gesetzt werden dürfen, die später leicht in der Präprozessorzeile gemeinsam verändert werden können.

3.2.2 Vertauschen zweier Werte

Der Tausch der Inhaltswerte von zwei Variablen ist eine kleines, aber dennoch interessantes Problem. Hier werden drei Varianten gezeigt, die auf Geschwindigkeit z.B. durch 100.000-fache Wiederholung getestet werden können.

Alle drei Funktionen enthalten in den Klammern anstelle … die Referenzparameter a und b. Für zu tau-schende ganzzahlige Größen könnte das so aussehen: (int &a, int &b).

void swap1(...) { a^=b; b^=a; a^=b; }

void swap2(...) { register short h; h=a; // 1 a=b; // 2 b=h; // 3 }

void swap3(...) { b=b+a; a=b-a; b=b-a; }

1 2 Der Datentypzusatz „register“ kann den

3 Zugriff auf Variablen beschleunigen, weil der Compi-ler versucht, die definierte Größe direkt in einem Pro-zessorregister zu speichern.

a b

h

Abb. 22

Cassebaum, Skript zur Programmierung mit C++

44

3.2.3 Fakultät (Rekursion)

Eine einfache Lösung zur Berechnung von n! = 1*2*…*(n-1)*n {0! = 1} ist die Basis für viele numerische Berechnungsverfahren:

double faku(unsigned int f) { return( f<=1 ? 1 : f*faku(f-1) ); }

3.2.4 Näherungswertbestimmung für den Sinus

Im folgenden Quellprogramm wird beispielhaft eine Näherungs-rechnung mit dem nebestehenden mathematischen Ansatz für die Sinusfunktion realisiert.

Es wird zyklisch aus einer Näherungslösung «alt» die neue, bessere Näherungslösung «neu» errech-net, bis gilt : |«alt» - «neu»| < 10-6. Wenn die Näherungsreihe konvergiert, wird so eine Lösung mit einer Genauigkeit von 6 Stellen nach dem Komma erzielt.

double mysin(double alpha) // Sinusberechnung { unsigned int i=1; double ergneu=0.,ergalt; do { ergalt=ergneu; ergneu=ergneu+pow(-1,(i-1)/2)*(pow(alpha,i)/faku(i++)); i++; } while (fabs(ergneu-ergalt)>1E-6); // auf 6 Stellen genau return(ergneu); }

3.2.5 Euklidischer Algorithmus (ggT)

Mit dem euklidischen Algorithmus kann auf einfache Weise der größte gemeinsame Teiler von zwei natürlichen Zahlen ermittelt werden. Dieser wird beispielsweise beim Kürzen eines Bruches z/n benötigt.

unsigned int ggT(unsigned int z,unsigned int n) { if(!n||!z) return 0; while(n) { if(z>n) { z+=n; n=z-n; z-=n; } // Tausch n-=z; } return z; }

3.2.6 Sieb des Erastothenes (Primzahlen)

#include <iostream.h> #define N 1000 int main() { int i,j,a[N+1]; for(a[1]=0,i=2;i<=N;i++) a[i]=1; for(i=2;i<=N/2;i++) for(j=2;j<=N/i;j++) a[i*j]=0; for(i=1;i<=N;i++) if(a[i]){cout.width(4);cout<<i;} getchar(); return 0; }

Das nebestehende C++-Programm setzt einen aus dem 3.Jh. vor Christus stammen-den Algorithmus um, mit dem man alle Primzahlen, die kleiner als eine vorgegebe-ne natürliche Zahl N sind, bestimmen kann.

Im Beispiel kann die Zahl N in der Präpro-zessoranweisung #define N 1000 auch auf einen beliebigen anderen Maximalwert gesetzt werden.

!

)1()

2

1(

ialtneu

i

i

Cassebaum, Skript zur Programmierung mit C++

45

4 Objektorientierte Programmierung

4.1 Strukturen und Unions (ohne „OOP“)

4.1.1 Strukturen

Strukturen fassen C++Speichergrößen, wie Variablen, Arrays,... zu einem unter einem eigenen Na-men verwaltbaren "Datentyp" zusammen. Die mit dem Schlüsselwort struct zusammengefassten Speichergrößen werden Attribute der Struktur genannt.

Strukturen sind keine objektorientierten Größen. Wegen ihrer großen Ähnlichkeit mit den objektori-entierten Klassen werden sie in diesem Kapitel behandelt.

struct Brotsorte { string Bez; // Attribut Bezeichnung double Preis; // Attribut Preis unsigned int stk; // Attribut Stückzahl } a[100]; // 100 Instanzen Brotsorte b[20]; // 20 weitere Instanzen Brotsorte *p; // Zeiger auf eine Strukturinstanz b[0].Bez = "Roggenbrot"; p = new Brotsorte; // dynamische Strukturinstanz p->Bez = "Weizenbrot"; // Attributzugriff mit Zeiger cout <<b[0].Bez <<endl <<p->Bez;

Eine definierte Struktur belegt keinen Speicherplatz, der Daten aufnehmen kann. Sie ist vielmehr eine Vorschrift dafür, wie Speicherplatz zu dieser Struktur gebildet werden kann.

Brotsorte bs; // Instanz „bs“ bilden Brotsorte *p; // Zeiger auf eine Strukturinstanz

Analog einer Variablendefinition der Standardtypen kann anstelle des Datentyps der Name einer zuvor definierten Struktur benutzt werden. Die Verwendung des Strukturnamens bei Speicherdekla-rationen organisiert Speicherplatz, der alle Strukturattribute aufnehmen kann. Strukturen können auch für dynamischen Speicher instanziiert werden. Dazu werden Zeigern des Strukturtyps Speicher-adressen mit der new-Anweisung zugewiesen.

Die Herstellung einer Strukturinstanz wird Instanzierung genannt. Strukturdefinition Strukturinstanzen („Rezept“) („belegen Speicher“) Instanziierungen person ich,du,es;

01 b[0].Bez = "Roggenbrot"; 02 b[0].stk = 100; 03 p = new Brotsorte; // dynamische Strukturinstanz 04 p->Bez = "Weizenbrot"; // Attributzugriff mit Zeiger 05 cout << b[0].Bez << endl << p->Bez;

Der Zugriff auf die Attribute statisch gebildeter Strukturinstanzen erfolgt mit dem "Punktoperator" (z.B.: "b[0].Bez"). In der Zeile 01 wird auf das Attribut Bez des ersten Elementes des Instanzarrays b zugegriffen. In Zeile 02 wird die Stückzahl b[0] für eingetragen, d.h. es sind 100 Stück „Roggen-brot“ vorrätig.

struct person { string name; int alter; };

person ich; ich.name = ”Emil Krause”; ich.alter= 26;

Abb. 23

Cassebaum, Skript zur Programmierung mit C++

46

Mit einem Zeiger, der die Adresse einer Strukturinstanz enthält, kann mit dem "Pfeiloperator ->" auf ein Attribut zugegriffen werden. z.B.: "p->Bez" greift in den Zeilen 04 und 05 auf das Attribut Bez der Instanz, auf deren Adresse der Zeiger p zeigt.

4.1.2 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 Speicher-adresse 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;

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 Byte-Registern al und ah dargestellt. Tatsächlich sind das al- und ah-Register jeweils Teile des ax-Registers eines Intel-Prozessors. Die Uni-on liefert ein praktikables Hilfsmittel für die Zugriffe auf diese Register.

Übungsaufgaben

88. Für die Vorbereitung einer Festveranstaltung einer Berufsschule werden gedruckte Schülerlisten benötigt, die alphabetisch nach dem Namen, nach dem Alter und nach dem Geschlecht geordnet ausgegeben werden können. Erstellen Sie eine C++ Struktur Schueler, die als Attribute ein Textfeld "Name", ein logisches Feld zur Speicherung des Geschlechts und ein Ganzzahlenfeld "Alter" integriert. Bilden Sie Funktionen zur Da-teneingabe Create() und zur Druckausgabe List(Sortierfeld). Testen Sie die Methoden Create und List in der Hauptfunktion (main) durch passende Aufrufe.

89. Erstellen Sie eine Struktur Fach zur Speicherung von bis zu 10 mündlichen und bis zu 10 schriftlichen Zensu-ren oder Notenpunkten (00...15) für ein Unterrichtsfach. Weiter werden die Bezeichnung des Unterrichts-faches und der(die) Name(n) der bis zu 5 unterrichtenden Lehrer(innen) in die Struktur aufgenommen. Bil-den Sie eine Funktion Fach_ein() zur Eingabe der Fachbezeichnung, der Lehrernamen und der Noten (ge-sondert nach mündlichen und schriftlichen Noten). Erstellen Sie eine Funktion Fach_aus() zur Ausgabe aller Daten dieser Struktur, ergänzt durch den Mittelwert der mündlichen und den der schriftlichen Noten.

90. Erweitern Sie die Struktur Schueler aus Aufgabe 82 um 20 Attributinstanzen der Struktur Fach aus Aufgabe 83. Schaffen Sie ein geeignetes Menü zur Bearbeitung von Schülerdaten. Nehmen Sie zusätzliche Funktio-nen zur Änderung Change(SNr) und Löschung Delete(Snr) von Schülerdaten anhand der Schülernummer in das Menü auf!

WORDREGS x BYTEREGS h Startadresse der union r

Gemeinsam von x und h belegt. Abb. 24

Cassebaum, Skript zur Programmierung mit C++

47

4.2 Klassen

Das Konzept der OOP beruht auf der Erfahrung, dass man reale Ob-jekte nach zwei Maßen beurteilt:

Einmal nach Eigenschaften wie Form und Farbe,

Zweitens nach dem Verhalten, das ein Objekt zeigt.

In der OOP werden die Eigenschaften mit Daten (Attribute) und die Verhaltensweisen mit Methoden erklärt. Objekte, die mit den glei-chen Attributen und Methoden definiert werden können, werden in einer Klasse zusammengefasst beschrieben.

Tafel 6

Tafel 7

4.2.1 Objekt und Klasse

Der Mensch als Objekt: Menschen besitzen individuell Eigenschaften und Verhaltensweisen. Diese lassen sich aber durch benennbare gemeinsame Attribute und Methoden beschreiben:

Ein Attribut ist z.B. die Größe des Menschen, der Wert dieses Attri-butes ist bei den einzelnen Menschen unterschiedlich.

Wir sagen:

Die Klasse „Mensch“ enthält die „Größe“ und das „Gewicht“ als Attri-bute. Er kann die Methoden „denken“ und „lesen“ funktional nutzen. Nach der Erklärung der Klasse „Mensch“ wird das Objekt „Lisa Krause“ gebildet („instanziiert“).

In der Programmiersprache C gibt es keine konkreten Elemente für die Umsetzung objektorientierter Bestandteile. Das gesamte objektorientierte Modell wurde in der Sprache C++ durch Anweisungen und passende Funktionalitäten verwirklicht.

Die OOP-Realisierung stellt die wesentlichste Erweiterung von C auf C++ dar.

Definition der Klasse

Instanziierung der Klasse

Objekt

Konstruktor

Nutzungsphase

Objektfreigabe

Destruktor

Vielfache Realisierung („Instanziierung“, „Objektbildung“)

Objekt

Attributwerte

Methoden

Klasse

Attribute Methoden

Erklärung

Objekt

Attributwerte

Methoden

Objekt

Attributwerte

Methoden

Mensch

Größe, Gewicht,...

denken, lesen, ...

Erklärung (Klasse)

Lisa Krause

1,66m, 54 kg,...

Konkretes denken, lesen, ...

Realisierung (Objekt) Abb. 25

Cassebaum, Skript zur Programmierung mit C++

48

4.2.2 Klassendefinition in C++

Klassen fassen C++Speichergrößen (Attribute), wie Variablen, Arrays, Strukturen,... und C++Funktionen (Methoden) zu einem unter einem eigenen Namen verwaltbaren "Datentyp" zusam-men. Es werden geschützte (private oder protected) und öffentliche (public) Attribute und Metho-den unterschieden.

class bruch { public: bruch(int z, int n = 1); // Konstruktor bruch Mul(bruch x); // externen Methoden void Zeige(void); private:int zaehl,nenn; // private Attribute } a(3,4); // Globalobjekt int main() { bruch *p; // Klassenzeiger p = new bruch(2,3); // dynamisches Objekt a.Zeige();cout<<" * ";p->Zeige(); // Ausgabezeile: cout<<" = "; a.Mul(*p).Zeige(); // 3/4 * 2/3 = 6/12 getchar(); return 0; }

Eine Klasse besitzt in ihrer Handhabung sehr große Ähnlichkeit mit den Strukturen der struct-Anweisung. Sie belegt selbst keinen Speicherplatz, wird zur Bildung von Instanzen als datentypähnli-cher Begriff benutzt. Auch die Elementzugriffe sind sehr ähnlich.

4.2.3 Objektbildung und –zugriff

Die Instanzen einer Klasse werden Objekte genannt. Die Instanziierung wird daher auch gern als Ob-jektbildung bezeichnet.

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 Klas-senattribute oder -methoden zugegriffen werden. z.B.: p->Zeige() greift auf die Methode Zei-ge() des Objektes, auf deren Adresse der Zeiger p zeigt.

Ein gemeinsamer Begriff als „Teil einer Klasse“ ist „member“ oder „Element“ einer Klasse. Nur Attri-bute oder Methoden können member der Klasse sein. Methoden können auch als „Memberfunktion“, Attribute als „Elementeigenschaft“ bezeichnet werden.

Die Zugriffsspezifizierer public, private und protected regeln, wie von innerhalb und außer-halb der Klasse auf deren Elemente zugegriffen werden kann. Sie sind daher ein wichtiges Instrument der Datenkapselung.

+ public Das Element kann von jeder eigenen/fremden Klassen erreicht werden.

- private Das Element kann nur von eigenen Methoden benutzt werden.

# protected Es gilt zunächst das gleiche, wie für private. Zusätzlich ist jedoch die Benutzung durch Methoden von Klassen möglich, die von der deklarierten Klasse abgeleitet sind.

Klassen können zeichnerisch als Klassendiagramm dargestellt werden. →

Klassennname

Attribute

Methoden

Abb. 25

Cassebaum, Skript zur Programmierung mit C++

49

4.2.4 Konstruktor und Destruktor

Der Konstruktor ist die Methode, die wie die Klasse selbst benannt ist und zum Zeitpunkt der Ob-jektbildung automatisch gestartet wird. Die Parameter der Konstruktorfunktion können in mehreren überladenen Varianten Attribute des gebildeten Objekts füllen.

Sollte kein Konstruktor selbst definiert worden sein, füllt ein automatisch gebildeter Standardkonstruktor die Attribute mit Basiswerten. Vorsicht! Wenn ein beliebiger anderer Konstruktor gebildet wird, existiert dieser parameterlose Standardkonstruktor nicht!!

Der Destruktor ist wie die Klasse selbst mit vorangestelltem ~ („Tilde“) benannt wird bei der Objekt-freigabe gestartet. Konstruktoren und Destruktoren besitzen keine Datentypen und deshalb auch keinen Wert. Das Anlegen eines Destruktors ist keine Pflicht.

Übungsaufgaben

91. Schaffen Sie eine Klasse zur Behandlung von Brüchen mit einem Konstruktor, der die Zähler- und Nennereingabe zum Zeitpunkt der Instanziierung ermöglicht!

92. Schaffen Sie neben den notwendigen Atttributen und dem Konstruktor eine Methode „Div“, mit deren Hilfe Sie zwei Brüche addieren können und eine Methode „Zeige“, die zur Ausgabe eines Bruches auf dem Bildschirm genutzt werden kann!

93. Schreiben Sie einen Destruktor, der auf dem Bildschirm ausgibt: „Freigabe des Objekts erfolgt!“!

94. Schreiben Sie eine neue private Methode void kuerze() zum Kürzen einer rationalen Zahl!

Testen Sie mit einfachen Befehlen in der main-Funktion alle Methoden! Achten Sie auf die Lauffähigkeit Ihres Programmes!

4.2.5 Vererbung und Aggregation

Eine Klasse „embryo“ heißt in die Klasse „mutti“ aggregiert, wenn sie eine Instanz innerhalb der De-finition der Klasse „mutti“ besitzt:

class mutti{ embryo x; ...}; class embryo{...};

Über die Variable „x“ wird der Zugriff auf die Elemente der Klasse „mutti“ möglich.

Eine Klasse heißt abgeleitet, wenn ihre Definitionszeile den Namen einer Basisklasse benennt:

class vati{...}; class kind: public vati{...};

Aggregation (Einbettung) und Vererbung (Ableitung) sind ähnliche Verfah-rensweisen mit dem Ziel, den Zugriff auf Elemente anderer Klassen zu verein-fachen. Um die richtige Wahl zwischen beiden Verfahren treffen zu können, muß die konkrete Beziehung der Klassen zueinander untersucht werden.

Wir betrachten beispielhaft die Klassen Auto, Motor und Sportwagen. Es soll der Zusammenhang der Klassen mit Blick auf die Möglichkeiten Aggregation oder Vererbung entschieden werden.

Jeder Sportwagen ist ein Auto, ein Motor ist kein Auto. Jedes Auto enthält einen Motor. Deshalb sollte die Klasse Sportwagen von der Klasse Auto abgeleitet werden. Die Klasse Motor sollte dagegen als Objekt in die Klasse Auto aggregiert werden.

embryo mutti

vati

kind

embryo x;

Abb. 26

Cassebaum, Skript zur Programmierung mit C++

50

// Beispiel für privaten, geschützten und öffentlichen Zugriff class Recht { public: float Flaeche(); protected: float b, h; }; class Quader:public Recht { public: Quader(float bk,float hk,float lk) { b=bk; h=hk; l=lk; } float Volumen(); protected: float l; }; void main() { Quader Q(1,2,3); cout <<"Grundfläche: "<< Q.Flaeche(); cout <<"\nVolumen : "<< Q.Volumen(); } float Recht:: Flaeche() { return b*h; } float Quader:: Volumen() { return Flaeche()*l; }

Übungsaufgaben

95. Schaffen Sie eine Basisklasse „Kreis“, die anhand des Attributes „Radius“ mit passenden Methoden den Flächeninhalt und den Umfang berechnen kann! Erarbeiten Sie zwei abgeleitete Klassen „Kugel“ und „Zy-linder“, die Methoden zur Errechnung des Volumens und der Oberfläche dieser Körper enthalten!

96. Erarbeiten Sie die Klassen „Schüler“, „Schulklasse“ und „Schule“! Treffen Sie eine sinnvolle Wahl hinsichtlich der Einbettung oder der Vererbung der Klassen untereinander! Erarbeiten Sie einige wenige Attribute und Methoden für jede Klasse und schaffen Sie von jeder Klasse Beispielobjekte mit sinnvollen Konstruktoren!

Abb. 28

Abb. 27

Cassebaum, Skript zur Programmierung mit C++

51

4.2.6 Textdateien/ Streams

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 Ar-beit mit Textdateien einfach mit Streams ("Strömen") realisieren.

#include <fstream.h> // zusätzlicher Header int main() { ofstream OU; char z; // ofstream für Ausgabeströme OU.open("\\temp\\cpptrain\\MeinText.txt"); // Öffnen if(!OU) { 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 Bei-spiel wird ein Ausgabestream OU vereinbart. Mit OU.open(char* File) wird dieser Stream eröff-net. Wenn die open-Methode keine 0 zurückgibt, war der Vorgang erfolgreich, ansonsten ist ein Feh-ler 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 werden. Zum Abschluss müs-sen geöffnete Dateien wieder geschlossen werden: OU.close();

4.3 Listen

4.3.1 Liste, einfach verkettet

Eine einfach verkettete Liste ist eine durch next-Zeiger verknüpfte Folge dynamisch erzeugter (d.h. mit „new“ erzeugter) Objekte.

Jedes Objekt besitzt ein Folgeobjekt, dessen Adresse als Objektattribut im Zeigerformat Teil jedes Objektes ist. Das letzte Objekt führt im next-Zeiger entweder NULL oder die Adresse des Startele-mentes („Ringliste“).

Sonderform Ringliste:

Jede einfach verkettete Liste besitzt ein erstes Objekt, dessen Adresse in Form eines Startzeigers die gesamte Liste adressiert. Meist wird zur Führung einer Liste eine „aktueller“ Zeiger genutzt, der die Adresse des in Arbeit befindlichen Listenobjektes enthält.

Listen- adresse

1.Objekt

next 2.Objekt

next 3.Objekt

next NULL

Listen- adresse

1.Objekt

next 2.Objekt

next 3.Objekt

next

Abb. 29

Cassebaum, Skript zur Programmierung mit C++

52

// programmiert von Thomas Cassebaum, all rights reserved // Typdefinitionen und Methoden zur Nutzung einer einfach verketteten Liste // *** nicht-objektorientierte Lösung ************************************* void init(); Zeiger kopf,ende,aktuell auf NULL setzen(Liste beginnen) bool fuegeeinvor(); Inhalt von satz vor aktuellem Element einfügen (false:Speicherfehler) bool fuegeeinnach(); Inhalt von satz nach dem aktuellen Element einfügen (false:Speicherfehler) void lies(); satz mit dem aktuellen Element füllen (z.B. nach next(); ) void aendern(); aktuelles Element mit satz überschreiben void head(); erstes Element als aktuelles einstellen void tail(); letztes Element als aktuelles einstellen bool next(); folgendes Element als aktuelles einstellen (false:Tail) bool prev(); vorheriges Element als aktuelles einstellen (false:Head) bool listeleer(); Ist die Liste leer? (false:nein, true:ja) bool letzteselement(); Ist das aktuelle das letzte Element? (false:nein, true:ja) int anzahl(); Rückgabe der Elementanzahl in der Liste struct t_inhalt{ string name; string nummer; }; struct t_liste { t_inhalt inhalt; t_liste* next; }; typedef t_liste* t_zeiger ; t_zeiger kopf,ende,aktuell; t_inhalt satz; FILE *datei; void init() { kopf = NULL; ende = NULL; aktuell = NULL; } bool fuegeeinvor() { t_zeiger akt=new t_liste; if(akt==NULL) { cout<<"\nSpeicherfehler! Satz nicht eingefuegt!"; return false; } if(kopf==NULL) // Sonderfall: leere Liste { kopf = akt; ende = akt; akt->next = NULL; } else { if (kopf==aktuell) // Sonderfall: Element wird Kopfelement { kopf = akt; akt->next = aktuell; } else // allgemeiner Fall { akt->next = aktuell; // Vorwaertsverkettung } } akt->inhalt = satz; // Inhalt übertragen aktuell = akt; // das aktuelle Element ist das neue return true; } bool fuegeeinnach() { t_zeiger akt=new t_liste[1]; if(akt==NULL) { cout<<"\nSpeicherfehler! Satz nicht eingefuegt!"; return false; } if(kopf==NULL) // Sonderfall: leere Liste { kopf = akt; ende = akt; aktuell = akt; akt->next = NULL; } else { akt->next = aktuell->next; // Vorwaertsverkettung aktuell->next = akt; }

Cassebaum, Skript zur Programmierung mit C++

53

akt->inhalt = satz; // Inhalt übertragen if(aktuell==ende) // ggf. Ende aktualisieren ende = akt; aktuell = akt; // das aktuelle Element ist das neue return true; } void lies() { if(aktuell!=NULL) satz = aktuell->inhalt; } void aendern() { if(aktuell!=NULL) aktuell->inhalt = satz; // Uebertragen des Inhaltes else fuegeeinnach(); // Wenn Liste Leer, Element einfügen } void head() { aktuell = kopf; } void tail() { aktuell = ende; } bool next() { if(aktuell->next!=NULL) { aktuell = aktuell->next; return true; } else return false; } bool listeleer() { if(kopf==NULL) return true; else return false; } bool letzteselement() { if(aktuell==ende) return true; else return false; } int anzahl() { t_zeiger akt=kopf; int counter=0; while(akt!=NULL) { counter++; akt=akt->next; } return counter; }

4.3.2 Liste, doppelt verkettet

Die Listenobjekte einer doppelt verketteten Liste besitzen neben dem next-Zeiger einen weiteren wichtigen Zeiger zur Elementverknüpfung: den prev-Zeiger. Jedes Folgeobjekt besitzt einen Vorgän-ger, dessen prev-Adresse als Objektattribut im Zeigerformat Teil jedes Objektes ist. Das letzte Objekt führt im prev-Zeiger entweder NULL oder die Adresse des letzten Elementes („doppelte Ringliste“).

Doppelringliste:

// programmiert von Thomas Cassebaum, all rights reserved // Typdefinitionen und Methoden zur Nutzung einer doppelt verketteten Liste

Listenadresse

NULL 1.

next prev NULL 2.

next prev 3.

next prev

Listenadresse

1.

next prev 2.

next prev 3.

next prev

Abb. 30

Cassebaum, Skript zur Programmierung mit C++

54

// *** objektorientierte Lösung ******************************************* class d_list // Klasse der Listen { friend class d_liste_l; // Zugriff auf prev und next erlauben public: d_list(void): head(0), tail(0) { } // Konstruktor: Liste leer d_list &insHead(d_liste_l *el); // vorn einfügen d_list &insTail(d_liste_l *el); // hinten anfügen d_liste_l *getHead(void); // gib erstes Element d_liste_l *getTail(void); // gib letztes Element private: d_liste_l *head, *tail; // Anfangs-/Endelement }; class d_liste_l // Klasse der Listenelemente { friend class d_list; // Zugriff auf prev und next erlauben public: d_liste_l *operator++(void) // next Operator ++ { return akt=akt?akt->next:liste.head;} d_liste_l *operator--(void) // prev Operator -- { return akt=akt?akt->prev:liste.tail;} protected: d_liste_l(void):prev(0),next(0),akt(0){} // Konstruktor: kein Vorgg./Nachf. virtual ~d_liste_l(void) { } private: d_list liste; d_liste_l *prev, *next, *akt; // Folge-/Vorgänger-/aktuelles Element }; d_list &d_list::insHead(d_liste_l *el) // vorn einfügen { if(head) head->prev = el; else tail = el; el->next=head; el->prev=0; head=el; return *this; }; d_list &d_list::insTail(d_liste_l *el) // hinten anfügen { if(tail) tail->next = el; else head = el; el->prev=tail; el->next=0; tail=el; return *this; }; d_liste_l *d_list::getHead(void) // gib erstes Element { d_liste_l *a=head; return a; } d_liste_l *d_list::getTail(void) // gib letztes Element { d_liste_l *a=tail; return a; } class X: public d_liste_l // Kindklasse von s_liste_l mit Textfld { friend ostream &operator<<(ostream &ost, X *elp) { return ost << elp->str; } public: X(char *s): str(s) { } private: char *str; // Textfeld zusätzlich zur Elternklasse

};

Cassebaum, Skript zur Programmierung mit C++

55

5 Aufgaben zur Prüfungsvorbereitung

5.1 Theoretische Fragen, ohne PC schriftlich zu lösen

1. Erläutern Sie den Begriff „Iteration“! Nennen Sie und bringen Sie kurze Beispiele zu allen C++Schleifenformen!

2. Erklären Sie die Funktion und die Arbeitsweise des Präprozessors! Nennen Sie zwei Präprozesoranweisungen und beschreiben Sie deren Einsatzzweck!

3. Erklären Sie die unterschiedlichen Typen zur Parameterübergabe „call by value“ und „call by reference!“ in C/C++. Beschreiben Sie den Einsatz von Referenzparametern!

4. Schreiben Sie beispielhaft je einen Quelltext für eine Rekursion und eine Funktionsüberadung auf!

5. Erörtern Sie den Begriff Zeiger. Definieren Sie verschiedene Zeigervariablen für unterschiedliche Datenty-pen! Füllen Sie die Zeiger mit passenden Adressen und lassen Sie sich die Adressen und deren Inhalt auf dem Bildschirm typgerecht anzeigen!

6. Erörtern Sie, warum eine Kombination aus ARRAY und STRUCT zur Speicherung größerer, logisch zusam-mengehöriger Datenmengen genutzt wird! Schreiben Sie ein beliebiges C++-Beispiel, das Ein- und Ausgaben für Elemente der Array-Struct-Kombination enthält!

7. Erklären Sie den Begriff „dynamisches Array“! Welche Anweisung wird zum Aufbau eines solchen Arrays verwendet (Quelltext-Beispielzeile in C++)? Wie wird ein Element eines dynamischen Arrays gerufen (Quell-text-Beispielzeile in C++)? Warum und wie wird das dynamische Array freigegeben?

8. Beschreiben Sie die Realisierung der Speicherung von Zeichenketten in C (nullterminierte Strings) und in C++ (string-Klasse)! Wie können Sie programmtechnisch das fünfte und wie das vorletzte Zeichen eines C-Strings und wie bei einem C++-String inhaltlich erkennen (z.B. ausgeben)?

9. Sortieren Sie ein dynamisches Array mit ganzzahligen Zufallszahlen! Berechnen Sie die Summe und den Mittelwert aller Zufallszahlen! Bestimmen Sie die Anzahl aller enthaltenen ungeraden Zahlen! Vergrößern Sie ein dynamisches Array!

10. Begründen Sie, warum für größere Datenmengen häufig nicht ARRAYs, sondern verkettete Listen verwen-det werden!

11. Nennen Sie zwei Motive zur Verwendung der heute oft genutzten objektorientierten Programmierung (OOP)!

12. Beschreiben Sie , wie die rechts dargestellte C++ Funktion arbeitet und erläutern Sie deren Zweck!

13. Schreiben Sie eine Funktion rnd(double &w, int s), die die reelle Zahl w auf s Stellen nach dem Komma rundet!

double func(double w) { int z; w = w * 100 + 0.5; z = (int)w; w = (double)z/100; return w; }

14. Beschreiben Sie , wie das rechts dargestellte Struktogramm arbeitet und erläutern Sie dessen Zweck!

15. Setzen Sie das Struktogramm als C++ Hauptpro-gramm um und testen Sie dieses Programm!

Eingabe String1

Beseitige alle Zeichen in String1, die keine Ziffern (0..9) sind!

Falls String1 mit „049391“ oder mit „0391“ beginnt, entferne genau diese Ziffern aus String1

Ausgabe String1

Solange (String1 nicht leer)

16. Erklären Sie bei Funktionen in C/C++ die Unterschiede des Typs der Funktion zwischen void und einem an-deren beliebigen Datentyp! Begründen Sie, warum sollten globale Variablen nur in Ausnahmefällen für den Datenaustausch zwischen den Funktionen verwendet werden!

17. Erörtern Sie die Unterschiede einer einfach und einer doppelt verketteten Liste!

18. Zeichnen Sie ein Klassendiagramm für die Daten zu den Post-Sendungen als verkettete Listen! Benutzen Sie eine virtuelle Basisklasse „Sendung“ und zwei Kindklassen „Brief“ und „Paket“. Ein Brief kann die logische Eigenschaft „Doppelbrief“ besitzen. Vom Paket ist das Gewicht relevant. Zeichnen Sie eine Lösung als ein-

Cassebaum, Skript zur Programmierung mit C++

56

fach und eine zweite als doppelt verkettete Liste! Neu zu erfassende Sendungen sind grundsätzlich dyna-misch zu erstellen und beim Löschen wieder freizugeben!

19. Erklären Sie die Begriffe mit Bezug zur OOP: Klasse, Instanz, Kapselung, Vererbung, Attribut, Methode, Konstruktor, Destruktor, Parentalklasse, Basisklasse, Kindklasse, Polymorphismus, Memberfunktion, Objekt, Listenanker, prev-Zeiger.

5.2 Praktische, am PC zu lösende Aufgabe

a) Zeichnen Sie ein Klassendiagramm zu folgender Problemstellung.

Die Klasse "Tperson" hat die nicht öffentlichen Attribute:

"pnr" Personalnummer "name" Name "anr" Abteilungsnummer "gehalt" Monats-Bruttogehalt

Notieren Sie im Diagramm die zur Klasse gehörenden kompletten Quelltexte der Methoden "Setze" und "Zeige" zur jeweils vollständigen Ein- und Ausgabe aller Attribute.

Notieren Sie im Diagramm einen Konstruktor, der die numerischen Attribute mit passenden Nullwerten und die Zeichenketten als leere Zeichenketten initialisiert.

b) Setzen Sie das Klassendiagramm aus a) in Form eines Quelltexts um, erweitern Sie es mit einer passen-den main() –Funktion und den folgenden Angaben! Erstellen Sie eine statischen Instanz "beschaeftigter" dieser Klasse. Notieren Sie Quelltextzeilen zum Aufrufen der Dateneingabe- und der Datenausgabe-Methode für die Instanz " beschaeftigter".

c) Formen Sie die gesamte in a) und b) geschaffene Lösung so, dass Sie beliebig viele neue Mitarbeiter in einer einfach verketteten Liste speichern, löschen, ändern und anzeigen können. Zeigen Sie auf dem Bildschirm ein kurzes Menü an, was die einzelnen Funktionen per Anfangsbuchstabe abrufbar macht!

d) Schaffen Sie die Statistikmethoden gesamt_gehalt(), gehalts_mittel(abteilung), mitarbeiter-_zahl(abteilung), gehalt_pro_mitarbeiter_mittel(abteilung) … und testen Sie diese im Hauptprogramm!

define ....................................................... 62 #include ....................................................... 11 include ...................................................... 62 abs ................................................................ 60 abweisende Schleife ................................ 20, 21 Adressen ........................................................ 61 Adressoperator .............................................. 61 Aggregation ................................................... 49 aggregiert ...................................................... 49 aktueller Parameter ...................................... 29 Alias ............................................................... 31 Alternative ..................................................... 60 Anfragefunktion ............................................ 61 append .................................................... 35, 60 Arrays....................................................... 33, 61

AAsssseemmbblleerr ........................................................ 7 Assemblersprache ........................................... 7 assign .......................................................... 60 atan .............................................................. 60 atod .............................................................. 60 atof .............................................................. 60 atoi .............................................................. 60 Attribute .................................................. 45, 48 Auftragsfunktion............................................ 61 Ausdrücke ...................................................... 14

Beamer .......................................................... 10 Bezeichner ................................................ 12 Bildschirmausgaben ...................................... 13 Bitstreamoperator >> ................................ 51

bbiittwweeiissee OOppeerraattoorreenn ..................................... 14 bool ....................................................... 12, 59 break ..................................................... 19, 60 c_str ..................................................... 35, 60 C++ Trainer 2.0 ................................................ 9 C++Trainer ...................................................... 9 capacity ..................................................... 60 case ....................................................... 19, 60 ceil ............................................................. 60 cerr ............................................................. 59 char......................................................... 13, 59 cin .......................................................... 13, 59 class ........................................................... 61 close ........................................................... 62 clreol ......................................................... 59 clrscr ......................................................... 59 Codierung........................................................ 6 compare ................................................. 35, 60

CCoommppiilleerr ......................................................... 8 const ........................................................... 60 continue ..................................................... 60

Cassebaum, Skript zur Programmierung mit C++

57

cos ................................................................ 60 cout .................................................... 11, 13, 59 C-String .......................................................... 60 Datenkapselung ............................................. 48 Datentypen .............................................. 12, 59 default.................................................. 19, 60 delete .......................................................... 41 delete[] ..................................................... 61 Destruktor ..................................................... 49 divide and conqeur ........................................ 31 divide and conquer ........................................ 43 do ............................................................ 22, 60 doppelt verketteten Liste .............................. 53 doppelte Ringliste .......................................... 53 double .................................................... 12, 59 do-while-Schleifen ......................................... 22 Dynamisches Array ........................................ 41 E/A-Stream-Bibliothek ................................... 11 Easycode EasyCase (C++) 6.8 ........................... 9 einfach verkettete Liste ................................. 51 else ........................................................ 18, 60 empty ............................................................ 60 Entwicklungsumgebung .................................. 9 Ergibtanweisung ............................................ 12 exit .............................................................. 62 exp ................................................................ 60 fabs .............................................................. 60 Fallunterscheidung ........................................ 19 false ............................................................... 15 Felder ............................................................. 33 fill .............................................................. 62 float ...................................................... 12, 59 floor ............................................................ 60 for ................................................................ 60 For-Anweisung ............................................... 21 formaler Parameter ....................................... 28 friend .......................................................... 61 Funktionen............................................... 28, 61 Funktionsüberladung .................................... 32 fußgesteuerte Schleife .................................. 22 gcvt .............................................................. 60 get .......................................................... 59, 62 getch ............................................................ 59 getchar........................................................ 59 getline........................................................ 62 get-Methode ................................................. 51 Gleitkomma ................................................... 59 Grossbuchstaben ........................................... 62 Grundlagen der Programmierung ................... 6

HHeeaaddeerr ........................................................... 11 Heap .............................................................. 41 hex ................................................................ 62

HHoottKKeeyyss ......................................................... 10 if ............................................................ 18, 60 ifstream .................................................. 51, 62 in .................................................................. 62 Inhaltsoperator ............................................. 61 insert ................................................... 35, 61 Insertion Sort ................................................ 43 Instanz ........................................................... 49 int .......................................................... 12, 59 integrierten Entwicklungsumgebung ............. 9 Interfacemethode ......................................... 61

IInntteerrpprreetteerrss ..................................................... 8 ios:: ........................................................... 62 iostream.h .............................................. 11 Iteration ........................................................ 60 itoa ............................................................. 60 kbhit ........................................................... 59 Klassen .......................................................... 61 Klassendiagramm .......................................... 48 Klasseninstanzen........................................... 48 Konstruktor ................................................... 49 Kopfgesteuert ............................................... 60 kopfgesteuerte Schleife .......................... 20, 21 Kurzübersicht ................................................ 59 length ................................................... 35, 61 Liste, doppelt verkettet ................................ 53 Liste, einfach verkettet ................................. 51 Listen ............................................................. 51 log ................................................................ 60 Logische Ausdrücke ...................................... 15

llooggiisscchhee OOppeerraattoorreenn ..................................... 14 Logische Werte ............................................. 15 main( ).......................................................... 11 main-Funktion ............................................... 29

MMaasscchhiinneennbbeeffeehhll ............................................ 6 Maschinenorientierte Programmiersprachen 7 Mathematik .................................................. 60 max ................................................................ 60 Mehrfachauswahl ......................................... 19 Methoden ............................................... 48, 61 min ................................................................ 60

MMnneemmoonniikk ....................................................... 7 new ......................................................... 41, 61 next-Zeiger .................................................... 51 nicht abweisende Schleife ............................ 22 nocreate ..................................................... 62 NULL .............................................................. 51 Nullterminierte (C-)Strings............................ 60 Numerische Ausdrücke ................................. 15

nnuummeerriisscchhee OOppeerraattoorreenn ............................... 14 Objektbildung ............................................... 61 Objekte ......................................................... 48

Cassebaum, Skript zur Programmierung mit C++

58

Objektfreigabe ............................................... 61 Objektorientierte Programmierung .............. 45 oct ................................................................ 62 ofstream ................................................. 51, 62 open .............................................................. 62 OpenGl-Grafikprogramme............................. 10 Operandenteil ................................................. 7 Operationsteil .................................................. 7 Operatoren .............................................. 14, 59 Overloading ................................................... 32 Pfeiloperator -> ............................................. 48 PI .................................................................. 60 Pointer ........................................................... 36 pow ................................................................ 60 Präprozessor-Anweisung ............................... 11 precision ................................................... 62 prev-Zeiger .................................................... 53 private ..................................................... 48, 61 Problemorientierte Programmiersprachen ..... 8

PPrrooggrraammmm ........................................................ 6 Programmbegriff ............................................. 6 Programmiersprachen ..................................... 6 Programmzustände ......................................... 6 protected ................................................. 48, 61 Prozessor ......................................................... 6

PPrroozzeessssoorrbbeeffeehhll ............................................... 6 public ....................................................... 48, 61 Punktoperator ............................................... 48 put ................................................................ 62 put-Methode ................................................. 51 Quicksort ....................................................... 43 rand .............................................................. 33 random .......................................................... 33 randomize ............................................. 33, 62

RRaannggffoollggee ................................................. 14, 59 Rangfolge aller Operatoren ........................... 14 reelle Zahlen .................................................. 59 Rekursionen ................................................... 31 replace........................................................ 61 resetiosflags .......................................... 62 return .................................................... 29, 61 Ringliste ......................................................... 51

RRüücckkggaabbeewweerrtteess ............................................ 28 runde ............................................................. 60 Schleife .......................................................... 60 Schulgesetz ...................................................... 2 Selektion .................................................. 17, 60 Sequenz ......................................................... 17 setiosflags ............................................... 62 settextposition ...................................... 59 setw .............................................................. 62 short ...................................................... 12, 59

sin ................................................................ 60 Snippetlisten ................................................. 10 Softwareentwicklung .................................... 24 Sortierung ..................................................... 43 srand ........................................................... 62 Startzeigers ................................................... 51 static ......................................................... 61 strcat ......................................................... 60 strcmp ......................................................... 60 strcpy ......................................................... 60 Streams ......................................................... 51 string ...................................................... 13, 60 strlen ......................................................... 60 strnset ....................................................... 60 struct ......................................................... 61 Strukturattribute........................................... 45 Strukturen ............................................... 45, 61 substr ................................................... 35, 61 swap ............................................................. 61 switch ................................................... 19, 60 syntax-highlighted ........................................ 10 tan ................................................................ 60 Tastatureingaben .......................................... 13 textbackground ....................................... 59 textcolor .................................................. 59 Textdateien ................................................... 51 Texteingabe .................................................. 59 time_t ......................................................... 62 true ............................................................... 15

TTyyppbbeezzeeiicchhnneerr............................................... 12 Unions ..................................................... 45, 61 unsigned ............................................... 12, 59 uppercase .................................................. 62 Variablen ....................................................... 12 Vererbung ..................................................... 49 Verzweigungen ............................................. 19 void ............................................................. 59 Wasserfallmodell .......................................... 24 Wert .............................................................. 12 Wertkonstante .............................................. 12 while ........................................................... 60 width ........................................................... 59 Zahlen ........................................................... 60 Zahlenwerte .................................................. 15 Zeiger ...................................................... 36, 61 Zeigeradresse ................................................ 37 Zeigerarithmetik ........................................... 37 Zufallswert .................................................... 33 Zugriffsspezifizierer ....................................... 48

ZZuuwweeiissuunngg ..................................................... 12

ZZuuwweeiissuunnggssooppeerraattoorreenn ................................. 14 Zyklus ............................................................ 60

Cassebaum, Kurzübersicht zur Programmiersprache C und C++ 59

Kurzübersicht zur Programmiersprache C und C++ <Ax> Kurzdarstellung einer Anweisung Ax. Es könnte sich um eine einzelne C/C++-Anweisung oder um eine Block- oder

Mehrfachanweisung handeln. ( Mehrere Anweisungen in { …; } geklammert stehen für eine Anweisung!) <LA> Logischer Ausdruck LA (jeder Ausdruck, der einen Wert true oder false besitzt). z.B.: =0 → false, ≠0 → true <Wx> Kurzdarstellung eines Wertes Wx. Werte in C/C++ sind datentypabhängige Größen. Beispiele: bool: true/ false, char: ’a’, int: -1, float/double: 3.14E-2, string: “Schule” <Dx> Typabhängiges Datenobjekt Dx, z.B.: Variable, Arrayelement, Funktionspara., struct-Instanz, class-Objekt <typ> Datentypbezeichner, wie int, float, bool, double, char, … (xx.h) Header xx, der mit einer #include-Präprozessor-Direktive vor Nutzung des erklärten Kommandos aufzurufen ist. Operatoren || logisch „or“ + Addition, string-Verkettung < kleiner als > größer als && logisch „and“ - Subtraktion <= kleiner oder gleich >= größer gleich ^ logisch „exclusive or“ * Multiplikation, Zeigertyp == gleich != ungleich ! logisch „not“ / Division = Zuweisung += aufaddieren | bitweises „or“ % modulo (Divisionsrest) -= abziehen *= aufmultiplzrn. ~ Bitkomplement, Destruktor -> Zeiger des Elements von . Element von /= aufdividieren & bitweises „and“, Adressoperator für Zeigerzuweisung, Referenzoperator ++ Inkrement () Ausdrucksvorrang {} Anweisungsblock [] Arrayindex -- Dekrement << Linksshift, Outputstream >> Rechtsshift, Inputstream :: Bereichszuordnung , Anweisungsverbd <<= Linksshift zuweisen >>= Rechtsshift zuweisen %= Modulo zuweisen &= bitw.“und“zws. sizeof(<D>)Bytezahl von D new <typ>[n];Heapforderung delete Heapfreigabe typeid Typinfo (cast)explizite Typumwandlung mit in () gesetzten Datentyp. z.B: (3/4) ergibt: 0, aber: (float)(3/4) ergibt 0.75 Rangfolge: (1)()•[]•->•::•.(2)!•~•++•--•*•&•sizeof•new•delete•typeid•cast(3).*•.->(4)*•/•% (5)+•-(6)<<•>>(7)<•<=•>•>=(8)==•!=(10)^(11)|(12)&&(13)||(14)?:(15)=•+=•-=•*=•/=•%=•>>=•<<=•&=•^= Datentypen Länge int 4 Byte „Integer“, ganze Zahlen -2

31…2

31-1

unsigned int 4 Byte „Dual ohne Vorzeichen“, natürliche Zahlen 0…232

-1 short int 2 Byte „Integer-kurz“, natürliche Zahlen 0…2

16-1

char 1 Byte „Zeichen“, natürliche Zahlen 0…28-1

bool 1 Byte „Boolsch“, logische Werte true (≠0) oder false (=0) float 4 Byte „Gleitkomma einfach“, reelle Zahlen 7 Stellen genau double 8 Byte „Gleitkomma doppelt“, reelle Zahlen 15 Stellen genau long double 10 Byte „Gleitkomma lang doppelt“, reelle Zahlen 19 Stellen genau void - leer, „nichts“ Textausgabe clrscr(); (conio.h) Gesamten Text im Bildschirm löschen clreol(); (conio.h) Löscht Zeile ab Cursor bis zum Zeilenende cout<<...; (iostream.h) „stream“ Standardausgabe (auf Bildschirm, umlenkbar) cerr<<...; (iostream.h) „stream“ Fehlerausgabe (auf Bildschirm, umlenkbar) cout.width(n); (iostream.h) Vorgabe der Ausgabebreite als Zeichenanzahl n _settextposition (<Wy>, <Wx>); (conio.h) Nächste Ausgabeposition festlegen, oben und links ist (1,1) textcolor (<W>); (conio.h, iostream.h) Legt Textfarbe W fest textbackground (<W>); (conio, iostream.h) Legt Texthintergrundfarbe W fest cout<<“\n“ (iostream.h) Neue Zeile(CR - carriage return/LF - line feed) cout<<endl; (iostream.h) Neue Zeile(CR/LF), endl leert auch den Puffer. cout<<“\t“ (iostream.h) Tabulator, springt zu Position 9, 17, 25, 33, ... cout<<“\r“ (iostream.h) Wagenrücklauf, Cursor kommt an Anfang der Zeile cout<<“\b“ (iostream.h) Backspace, ein Zeichen wird gelöscht. cout<<”\\...\’...\“...“ (iostream.h) Backslash \, Apostroph ’, Anführungsstriche “ ausgeben. cout<<“\a“; oder cout<<“\007“; (iostream.h) Gibt einen Ton aus (kurzes Piepsen).

Texteingabe cin>> <D>; (iostream.h) „stream“ Standardeingabe in D von Tastatur (umlenkbar) char c=getch(); (conio.h) Pause bis Taste gedrückt wird, Taste in c speichern getchar(); (stdlib.h) Pause bis Taste gedrückt wird while(!kbhit()) x++; (stdio.h, conio.h) Warten und zählen, bis eine Taste betätigt wird; char <D>; <D>=cin.get(); (iostream.h) Nimmt die nächste Taste, die der User eingibt, in D auf <D> = getch()-’0’; (conio.h) D erhält den Wert der nächsten Ziffer, die gegeben wird.

Cassebaum, Kurzübersicht zur Programmiersprache C und C++ 60

Zahlen und Mathematik <D>*=-1;<D>/=2;<D>+=1;<D>-=1; Ändere <D> durch Multiplizieren von <D> mit -1, dividieren durch 2, … <D1>=<D2>++; Erhöhe <D2> nach Zuweisung, d.h.<D1> wird alter Wert zugewiesen. <D1>=--<D2>; Vermindere <D2> vor Zuweisung, d.h. <D1> bekommt den neuen Wert <D>=sin(<W>),cos,tan,atan,... (math..h) diverse mathematische Funktionen für Parameter W <D>=exp(log(<W1>)*<W2>) (math.h) (W1)

W2 rechnen (Exposant) und D zuweisen.

abs(<W>), fabs(<W>), labs(<W>) (math.h,stdlib.h) Die Absolutbeträge von int/float/long <D>=pow (<W1>,<W2>) (math.h) (W1)

W2 rechnen und D zuweisen.

<D>=ceil(<W>); (math.h) D den ganzzahlig aufgerundeten Wert von W zuweisen. <D>=floor(<W>); (math.h) D den ganzzahlig abgerundeten Wert von W zuweisen. <D>=min(<W1>,<W2>); (stdlib.h) D das Minimum von W1 und W2 zuweisen. <D>=max(<W1>,<W2>); (stdlib.h) D das Maximum von W1 und W2 zuweisen. 0x1A9F / 015237 hexadezimale Zahl (beginnt mit 0x) /oktale (beginnt mit 0) 3.14159f Wert anstelle von double(Standard) als float im Programm ablegen. 44. Wertkonstante anstelle von int (Standard ohne Punkt) als double ablegen. Maximalwerte für signed/unsigned: char: 127/255, int: 2,14Mrd. / 4,27Mrd., Maximalwerte/Stellengenauigk. float:3.4e38/7,double:1.7e308/15,long double:3.4e4932/19 M_PI (iostream.h) Zahlkonstante π (Pi) als double-Wert const long PI= 3.14159; Festlegen von Konstanten <D1>=atoi(<D2>); (stdlib.h) D1 wird der int-Zahlenwert vom String D2 zugewiesen <D1>=atod(<D2>); (stdlib.h) D1 wird der double-Wert vom String D2 zugewiesen <D1>=atof(<D2>); (stdlib.h) D1 wird der float-Zahlenwert vom String D2 zugewiesen itoa(<W>, <D>, n); (stdlib.h) int-Wert W Basis n:2|8|10|16 in C-String(nt.) D wandeln. gcvt(<W>, <D>, n); (stdlib.h) double-Wert W (n Stellen) in C-String(nullt.) D wandeln.

Selektion (Alternative) if(<LA>)<A1>; Wenn LA=true, wird Anweisung(-sblock) A1 abgearbeitet, sonst nicht. if(<LA>)<A1>; else <A2>; Wenn LA=true, wird Anweisung(-sblock) A1 abgearbeitet, sonst A2. switch(i) Fallunterscheidung, Mehrfachselektion, i muss ganzzahlig sein, { case 1: case 2: <A1>; falls i den Wert 1 oder 2 enthält, wird A1 und danach A2 ausgeführt, case 3: <A2>; break; falls i den Wert 3 enthält, wird nur A2 ausgeführt, jeder nicht als vorlau- default: <A3>;} fendes case abgeprüfter Wert führt zur Bearbeitung von A3. <D>= <LA>? <W1>: <W2>; ?-Operator: Falls LA=true, erhält D den Wert W1, sonst den Wert W2.

Iteration (Schleife, Zyklus) for(<A1>; <LA>; <A2>) <A3>; Kopfgesteuert: Führt zuerst genau 1x Anweisung A1 aus, prüft dann den logischen Ausdruck LA. Solange LA=true, wird nun zyklisch zuerst A3 und dann A2 ausgeführt (bis LA=false). for(i=a; i<b; i+=c) <A>; Zählschleife: Anfangswert a, Endwert b, Schrittweite c (1: A läuft b mal) while(<LA>) <A>; Kopfgesteuert, Solange logischer Ausdruck LA=true, führe A aus do <A>; while(<LA>); Fußgesteuert, Wie while, LA wird erst nach der 1. Ausführung geprüft. break; sofortigerAbbruch eines switch-, for-, do-, oder while-Blockes continue; Fortsetzung mit Schleifenbeginn (kein Schleifenabbruch)

Nullterminierte (C-)Strings char s[20]; Definition eines C-Strings s (char-Array) mit maximal 20 Zeichen char s[]= “Weissbrot“; Definition eines C-Strings s mit Inhalt „Weissbrot“ für max. 9 Zeichen strcpy(s, “Hallo“); (string.h) C-String s wird mit Text und Nullterminator gefüllt. strcat(s, “ Welt!“); (string.h) An den C-String s wird angehängt, \0 wird angepasst <D>= strcmp (s, q); (string.h) Vergleicht C-Strings s und q (s<q→D<0, s=q→D=0, s>q→D>0) <D>= strlen(s); (string.h) Ermittelt die Länge des Textes im String, ohne Terminator <D>= strnset(s, z, n); (string.h) C-String s wird mit n mal dem Zeichen (char) z gefüllt. (C++-)Strings der Klasse string string s; Definition eines C++-Strings s (class string) s+=“kette“; hängt den String „kette“ an C++ String s an. s.append(“kette“); hängt den String „kette“ an C++ String s an. s.append(“kette“, 0, 3); hängt die ersten 3 Zeichen an C++ String s an. s.assign(“kette“); ersetzt den C++ String s durch „kette“. <D>= s.capacity(); Gibt in D die Zeichenkapazität des C++ String s zurück. <D>= s.c_str(); Übergibt im char-Array D den C++ String s als nullterminierten (C-)String <D>= s.compare(q); vergleicht die C++ Strings s, q (s<q→D<0, s=q→D=0, s>q→D>0). <D>= s.empty(); fragt, ob der C++ String s leer ist. bool D ist true, wenn s leer ist. s.erase(); löscht den Inhalt des C++ Strings s, d.h. s erhält den leeren String als Inhalt.

Cassebaum, Kurzübersicht zur Programmiersprache C und C++ 61

<D>= s.find(q, 3); Sucht im C++ Strings s ab der 3.Position den String q. Gibt Position des Vorkom-mens von q in s als als int-Wert an D zurück. (0 für nicht gefunden).

s.insert(3, q); Fügt im C++ Strings s ab der 3.Position den String q ein. <D>= s.length(); Gibt die Länge C++ Strings s in Zeichen an D zurück. s.replace(a, l, q); Fügt im C++ Strings s ab der a.Position den String q in der Länge l ein. s.resize(l, z); Füllt den C++ Strings s bis zur Länge l mit Zeichen z auf. <D>= s.substr(a, l); Gibt den Teil des C++ Strings s ab Position a in Länge l zurück. s.swap(q); Tauscht den Inhalt des C++ String s mit dem Inhalt von String q. Funktionen void <Fktname>(...) Auftragsfunktion (liefert keinen Wert zurück) <typ> <Fktname>(...) Anfragefunktion (liefert <typ>-Wert über return-Anweisung zurück) ... <Fktname>(void) Funktion wird ohne Parameter aufgerufen return x; Funktion gibt den Wert x zurück return; Beenden einer Funktion ... Fkt(char <D1>, int <D2>=9) Wenn Fkt ohne 2.Parameter gerufen wird, dann wird Parameter D2=9. ... <Fktname>(...); Prototyp, jede Funktion muss einmal im Voraus definiert werden void Fkt() const Funktion ist read-only, d.h. kann keine Daten ändern. static <D1>=999; Statische Variable (innerhalb Funktion) deklarieren. Behält unveränderten Wert

nach Beenden beim erneuten Ruf. (ohne static: Wert zerstört) Arrays

<typ> arrn; Festlegen eines Arrays arr mit n Elementen vom Datentyp <typ>.

int a5= {1, 2, 3, 4, 5}; Definieren des Arrays a mit 5 Elementen a[0]…a[4] mit Initialisierung.

float b354; Festlegen eines (3)dimensionalen Arrays (Feldes). Dieses Array besitzt

3*4*5= 60 Elemente im Bereich von b000 bis b243.

b243= 17; Wertzuweisung an ein Arrayelement Zeiger und Adressen char *Z1, double *Z2; Zeiger kann eine Adresse speichern und somit auf ein Objekt zeigen. Zeig1= &<D>; Adressoperator, gibt die Adresse statt dem Wert von D zurück cout << *Z1; Inhaltsoperator * benutzt den Zeiger Z1 zur Ausgabe des Zeigeobjekts char *s= “Weissbrot“; Definition eines C-Strings s mit Inhalt „Weissbrot“ für max. 9 Zeichen int <D1>; int &<D2>=<D1>; Referenz <D2> hat dieselbe Speicheradresse wie <D1>. („Alias“) int *p = new int[n]; Fordert ein dynamisches Array(Heap) p der Grösse n und Typ int ab. delete[] p; Gibt das dynamische Array(Heap) p wieder frei. Strukturen und Unions struct artikel Festlegen der Struktur artikel { int ArtNr; Festlegung des Strukturelementes ArtNr double Umsatz ...;} In1; Implizite Instanziierung der Instanz In1 (In der Deklarationsanweisung); artikel In2, *In3; Explizite Instanziierung der Instanz In2 (Außerhalb der Strukturdeklar.); In1.ArtNr= 20; Eingabe der Werte für die Struktur artikel In3=new artikel; Dynamische Erstellung einer Strukturinstanz In3->ArtNr=33; Zugriff auf ein Element einer dynamischen Strukturinstanz union ... (siehe struct) Wie struct, bloss dass alle Elemente denselben Speicherbereich nutzen.

Klassen class xx Definition einer Klasse „xx“ { private: int x; Zugriff nur mit klasseneigenen Methoden möglich int met1(); parameterlose private Methode „met1()“ protected: ...; Zugriff mit klasseneigenen und ererbten Methoden möglich public: ...; öffentlicher Zugriff (alle dürfen zugreifen) void SetX(int xs){x=xs;} Interfacemethode, zum Setzen des Privatattributs x xx(int xs){x=xs;} Konstruktor, diese Methode wird bei der Objektbildung gestartet ~xx(); Destruktor, wird wird bei der Objektfreigabe gestartet (Prototyp) } Ob1,Ob2(3); Implizite Objektbildung der Objekte Ob1, Ob2 (oder: Instanz Ob1) xx Ob3; Implizite Objektbildung des Objektes Ob3 void xx::sp(void) (Ausserhalb der Klasse) Die Funktion sp gehört zur Klasse xx. xx::~xx() { cout<<"tot"; } Bei Freigabe einer Instanz von xx wird "tot" ausgegeben friend int freund(kla1, kla2); Deklaration der friend-Methode freund, welche Zugriff auf private class schueler:public mensch schueler erbt alles von der Klasse mensch (Zugang auf alles) class sch:public k1,k2,... sch erbt alles von k1, k2, ...

Cassebaum, Kurzübersicht zur Programmiersprache C und C++ 62

Verschiedenes

include“my_h.h“ Präprozessor: Header wird zuerst im Programmverzeichnis gesucht.

define WERT 12 const Wert=12 Präprozessor: Festlegen von unveränderbaren Variablen. randomize(); (stdlib, stdio, time) aktiviert den Zufallsgenerator srand(getpid()); (stdlib, process) aktiviert einen besseren Zufallsgenerator time_t t; (time.h, stdlib.h, Zufallsgenerator wird mit neuen Zuf.werten initialisiert srand((unsigned)time(&t)); (process.h) (sehr nützlich!) b=rand()%100; (stdlib, stdio, time) b erhält einen Wert >=0 und <100 (int) exit(0); (process.h) Programm beenden, gibt den Rückkehrcode 0 zurück time_t jetzt=time(NULL); while (time(NULL)<jetzt+10); (time.h, dos.h) Pause von 10 Sekunden

Streams cout.width (42) (iomanip.h) Daten über << werden in Breite 42 Zeichen ausgegeben cout << setw(10) << ”...” (iomanip.h) Links wird mit Leerzeichen bis Ausgabebreite 10 aufgefüllt. cout.fill('.'); (iomanip.h) Anstatt mit Leerzeichen wird (hier) mit . aufgefüllt. setiosflags(ios::left) (iomanip.h) Ausrichtung der Daten wird auf linksbündig geändert. resetiosflags(ios::left) (iomanip.h) setiosflags rückgängig machen cout.setf(ios::fixed); (iomanip.h) Zahlen gleicher Nachkommaanzahl (cout.precision vorher benutzen) cout.precision(x); (iostream.h) Angabe der Stellenzahl, mit der eine Zahl ausgegeben wird. cout<<setiosflags(ios::showpos) (iomanip.h) Auch bei positiven Zahlen wird das Vorzeichen angezeigt cout << dec oder hex oder oct (iomanip.h) Zahlen werden in bestimmten Zahlensystemen ausgegeben cout<<setiosflags(ios::uppercase; (iomanip.h) Hexzahlen A…F werden als Grossbuchstaben ausgegeben while((cin.peek())>’9’||cin. peek()<’0’)cin.ignore(); Untersucht Eingabezeichen ; nur Ziffern werden akzeptiert. cin.getline(text,127); (fstream.h) Das Eingegebene wird in text kopiert bis zum nächsten Return cin.get(text,127); (fstream.h) Das Eingegebene wird in text kopiert bis zum nächsten Return. ofstream Ausgabe; (iomanip, fstream.h) Erzeugung des ofstream-Objektes Ausgabe Ausgabe.open(datei1,ios::app) (iomanip, fstream.h)datei1 (= Name der Datei) wird geöffnet, Zeiger ans Dateiende setzen

ios::in Lesen, verhindert bei Ausgabedateien Löschen ios::nocreate Kein Anlegen fehlender Dateien ios::out Schreiben; ohne Angabe weiterer Modi werden vorhandene Dateien gelöscht ios::app Ausgabe an Datei anhängen ios::ate Ausgabe an Datei anhängen, erlaubt nach erster Schreibanweisung. ios:noreplace Keine vorhandene Datei überschreiben ios::trunc Vorhandenen Dateiinhalt löschen

Ausgabe.close(); (iomanip, fstream.h) Objektfreigabe von Ausgabe und Datei schliessen. ofstream Ausgabe2(d2,ios ::ate) (iomanip, fstream.h) Zeiger wird an den Anfang der Datei gesetzt. zeichen=eingabe.get()od:eingabe.get(z)(iomanip, fstream.h) Einzelne Zeichen worauf der Zeiger zeigt, wird in z kopiert. ausgabe.put(z) (iomanip, fstream.h) Das Zeichen auf das der Zeiger zeigt, wird durch z ersetzt.. ifstream test; Testet ob eine Datei existiert (löscht oder ändert nichts und test.open(te xt,ios::in|ios:nocreate); legt auch keine neue Datei an falls nicht vorhanden) if (test.good())... Falls der Test in der vorigen Zeile gut ausgefallen war, … ofstream Drucker(„PRN“,ios::out|ios::app);cout=Drucker; Umlenkung von cout auf den Drucke close Schliesst eine Datei get Liest Zeichen und lässt Stoppzeichen im stream getline Liest Zeichen und entfernt Stoppz. aus Datei ignore Entfernt Zeichen aus dem Datenstrom open Initialisiert das Objekt und öffnet eine Datei peek Prüft Folgezeichen im stream, ohne zu lesen

put Schreibt ein einzelnes Zeichen read Liest Datenblock in einen Speicherbereich seekg,seekp Bewegt Dateizeiger tellg,tellp Ermittelt Dateizeigerposition write Schreibt einen Speicherbereich als Datenblock