Skript - Thomas Cassebaum

Werbung
1
Cassebaum, Skript zur Programmierung mit C++
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
Cassebaum, Skript zur Programmierung mit C++
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 Kultusministerkonferenz 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.
2
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 SmallCpp..................................................................................... 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++
Vorwort
Liebe Leser,
das vorliegende Skript habe ich zur Unterstützung des Unterrichts im Programmierungsteil zum Profilfach „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 Rahmenrichtlinien und der Aufgaben für die schriftlichen Abiturprüfung im genannten Profilfach für das Fachgymnasium 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“, „Technische Kommunikation und Netzwerke“ und „Datenbanken“ werden nicht behandelt.
Ausdrücklich sei gesagt, dass die von mir benutzte Programmiersprache C/C++ in den Rahmenrichtlinien für Fachgymnasien der meisten Bundesländer empfohlen oder gar vorgeschrieben wurden. Nach
Gesprächen mit Vertretern der Praxis und meinen eigenen gesammelten Unterrichtserfahrungen begrüß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
5
6
Cassebaum, Skript zur Programmierung mit C++
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 Realisierung durch den technischen Aufbau der Hardware (insbesondere des Prozessors) gewährleistet ist.
Ein Maschinenbefehl oder
Prozessorbefehl ist eine duale Codierung, die den Prozessor zu einer bestimmten Tätigkeit veranlasst.
Abb. 1
S
o
f
t
w
a
r
e
Befehl 1
H
a
r
d
w
a
r
e
Prozessor
Befehl 2
Befehl 3
…
Befehl n
Programm
Ein Programm 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 entworfen. Dann wird der codierte
Programmtext (Q
Quelle) über Tasteneingabe mit einem Editor erfasst („e
editiert“). Der Compiler übersetzt den Text in Maschinencode, es entsteht das Objekt. Der Linker bindet dieses Objekt mit anderen
notwendigen Objekten zum Task. Mit dem Debugger testet man das Programm.
Nach dem Start belegt das Programm als „P
Prozess“ Teile des Arbeitspeichers, von denen das Betriebssystem (z.B. Windows) die Programmabarbeitung leitet.
Tools
Tätigkeiten
Zustände
Editor
Erfassung/ Bearbeitung des Quelltextes
Quelle (.cpp)
Compiler
Übersetzung des Quelltextes (Borland 5.5)
Objekt (.obj)
ja
Linker
Fehler?
Hilfstools
StruktogrammEditor
(Entwerfen)
nein
Verbindung mit C++Umgebungsmoduln
Task (.exe)
Texteditor
(Dokumentie-
ja
Debugger
Fehler?
ren)
nein
Testen und Fehler finden
ja
Fehler?
nein
Start
Prozess
Tafel 1
7
Cassebaum, Skript zur Programmierung mit C++
1.1.3 Maschinenorientierte Programmiersprachen
Eine Programmiersprache, die genau eine Mnemonik (sprachliches Kürzel. z.B. „MOV“) für jeden Prozessorbefehl besitzt, bezeichnet man als Assemblersprache. Maschinen- und Assemblersprachen werden in der Informatik maschinenorientierte Programmiersprachen genannt.
Eine Quelle ist ein Text (Folge von ASCII-Zeichen), der symbolische Befehle (meist in englischer Sprachanlehnung) enthält. Die Quelle wird in einer Quelldatei auf einem Datenträger gespeichert.
Ein Assembler ist ein Übersetzungsprogramm, das einen symbolischen Befehl im Verhältnis 1:1 in einen binären Maschinenbefehl übersetzt.
Das Ergebnis der Übersetzung ist das Objekt, dessen Inhalt, eine Folge von binären Prozessorbefehlen,
als Binärdatei („O
Objektdatei“) auf einem Datenträger (z.B. Festplatte) gespeichert wird.
Beim Linken 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 “T
Task“, "EXE-File", "ausführbares Programm", „executable binary file“ oder "startbares Programm". Sie wird auf einem Datenträger mit einem Namen gespeichert und von dort gestartet.
Menschliche Sprache
Programmiersprache
Maschinensprache
Addieren, Sortieren, Vergleichen, Suchen, ...
Cout, cin, if, while, then, do,
k++, k=k+12, ...
1100111100001011,
0011101111000011, ...
Beispiel einer mnemonischen Befehlsfolge im Assembler einer Registermaschine:
Operationsteil
LD
ADD
STORE
Operandenteil (hexadezimal)
(Laden in den Akku)
(Addieren zum Akku)
(Speichern des Akkus)
1000 (Speicherstelle der zu lesenden Größe)
1004 (Speicherstellen der Summanden)
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ärcodes dargestellt, spricht man von einer Maschinensprache. Sie kann vom Prozessor unmittelbar (direkt) verstanden werden.
Befehlsmnemonik (8086 -Assembler)
Beispiel für einen Maschinenbefehl:
Der Beispielbefehl füllt das 16-BitRegister AX („Akku“) mit dem Inhalt
des Speicherplatzes, der durch die
symbolische Adresse x erkannt wird.
Ein Register ist ein kleiner Speicherbereich direkt im Prozessor.
MOV
00010100
Operationsteil
Prozessor
CX-Register
AX ,
00011101
1. Operand
x
11101111
2. Operand
Arbeitsspeicher (RAM)
x (Adresse)
BX-Register
AX-Reg. Akku
Speicherplatz „x“ (16 Bits)
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 Befehlscodes für einen Prozessortyp wird auch "M
Maschinensprache" 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 Kommunikationsstruktur recht fremd sind.
Cassebaum, Skript zur Programmierung mit C++
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 problemorientierte Programmiersprachen.
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 Interpreters 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 gespeichert. Damit verlängert sich die Abarbeitungszeit um die benötigte Übersetzungszeit. Programmierer arbeiten gern mit diesem Verfahren bei der Softwareentwicklung, weil die zu entwickelnden Programme 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ültigen Programmgeschwindigkeit dennoch ein Compiler zur Übersetzung eingesetzt.
2. Ein Compiler ist ein Übersetzungsprogramm, das die symbolischen Befehle einer problemorientierten Sprache aus einer Quelldatei vollständig in eine Folge binärer Maschinenbefehle einer abzuspeichernden Objektdatei verwandelt.
Die Vorteile des Einsatzes von problemorientierten Sprachen sind die günstige, vereinfachte Programmentwicklung und die Portierbarkeit (Überführbarkeit in andere Systeme) der Lösungen. Lösungen
mit maschinenorientierten Sprachen besitzen meist eine bessere rechentechnische Qualität (kurze
Laufzeit, geringer Speicherplatzbedarf), weil sie der Maschinenstruktur besser angepasst sind.
Hybridprogramme werden auf Basis problemorientierter Sprachen hergestellt, in denen einzelne rechentechnisch 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 werden? 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 InternetRecherche selbst zu erkennen. Erklären Sie die Vor- und Nachteile dieser Sprachfamilie.
8
9
Cassebaum, Skript zur Programmierung mit C++
1.2 Die integrierte Entwicklungsumgebung C++ Trainer 2.x 1
Für eine Softwareentwicklung empfiehlt sich der Einsatz eines speziellen Softwaresystems, das abgekürzt als „IIDE“ bezeichnet wird. Der Begriff IDE steht für Integrated Development Environment,
deutsch: Integrierte Software-Entwicklungs-Umgebung.
Es handelt sich um eine Sammlung von zueinander passenden Programmen, die für eine effektive Softwareentwicklung notwendig sind. Bei der Sprache C++ sind das Programme der C++ -Sprachumgebung,
passende Toolprogramme und das sogenannte „front end“, das alles bequem durch den Programmierer 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 C++ Trainer 2.3 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++ Programmen Struktogrammzeichnungen oder schreibt umgekehrt automatisch generierte C/C++ Quellen
anhand mit diesem Tool gefertigter Struktogramme.
1.2.1 Bedienelemente des C++ Trainers
Neue Quelldatei
Quelle öffnen/ speichern
Struktogramm zeigen Quelle drucken Breakpoints
Starten Debugger
Hilfe
ein/aus
Bookmarkfinder
Snippets
für
C++
zeigen
Einrücken
der
C++Zeilen
Snippets
Text klein
- groß
Easycode
Beamereinstellung
ein/ aus
Hinweise
und
Fehlermeldungen
Assemblerquelle
Statuszeile
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
10
Cassebaum, Skript zur Programmierung mit C++
Als didaktische Bestandteile besitzt diese IDE sogenannte Snippetlisten, die als Seitenleisten einfach
die C++ Grundbestandteile erklären und rufen lassen. Viele der Snippets lassen sich mit HotKeys (z.B.
Strg/F fügt in den Quelltext eine for-Anweisung ein) aufrufen. Als weiterer Zusatz existiert ein Verzeichnis „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 „C
C++ Builder 5.5 free command line tools“ erstellt
werden können.
1.2.2 Die Entwicklungsumgebung SmallCpp
Diese noch neue Möglichkeit, besonders einfach C++-Entwicklungen durchzuführen, kann auch an 64-Bit-Systemen genutzt
werden. Es gibt viele Ähnlichkeiten mit dem C++ Trainer.
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
Abb. 3
Editorfenster
Ausgabefenster
Auch die Mini-IDE SmallCpp läßt sich von der Download-Seite
http://www.t-cassebaum.de kostenfrei herunterladen.
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
Nach der fertigen Eingabe eines Quelltextes im Editorfenster
sollte er zunächst mit einem neuen Namen abgespeichert werden. Danach erfolgt Übersetzen, Linken und Start des Programmes in einem Schritt. Sollte das Programm nicht starten, werden im Ausgabefenster Fehler und Warnungen 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 Fehler
müssen alle durch Änderung des Quelltextes beseitigt werden. Erst danach kann der erste Programmstart gelingen. Warnungen 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 Ausgabefenster sichtbar und wieder unsichtbar gemacht werden.
11
Cassebaum, Skript zur Programmierung mit C++
1.2.3 Erstes Übungsprogramm
Das denkbar einfachste C++ Programm wird, wie auch in anderen Programmiersprachen, mit dem so
genannten "Hello-world-Programm" vorgeführt. Der Hauptteil des Programms wird Hauptfunktion als
bezeichnet und mit main() eingeleitet. Die folgenden, zwischen geschweiften Klammern angeordneten 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
Hello world!
Der Präprozessor 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.
Header (*.h / *.hpp) sind Textdateien, die C/C++ -Zeilen enthalten, die vom Compiler übersetzt werden. 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 “…“ eingeschlossen 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.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
/* Thomas Cassebaum 2011, all rights reserved
Mehrzeiliger Kommentar wird nicht vom Compiler bearbeitet
beginnt mit: /* und endet mit: */
#include <iostream>
// Zeile mit # ist für den Präprozessor, lädt Header "iostream"
// Einzeiliger Kommentar beginnt mit // und endet am Zeilenende
using namespace std; // Stellt den Standard-Namensraum "std" ein
int main()
// Erste Zeile der main-Funktion (Hauptfunktion)
{ string s;
// Variable: s vom Datentyp: string
cout << "Name: ";
// Ausgabe der Ausschrift mit Leerzeichen am Ende
cin >> s;
// Eingabe von Tastatur wird in der Variablen s gespeichert
cout << "Guten Tag " << s << ". Wie geht's?"; // Ausgabe des Antwortsatzes
getchar();
// Wartet auf die Eingabe einer beliebigen Taste
return 0;
// Liefert Rückkehrcode der main-Funktion (0 bedeutet: Ablauf gut)
}
// Eine schließende geschweifte Klammer schließt die Funktion ab
Aus- und Eingaben des Programmes nach dem Start:
Name: Tim
Guten Tag Tim. Wie geht’s?
12
Cassebaum, Skript zur Programmierung mit C++
1.3 Variablen und Datentypen
1.3.1 Variablen
In C/C++ ist eine Variable ein Datenobjekt mit veränderlichem Wert, das einen Namen und einen Datentyp besitzt, sowie einen Speicherplatz einer festgelegten Länge belegt. Variablen müssen vor ihrer
ersten Verwendung für einen bestimmten Datentyp deklariert werden:
<datentyp><Bezeichner>[,<Bezeichner>[,...]];
// z.B.: int x, y;
Ein Bezeichner in C++ besteht aus einer Folge von Groß-/ Kleinbuchstaben, Ziffern oder der Unterstreichung _ . Das erste Zeichen darf keine Ziffer sein. Der Bezeichner darf beliebig lang sein, nur 250 Zeichen werden zur Erkennung benutzt 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 Zuweisung ("Ergibtanweisung") in der Form:
<variable_typ1> = <Ausdruck_typ1>;
einen Wert.
Der Wert errechnet sich durch einen Ausdruck, der von gleichem Datentyp wie die Variable ist oder in
diesen automatisch konvertiert werden kann. Die Zuweisung kann schon in der Deklaration erfolgen.
void main()
{ int var, VAR, Meine_Lieblingsvariable= 0;
var = -3; VAR = 4;
Meine_Lieblingsvariable = var + VAR;
cout << Meine_Lieblingsvariable;
getchar();
}
1
Im Beispiel werden drei Variablen im ganzzahligen Datentyp (int) deklariert. Die Variable "Meine_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änge ist die Anzahl der Bytes, die eine gespeicherte Variable dieses Datentyps im Speicher belegt.
Typbezeichner in C++ sind z.B.:
Bytes Typ
10 long double
8 double
4 float
4 int
2 short int
4 unsigned int
1 char
? string
1 bool
0 void
int x, y;
x = 0xff;
Tafel 2
geeignet für
sehr genaue reelle Zahlen (bis 18 Stellen)
reelle Zahlen (bis 15 Stellen)
wenig genaue reelle Zahlen (bis 7 Stellen)
ganze Zahlen (-2.147.483.648...2.147.483.647)
ganze Zahlen (-32.768...32.767)
natürliche Zahlen (0...4.294.967.295)
Zeichen (0...255)
Zeichenketten (Klasse string)
logische Werte (true oder false)
leer (ohne Wertrückgabe, main() ohne return)
bool a;
a = true;
double b;
b = 1.2-02;
string s;
s = "\nJa";
Wertkonstante
123456.789012345678
-0.123456789012345
1.234567E02
-0x25 (0x: hexadezimal)
+321
12
'a'
"Zeichen abc"
true
char c;
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.
Cassebaum, Skript zur Programmierung mit C++
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 Typkennzeichner 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.
01
02
03
04
05
06
07
07
08
09
10
11
#include <iostream>
Geschwindigkeitsberechnung
using namespace std;
int main()
Weg
s [in m] : 30
{ double s,t;
Zeit t [in s] : 5
cout << "\"Geschwindigkeitsberechnung\"\n";
cout << "\nWeg s [in m] : "; cin >> s;
Geschwindigkeit : 6 m/s
cout << "Zeit t [in s] : ";
cin >> t;
oder 21.6 km/h
cout << "\nGeschwindigkeit : " << s/t << " m/s"
<< "\noder " << s/t * 3.6 << " km/h";
getchar();
// Wartet auf die Eingabe einer beliebigen Taste
return 0;
// Liefert Rückkehrcode der main-Funktion (0 bedeutet: Ablauf gut)
}
// Eine schließende geschweifte Klammer schließt die Funktion ab
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 eingeschlossen (z.B.: "Kette") und bei Eingaben in Variablen vom Datentyp string gespeichert. Für
Ausgaben können spezielle Zeichenfolgen innerhalb der Anführungszeichen einer auszugebenden Zeichenkette eine besondere Steuerung veranlassen. 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
13
14
Cassebaum, Skript zur Programmierung mit C++
1.4 Operatoren und Ausdrücke
1.4.1 Operatoren
Operatoren beziehen sich auf einen oder zwei Operanden und liefern ein operationstypisches Resultat. Größen (z.B. Variablen, Werte, ...) der Sprache C++, die mit Operanden einfach oder vielfach verknüpft wurden, nennt man Operation oder Ausdruck.
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:
numerische Operatoren
++ (Inkrement)
-- (Dekrement)
% (modulo)
+ (Addition)
logische Operatoren
! (Negation)
> (größer?)
== (gleich?)
!= (ungleich?)
* (Multiplikation)
- (Subtraktion)
/ (Division)
>= (größer gleich?) < (kleiner?) <= (kleiner gleich?)
&& (logisches "UND")
|| (logisches "ODER")
bitweise Operatoren
~ (Komplement) >> (Rightshift) << (Leftshift)
& (AND)
^ (XOR)
| (OR)
Zuweisungsoperatoren
= (ergibt) += (plus gleich) -= (minus gleich) *= (mal gleich) /= (durch gleich)
&= (und gleich)
%= (modulo gleich)
sonstige Operatoren
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;
int y=11; cout << (--(y%5));
int x=5; cout << ((x-5)?5+x:x>>1);
char x='A'; cout << x << "-" << (int)x;
//
//
//
//
Ausgabe:
Ausgabe:
Ausgabe:
Ausgabe:
8
0
2
A-65
Operatoren sind in eine Rangfolge geordnet, so dass innerhalb eines Ausdrucks zunächst die vorrangigen Operatoren realisiert werden. Ausdrücke mit Operatoren können mit Rundklammern geklammert
werden, um die Operatoren in der Klammer im Rang zu bevorzugen.
[()[]-> :: .][! ~ ++ -- sizeof new delete typeid (typumformer)]
[.* ->* ][ * / % ][ + - ]
[<< >> ][ < <= > >= ][ = = != ]
Rangtabelle der Operatoren
[ & ][ ^ ][ | ][ && ][ || ][ ?: ]
[= += - = *= /= %= >>= <<= &= ^= ]




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,
3+(x&&0) ergibt 3,
aber: 12/(2+4) ergibt 2.
aber: 3+x&&0
ergibt 4.
15
Cassebaum, Skript zur Programmierung mit C++
1.4.2 Numerische Ausdrücke
Numerische Ausdrücke <NA> sind alle C++ Bestandteile, die einen Zahlenwert besitzen. Wichtige Beispiele für numerische Ausdrücke sind:
(1)
(2)
(3)
(4)
Logische Werte ( true besitzt den Wert 1, false besitzt den Wert 0 ),
Zahlenwerte (Zahlkonstanten, ganzzahlig: 2, -4, 0xa, ... reell: 0., .3, 3.1e4,... ),
C++Größen (Variablen, u.a.) mit numerischem Datentyp (int, float, double, ... )
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.)
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)
(5)
Beispiele für numerische Ausdrücke mit numerischem Ergebniswert:
cout << "3 * 2 = "
<< 3 * 2;
// 6
cout << "\n3 / 2 = " << 3 / 2;
// 1
cout << "\n3 / 2. = " << 3 / 2.;
// 1.5
cout << "\ntrue = "
<< true;
// 1
cout << "\nfalse = " << false;
// 0
cout << "\n0xa = "
<< 0xa;
// 10
cout << "\n0xa = "
<< hex << 0xa;
// a
cout << "\n027 = "
<< dec << 027;
// 23
cout << "\n027 = "
<< oct << 027;
// 27
cout << dec << "\n7&12 = " << (7 & 12); // 4
cout << "\n5&3 = "
<< 5%3;
// 2
cout << "\n5e1/5 = " << 5e2/50;
// 10
(1 Rest 1)
(hex a = dec 10)
(hex a = hex a)
(oct 27 = dec 23)
(oct 27 = oct 27)
(0111 & 1100 = 0100)
(5/3 = 1 Rest 2)
(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
1
1
0
0
Or
||
1
0
not
0
1
1
1
1
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";
if (i) cout << "i ist true"; else cout << "i ist false";
if (x) cout << "x ist true"; else cout << "x ist false";
if (i-2) cout << "i-2 ist true"; else cout << "i-1ist false";
if (!a) cout << "!a ist true"; else cout << "!a ist false";
cout<<"i==2||i==3 ";if(i==2||i==3)cout<<"true";else cout <<"false";
//
//
//
//
//
//
false
true
false
false
true
true
16
Cassebaum, Skript zur Programmierung mit C++
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.
01
02
03
04
05
06
07
08
09
#include <iostream>
using namespace std;
int main()
{ string s = ((63/5)%7)?"true":"false";
cout << "numerisch: " << (double)((63/5)%7);
cout << "\n logisch: " << s;
getchar();
return 0;
}
numerisch: 5
logisch: true
Beispielaufgabe 4
Das Programm untersucht die drei als Variablen a, b, c gegebenen möglichen Seitenlängen eines Dreiecks. 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.
01
02
03
04
05
06
07
08
#include <iostream>
using namespace std;
int main()
{ float a=6, b=3, c=2.5; string s = (a+b>c)&&(a+c>b)&&(b+c>a)?"Dreieck":"Kein Dreieck";
cout << s;
getchar();
Kein Dreieck
return 0;
}
Übungsaufgaben
Für die Lösung der folgenden Aufgaben wird vorausgesetzt, dass folgende Vereinbarungen vorher vorgenommen 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 Ausdruck, 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.
17
Cassebaum, Skript zur Programmierung mit C++
1.5 Strukturanweisungen
1.5.1 Sequenz
Sequenzen 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!!) abgeschlossen. Anweisungen werden in den Reihenfolgen "von links nach rechts" und "von oben nach unten" abgearbeitet.
Abb.4
A
Sequenzen in der Struktogramm-Darstellung:
B
Mit der in Abb.4 dargestellten Zeichnung wird bestimmt, dass der
Block A vor dem Block B abgearbeitet wird.
A:(BS) : "Spannung U[V]:"
Ausgabe der Eingabeaufforderung am Bildschirm (BS).
E:(Tas) : U
Eingabe von Tastatur (Tas) in der Variablen U speichern.
A:(BS) : "Stromstärke I[A]:"
Ausgabe der Eingabeaufforderung am Bildschirm (BS)
E:(Tas) : I
Eingabe von Tastatur (Tas) in der Variablen I speichern.
A:(BS) : U / I, "Ohm"
Ausgabe des errechneten Ergebnisses am Bildschirm (BS)
double U, I;
cout << "Programm zur Widerstandsberechnung\n";
cout << "\nSpannung U [in V] : "; cin >> U;
cout << "Stromstärke I [in A] : "; cin >> I;
cout << "\nGeschwindigkeit : " << U/I << " Ohm";
//
//
//
//
//
Variablen U und I definieren
Ausgabe Titel
Ausgabe und Eingabe U
Ausgabe und Eingabe I
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 Selektion (auch: Auswahl, Wahlstruktur, Alternative) ist eine Programmstruktur, die eine Verzweigung 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 (<llog. Ausdruck>) <A
Anweisung>;
konstruiert.
Die Anweisung wird nur ausgeführt wird, wenn der <llogische Ausdruck> den Wert true enthält.
Einfache Selektion in der Struktogramm - Darstellung
<LLA> ?
J
A
Mit der Zeichnung in Abb. 5 wird erklärt, dass wenn der logische
Ausdruck <LLA> = true ist, der Block A ausgeführt und anderenfalls nichts geschieht.
N

Abb. 5
18
Cassebaum, Skript zur Programmierung mit C++
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>) < Anweisung A im Fall <LA>=true >;
else < Anweisung B im Fall <LA>=false >;
Zweifache Selektion in der Struktogramm-Darstellung
<LA> ?
J
A
N
B
Abb. 6
Mit der Zeichnung in Abb. 6 wird erklärt, dass wenn der logische
Ausdruck <LA> = true ist, der Block A ausgeführt wird. Für den
Fall, dass der logische Ausdruck <LA> den Wert „false“ besitzt,
wird der Block B 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
Mehrfachanweisungen 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 Ausdrucks) erfolgen. Man benutzt den Fragezeichenoperator 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! Zeigen 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)
19
Cassebaum, Skript zur Programmierung mit C++
1.5.3 Mehrfachauswahl (Fallunterscheidung)
Eine Mehrfachauswahl (auch: Fallunterscheidung) ist eine Programmstruktur, die abhängig vom Wert
eines ganzzahligen Ausdrucks <GA> endlich viele Verzweigungen enthalten.
Fallunterscheidung in der Struktogramm-Darstellung:
<GA> ?
1
2
A
B
3
C
In Abb. 7 wird aufgezeigt, dass der abzuarbeitende Block x
abhängig vom Wert des ganzzahligen Ausdrucks <GA> ausgefü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 ausgeführt.
sonst
D
Abb. 7
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 Ausdruck 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 switchAnweisung abgearbeitet werden!
01
02
03
04
05
06
07
08
09
10
11
char s = 2;
switch(s)
{ case 0:
case 1:
case 'c'-'a':
case 3:
case 4:
case 'a':
default:
cout
cout
cout
cout
cout
cout
cout
cout
<<
<<
<<
<<
<<
<<
<<
<<
"\n0 kommt nicht";
"\n1 kommt nicht";
"\n2 kommt";
"\n3 kommt";
"\n3 kommt";
"\n4 kommt"; break;
"\n'a' kommt nicht";
"\n kommt nicht";
}
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: ö)
20
Cassebaum, Skript zur Programmierung mit C++
1.5.4 Kopfgesteuerte Schleifen
Eine Mehrfachausführung einer Anweisung (eines Anweisungsblockes) wird
Schleife ( auch: Zyklus, Wiederholstruktur, Iteration ) genannt.
Die Eigenschaft „k
kopfgesteuert“ steht dafür, dass die Arbeitsbedingung (ein logischer Ausdruck) schon
vor Ausführung des „Schleifenkörpers“ auf den Inhalt „true“ überprüft wird. Der Schleifenkörper 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 Schleifenkörper eine Anweisung „continue“ erreicht, wird die Bearbeitung der Anweisungen des Schleifenkörpers unterbrochen und die Schleife mit der erneuten Überprüfung der Arbeitsbedingung fortgesetzt.
1.5.4.1
WHILE
Kopfgesteuerte Schleife in der Struktogramm-Darstellung:
while (<LA>)
Schleifenkörper
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.
Die while-Anweisung konstruiert mit einem Parameter eine kopfgesteuerte Schleife (a
abweisende Schleife).
Abb. 8
while ( <log. Ausdruck> ) Anweisung ;
while ( <log. Ausdruck> ) { A; B; C; }
(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 werden. 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>
02 int z=0;
03 while(!kbhit())
04 cout << z++ << " ";
//
//
//
//
conio-Header für kbhit-Funktion
Zählvariable
kbhit() ist true, wenn eine Taste gedrückt wurde
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 asynchron genannt, wenn die Gesamtzahl der
Schleifendurchläufe für das ausführende System nicht vorhersehbar ist. Sie heißt synchron, wenn die
Schleifendurchlaufzahl berechenbar ist.
Beispiele für eine synchrone Schleifen:
int
int
int
int
i=5;
i=5;
i=5;
i=5;
while(i--) cout << i;
//
while(i>2) cout << i--;
//
while(i) {cout << i; i-=2; } //
while(i) cout << " ";
//
gibt aus: 43210
gibt aus: 543
gibt aus: 531...
Ausgabe unsichtbar
(5
(3
(∞
(∞
Schleifendurchläufe)
Schleifendurchläufe)
Schleifendurchläufe)
Schleifendurchläufe)
21
Cassebaum, Skript zur Programmierung mit C++
Eine oft benötigte Anwendung einer Schleife mit synchroner Arbeitsbedingung ist die Zählschleife, 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 kopfgesteuerte (a
abweisende) Schleife.
Kopfgesteuerte Schleifen in Struktogrammen:
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 (<A1>;<LA>;<A2>)
Schleifenkörper <A3>
Abb. 9
for (<Anweisung 1>;<log.Ausdruck>;<Anweisung 2>) Anweisung 3;
<A1>
<A1>
while <LA>
<LA>?
<A3>
<A2>
<A3>
Abb. 10
<A2>
(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 Anweisung 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;
while(i<4)
{ cout << i;
i++; }
//
//
//
//
<A1>
<LA>?
<A3>
<A2>
int i;
for(i=0;i<4;i++)
cout << i;
// <A1>,<LA>,<A2>
// <A3>
Es handelt sich bei diesen Beispielen um je eine Zählschleife, die eine Laufvariable i zur Zählung der
Schleifendurchläufe vom Startwert 0 bis zum nicht erreichten Endwert 4 mit der Schrittweite 1 verwenden. 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 Kommaoperator 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 verschachtelten Schleifen. Im folgenden Beispiel wird eine Multiplikationstabelle mit zwei Zählschleifen zur Anzeige des „kleinen Einmaleins“ auf
dem Bildschirm dargestellt:
01 for(int i=1;i<10;i++)
02 { for(int j=1;j<10;j++)
03
cout << i*j << “\t“;
04
cout << endl;
05 }
// äußere for-Schleife
// innere for-Schleife
// Schleifenkörper der inneren Schleife
// Teil des Schleifenkörpers der äußeren Schleife
// 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.
22
Cassebaum, Skript zur Programmierung mit C++
1.5.5 Fußgesteuerte Schleife
Die do-while-Anweisung konstruiert eine fußgesteuerte Schleife (n
nicht abweisende Schleife).
Schleifenkörper
do
while (<LA>);
Abb. 11
(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).
do Anweisung; while ( <log. Ausdruck> );
01 int x;
02 do { cout << "x: "; cin >> x;
03
} while(x<=0);
04 do { if(!(x%2)) cout << x << " ";
05
} while (--x>0);
// Ausgabe aller geraden Zahlen,
// beginnend mit einer eingege// benen Zahl x (rückwärts bis 2)
Der Anweisungsblock {…} des Schleifenkörpers kann durch eine continue-Anweisung vorzeitig unterbrochen 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 Anwendung der do-while-Schleife sollte in Fällen angewendet werden, wenn der erste Schleifendurchlauf 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.
01
02
03
04
05
06
07
08
09
10
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{ for( int i=1; i<=10; i++, cout<<endl )
for( int j=1; j<=10; j++ )
cout << setw(4) << i*j;
getchar();
return 0;
}
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 10
18 20
27 30
36 40
45 50
54 60
63 70
72 80
81 90
90 100
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
 m
m!
Bestimmen Sie den Wert des Binomialkoeffizienten   
.
 n  n!(m  n)!
01
02
03
04
05
06
07
07
08
09
10
11
#include <iostream>
using namespace std;
Binomial(7,3) = 21
int main()
{ float m=7, n=2, b=1;
cout << "Binomial(" << m << "," << n << ") = ";
if( m >= n )
while(n)
// n!=0 ist true, n==0 ist false
b *= m-- / n--; // erst nach Multiplikation und Division folgen die Dekremente -cout << b;
getchar();
return 0;
}
Cassebaum, Skript zur Programmierung mit C++
Übungsaufgaben
34. Geben Sie über Bildschirm 30 mal das Wort „Software“ aus! Lösen Sie das Problem mit den Schleifenkonstruktionstypen a) for, b) while, c) do while!
35. Geben Sie Zahlenwerte nacheinander über Tastatur ein, bestimmen Sie das Maximum, das Minimum 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! Mathematisch: [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)
b)
c)
d)
e)
f)
g)
h)
Definition zweier reeller Variablen doppelter Genauigkeit;
Selektion nach dem Inhalt der ganzzahligen Variablen x für mehr als zwei Fälle;
Verminderung des Inhaltes der ganzzahligen Variablen x um 1;
Tastatureingabe einer reellen Zahl zur Speicherung in der Variablen a;
Erhöhung der ganzzahligen Variablen x um 5, wenn die logische Variable y den Wert true besitzt;
6000-malige Bildschirmausgabe des Wortes „Test“;
Die int-Variable x erhält Wert 1, wenn die float-Variable v<π ist. Sonst wird x=0 gesetzt;
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örpergröß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 geraden 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 diese 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.
23
24
Cassebaum, Skript zur Programmierung mit C++
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 laufenden Folgeschritte und einer gleichzeitigen eventuellen Nachbesserung aufgebaut werden.
Ist-Analyse
Soll-Analyse
Entwurf
Implementierung
Test
Abb. 12
Dokumentation, Archivierung
Die Ist-Analyse beschreibt den Zustand des Prozesses vor dem Einsatz der neu zu entwickelnden Software. Sie stellt die Voraussetzung für die Schaffung der Soll-Analyse, die eine Aufgabenstellung zur
neuen Software mit einem zugehörigen Pflichtenheft dar.
Die drei in der Zeichnung rot gekennzeichneten Tätigkeiten stellen die Hauptprozesse der Entwicklung
dar. Sie werden Entwurf, Implementierung und Test genannt.
Im Entwurf wird die Aufgabenstellung in relevante Teile zerlegt. Es gibt eine Reihe von Methoden, die
unter dem Oberbegriff „S
Systemanalyse“ zusammengefasst werden. Besonders interessant ist die Zerlegung der künftigen Software in die drei Grundstrukturen Sequenz, Selektion und Iteration, die bereits im vorhergehenden ↑Kapitel 1.5 behandelt wurden. Dabei wird eine zeichnerische, sprachunabhängige Programmdarstellung als Struktogramme (↑nachfolgendes Kapitel1.6.2) geschaffen.
Die Implementierung übernimmt den Entwurf und setzt ihn zu einer ungetesteten Programmlösung
zusammen. Dazu werden die in dem ↑Kapitel1.1.2 erläuterten Teilschritte der Programmentwicklung
benötigt. Gemeint sind die Codierung in einer Programmiersprache, die Übersetzung, das Linken und
der Start des Tasks.
Der Test dient der Prüfung und Nachbesserung des Ergebnisses der Implementierung. Es wird dabei
getestet, ob das geschaffene Programmergebnis der vorgegebenen Ziel- und Aufgabenstellung entspricht, die im Pflichtenheft dokumentiert wurde. Dazu werden Testdaten genutzt, die möglichst sicher alle auftretetenden Praxissituationen nachbilden.
Die Dokumentation fasst die Schritte der Entwicklung mit allen Teilschritten schriftlich zusammen und
wird gemeinsam mit den Programmdateien und Testdaten abschließend archiviert.
Übungsaufgaben
46. Erklären Sie die Begriffe Testdaten, Codierung, Sequenz, Implementierung, Iteration, Test, Projekt, Grundstruktur, Selektion, Struktogramm, Soll-Analyse, Pflichtenheft und Hybridprogramm!
47. Nennen Sie die Schnittstellen zwischen den einzelnen Tätigkeiten der Softwareentwicklung. Nennen Sie für jede Tätigkeit geeignete Software, die den Entwicklungsprozess verbessern könnte.
25
Cassebaum, Skript zur Programmierung mit C++
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 Iteration zu beschränken. Gleichzeitig wird das Programm in Strukturblöcke zerlegt, die alle nur einen Einund einen Ausgang besitzen („B
Blockkkonzept“).
Die Struktogrammtechnologie hat sich durch diese beschriebenen Vorteile zur bekanntesten Entwurfstechnologie in der Programmierung entwickelt und dabei die heute veralteten Methode des Programmablaufplans („PAP“) abgelöst. Die wichtigsten zeichnerischen Blockarten werden hier gezeigt:
Sequenz, Folge
A
Selektion,
Alternative
J
B
A;
B;
B wird nach A
verarbeitet.
b?
A
Fallunterscheidung
N
B
if(b) A;
else B;
Wenn b==true,
dann arbeitet A,
sonst B.
1 2 3
x
A B C D E
Kofgesteuerte
Schleife
Fußgesteuerte
Schleife
while b
A
do while b
A
switch(x){
case 1:A;… }
while(b)
{ A; }
do{ A;
} while(b);
Wenn x=1,dann
arbeitet A,wenn
x=2, dann B, …
Wiederhole A,
solange
b==true.
Starte A und
wiederh. A, solange b==true.
Break,
Abbruch
BREAK
{ break;
}
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 volles 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 positive Zahl das Zeichen ‚+‘, für eine negative ‚-‘ und für Null ‚0‘ aus. Zeichnen Sie das Struktogramm und
erstellen Sie ein C++ Programm.
Vorzeichen, 04.09.2011
01
02
03
04
05
06
07
08
09
10
#include <iostream>
using namespace std;
int main()
{ float x;
cout << "Zahl: "; cin >> x;
if(x>0) cout << "+";
else { if(x<0) cout << "-";
else cout << "0";
}
getchar();
return 0; }
Th. Cassebaum
O:Scr "Reelle Zahl: "
I:Kbd x
J
x>0 ?
O:Scr "+" J
x<0 ?
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.
01
02
03
04
05
06
07
08
09
10
#include <iostream>
using namespace std;
int main()
{ int n; double f=1;
do { cout << "Nat.Zahl: "; cin >> n;
} while(n<0);
while(n) f*=n--;
cout << f;
getchar();
return 0; }
N
N
O:Scr "-" O:Scr "0"
Fakultät, 22.7.2011
Th. Cassebaum
f := 1
O:Scr "Nat.Zahl:"
I:Kbd n
do while ( n<0 )
while ( n )
f := f * n
n := n - 1
O:Scr f
26
Cassebaum, Skript zur Programmierung mit C++
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 volles 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örpergröß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 Trockentests („Schreibtischtests“) wird genutzt, um kleine Programmabschnitte ohne Computer testen zu können. Die dabei verwendeten Daten werden „T
Testdaten“ 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
02
03
04
05
unsigned x, f=1;
cout << "x = ";
cin >> x;
while(x) f *= x--;
cout << "x! = " << f;
2) Zeile
01
03
04
04
05
x
f
1
1) Zeile
01
2
03
1 2
04
0
05
out→ x! = 2
x
f
1
0) Zeile x
f
01
1
1
03
0
0 1
05
out→ x! =1
out→ x! = 1
Bei der Auswahl der Testdaten sollte auf Eckdaten des Algorithmus zurück gegriffen werden, die Sonderfä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 Trockentests 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;
27
Cassebaum, Skript zur Programmierung mit C++
c) int main()
{ int x=3, a=4;
do { a-=2;
x+=a;
} while(a);
e) int main()
{ double x=2.2; i=3;
while(i)
{ x+=2; i--; }
g) int main()
{ int x=0, a[]={3,2,1,4}, i=3;
while(i) x+=a[i--];
i) bool fkt(int a){ return !a; }
int main()
{ int x=2;
if(fkt(x)) x++;
else x--; x+=x;
d) int main()
{ int i,x= 'd'-'b';
for(i=0; i<2; i++)
{ x--; }
if(x) x++;
f) int main()
{ int x=6, i=-3;
while(i)
{ x-=2; i+=2;}
h) int main()
{ int a[3], i=0, x;
for( ; i<3; i++) a[i]=i;
x= a[0]+a[1]*(a[2]-1);
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)
x=2
a=0
while (x > 0)
a=a+3
x=x-1
x=a+1
b)
x=2
a=2
while (a > 0)
x=x*2
a=a-1
x=a/2
x=6
a=0
x%2
N
a=a+x
x=x-1
c)
J
do
while ( x )
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;
a= x+2;
x += a;
b) int a=0, x;
x=a-3;
x-=3; x++;
c) int a=3, x=4;
a=a*a*a/x++;
x++;
52. a) double x,a=0.6; b) bool x=!true;
x= 2+a--;
if(!x)x=!(x||x);
x= a*a/a-1;
else x-=1;
d) (x
int
while
> 0)a, x=4;
a= (++x)+4;
x= a%2;
c) int x=0,i=3;
switch(i)
{ 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;
b)int i=0,x=-2;
c)int x=0;
d)int x=0,i=0;
54.a) int x=2;
do
for(;!x;x-=2)
for(;i<=3;i++,x--)
while(x<17)
{ x+=i; i+=x;
x+=3;
x *= i;
x *= 3;
} while(i>=-8);
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;
clrscr();
for(;a;a--)
cout << "++";
b) int i=1, a=1;
c)
clrscr();
while(i<5)
{ cout << a++; i++;}
int x=1; bool b;
clrscr();
b=(x!=1);
for(; !b; b=!b){cout << "###"}
28
Cassebaum, Skript zur Programmierung mit C++
2 Elementare Einführung in C/C++
2.1 Funktionen
Die wesentlichsten ausführbaren Programmteile in C++ sind (g
gerufene, gestartete) Funktionen, die
wiederum von anderen (rrufenden) Funktionen gestartet werden. Eine Funktion kann mit „P
Parametern“ Steuerinformation von der rufenden („übergeordneten“) Funktion übernehmen und mit einem
„R
Rückgabewert“ 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 Funktionskörper enthält die C/C++Anweisungsfolge, die die Arbeitsweise nach dem Funktionsaufruf erklären.
Eine Funktion des Datentyps void wird „A
Auftragsfunktion“ genannt. Eine solche Funktion führt Tätigkeiten aus, besitzt aber kein Ergebnis in Form eines Wertes. Jeder andere Datentyp macht eine returnAnweisung in der Definition erforderlich, weil mit (return x; ) das datentypgerechte Wertergebnis an
die rufende Funktion übergeben wird. Funktionen mit Wertrückgabe werden „A
Anfragefunktion“ genannt.
void aus(int x) // Auftrag
{ cout << x;
}
int main()
{ aus(8);
// Aufruf
...
}
int doppel(int x)
{ return t+t;
}
int main()
{ cout << doppel(5);
...
}
// Anfrage
// 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 Prototyp 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
02
03
04
05
06
07
08
09
10
11
12
void aus(int, int); // Prototypen
int mult(int, int);
int main()
{ aus(3,4);
// Funktionsaufruf
getchar();
return 0;
}
void aus(int a, int b)
{ cout <<a <<“*“ <<b <<“=“ <<mult(a,b);
}
int mult(int x, int y)
{ 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 bekannt ist.
Durch den Prototyp in Zeile 02 ist die
nebenstehende Variante fehlerfrei
compilierbar.
29
Cassebaum, Skript zur Programmierung mit C++
2.1.3 Funktionsparameter
Parameter sind die Angaben in der nach dem Funktionsnamen folgenden Klammer. Sie besitzen einen
Datentyp und werden anhand ihrer Position Parameterreihenfolge unterschieden.
Die „fformalen“ Parameter in der Funktionsdefinition werden immer mit einem Datentyp und einem
Namen definiert. Der Funktionskörper enthält die beim Funktionsaufruf auszuführenden Anweisungen, die die Parameter nutzen dürfen. Ist die Funktion nicht vom Datentyp void (steht für den "leer"),
so gibt die Funktion mit der return-Anweisung einen datentypgerechten Funktionswert an die rufende Funktion zurück. Kennt eine Funktion den Namen einer anderen Funktion, so kann sie diese mit
einem Funktionsaufruf starten.
Im Funktionsaufruf werden die formalen Parameter durch „a
aktuelle“ Parameter ersetzt. Die aktuelle
Parameterliste des Funktionsaufrufs muß hinsichtlich der Parameteranzahl, -Reihenfolge und Datentypen vollständig mit der formalen Parameterliste harmonieren.
<Funktionsname>([aktueller Parameter_1[,aktueller Parameter_2[,...]]]);
string Multistring(string s, int r);
void main(void)
{ cout << Multistring("Tick",5);
getchar();
}
string Multistring(string s, int r)
{ while(r--) s+=s;
return s;
// Rückgabewert
}
// Prototypzeile
// Funktionsaufruf
Gibt aus:
TickTickTick…
Wie viele Tick’s
werden sichtbar?
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 main-F
Funktion, die Hauptfunktion
des Programmes.
Wie jede andere Funktion kann sie Parameter von der startenden Funktion empfangen und einen Ergebniswert zurückgeben. Da die main-Funktion vom Betriebssystem gestartet wird, empfängt sie
Kommandozeilen-Parameter von der Startzeile und gibt üblicherweise einen ganzzahligen Ergebniscode an das Betriebssystem zurück (z.B. 0 für erfolgreiche und 1 für erfolglose Abarbeitung).
int main( int argc, char* argv[] ) // Argumentanzahl/ Argumente
{ ..
// Programmzeilen
getchar();
// Warten auf Tasteneingabe vor Programmende
return 0; // Rückgabe des Erfolgscodes 0 und Funktion beenden
}
Angenommen, das gezeigte Programm 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) .
30
Cassebaum, Skript zur Programmierung mit C++
2.1.5 Datenkapseln
Als Datenkapsel wird ein C++-Konstrukt bezeichnet, das eigene „lokale“ Größen (z.B. Variablen) definiert. 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 „g
globale“ 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;
Gibt aus:
}
int main()
12 5
{ int x=12;
// lokale Variable x in main()
2 2 6
cout << x << “ “ << ::x << endl;
2 3 7
aend(); aend();
// zweimaliger Aufruf
12 7
cout << x << “ “ << ::x; getchar();
}
Abb. 11
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 gerufene Funktion zu übergeben. Es werden bei der Parameterübergabe zwei grundsätzliche Formen unterschieden. Zum einen können die Parameter als „W
Wert“ (ccall by value), aber andererseits auch als „R
Referenz“ (ccall by reference) übergeben werden.
Bei Übernahme von Wertparametern wird in der gerufenen Funktion neuer Speicherplatz zur Aufnahme der übernommenen Parameterwerte bereitgestellt. Eine Änderung dieses funktionsinternen Speicherplatzes führt bei einer Änderung des Parameterinhaltes nicht gleichzeitig zur Änderung der Position im rufenden Programm.
Ein Referenzparameter ist an einem vorangestellten & erkennbar.
void aend(int x)
Gibt aus:
{ cout << ++x;}
1
int main()
{ int x=1;
22
cout << x << endl;
1
aend(x); aend(x);
cout << endl << x; getchar();
}
void aend(int &x)
Gibt aus:
{ cout << ++x;}
1
int main()
23
{ int x=1;
cout << x << endl;
3
aend(x); aend(x);
cout << endl << x; getchar();
}
31
Cassebaum, Skript zur Programmierung mit C++
Der Parameter im rechten Beispiel wird als Referenz übergeben. Die Veränderung des Parameters ist
vom rufenden Programm erkennbar. Ein Rückgabewert braucht nicht zwingend übergeben werden,
wenn der Referenzparameter zur Ergebnisübergabe genutzt wird.
Referenzen verweisen auf Objekte, können jedoch nur einmal mit einem Objekt initialisiert werden
und danach nicht mehr auf andere Objekte umgelenkt werden. Weiter entfällt für Referenzen die Nutzung der typischen Zeigersyntax, sie werden wie die Variable selbst behandelt, die sie referenzieren.
Wegen dieser einfachen Arbeitsweise werden Referenzen auch 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.;
Gibt aus:
x=quad_v(x);
// call by value
cout << "\n(1) 12*12= " << x;
(1) 12*12= 144
x=12.; quad_r(x);
// call by reference
(2) 12*12= 144
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 rekursiv genannt. 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();
}
Gibt aus:
TickTickTick…
Wie viele Tick’s
werden sichtbar?
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 Einfachheit. Es gibt insbesondere bei den sogenannten "divide and conqeur"-Verfahren Sortier-, Such- und
Ordnungsalgorithmen, die äußerst effektiv (gemeint ist die Schnelligkeit) gerade wegen der rekursiven
Lösung sind.
32
Cassebaum, Skript zur Programmierung mit C++
2.1.8 Funktionsüberladung
Wichtige äußere Eigenschaften einer Funktion sind die Anzahl, Reihenfolge und die einzelnen Datentypen der Parameter. Aus praktischen Gründen stellt man sich die Frage, ob es nicht vernünftig ist, unterschiedliche Parameterlisten für den gleichen Funktionsnamen zuzulassen.
In C++ ist dies mit Hilfe des Overloading möglich. Der Begriff Overloading oder Überladung bezeichnet
die Fähigkeit von C++, anhand der Parameterliste einen von mehreren existierenden Funktionsdefinitionen 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 doubleParameter 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;
}
33
Cassebaum, Skript zur Programmierung mit C++
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 Arrays 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:
2
1
5
3
4
1
Abb. 12
Die einzelnen Arrayelemente sind im Speicher auch
bei mehrdimensionalen Arrays physisch zusammenhängend (in lückenloser Folge) gespeichert. Die Vorstellung des Arrays als Tabelle oder Matrix ist zur theoretischen Vorstellung der Werte recht praktikabel.
Summation der Elemente einer 3,4 Matrix:
int i,k; double m[3][4], s=0;
for(i=0;i<3;i++)
for(k=0;k<4;k++)
s += m[i][k];
cout << "Summe: " << s;
2
5
9
4
2
3
Abb. 13
0
1
2
1
5
9
0
4
2
3
1
a[0][1]=5;
a[1][0]=4;
a[1][2]=3;
Füllung eines Lotto-Arrays mit Zufallswerten
int i,k,a[10][6];
randomize();
for(i=0;i<10;i++)
for(k=0;k<6;k++)
a[i][k]=random(49)+1;
3
S =  mi ,k
i 0 k 0
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
34
Cassebaum, Skript zur Programmierung mit C++
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";
0
1
2
3
4
5
6
7
’T’ ’u’ ’r’ ’m’ 0
0 1 2 3 4
?
?
?
’T’ ’u’ ’r’ ’m’ 0
Die Definition char s[]= "Turm"; (oder mit *s) vereinbart einen String der Länge 4 inklusive Nullterminator 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 strxxxFunktionen, die im Header string.h definiert sind.
strcat(e,q)
strcmp(e,q)
strcpy(e,q)
strlen(e)
strlwr(e)
strstr(e,q)
strupr(e)
string(e)
An den String e (vor dem 1.Komma) wird der String q angehängt.
Der String e wird mit dem String q verglichen. Es werden Ergebniswerte zurückgegeben: <0 für s<q , =0 für s=q, >0 für s>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.
Liefert die Länge des Strings e (in Klammern) als int-Wert zurück.
Im String e werden alle Groß- in Kleinbuchstaben verwandelt.
Liefert einen Zeiger auf die Position des ersten Vorkommens des Strings q im
String e. ( Zeiger werden in einem späteren Kapitel erklärt)
Im String e werden alle Klein- in Großbuchstaben verwandelt.
Liefert einen C++-String gleichen Inhalts wie e zurück.
Die Ein-/Ausgaben über cin/cout können vereinfacht durch Weglassen der Indexangabe realisiert werden. 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
35
Cassebaum, Skript zur Programmierung mit C++
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 Speicherplatzbedarf 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 Operatoren wie "=" und "+=" zur Zuweisung und "+" zur Verkettung zweier Strings verwendet werden.
string
int
string
char*
string
int
s.substr(p,l)
s.compare(s2)
s.append(s2)
s.c_str()
s.insert(i,s2)
s.length()
liefert einen Teilstring von s, der in Länge l ab Position p beginnt
vergleicht s mit s2, für s<s2: <0, s==s2: ==0, s>s2: >0
hängt String s2 an s an
gibt nullterminierten C-String gleichen Inhalts wie s zurück
fügt ab i-Position s2 in s ein.
liefert die aktuelle Länge von s
Auf die Einzelzeichen eines C++-Strings kann wie auf die Elemente eines char-Arrays zugegriffen werden. Wichtig ist allerdings, dass der Index nur kleiner als die Längenkapazität des Strings gewählt werden 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! Beachten 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 Ergebnisse 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 bereits 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.
36
Cassebaum, Skript zur Programmierung mit C++
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 Speicherposition) einer gespeicherten Größe darstellt. Eine Adresse wird meist hexadezimal aufgeschrieben ( z.B.
in C++, 32 Bit: 0x0012FF84 )
Speicher
Adresse
00000000
Adresse („Speicherende“)
FFFFFFFF
00 00 00 00 00 00 00 00
z.B.Adresse z.B.Adresse
0012FF88
0012FF84
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;
}
Gibt aus:
1 1
1 2
1 3
Abb.15
2.3.2 Zeiger (Pointer)
Zeiger (Pointer) sind Größen, die Adressen von Variablen, Arrays,... unter einem eigenen Namen speichern. 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
ptr
Adresse
00000000
a
00 12 FF 88 00 00 00 03
z.B.Adresse z.B.Adresse
0012FF84
0012FF88
Adresse
(Speicherende)
FFFFFFFF
„Der Zeiger (Pointer) ptr
zeigt auf die Variable a“
Ein Zeiger speziell für einen bestimmten Datentyp gebildet, weil die Bytelängen der Typobjekte unterschiedlich sind. Ein mit „double *b;“ definierter Zeiger b zeigt auf einen double-typspezifischen Datenbereich mit 8 Byte Länge. Ein mit „int *a;“definierter Zeiger a zeigt auf einen int-typspezifischen
Datenbereich mit 4 Byte Länge.
37
Cassebaum, Skript zur Programmierung mit C++
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.
a
p
00 12 FF 88 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 00
p
Abb. 17
a[0] (p[0])
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ändert.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
double *pd, d[11];
int *pi, i[11];
pd = d;
pi = i;
*pd = 21.34;
*pi = 5;
cout <<pd <<" " <<pi <<endl;
pd++;
pi+=3;
*pd = 33.99;
*pi = 6;
cout
<<pd <<" " <<pi <<endl
<<d[0] <<" " <<d[1] <<endl
<<i[0] <<" " <<i[3];
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 ganzen Zufallswerten zwischen -100 und +100
initialisiert.
Im Beispiel wird in Zeile 08 der Zeiger
„pd“ mit pd++; passend zum doubleArray 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 Elementlängen (d.h. 3 * 4 = 12 Byte) passend
zum Datentyp int erhöht.
01
02
03
04
05
05
06
07
08
double *pd,d[11];
int *pi,i[11];
pd = d; pi = i;
randomize();
do
{ *pd = random(10000)/100.;
*pi = random(201)-100;
pd++; pi++;
} while(pd <= &d[10]);
38
Cassebaum, Skript zur Programmierung mit C++
Ü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 anzeigen! 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 kommentierten 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 beliebigen reellen Zahlen! Lassen Sie sich die Adressen und die Inhalte aller Elemente auf dem Bildschirm 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;
p
a
Diese Anweisungsfolge bewirkt, dass
00 12 FF 88 ‘Z ‘e ‘i‘ ‘g ‘e ‘r‘ 00
an einer Position im
‘ ‘
‘ ‘
Abb. 18
Speicher, deren Adp
a[0] (p[0])
resse in p gespeichert
wurde, für sechs Zeichen mit dem Inhalt „Zeiger“ und einen Nullterminator Speicherplatz bereitgestellt wurde. Der Zeiger p kann wie ein als char-Array definierter nullterminierter String verwendet
werden.
39
Cassebaum, Skript zur Programmierung mit C++
2.3.4 Mehrfachzeiger
Ein Mehrfachzeiger ist ein Zeiger, dessen Inhalt auf einen Zeiger niederer Ordnung zeigt. In der Zeigerdefinition erklärt die Anzahl der Sternchen * die Ordnung des Zeigers.
Der Zeiger p zeigt über den Zeiger p1 auf das Objekt a.
p
p1
p2
b
a
00 12 FF 84 00 12 FF 88 00 12 FF 80 00 00 00 03 00 00 00 03 00 00 00 03
Adresse
0012FF7C
Adresse
0012FF80
Adresse
0012FF84
Adresse
0012FF88
Adresse
0012FF8C
Abb. 19
#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;
}
**pp
Abb. 20
*p[0]
*p[1]
*p[2]
a
b
c
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…
Cassebaum, Skript zur Programmierung mit C++
Ü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 Buchstaben! 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 Zeigerarithmetik alle Arrayelemente aus Aufgabe 66 um! Lassen Sie sich das Ergebnis auf dem Bildschirm 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
40
41
Cassebaum, Skript zur Programmierung mit C++
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 vereinbarten Speicherplatzes erst während der Laufzeit zu verändern. Dazu ist es erforderlich, Speicherplatz
direkt vom Betriebssystem abzufordern. Das Betriebssystem gibt die Startadresse des zugeordneten
Speicherplatzes im Erfolgsfall zurück. Ein solcher Bereich wird Heap oder dynamisches Array genannt.
Anforderung
des dynam.
Speichers
<typ> *p;
p = new <typ>[n];
Nutzung des Heaps
Betriebssystem
Rückgabe
Der Adresse
im Zeiger p
Speicher
„Heap“…
Adresse des Heaps
delete p;
Programmsequenz…
Freigabe des
nicht mehr benötigten Heaps.
Abb. 21
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;
randomize();
ip = new int[10];
if(!ip)
{ cout <<"\nSpeicherfehler!";
return 1;
}
for(i=0 ; i<10 ; i++)
{ ip[i]= random(10)+1;
cout << "\nElement " << i
<< " = " << ip[i];
}
delete ip;
// Pointervereinbarung
// Speicheranforderung für den Heap
// Erfolgreich?
// Freigabe des Heaps
Der angeforderte Speicherplatz kann mit delete <pointer>; wieder freigegeben werden. Dadurch wird erreicht, daß der zuvor angeforderte Speicherbereich wieder für andere Zwecke zur Verfügung steht.
42
Cassebaum, Skript zur Programmierung mit C++
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ülernamen von beliebig vielen
Schulklassen gespeichert
werden. Vor der Eingabe
der Namen einer weiteren Schulklasse wird
Heap für 32 Namen angefordert.
Maximal
Klassen
werden
dürfen 100
gespeichert
Ü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 Zahlen 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 “ beginnen!
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 freigegeben.
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 maximal 50 Schülern pro Klasse zu speichern und danach auszugeben. Es soll möglichst wenig Speicher (als nullterminierte Strings) passend zur aktuellen Datenmenge im Heap angefordert werden.
43
Cassebaum, Skript zur Programmierung mit C++
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 bewerten sind. Hier werden zwei Arten mit sehr verschiedener Qualität dargestellt:
Quicksort (divide and conquer)
#define gr 20
unsigned int gr, T[gr];
void main(void)
{ quicksort(0,gr-1);
}
void quicksort(int l,int r)
{ int wert,t,i=l,j=r;
wert=T[(l+r)/2];
do
{ while(T[i]<wert) i++;
while(wert<T[j]) j--;
if(i<=j)
{ t=T[i]; T[i++]=T[j]; T[j--]=t;
}
} while(i<=j);
if(l<j) quicksort(l,j);
if(i<r) quicksort(i,r);
}
Insertion Sort
#define gr 20
unsigned int mi,i,j,gr,T[gr];
void main(void)
{ for( i=2;i<=gr;i++);
{ mi=T[i];
j=i;
while((T[j-1]>mi)&&(j>1))
{ T[j]=T[j-1];
j=j-1;
}
}
T[j]=mi;
}
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 tauschende ganzzahlige Größen könnte das so aussehen: (int &a, int &b).
void swap1(...)
{ a^=b;
b^=a;
a^=b;
}
1
a
h
3
2
b
void swap2(...)
void swap3(...)
{ register short h;
{ b=b+a;
h=a; // 1
a=b-a;
a=b; // 2
b=b-a;
b=h; // 3
}
}
Der Datentypzusatz „register“ kann den
Zugriff auf Variablen beschleunigen, weil der CompiAbb. 22
ler versucht, die definierte Größe direkt in einem Prozessorregister zu speichern.
44
Cassebaum, Skript zur Programmierung mit C++
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äherungsrechnung mit dem nebestehenden mathematischen Ansatz für die
Sinusfunktion realisiert.
neu  alt 
(1)
(
i 1
)
2
 i
i!
Es wird zyklisch aus einer Näherungslösung «alt» die neue, bessere Näherungslösung «neu» errechnet, 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 stammenden Algorithmus um, mit dem man alle
Primzahlen, die kleiner als eine vorgegebene natürliche Zahl N sind, bestimmen kann.
Im Beispiel kann die Zahl N in der Präprozessoranweisung #define N 1000 auch
auf einen beliebigen anderen Maximalwert
gesetzt werden.
45
Cassebaum, Skript zur Programmierung mit C++
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 Namen 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 objektorientierten 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;
Brotsorte *p;
// Instanz „bs“ bilden
// 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 Speicherdeklarationen organisiert Speicherplatz, der alle Strukturattribute aufnehmen kann. Strukturen können
auch für dynamischen Speicher instanziiert werden. Dazu werden Zeigern des Strukturtyps Speicheradressen mit der new-Anweisung zugewiesen.
Die Herstellung einer Strukturinstanz wird Instanzierung genannt.
Strukturdefinition
(„Rezept“)
struct person
{ string name;
int alter;
};
01
02
03
04
05
Abb. 23
Instanziierungen
person ich,du,es;
Strukturinstanzen
(„belegen Speicher“)
person ich;
ich.name = ”Emil Krause”;
ich.alter= 26;
b[0].Bez = "Roggenbrot";
b[0].stk = 100;
p = new Brotsorte;
// dynamische Strukturinstanz
p->Bez = "Weizenbrot"; // Attributzugriff mit Zeiger
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 „Roggenbrot“ vorrätig.
46
Cassebaum, Skript zur Programmierung mit C++
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 Speicheradresse beginnen.
struct WORDREGS {unsigned short ax;};
struct BYTEREGS {unsigned char al,ah;};
union REGS
{ struct WORDREGS x;
// Wortregister (16 Bit)
struct BYTEREGS h;
// Byteregister ( 8 Bit)
} r;
// Union-Instanz r
r.x.ax = 0x0101;
// Zuweisung zum Register ax
cout << &r.x << " " << &r.h << endl;
cout << (int)r.x.ax << endl;
cout << (int)r.h.ah << " " << (int)r.h.al;
Startadresse
der union r
Abb. 24
WORDREGS x
BYTEREGS h
Gemeinsam von
x und h belegt.
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 Union 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 Dateneingabe 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 Zensuren oder Notenpunkten (00...15) für ein Unterrichtsfach. Weiter werden die Bezeichnung des Unterrichtsfaches und der(die) Name(n) der bis zu 5 unterrichtenden Lehrer(innen) in die Struktur aufgenommen. Bilden Sie eine Funktion Fach_ein() zur Eingabe der Fachbezeichnung, der Lehrernamen und der Noten (gesondert 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 Funktionen zur Änderung Change(SNr) und Löschung Delete(Snr) von Schülerdaten anhand der Schülernummer in
das Menü auf!
47
Cassebaum, Skript zur Programmierung mit C++
4.2 Klassen
Das Konzept der OOP beruht auf der Erfahrung, dass man reale Objekte nach zwei Maßen beurteilt:


Erklärung
Klasse
Einmal nach Eigenschaften wie Form und Farbe,
Zweitens nach dem Verhalten, das ein Objekt zeigt.
Attribute
In der OOP werden die Eigenschaften mit Daten (Attribute) und die
Verhaltensweisen mit Methoden erklärt. Objekte, die mit den gleichen Attributen und Methoden definiert werden können, werden in
einer Klasse zusammengefasst beschrieben.
Methoden
Objekt
Objekt
Objekt
Attributwerte
Attributwerte
Attributwerte
Methoden Tafel 6
Methoden
Methoden
Definition der Klasse
Instanziierung der Klasse
Objekt
Konstruktor
Vielfache Realisierung
(„Instanziierung“,
„Objektbildung“)
Nutzungsphase
Tafel 7
Destruktor
Objektfreigabe
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 Attributes ist bei den einzelnen Menschen unterschiedlich.
Erklärung (Klasse)
Mensch
Größe, Gewicht,...
denken, lesen, ...
Lisa Krause
Wir sagen:
Die Klasse „Mensch“ enthält die „Größe“ und das „Gewicht“ als Attribute. Er kann die Methoden „denken“ und „lesen“ funktional nutzen.
Nach der Erklärung der Klasse „Mensch“ wird das
Objekt „Lisa Krause“ gebildet („instanziiert“).
1,66m, 54 kg,...
Konkretes denken,
lesen, ...
Abb. 25
Realisierung (Objekt)
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.
48
Cassebaum, Skript zur Programmierung mit C++
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" zusammen. Es werden geschützte (private oder protected) und öffentliche (public) Attribute und Methoden unterschieden.
class bruch
{ public: bruch(int z, int n = 1);
bruch Mul(bruch x);
void Zeige(void);
private:int zaehl,nenn;
} a(3,4);
int main()
{ bruch *p;
p = new bruch(2,3);
a.Zeige();cout<<" * ";p->Zeige();
cout<<" = "; a.Mul(*p).Zeige();
getchar(); return 0;
}
// Konstruktor
// externen Methoden
// private Attribute
// Globalobjekt
//
//
//
//
Klassenzeiger
dynamisches Objekt
Ausgabezeile:
3/4 * 2/3 = 6/12
Eine Klasse besitzt in ihrer Handhabung sehr große Ähnlichkeit mit den Strukturen der structAnweisung. Sie belegt selbst keinen Speicherplatz, wird zur Bildung von Instanzen als datentypähnlicher 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 Objektbildung 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 Klassenattribute oder -methoden zugegriffen werden. z.B.: p->Zeige() greift auf die Methode Zeige() des Objektes, auf deren Adresse der Zeiger p zeigt.
Ein gemeinsamer Begriff als „Teil einer Klasse“ ist „member“ oder „Element“ einer Klasse. Nur Attribute 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ßerhalb der Klasse auf deren Elemente zugegriffen werden kann. Sie sind daher ein wichtiges Instrument
der Datenkapselung.
+ public
- private
# protected
Das Element kann von jeder eigenen/fremden Klassen erreicht werden.
Das Element kann nur von eigenen Methoden benutzt werden.
Es gilt zunächst das gleiche, wie für private.
Klassennname
Zusätzlich ist jedoch die Benutzung durch Methoden
Attribute
von Klassen möglich, die von der deklarierten Klasse
abgeleitet sind.
Methoden
Klassen können zeichnerisch als Klassendiagramm dargestellt werden. →
Abb. 25
49
Cassebaum, Skript zur Programmierung mit C++
4.2.4 Konstruktor und Destruktor
Der Konstruktor ist die Methode, die wie die Klasse selbst benannt ist und zum Zeitpunkt der Objektbildung 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 Objektfreigabe 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 Definition der Klasse „mutti“ besitzt:
class mutti{ embryo x; ...};
class embryo{...};
mutti
embryo
embryo x;
Ü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:
Abb. 26
vati
class vati{...};
class kind: public vati{...};
Aggregation (Einbettung) und Vererbung (Ableitung) sind ähnliche Verfahrensweisen mit dem Ziel, den Zugriff auf Elemente anderer Klassen zu vereinfachen. Um die richtige Wahl zwischen beiden Verfahren treffen zu können,
muß die konkrete Beziehung der Klassen zueinander untersucht werden.
kind
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.
50
Cassebaum, Skript zur Programmierung mit C++
// 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;
}
Abb. 27
Ü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 „Zylinder“, 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
51
Cassebaum, Skript zur Programmierung mit C++
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 Arbeit 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 Beispiel wird ein Ausgabestream OU vereinbart. Mit OU.open(char* File) wird dieser Stream eröffnet. Wenn die open-Methode keine 0 zurückgibt, war der Vorgang erfolgreich, ansonsten ist ein Fehler aufgetreten. Nach dem Öffnen können Zeichen entweder mit der put-Methode oder mit den
Bitstreamoperator << in passende Grössen ausgegeben werden. Mit der get-Methode oder mit den
Bitstreamoperator >> kann aus einem geöffneten ifstream eingegeben werden. Zum Abschluss müssen 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 Startelementes („Ringliste“).
Listenadresse
1.Objekt
next
2.Objekt
next
3.Objekt
Sonderform Ringliste:
Listenadresse
1.Objekt
next
NULL
next
Abb. 29
2.Objekt
next
3.Objekt
next
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.
Cassebaum, Skript zur Programmierung mit C++
// 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;
}
52
53
Cassebaum, Skript zur Programmierung mit C++
akt->inhalt = satz;
if(aktuell==ende)
ende = akt;
aktuell = akt;
return true;
// Inhalt übertragen
// ggf. Ende aktualisieren
// das aktuelle Element ist das neue
}
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änger, 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“).
NULL
1.
prev
next
2.
prev
next
3.
prev
NULL
next
Listenadresse
Abb. 30
Doppelringliste:
1.
prev
next
2.
prev
next
3.
prev
next
// programmiert von Thomas Cassebaum, all rights reserved
//Listenadresse
Typdefinitionen und Methoden zur Nutzung einer doppelt verketteten Liste
54
Cassebaum, Skript zur Programmierung mit C++
// *** objektorientierte Lösung *******************************************
class d_list
{ friend class d_liste_l;
public:
d_list(void): head(0), tail(0) { }
d_list
&insHead(d_liste_l *el);
d_list
&insTail(d_liste_l *el);
d_liste_l
*getHead(void);
d_liste_l
*getTail(void);
private:
d_liste_l
*head, *tail;
};
// Klasse der Listen
// Zugriff auf prev und next erlauben
class d_liste_l
{ friend class d_list;
public:
d_liste_l *operator++(void)
{ return akt=akt?akt->next:liste.head;}
d_liste_l *operator--(void)
{ return akt=akt?akt->prev:liste.tail;}
protected:
d_liste_l(void):prev(0),next(0),akt(0){}
virtual ~d_liste_l(void) { }
private:
d_list
liste;
d_liste_l *prev, *next, *akt;
};
// Klasse der Listenelemente
// Zugriff auf prev und next erlauben
d_list &d_list::insHead(d_liste_l *el)
{ if(head) head->prev = el;
else tail = el;
el->next=head; el->prev=0; head=el;
return *this;
};
// vorn einfügen
d_list &d_list::insTail(d_liste_l *el)
{ if(tail) tail->next = el;
else head = el;
el->prev=tail; el->next=0; tail=el;
return *this;
};
// hinten anfügen
d_liste_l *d_list::getHead(void)
{ d_liste_l *a=head; return a;
}
// gib erstes Element
d_liste_l *d_list::getTail(void)
{ d_liste_l *a=tail; return a;
}
// gib letztes Element
//
//
//
//
//
Konstruktor: Liste leer
vorn einfügen
hinten anfügen
gib erstes Element
gib letztes Element
// Anfangs-/Endelement
// next Operator ++
// prev Operator --
// Konstruktor: kein Vorgg./Nachf.
// Folge-/Vorgänger-/aktuelles Element
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
};
55
Cassebaum, Skript zur Programmierung mit C++
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 Datentypen! 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 zusammengehö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 (Quelltext-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 CStrings 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 verwendet 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!
14. Beschreiben Sie , wie das rechts dargestellte
Struktogramm arbeitet und erläutern Sie dessen
Zweck!
15. Setzen Sie das Struktogramm als C++ Hauptprogramm um und testen Sie dieses Programm!
double func(double w)
{ int z;
w = w * 100 + 0.5;
z = (int)w;
w = (double)z/100;
return w;
}
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 anderen 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-
56
Cassebaum, Skript zur Programmierung mit C++
fach und eine zweite als doppelt verkettete Liste! Neu zu erfassende Sendungen sind grundsätzlich dynamisch 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 passenden main() –Funktion und den folgenden Angaben! Erstellen Sie eine statischen Instanz "beschaeftigter"
dieser Klasse. Notieren Sie Quelltextzeilen zum Aufrufen der Dateneingabe- und der DatenausgabeMethode 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
Assembler ........................................................ 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
bitweise Operatoren ..................................... 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
Compiler ......................................................... 8
const ........................................................... 60
continue ..................................................... 60
57
Cassebaum, Skript zur Programmierung mit C++
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
Header ........................................................... 11
Heap .............................................................. 41
hex ................................................................ 62
HotKeys ......................................................... 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
Interpreters..................................................... 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
logische Operatoren ..................................... 14
Logische Werte ............................................. 15
main( ).......................................................... 11
main-Funktion............................................... 29
Maschinenbefehl ............................................ 6
Maschinenorientierte Programmiersprachen 7
Mathematik .................................................. 60
max................................................................ 60
Mehrfachauswahl ......................................... 19
Methoden ............................................... 48, 61
min................................................................ 60
Mnemonik....................................................... 7
new ......................................................... 41, 61
next-Zeiger .................................................... 51
nicht abweisende Schleife ............................ 22
nocreate ..................................................... 62
NULL .............................................................. 51
Nullterminierte (C-)Strings............................ 60
Numerische Ausdrücke ................................. 15
numerische Operatoren ............................... 14
Objektbildung ............................................... 61
Objekte ......................................................... 48
58
Cassebaum, Skript zur Programmierung mit C++
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
Programm ........................................................ 6
Programmbegriff ............................................. 6
Programmiersprachen ..................................... 6
Programmzustände ......................................... 6
protected ................................................. 48, 61
Prozessor ......................................................... 6
Prozessorbefehl ............................................... 6
public ....................................................... 48, 61
Punktoperator ............................................... 48
put ................................................................ 62
put-Methode ................................................. 51
Quicksort ....................................................... 43
rand .............................................................. 33
random .......................................................... 33
randomize ............................................. 33, 62
Rangfolge ................................................. 14, 59
Rangfolge aller Operatoren ........................... 14
reelle Zahlen .................................................. 59
Rekursionen ................................................... 31
replace........................................................ 61
resetiosflags .......................................... 62
return .................................................... 29, 61
Ringliste ......................................................... 51
Rückgabewertes ............................................ 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
Typbezeichner............................................... 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
Zuweisung ..................................................... 12
Zuweisungsoperatoren ................................. 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)*•/•%
(6)<<•>>(7)<•<=•>•>=(8)==•!=(10)^(11)|(12)&&(13)||(14)?:(15)=•+=•-=•*=•/=•%=•>>=•<<=•&=•^=
(5)+•-
Datentypen
int
unsigned int
short int
char
bool
float
double
long double
void
Länge
4 Byte
4 Byte
2 Byte
1 Byte
1 Byte
4 Byte
8 Byte
10 Byte
-
Textausgabe
clrscr();
clreol();
cout<<...;
cerr<<...;
cout.width(n);
_settextposition (<Wy>, <Wx>);
textcolor (<W>);
textbackground (<W>);
cout<<“\n“
cout<<endl;
cout<<“\t“
cout<<“\r“
cout<<“\b“
cout<<”\\...\’...\“...“
cout<<“\a“; oder cout<<“\007“;
(conio.h)
Gesamten Text im Bildschirm löschen
(conio.h)
Löscht Zeile ab Cursor bis zum Zeilenende
(iostream.h) „stream“ Standardausgabe (auf Bildschirm, umlenkbar)
(iostream.h) „stream“ Fehlerausgabe (auf Bildschirm, umlenkbar)
(iostream.h) Vorgabe der Ausgabebreite als Zeichenanzahl n
(conio.h)
Nächste Ausgabeposition festlegen, oben und links ist (1,1)
(conio.h, iostream.h) Legt Textfarbe W fest
(conio, iostream.h)
Legt Texthintergrundfarbe W fest
(iostream.h) Neue Zeile(CR - carriage return/LF - line feed)
(iostream.h) Neue Zeile(CR/LF), endl leert auch den Puffer.
(iostream.h) Tabulator, springt zu Position 9, 17, 25, 33, ...
(iostream.h) Wagenrücklauf, Cursor kommt an Anfang der Zeile
(iostream.h) Backspace, ein Zeichen wird gelöscht.
(iostream.h) Backslash \, Apostroph ’, Anführungsstriche “ ausgeben.
(iostream.h) Gibt einen Ton aus (kurzes Piepsen).
Texteingabe
cin>> <D>;
char c=getch();
getchar();
while(!kbhit()) x++;
char <D>; <D>=cin.get();
<D> = getch()-’0’;
(iostream.h) „stream“ Standardeingabe in D von Tastatur (umlenkbar)
(conio.h)
Pause bis Taste gedrückt wird, Taste in c speichern
(stdlib.h)
Pause bis Taste gedrückt wird
(stdio.h, conio.h) Warten und zählen, bis eine Taste betätigt wird;
(iostream.h) Nimmt die nächste Taste, die der User eingibt, in D auf
(conio.h)
D erhält den Wert der nächsten Ziffer, die gegeben wird.
31
31
„Integer“, ganze Zahlen -2 …2 -1
32
„Dual ohne Vorzeichen“, natürliche Zahlen 0…2 -1
16
„Integer-kurz“, natürliche Zahlen 0…2 -1
8
„Zeichen“, natürliche Zahlen 0…2 -1
„Boolsch“, logische Werte true (≠0) oder false (=0)
„Gleitkomma einfach“, reelle Zahlen 7 Stellen genau
„Gleitkomma doppelt“, reelle Zahlen 15 Stellen genau
„Gleitkomma lang doppelt“, reelle Zahlen 19 Stellen genau
leer, „nichts“
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
W2
<D>=exp(log(<W1>)*<W2>)
(math.h)
(W1) rechnen (Exposant) und D zuweisen.
abs(<W>), fabs(<W>), labs(<W>)
(math.h,stdlib.h) Die Absolutbeträge von int/float/long
W2
<D>=pow (<W1>,<W2>)
(math.h)
(W1) 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>;
if(<LA>)<A1>; else <A2>;
switch(i)
{ case 1: case 2: <A1>;
case 3: <A2>; break;
default: <A3>;}
<D>= <LA>? <W1>: <W2>;
Wenn LA=true, wird Anweisung(-sblock) A1 abgearbeitet, sonst nicht.
Wenn LA=true, wird Anweisung(-sblock) A1 abgearbeitet, sonst A2.
Fallunterscheidung, Mehrfachselektion, i muss ganzzahlig sein,
falls i den Wert 1 oder 2 enthält, wird A1 und danach A2 ausgeführt,
falls i den Wert 3 enthält, wird nur A2 ausgeführt, jeder nicht als vorlaufendes case abgeprüfter Wert führt zur Bearbeitung von A3.
?-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];
char s[]= “Weissbrot“;
strcpy(s, “Hallo“);
strcat(s, “ Welt!“);
<D>= strcmp (s, q);
<D>= strlen(s);
<D>= strnset(s, z, n);
Definition eines C-Strings s (char-Array) mit maximal 20 Zeichen
Definition eines C-Strings s mit Inhalt „Weissbrot“ für max. 9 Zeichen
(string.h) C-String s wird mit Text und Nullterminator gefüllt.
(string.h) An den C-String s wird angehängt, \0 wird angepasst
(string.h) Vergleicht C-Strings s und q (s<q→D<0, s=q→D=0, s>q→D>0)
(string.h) Ermittelt die Länge des Textes im String, ohne Terminator
(string.h) C-String s wird mit n mal dem Zeichen (char) z gefüllt.
(C++-)Strings der Klasse string
string s;
s+=“kette“;
s.append(“kette“);
s.append(“kette“, 0, 3);
s.assign(“kette“);
<D>= s.capacity();
<D>= s.c_str();
<D>= s.compare(q);
<D>= s.empty();
s.erase();
Definition eines C++-Strings s (class string)
hängt den String „kette“ an C++ String s an.
hängt den String „kette“ an C++ String s an.
hängt die ersten 3 Zeichen an C++ String s an.
ersetzt den C++ String s durch „kette“.
Gibt in D die Zeichenkapazität des C++ String s zurück.
Übergibt im char-Array D den C++ String s als nullterminierten (C-)String
vergleicht die C++ Strings s, q (s<q→D<0, s=q→D=0, s>q→D>0).
fragt, ob der C++ String s leer ist. bool D ist true, wenn s leer ist.
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++
<D>= s.find(q, 3);
s.insert(3, q);
<D>= s.length();
s.replace(a, l, q);
s.resize(l, z);
<D>= s.substr(a, l);
s.swap(q);
Funktionen
void <Fktname>(...)
<typ> <Fktname>(...)
... <Fktname>(void)
return x;
return;
... Fkt(char <D1>, int <D2>=9)
... <Fktname>(...);
void Fkt() const
static <D1>=999;
Arrays
<typ> arrn;
int a5= {1, 2, 3, 4, 5};
float b354;
61
Sucht im C++ Strings s ab der 3.Position den String q. Gibt Position des Vorkommens von q in s als als int-Wert an D zurück. (0 für nicht gefunden).
Fügt im C++ Strings s ab der 3.Position den String q ein.
Gibt die Länge C++ Strings s in Zeichen an D zurück.
Fügt im C++ Strings s ab der a.Position den String q in der Länge l ein.
Füllt den C++ Strings s bis zur Länge l mit Zeichen z auf.
Gibt den Teil des C++ Strings s ab Position a in Länge l zurück.
Tauscht den Inhalt des C++ String s mit dem Inhalt von String q.
Auftragsfunktion (liefert keinen Wert zurück)
Anfragefunktion (liefert <typ>-Wert über return-Anweisung zurück)
Funktion wird ohne Parameter aufgerufen
Funktion gibt den Wert x zurück
Beenden einer Funktion
Wenn Fkt ohne 2.Parameter gerufen wird, dann wird Parameter D2=9.
Prototyp, jede Funktion muss einmal im Voraus definiert werden
Funktion ist read-only, d.h. kann keine Daten ändern.
Statische Variable (innerhalb Funktion) deklarieren. Behält unveränderten Wert
nach Beenden beim erneuten Ruf. (ohne static: Wert zerstört)
b243= 17;
Festlegen eines Arrays arr mit n Elementen vom Datentyp <typ>.
Definieren des Arrays a mit 5 Elementen a[0]…a[4] mit Initialisierung.
Festlegen eines (3)dimensionalen Arrays (Feldes). Dieses Array besitzt
3*4*5= 60 Elemente im Bereich von b000 bis b243.
Wertzuweisung an ein Arrayelement
Zeiger und Adressen
char *Z1, double *Z2;
Zeig1= &<D>;
cout << *Z1;
char *s= “Weissbrot“;
int <D1>; int &<D2>=<D1>;
int *p = new int[n];
delete[] p;
Zeiger kann eine Adresse speichern und somit auf ein Objekt zeigen.
Adressoperator, gibt die Adresse statt dem Wert von D zurück
Inhaltsoperator * benutzt den Zeiger Z1 zur Ausgabe des Zeigeobjekts
Definition eines C-Strings s mit Inhalt „Weissbrot“ für max. 9 Zeichen
Referenz <D2> hat dieselbe Speicheradresse wie <D1>. („Alias“)
Fordert ein dynamisches Array(Heap) p der Grösse n und Typ int ab.
Gibt das dynamische Array(Heap) p wieder frei.
Strukturen und Unions
struct artikel
{ int ArtNr;
double Umsatz ...;} In1;
artikel In2, *In3;
In1.ArtNr= 20;
In3=new artikel;
In3->ArtNr=33;
union ... (siehe struct)
Festlegen der Struktur artikel
Festlegung des Strukturelementes ArtNr
Implizite Instanziierung der Instanz In1 (In der Deklarationsanweisung);
Explizite Instanziierung der Instanz In2 (Außerhalb der Strukturdeklar.);
Eingabe der Werte für die Struktur artikel
Dynamische Erstellung einer Strukturinstanz
Zugriff auf ein Element einer dynamischen Strukturinstanz
Wie struct, bloss dass alle Elemente denselben Speicherbereich nutzen.
Klassen
class xx
{ private:
Definition einer Klasse „xx“
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
put
Schreibt ein einzelnes Zeichen
get
Liest Zeichen und lässt Stoppzeichen im stream
read
Liest Datenblock in einen Speicherbereich
getline
Liest Zeichen und entfernt Stoppz. aus Datei
seekg,seekp Bewegt Dateizeiger
ignore
Entfernt Zeichen aus dem Datenstrom
tellg,tellp Ermittelt Dateizeigerposition
open
Initialisiert das Objekt und öffnet eine Datei
write
Schreibt einen Speicherbereich als Datenblock
peek
Prüft Folgezeichen im stream, ohne zu lesen
Herunterladen