SlideShare ist ein Scribd-Unternehmen logo
Version 2.01 - 27. April 2010




    Hydroinformatik I
 ”C++ und Visual C++”
Olaf Kolditz und Bastian Kolditz




    TU Dresden / UFZ Leipzig
 Angewandte Umweltsystemanalyse
        Umweltinformatik
            SS 2010

       c   OGS Publisher 2010
2



Vorlesungskonzept
Ein wesentlicher Bestandteil der Hydroinformatik ist die Informationsverarbei-
tung. Typische Hydrodaten sind z.B: digitale Gel¨ndemodelle (DGM), Nieder-
                                                  a
schlagsmessungen, Wasserpegel, Bodentemperaturen, Bodenkarten (Bodenty-
pen), geologische Schnitte u.v.a. (s. Abb. 1 und 2)




    Abbildung 1: Informationsverarbeitung in der Hydrologie - Datentypen

Eine grundlegende Methodik f¨ r die Informationsverarbeitung ist die wissen-
                             u
schaftliche Programmierung. Daher besch¨ftigen wir uns im ersten Semester
                                         a
der Veranstaltung ’Hydroinformatik’ mit der objekt-orientierten Programmie-
rung in C++.
Es gibt zwei M¨glichkeiten eine Programmiersprache zu erlernen: mehr theore-
              o
tisch oder mehr praktisch. Wir beschreiten den zweiten Weg. Das heißt anhand
von dem, was wir f¨ r das Programmieren ben¨tigen, erarbeiten wir uns die
                    u                           o
Theorie. Unser Motto ist ’Learning by doing’.
3



.




Abbildung 2: Informationsverarbeitung in der Hydrologie - Beispiel aus der Hy-
drogeologie



Organisatorisches
Die Pr¨ fung ’Hydroinformatik I’ (erstes Semester) ist eine Klausur. Die Pr¨fung
      u                                                                    u
’Hydroinformatik II’ (zweites Semester) besteht aus zwei Teilen, einer Klausur
und einer Programmier-Hausarbeit. Bei den Klausuren geht es um die Beant-
wortung von Verst¨ndnisfragen (siehe Testfragen zu jeder Vorlesung).
                  a
Sprache: normalerweise in Deutsch. Da die Syntax von Computersprachen (wie
C++) immer in Englisch ist, w¨ rde ich auch mal eine Vorlesung in Englisch
                               u
anbieten.
Konsultationen: immer nach der Vorlesung (Freitag ab 11 Uhr).
Kontakt: jederzeit by e-mail (olaf.kolditz@ufz.de), in dringenden F¨llen auch
                                                                    a
per Handy (0151 52739034), ich empfehle auch eine mailing Liste der Studenten
anzulegen, wenn alle damit einverstanden sind.
Vorlesungsunterlagen: lege ich erstmal auf meinem UFZ Server ab
(http://www.ufz.de/index.php?de=11877).
4



Es gibt viele und sehr gute C++ B¨ cher. Bei Amazon finden sie locker uber
                                   u                                   ¨
50 C++ B¨ cher (Abb. 3). Sehr gut finde das Buch von Prinz & Prinz ”C++
           u
- Lernen und professionell anwenden”, da es eine gute Kombination aus Theo-
rie und Programm-Beispielen ist. Zu diesem Lehrbuch gibt es auch ein extra
¨
Ubungsbuch. Unsere Vorlesung lehnt sich an dieses Buch an.




                         Abbildung 3: C++ Literatur

Das heisst, etwas anders wird unsere Vorgehensweise sein. Im ersten Semester
wollen wir zielgerichtet die C++ Grundlagen anhand der Entwicklung einer
einfachen ’Datenbank’-Anwendung erlernen - learning-by-doing - und die Daten
schließlich in einer graphischen Benutzerschnittstelle (GUI) sichtbar machen.
Somit besch¨ftigen wir uns auch zielgerichtet mit den Grundlagen von Visual
             a
C++.
Das Vorlesungskonzept:

    • Zielgerichtetes Erlernen der C++ Grundlagen,
    • Entwicklung einer ’Datenbank’-Anwendung,
    • Umsetzung in eine graphische Benutzerschnittstelle (Visual C++, C++
      GUI), siehe Abb. 4.
5



.




                      Abbildung 4: Vorlesungs-Konzept


Die Implementierung des Dialogs in Abb. 4 ist das erste greifbare Ziel der Ver-
anstaltung Hydroinformatik I. In dieser GUI-Anwendung k¨nnen sie (fast) alles,
                                                         o
was wir lernen werden, wiederfinden: Datentypen, Ein- und Ausgabe mit ver-
schiedene Ger¨ten (Tastatur, Bildschirm, Dateien), Klassen, Vererbung, Con-
               a
tainer (Listen, Vektoren) und graphische Programmierung unter Windows. Es
lohnt sich also dranzubleiben ...
Part I
C ++ Basics
Kapitel 1

Einfuhrung
    ¨




             7
8                                                                   ¨
                                                      KAPITEL 1 EINFUHRUNG



1.1     Historisches
Die Programmiersprache C++ wurde von dem d¨nischen Informatiker Bjar-
                                                  a
ne Stroustrup in den Bell Labs des nordamerikanischen Telekommunikations-
konzerns AT&T (American Telephone & Telegraph Corporation) ab 1979/80
entwickelt. C++ stellt eine Weiterentwicklung der ebenfalls von AT&T ent-
wickelten, Programmiersprache C dar. Die Programmiersprache C wurde als
Grundlage f¨ r C++ aufgrund seiner effizienten Codeverarbeitung und einfachen
            u
¨
Ubertragbarkeit auf anderen Plattformen verwendet. C wurde in C++ nach dem
Vorbild der Programmiersprache Simula-67 (1967), der ersten objektorientierten
Programmiersprache, im Wesentlichen um ein Klassenkonzept, d.h. die Abbil-
dung von Objekten in verschiedenen Klassen mit unterschiedlichen Attributen,
erweitert. Daher wurde C++ zun¨chst unter dem Namen ’C mit Klassen’ (C
                                  a
with classes) entwickelt. Der Name C++ wurde 1983 von Rick Mascitti erst-
mals angewandt. Dabei ist das ++ eine Andeutung an den Inkrement-Operator
(Inkrement: Erh¨hung einer Variable um 1), der die Verbesserungen gegen¨ ber
                o                                                         u
dem Vorg¨nger C zum Ausdruck bringen soll. Im Jahr 1985 erschien die erste
          a
Version von C++, die eine wichtige Grundlage f¨ r die weitere Entwicklung und
                                              u
Standardisierung von C++ darstellte, da die Sprache zu dieser Zeit noch nicht
akzeptiert war. Im Jahre 1989 erschien die erweiterte Version 2.0 von C++.
In den 90er Jahren begann nun der Standardisierungs- und Vereinheitlichungs-
prozess von C++, der eingeleitet wurde durch das Buch ’The Annotated C++
Reference Manual’ (1990) von Margaret Ellis und Bjarne Stroustrup. Die ge-
normte Fassung von C++ erschien 1998 (ISO/IEC 14882:1998), die 2003 mit
einer neuen Version (ISO/IEC 14882:2003) nochmals nachgebessert wurde.




    Abbildung 1.1: Bjarne Stroustrup (http://www.research.att.com/bs/)
1.2 PARADIGMEN                                                              9



1.2     Paradigmen
Programmier-Paradigmen sind sogenannte Leitlinien / Konzepte f¨ r die Ge-
                                                                   u
staltung von Programmen, diese k¨nnen durch entsprechende Sprachmittel un-
                                  o
terst¨ tzt werden. Allerdings bedeutet die Benutzung einer objekt-orientierten
     u
Sprache nicht automatisch ein objekt-orientiertes Programm (OOP).

   • Prozedurales Programmieren: Welche Prozeduren ben¨tigen Sie f¨ r Ihr
                                                       o          u
     Programm ? Verwenden Sie die optimalen Algorithmen.
   • Modulares Programmieren: Welche Module ben¨tigen Sie f¨ r Ihr Pro-
                                                   o         u
     gramm ? Strukturieren Sie Ihr Programm entsprechend modular. Die Da-
     ten sollten in den Modulen gekapselt sein.
   • Objekt-orientiertes Programmieren: Welche Klassen ben¨tigen Sie f¨ r Ihr
                                                          o           u
                  ¨
     Programm ? Uberlegen Sie, welche Gemeinsamkeiten die Klassen haben,
     benutzen Sie das Konzept der Vererbung.
   • Datenabstraktion: Welche Datentypen ben¨tigen Sie f¨ r Ihr Programm ?
                                                o         u
     Erstellen Sie f¨ r jeden benutzerdefinierten Typen m¨glichst viele Opera-
                    u                                   o
     tionen.
10                                                                   ¨
                                                       KAPITEL 1 EINFUHRUNG



.




          Abbildung 1.2: Objekt-orientiertes Programmieren - OOP

Die Abb. 1.2 soll das Konzept des Objekt-Orientierten Programmierens (OOP)
mal aus einer anderen Sichtweise erl¨utern. Normalerweise bedeutet die Pro-
                                     a
grammentwicklung (prozedural und modular) eine stetige Erweiterung des Co-
des (Abb. oben). Irgendwann ist das Programm dann so un¨ bersichtlich ge-
                                                              u
worden, dass eigentlich niemand mehr durchblickt. Die grundlegenden Idee von
OOP dagegen sind, dass, erstens Objekte (logische Einheiten des Programms)
streng gekapselt sind (sich also nicht gegenseitig beeinflussen) und, zweitens,
dass es ganz schmale Schnittstellen zwischen diesen Objekten gibt (z.B. nur
uber eine Adresse (sogenannte pointer)) (Abb. unten). Nat¨ rlich wachsen auch
¨                                                          u
diese Objekte weiter und stoßen irgendwann an Grenzen ...
Ein Beispiel aus der Praxis unserer eigenen Programmentwicklung OpenGeo-
Sys. Die Abb. 1.3 zeigt das objekt-orientierte Konzept der Kernels von Open-
GeoSys zur L¨sung von partiellen Differentialgleichungen. Letztlich f¨ hren alle
              o                                                      u
numerischen Methoden zur L¨sung von linearen Gleichungssystemen Ax = b.
                              o
Daher haben wir ein Objekt konstruiert (PCS von ProCesS), das die Aufgabe
ubernimmt, alle Bausteine f¨ r die Assemblierung und L¨sung der Gleichungs-
¨                           u                            o
systeme einzusammeln. Dabei geht es um geometrische (Punkte, Polylinien,
Fl¨chen, Volumen), topologische (Element-Netze), numerische und physikali-
  a
sche Daten (z.B. Materialeigenschaften, Anfangs- und Randbedingungen). Ent-
scheidend f¨ r die Machbarkeit eines objekt-orientierten Konzepts ist, dass der
           u
Algorithmus zum Aufstellen und L¨sen der Gleichungssysteme vollkommen
                                      o
unabh¨ngig von dem spezifischen physikalischen Problem ist. Die Basisklasse
      a
1.3 COMPILER                                                                11



f¨ r das PCS-Objekt ist CProcess, davon abgeleitet werden die speziellen Klas-
 u
sen f¨ r die spezifischen Probleme (z.B. Str¨mung, Stoff- und W¨rmetransport,
      u                                    o                   a
Deformation). Wenn Sie diesen Abschnitt noch mal durchlesen, sollten sie aller-
dings stutzig werden, da neben dem erwarteten Begriff der Objekt-Orientierung
auf der des Algorithmus auftaucht. Richtig, OpenGeoSys ist kein reines OOP
sondern eine Kombination von objekt-orientierten und prozeduralen Konzepten.
Anyway, der Schritt von C zu C++ (3. zur 4. Version, Abb. 1.3) bedeutete eine
Reduzierung des Quellcodes von 10MB auf 3MB, also um 70% !!!




  Abbildung 1.3: Objekt-orientiertes Konzept des Kernels von OpenGeoSys



1.3     Compiler
Bevor wir irgendetwas programmieren k¨nnen, ben¨tigen wir zwei Werkzeuge:
                                       o          o
einen Editor und einen Compiler. In der Abb. 1.4 sind die wichtigsten Schritte
der Programmerstellung zu sehen.
In der Computer-Welt (und deshalb auch in der Programmier-Welt) gibt es zwei
verschiedene Philosophien: Microsoft (MS) und ’den Rest’. Um diesem Problem
’auszuweichen’ und fair zu sein, benutzen wir Werkzeuge aus beiden Welten.
Wir beleuchten dieses ’Problem’ sp¨ter noch mal, wenn wir uber Open Source
                                    a                      ¨
Projekte (z.B. OpenGeoSys, unsere eigene Software-Entwicklung) sprechen. Wir
installieren uns zun¨chst den GNU Compiler (Abschn. 1.3.1) und sp¨ter den MS
                    a                                            a
Compiler (Abschn. 1.3.2) f¨ r das visuelle C++ Programmieren.
                           u
12                                                                  ¨
                                                      KAPITEL 1 EINFUHRUNG




              Editor

                        Source file            Header file

              Compiler

                        Object file

              Linker                           Libraries

                        Executable

                  Abbildung 1.4: Quell-Code Kompilation


1.3.1    GNU
Das GNU-Projekt wurde von Richard Stallman mit dem Ziel gegr¨ ndet, ein
                                                                   u
vollst¨ndig freies Betriebssystem, genannt GNU (GNU is not Unix), zu ent-
      a
wickeln. Bekannt geworden ist das Projekt vor allen Dingen auch durch die von
ihm eingef¨ hrte GNU General Public License (GPL), unter der viele bekannte
           u
Softwareprojekte ver¨ffentlicht werden (Quelle: Wikipedia).
                     o
Wenn ihr mehr uber das GNU Projekt erfahren wollt, schaut nach unter
              ¨
http://de.wikipedia.org/wiki/GNU-Projekt
Als Kompromiss benutzen wir cygwin (Abb. 1.5). Dass erm¨glicht uns, auch
                                                           o
unter Windows mit GNU Software arbeiten zu k¨nnen. Die Linux / Ubuntu
                                                   o
’Freaks’ haben die GNU Software automatisch mit dem Betriebssystem auf ih-
rem Rechner. Die Anleitung zur Installation finden sie im Anhang, Abschn.
12.2.2.2 (und wird nat¨ rlich in der Vorlesung besprochen)
                      u
1.3 COMPILER                                                           13



.




                 Abbildung 1.5: Ein Kompromiss: cygwin



1.3.2   MS Visual C++
Auch die nicht-MS-Fans m¨ ssen zugeben, das MS Visual C++ Studio ist eine
                           u
tolle Entwicklungsumgebung. Die wird uns enorm helfen, wenn wir uns sp¨ter
                                                                      a
mit GUI Programmierung besch¨ftigen. Die Express-Version von VC++ kann
                                 a
kostenlos direkt bei Microsoft unter
http://www.microsoft.com/germany/express/download/webdownload.aspx her-
untergeladen werden.


1.3.3   Qt
Als plattformunabh¨ngiges visuelles C++ empfehle ich Qt (siehe Abschn. 11
                  a
und 12.8)
14                                                                   ¨
                                                       KAPITEL 1 EINFUHRUNG



1.4      ”Hello World”
Unser allererstes C++ Programm.


1.4.1     Grundlagen
Jedes C/C++ Programm ben¨tigt eine main() Funktion
                        o

int main()
{
  return 0;
}

Die main() Funktion ist der ’Startpunkt’ eines jeden C/C++ Programms. Die
wichtigsten Bausteine einer Funktion sind:

     • Typ (R¨ ckgabewert): int (return 0)
             u
     • Name: main
     • Argumente: (), man kann die main Funktion auch mit Argumenten auf-
       rufen, z.B. der Name der Eingabe-Datei,
     • Funktionsrumpf: ...

Die Struktur der main() Funktion ist in der Abb. 1.6 dargestellt.

                    function type
                             function name
                                      function arguments

                                int main()
          function start        {
                                  ...             function block
                                  return 0;
           function end         }

                  Abbildung 1.6: Struktur der Funktion main()
1.4 ”HELLO WORLD”                                                          15



1.4.2    Exercise E1




                       Abbildung 1.7: cygwin aufrufen




Abbildung 1.8: cygwin drive ist /cygwin/home/user, wechseln zum Arbeitsver-
zeichnis cd c:/myworkdirectory (oder copy und paste)




              Abbildung 1.9: slash (/) ist nicht gleich slash ()

              ¨
Die einzige C Ubung:

#include <stdio.h>
int main()
{
  printf("Hello World");
  return 0;
}




Abbildung 1.10: Kommandozeile: gcc main.c, das Ergebnis ist a.exe, Aufruf des
Programms: ./a

Jetzt endlich zu C++ ...
16                                                                   ¨
                                                       KAPITEL 1 EINFUHRUNG



#include <iostream>
using namespace std;
int main()
{
  cout << "Hello World" << endl;
  return 0;
}




Abbildung 1.11: Kommandozeile: g++ main.cpp, mit ls den Inhalt des Verzeich-
nisses ansehen, das Ergebnis ist a.exe, Aufruf des Programms: ./a



1.5     Students Forum
Vielen Dank f¨ r Ihre Fragen zur ersten Vorlesung!
             u

JB Der C compiler funktioniert, der C++ aber nicht: Wahrscheinlich haben
    sie nur den C Compiler (GCC) installiert. Die k¨nnen jederzeit cygwin
                                                    o
    Komponenten nachinstallieren, siehe Abschn. 12.2.2.2.
                                                    ¨
DB Ich habe den MS VC++ installiert und kann die Ubungen nachvollziehen.
    Brauche ich den GNU Compiler von cygwin wirklich noch ?: Eigentlich
    nicht, mit MS VC++ haben sie einen kompletten Compiler mit allem
    drum und dran, dennoch kann ein Ausflug in die Konsolenwelt ja nicht
    schaden ... und sie k¨nnen sp¨ter in ihre Bewerbungen schreiben, dass sie
                         o       a
    auch unter Linux Programme entwickelt haben.

MF Die aktuelle cygwin Installation sieht anders aus als im Skript beschrieben:
   [OK] Im Anhang (Abschn. 12.2.2.2) finden sie eine bessere Beschreibung
   der cygwin Installation.

 C++ und Mac: erstmal eine Adresse http://developer.apple.com/TOOLS/xcode/
1.6 TESTFRAGEN                                                               17



1.6    Testfragen
  1. Was bedeutet das ++ im Namen der Programmiersprache C++ ?
  2. Ist C++ eine standardisierte Programmiersprache ?
  3. Was ist der Unterschied zwischen C und C++ ?
  4. Was sind sogenannte Programmier-Paradigmen ?
  5. Welche verschiedenen Programmier-Paradigmen kennen sie und worin un-
     terscheiden sie sich ?
  6. Welches Paradigma verfolgen wir in der Vorlesung ?
  7. Was ist objekt-orientierte Programmierung ?
  8. Was ist ein Kompiler ?
  9. Erkl¨ren sie die einzelnen Schritte bei einer Kompilierung (s. Abb. 1.4).
         a
                                                ¨
 10. Welchen Kompiler benutzen sie f¨ r die C++ Ubungen ?
                                    u
 11. Welche Funktion ben¨tigt jedes C oder C++ Programm ?
                        o
 12. Was ist der Typ einer Funktion ?
 13. Was ist eine Parameterliste einer Funktion ?
 14. Was ist der R¨ ckgabewert einer Funktion ?
                  u
Kapitel 2

Datentypen

Jede Programmiersprache bietet die Verwendung elementarer Datentypen an,
wie z.B. Ganzzahlen oder Gleitkommazahlen, logische Ausdr¨ cke oder Zeichen-
                                                          u
ketten. Die Besonderheit von objekt-orientierten (OO) Sprachen ist die Erstel-
lung benutzerdefinierter Datentypen. Dies war schon in der Sprache C mit sog.
’typedef struct’ Typen m¨glich. OO Sprachen, wie C++, bieten aber noch mehr
                        o
an, die Verkn¨ pfung von benutzerdefinierten Datentypen mit den entsprechen-
              u
den Methoden. Diese Konstrukte nennt man Klassen, aber darum geht es erst
im n¨chsten Kapitel. Zun¨chst m¨ ssen wir uns (kurz) mit den handels¨ blichen
     a                   a       u                                   u
Datentypen herumschlagen.



2.1     Elementare Datentypen
                                    ¨
Die nachfolgende Tabelle zeigt eine Ubersicht der elementaren Datentypen.

 Typ                 Bezeichner    Erl¨uterung
                                      a
 Wahrheitswerte      bool          Wert kann true (=1) oder false (=0) sein
 Zeichen             char          Zeichen, statische Zeichenketten
                     wchar t       ’wide character type’ (≥ 2 Byte)
                     string        Dynamische Zeichenketten
 Ganzzahlen          short         Ganze Zahlen mit geringer Genauigkeit
                     int           Ganze Zahlen mit hoher Genauigkeit
                     long          Ganze Zahlen mit sehr hoher Genauigkeit
 Gleitpunktzahlen    float          Reelle Zahlen mit geringer Genauigkeit
                     double        Reelle Zahlen mit hoher Genauigkeit
                     long double   Reelle Zahlen mit sehr hoher Genauigkeit

                            ¨
               Tabelle 2.1: Ubersicht elementarer Datentypen


                                     18
2.2 SPEICHERBEDARF                                                         19



2.2     Speicherbedarf

Die unterschiedlichen Datentypen werden durch den Compiler verschieden ver-
arbeitet und gespeichert (Gr¨ße des ben¨tigten Speicherplatzes).
                            o          o

 Typ             Speicherplatz   Wertebereich
 bool            1 Byte          (weniger geht leider nicht)
 char            1 Byte          -128 bis + 127 bzw. 0 bis 255
 int             2/4 Byte        -32768 bis +32767 bzw. -2147483648 bis + 2147483647
 short           2 Byte          -32768 bis +32767
 long            4 Byte          -2147483648 bis + 2147483647
 float            4 Byte          ± 3.4E+38, 6 Stellen Genauigkeit
 double          8 Byte          ± 1.7E+308, 15 Stellen Genauigkeit
 long double     10 Byte         ± 1.7E+4932, 19 Stellen Genauigkeit

               Tabelle 2.2: Speicherbedarf elementarer Datentypen

Der sizeof Operator ermittelt die ben¨tigte Speichergr¨ße f¨ r einen bestimm-
                                     o                o    u
ten Datentypen, z.B. sizeof(float) = 4: eine einfach genaue Gleitkommazahl
                                                                   ¨
ben¨tigt 4 Byte Speicher. Wir verwenden den sizeof Operator in der Ubung E34.
    o




2.3     Escape-Sequenzen

Escape-Sequenzen sind n¨ tzliche Helfer, z.B. zum Formatieren von Ausgaben
                         u
oder f¨ r die Benutzung von Sonderzeichen in der Ausgabe.
      u

          Zeichen     Bedeutung              Wirkung
          a          alert (BEL)            Ausprobieren
          b          backspace (BS)         eine Position zur¨ ck
                                                              u
          t          horizontal tab (HT)    horizontaler Tabulator
          n          line feed (LF)         Zeilenumbruch
          v          vertical tab (VT)      vertikaler Tabulator
          r          carriage return (CR)   Zeilenumbruch
          0          end of string          Zeilenende
          ”          ”                      Zeichen
          ’          ’                      Zeichen
          ?          ?                      Zeichen
                                          Zeichen

                    Tabelle 2.3: N¨ tzliche Escape-Sequenzen
                                  u
20                                                     KAPITEL 2 DATENTYPEN



2.4       Testfragen
     1. Was ist der genaueste Datentyp in C++ ?
     2. Wie groß ist der Speicherbedarf von einem string Datentyp ?
     3. Mit welcher Anweisung k¨nnen wir den Speicherbedarf von elementaren
                               o
        Datentypen ermitteln ?
     4. Was sind Escape-Sequenzen ?
     5. Was ist der Unterschied zwischen den Escape-Sequenzen n und r ?
     6. Was ist die C++ Entsprechung der Klasse cout f¨ r einen Zeilenumbruch
                                                      u
        ?
Kapitel 3

Ein- und Ausgabe

Ein Programm (ob prozedural, modular, objekt-orientiert) ist eigentlich nichts
weiter als eine Datenverarbeitung zwischen einer Eingabe (Input) und einer
Ausgabe (Output). I und O k¨nnen mehr oder weniger schick gemacht sein:
                            o

  1. I/O Standardger¨te,
                    a
  2. I/O Dateien,
  3. Datenbanken (I) und Visualisierung (O).

Aus didaktischen Gr¨ nden m¨ ssen wir leider mit dem Langweiligsten - I/O
                     u        u
Standardger¨te - anfangen. Spannend wird’s, wenn Daten durch die Visualisie-
            a
rung ’lebendig’ werden. Die Abb. 3.1 zeigt eine professionelle Datenaufbereitung
einen Porenraummodells in unserem Labor f¨ r wissenschaftliche Visualisierung
                                              u
(TESSIN-VISLab) am UFZ in Leipzig.


Die iostream Klasse
Die Ein- und Ausgabe in C++ erfolgt mit sogenannten Str¨men (streams). Die
                                                        o
I/O-Stream-Klassen (Abb. 3.2) bieten vielf¨ltige M¨glichkeiten, die wir uns in
                                          a       o
                  ¨
den nachfolgenden Ubungen n¨her anschauen.
                            a




                                      21
22                                              KAPITEL 3 EIN- UND AUSGABE



.




               Abbildung 3.1: Wissenschaftliche Visualisierung



                                    ios


                    istream                     ostream


                                 iostream

                     Abbildung 3.2: I/O stream Klassen

Die Klasse iostream geht durch Mehrfachvererbung aus den Klassen istream
und ostream hervor. iostream stellt damit die Funktionalit¨t beider I/O Klas-
                                                          a
sen zu Verf¨ gung.
           u
3.1 DIE STANDARD-STREAMS                                                   23



3.1     Die Standard-Streams
Es gibt vier Standard-Streams:

   • cin: Standard-Eingabe uber die Tastatur, Objekt der Klasse istream
                           ¨
   • cout: Standard-Ausgabe auf dem Bildschirm, Objekt der Klasse ostream

   • cerr und clog: zwei Objekte der Klasse ostream f¨ r die Fehlerausgabe.
                                                     u

Exercise E3.1:

#include <iostream>
using namespace std;
int main()
{
  int zahl;
  cout << "Bitte eine ganze Zahl eingeben: ";
  cin >> zahl;
  cout << zahl << endl;
  return 0;
}

Die Ein- >> und Ausgabeoperatoren << transportieren die Str¨me von und zu
                                                             o
den Eingabe- bzw. Ausgabeger¨ten. Dabei formatieren sie die Datentypen (z.B.
                             a
           ¨
int in der Ubung E3.1) entsprechend den Einstellungen der Klasse ios. Diese
Einstellungen k¨nnen durch Flags ver¨ndert werden (siehe n¨chsten Abschnitt).
               o                    a                     a


3.2     Formatierte Ausgaben
redmehr Beschreibung notwendig


3.2.1    Formatierte Ausgabe von Ganzzahlen
                     ¨
In der nachfolgenden Ubung besch¨ftigen wir uns mit den verschiedenen Aus-
                                a
gabem¨glichkeiten von ganzen Zahlen.
      o
Exercise E3.2.1:

#include <iostream>
using namespace std;
int main()
{
  int zahl;
  cout << "Bitte eine ganze Zahl eingeben: ";
  cin >> zahl;
24                                                   KAPITEL 3 EIN- UND AUSGABE




     cout << uppercase // f¨r Hex-Ziffern
                           u
          << " oktal tt dezimal t hexadezimal n "
          << oct << zahl << " tt "
          << dec << zahl << " tt "
          << hex << zahl << endl;
     return 0;
}


3.2.2      Formatierte Ausgabe von Gleitpunktzahlen
                     ¨
In der nachfolgenden Ubung besch¨ftigen wir uns mit den verschiedenen Aus-
                                 a
gabem¨glichkeiten von realen Zahlen.
      o

            Methoden                 Wirkung
            int precision(int n)     Genauigkeit wird auf n gesetzt

Exercise E3.2.2:

#include <iostream>
using namespace std;
int main()
{
  double zahl;
  cout << "Bitte eine Gleitkommazahl eingeben: ";
  cin >> zahl;

     cout.precision(7); // auf sieben Stellen genau

     cout << "Standard: t"                   <<   zahl   <<   endl;
     cout << "showpoint: t" << showpoint     <<   zahl   <<   endl;
     cout << "fixed: tt"    << fixed        <<   zahl   <<   endl;
     cout << "scientific: t" << scientific   <<   zahl   <<   endl;
     return 0;
}


3.2.3      Ausgabe von Speicherbedarf
          ¨
In dieser Ubung benutzen wir den sizeof Operator, um den Speicherbedarf von
Standard Daten-Typen zu bestimmen.
Exercise E3.2.3:

#include <iostream>
using namespace std;
int main()
{
3.3 TESTFRAGEN                                                               25



    cout << "TypetNumber of bytesn";
    cout << "-----------------------n";
    cout << "booltt" << sizeof(bool) << endl;
    cout << "chartt" << sizeof(char) << endl;
    cout << "shorttt" << sizeof(short) << endl;
    cout << "inttt" << sizeof(int) << endl;
    cout << "longtt" << sizeof(long) << endl;
    cout << "floattt" << sizeof(float) << endl;
    cout << "doublett" << sizeof(double) << endl;
    cout << "long doublet" << sizeof(long double) << endl;
    return 0;
}



3.3       Testfragen
     1. Sind sie mit der Tab. 2.2 einverstanden ?
     2. Welche Ein- und Ausgabeger¨te kennen sie ?
                                  a
     3. Welche Klasse ben¨tigen wir f¨ r die Standard-Ein- und Ausgabe ?
                         o           u
     4. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ?
                                  u
     5. Mit welcher Klasse k¨nnen wir sowohl Eingabe- als auch Ausgabestr¨me
                            o                                            o
        benutzen ?
     6. Welche Include-Datei ist notwendig, um mit I/O-Str¨men arbeiten zu
                                                          o
        k¨nnen ?
         o
     7. Wozu dient der Zusatz using namespace std; nach dem Include von
        Standard-Klassen, wie I/O Streams ?
     8. Was bewirken die Stream-Operatoren << und >> ?
     9. Was bewirken die Flags oct, dec, hex f¨ r die formatierte Ausgabe von
                                              u
        Ganzzahlen ? (ToDo)
    10. Wie kann ich die Genauigkeit der Ausgabe von Gleikomma-Zahlen festle-
        gen ?
    11. Wie kann man den Speicherbedarf einer Variable ermitteln ? Schreiben
        sie die C++ Anweisung f¨ r die Berechnung des Speicherbedarfs f¨ r eine
                               u                                       u
        doppelt-genaue Gleitkomma-Zahl.
Kapitel 4

Klassen




                                source:
                                TU Dresden




Data abstraction

    class CStudent
       properties
       ...                Instances
       methods
       ...                CStudent *m_std;


              Abbildung 4.1: Das Klassen-Konzept - CStudent




                                      26
4.1 DATEN-ABSTRAKTION                                                        27



Das Sprachelement der Klassen sind das entscheidende Kriterium von objekt-
orientierten Konzepten und die objekt-orientierte Programmierung (OOP). Klas-
sen sind eine Art Schablone f¨ r einen benutzerdefinierten Datentypen. Dar¨ ber
                             u                                           u
hinaus enth¨lt die Klasse neben den Daten auch alle Methoden (Funktionen),
            a
um mit den Daten der Klasse operieren zu k¨nnen. Unser Beispiel f¨ r Klassen,
                                             o                      u
das uns im Verlaufe der Vorlesung besch¨ftigen wird, ist - wie k¨nnte es an-
                                          a                       o
ders sein - CStudent (Abb. 4.1). F¨ r die Konzipierung von Klassen spielt die
                                     u
Abstraktion der Daten einer Klasse eine besonders wichtige Rolle.


4.1     Daten-Abstraktion
Die Abb. 4.1 illustriert uns, dass eine Abstraktion von Daten (d.h. Eigenschaf-
ten) der Klasse Studenten eine durchaus vielschichtige Angelegenheit sein kann.
Eine Aufstellung von Daten / Eigenschaften, die es aus ihrer Sicht zu ber¨ ck-
                                                                           u
sichtigen gilt, ist ihre n¨chste Hausaufgabe.
                          a
Der n¨chste Block zeigt ihnen das Schema der Syntax der Klassen-Definition
       a
CStudent. Das Schl¨ sselwort f¨ r die Klassen-Definition ist class, der Name ist
                    u         u
CStudent. Der Klassen-Rumpf ist in geschweifte Klammer eingebettet. Wichtig
ist der Abschluss mit einem Semikolon. Wie bereits erw¨hnt, eine Klasse enth¨lt
                                                      a                     a
Daten (Eigenschaften) und Methoden (Funktionen) auf den Daten. Prinzipiell
geht diese Datenabstraktion auch mit anderen Sprachen wie C. A data construct
typedef struct {...} in C can be seen as an analogue to a C++ class.
Die C Version:

typedef struct
{
  char* name_first;
  char* name_last;
  long matrikel_number;
} TDStudent;
TDStudent *student = NULL;

Die C++ Version:

class CStudent
{
  data:
  ...
  methods:
  ...
};

Bei der Namensgebung von Klassen wird oft ein ’C’ (CStudent) vorangestellt,
um die Bedeutung als Klasse (wesentlicher Baustein des Programm-Konzepts)
herauszustellen.
28                                                          KAPITEL 4 KLASSEN



Ein weiterer Vorzug von OO-Sprachen ist z.B. die Sichtbarkeit / Zugreifbarkeit
von Daten zu regeln. Der nachfolgende Block zeigt das Datenschutz-Konzept
von C++ (Sicherheitsstufen): Daten k¨nnen ¨ffentlich sein (public) oder gezielt
                                       o    o
f¨ r ’Freunde’ verf¨ gbar gemacht werden (protected) oder nur exklusiv f¨ r die
 u                 u                                                    u
eigene Klasse sichtbar zu sein (private).

class CStudent
{
  private:
  ...
  protected:
  ...
  public:
  ...
};



4.2      Klassen-Deklaration
Im vorangegangenen Abschnitt haben wir uns mit der Datenabstraktion mittels
Klassen besch¨ftigt. So sollte konsequenterweise jede Klasse auch ihre eigenen -
              a
sorry - eigenen Quelldateien besitzen. Die Deklaration von Klassen erfolgt ubli-
                                                                           ¨
cherweise in einer sogenannten Header-Datei *.h. F¨ r die Methoden / Funk-
                                                      u
tionen der Klasse ist eine *.cpp Datei reserviert. F¨ r uns bedeutet dies, zwei
                                                     u
Dateien anlegen:

     • student.h - die Deklaration der Klasse CStudent

     • student.cpp - die Methoden der Klasse CStudent

Um mit der Klasse arbeiten zu k¨nnen, m¨ ssen wir das entsprechende Header-
                                  o       u
File inkludieren. Dies erfolgt mit der Anweisung #include ”student.h” am An-
fang unseres Main-Files.

#include "student.h"
int main
{
  return 0;
}



4.3      Instanzen einer Klasse
An dieser Stelle m¨chten wir unsere Eingangsgraphik (Abb. 4.1) erinnern. In-
                  o
stanzen sind Kopien einer Klasse mit denen wir arbeiten k¨nnen, dass heißt
                                                         o
4.3 INSTANZEN EINER KLASSE                                                   29



diese bekommen echten Speicher f¨r ihre Daten (die nat¨ rlich f¨ r jede Instanz
                                   u                  u        u
einer Klasse unterschiedlich sein k¨nnen).
                                   o
Es gibt zwei M¨glichkeiten, Instanzen einer Klasse zu erzeugen:
              o


#include "student.h"
void main()
{
  // Creating an instances of a class - 1
  CStudent m_std_A;
  // Creating an instances of a class - 2
  CStudent *m_std_B;
}


Der direkte und der mittels eines sogenannten Zeigers (hierf¨ r gibt ein Extra-
                                                            u
Kapitel). Wir werden sehen, dass der zweite Weg oft der bessere ist, da wir z.B.
die Initialisierung und das Speichermanagement f¨ r unsere Daten selber in die
                                                u
Hand nehmen k¨nnen. Dies k¨nnen wir mittels sogenannter Konstruktoren und
                 o            o
Destruktoren erledigen. Damit besch¨ftigen wir uns im n¨chsten Abschnitt.
                                     a                  a
Exercise E4.3:


#include "student.h"
#include <iostream>
using namespace std;
int main()
{
  CStudent *m_std_cpp; // pointer to an instance
  cout << "E41: Instances of classes" << endl;
  cout << "What have we created?t : " << m_std << endl;
  cout << "What size has it?t : " << sizeof(m_std) << endl;
  TDStudent *m_std_c; // pointer to TD
  return 0;
}

-> student.h
// Class definition
class CStudent
{
  public:
  protected:
  private:
};
// Type definition
typedef struct
{
} TDStudent;
30                                                       KAPITEL 4 KLASSEN



4.4      Konstruktor und Destruktor
Wohl die wichtigsten Methoden von Klassen sind deren Konstruktoren CStudent()
und Destruktoren ∼ CStudent(). Diese Funktionen haben den gleichen Namen
wie die Klasse selbst. Der nachfolgende Block zeigt die Deklaration unserer er-
sten beiden Klassen-Funktionen in der Header-Datei students.h.

class CStudent
{
  public:
    CStudent(); // constructor
    ~CStudent(); // destructor
};

Wie sehen die Konstruktor/Destruktor-Funktionen aus.
#include "student.h"

CStudent::CStudent()
{
}

CStudent::~CStudent()
{
}

Die Konstruktor/Destruktor-Funktionen werden ’automatisch’ aufgerufen beim
Erzeugen (¨ ber die Zeiger-Version) und Zerst¨ren der Klassen-Instanz:
          u                                  o

     • new ruft den dazugeh¨rigen Konstruktor auf,
                           o
     • delete ruft den dazugeh¨rigen Destruktor auf.
                              o

Die Anwendung der Konstruktor/Destruktor-Funktionen ist im folgenden Quellcode-
Abschnitt dargestellt.
Exercise E4.4:
#include <iostream>
using namespace std;
#include "student.h"
int main()
{
  CStudent* m_std = new CStudent(); // instance using constructor
  cout << "E44: Constructor of class CStudent" << endl;
  cout << "What have we created? m_stdt : " << m_std << endl;
  cout << "What size has it?t : " << sizeof(m_std) << endl;
  cout << "What have we created? &m_stdt : " << &m_std << endl;
  cout << "What size has it?t : " << sizeof(&m_std) << endl;
  return 0;
}
4.5 DATENINITIALISIERUNG MIT DEM KONSTRUKTOR                                 31



4.5     Dateninitialisierung mit dem Konstruktor
Der Klassen-Konstruktor kann dar¨ ber hinaus auch zur Initialisierung von Da-
                                    u
ten f¨ r die Klassen-Instanz benutzt werden. Ganz nebenbei schreiben wir unsere
     u
erste Klassen-Funktion in der Quell-Datei der Klasse students.cpp. Wir initiali-
sieren den Namen unseres ersten Studenten.
Exercise E4.5:

CStudent::CStudent()
{
  // Initializations
  name_first = "James";
  name_last = "Bond";
}

Daf¨ r m¨ ssen wir die notwendigen Klassen-Variablen (member variables) f¨ r
    u   u                                                                  u
den Namen bereitstellen. Praktischerweise ist es ratsam, die Daten und Metho-
den der Klasse zu trennen. Unsere Klassen-Deklaration nimmt langsam Gestalt
an ...

#include <string>
using namespace std;
class CStudent
{
  // Data / Properties
  public:
    string name_first;
    string name_last;
  // Methods / Functions
  public:
    CStudent(); // constructor
    ~CStudent(); // destructor
};

F¨ r die Namen benutzen wir die string Klasse von C++ (auch hierzu gibt’s
  u
ein Extra-Kapitel). Um den Daten-Typ string aus dieser Klasse benutzen zu
k¨nnen, m¨ ssen wir die Klasse wie folgt inkludieren.
 o        u

#include <string>
using namespace std;

Exercise E4.5:

#include <iostream>
using namespace std;
#include "student.h"
32                                                           KAPITEL 4 KLASSEN



int main()
{
  CStudent* m_std = new CStudent(); // instance using constructor
  cout << "E45: Data initialisation by constructor of class CStudent" << endl;
  cout << "m_std->name_firstt : " << m_std->name_first << endl;
  cout << "m_std->name_lastt : " << m_std->name_last << endl;
  delete(m_std);
  return 0;
}



4.6     Datenschutz
Eine wichtige Eigenschaft der Sprache C++ ist die M¨glichkeit, Daten unter-
                                                        o
schiedlich sichtbar zu machen. Eingangs des Kapitels haben wir gesehen, dass
es verschiedene Schl¨ sselw¨rter gibt, um Variablen zu klassifizieren: public, pro-
                     u     o
tected und private. Daten des Typs ’public’ sind uberall sichtbar, aus sie kann
                                                   ¨
von uberall im Programm zugegriffen werden - also auch ver¨ndert werden. Dies
     ¨                                                       a
kann sehr schnell problematisch werden, wenn das Programm sehr groß ist oder
mehrere Programierer gleichzeitg entwickeln. Daten des Typs ’private’ sind nur
f¨ r die eigene Klasse sichtbar, dass auf sie k¨nnen nur durch Klassen-eigene
 u                                             o
Methoden zugegriffen werden. Private data sind f¨ r andere Klassen verborgen.
                                                   u
Nat¨ rlich gibt es noch einen Kompromiss: Mit dem Schl¨ sselwort ’protected’
     u                                                     u
kann man gewisse Daten f¨ r ’befreundete’ Klassen offnen. Dies ist im Wesentli-
                           u                         ¨
chen das Datenschutz-Konzept von C++.
                 ¨
In der folgenden Ubung sehen wir, wie man mit ’private’ data (Kontonummer)
umgehen kann. Die Variable bank account ist als private Typ deklariert.

class CStudent
{
  public:
    long GetBankAccount();
    void SetBankAccount(long);
  private:
    long bank_account;
};


Die Zugriffsfunktion GetBankAccount() der Klasse CStudent gibt lediglich den
Wert der Variable zur¨ ck, ihr Typ ist nat¨ rlich public. Die Kontonummer kann
                     u                    u
also zun¨chst nicht von ’außen’ ge¨ndert werden.
        a                          a

long CStudent::GetBankAccount()
{
  return bank_account;
}
4.6 DATENSCHUTZ                                                             33



void CStudent::SetBankAccount(long new_bank_account)
{
  bank_account = new_bank_account;
}

Nat¨ rlich l¨sst sich auch eine Funktion schreiben, mit der man private Daten
    u       a
von außen ¨ndern kann: SetBankAccount(long). Letztlich entscheidet der Pro-
            a
grammierer, ob dieser Zugriff zul¨ssig sein soll, wenn nicht gew¨ nscht, werden
                                  a                             u
die Get und Set Zugriffsfunktionen einfach nicht bereitgestellt.
                    ¨
Die nachfolgende Ubung zeigt zusammenfassend den Zugriff auf private Varia-
blen von Außen.
Exercise E4.6:

int main()
{
  CStudent* m_std = new CStudent(); // instance using constructor
  cout << "E46: Data security - using private data" << endl;
  cout << "m_std->GetBankAccount()t : " << m_std->GetBankAccount() << endl;
  m_std->SetBankAccount(987654321); // changing private data
  cout << "m_std->GetBankAccount()t : " << m_std->GetBankAccount() << endl;
  delete(m_std);
  return 0;
}
34                                                            KAPITEL 4 KLASSEN



4.7       Testfragen
     1. Geben sie eine Definition von C++ Klassen mit eigenen Worten (max 5
        S¨tze).
         a
     2. Was ist ein benutzerdefinierter Datentyp ?
     3. Welches Datennschutz-Konzept gibt es f¨ r Klassen ?
                                              u
     4. Wozu brauchen wir zwei Dateien f¨ r Klassen, eine H (Header) Datei und
                                        u
        eine CPP (Quelltext) Datei ?

     5. Was ist ein Inklude / Include ?
     6. Was ist eine Instanz einer Klasse ?
     7. Worin besteht der Unterschied zwischen den Anweisungen: CStudent m std 1
        und CStudent* m std 2 ?
     8. Was ist ein Konstruktor einer Klasse ?
     9. Was ist das Gegenst¨ ck zum Klassen-Konstruktor ?
                           u
 10. Wie k¨nnen Daten / Variablen einer Klasse initialisiert werden ?
          o
 11. Schreiben sie den Quelltext f¨ r den Klassen-Konstruktor und weisen sie
                                  u
     den Variablen name first und name last ihren eigenen Namen zu.
 12. Was verbirgt sich hinter der Anweisung: CStudent* m std = new CStudent()
     ?
 13. Was ist der Unterschied zwischen CStudent und CStudent() ?
 14. Wie kann ich meine Daten gegen einen externen Zugriff sch¨ tzen ?
                                                             u
Kapitel 5

Strings

                            ¨
Wir haben schon in mehreren Ubungen den Datentyp string benutzt, ohne diesen
Datentyp etwas n¨her zu beleuchten. Dieses Vers¨umnis soll in diesem Kapitel
                 a                             a
nachgeholt werden.


5.1     Die Standardklasse string
String (in Deutsch Zeichenkette) ist vielmehr als nur ein Datentyp, string ist eine
Standard-Klasse in C++. String ist eine der genialsten Weiterentwicklungen des
C-Datentyps char, die das Hantieren mit Zeichen und Zeichenketten zu einem
Kinderspiel macht, na sagen wir mal - uns das Programmierleben erheblich
vereinfachen wird, wenn wir mit Zeichenketten operieren werden. So wird z.B.
der erforderliche Speicherplatz f¨ r Zeichenketten automatisch reserviert und bei
                                 u
Ver¨nderungen angepasst.
    a
Wenn wir strings benutzen wollen, m¨ ssen den Header der string-Klasse wie
                                   u
folgt inkludieren.

#include <string>    // for using strings
using namespace std; // for using standard names


Wichtig ist auch die zweite Zeile using namespace std. Diese Anweisung besagt,
dass wir im folgenden Standard-Namen benutzen. Sonst m¨ ssten wir vor jeder
                                                            u
string-Operation noch den Zusatz std:: setzen. Zur Benutung von namespace f¨ r
                                                                            u
die Strukturierung und Kapselung von Programmteilen gibt es sp¨ter ein Extra-
                                                                 a
kapitel (9.2.2). An dieser Stelle zeigen wir die Bedeutung von using namespace
std; in bew¨hrter Weise an einem Beispiel.
            a
Sie haben sicher schon bemerkt, dass wir bei #include manchmal eckige Klam-
mern <> und manchmal G¨nsef¨ ßchen ” benutzen. Wir schauen uns dies, wie
                          a     u

                                        35
36                                                         KAPITEL 5 STRINGS



gesagt, genauer im Kapitel 9.2.2 an. Hier nur soviel, dass mit eckigen Klammern
<> an Header-Dateien im Systemverzeichnis von C++ gesucht wird, w¨hrend   a
” benutzerdefinierte, eigene Header (z.B. student.h) kennzeichnet und somit im
aktuellen Arbeitsverzeichnis (also ./) nachgeschaut wird.



5.2     Operationen mit strings

                                    ¨
Die nachfolgende Tabelle zeigt eine Ubersicht der wichtigsten string Operatio-
nen, die wir in diesem Kapitel verwenden.

        Methode       Erl¨uterung
                          a
        .append()     verl¨ngert den String
                           a
        .c str()      erzeugt Zeichenfeld mit dem Inhalt des Strings
        .clear()      l¨scht den Inhalt des Strings
                       o
        .compare()    vergleicht Strings
        .erase()      l¨scht Zeichen im String
                       o
        .find()       sucht Zeichen in einem String
        .insert()     f¨ gt in den String ein
                       u
        .length()     ermittelt die L¨nge des Strings
                                      a
        .replace()    ersetzt Zeichen im String
                      wichtig f¨ r die Konvertierung von string zu char*
                                u
        .resize()     a
                      ¨ndert L¨nge des Strings
                                a
        .substr()     gibt einen Substring zur¨ ck
                                               u
        >>            Eingabeoperator f¨ r Strings
                                         u
        <<            Ausgabeoperator f¨ r Strings
                                          u
        getline()     liest Zeichen aus der Eingabe

                         Tabelle 5.1: string Methoden




5.2.1    Initialisieren von strings

Eine M¨glichkeit f¨ r die Initialisierung von strings haben wir uns bereits in
       o           u
der Exercise E4.5 angesehen bei der Verwendung von Klassen-Konstruktoren.
Der Standard-Konstruktor string() erzeugt einen leeren String. Eine zweite
M¨glickeit besteht direkt bei der Deklaration des strings, wie folgt:
  o
Exercise E5.2.1:


string exercise("Exercise: string initialisation");
cout << exercise.length() << endl;
5.2 OPERATIONEN MIT STRINGS                                                  37



5.2.2    Zuweisen von strings
                  ¨
In der folgenden Ubung schauen wir uns an, wie wir mittels Tastatureingabe
(Standard-Eingabe-Ger¨t) strings zuweisen und Teile von strings in andere ko-
                     a
pieren zu k¨nnen.
           o
Exercise E5.2.2:

#include ... // Bitte f¨gen sie die notwendigen Header selbst ein
                       u
main()
{...
string eingabe;
string eingabe_anfang;
string message("Bitte geben Sie eine Zeile mit der Tastatur ein.
                Schliessen Sie die Eingabe mit Enter ab");
//-------------------------------------------------------------------
cout << message << endl; // Ausgabe der Eingabeaufforderung
getline(cin,eingabe); // Eingabe einer Zeile uber Tastatur
                                             ¨
eingabe_anfang(eingabe,0,10); // die ersten 10 Zeichen von eingabe werden
                                 nach eingabe_anfang kopiert
cout << "Ihr Eingagetext: " << eingabe << endl;
cout << "Die ersten 10 Zeichen des Eingagetextes: " << eingabe_anfang << endl;
...}


5.2.3    Verketten von strings
Mit dem Operator + k¨nnen Strings miteinander verkn¨ pft werden und in einem
                    o                              u
                                            ¨
neuen string name kopiert. In der folgenden Ubung produzieren wird aus Vor-
und Nachnamen den ganzen Namen.
Exercise E5.2.3:

string name;
CStudent* m_std = new CStudent();
name = m_std->name_first + m_std->name_last;
// oder
name = m_std->name_first;
name += m_std->name_last;

Wie bekommen wir einen Zwischenraum (Leerzeichen) zwischen Vor- und Nach-
namen ?


5.2.4    Vergleichen von strings
Oft sind Abfragen notwendig, ob gewisse Zeichenketten gefunden wurden, um
dann gewisse Operationen durchzuf¨ hren. Hierf¨ r bietet die String-Klasse meh-
                                   u          u
rere M¨glichkeiten an, z.B. den exakten Vergleich (string::compare) oder einen
       o
38                                                          KAPITEL 5 STRINGS



                                                        ¨
Teil von Zeichenketten (string::find). Die nachfolgende Ubung zeigt, wenn der
Nachname BOND gefunden wurde, dann wird der Vorname auf JAMES gesetzt
(und nat¨ rlich der russische Geheimdienst informiert).
         u
Exercise E5.2.4:

if(m_std->name_last.compare("BOND")==0)
{
  m_std->name_first = "JAMES";
}

                 ¨
Die nachfolgende Ubung zeigt, wie ein Programm beendet werden kann, wenn
eine bestimmte Taste gedr¨ ckt wird. Hierf¨ r werden einzelne Zeichen mit dem
                         u                u
Operator == verglichen.

string Taste("N");
while(Taste == "J")
{
  cout << "Soll dieses Programm endlich beendet werden? (J/N)" << endl;
  getline(cin,Taste);
}
cout << "Programm-Ende" << endl;



5.2.5    Suchen in strings
       ¨
Diese Ubung zeigt ihnen, wie nach Zeichenketten in string suchen k¨nnen. Sie
                                                                      o
sehen, je nach Sorgfalt des Programmierers haben sie eventuell schlechte Karten,
wenn ihr Vorname die Zeichenkette ’BON’ enth¨lt.
                                               a
Exercise E5.2.5:

if(m_std->name_last.find("BON")!=string::npos)
{
  m_std->name_first = "JAMES";
}



5.2.6    Einfugen in strings
             ¨

Nun benutzen wir die Einf¨ ge-Funktion von strings (string::insert), um Vor-
                           u
und Nachnamen zusammenzusetzen. Dabei ermitteln wir zun¨chst die L¨nge des
                                                           a         a
Vornamen mit string::length, setzen dann den Positionsz¨hler pos um Eins hoch
                                                       a
(Leerzeichen zwischen Vor- und Nachnamen) und f¨ gen dann den Nachnamen
                                                   u
mit string::insert ein.
Exercise E5.2.6:
5.2 OPERATIONEN MIT STRINGS                                                  39



string name;
int pos;
if(m_std->name_first.find("JAMES")!=string::npos)
{
  pos = m_std->name_first.length();
  name.insert(pos+1,"BOND");
}


5.2.7    Ersetzen in strings
Eine weitere n¨ tzliche String-Funktion ist das Ersetzen von Zeichen. In der
               u
               ¨
nachfolgenden Ubung andern wir den Nachnamen. Dazu wird zun¨chst wieder
                       ¨                                          a
die L¨nge des Vornamens mit string::length ermittelt und dann der neue Nach-
     a
name eingef¨gt. So k¨nnen sie ihre Spuren verwischen ... ist auch praktisch bei
            u        o
Namens¨nderungen z.B. infolge Heiraten (Beachten sie, dass Triple-Namen wie
        a
M¨ ller-Graf-Kleditsch nicht mehr zul¨ssig sind).
  u                                  a
Exercise E5.2.7:

string name;
int pos;
name = "JAMES" + " " + "CHRISTIE"
if(m_std->name_first.find("JAMES")!=string::npos)
{
  pos = m_std->name_first.length();
  name.replace(pos+1,"BOND");
}

Was passiert, wenn der neue Nachname l¨nger ist als der alte ?
                                      a


5.2.8    Loschen in strings
          ¨
Nat¨ rlich k¨nnen auch Zeichen in einem string gel¨scht werden. Diese Funktion
   u        o                                     o
passt den Speicherbedarf des gek¨ rzten Strings automatisch an.
                                 u
Exercise E5.2.8:

string name;
int pos;
name = "JAMES" + " " + "CHRISTIE"
if(m_std->name_first.find("JAMES")!=string::npos)
{
  pos = m_std->name_first.length();
  name.erase(pos);
  name.replace(pos+1,"BOND");
}

Abschliessend kommen wir zu zwei weiteren Punkten, (1) das Umwandeln von
C++ strings in C char und (2) das Auslesen von string Teilen.
40                                                           KAPITEL 5 STRINGS



5.2.9    Umwandeln von strings in char

Manchmal ist es notwendig C++ strings in C char umzuwandeln (wir ben¨tigen
                                                                       o
dies sp¨ter, wenn wir mit der MFC Klasse CStrings f¨ r grafische Benutzerober-
       a                                           u
߬chen arbeiten). Die String-Methoden c str() und data() wandeln strings in
 a
char um. Aufgepasst, ab char m¨ ssen wir uns selber um das Speichermanage-
                                u
ment k¨ mmern.
       u

fprintf(f," %sn",name.c_str());
name.clear();
const char *char_string;
char_string = name.data();


5.2.10     Auswerten von Strings: Stringstreams

Stringstreams ... l¨sst sich kaum aussprechen .. es handelt sich aber definitiv
                   a
nicht um stringdreams ... (sie erinnern sich an die Eingangsfolie der Vorlesung).
Stringstreams sind eine sehr n¨ tzliche Sache, damit lassen sich Eingabedaten
                                u
(von Tastatur und Datei) bequem als Stream auswerten. Um Stringstreams
                                                                     ¨
nutzen zu k¨nnen, muss die Klasse sstream inkludiert werden. Die Ubung zeigt,
           o
wie man eine eingegebene Zeile (Vor- und Nachnahme) elegant zerlegen kann.
Dabei wird die eingebene Zeile zun¨chst in den stringstream kopiert, danach
                                    a
wird input line wie ein normaler stream ausgelesen.
Exercise E5.2.10:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
  string name;
  string name_first;
  string name_last;
  stringstream input_line;
  cout << "Geben Sie bitte Ihren Namen (Vor- und Nachnamen) ein: ";
  getline(cin,name);
  input_line.str(name);
  // Der Name wird nun zerlegt
  input_line >> name_first;
  cout << "Vorname:t" << name_first << endl;
  input_line >> name_last;
  cout << "Nachname:t" << name_last << endl;
  input_line.clear();
  return 0;
}
5.3 TESTFRAGEN                                                              41



5.3    Testfragen
  1. Welche Klasse bietet uns C++ zur Verarbeitung von Zeichenketten an ?
  2. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Zeichenketten ?
                        o           u
  3. Wof¨ r ist die Anweisung using namespace std n¨ tzlich ?
        u                                          u
  4. M¨ ssen wir selber Speicherplatz f¨ r C++ Zeichenketten (Strings) reser-
       u                               u
     vieren ?
  5. Wie k¨nnen wir einen String, sagen wir mit der Zeichenkette ”Das ist eine
           o
     gute Frage”, initialisieren ?
  6. Wie k¨nnen wir zwei Strings, ihren Vor- und Nachnahmen, miteinander
           o
     verbinden ?
  7. Mit welcher string Funktion kann ich Zeichenketten miteinander verglei-
     chen ?
  8. Schreiben sie eine Anweisung zum Vergleich der Klassen-Variable
     m std− >name last mit ihrem Nachnamen ?
  9. Mit welcher string Funktion kann ich Zeichenketten suchen ?
 10. Schreiben sie eine Anweisung zum Suchen ihres Vornamens in der Klassen-
     Variable m std− >name first ?
 11. Mit welcher string Funktion kann ich Teile in Zeichenketten erstetzen ?
 12. Wie k¨nnen wir die L¨nge von Strings ermitteln ?
          o              a
 13. Schreiben sie die Anweisungen, um ihren Nachnamen in die Zeichenkette
     ”JAMES BOND” nach ”JAMES” einzuf¨ gen ?u
 14. Was passiert, wenn ihr Nachname l¨nger als ”BOND” ist ?
                                      a
 15. Mit welcher string Funktion k¨nnen wir Zeichen in einem String l¨schen ?
                                  o                                  o
 16. Wir haben gesehen, dass es verschiedene Daten-Typen f¨ r Zeichenketten
                                                          u
     in C, C++, MFC, .NET und Qt gibt. Zeichenketten geh¨ren zu den wich-
                                                         o
     tigsten Daten-Typen bei der Programmierung. Wie k¨nnen wir einen C++
                                                      o
     string in eine C Zeichenkette (char) umwandeln ?
 17. K¨nnen wir eine .NET Zeichenkette (String∧) in eine C++ Zeichenkette
       o
     (string) umwandeln ?
 18. Was ist ein stringstream ?
 19. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Stringstreams ?
                        o           u
Kapitel 6

Ein- und Ausgabe - II

Nachdem wir uns im Kapitel 3 bereits mit der Ein- und Ausgabe uber die¨
Standard-Ger¨te (Tastatur und Bildschirm) besch¨ftigt haben, geht es in diesem
             a                                 a
Teil um die Dateiverarbeitung.



6.1     Die fstream Klassen
Abb. 6.1 zeigt die Hierarchie der fstream Klassen.

                                     ios


                    istream                          ostream


                                  iostream


                    ifstream                         ofstream


                                  fstream

                     Abbildung 6.1: Die fstream Klassen

Diese sind von den bereits bekannten ios stream Klassen abgeleitet.

                                      42
6.2 ARBEITEN MIT FILE-STREAMS                                               43



   • ifstream: ist von istream abgeleitet f¨ r das Lesen von Dateien.
                                           u

   • ofstream: ist von ostream abgeleitet f¨ r das Schreiben von Dateien.
                                           u

   • fstream: ist von iostream abgeleitet f¨ r das Lesen und Schreiben von Da-
                                           u
     teien.


6.2     Arbeiten mit File-Streams

6.2.1    File-Streams anlegen
Er¨ffnungsmodus: Um eine Datei benutzen zu k¨nnen, muss diese zun¨chst
  o                                               o                      a
ge¨ffnet werden. Daf¨ r gibt es verschiedene M¨glichkeiten (siehe Tab. 6.1).
  o                u                         o

 Flag            Funktion
 ios::in         Eine (existierende) Datei wird zum Lesen ge¨ffnet.
                                                            o
 ios::out        Eine Datei wird zum Schreiben ge¨ffnet.
                                                  o
                 Existierende Inhalte werden uberschrieben.
                                              ¨
 ios::app        Die neuen Inhalten werden an die existierenden angeh¨ngt.
                                                                     a
 ios::trunc                                        ¨
                 Eine bestehende Datei wird beim Offnen auf die L¨nge 0 gek¨ rzt.
                                                                  a          u
 ios::ate        Schreib- und Leseposition werden auf das Dateiende gesetzt.
 ios::binary     Schreib- und Leseoperationen werden im Bin¨rmodus ausgef¨hrt.
                                                             a              u

                   Tabelle 6.1: Er¨ffnungsmodi f¨ r Dateien
                                  o            u

Die default Werte sind:

   • ios::in f¨ r ifstream
              u

   • ios::out | ios::trunc f¨ r ofstream
                            u


6.2.2    File-Streams schließen
Wir wissen schon, dass es bei objekt-orientierten Sprachen immer zwei passende
Dinge gibt, z.B. Klassen-Konstruktoren und -Destruktoren. So ist zu erwarten,
dass es zu einer Methode ’Datei ¨ffnen’ (open()) auch eine Methode ’Datei
                                   o
schließen’ gibt (close()) (Tab. 6.4)


6.2.3    ¨
         Ubung: Eine einfache Kopierfunktion
                  ¨
In unserer ersten Ubung zur Dateiverarbeitung schreiben wir eine einfache Ko-
pierfunktion.
Exercise E6.2.3: Eine einfache file copy Funktion
44                                                 KAPITEL 6 EIN- UND AUSGABE - II



#include <iostream>    //   for using   cout
#include <fstream>     //   for using   ifstream / ofstream
#include <string>      //   for using   string
using namespace std;   //   namespace   for std functions

int main()
{
  //----------------------------------------------------------------
  ifstream input_file;                 // Instance of class ifstream
  input_file.open("input_file.txt");   // Open file "text_file.txt"
  string my_string;                    // Instance of class string
  input_file >> my_string;             // Reading a string from file
  cout << my_string.data() << endl;    // Output of string to screen
  //----------------------------------------------------------------
  ofstream output_file;                // Instance of class ifstream
  output_file.open("output_file.txt"); // Open file "text_file.txt"
  output_file << my_string;            // Writing a string to a file
  //----------------------------------------------------------------
  return 0;
}

Die Ein- >> und Ausgabeoperatoren << formatieren die Datentypen (z.B. int
       ¨
in der Ubung E6.2.3) entsprechend den Einstellungen der fstream Klasse. Diese
Einstellungen k¨nnen durch Flags ver¨ndert werden (siehe n¨chsten Abschnitt).
               o                    a                     a
Die main() Funktion kann auch mit einer Parameterliste (int argc, char
*argv[]) versehen werden. Die Anzahl der Parameter (argc) wird automatisch
erkannt. MIt jedem Leerzeichen in der Tastatureingabe entsteht ein neuer Ein-
gabeparameter (Abb. 6.2).

int main(int argc, char *argv[])
{
  ifstream input_file;                       //   Instance of class ifstream
  input_file.open(argv[1]);                  //   Open file, name from cin
  ofstream output_file;                      //   Instance of class ifstream
  output_file.open(argv[2]);                 //   Open file, name from cin
  return 0;
}

Die Benutzung der main Funktion mit Eingabeparametern ist in der folgenden
Abbildung zu sehen.




             Abbildung 6.2: Die main Funktion mit Parametern
6.2 ARBEITEN MIT FILE-STREAMS                                                  45



6.2.4    ¨
         Ubung: Ein einfacher Konverter
                                 ¨
Ihre Frage nach dem Sinn der Ubung 6.2.3 ist vollkommen berechtigt, wozu
ein Programm schreiben, um eine Datei zu kopieren. Das kann ich doch auch
mit dem Windows-Explorer oder mit cp file1 file2 machen. Richtig, aber
genauso funktionieren Kopierprogramme, Windows-Explorer ruft ’unser’ Ko-
                                                ¨
pierprogramm auf. Wenn wir auch nur kleine Anderungen in unserer Datei vor-
nehmen wollen (z.B. eine laufenden Nummer in jede Zeile einf¨ gen), kann uns
                                                                 u
der Windows-Explorer nicht mehr weiter helfen. Dies ist insbesondere dann
a
¨rgerlich, wenn die Datei ziemlich groß ist ... Auch hier sagen sie zu Recht, eine
Nummerierung in eine gr¨ßere Datei einf¨ gen, das kann ich z.B. auch mit EX-
                          o               u
                              ¨
CEL machen. In der n¨chsten Ubung schreiben wir einen kleinen Konverter, also
                     a
genau was EXCEL im Hintergrund macht, wenn wir eine neue Spalte einf¨ gen.  u
Exercise E6.2.4: Ein einfacher Konverter

int main()
{
  //----------------------------------------------------------------
  ifstream input_file;                 // Instance of class ifstream
  input_file.open("input.txt");        // Open file "text_file.txt"
  ofstream output_file;                // Instance of class ifstream
  output_file.open("output.txt");      // Open file "text_file.txt"
  //----------------------------------------------------------------
  char line[80];
  int i=0;
  while(input_file.getline(line,80))   // Loop condition
  {
    output_file << i << " " << line << endl;
    i++;                               // Incrementor (+1)
  }
  //----------------------------------------------------------------
  return 0;
}


Unser Konverter macht nichts anderes, als die Datei input.txt zu ¨ffen, nach-
                                                                  o
einander alle Zeilen lesen und am Anfang der Zeile eine Nummer (i) einzuf¨ gen
                                                                         u
und dann in die neue Datei output.txt zu schreiben.
                       ¨
Was ist neu bei dieser Ubung.

 C++ Ding      Was tut’s
 while()       eine Kontrollstruktur f¨ r Schleifen
                                      u
               (solange der Ausdruck in () wahr (true) ist
               wird die Schleife ausgef¨hrt)
                                       u
 i++           der Inkremetor (z¨hlt Eins hoch)
                                 a

                            Tabelle 6.2: C++ news
46                                           KAPITEL 6 EIN- UND AUSGABE - II



Alle benutzten fstream Methoden finden sie in Tab. 6.4.


6.2.5     Einschub: Erstes Arbeiten mit MS VC++
Wir haben den Editor von MS VC++ ja schon mehrfach benutzt, da die Syntax
                                                      ¨
des Quelltextes sehr sch¨n angezeigt wird (Abb. 6.3). Uberhaupt ist MS VC++
                        o
ein sehr sch¨nes Entwicklungssystem f¨ r Programmentwicklung ... Wir f¨ hren
            o                         u                                 u
    ¨
die Ubung E6.2.4 jetzt mal mit MS VC++ aus.




                       Abbildung 6.3: Der MS VC++ Editor

Standardm¨ßig werden folgende Einf¨rbungen benutzt f¨ r
         a                        a                 u

     • Keywords: Blau
     • Kommentare: Gr¨ n
                     u
     • Normaler Quelltext: Schwarz
     • Includes: Rot
6.2 ARBEITEN MIT FILE-STREAMS                                                      47



   • Zeichenketten: Rot


Ich bin mir ziemlich sicher, dass man in einem gut versteckten MS VC++ Menu-
punkt alles selber einstellen kann ...
Highlighting of sytax ... ist nur eines der sehr n¨ tzliches features (langsam gleiten
                                                  u
wir in IT slang ab). Um MS VC++ richtig nutzen zu k¨nnen, m¨ ssen wir
                                                                  o         u
ein sogenanntes Projekt anlegen (mal sehen, ob ihre Begeisterung danach noch
anh¨lt). Die Schritte f¨ r die Projekterstellung finden sie in der Anlage (Abschn.
    a                  u
12.4) ... Nachdem das Projekt angelegt ist, k¨nnen wir damit arbeiten.
                                                  o




                     ¨
      Abbildung 6.4: Ubersetzen sie das Projekt mit F7 (build solution)




                      Abbildung 6.5: Das Debug Verzeichnis
48                                            KAPITEL 6 EIN- UND AUSGABE - II



MSVS legt allerhand Zeug’s an. Das executable finden sie im Unterverzeichnis
Debug und kann nat¨ rlich mit einem Doppelklick gestartet werden. Wir starten
                  u
die Konsolenanwendung aus MSVS mit Ctrl-F5 (Abb. 6.6).




Abbildung 6.6: Starten der Konsolenanwendung mit Ctrl-F5 oder Menu-
Auswahl (Start without debugging)

                            ¨
Hier wartet schon die erste Uberraschung auf uns: pwd wird nicht erkannt und
wir werden aufgefordert eine Zeit einzugeben (Abb. 6.7).




                     Abbildung 6.7: Das Debug Verzeichnis

Was ist passiert ?

     • pwd ist ein Linux-Befehl, den kennt der Windows-Compiler nicht.
     • time gibt es auch als DOS-Befehl, hat aber eine ganz andere Bedeutung:
       nicht Ausgabe der Zeit sondern Zeit ¨ndern.
                                           a

Wir sehen also, dass unser Quellcode von verschiedenen Compilern unterschied-
lich interpretiert wird.
6.3 FILE-STREAMS UND KLASSEN                                                  49



.




               Abbildung 6.8: Der Windows bereinigte Quelltext

Sie sehen ’Sch¨nheit’ hat auch ihren Preis ... dennoch die Funktionalit¨t der MS
              o                                                        a
VC++ Entwicklungsumgebung, das muss man neidlos anerkennen, ist einfach
Klasse.


6.3     File-Streams und Klassen
Wir wollen eine Lesefunktion f¨ r die Klasse CStudent schreiben. Bevor wir
                                u
damit beginnen, m¨ ssen wir uns Gedanken uber eine geeignete Struktur f¨ r die
                    u                       ¨                            u
Darstellung eines CStudent Datensatzes in einer Datei machen. Der Vorschlag
f¨ r die Strukturierung von Datens¨tzen ist die Benutzung von Schl¨ sselw¨rtern
 u                                a                               u      o
zur Trennung von Datenbl¨cken, z.B.
                           o

#STUDENT
 $NAME_FIRST
  James
 $NAME_LAST
  Bond
 ...
#STOP

Wir benutzen zwei verschiedene Symbole f¨ r Schl¨ sselw¨rter:
                                        u       u      o
50                                             KAPITEL 6 EIN- UND AUSGABE - II



     • keyword # : zur Trennung von Datens¨tzen f¨ r eine Instanz von CStudent,
                                          a      u

     • subkeyword $ : zur Identifizierung der einzelnen Daten f¨ r die CStudent
                                                              u
       Instanz.

     • #STOP zeigt das Ende der Datenbasis an. (Eigentlich w¨re dies nicht
                                                             a
       n¨tig, da das Dateiende auch mit dem Parameter eof (end-of-file) ab-
        o
       gefragt werden kann. Wir werden aber sehen, dass mit #STOP einiges
       einfacher zu programmieren ist.)

Exercise E6.3: Implementierung der CStudent Lesefunktion


ios::pos_type CStudent::Read(ifstream& input_file)
{
  //----------------------------------------------------------------------
  string input_line;
  char buffer[256]; // MAX_LINE
  ios::pos_type position;
  //----------------------------------------------------------------------
  while(true)
  {
    position = input_file.tellg();
    input_file.getline(buffer,256);
    input_line = buffer;
    if(input_line.size()<1) // empty line
      continue;
    // Dealing with keywords
    if(input_line.find(’#’)!=string::npos) // keyword found
      return position;
    // Dealing with subkeywords
    if(input_line.find("$NAME_FIRST")!=string::npos)
    {
      input_file.getline(buffer,256);
      input_line = buffer;
      name_first = input_line;
    }
    if(input_line.find("$NAME_LAST")!=string::npos)
    {
      input_file >> name_last;
    }
    if(input_line.find("$subkeyword")!=string::npos)
    {
      input_file >> member;
    }
  }
  //----------------------------------------------------------------------
  return position;
}
6.3 FILE-STREAMS UND KLASSEN                                                  51



Der Lesealgorithmus funktioniert wird folgt: Nach dem Auffinden eines Schl¨ ssel-
                                                                            u
worts #STUDENT, wird in einer while Schleife nach subkeywords ($) gesucht,
wenn gefunden, werden der CStudent Instanz die Werte aus der Eingabedatei
zugewiesen (also die Namen). Wenn das n¨chste Schl¨ sselwort (#STUDENT
                                            a          u
oder #STOP) gefunden wird, geht’s mit der vorletzten Position raus aus der
Funktion. Die vorletzte position ist wichtig, damit die letzte Zeile sp¨ter noch-
                                                                       a
mal gelesen werden kann, um das Schl¨ sselwort auswerten zu k¨nnen ...
                                      u                          o
Die Implementierung der main Funktion, in der die CStudent::Read() Funktion
aufgerufen wird, ist im folgenden Block dargestellt.

#include <iostream>    //   for   using cout
#include <fstream>     //   for   using ifstream / ofstream
#include <string>      //   for   using string
#include "student.h"   //   for   using CStudents
using namespace std;   //   for   std functions

int main()
{
  //----------------------------------------------------------------
  // File handling
  ifstream input_file; // ifstream instance
  input_file.open("data_set.txt");
  if(!input_file.good())               // Check is file existing
  {
    cout << "! Error in STD::Read: file could not be opened" << endl;
    return 0;
  }
  input_file.seekg(0L,ios::beg);       // Rewind file
  //----------------------------------------------------------------
  CStudent* m_std = new CStudent();    // CStudent instance
  m_std->Read(input_file);
  //----------------------------------------------------------------
  input_file.close();
  return 0;
}

Die main Funktion besteht aus zwei Teilen, dem File-Handling und dem Aufruf
der Lesefunktion. Beim File-Handling wird der stream aus der Datei data set.txt
ge¨ffnet, anschließend erfolgt der Test, ob das File erfolgreich ge¨ffnet werden
  o                                                               o
konnte; wenn nicht, wir die main Funktion sofort beendet.
                       ¨
Was ist neu bei dieser Ubung.
Wir benutzen den Referenz-Operator & (Kapitel 7) als Parameter der Funktion
CStudent::Read(). Eine Referenz ist eigentlich nicht anderes als ein anderer
Bezeichner (Alias) f¨ r eine bereits existierende Instanz eines Objekts. Es kann
                    u
also mehrere solcher Referenzen geben und vor Benutzung einer Referenz muss
die Instanz des Objekts physikalisch (also speicherm¨ßig) vorhanden sein, sonst
                                                      a
’crashed’ unser Programm.
52                                             KAPITEL 6 EIN- UND AUSGABE - II



 C++ Ding                   Was tut’s
 ifstream& input file       eine Reference auf ein Objekt
                            wird in Kapitel 7 ausf¨ hrlich abgehandelt
                                                  u

                            Tabelle 6.3: C++ news


6.4     fstream Methoden
Die bisher benutzten fstream Methoden sind in der Tab. 6.4 zusammengestellt.

 Methode                   Funktion
 open()                    o
                           ¨ffnet die Datei
 good()                                         ¨
                           tested erfolgreiche Offnung der Datei
 seekg(pos,ios::beg)       geht zur Position pos in der Datei
 seekg(0L,ios::beg)        spoolt zum Dateianfang zur¨ ck
                                                       u
 tellg()                   merkt sich die aktuelle Position im stream
 getline(buffer,256)       holt eine Zeile der L¨nge 256 (Zeichen) aus dem stream
                                                 a
                           und kopiert diese in buffer
 close()                   schließt Datei
 >>                        Eingabeoperator f¨ r Dateien
                                              u
 <<                        Ausgabeoperator f¨ r Dateien
                                               u

                        Tabelle 6.4: fstream Methoden

Die string Auswertung spielt bei der Lesefunktion eine wichtige Rolle, daher ha-
ben wir uns wir uns im vorangegangenen Kapitel mit der string Klasse besch¨ftigt.
                                                                           a
6.5 TESTFRAGEN                                                               53



6.5    Testfragen
  1. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ?
                               u
  2. Was sind die C++ Klassen f¨ r das Lesen und Schreiben von Dateien ?
                               u
  3. Welchen Include ben¨tigen wir f¨ r das Arbeiten mit I/O File-Klassen ?
                        o           u
  4. Was sind die Standard-Flags f¨ r File-Streams (Lesen und Schreiben) ?
                                  u
  5. Mit welchem Flag k¨nnen wir zu schreibende Daten an eine existierende
                       o
     Datei anh¨ngen ?
              a
  6. Was ist der Unterschied zwischen ASCII- und Bin¨r-Formaten ?
                                                    a
  7. Mit welchem Flag k¨nnen wir Daten in einem Bin¨r-Format schreiben ?
                          o                         a
     Mit welcher Anweisung wird ein File ge¨ffnet ? Mit welcher Anweisung
                                           o
     wird ein File geschlossen ?
  8. Was bewirken die Stream-Operatoren << und >> ?
  9. Wie k¨nnen wir mit Dateinamen in unserem Hauptprogramm main(...)
           o
     arbeiten ?
 10. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen
                         o           u                                u
     Eingabe-Strom ?
 11. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen
                         o           u                                u
     Ausgabe-Strom ?
 12. F¨ r die Erstellung einer Datenbank ist es wichtig einzelnen Datens¨tze zu
       u                                                                a
     trennen. Wie k¨nnen wir soetwas in der Datenbank-Datei bewerkstelligen
                     o
     ?
 13. Ist es wichtig das Ende einer Datenbank-Datei, z.B. mit einem Schl¨ ssel-
                                                                       u
     wort #STOP, zu markieren ?
                          o          u             ¨
 14. Mit welcher Abfrage k¨nne wir pr¨ fen, ob die Offnung einer Datei erfolg-
     reich war ?
 15. Mit welcher Anweisung k¨nnen wir die aktuell gelesene Position in einer
                             o
     ge¨ffneten Datei abfragen ?
       o
 16. Mit welcher Anweisung k¨nnen wir zu einer bestimmten Position in einer
                             o
     ge¨ffneten Datei springen ?
       o
 17. Mit welcher Anweisung k¨nnen wir eine komplette Zeile aus ge¨ffneten
                            o                                    o
     Datei auslesen ?
Kapitel 7


Referenzen und Zeiger

Referenzen und Zeiger (pointer), d.h. die Symbole & und * sind uns bereits
mehrfach begegnet, z.B. in der Parameterliste der main() Funktion ... Generell
k¨nnen Zeiger und Referenzen als einfache Variable, Parameter oder R¨ ckgabe-
 o                                                                   u
wert (return) einer Funktion auftauchen.

        ¨
In der Ubung E6.3 haben wir bereits mit Referenzen gearbeitet und festgestellt,
dass Referenzen eigentlich nichts anderes als andere Bezeichner (Alias) f¨ r eine
                                                                         u
bereits existierende Instanz eines Objekts sind. Es kann also mehrere solcher
Referenzen geben. Bei der Definition eines Zeigers wird also kein neuer Spei-
cher reserviert. Die Instanz des Objekts muss physikalisch (also speicherm¨ßig)
                                                                            a
nat¨ rlich vorhanden sein, sonst ’verabschiedet’ sich unser Programm gleich wie-
   u
der.




            x                   &ref_x                             x
                                Referenz auf
                                das Objekt
                                                                   y


                Objekt
                im Speicher

                    Abbildung 7.1: Referenzen auf Objekte


                                       54
7.1 REFERENZEN                                                                  55



7.1     Referenzen

7.1.1    Das Call-by-reference Prinzip - Referenzen als Pa-
         rameter

Def: Eine Referenz ist nichts anderes als ein anderer Name (Alias) f¨ r ein bereits
                                                                      u
existierendes Objekt. Bei der Definition einer Referenz wird also kein neuer
Speicherplatz f¨ r das Objekt belegt (außer nat¨ rlich die 4 Byte f¨ r die Referenz
               u                                u                  u
selbst).
Die Abb 7.2 soll das Konzept des Referenzierens noch einmal verdeutlichen.

   • x ist die Instanz eines Datentyps T

   • &ref x ist eine Referenz (Verweis) auf x

              ¨
In der ersten Ubung sehen die Definition von Referenzen und Zeigern im Quell-
text
¨
Ubung: E7.1.1

double x = 1.23456789;
double* ptr_x;
double& ref_x = x; // initialisation is needed

                                 ¨
Die Bildschirmausgabe der ersten Ubung zeigt Folgendes:




                    Abbildung 7.2: Referenzen auf Objekte

Eine Referenz (ref x) muss bei der Definition initialisiert werden (mit x), sonst
bekommen sie eine Fehlermeldung beim Kompilieren.
Der Referenztyp-Parameter (&) ist ein Aliasname f¨ r das ’richtige’ Argument.
                                                     u
Beim Aufruf der Funktion wird der Referenz-Parameter mit dem Objekt initia-
lisiert. Die Funktion arbeitet also direkt mit dem von außen ubergebenen Argu-
                                                             ¨
                                                          ¨
ment. Das ’Call-by-reference’ Prinzip ist sozusagen eine Ubergabe-von-Außen.
Wir schauen uns dies mal an bei der CStudent-Lesefunktion aus der letzten
Vorlesung.
¨
Ubung: E7.1.1
56                                          KAPITEL 7 REFERENZEN UND ZEIGER



Definition:
  CStudent::Read(ifstream& ref_input_file)
Aufruf:
  ifstream input_file;
  CStudent* m_std = new CStudent();    // CStudent instance
  m_std->Read(input_file);

Was passiert ? Beim Aufruf der Lese-Funktion Read wird die Adresse des ifstream
Objekts (input file) an die Funktion ubergeben. Das heisst die Lese-Funktion
                                        ¨
arbeitet intern mit dem ’richtigen’ Objekt. ’Call-by-reference’ Prinzip erm¨glicht
                                                                           o
es also der Funktion einen Zugriff auf Daten des Aufrufers.
Beim sogenannten ’Call-by-value’ Prinzip k¨nnen Funktions-Argumente inner-
                                          o
halb der Funktion nicht ge¨ndert werden.
                          a


7.1.2    Referenzen als Ruckgabe-Wert
                         ¨
Referenzen auf Objekte k¨nnen auch R¨ ckgabe-Werte von Funktionen sein.
                        o           u
¨
Ubung: E7.1.2 (aus [5])

Definition:
  string& message()
  {
    static string m_str("Vorsicht Speicher-Falle");
    return m_str;
  }
Aufruf:

!!! Das Objekt muss nach dem Verlassen der Funktion noch existieren
                       ¨
Was ist neu bei dieser Ubung.

 C++ Ding      Was tut’s
 static        Speicherklasse: der Speicher f¨ r das Objekt bleibt w¨hrend
                                              u                     a
               der gesamten Programmausf¨ hrung bestehen,
                                             u
               wird in Kapitel 7.3 ausf¨ hrlich abgehandelt.
                                       u

                            Tabelle 7.1: C++ news




7.2     Zeiger
Zeiger sind eine der Grundideen moderner Programmiersprachen. Dabei arbei-
tet man nicht direkt mit den Daten-Bl¨cken im Speicher sondern mit deren
                                       o
Adressen. Dies macht insbesondere Sinn, wenn es um große Daten-Objekte geht
7.2 ZEIGER                                                                      57



oder bei Objekten, die erst zur Laufzeit angelegt werden (z.B. Vektoren, Li-
sten, Strings). Das Klassen-Prinzip unterst¨ tzt die Zeigertechnik optimal, da
                                             u
die Klasse ihre Daten ja selber verwaltet (siehe Klassenkonstruktur) Der Zeiger
(pointer) auf ein Objekt repr¨sentiert dessen Adresse und Daten-Typ.
                              a


7.2.1    Definition von Zeigern
                  ¨
Die nachfolgende Ubung zeigt, wie wir Zeiger definieren und mit ihnen arbeiten
k¨nnen. F¨ r den Zugriff auf Zeiger gibt es den sogenannten Verweisoperator ’*’.
 o       u
¨
Ubung: E7.2 (aus [5])

int main()
{
  int i, *ptr_i;   //   Definitionen
  i = 100;         //   Zuweisung
  ptr_i = &i;      //   Dem Zeiger wird die Adresse der integer Variable i zugewiesen
  *ptr_i += 1;     //   Die integer Variable i wird um Eins erh¨ht (i += 1;)
                                                               o
}


⇒Geben sie Werte und Adressen der Integer-Variable i und den Zeiger auf i
(i ptr) aus.
Unabh¨ngig vom Daten-Typ ist der ben¨tigte Speicher f¨ r eine Zeigervariable
      a                                o                u
immer gleich groß - der zur Speicherung ben¨tigte Platz f¨ r die Adresse des
                                            o              u
Objekts (4 Byte auf einer 32-Bit-Rechner-Architektur, siehe auch Abb. 7.2).
                       ¨
Was ist neu bei dieser Ubung.

 C++ Ding      Was tut’s
 *ptr          Verweisoperator (un¨r: ein Operand)
                                  a
 i*i           Multiplikations-Operator (bi¨r: zwei Operanden)
                                           a

                        Tabelle 7.2: C++ news: Operatoren




7.2.2    NULL Zeiger

Wir haben gesehen, dass Referenzen auf Daten-Objekte zwingenderweise in-
itialisiert werden m¨ ssen (sonst streikt der Kompiler). Zeiger m¨ ssen eigentlich
                      u                                           u
nicht initialisiert werden, ihnen wird bei der Definition eine ’vern¨ nftige’ Adres-
                                                                   u
se zu gewiesen. Dies bedeutet noch lange nicht, dass sich hinter dieser Adresse
etwas Vern¨ nftiges verbirgt. Daher ist es ratsam, auch Zeiger zu initialisieren,
             u
um Nachfragen zu k¨nnen, ob sie tats¨chlich auf existierende Objekte zeigen.
                        o                a
Zum Initialisieren von Pointern gibt es den NULL-Zeiger.
58                                          KAPITEL 7 REFERENZEN UND ZEIGER



double* ptr_x = NULL;
ptr_x = &x;
if(!ptr_x) cout << "Warning: ptr_x does not have a meaningful adress";

Der linke Operand der Operators = muss immer auf eine ’sinnvolle’ Speicher-
stelle verweisen. Dieser wird daher auch als so genannter L-Wert (L(eft) value)
bezeichnet. Wenn eine Fehlermeldung ’wrong L-value’ erscheint, wissen sie, dass
keine ’sinnvolle’ Adresse vergeben wurde, dies spricht wiederum f¨ r eine Initia-
                                                                 u
lisierung von Zeigern mit Zero-Pointer.


7.2.3    Zeiger als Parameter
Der Verweisoperator ist uns unl¨ngst schon mal begegnet bei der erweiterten
                               a
main() Funktion mit Eingabeparametern: int main(int argc, char* argv[])


7.3     Zeiger und Arrays
Wie bereits gesagt, die Verzeigerungs-Technik ist eine der Besonderheiten von
objekt-orientierten Sprachen, wie z.B. von C++. Mit solchen Pointern k¨nnen
                                                                        o
wir auch gr¨ßere Daten-Objekte wie Vektoren verwalten. Die zentrale Idee ist:
            o
Wenn Startpunkt (id Adresse) und L¨nge des Vektors bekannt sind, wissen wir
                                      a
eigentlich alles und k¨nnen auf alle Vektor-Daten zugreifen.
                      o


7.3.1    Statische Objekte
Bei der Einf¨ hrung der String-Klasse hatten wir bereits mit Zeichenketten zu
            u
tun. Aus der Sicht des Speichers ist eine Zeichenkette ein Vektor der eine be-
stimmte Anzahl von Zeichen enth¨lt. Vektoren k¨nnen nat¨ rlich f¨r (fast) alle
                                 a              o          u     u
Datentypen definiert werden. Im n¨chsten Kapitel (8) besch¨ftigen wir uns mit
                                  a                         a
sogenannten Containern, damit k¨nnen z.B. Vektoren, Listen etc. f¨ r ganze
                                  o                                  u
Klassen generiert werden.

char Zeichenkette[80];
int iVektor[50];
double dVektor[50];


7.3.2    Dynamische Objekte
Bisher haben wir uns fast ausschließlich mit Datentypen besch¨ftigt, deren
                                                                 a
Speicherbedarf bereits w¨hrend der Kompilierung fest steht und reserviert wird
                        a
(bis auf Strings-Objekte). Es gibt aber auch die M¨glichkeit, den Speicherbe-
                                                  o
darf w¨hrend der Programmausf¨ hrung zu ¨ndern - dies geht mit dynamischen
       a                        u         a
Daten-Objekten. Die werden wir folgt deklariert.
7.4 SUMMARY                                                                   59



char* Zeichenkette;
int* iVektor;
double* dVektor;


Nun m¨ ssen wir uns allerdings selber um die Speicherreservierung k¨ mmern.
       u                                                              u
                                                               ¨
Dies erfolgt mit dem new-Operator und wird in der n¨chsten Ubung gezeigt.
                                                       a
Wir ahnen schon, wenn es etwas zum Vereinbaren von Speicher gibt, muss es
wohl auch das Gegenst¨ ck - freigeben von Speicher - geben. Nat¨ rlich habe sie
                       u                                       u
Recht. Dies erledigt der delete-Operator.

double* dVektor;
dVektor = new double[1000];
delete [] dVektor;


Die Anwendung beider Operatoren zum Speichermanagement sowie eine M¨glich-
                                                                      o
                                                                   ¨
keit, den verbrauchten Speicher zu messen, werden in der folgenden Ubung ge-
zeigt.
¨
Ubung: E7.3.2

#include <iostream> // for using cout
#include <malloc.h> // for using malloc_usable_size
using namespace std;

int main()
{
  char* Zeichenkette;            // Definitions
  long size_memory;              // Auxiliary variable for memory size
  Zeichenkette = new char[1000]; // Memory allocation
  size_memory = malloc_usable_size(Zeichenkette); // calculation of memomry
  delete [] Zeichenkette;        // Memory release
  return 0;
}

HomeWork: HW7.3.2
Schreiben sie ein kleines Programm, mit der sie den ben¨tigten Speicher ermit-
                                                        o
teln k¨nnen und pr¨ fen sie, ob die Freigabe des Speichers funktioniert hat.
      o             u
Zeiger k¨nnen auch verschachtelt werden: Zeiger auf Zeiger ... Damit lassen sich
        o
mehrdimensionale Datenstrukturen schaffen, z.B. Matrizen.



7.4     Summary
Das Verstehen und Arbeiten mit Zeigern und Referenzen ist nicht ganz ein-
fach und braucht eine ganze Zeit der praktischen Anwendung. Der *Operator
60                                          KAPITEL 7 REFERENZEN UND ZEIGER



                  **matrix

                     *matrix[0] *matrix[1] *matrix[2]



                                                *matrix[1][0]
                                                *matrix[1][1]
                                                *matrix[1][2]


          Abbildung 7.3: Die Definition einer Matrix mittels Pointer


kann beispielsweise als Zeiger auf etwas und gleichzeitig f¨ r dynamische Vek-
                                                            u
toren benutzt werden. Dies scheint zun¨chst absolut verwirrend zu sein, beim
                                        a
            ¨
genaueren Uberlegen aber: * ist lediglich die Startadresse f¨ r den Vektor. Mer-
                                                            u
ken sie sich erst einmal nur, dass es geschickter (und schneller) ist, nicht mit
den Daten-Objekten direkt sondern mit Verweisen darauf (also deren Adres-
sen) zu arbeiten. Die nachfolgende Tabelle und Abbildung sollen das Thema
’Referenzen und Zeiger’ noch einmal illustrieren.

 Syntax               Bedeutung
 double x             Definition einer doppelt-genauen Gleitkommazahl
                      (Speicherbedarf 8 Byte)
 double* ptr          Zeiger auf eine doppelt-genauen Gleitkommazahl
                      (Speicherbedarf 4 Byte)
 double& ref          Referenz auf eine doppelt-genaue Gleitkommazahl
                      (Speicherbedarf 4 Byte)
 double* dVektor      Zeiger auf einen Gleitkommazahl-Vektor

                      Tabelle 7.3: Zeiger und Referenzen


                              ptr_x                 x



                                         &x                 x
                     &ptr_x             ptr_x             *ptr_x

             Adresse von ptr_x        Adresse von x
                                                        Wert von x
                                      Wert von ptr_x

               Abbildung 7.4: Referenzen und Zeiger (nach [5])
7.5 TESTFRAGEN                                                               61



7.5    Testfragen
  1. Was ist &x ? (x ist ein beliebiger Datenobjekt T, z.B. eine Gleitkomma-
     zahl: double x)
  2. Was ist eine Referenz &ref?
  3. Was bedeutet die Anweisung: &ref = x?
  4. Erkl¨ren sie kurz (mit eigenen Worten) das Zeiger-Konzept in C++?
         a
  5. Was bewirkt der NULL Zeiger, d.h. *ptr = NULL ?
  6. Was bedeutet die Anweisung: ptr = x?
  7. M¨ ssen Referenzen (&) und Zeiger (*) auf Daten-Objekte initialisiert wer-
       u
     den ?
  8. Was bewirkt die Definition long l[1000] speichertechnisch ?
  9. Wie groß ist der Speicherbedarf des statischen Datenobjekts long l[1000]
     ?
 10. Wie groß ist der Speicherbedarf des dynamische Datenobjekts long* ptr l
     = new long[1000] ?
 11. Woher kommt der Unterschied (4 Byte auf einem 32Bit Rechner) im
     Speicherbedarf zwischen statischen und dynamischen Datenobjekten.
 12. Zusatzfrage: Was bedeutet die Definition **ptrptr (Zeiger auf Zeiger), was
     f¨ r ein Datenkonstrukt entsteht ?
      u
Kapitel 8

Container

Wir haben bereits mit der String-Klasse gesehen, dass C++ neben der Ba-
sisfunktionalit¨t einer Programmiersprache auch sehr n¨ tzliche Erweiterungen,
               a                                      u
wie das Arbeiten mit Zeichenketten, anbietet. Diese Erweiterungen geh¨ren o
zum Standard von C++, geh¨ren also zum ’Lieferumfang’ des Compilers dazu
                              o
und heißen daher auch Standard-Klassen. Diese Klassen bilden die sogenannte
Standard-Bibliothek (STL - STandard Library).
In diesem Kapitel besch¨ftigen wir uns mit sogenannten Containern mit de-
                          a
nen Daten organisiert, gespeichert und verwaltet werden k¨nnen, z.B. Listen
                                                            o
und Vektoren. In der Abb. 8.1 sind die wichtigsten Elemente der Container
dargestellt. Der Begriff Container soll verdeutlichen, dass Objekte des gleichen
Typs z.B. in einer Liste gespeichert werden. Und wie immer bei Klassen, werden
nat¨ rlich auch die Methoden f¨ r den Zugriff oder die Bearbeitung von diesen
   u                            u
Objekten bereitgestellt. Die Speicherverwaltung f¨ r Container-Elemente erfolgt
                                                  u
dynamisch zur Laufzeit (siehe Kapitel Speicherverwaltung). Die Abb. 8.1 zeigt
auch, welche verschiedenen Typen von Containern es gibt:

Sequentielle Container: sind z.B. Vektoren, Listen, Queues und Stacks. Vek-
    toren sind Felder (arrays) in denen die einzelnen Elemente nacheinander
    angeordnet sind. Bei einer Liste kennt jedes Element nur seine Nach-
    barn (Vorg¨nger- und Nachfolgeelement). Queues (wir kennen dies von
                a
    Druckern) sind Warteschlangen, die nach dem FIFO-Prinzip (first in, first
    out) funktionieren. Das heißt, dass zuerst eingef¨ gte Element wird auch
                                                     u
    zuerst verarbeitet (z.B. Druckjobs). Stacks sind sogenannte Kellerstapel,
    die nach dem LIFO-Prinzip (last in, first out) funktionieren. Das bedeutet,
    das zuletzt eingef¨ gte Element wird zuerst verarbeitet.
                      u
Assoziative Container: sind z.B. Maps (Karten) und Bitsets. Die Elemen-
    te sind nicht wie bei sequentiellen Container linear angeordnet sondern
    in bestimmtem Strukturen (z.B. Baumstrukturen). Dies erm¨glicht einen
                                                                 o
    besonders schnellen Datenzugriff, der uber eine Verschl¨ sselung erfolgt.
                                         ¨                 u

                                      62
8.1 SEQUENTIELLE CONTAINER                                                        63



                                  Container




                  sequential                         associative
                  Container                          Container




         Vectors     Stacks     Queues        Sets      Maps       Bitsets

      Abbildung 8.1: C++ Container (Bildquellen: www.prachensky.com)


Die Besonderheit der C++ Container ist die dynamische Speicherverwaltung.
Das heisst, Einf¨ gen und Entfernen von Container-Elementen ist sehr einfach,
                u
wir brauchen uns nicht selbst um das Speichermanagement zu k¨ mmern. Dies
                                                              u
ubernehmen die Konstruktoren und Destruktoren (siehe Abschnitt 4.4) der je-
¨
weiligen Container-Klasse.


8.1      Sequentielle Container
Ein weiterer Grund f¨ r die Bereitstellung von Containern ist, dass die Elemente
                       u
gemeinsame Datentypen und Methoden haben. Der Datentyp T eines Containers
ist nat¨ rlich eine (beliebige) Klasse. Die Tab. 8.1 listet die Klassentemplates f¨ r
       u                                                                          u
einige sequentielle Container sowie die ben¨tigen Include-Files auf.
                                              o
Ein Klassentemplate ist nichts weiter als eine formale Beschreibung der Syntax.
64                                                         KAPITEL 8 CONTAINER



                       Klassen-Template        Include-Files
                       vector<T,Allocator>     <vector>
                       list<T,Allocator>       <list>
                       stack<T,Container>      <stack>
                       queue<T,Container>      <queue>

             Tabelle 8.1: Klassentemplates f¨ r sequentielle Container
                                            u

     • vector: Schl¨ sselwort
                   u
     • < ... >: Parameterliste
     • T: erster Parameter, Datentyp des Vektors
     • Allocator: zweiter Parameter, Speichermodell des Vektors

Die Methoden sequentieller Container sind sehr einfach, intuitiv zu bedienen
und sie sind gleich f¨ r Vektoren, Listen etc. Ein Auswahl der wichtigsten ge-
                     u
meinsamen Methoden finden sie in der nachfolgenden Tabelle.

           Methode          Bedeutung
           size()           Anzahl der Elemente, L¨nge de Containers
                                                    a
           push back(T)     Einf¨ gen eines Elements am Ende
                                u
           pop back()       L¨schen des letzten Elements
                             o
           insert(p,T)      Einf¨ gen eines Elements vor p
                                u
           erase(p)         L¨schen des p-Elements (an der Stelle p)
                             o
           clear()          L¨scht alle Elemente
                             o
           resize(n)        ¨
                            Andern der Containerl¨nge
                                                  a

                 Tabelle 8.2: Methoden f¨ r sequentielle Container
                                        u



8.2       Vectors
The standard vector is a template defined in namespace std and presented in
<vector>. The vector container is introduced in stages: member types, iterators,
element access, constructors, list operations etc. The structure of a vector is
illustrated in Fig. 8.2.




                       Abbildung 8.2: Structure of vectors

Following lines are necessary in order to use the vector container in your sources
code.
8.2 VECTORS                                                                   65



#include <vector>
using namespace std;

Types: Very different types can be used in vectors. A vector e.g. of integers can
be declared in this way.

// Declaration and construction
  vector<int> v;

Constructors: With the above source code a vector of integer types is constructed
as well.
Stack operators: The functions push back and pop back treat the vector as a
stack by adding and removing elements from its end.

// Input elements to vector
  for(i=0;i<9;i++)
  {
    v.push_back(i+1);
  }

Iterators: Iterators can be used to navigate containers without the programmer
having to know the actual type to identify the elements, e.g. for inserting and
deleting elements. A few number of key functions allow to step through the
elements, such as begin() pointing to first element and end() pointing to the
one-past-last element. An example of a loop through all vector elements using
the iterator is given below.

// Navigating vector elements
  for(vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
  {
    cout << *it << ’n’;
  }

Vector elements can be addressed directly by element number. Fast data access
is an advantage of vectors.




                   Abbildung 8.3: Access to vector elements

In contrast, vectors are not as flexible as lists. Deleting and adding of elements
within the vector is complicated (Fig. 8.4).
66                                                       KAPITEL 8 CONTAINER




                      Abbildung 8.4: Deleting elements


Programming exercises

8.2.1    Defining vectors
In the first exercise we just define a vector and insert some elements into it in
order to show the concept.
Exercise 8.2.1

#include <iostream>   // for using cout
#include <vector>     // for using vectors
using namespace std; // for std functions
void main()
{
  //-------------------------------------------------------
  cout << "E81 - Working with vectors" << endl;
  //-------------------------------------------------------
  vector<int>my_vector;   // Declaration of vector
  my_vector.push_back(1); // Inserting an element to vector
  my_vector.push_back(3);
  my_vector.push_back(5);
  for(int i=0;i<(int)my_vector.size();i++)
  {
    cout << my_vector[i] << endl; // Access to vector elements
  }
  //-------------------------------------------------------
}


8.2.2    Vectors and data base
                ¨
In der n¨chsten Ubung werden einige Dinge, die wir bisher gelernt haben, zu-
        a
sammenbringen. Sie werden sehen, dass ’gut’ programmierte Dinge einfach ’zu-
sammengebaut’ werden k¨nnen: Objekte (Kapitel 4), IO-Methoden (Kapitel 6),
                        o
Stringverarbeitung (Kapitel 5).
8.2 VECTORS                                                                67



Exercise 8.2.2

#include <iostream>    //   for   using cout
#include <fstream>     //   for   using ifstream / ofstream
#include <string>      //   for   using string
#include <vector>      //   for   using vectors
#include "student.h"   //   for   using CStudents
using namespace std;   //   for   std functions

#define MAX_ZEILE 256
bool STDRead(ifstream&);

int main()
{
  //----------------------------------------------------------------
  cout << "E82: an object-oriented DB read function" << endl;
  //----------------------------------------------------------------
  // 1 File handling
  ifstream input_file; // ifstream instance
  input_file.open("data_base.txt");
  if(!input_file.good())               // Check is file existing
  {
    cout << "! Error: input file could not be opened" << endl;
    return 0;
  }
  //----------------------------------------------------------------
  // 2 Read data base
  STDRead(input_file);
  //----------------------------------------------------------------
  return 0;
}

Unser Programm besteht aus drei gekapselten Teilen:

   • main(): Das Hauptprogramm: die Steuerzentrale, hier wir i.W. das Da-
     teimanagement erledigt.
   • STDRead(ifstream&): Die ubergeordnete Lesefunktion f¨ r die komplet-
                                ¨                            u
     te Datenbank, hier befindet sich eigentlich nur eine Schleife, welche die
     Objekt-Lesefunktion aufruft, solange Daten in der Datei vorhanden sind.
   • CStudent::Read(ifstream): Die Objekt-Lesefunktion, die liest die ei-
     gentlichen Daten f¨ r jeden Datensatz aus der Datenbankdatei.
                       u

            ¨
Der einzige Ubergabeparameter ist die Datenbank-Datei: std file.
68                                                     KAPITEL 8 CONTAINER



Exercise 8.2.2 continued

/**************************************************************************
STDLib-Method:
Task: Reading all STD objects
06/2009 OK Implementation
**************************************************************************/
bool STDRead(ifstream& std_file)
{
  //-1--------------------------------------------------------------------
  char line[MAX_ZEILE];
  string line_string;
  ios::pos_type position;
  vector<CStudent*>std_vector;
  CStudent* m_std = NULL;
  //----------------------------------------------------------------------
//OK STDDelete();
  //-2--------------------------------------------------------------------
  // rewind the file
  std_file.seekg(0,ios::beg);
  //-3--------------------------------------------------------------------
  // OBJ reading, keyword loop
  cout << "STDRead" << endl;
  while (!std_file.eof())
  {
    std_file.getline(line,MAX_ZEILE);
    line_string = line;
    if(line_string.find("#STOP")!=string::npos)
      break;
    if(line_string.find("#STUDENT")!=string::npos)
    {
      m_std = new CStudent();
      position = m_std->Read(std_file); // from E63
      std_vector.push_back(m_std);
      std_file.seekg(position,ios::beg);
    }
  } // eof
  //----------------------------------------------------------------------
  cout << "Number of data sets: " << std_vector.size() << endl;
  return true;
}



8.2.3    Updating your data base entry

Homework 8.2.3a: Please update your data base entries and send it by mail to
me (olaf.kolditz@ufz.de).
Homework 8.2.3b: Please write a print function for the CStudent class.
8.3 LISTS                                                                         69



8.3      Lists
A list is a sequence optimized for insertion and deletion of elements. They allow
a very flexible organization of elements. But the price for flexibility is a relatively
slow access to data.
List provides bidirectional iterators (Fig. 8.3). This implies that a STL list will
typically be implemented using some form of a doubly-linked list.




                         Abbildung 8.5: Structure of lists

Following lines are necessary in order to use the list container in your sources
code.

#include <list>
using namespace std;

Types: All data types are possible for lists, e.g. a class.

// Declaration
list<CStudent*> std_list;
list<int> int_list;

Constructors: With the above source code a list for class instances is constructed
as well.
Stack operators: Lists provide same typical member functions as for vectors.

// Insert list elements at end
CStudent* m_std;
my_list.push_back(m_std);

Iterators: Again iterators can be used to navigate lists. We show an example for
deleting a specific element from the list. Identification of the list element is by
name (Fig. 8.6).




                      Abbildung 8.6: Deleting list elements

The following exercise shows how conveniently we can deal with lists, i.e. in
order to sort, reverse, merge, and unify lists. The unifying function removes
70                                                        KAPITEL 8 CONTAINER



multiple entries from lists, which is a very nice tool in order to clean a data
base.
Exercise 8.3

#include <iostream> // for using cout
#include <list>      // for using lists
using namespace std; // for std functions
typedef list<int>INTLIST;
void display(list<int>);

int main()
{
  int i;
  list<int>list1;
  INTLIST list2;
  // Filling the list with random numbers
  for(i=0;i<4;i++)
  {
    list1.push_back(rand()%10);
    list2.push_back(rand()%10);
  }
  display(list1); // Display the list
  display(list2);
  // Putting first element to the end as well
  list1.push_back(list1.front());
  list1.reverse();     // Reverse list
  list1.sort();        // Sort list
  list1.merge(list2); // Merge two lists
  list1.sort();        // Remove multiple entries #1
  list1.unique();      // Remove multiple entries #2
  return 0;
}

void display(list<int>my_list)
{
  int i;
  list<int>::const_iterator iterator;
  iterator = my_list.begin();
  while(iterator != my_list.end())
  {
    i = *iterator;
    cout << i << endl;
    ++iterator;
  }
}

The concept of the data base read function is illustrated in Fig. 8.7.
8.4 TESTFRAGEN                                                             71




                  main()

                  Files
                  STDRead(ifstream&)         STD::Read()


                   Abbildung 8.7: Data base read concept

The last exercise shows how we can delete entries from the students data base
(i.e. people we don’t like)

// Deleting list elements
CStudent* m_std = NULL;

list<CStudent*>::const_iterator p = std_list.begin();
while(p!=std_list.end())
{
  m_std = *p;
  if(m_std->GetStudentName()=="James Bond")
  {
    my_list.remove(*p);
    break;
  }
    ++p;
}
// Deleting repeated entries
std_list.unique();



8.4     Testfragen
  1. Was sind C++ Container ?
  2. Welche Typen von C++ Containern kennen sie ?
  3. Worin besteht der Unterschied zwischen sequentiellen und assoziativen
     Containern ?
  4. Welche sequentiellen Container kennen sie ?
  5. Erkl¨ren sie die Syntax des Vektor-Containers: vector<int>my vector .
         a
  6. Was ist der Unterschied zwischen Vektoren und Listen ?
  7. Was sind die Gemeinsamkeiten von Vektoren und Listen ?
  8. Welcher Include ist notwendig f¨ r das Arbeiten mit Vektoren ?
                                    u
  9. Welcher Include ist notwendig f¨ r das Arbeiten mit Listen ?
                                    u
72                                                      KAPITEL 8 CONTAINER



 10. Ben¨tigen wir den Zusatz (Namensraum) using namespace std, wenn ja
        o
     warum ?
 11. Mit welcher Instruktion k¨nnen Elemente in Vektoren und Listen einf¨ gen
                              o                                         u
     ?
 12. Wo werden sequentielle Container-Elemente mit der Instruktion push back(T)
     eingef¨ gt ?
           u
 13. Mit welcher Anweisung k¨nnen wir die L¨nge von sequentiellen Container-
                            o              a
     Elementen bestimmen ?
 14. Mit welcher Anweisung k¨nnen wir einen Vektor platt machen (d.h. alle
                            o
     Elemente l¨schen) ?
               o
 15. Wie k¨nnen wir auf ein Vektor-Element, sagen wir das 17te Element des
          o
     Vektors vector<int>my vector, direkt zugreifen ?
 16. Quellcode verstehen: Erkl¨ren sie die Struktur (1,2,3) der DB-Lese-Funktion
                              a
                                          ¨
     STDRead(ifstream& std file) in der Ubung 8.2.2. Beginnen sie mit der Pa-
     rameterliste.
 17. Wie k¨nnen wir unsere Studenten-Klasse CStudent in die DB-Anwendung
          o
      ¨
     (Ubung 8.2.1) einbinden ?
                                       u                          a     ¨
 18. Was ist eigentliche Lesefunktion f¨ r unsere Studenten-Datens¨tze (Ubung
     8.2.2) ?
 19. Mit welchem Befehl k¨nnen wir die Reihenfolge von Listen-Elementen
                         o
     umkehren ?
 20. K¨nnen wir Listen-Elemente sortieren, wenn ja wie, mit welcher Instruk-
       o
     tion ?
 21. Mit welchem Befehl k¨nnen wir mehrere Listen zusammenf¨ hren ?
                         o                                 u
 22. K¨nnen wir doppelte Elemente aus einer Liste entfernen sortieren, wenn
       o
     ja wie, mit welcher Instruktion ?
 23. Was ist ein Iterator ?
 24. Quellcode verstehen: Erkl¨ren sie die Funktion void display(list<int>my list)
                              a
         ¨
     der Ubung 8.3. Beginnen sie mit der Parameterliste.
 25. Wie k¨nnen wir Elemente aus einer Liste entfernen ?
          o
Kapitel 9

Andere Sprachelemente

Wir haben das Ende der C++ Grundvorlesung erreicht (hoffentlich ein Grund
zur Freude). Das Ziel der Vorlesung ’Hydroinformatik’ ist allerdings bei Weitem
noch nicht erreicht. Sie erinnern sich, wir wollen eine Dialog-gef¨hrte Datenbank-
                                                                  u
Anwendung (Fig. 4) mit C++ entwickeln. Sie werden sehen, dass wir fast al-
le Bausteine beisammen haben (außer die Grafik-Programmierung mit Visual
C++) und die Realisierung unser Applikation (nach der langen Vorbereitung)
dann sehr schnell geht.

Bevor wir zum graphischen (Visual) C++ kommen, wollen wir Sprachelemen-
te (C++ news), die wir zuvor schon benutzt haben, aber noch nicht explizit
besprochen haben, hier kurz einf¨ hren.
                                u



9.1     Kontrollstrukturen

Bei Kontrollstrukturen handelt es sich um Sprachelemente f¨ r bedingte Anwei-
                                                          u
sungen und Schleifen mit Z¨hlern und Bedingungen.
                          a

                Control          Bedeutung
                if-else          Anweisungen mit Bedingungen
                switch-case      Fallunterscheidungen
                for              Schleifen mit Z¨hlern
                                                a
                while            Schleifen mit Bedingungen

                        Tabelle 9.1: Kontrollstrukturen

Verschachtelungen von Kontrollstrukturen sind nat¨ rlich m¨glich.
                                                 u        o

                                       73
74                                       KAPITEL 9 ANDERE SPRACHELEMENTE



9.1.1    if-else
Es geht um die Ausf¨ hrung von Anweisungen und Alternativen unter bestimm-
                   u
ten Bedingungen. Ausf¨ hrung einer Anweisung unter einer Bedingung (siehe,
                       u
     ¨
z.B. Ubung 8.2.2):

if(logische Bedingung)
{...} // Ausf¨hrung, wenn Bedingung erf¨llt ist
             u                         u

Ausf¨ hrung einer Anweisung unter einer Bedingung mit Alternative (else) (sie-
     u
         ¨
he, z.B. Ubung 8.2.2):

if(logische Bedingung)
{...} // Ausf¨hrung, wenn Bedingung erf¨llt ist
             u                         u
else
{...} // Ausf¨hrung, wenn Bedingung nicht erf¨llt ist
             u                               u


9.1.2    switch-case
Die Kontrollstruktur switch-case bietet die M¨glichkeit von Fallunterscheidun-
                                             o
gen durch Ausdr¨ cke (z.B. Aufz¨hlungen durch Zahlen). Der Schalter switch
                 u             a
springt entsprechend dem Zahlenausdruck in einen Fall case.

switch(Ausdruck)
{
  case 0: // wenn Ausdruck == 0
    ... // Anweisungen
    break; // Verlassen
  default: // wenn kein Ausdruck zutrifft
}

Es gibt eine weitere Variante, wo der Ausdruck ein Zeichen sein kann.

switch(Ausdruck)
{
  case ’A’: // wenn Ausdruck == A
    ... // Anweisung
    break; // Verlassen
}

Eine weitere M¨glichkeit diese Kontrollstruktur elegant einzusetzen ist die Be-
              o
nutzung von enum - einem Konstrukt f¨ r eigene Z¨hler.
                                     u           a

enum Wochentag {Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag}

Die einzelnen Wochentage bekommen dann aufsteigende Werte (von 0 begin-
nend) zugewiesen. Dann k¨nnen wir unsere Fallunterscheidung (z.B. f¨ r das
                          o                                        u
Mensa-Men¨ ) wie folgt schreiben:
           u
9.1 KONTROLLSTRUKTUREN                                                       75



switch(Wochentag)
{
  case Montag:    // wenn Wochentag == 0
  case Dienstag: // wenn Wochentag == 1
  ...
  case Sonntag: // wenn Wochentag == 6
}


9.1.3    for
Die for Schleife ist eine Schleife mit einem Z¨hler.
                                              a

for(int i=0;i<stop;i++)
{
... // Anweisungen
}

Die Anweisungen im Funktionsrumpf {...} werden solange ausgef¨ hrt, bis der
                                                                   u
Z¨hler den Wert stop erreicht (das heißt, f¨ r den Wert stop wird die Schleife
  a                                          u
nicht mehr ausgef¨ hrt). Bei jedem Schleifendurchlauf wird der Z¨hler i um Eins
                   u                                            a
(i++) hochgez¨hlt. Ich habe gerade mal nachgesehen. In unserem Programm-
                a
system OpenGeoSys wird die for-Schleife uber 4000 mal verwendet! Wir haben
                                           ¨
                 ¨
sie z.B. in der Ubung 8.2.1 zum Generieren von Vektor-Elementen benutzt.


9.1.4    while
Die while Schleife ist eine Endlos-Schleife mit einer Bedingung.

while(Bedingung)
{
... // Anweisungen
}

Die Anweisungen im Funktionsrumpf {...} werden ausgef¨ hrt, solange die Be-
                                                          u
dingung erf¨ llt (das heißt, der numerische Wert Bedingung muss gr¨ßer als 0
            u                                                       o
sein). Um aus der Schleife herauszukommen, muss also der Wert der Bedingung
ge¨ndert werden - oder ’hart’ abgebrochen werden (siehe n¨chster Abschn. 9.1.5)
   a                                                     a
In unserem Programmsystem OpenGeoSys wird die while-Schleife fast 500 mal
                                                   ¨
verwendet! Wir haben sie f¨ r unsere Lesefunktion (Ubung 8.2.1) und beim Ite-
                            u
                  ¨
rieren in Listen (Ubung 8.2.1) verwendet.


9.1.5    continue, break, return
Es gibt mehrere M¨glichkeiten, um Kontrollstrukturen (vorzeitig) verlassen zu
                 o
k¨nnen.
 o
76                                        KAPITEL 9 ANDERE SPRACHELEMENTE



9.2     Gultigkeitsbereiche
         ¨

F¨ r alles, was wir deklarieren, Funktionen, Klassen, Variablen gibt es G¨ ltig-
  u                                                                      u
keitsbereiche. Wenn irgendwo etwas definieren, ist es also nicht uberall sicht-
                                                                  ¨
bar. Wir hatten uns mit diesem Thema schon bei der Definition von ’privaten’
Klassen-Elementen besch¨ftigt (Abschn. 4.6). Die Abb. ?? zeigt das Prinzip von
                          a
lokalen und globalen G¨ ltigkeitsbereichen. Wir sollen immer versuchen soviel
                        u
wie m¨glich lokal zu definieren, das unterst¨ tzt die Daten-Kapselung in unse-
       o                                    u
rem Programm. Klassen sind immer nur dort sichtbar, wo ihre Header-Dateien
inkludiert worden sind.



9.2.1    Namensbereiche

Sind uns auch schon mehrfach begegnet bei der Verwendung von Strings, Vekto-
ren und Listen. Dabei wurde nach dem Includieren der entsprechenden Header-
Dateien die Anweisung using namespace std benutzt. Strings, Vektoren und
Listen geh¨ren zum Namensraum der Standard-Bibliothek STL.
          o


#include <strings>
std::my_string("Beispiel ohne Namensbereich");
using namespace std;
my_string("Beispiel mit Namensbereich");


Wir k¨nnen auch eigene Namensbereiche definieren.
     o


namespace Meins
{ // hier sind Funktionen des Namensbereichs
 class CStudent
}
using namespace Meins;


Wozu ? Wenn sie ihren Programmcode mit einem anderen Entwickler zusam-
menf¨ hren wollen und es gibt mehrere Klassen CStudent, dann k¨nnen sie sicher
     u                                                        o
auf ihre Funktion zugreifen, wenn sie ihren Namensraum gesetzt haben.



9.2.2    Compiler-Direktiven – #

Alles was mit # anf¨ngt, versetzt den Kompiler in den Alarmzustand - es sind
                   a
sogenannte Kompiler-Direktiven, das heißt beim Kompilieren werden gewisse
Weichen gestellt.
¨
9.2 GULTIGKEITSBEREICHE                                                        77



                   Direktive    Wirkung
                   #include     Einf¨ gen einer Header-Datei
                                    u
                   #define      Definition einer Direktive
                   #ifdef       Wenn die Direktive gilt
                   #ifndef      Wenn sie nicht gilt
                   #endif       Ende der Direktive
                   #define      Definition eines Makros

                       Tabelle 9.2: Compiler-Direktiven


9.2.2.1   Includes

Ohne Includes geht gar nichts, sie erinnern sich, selbst um einfache Bildschirm-
ausgaben mit cout machen zu k¨nnen mussten wir Klasse iostream einf¨ gen.
                                 o                                         u
An dieser Stelle nochmal zur Erinnerung. Es gibt Arten von Includes:

<Header> Die eckigen Klammern bedeuten, es geht um einen System-Inklude.
    Es wird im Systemverzeichnis (dort wo C++ installiert ist) gesucht.

”Header” Die G¨nsef¨ ßchen bedeuten, es geht um einen eigenen Inklude. Es
                a    u
    wird lokalem Verzeichnis gesucht.

Wenn der Programm-Code verzweigt ist, also eine komplexere Verzeichnisstruk-
tur hat, m¨ ssen Pfade der Inklude-Dateien mit angegeben werden, sonst werden
           u
sie nicht gefunden. Keine Angst, in diesem Falle bekommen sie sofort eine ein-
deutige Fehler-Meldung beim Versuch zu Kompilieren.


9.2.2.2   Bedingte Kompilation

Eine sehr n¨ tzliche Sache sind Direktiven f¨ r die Kompilation von Test-Versionen.
            u                               u
Gerade w¨hrend der Entwicklung m¨chte man neue Programmteile einfach an-
          a                           o
und ausschalten k¨nnen. Dies geht mit der Kompiler-Direktive (KD) #ifdef.
                   o

#define TEST   // Anschalten der Direktive TEST
#ifdef TEST
...
#endif


Wenn die Kompiler-Direktive TEST an ist, wird der Programmtext von der Stel-
le #ifdef bis #endif beim Kompilieren ubersetzt, ansonsten einfach ignoriert.
                                        ¨
Kompiler-Direktiven sind immer aus, wenn sie nicht explizit eingeschaltet wer-
den. Das Gegenst¨ ck von #ifdef ist #infdef, also wenn die Kompiler-Direktive
                  u
aus ist. Oft m¨ ssen Funktionen uberarbeitet werden. Mit Kompiler-Direktiven
              u                 ¨
kann man sehr sch¨n eine neue Variante der Funktion entwickeln und die alte
                    o
78                                         KAPITEL 9 ANDERE SPRACHELEMENTE



erstmal zu Vergleichszwecken beibehalten. Erst wenn alles richtig funktioniert,
schmeißt man das alte Zeug weg.
¨
Ubung 9.2.2.2:

#define NEW_VERSION // Anschalten der Direktive NEW_VERSION
#ifdef NEW_VERSION
... // wenn NEW_VERSION an ist
#else
... // wenn NEW_VERSION aus ist
#endif

                                           ¨
Ich empfehle ihnen, das mal in irgendeiner Ubung auszuprobieren. Wichtig:
Denken sie immer an das #endif zum Ausschalten, sonst gilt die Kompiler-
Direktive bis zum Ende des gesamten Programms.


9.2.2.3     Makros

Die Kompiler-Direktive #define kann auch zur Definition sogenannter Makros
verwendet werden, z.B. f¨ r Konstanten, die man oft benutzt. Es geht aber auch
                         u
f¨ r einfache Funktionen oder sogar Print-Anweisungen.
 u

#define PI 3.1416 // Definition der Zahl PI
#define MULT(a,b) ((a)*(b))
#define PRINT(x) cout << (#x) << ": " << (x);


Der Makro-Einsatz sollte aber nicht ubertrieben werden, eigentlich gibt es daf¨ r
                                     ¨                                        u
richtige Funktionen. Bei Makros werden z.B. keine Pr¨ fungen durch den Kom-
                                                     u
piler gemacht, daher sind sie fehleranf¨llig.
                                       a


9.3       Testfragen
     1. Was sind Kontrollstrukturen, welche kennen sie ?

     2. Bei welcher logischen Bedingung wird eine if-Anweisung ausgef¨ hrt ?
                                                                     u

     3. Lassen sich Kontroll-Strukturen verschachteln ?

     4. Mit welcher Kontrollstruktur k¨nnen wir Fallunterscheidungen program-
                                      o
        mieren ?

     5. Welche Ausdr¨ cke k¨nnen wir bei der switch-case Kontrollstruktur be-
                    u      o
        nutzen ?

     6. Wie kann ich eine Kompiler-Direktive an- und ausschalten ?
9.3 TESTFRAGEN                                                            79



                       ¨
  7. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle
                                      u
     von #ifdef um.
  8. Erl¨utern sie den Kopf der for-Schleife: for(int i=0;i<stop;i++), wel-
        a
     chen Daten-Typ hat stop ?
  9. Was ist eine Endlos-Schleife, wie kommen wir daraus ?
 10. Was sind Namensbereiche ?
 11. Was m¨ ssen wir tun, um die Arbeit mit C++ Standard-Klassen zu verein-
            u
     fachen, d.h anstelle von std::my string() direkt my string() benutzen
     zu k¨nnen ?
         o
 12. Was sind Kompiler-Direktiven, was bewirken diese ?
 13. Wie k¨nnen wir Kompiler-Direktiven an- und ausschalten ?
          o
 14. Worin besteht der Unterschied bei Includes mit eckigen Klammern < ... >
     bzw. mit G¨nsef¨ ßchen ”...” ?
               a    u
                       ¨
 15. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle
                                      u
     von #ifdef um ?
 16. Was sind Makros ?
 17. Welche beiden Einsatzm¨glickeiten von Makros gibt es ?
                           o
 18. Worin besteht die Gefahr, Makros als Funktionsersatz zu benutzen ?
Part II
Visual C++

Wir kommen zur grafischen Programmierung - ’Visual C++’. Leider m¨ ssen wir
                                                                         u
uns nun f¨ r ein Betriebssystem entscheiden, da die Grafikprogrammierung platt-
          u
formabh¨ngig ist. Es gibt zwar auch plattformunabh¨ngige Grafik-Bibliotheken
         a                                            a
aber die kosten aber in der Regel ... Die Entscheidung ist nicht leicht (die Mac’s
und Ubuntu’s werden jetzt zu Recht schimpfen) aber sie f¨ hrt unweigerlich zu
                                                            u
Windows. Die Ideen und Techniken der Grafik-Programmierung sind gr¨ßten-     o
teils unabh¨ngig vom Betriebssystem, so werden auch die nicht-Windows’ler
            a
eine Menge lernen. Man kann Windows unter Ubuntu emulieren, na schauen
wir mal (siehe Anlage 12.7) ... Mittlerweile gibt es auch plattformunabh¨ngige
                                                                            a
Grafik-Bibliotheken wie z.B. Qt (siehe Anlage 11) die open source sind.




Abbildung 9.1: Eine der bekanntesten Dialog-Applikationen: Der RAR-Packer
9.3 TESTFRAGEN                                                           81



Prinzipiell gibt es folgende Konzepte f¨ r die Grafik-Programmierung:
                                       u

   • Dialoge (Abschn. 10),
   • Dokumente und Ansichten (Doc-View concept),
   • und nat¨ rlich diverse Kombinationen.
            u

Eine typische Dialog-Applikation ist z.B. der RAR-Packer zum Komprimie-
ren von Dateien unter Windows (Abb. 9.1). MS-Word ist eine Anwendung des
Doc-View-Konzepts, dabei k¨nnen gleichzeitig mehrere Dokumente (d.h. Word-
                           o
Dateien) ge¨ffnet und bearbeitet werden (Abb. 9.2)
           o




  Abbildung 9.2: Eine der bekanntesten Doc-View-Applikationen: MS Word
Kapitel 10

Dialoge

Dialoge geh¨ren zu den einfachsten Anwendungen von grafischen Benutzer-
              o
schnittstellen (GUI graphical user interface). Ihre Aufgabe ist, es eine grafisch-
gest¨ tzte Interaktion (Dialog) mit einem Programm zu erm¨glichen. Wir besch¨fti-
    u                                                     o                    a
gen uns mit drei Varianten grafische Dialoge zu produzieren:

   • dem MFC Dialog (Abschn. 10.1),

   • dem .NET Formular (Abschn. 10.4),
   • dem Qt Dialog (Abschn. 11).

Mit dem .NET Formular m¨ ssen wir uns ’notgedrungen’ besch¨ftigen, da die
                            u                                  a
freien Express Editionen von VC++ (2005 und 2008) die Microsoft-Foundation-
Classes (MFC) nicht mehr unterst¨ tzen. Die Erzeugung der leeren Dialoganwen-
                                u
dungen mit MFC, .NET und Qt finden sie in der Anlage.


10.1      What have we (i.e. MFC) created ?
Finden sie es nicht auch etwas unheimlich, mit 5 Maus-Klicks etwas kreiert zu
haben, was sich auf unserem Bildschirm hin- und her verschieben l¨sst (Ab-
                                                                   a
schn. 12.5) ... Schauen wir uns in Ruhe an, was VC++ f¨ r uns erledigt hat.
                                                         u
Der ’Solution-Explorer’ auf der rechten Seite von VC++ (Abb. 10.1) gibt uns
Aufschluss uber den automatisch erzeugten Code. Den kompletten Quellcode
            ¨
                                               ¨
der leeren Dialog-Anwendung finden sie in der Ubung E10.1.




                                      82
10.1 WHAT HAVE WE (I.E. MFC) CREATED ?                                        83



.




                   Abbildung 10.1: Der ’Solution-Explorer’


    • Header Files: wie gewohnt, unsere Klassen-Definitionen,
    • Resource Files: neu, unsere grafischen Elemente,
    • Source Files: unser aktives Bet¨tigungsfeld zum Programmieren.
                                     a
    • ReadMe.txt: ... endlich eine Erkl¨rung, es lohnt sich diese ReadMe-Datei
                                       a
      zu lesen.

oder file-m¨ßig aufgedr¨selt:
          a           o

    • MyDialog.*: Die Windows-Applikation
    • MyDialogDlg.*: Unser Ding,
    • Resource.h: Die IDs unserer grafischen Elemente (wird automatisch ak-
      tualisiert ...),
    • stdafx.*: Irgendwas, das Windows standartm¨ßig braucht ...
                                                a

Die Abb. 10.2 soll illustrieren, was VC++ f¨ r uns freundlicherweise erzeugt hat.
                                           u

    • MyDialog.cpp/h enth¨lt die Windows-Applikation, die erzeugt und ruft
                           a
      den Dialog auf: CMyDialogApp::InitInstance().
    • MyDialog.rc ist die Dialog-Resource, der grafische Dialog mit seinen Ele-
      menten. Dialog-Resourcen und Dialog-Elemente werden uber Nummern
                                                               ¨
      (IDD/IDs) zugeordnet.
84                                                         KAPITEL 10 DIALOGE



                      IDD_MYDIALOG



                          Dialog
                          Resource


                                             Funktionen
                                             ‘hinter’ den
                                             Dialog-Elementen

                 Windows
                 Application                MyDialogDlg.cpp/h



              MyDialog.cpp/h

                    Abbildung 10.2: What have ’we’ created?


     • MyDialogDlg.cpp/h enth¨lt alle Funktionen des Dialogs, also das was hin-
                               a
       ter den Kn¨pfchen steckt ...
                 o

Die Windows-Applikation macht nichts anderes, als den Dialog aufzurufen.

CMyDialogApp theApp;
BOOL CMyDialogApp::InitInstance()
{
CMyDialogDlg dlg; // Instanz der Dialog-Klasse
dlg.DoModal();    // Aufruf des Dialogs
10.2 GESTALTUNG DES DIALOGS                                                 85



10.2      Gestaltung des Dialogs
Zum Design des Dialogs bietet MS-VC++ viele M¨glichkeiten. Hierf¨ r benutzen
                                             o                  u
wir den Resourcen-Editor (Abb. 10.3).




         Abbildung 10.3: Die Dialog-Resource und der Dialog-Editor

Die Resourcen-Elemente der ToolBox k¨nne einfach auf das Dialog-Feld ’gezo-
                                      o
gen’ werden (’Drag and drop’). Die Gestaltung des Dialogs (also die Positionen
und IDs von jedem Element) ist dann in der Datei Resources.rc gespeichert.
86                                                    KAPITEL 10 DIALOGE



Resources.rc
...
IDD_MYFIRSTWINDOWS_DIALOG DIALOGEX 0, 0, 320, 246
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "MyFirstWindows"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "Geoecology",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,10,
                    110,54,10
    CONTROL         "Geology",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,10,124,
                    42,10
    CONTROL         "AEG",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,
                    10,95,31,10
    DEFPUSHBUTTON   "OK",IDOK,265,230,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,5,230,50,14
    GROUPBOX        "Student data",IDC_STATIC,0,0,170,225
    GROUPBOX        "Students data base",IDC_STATIC,175,0,140,85
    GROUPBOX        "Biometric picture",IDC_STATIC,175,90,140,135
    LTEXT           "First name",IDC_STATIC,5,15,33,8
    LTEXT           "Last name",IDC_STATIC,5,30,34,8
    LTEXT           "Birthday",IDC_STATIC,5,45,26,8
    LTEXT           "Matrikel",IDC_STATIC,5,60,26,8
    LTEXT           "Bank account",IDC_STATIC,5,75,46,8
    EDITTEXT        IDC_EDIT1,60,15,105,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT2,60,30,105,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT3,60,45,105,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT4,60,60,105,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT5,60,75,105,14,ES_AUTOHSCROLL | WS_DISABLED
    EDITTEXT        IDC_EDIT6,60,205,105,14,ES_AUTOHSCROLL | WS_DISABLED
    PUSHBUTTON      "Read DB",IDC_BUTTON1,180,15,50,14
    PUSHBUTTON      "Write DB",IDC_BUTTON2,260,15,50,14
    LISTBOX         IDC_LIST1,180,35,75,45,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
                    WS_TABSTOP
    PUSHBUTTON      "Add",IDC_BUTTON3,260,35,50,14
    PUSHBUTTON      "Edit",IDC_BUTTON4,260,50,50,14
    PUSHBUTTON      "Remove",IDC_BUTTON5,260,65,50,14
    LTEXT           "Mark",IDC_STATIC,5,205,17,8
    LTEXT           "Home work I",IDC_STATIC,5,160,41,8
    LTEXT           "Home work II",IDC_STATIC,5,175,43,8
    EDITTEXT        IDC_EDIT7,60,145,105,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT8,60,160,30,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT9,60,175,30,14,ES_AUTOHSCROLL
    LTEXT           "e-mail",IDC_STATIC,5,145,19,8
    EDITTEXT        IDC_EDIT10,95,160,70,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT11,95,175,70,14,ES_AUTOHSCROLL
    PUSHBUTTON      "Info",IDC_BUTTON7,5,185,50,14
END
10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG                                 87



10.3          Programmierung des Dialogs – MyDialogDlg
Um jetzt mit dem Programmieren unseres Dialogs beginnen zu k¨nnen, m¨ ssen
                                                             o        u
wir uns den Zusammenhang zwischen Dialog-Resource (also seine grafische Ge-
stalt) mit seinen Elementen (Kn¨pfchen ...) anschauen. Alle Funktionen und
                               o
Daten unseres Dialogs befinden sich in der Klasse CMyDialogDlg, die von der
(Windows) Basis-Klasse CDialog abgeleitet wird (dies nennt man auch Verer-
bung).

class CMyDialogDlg : public CDialog



10.3.1        Dialog-Funktionen

Die alles entscheidende Stelle, die Verbindung zwischen Dialog-Resource und
Funktionen erfolgt in der sogenannten MESSAGE MAP (Nachrichten-Schleife) durch
die Anweisung (Abb. 10.6)

BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog)
...
  ON_BN_CLICKED(IDC_BUTTON, OnButtonReadDB)
...
END_MESSAGE_MAP()


die nichts anderes besagt, wenn das Kn¨pfchen IDC BUTTON gedr¨ ckt wird, dann
                                      o                      u
f¨ hre die Funktion OnButtonReadDB aus.
 u

     ID = IDC_BUTTON                             CMyDialogDlg


Resource.h                            BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog)
#define IDD_DIALOG        129         ...
#define IDB_MARTIN_ZIPPEL 201           ON_BN_CLICKED(IDC_BUTTON, OnButtonReadDB)
#define IDC_BUTTON       1009         ...
                                      END_MESSAGE_MAP()
MyDialog.rc

   Abbildung 10.4: Dialog-Resource und Dialog-Klasse - Teil 1: Funktionen



10.3.2        Dialog-Daten

Wie der Datenaustausch zwischen der Dialog-Resource und der Dialog-Klasse
erfolgt, ist in der Abb. 10.7 dargestellt.
88                                                                KAPITEL 10 DIALOGE




      ID = IDC_EDIT1                            CMyDialogDlg
Resource.h                           DoDataExchange()
#define IDC_EDIT1      1000          ...
                                       DDX_Text(pDX, IDC_EDIT1, m_str_FirstName);
                                     ...

       Abbildung 10.5: Dialog-Resource und Dialog-Klasse - Teil 2: Daten

Das Entscheidende passiert in der Funktion DoDataExchange(). Hier wird das,
was wir z.B. in das Editier-Feld (First name) eintippen an die (string) Variable
m strFirstName weitergeben. Aufgepasst, die Datenaustausch-Funktion wird
nicht automatisch aufgerufen, wie die Funktionen in der MESSAGE MAP. Daf¨ r   u
gibt es einen triftigen Grund, der Datenaustausch kann in beide Richtungen
zwischen Dialog und Klasse erfolgen. Wir schauen uns das sp¨ter in der Imple-
                                                              a
mentierung des Dialogs genau an.

void CMyDialogDlg::DoDataExchange(CDataExchange* pDX)
{...
  CDialog::DoDataExchange(pDX);
  DDX_Text(pDX, IDC_EDIT1, m_strFirstName);
...}


10.3.3       Implementierung des Dialogs
MyDialogDlg.h

Im Header-File der Klasse erfolgt die Deklaration der Daten und Funktionen.
Das Einf¨ gen von neuen Daten-Elementen und Funktionen ist Bestandteil der
        u
¨
Ubung 10.3.
Schritte f¨ r neue Daten-Elemente:
          u

     1. Erzeugen des Daten-Elements (IDC EDIT1) mit dem Resourcen-Editor (z.B.
        Editier-Feld),
     2. Deklarieren der Dialog-Variable: CString m strFirstName,
     3. Datenaustausch zwischen Resource und Variable: DDX Text(pDX, IDC EDIT1,
        m strFirstName).

Schritte f¨ r neue Funktionen:
          u

     1. Erzeugen des Funktions-Elements (IDC BUTTON) mit dem Resourcen-Editor
        (z.B. Button),
10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG                                89



  2. Deklarieren der Funktion: void OnButtonReadDB(),

  3. Verkn¨ pfen von Resource mit Funktion: ON BN CLICKED(IDC BUTTON, OnButtonReadDB).
          u

Das komplette Ergebnis finden sie im Header-File des Dialogs MyDialogDlg.h.

class CMyDialogDlg : public CDialog
{...
  // Dialog data
  CListBox m_STDVector;           //    Studenten-Liste
  CString m_strFirstName;         //    Vorname
  CString m_strLastName;          //    Nachname
  ...
  // Dialog functions
  afx_msg void OnButtonReadDB(); //     Lesen der DB
  afx_msg void OnButtonWriteDB(); //    Schreiben der DB
  afx_msg void OnSelchangeList(); //    ¨nderungen anzeigen
                                        A
  afx_msg void OnButtonAdd();     //    Hinzuf¨gen eines Datensatzes
                                              u
  afx_msg void OnButtonRemove(); //     L¨schen eines Datensatzes
                                         o
  afx_msg void OnButtonEdit();    //    Editieren eines Datensatzes
...};


10.3.4    Schnittstelle zwischen Dialog- und Studenten-Klasse

Im CPP-File der Klasse (MyDialogDlg.cpp) stehen unsere Funktionen also die
Schnittstelle zwischen dem Dialog und unserer Studenten-Klasse CStudent. Da-
her darf nat¨ rlich auch nicht der entsprechende Include fehlen.
             u

#include "student.h"


Wir schauen uns nun zwei Funktionen im Detail an, das Lesen der Datenbank
OnButtonReadDB() und das Anzeigen der Datens¨tze OnSelchangeList(). Da-
                                                  a
bei sehen wir, wie die Interaktion zwischen Dialog und unserer Studenten-Klasse
                                                          ¨
funktioniert. Den kompletten Quelltext finden sie in der Ubung E10.3.


Lesen der Datenbank - OnButtonReadDB()

Die Funktion hinter dem Kn¨pfchen ’Read DB’ macht drei Dinge:
                          o

   • File handling, Offen der DB Datei (Details in Abschn. 10.3.5),
                    ¨

   • Lesen der DB, dies ist 1-zu-1 unser DB Lesefunktion (Ubung E8.2.2),
                                                          ¨

   • Die Listen-Box (CListBox m STDVector) mit den gelesenen Datens¨tzen
                                                                   a
     (Namen) wird gef¨ llt
                      u
90                                                        KAPITEL 10 DIALOGE



void CMyDialogDlg::OnButtonReadDB()
{
  //-------------------------------------------------------
  // 1 File handling
  see section "File handling"
  //-------------------------------------------------------
  // 2 Read DB file
  STDRead((string)file_name);
  //-------------------------------------------------------
  // 3 Fill list box
  CStudent* m_std = NULL;
  string m_str;
  for(int i=0;i<std_vector.size();i++)
  {
    m_std = std_vector[i];
    m_str = m_std->name_first + " " + m_std->name_last;
    m_STDVector.AddString(m_str.c_str());
  }
}


Anzeigen der Datens¨tze - OnSelchangeList()
                   a

Wenn wir auf einen Namen in der Listen-Box klicken, wird eine Funktion aus-
gef¨ hrt, welche uns die Daten des ausgew¨hlten Studenten anzeigt.
   u                                     a
Diese Funktion besteht aus vier Teilen:

     • Bestimmen der Position des Mausklicks im der Listen-Box (nSel),

     • Zugriff auf den Datensatz (m std) aus der DB entsprechend der angeklick-
       ten Position und Kopieren der Daten in die Daten-Elemente des Dialogs,

     • Anzeigen des BMPs (Foto) (Details in 10.3.5),

     • Aktualisieren des Daten-Elemente des Dialogs.

void CMyFirstWindowsDlg::OnSelchangeList()
{
  //-1--------------------------------------------------------------------
  int nSel = m_STDVector.GetCurSel();
  //-2--------------------------------------------------------------------
  if(nSel>-1)
  {
    m_std = student_vector[nSel];
    m_strFirstName = m_std->name_first.c_str();
    m_strLastName = m_std->name_last.c_str();
    m_strBirthDay = m_std->birthday.c_str();
    m_lMatrikelNumber = m_std->id;
    m_strEMail = m_std->email.c_str();
10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG                              91



     m_strHomeWorkI_submitted = m_std->home_work_I_submitted.c_str();
     m_strHomeWorkI_submitted = m_std->message.c_str();
     m_iHomeWorkI = m_std->home_work_I;
     m_strHomeWorkII_submitted = m_std->home_work_II_submitted.c_str();
     m_iHomeWorkII = m_std->home_work_II;
     m_iCredit = m_std->credit;
    }
    //-3--------------------------------------------------------------------
    // BMP
    //-4--------------------------------------------------------------------
    UpdateData(FALSE); // Akualisieren der Dialog-Elemente
}


Sortieren der Datens¨tze - OnBnClickedButtonDBSort()
                    a

Beim alphabetischen Sortieren der Datens¨tze k¨nnen wir uns die Sortier-Funktion
                                        a     o
der Listen zu Nutze machen.

void CMyDialog::OnBnClickedButtonDBSort()
{
  STDSort();
  UpdateSTDVector();
}

void STDSort()
{
  //----------------------------------------------------------------
  int i;
  CStudent* m_std = NULL;
  list<string>name_list;
  for(i=0;i<(int)std_vector.size();i++)
  {
    m_std = std_vector[i];
    name_list.push_back(m_std->name_last);
  }
  //----------------------------------------------------------------
  name_list.sort();
  //----------------------------------------------------------------
  //
  list<string>::const_iterator iterator;
  iterator = name_list.begin();
  string name_last;
  while(iterator != name_list.end())
  {
    name_last = *iterator;
    for(i=0;i<(int)std_vector.size();i++)
    {
      m_std = std_vector[i];
      if(m_std->name_last.compare(name_last)==0)
92                                                           KAPITEL 10 DIALOGE



           {
               std_vector_sorted.push_back(m_std);
           }
         }
         ++iterator;
     }
}

void CMyDialog::UpdateSTDVector()
{
  std_vector.clear();
  for(int i=0;i<(int)std_vector_sorted.size();i++)
  {
    std_vector.push_back(std_vector_sorted[i]);
  }
  std_vector_sorted.clear();
  UpdateSTDVectorList();
}


10.3.5           Nutzliche Windows-Funktionen
                  ¨
Wir benutzen fertige Windows-Funktionen / MFC Klassen f¨ r die Datei-Auswahl
                                                       u
(CFileDialog) und das Anzeigen von BMPs (DrawBitmap).


File handling

CString file_name;
CFileDialog fileDlg(TRUE,"dat",NULL,OFN_ENABLESIZING,"DAT Files(*.dat)|*.dat||");
if(fileDlg.DoModal()==IDOK)
{
  file_name = fileDlg.GetFileName();
}


Bitmaps

Die Schritte zum Zeichnen des BMPs (Fotos) sind folgende:

         • Auswahl des rechteckigen Zeichenbereichs (CRect rc),
         • Auswahl des entsprechenden BMPs (IDB BITMAP1),
         • Zeichnen des ausgew¨hlten BMPs (DrawBitmap())
                              a

void CMyFirstWindowsDlg::OnButtonReadDB()
{...
  CRect rc;
  GetClientRect(&rc);
10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG                          93



  rc.top = 160;
  rc.left= 290;
  CBitmap m_bmpStudent;
  m_bmpStudent.DeleteObject();
  m_bmpStudent.LoadBitmap(IDB_BITMAP1);
  DrawBitmap(rc,m_bmpStudent);
...}

Dies ist die Zeichenfunktion des ausgew¨hlten BMBs.
                                       a

void CMyDialogDlg::DrawBitmap(CRect& rc,CBitmap& bm)
{
  CPaintDC dc(this);
  HBITMAP hbmpOld;
  CDC dcMem;
  dcMem.CreateCompatibleDC(&dc);
  hbmpOld = (HBITMAP)dcMem.SelectObject(bm);
  GetDC()->BitBlt(rc.left,rc.top,rc.right,rc.bottom,&dcMem,0,0,SRCCOPY);
  dcMem.SelectObject(hbmpOld);
}
94                                                       KAPITEL 10 DIALOGE



10.4      Das .NET Formular
.NET (sprich dotnet) ist eine von Microsoft entwickelte Software-Plattform. Die-
se umfasst eine Laufzeitumgebung, eine f¨ r Programmierer bestimmte Samm-
                                          u
lung von Klassenbibliotheken (API) und angeschlossene Dienstprogramme (Ser-
vices) (Quelle http://de.wikipedia.org/wiki/.NET). Mit .NET soll i.W. auch
Vereinheitlichung der (MS) Programmiersprachen VisualBasic (VC), C sharp
(C#) und C++ erreicht werden. Die Gestaltung des Formulars mit dem Resourcen-
Editor (siehe Anlage 12.6) funktioniert genauso so einfach wie bei den MFC-
Dialogen (Anlage 10.2).




                   Abbildung 10.6: Die Formular-Resource

In der ReadMe.txt finden wir eine Beschreibung, was der Anwendungs-Assistent
f¨ r uns erstellt hat.
 u

========================================================================
    ANWENDUNG: MyForm-Projekt¨bersicht
                             u
========================================================================

Diese MyForm-Anwendung wurde vom Anwendungs-Assistenten f¨r Sie erstellt.
                                                         u

Diese Datei enth¨lt eine Zusammenfassung dessen, was Sie in jeder der Dateien
                a
finden, aus denen Ihre MyForm-Anwendung besteht.

MyForm.vcproj
    Dies ist die Hauptprojektdatei f¨r VC++-Projekte, die mit dem Anwendungs-
                                    u
    Assistenten generiert werden.
    Sie enth¨lt Informationen uber die Version von Visual C++, in der die Datei
            a                 ¨
    generiert wurde, sowie uber die Plattformen, Konfigurationen und
                           ¨
    Projektfeatures, die im Anwendungs-Assistenten ausgew¨hlt wurden.
                                                         a

MyForm.cpp
    Dies ist die Hauptquelldatei der Anwendung.
10.4 DAS .NET FORMULAR                                                        95



    Enth¨lt den Code zum Anzeigen des Formulars.
        a

Form1.h
    Enh¨lt die Implementierung der Formularklasse und
       a
    der InitializeComponent()-Funktion.

AssemblyInfo.cpp
    Enth¨lt benutzerdefinierte Attribute zum ¨ndern von Assemblymetadaten.
        a                                    A

/////////////////////////////////////////////////////////////////////////////
Weitere Standarddateien:

StdAfx.h, StdAfx.cpp
    Diese Dateien werden verwendet, um eine vorkompilierte Headerdatei
    (PCH-Datei) mit dem Namen "MyForm.pch und eine
    vorkompilierte Typendatei mit dem Namen "StdAfx.obj" zu erstellen.

/////////////////////////////////////////////////////////////////////////////

Um eine Funktion anzulegen (z.B. mit einem Doppelklick auf eine Schalt߬che)
                                                                          a
erstellt der Anwendungs-Assistent einen Funktionsrumpf in der Form1.h vor.
F¨ r unsere Formular-Funktionen legen wir besser eine neue Quell-Datei Form1.cpp
  u
an (enspricht MyDialogDlg.cpp f¨ r den MFC Dialog). In der nachfolgenden Ta-
                                u
belle finden sie die Entsprechungen der Funktionen f¨ r MFC-Dialog und .NET-
                                                     u
Formular.

 Bedeutung         MFC-Dialog CMyDialog::        .NET-Formular Form1::
 DB lesen          OnButtonReadDB                button1 Click
 DS ausw¨hlen
         a         OnSelchangeList               listBox1 SelectedIndexChanged
 DB sortieren      OnBnClickedButtonDBSort       button2 Click
 ListBox f¨ llen
          u        UpdateSTDVector               listBox1 Fill

                                 Tabelle 10.1:

Die gute Nachricht ist, unsere eigenen C++ Funktionen k¨nnen wir 1-zu-1 wei-
                                                         o
terverwenden. Andererseits m¨ ssen wir uns mit den neuen Formular-Elementen
                              u
und Daten-Typen vertraut machen, wir sehen auch erhebliche Unterschiede in
der Nachrichten-Signal-Verarbeitung. Es ist einfacher geworden, es gibt z.B. kei-
ne IDs mehr, die grafischen Elemente sind direkte Bestandtteile (member) der
Formular-Klasse.


10.4.1     Funktionen
Eine Funktion f¨ r Schaltfl¨che erstellen wir mit einem Doppelklick auf die ent-
                u         a
sprechende Formular-Resource. Damit generieren wir ein Ereignis button1→Click,
das mit einer Funktion vern¨ pft ist. Eine weitere Besonderheit ist, dass das Er-
                            u
eignis dynamisch zur Laufzeit erzeugt wird.
96                                                        KAPITEL 10 DIALOGE



Form1.h: Verkn¨ pfung von Ereignis (Klick auf button1) und Funktion
              u

.NET: this->button1->Click += gcnew System::EventHandler(this,&Form1::button1_Click);
 MFC: ON_BN_CLICKED(IDC_BUTTON1, OnButtonReadDB)

Die Definition der Klick-Funktion button1 Click in der Quell-Datei ist im fol-
genden dargestellt sowie der Vergleich mit der entsprechenden MFC-Funktion.
Nat¨ rlich k¨nnen wir die .NET Funktionen auch umbenennen. Nat¨ rlich k¨nnen
    u       o                                                  u       o
wir die .NET Funktionen auch umbenennen, z.B. button1 Click in ReadDB.
    ¨
Die Anderung muss an allen Stellen wo der alte Funktionsname button1 Click
auftaucht erfolgen. Keine Angst, der Kompiler meldet sich sofort, wenn sie es
irgendwo vergessen haben sollten ...
Form1.cpp: Klick-Funktion

.NET: Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e)
 MFC: void CMyDialog::OnButtonReadDB()

                                         ¨
Wir sehen uns die Funktion sp¨ter in der Ubung genauer an.
                             a


10.4.2     Daten

Wie schon erw¨hnt, .NET benutzt komplett neue Daten-Typen (Kommentar).
               a
Die Tabelle 10.2 am Ende des Abschnitts gibt einen kleinen Vergleich. Die Hier-
archie der Namensr¨ume ist f¨ r .NET Formulare ist: System::Windows::Forms.
                   a        u
Der Datenaustausch zwischen den Variablen und den Resourcen ist in .NET ein-
facher geworden und erfolgt direkt ohn den Umweg uber IDs. Es gibt also keine
                                                    ¨
DDX Datenaustausch-Funktionen mehr.
Form1.h:

.NET: private: System::Windows::Forms::TextBox^ textBox1;
      private: System::Windows::Forms::ListBox^ listBox1;
 MFC: CString m_strFirstName;
      CListBox m_STDVector;
 MFC: DDX_Text(pDX, IDC_EDIT1, m_strFirstName);
      DDX_Control(pDX, IDC_LIST1, m_STDVector);


Nachfolgend sehen wir, wie Werte der Variablen an die grafischen Resourcen
weitergegeben werden.
Form1.cpp:

.NET: textBox1->AppendText(name_first_trimmed);
      listBox1->Items->Add(Str);
10.4 DAS .NET FORMULAR                                                     97



               Bedeutung       C++       MFC         .NET
               Zeichenkette    string    CString     String^
               ListBox         -         CListBox    ListBox

                  Tabelle 10.2: Vergleich von Daten-Typen


10.4.3    ¨
          Ubung: Hinzufugen von Funktionen
                       ¨
           ¨
Schritt 1: Uberlegen

Was wollen wir tun ? Eine Funktion zum Anlegen eines neuen Datensatzes
erstellen. Eine perfekte Vorbereitung w¨re es gewesen, diese Funktion bereits
                                       a
geschrieben und in einem kleinen Konsolenprogramm getestet zu haben ...


Schritt 2: Resourcen-Element anlegen

Die Schalt߬che einfach auf das Formualfeld ziehen (Abb. 10.7).
           a




             Abbildung 10.7: Die Formular-Resource bearbeiten

Um herauszubekommen, was passiert ist, suchen wir einfach mal nach button3
in unserem Projekt. Das Suchergebnis sehen wir in Abb. 10.8.
98                                                        KAPITEL 10 DIALOGE



.




                   Abbildung 10.8: What have we created


Die Treffer betreffen ausschließlich die Header-Datei Form1.h. Dort finden wir
die Deklaration der Schaltfl¨che button3 als Daten-Typ Button^ sowie die Defi-
                           a
nition der dazugeh¨rigen grafischen Resource (Position, Gr¨ße etc.) in der Funk-
                  o                                      o
tion InitializeComponent().
Form1.h

Windows Form Designer generated code
private: System::Windows::Forms::Button^ button3; // Daten-Typ

void InitializeComponent(void)
{...
  this->button3 = (gcnew System::Windows::Forms::Button());
  ...
  // button3
  this->button3->Location = System::Drawing::Point(160, 145);
  this->button3->Name = L"button3"; // andern in L"Add"
                                       ¨
  this->button3->Size = System::Drawing::Size(75, 23);
  this->button3->TabIndex = 8;
  this->button3->Text = L"button3";
  this->button3->UseVisualStyleBackColor = true;
...}


Schritt 3: Funktion anlegen

Wie schon erw¨hnt, mit einem Doppelklick auf das Resourcen-Element wird die
             a
Funktion automatisch im Header-File angelegt.
Form1.h

private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) { }


In der Parameterliste der Funktion sehen wir ein Objekt sender und Ereignisse
EventArgs, welche die Nachrichtenliste (message map) in MFC ersetzen.
10.4 DAS .NET FORMULAR                                                       99



Schritt 4: Funktion in CPP File

Eigentlich k¨nnten wir die Funktion button3 Click auch im Header-File belas-
            o
sen. Ich empfehle aber, die Funktion in das CPP-File zu kopieren und nur ihre
Deklaration im H-File zu hinterlassen.
Form1.h/cpp

private: System::Void button3_Click(System::Object^      sender, System::EventArgs^   e);

Void Form1::button3_Click(System::Object^     sender, System::EventArgs^    e)
{
}



Schritt 5: Funktion schreiben

Unsere Funktion ’hinter dem Kn¨pfchen’ ist erfreulich kurz und enth¨lt folgende
                                o                                  a
Schritte: (1) Erzeugen einer neuen Instanz unser Klasse CStudent, (2) Einf¨ gen
                                                                           u
dieser Instanz in den Datenbank (DB) Vektor, (3) Aktualisieren unserer ListBox
im Formular.
Form1.h/cpp

Void Form1::button3_Click(System::Object^ sender, System::EventArgs^        e)
{
  CStudent* m_std = new CStudent(); // neue CStudent Instanz
  std_vector.push_back(m_std);      // in Vektor eintragen
  listBox1_Fill();                  // ListBox aktualisieren
}




                  Abbildung 10.9: Neuen Datensatz einf¨ gen
                                                      u
100                                                     KAPITEL 10 DIALOGE



Schritt 6: Funktion testen

Der letzte Schritt ist das Testen der neuen Funktion. Dabei m¨ ssen wir alle
                                                              u
Kombinationen von Kn¨pfchen ausprobieren. Der Unterschied von interaktiven
                        o
zu Konsolen-Programmen ist, das jede Funktion beliebig oft ausgef¨ hrt wer-
                                                                   u
den k¨nnen muss. Daher m¨ ssen vor Ausf¨ hren der Funktion i.d.R. alle Daten
      o                    u             u
gel¨scht und wieder neu erzeugt werden.
   o




                       Abbildung 10.10: DB sortieren

Die soll zur MS-Windows-Programmierung mit MFC und .NET gen¨ gen, um
                                                           u
ihnen den ’flavour’ vermittelt zu haben.
10.5 HOMEWORKS                                                            101



10.5     HomeWorks
MFC (obsolet f¨ r VC++ Express)
              u

  1. Implementieren sie die Funktion zum Einf¨ gen eines neuen Datensatzes –
                                             u
     CMyDialogDlg::OnButtonAdd().
  2. Implementieren sie die Funktion zum L¨schen eines Datensatzes –
                                          o
     CMyDialogDlg::OnButtonRemove().
  3. Implementieren sie die Funktion zum Editieren eines Datensatzes –
     CMyDialogDlg::OnButtonEdit().
  4. Implementieren sie die Funktion zum Schreiben der Datenbank –
     CMyDialogDlg::OnButtonWriteDB().
  5. Bauen sie einen Z¨hler f¨ r die Anzahl der existierenden Datens¨tze ein.
                      a      u                                      a
     Hinweis: Benutzen sie dazu ein Editier-Feld.

.NET

  1. Implementieren sie die Funktion zum L¨schen eines Datensatzes –
                                          o
     button4 Click.
  2. Implementieren sie die Funktion zum Editieren eines Datensatzes –
     button5 Click.
  3. Implementieren sie die Funktion zum Schreiben der Datenbank –
     button5 Click.
  4. Bauen sie einen Z¨hler f¨ r die Anzahl der existierenden Datens¨tze ein.
                      a      u                                      a
     Hinweis: Benutzen sie dazu ein Editier-Feld.
102                                                    KAPITEL 10 DIALOGE



10.6     Testfragen
MFC

  1. Welche Typen von grafischen Windows-Applikationen kennen sie ?
  2. Was ist eine Dialog-Resource ?
  3. Welche Dialog-Elemente haben wir in unserer Windows-Applikation be-
     nutzt (Abb. 10.3) ?
  4. Was sind IDs ?
  5. Was ist eine MESSAGE MAP ?
  6. Wie wird die Verbindung zwischen Funktionen und grafischen Dialog-
     Elementen hergestellt ?
  7. Wie wird die Verbindung zwischen Daten und grafischen Dialog-Elementen
     hergestellt ?
  8. Was bedeutet die Definition: class CMyDialog : public CDialog ?
  9. Wie wird ein Dialog aufgerufen (Funktion der Klasse CDialog)?
 10. Was bewirkt die Dialog-Funktion UpdateData() ?
 11. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten-
     Klasse ?
 12. Wie kann ich Files unter Windows ¨ffnen (welche Klasse) ?
                                      o
 13. Was ist ein BMP ?

.NET

  1. Was ist eine Formular-Resource ?
  2. Welche Formular-Elemente haben wir in unserer .NET-Applikation be-
     nutzt (Abb. 10.10) ?
  3. Wie wird die Verbindung zwischen Funktionen und grafischen Formular-
     Elementen hergestellt ?
  4. Wie wird die Verbindung zwischen Daten und grafischen Formular-Elementen
     hergestellt ?
  5. Was bedeutet die Definition: private: System::Windows::Forms::Button
     MyButton ?
  6. Was bedeutet die Definition: private: System::Void button3 Click()
     ?
10.6 TESTFRAGEN                                                       103



  7. Wie wird ein Formular aufgerufen (Funktion der Klasse Form1)?
  8. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten-
     Klasse ?
  9. Wie kann ich Files mit .NET ¨ffnen (welche Klasse) ?
                                 o
Kapitel 11

Qt

Die Panne mit dem Dialog war echt nicht geplant, d.h. dass MFC Dialoge mit
der freien MSVC++ Express Version nicht mehr verf¨ gbar sind. Dies zeigt uns
                                                       u
aber, auch beim Programmieren niemals nur auf ein Pferd setzen. Wichtig ist,
unser eigener Code muss C++ Standard sein, den k¨nnen wir dann problemlos
                                                     o
in verschiedene GUI Frameworks, wie MSVC++, Qt etc. einbauen.
                                            ¨
Warum jetzt noch Qt ? Wir werden in den Ubungen sehen, dass Qt sehr dicht
an C++ Standards dran ist und Qt ist ’a cross-platform GUI’. Qt l¨uft auf Win-
                                                                   a
dows, Linux, Mac ... In der Anlage 12.8 finden sie eine Anleitung zur Installation
von Qt.


11.1      Hello Qt
Wie es sich f¨ r ein ordentliches Programmier-Framework geh¨rt, ist die erste
             u                                             o
¨
Ubung ”Hello World” auf graphisch.
¨
Ubung: 11.1

#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[])
{
  QApplication app(argc,argv);
  QLabel *label = new QLabel("Hello Qt!");
  label->show();
  return app.exec();
}

Sehr erfreulich ist die N¨he von Qt zum Standard C++, es gibt eine klassische
                         a
main() Funktion. Die Komposition von ”Hello Qt” ist sehr einfach:

                                      104
11.2 EXECUTABLE                                                            105



   • Es wird eine Qt Application angelegt (¨hnlich wie bei Windows, aber doch
                                           a
     irgendwie einfacher),
   • Es wird ein Label angelegt, das mit der Methode →show() angezeigt wird.

Qt bietet auch die M¨glichkeit, einfach HTML code zu integrieren. Ersetzen sie
                    o
die QLabel Zeile wie folgt.

  QLabel *label = new QLabel("<h2><i>Hello<!i>""<font color=red>Qt!</font></h2>");




                          Abbildung 11.1: Hallo Qt



11.2      Executable
Um ein ausf¨ hrbares Qt Programm zu erzeugen ben¨tigen wir 3+1 Schritte:
           u                                    o

   • Gehen sie in ihre Start - Programme Men¨ (Windows) und starten sie die
                                            u
     den Qt command prompt (Fig. 11.2).




                    Abbildung 11.2: Qt Kommando Zeile


   • Mit qmake -project erzeugen sie ein Qt Projekt.
   • Mit qmake legen sie ein makefile an.
   • Mit mingw32-make (kein Leerzeichen) kompilieren sie das Projekt und
     generieren ein ausf¨ hrbares Programm.
                        u
   • Mit E10 1 HelloQt.exe starten sie das Programm.
106                                                              KAPITEL 11 QT



.




                   Abbildung 11.3: Die Schritte in Bildern ...




11.3       Quit
      a      ¨
Die n¨chste Ubung zeigt uns, wie einfach mit Schaltfl¨chen (Push Button) ge-
                                                    a
arbeitet werden kann.

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication app(argc,argv);
  QPushButton *button = new QPushButton("Quit");
  QObject::connect(button, SIGNAL(clicked()),&app, SLOT(quit()));
  button->show();
  return app.exec();
}

Im Unterschied zu ”Hello Qt” ist eine Kommunikation mit dem Anwender
(dr¨ cken der Schaltfl¨che) notwendig. Die Signalverarbeitung erfolgt uber die
   u                 a                                               ¨
Object-Methode connect.

    QObject::connect(button, SIGNAL(clicked()),&app, SLOT(quit()));
11.4 DIALOG                                                             107



Dabei wird die Nachricht SIGNAL(clicked()) mit der Schalt߬che Quit mit
                                                          a
einem sogenannten SLOT(quit())) verbunden.




                          Abbildung 11.4: Hallo Qt



11.4     Dialog
Zum Abschluss unsere Dialog-Anwendung. Dabei wird in der main Funktion
eine Instanz der Klasse QDialog erzeugt.

#include <QtGui/QApplication>
#include "dialog.h"

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  Dialog w;
  w.show();
  return a.exec();
}


Der Header des Dialogs enth¨lt im Wesentlichen die Resourcen-Elemente, z.B.
                           a
die Schalt߬che pushButtonReadDB zum Lesen der Datenbank sowie die dazu-
           a
geh¨rigen Funktionen on pushButtonReadDB clicked().
    o

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;

    QListWidget   *listWidget;
    QPushButton   *pushButtonReadDB;
    QPushButton   *pushButtonAdd;
    QPushButton   *pushButtonDelete;
108                                                          KAPITEL 11 QT



      QLineEdit *lineEditNameFirst;
      QLineEdit *lineEditNameLast;

private slots:
    void on_pushButtonReadDB_clicked();
    void on_pushButtonAdd_clicked();
    void on_pushButtonDelete_clicked();
    void on_listWidget_clicked();
};


Die Implementierung des Dialogs besteht aus drei Teilen:

  1. Konstruktion der grafischen Resourcen-Elemente: pushButton (Schaltfl¨chen),
                                                                       a
     listWidget (Liste), lineEdit (Editierfelder),

  2. Signalverarbeitung: Wenn pushButtonReadDB gedr¨ ckt wurde, f¨ hre die
                                                   u             u
     Funktion on pushButtonReadDB clicked aus,

  3. Layout: Es werden horizontale und vertikale Boxen angelegt.

Dialog::Dialog(QWidget *parent)
    : QDialog(parent), ui(new Ui::Dialog)
{
  ui->setupUi(this);

  // 1.1 - pushButton
  pushButtonReadDB = new QPushButton(tr("&Read DB"));
  pushButtonAdd = new QPushButton(tr("&Add DS"));
  pushButtonDelete = new QPushButton(tr("&Delete DS"));
  // 1.2 - listWidget
  QString name = "Tom Hanks";
  QStringList names;
  names << name << "Alice Wunderland" << "Bob Dylan" << "Carol Crow"
                 << "Donald Dug" << "Emma Thomson";
  listWidget = new QListWidget();
  for (int row = 0; row < 5; ++row) {
    listWidget->addItem(names[row]);
  }
  //1.3 - lineEdit
  lineEditNameFirst = new QLineEdit();
  lineEditNameFirst->insert("Tom");
  lineEditNameLast = new QLineEdit();
  lineEditNameLast->insert("Hanks");
  // 2 - connect
  connect(pushButtonReadDB,SIGNAL(clicked()),this,SLOT(on_pushButtonReadDB_clicked()));
  connect(pushButtonAdd,SIGNAL(clicked()),this,SLOT(on_pushButtonAdd_clicked()));
  connect(pushButtonDelete,SIGNAL(clicked()),this,SLOT(on_pushButtonDelete_clicked()));
  connect(listWidget,SIGNAL(itemSelectionChanged()),this,SLOT(on_listWidget_clicked()));
  //3 - Layout
11.4 DIALOG                                                             109



    QHBoxLayout *leftTopLayout = new QHBoxLayout;
    leftTopLayout->addWidget(lineEditNameFirst);
    leftTopLayout->addWidget(lineEditNameLast);
    QVBoxLayout *leftLayout = new QVBoxLayout;
    leftLayout->addLayout(leftTopLayout);
    leftLayout->addWidget(listWidget);
    QVBoxLayout *rightLayout = new QVBoxLayout;
    rightLayout->addWidget(pushButton);
    rightLayout->addWidget(pushButtonAdd);
    rightLayout->addWidget(pushButtonDelete);
    rightLayout->addStretch();
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addLayout(leftLayout);
    mainLayout->addLayout(rightLayout);
    setLayout(mainLayout);
}


Das Ergebnis der Dialog-Implementierung sehen wir in Abb. 11.5.




                          Abbildung 11.5: Qt Dialog

Um zu pr¨ fen, ob die Signalverarbeitung hinter den Kn¨pfchen funktioniert,
          u                                           o
rufen wir eine MessageBox auf.


void Dialog::on_pushButtonAdd_clicked()
{
  QMessageBox msgBox;
  msgBox.setText("pushButtonAdd clicked");
  msgBox.exec();
}
110                                                               KAPITEL 11 QT



Dies soll als kurze Einf¨ hrung in Qt erstmal gen¨ gen, es geht weiter im n¨chsten
                        u                        u                         a
Semester.
Part III
Anlagen / Software
Kapitel 12

Software-Installation




             112
12.1 CYGWIN INSTALLATION                                                     113



12.1      cygwin Installation
In dieser Anlage finden sie eine Anleitung zur Installation von cygwin - dies ist
eine Linux-Umgebung f¨ r Windows. In dieser Umgebung k¨nnen sie die GNU
                       u                                    o
C und C++ Compiler verwenden.




Abbildung 12.1: Schritt 1: Gehen sie auf cygwin Web Seite - www.cygwin.com.
Klicken sie auf das cygwin Symbol (Install or update now!).




Abbildung 12.2: Schritt 2: Laden sie die setup.exe Datei auf ihren Rechner
herunter und f¨ hren sie die setup.exe aus.
              u
114                                       KAPITEL 12 SOFTWARE-INSTALLATION



.




Abbildung 12.3: Schritt 3: Das cygwin setup Programm wird gestartet. Hier se-
hen sie auch die aktuelle Versionsnummer (2.573.2.3). Best¨tigen sie mit Weiter.
                                                          a




Abbildung 12.4: Schritt 4: W¨hlen sie das Verzeichnis zur Installation von
                             a
cygwin aus, z.B. das Verzeichnis, in dem die Anwendungsprogramme sind
(C:/Programme). Behalten sie die Voreinstellungen. Best¨tigen sie mit Weiter.
                                                       a
12.1 CYGWIN INSTALLATION                                                     115



.




Abbildung 12.5: Schritt 5: cygwin ben¨tigt ein tempor¨res Verzeichnis f¨ r die
                                        o               a                  u
Installation, das sp¨ter gel¨scht werden kann. Behalten sie die Voreinstellungen.
                    a       o
Best¨tigen sie mit Weiter.
    a




Abbildung 12.6: Schritt 6: Benutzen sie die voreingestellte direkte Internetver-
bindung. Best¨tigen sie mit Weiter.
             a
116                                          KAPITEL 12 SOFTWARE-INSTALLATION



.




Abbildung 12.7: Schritt 7: W¨hlen sie die download site, am besten die Dresdner:
                             a
http://ftp.inf.tu-dresden.de; Best¨tigen sie mit Weiter.
                                  a


Liste der 6 zu installierenden Pakete aus der Kategorie ’Devel’:

      • binutils: The GNU assembler linker and binary utilities (release 20080624-
        2) [6MB]
      • gcc-core: C compiler (release 3.4.4.999) [3.6MB]
      • gcc-g++: C++ compiler (release 3.4.4.999) [7.8MB]
      • gcc-mingw-core: support headers and libraries for GCC (release 20050522-
        1) [69kB]
      • gcc-mingw-g++: support headers and libraries for GCC C++ (release
        20050522-1) [1.9MB]
      • mingw-runtime library (release 3.15.2-1) [372kB]
12.1 CYGWIN INSTALLATION                                                    117



.




Abbildung 12.8: Schritt 8: Nun erscheint die Liste der packages, die installiert
                ¨
werden k¨nnen. Offnen sie dem Baum Devel (klicken Sie auf das Plus-Symbol).
        o
W¨hlen sie die oben aufgef¨ hrten Pakete aus, welche f¨ r die Installation von C
  a                        u                          u
und C++ ben¨tigt werden. Best¨tigen sie mit Weiter.
              o                 a


Die nachfolgenden Abbildungen zeigen ihnen, welche Markierungen aktiviert
sein m¨ ssen, um den C (GCC) und den C++ (G++) zu installieren. Eigentlich
       u
reicht es, die binutils, gcc-core und gcc-g++ auszuw¨hlen, die restlichen
                                                         a
Pakete (mingw) m¨ ssten automatisch aktiviert werden. Egal, uberpr¨ fen sie, ob
                  u                                         ¨      u
alles wie in den nachfolgenden Abbildungen markiert ist. Viel Erfolg!
118                                       KAPITEL 12 SOFTWARE-INSTALLATION



.




           Abbildung 12.9: Schritt 8a: (aktive) Auswahl der binutils




    Abbildung 12.10: Schritt 8b: (aktive) Auswahl der C und C++ Compiler

Die nachfolgenden Pakete sollte automatisch markiert werden, bitte uberpr¨ fen
                                                                   ¨     u
sie dies sicherheitshalber.
12.1 CYGWIN INSTALLATION                                                    119



.




    Abbildung 12.11: Schritt 8c: (automatische) Auswahl von Hilfspaketen




    Abbildung 12.12: Schritt 8d: (automatische) Auswahl von Hilfspaketen




Abbildung 12.13: Schritt 9: Behalten sie die Voreinstellungen, um eine cygwin
Verkn¨ pfung auf ihrem desktop zu erstellen. Schließen sie die Installation ab.
     u
120                                       KAPITEL 12 SOFTWARE-INSTALLATION



Im Ergebnis der Installation erhalten sie eine desktop Verkn¨ pfung mit cygwin,
                                                            u
das nun mit einem Doppelklick gestartet werden kann.




          Abbildung 12.14: Schritt 8d: cygwin desktop Verkn¨pfung
                                                           u

Starten sie cygwin mit einem Doppelclick auf die desktop Verkn¨pfung.
                                                              u




                      Abbildung 12.15: Start von cygwin

Mit einem Rechtsklick auf den oberen Balken gelangen sie in das Eigenschaften-
Menu und k¨nnen Einstellungen (z.B. Farben) nach ihrem Geschmack andern.
           o                                                          ¨
12.1 CYGWIN INSTALLATION                                                     121



.




            Abbildung 12.16: Das Eigenschaften-Menu von cygwin


Testen sie, ob die Compiler einsetzbar sind, indem sie diese einfach aufrufen:

    • gcc - Aufruf des C Compilers
    • g++ - Aufruf des C++ Compilers

Da sie die Compiler ohne etwas zu tun aufrufen, erhalten sie die Meldung: keine
Eigabedateien.




                    Abbildung 12.17: Aufruf der Compiler

Nun kann es also endlich losgehen mit der ersten Ubung ⇒ Abschnitt 1.4.
                                                 ¨
122                                     KAPITEL 12 SOFTWARE-INSTALLATION



12.2       LINUX

12.2.1      ¨
            Ubersicht einiger grundlegenden Linux-Befehle

      Befehl / command    Bedeutung
 Hilfe
            man           Klassische Hilfe (verlassen mit Q)
           info           Online Hilfe von GNU (verlassen mit Q)
          apropos         Schl¨ sselw¨rtersuche bei “man“-Seiten
                              u      o
          whatis          Kurzbeschreibung zu einem Kommando oder Schl¨ sselwort
                                                                      u
 Dateien
             ls           Dateien auflisten
          ls -attr        Dateiattribute auflisten
            file          Dateityp ermitteln
       cp Quelle Ziel     Kopiert Quelle nach Ziel
      mv Datei1 Datei2    Datei1 umbenennen in Datei2
         mv Datei V1      Verschiebt Datei in das Verzeichnis V1
         rm Dateien       Dateien l¨schen
                                   o
      rmdir Verzeichnis   Verzeichnis l¨schen
                                       o
            find          Suche nach Dateien
            find/         Suche startet im Root-Verzeichnis / im ganzen System
 Verzeichnisse
            pwd           gibt aktuelles Arbeitsverzeichnis an
             ./           aktuelles Verzeichnis
             cd           Wechsel des aktuellen Verzeichnisses
           mkdir          ein Verzeichnis anlegen
       rm Verzeichnis     ein Verzeichnis l¨schen
                                           o
           rmdir          ein leeres Verzeichnis l¨schen
                                                  o
             ls           Verzeichnisinhalt auflisten
 Systembefehle
     shutdown -h          Herunterfahren des Systems
   shutdown Uhrzeit       Herunterfahren des Systems bei Uhrzeit (z.B.: 14.00)
 shutdown -t Sekunden     Herunterfahren des Systems nach Anzahl der Sekunden
      reboot oder
     shutdown -r          Neustart des Systems
         uname            Systeminformationen ausgeben

      ¨
Diese Ubersicht basiert auf ’Linux auf einem Blatt’ von Christian Helmbold
(www.helmbold.de) (siehe n¨chste Seite)
                           a
12.2 LINUX                                                                   123



weitere Informationen und Erkl¨rungen
                              a
         ¨
deutsche Ubersichten:
      ¨
- Pdf-Ubersicht ’Linux auf einem Blatt’ (auch zum Download)
www.helmbold.de/linux
- Linux-Befehle f¨ r Einsteiger
                  u
http://www.linux-fuer-alle.de/doc show.php?docid=33
  ¨
- Ubersicht f¨ r wichtige Linux-Befehle und Programme
             u
http://www.tnt-computer.de/yanip/lbefehle.html
          ¨
englische Ubersichten
               ¨
- umfangreiche Ubersicht mit Parametern und Beispielen
http://www.computerhope.com/unix.htm#04
- Vergleich zwischen MS-DOS- und Linux-Befehlen
http://www.yolinux.com/TUTORIALS/unix for dos users.html
Wir arbeiten uns jetzt mal mit der online-Hilfe ’man’ (steht f¨ r Manual) weiter
                                                              u
vor.




                  Abbildung 12.18: Benutzen der online Hilfe

Mit dem Befehl man ls k¨nnen wir uns die Optionen von ls (Dateien auflisten)
                       o
anzeigen lassen.
124                               KAPITEL 12 SOFTWARE-INSTALLATION



.




      Abbildung 12.19: Optionen von ls (Dateien auflisten)
12.2 LINUX                                                                 125



12.2.2       Profile

Wir n¨hern uns der L¨sung, einfach in das Verzeichnis zu gelangen, in dem sich
       a              o
         ¨                  ¨
unsere Ubungen befinden. Ahnlich wie in DOS die Programme autoexec.bat
und config.sys beim Start des Betriebsystems automatisch ausgef¨ hrt werden,
                                                                  u
ist es bei LINUX ein so genanntes Profile: .bash profile. In diese Datei k¨nnen
                                                                         o
eigene Befehle eingetragen werden.
Eigentlich ist es ganz einfach ....

cd C:/User/TEACHING/C++/EXERCISES


Durch diese Instruktion in der .bash profile wechseln wir direkt in das Ver-
                             ¨
zeichnis, in dem sich unsere Ubungen befinden.
Nachdem wir verschiedene Editoren ausprobiert haben (und erhebliche Unter-
schiede in der Behandlung von Zeilenenden (CR) gesehen haben), ließ sich zu
       ¨
allem Ubel unsere m¨ hsam editierte .bash profile mit dem Windows-Explorer
                       u
nicht speichern (es liegt an dem Punkt am Anfang des Datei-Namens). Ich kann
ihre Entt¨uschung gut verstehen, nicht umsonst gibt es Windows und Linux-
          a
Anh¨nger. Dennoch m¨ ssen wir eine L¨sung finden oder ?
    a                    u             o


12.2.2.1     L¨sung 1: unix2dos
              o

Nach unserem Schiffbruch mit dem Speichern einer ’.bash profile’ unter Win-
dows (’denkt’ vor dem Punkt kommt der Datei-Name und nach dem Punkt die
File-Extension, also nix vor dem Punkt heißt f¨ r Windows, kein Datei-Name ...
                                              u
so ist das, wenn Programme zu viel denken).
Die zweite L¨sung ist eine Dateikonvertierung. Linux bietet zwei Programme an:
            o
dos2unix und unix2dos, mit denen man Dateien plattformgerecht konvertieren
kann (Fig. 12.20)




           Abbildung 12.20: Wandeln zwischen Linux und Dos-Dateien
126                                       KAPITEL 12 SOFTWARE-INSTALLATION



12.2.2.2   L¨sung 2: Cygwin (the Linux point of view)
            o

Wir brauchen einen ’einfachen’ Editor f¨ r cygwin, d.h. wir m¨ ssen nachinstal-
                                       u                     u
lieren (siehe Abschn. )




               Abbildung 12.21: Nachinstallieren des vi Editors

Nach der vi Installation m¨ ssen wir in das Verzeichnis (home directory) gelan-
                          u
gen, wo sich die .bash profile Datei befindet.




             Abbildung 12.22: home directory und dessen Inhalt
12.2 LINUX                                                                      127



Wir ¨ffnen die .bash profile Datei mit dem vi Editor wie folgt:
    o




                    Abbildung 12.23: Starten des vi Editors



Jetzt k¨nnen wir mal einen Linux-Editor live erleben (danach werden sie Win-
        o
                                             ¨
dows noch mehr ’lieben’ ...). Nach dem Offnen der Datei gehen sie mit dem
Kursor dorthin, wo sie Text einf¨ gen m¨chten. Dann dr¨ cken sie die ’i’ Taste,
                                   u       o              u
der insert Modus wird gestartet. Nun k¨nnen sie den Befehl zum Wechseln in ihr
                                         o
¨                                            ¨
Ubungsverzeichnis eingeben cd ... Um die Anderungen zu speichern, dr¨ cken sie
                                                                           u
’Esc’ ’:’ ’w’. vi wechselt nun in den File-Modus ’w’ steht f¨ r write ... so einfach
                                                            u
ist das.




                   Abbildung 12.24: Editieren und speichern
128                                      KAPITEL 12 SOFTWARE-INSTALLATION



 Befehl   Wirkung
 i        Wechseln in den Insert/Einf¨ ge-Modus
                                     u
 a        Wechseln in den Append/Anh¨ngen-Modus
                                        a
 Esc:     Wechseln in den Kommando-Modus
 w        Write: Datei speichern (im Kommando-Modus)
 q                          ¨
          Quit: Datei ohne Anderung verlassen (im Kommando-Modus)
 q!                         ¨
          Quit: Datei ohne Anderung verlassen (im Kommando-Modus)


12.2.3    Make
Mit den Make utilities k¨nnen ganze Projekte kompiliert werden, die aus vielen
                        o
Quelltext-Dateien bestehen. Nachfolgend sehen sie die Instruktionen des ma-
kefile f¨ r die Kompilierung unseres Projekts. Dabei werden die Quell-Dateien
       u
main.cpp und student.cpp kompiliert, gelinkt und die ausf¨ hrbare Datei a.exe
                                                         u
erzeugt.

#
OPTFLAG = -O3
C++     = g++ $(OPTFLAG) -Wall
CFile = main.cpp student.cpp
OFile = main.o student.o
.SUFFIXES: .o .cpp .h
.cpp.o:
$(C++) -c -o $*.o     $<
main: $(OFile)
$(C++) -o main $(OFile)
clean:
rm -f *.o
¨
12.3 SCHUSSELWORTE IN C++                                                129



12.3     Schusselworte in C++
            ¨
                                            ¨
Die nachfolgende Tabelle gibt ihnen eine Uberblick der C++ Schl¨ sselworte.
                                                                    u
Wir werden die Tabelle sukzessive f¨ llen aber nicht alle Keywords benutzen.
                                   u

               Keyword     Bedeutung     Benutzung im Kapitel
               bool        Datentyp      2
               char        Datentyp      2
               double      Datentyp      2
               float        Datentyp      2
               int         Datentyp      2
               long        Datentyp      2
               short       Datentyp      2
               void        Datentyp      2
               wchar t     Datentyp      2

                         Tabelle 12.1: Schl¨ sselworte
                                           u
130                                     KAPITEL 12 SOFTWARE-INSTALLATION



12.4     MS VC++ Projekt #1 - Eine Konsolenan-
         wendung
In dieser Anlage finden sie eine Anleitung zur Erstellung eines MS VC++ Pro-
jekts.




      Abbildung 12.25: Schritt 1: Starten sie MS Visual Studio (MSVS)
12.4 MS VC++ PROJEKT #1 - EINE KONSOLENANWENDUNG                        131



.




Abbildung 12.26: Schritt 2: Gehen sie zu File - New und w¨hlen sie ’Project
                                                         a
from existing code’




Abbildung 12.27: Schritt 3: W¨hlen sie ein ’Visual C++’ Projekt. Sie sehen,
                             a
dass mit MSVS auch andere Projekte (z.B. Java) erzeugen k¨nnen
                                                         o
132                                       KAPITEL 12 SOFTWARE-INSTALLATION



.




Abbildung 12.28: Schritt 4: Richten sie am besten vorher ein neues Unterver-
zeichnis ein, in dem die Projektdateien gespeichert werden sollen ... es werden
einige Dateien sein. Kopieren sie das/die Quell-Files (hier copy.cpp) in dieses
Verzeichnis. W¨hlen sie mit ’Browse’ (nur) das Verzeichnis aus und vergeben
                a
sie einen Projektnamen (hier ’msvcp1’). Gehen sie weiter ’next’




Abbildung 12.29: Schritt 5: W¨hlen sie als Projekt-Typ ’Console application
                               a
project aus’. (Sp¨ter werden wir auch Windows-Applikationen erstellen, nur
                 a
Geduld). Schließen sie ab ’finish’
12.4 MS VC++ PROJEKT #1 - EINE KONSOLENANWENDUNG                             133



.




Abbildung 12.30: Nun m¨ ssten sie folgendes Bild sehen. Der ’solution explorer’
                         u
auf der linken Seite zeigt ihnen ihr Projekt ’msvcp1’ an und hat automatisch
das Quell-File copy.cpp in das Projekt eingetragen.




Abbildung 12.31: Wenn wir in unser Projekt-Verzeichnis schauen, sehen wir,
dass MSVS einige Dateien f¨ r uns angelegt hat. Das eigentlich Projekt-File ist:
                          u
msvcp1.vcproj. Mit einem Doppelklick darauf wird das Projekt geladen.

Das war’s erstmal.
134                                        KAPITEL 12 SOFTWARE-INSTALLATION



12.5      MFC-Dialog
Dialoge geh¨ren zu den einfachsten Anwendungen von grafischen Benutzer-
             o
schnittstellen (GUI graphical user interface). Ihre Aufgabe ist, es eine grafisch-
gest¨ tzte Interaktion (Dialog) mit einem Programm zu erm¨glichen. In der
    u                                                           o
Anlage finden sie die entsprechenden Schritte f¨ r die Dialog-Anwendung mit
                                                  u
VC++2005




                   Abbildung 12.32: Starten von VC++2005

Nach dem Starten von VC++ (Fig. 12.32) m¨ ssen wir ein neues Projekt anlegen
                                        u
(Fig. 12.33).
12.5 MFC-DIALOG                                                            135



.




              Abbildung 12.33: Klick 1: Neues Projekt anlegen


W¨hlen sie ’MFC Application’ aus. W¨hlen Sie im unteren Teil des Dialogs (Fig.
  a                                    a
12.34) das Verzeichnis f¨ r ihr Dialog-Projekt und geben sie ihm einen Namen.
                        u
Der ’Projektgruppen-Name’ wird automatisch vergeben.




           Abbildung 12.34: Klick 2: MFC Applikation ausw¨hlen
                                                         a
136                                      KAPITEL 12 SOFTWARE-INSTALLATION



.




               Abbildung 12.35: Klick 3: Einfach weiter (next)


W¨hlen sie ’Dialog based’ und ihre Sprache aus (Abb. 12.36) und schließen sie
  a
ab (Finish).




Abbildung 12.36: Klick 4: Auswahl des Applikations-Typs (Dialog, SDI, MDI)
12.5 MFC-DIALOG                                                             137



In dem Moment, wenn sie ’Finish’ dr¨ cken (Klick 5), wird der gesamte Quell-
                                     u
Code f¨ r ihre Dialog-Anwendung erzeugt. Mit ’Ctrl-F5’ oder Debug → ’Start
      u
without debugging’ ubersetzen sie den Quell-Code und starten ihre erste Dialog-
                    ¨
Applikation (Fig. 12.37).




                Abbildung 12.37: Die leere Dialog-Anwendung
138                                       KAPITEL 12 SOFTWARE-INSTALLATION



12.6      .NET Formular
Mit dem MSDS (Micro-Soft Developer Studio) 2005 braucht man genau 5
Mausklicks, um eine Dialog-Anwendung zu erstellen (siehe Anlage 12.5), mit
der 2008er Version sind es nur noch 3 f¨ r ein sogenanntes Formular (die Weiter-
                                       u
entwicklung von Dialogen). Wir schauen uns jetzt die Erzeugung der Formular-
Applikation mit VC++2008 an, machen aber dann in Abschn. 10.1 mit der
Dialog-Anwendung weiter.




                  Abbildung 12.38: Starten von VC++2008
12.6 .NET FORMULAR                                                       139



Nach dem Starten von VC++ (Fig. 12.38) m¨ ssen wir ein neues Projekt anlegen
                                        u
(Fig. 12.39).




              Abbildung 12.39: Klick 1: Neues Projekt anlegen




           Abbildung 12.40: Klick 2: Windows Form-Anwendung

W¨hlen sie ’CLR’ (Erkl¨rung folgt) → ’Windows Form-Anwendung’ aus. ’Win-
 a                    a
140                                       KAPITEL 12 SOFTWARE-INSTALLATION



dows Forms’ sind die neue Form von ’Windows Dialogen’. W¨hlen Sie im unteren
                                                             a
Teil des Dialogs (Fig. 12.40) das Verzeichnis f¨ r ihr Dialog-Projekt und geben
                                               u
sie ihm einen Namen. Der ’Projektgruppen-Name’ wird automatisch vergeben.
In dem Moment, wenn sie ’OK’ dr¨ cken (Klick 3), wird der gesamte Quell-Code
                                  u
f¨ r ihre Dialog-Anwendung erzeugt. Mit ’Ctrl-F5’ oder Debug → ’Start without
 u
debugging’ ubersetzen sie den Quell-Code (Fig. 12.41) und starten ihre erste
              ¨
Dialog-Applikation (Fig. 12.42).




                                   ¨
       Abbildung 12.41: ’Ctrl-F5’: Ubersetzen und starten des Dialogs




        Abbildung 12.42: Eine ’leere’ Windows Formular-Anwendung
12.7 UBUNTU & WINE                                                          141



12.7      UBUNTU & Wine
Man kann Windows-Applikationen unter UBUNTU starten. Dazu muss das Pro-
gramm ’Wine’ installiert werden. Hier kommt eine kurze Installationsanleitung.
F¨ r den Download und die Installation von Wine Microsoft Windows Com-
 u
patibility Layer ben¨tigen sie nat¨ rlich eine Internetverbindung. Gehen sie zu
                    o             u
Anwendungen > Hinzuf¨ gen/Entfernen > Suche: Wine.
                        u




               Abbildung 12.43: Anwendung Wine hinzuf¨ gen
                                                     u

Nun werden die Paketdateien f¨ r Wine heruntergeladen.
                             u




       Abbildung 12.44: Paketdateien f¨ r Wine werden heruntergeladen
                                      u

Danach werden die Software-Pakete f¨ r Wine installiert.
                                   u
142                                      KAPITEL 12 SOFTWARE-INSTALLATION



.




              Abbildung 12.45: Installation der Software-Pakete


Zur Ausf¨ hrung der Windows exe Datei gehen sie wie folgt vor: Rechtsklick auf
        u
Datei > Mit >>Wine Windows-Programmstarter<< ¨ffnen, die Anwendung
                                                      o
wird nun wie unter Windows ausgef¨hrt.
                                 u
Installierte Programme werden in einem Windows nachempfundenen Verzeich-
nissystem installiert z.B. home/user/.wine/dosdevices/c: sowie
home/user/.wine/dosdevices/c:/Programme. Installierte Programme/Anwendun-
gen k¨nnen unter Anwendungen > Wine > Programme bzw. Durchsuche C:
      o
gefunden werden.
12.8 QT INSTALLATION        143



12.8      Qt Installation
Qt installation
144                                      KAPITEL 12 SOFTWARE-INSTALLATION



Zur Qt Installation gehen sie auf folgende Web-Seite und folgen den Schritten
gem¨ß den Abbildungen: http://www.qtsoftware.com/products/. W¨hlen die
     a                                                              a
freie LGPL Lizenz.




Dabei wird die Installationsdatei f¨ r das entsprechende Betriebssystem herun-
                                   u
tergeladen (Abb. 12.46).




             Abbildung 12.46: Qt Installationsdatei f¨ r Windows
                                                     u

Nach der Installation haben sie den Qt Creator zur Verf¨ gung (Abb. 12.47).
                                                       u




                        Abbildung 12.47: Qt Creator
Kapitel 13

Students Forum

Vielen Dank f¨ r Ihre Fragen zur ersten Vorlesung!
             u


13.1      Vorlesung 1: 17.04.2009
JB Der C compiler funktioniert, der C++ aber nicht: Wahrscheinlich haben
    sie nur den C Compiler (GCC) installiert. Die k¨nnen jederzeit cygwin
                                                    o
    Komponenten nachinstallieren , siehe Abschn. 12.2.2.2.
                                                    ¨
DB Ich habe den MS VC++ installiert und kann die Ubungen nachvollziehen.
    Brauche ich den GNU Compiler von cygwin wirklich noch ?: Eigentlich
    nicht, mit MS VC++ haben sie einen kompletten Compiler mit allem
    drum und dran, dennoch kann ein Ausflug in die Konsolenwelt ja nicht
    schaden ... und sie k¨nnen sp¨ter in ihre Bewerbungen schreiben, dass sie
                         o       a
    auch unter Linux Programme entwickelt haben.
MF Die aktuelle cygwin Installation sieht anders aus als im Skript beschrieben:
   [OK] Im Anhang (Abschn. 12.2.2.2) finden sie eine bessere Beschreibung
   der cygwin Installation.
 C++ und Mac: erstmal eine Adresse http://developer.apple.com/TOOLS/xcode/




                                     145
Kapitel 14

Questions

14.1     Testfragen - Kapitel 1 - Einfuhrung
                                      ¨
  1. Was bedeutet das ++ im Namen der Programmiersprache C++ ?

  2. Ist C++ eine standardisierte Programmiersprache ?

  3. Was ist der Unterschied zwischen C und C++ ?

  4. Was sind sogenannte Programmier-Paradigmen ?

  5. Welche verschiedenen Programmier-Paradigmen kennen sie und worin un-
     terscheiden sie sich ?

  6. Welches Paradigma verfolgen wir in der Vorlesung ?

  7. Was ist objekt-orientierte Programmierung ?

  8. Was ist ein Kompiler ?

  9. Erkl¨ren sie die einzelnen Schritte bei einer Kompilierung (s. Abb. 1.4).
         a

                                                ¨
 10. Welchen Kompiler benutzen sie f¨ r die C++ Ubungen ?
                                    u

 11. Welche Funktion ben¨tigt jedes C oder C++ Programm ?
                        o

 12. Was ist der Typ einer Funktion ?

 13. Was ist eine Parameterliste einer Funktion ?

 14. Was ist der R¨ ckgabewert einer Funktion ?
                  u


                                     146
14.2 TESTFRAGEN - KAPITEL 2 - DATENTYPEN                                 147



14.2     Testfragen - Kapitel 2 - Datentypen
  1. Was ist der genaueste Datentyp in C++ ?

  2. Wie groß ist der Speicherbedarf von einem string Datentyp ?

  3. Mit welcher Anweisung k¨nnen wir den Speicherbedarf von elementaren
                            o
     Datentypen ermitteln ?

  4. Was sind Escape-Sequenzen ?

  5. Was ist der Unterschied zwischen den Escape-Sequenzen n und r ?

  6. Was ist die C++ Entsprechung der Klasse cout f¨ r einen Zeilenumbruch
                                                   u
     ?


14.3     Testfragen - Kapitel 3 - Ein- und Ausgabe
         I
  1. Sind sie mit der Tab. 2.2 einverstanden ?

  2. Welche Ein- und Ausgabeger¨te kennen sie ?
                               a

  3. Welche Klasse ben¨tigen wir f¨ r die Standard-Ein- und Ausgabe ?
                      o           u

  4. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ?
                               u

  5. Mit welcher Klasse k¨nnen wir sowohl Eingabe- als auch Ausgabestr¨me
                         o                                            o
     benutzen ?

  6. Welche Include-Datei ist notwendig, um mit I/O-Str¨men arbeiten zu
                                                       o
     k¨nnen ?
      o

  7. Wozu dient der Zusatz using namespace std; nach dem Include von
     Standard-Klassen, wie I/O Streams ?

  8. Was bewirken die Stream-Operatoren << und >> ?

  9. Was bewirken die Flags oct, dec, hex f¨ r die formatierte Ausgabe von
                                           u
     Ganzzahlen ? (ToDo)

 10. Wie kann ich die Genauigkeit der Ausgabe von Gleikomma-Zahlen festle-
     gen ?

 11. Wie kann man den Speicherbedarf einer Variable ermitteln ? Schreiben
     sie die C++ Anweisung f¨ r die Berechnung des Speicherbedarfs f¨ r eine
                            u                                       u
     doppelt-genaue Gleitkomma-Zahl.
148                                                    KAPITEL 14 QUESTIONS



14.4     Testfragen - Kapitel 4 - Klassen
  1. Geben sie eine Definition von C++ Klassen mit eigenen Worten (max 5
     S¨tze).
      a
  2. Was ist ein benutzerdefinierter Datentyp ?
  3. Welches Datennschutz-Konzept gibt es f¨ r Klassen ?
                                           u
  4. Wozu brauchen wir zwei Dateien f¨ r Klassen, eine H (Header) Datei und
                                     u
     eine CPP (Quelltext) Datei ?
  5. Was ist ein Inklude / Include ?
  6. Was ist eine Instanz einer Klasse ?
  7. Worin besteht der Unterschied zwischen den Anweisungen: CStudent m std 1
     und CStudent* m std 2 ?
  8. Was ist ein Konstruktor einer Klasse ?
  9. Was ist das Gegenst¨ ck zum Klassen-Konstruktor ?
                        u
 10. Wie k¨nnen Daten / Variablen einer Klasse initialisiert werden ?
          o
 11. Schreiben sie den Quelltext f¨ r den Klassen-Konstruktor und weisen sie
                                  u
     den Variablen name first und name last ihren eigenen Namen zu.
 12. Was verbirgt sich hinter der Anweisung: CStudent* m std = new CStudent()
     ?
 13. Was ist der Unterschied zwischen CStudent und CStudent() ?
 14. Wie kann ich meine Daten gegen einen externen Zugriff sch¨ tzen ?
                                                             u


14.5     Testfragen - Kapitel 5 - Strings
  1. Welche Klasse bietet uns C++ zur Verarbeitung von Zeichenketten an ?
  2. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Zeichenketten ?
                        o           u
  3. Wof¨ r ist die Anweisung using namespace std n¨ tzlich ?
        u                                          u
  4. M¨ ssen wir selber Speicherplatz f¨ r C++ Zeichenketten (Strings) reser-
       u                               u
     vieren ?
  5. Wie k¨nnen wir einen String, sagen wir mit der Zeichenkette ”Das ist eine
           o
     gute Frage”, initialisieren ?
  6. Wie k¨nnen wir zwei Strings, ihren Vor- und Nachnahmen, miteinander
           o
     verbinden ?
14.6 TESTFRAGEN - KAPITEL 6 - EIN- UND AUSGABE II                         149



  7. Mit welcher string Funktion kann ich Zeichenketten miteinander verglei-
     chen ?

  8. Schreiben sie eine Anweisung zum Vergleich der Klassen-Variable
     m std− >name last mit ihrem Nachnamen ?

  9. Mit welcher string Funktion kann ich Zeichenketten suchen ?

 10. Schreiben sie eine Anweisung zum Suchen ihres Vornamens in der Klassen-
     Variable m std− >name first ?

 11. Mit welcher string Funktion kann ich Teile in Zeichenketten erstetzen ?

 12. Wie k¨nnen wir die L¨nge von Strings ermitteln ?
          o              a

 13. Schreiben sie die Anweisungen, um ihren Nachnamen in die Zeichenkette
     ”JAMES BOND” nach ”JAMES” einzuf¨ gen ?u

 14. Was passiert, wenn ihr Nachname l¨nger als ”BOND” ist ?
                                      a

 15. Mit welcher string Funktion k¨nnen wir Zeichen in einem String l¨schen ?
                                  o                                  o

 16. Wir haben gesehen, dass es verschiedene Daten-Typen f¨ r Zeichenketten
                                                          u
     in C, C++, MFC, .NET und Qt gibt. Zeichenketten geh¨ren zu den wich-
                                                         o
     tigsten Daten-Typen bei der Programmierung. Wie k¨nnen wir einen C++
                                                      o
     string in eine C Zeichenkette (char) umwandeln ?

 17. K¨nnen wir eine .NET Zeichenkette (String∧) in eine C++ Zeichenkette
       o
     (string) umwandeln ?

 18. Was ist ein stringstream ?

 19. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Stringstreams ?
                        o           u


14.6     Testfragen - Kapitel 6 - Ein- und Ausgabe
         II
  1. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ?
                               u

  2. Was sind die C++ Klassen f¨ r das Lesen und Schreiben von Dateien ?
                               u

  3. Welchen Include ben¨tigen wir f¨ r das Arbeiten mit I/O File-Klassen ?
                        o           u

  4. Was sind die Standard-Flags f¨ r File-Streams (Lesen und Schreiben) ?
                                  u

  5. Mit welchem Flag k¨nnen wir zu schreibende Daten an eine existierende
                       o
     Datei anh¨ngen ?
              a

  6. Was ist der Unterschied zwischen ASCII- und Bin¨r-Formaten ?
                                                    a
150                                                    KAPITEL 14 QUESTIONS



  7. Mit welchem Flag k¨nnen wir Daten in einem Bin¨r-Format schreiben ?
                          o                         a
     Mit welcher Anweisung wird ein File ge¨ffnet ? Mit welcher Anweisung
                                           o
     wird ein File geschlossen ?

  8. Was bewirken die Stream-Operatoren << und >> ?

  9. Wie k¨nnen wir mit Dateinamen in unserem Hauptprogramm main(...)
           o
     arbeiten ?

 10. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen
                         o           u                                u
     Eingabe-Strom ?

 11. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen
                         o           u                                u
     Ausgabe-Strom ?

 12. F¨ r die Erstellung einer Datenbank ist es wichtig einzelnen Datens¨tze zu
       u                                                                a
     trennen. Wie k¨nnen wir soetwas in der Datenbank-Datei bewerkstelligen
                     o
     ?

 13. Ist es wichtig das Ende einer Datenbank-Datei, z.B. mit einem Schl¨ ssel-
                                                                       u
     wort #STOP, zu markieren ?

                          o          u             ¨
 14. Mit welcher Abfrage k¨nne wir pr¨ fen, ob die Offnung einer Datei erfolg-
     reich war ?

 15. Mit welcher Anweisung k¨nnen wir die aktuell gelesene Position in einer
                             o
     ge¨ffneten Datei abfragen ?
       o

 16. Mit welcher Anweisung k¨nnen wir zu einer bestimmten Position in einer
                             o
     ge¨ffneten Datei springen ?
       o

 17. Mit welcher Anweisung k¨nnen wir eine komplette Zeile aus ge¨ffneten
                            o                                    o
     Datei auslesen ?


14.7     Testfragen - Kapitel 7 - Referenzen und
         Zeiger
  1. Was ist &x ? (x ist ein beliebiger Datenobjekt T, z.B. eine Gleitkomma-
     zahl: double x)

  2. Was ist eine Referenz &ref?

  3. Was bedeutet die Anweisung: &ref = x?

  4. Erkl¨ren sie kurz (mit eigenen Worten) das Zeiger-Konzept in C++?
         a

  5. Was bewirkt der NULL Zeiger, d.h. *ptr = NULL ?

  6. Was bedeutet die Anweisung: ptr = x?
14.8 TESTFRAGEN - KAPITEL 8 - CONTAINER                                     151



  7. M¨ ssen Referenzen (&) und Zeiger (*) auf Daten-Objekte initialisiert wer-
       u
     den ?

  8. Was bewirkt die Definition long l[1000] speichertechnisch ?

  9. Wie groß ist der Speicherbedarf des statischen Datenobjekts long l[1000]
     ?

 10. Wie groß ist der Speicherbedarf des dynamische Datenobjekts long* ptr l
     = new long[1000] ?

 11. Woher kommt der Unterschied (4 Byte auf einem 32Bit Rechner) im
     Speicherbedarf zwischen statischen und dynamischen Datenobjekten.

 12. Zusatzfrage: Was bedeutet die Definition **ptrptr (Zeiger auf Zeiger), was
     f¨ r ein Datenkonstrukt entsteht ?
      u


14.8     Testfragen - Kapitel 8 - Container
  1. Was sind C++ Container ?

  2. Welche Typen von C++ Containern kennen sie ?

  3. Worin besteht der Unterschied zwischen sequentiellen und assoziativen
     Containern ?

  4. Welche sequentiellen Container kennen sie ?

  5. Erkl¨ren sie die Syntax des Vektor-Containers: vector<int>my vector .
         a

  6. Was ist der Unterschied zwischen Vektoren und Listen ?

  7. Was sind die Gemeinsamkeiten von Vektoren und Listen ?

  8. Welcher Include ist notwendig f¨ r das Arbeiten mit Vektoren ?
                                    u

  9. Welcher Include ist notwendig f¨ r das Arbeiten mit Listen ?
                                    u

 10. Ben¨tigen wir den Zusatz (Namensraum) using namespace std, wenn ja
        o
     warum ?

 11. Mit welcher Instruktion k¨nnen Elemente in Vektoren und Listen einf¨ gen
                              o                                         u
     ?

 12. Wo werden sequentielle Container-Elemente mit der Instruktion push back(T)
     eingef¨ gt ?
           u

 13. Mit welcher Anweisung k¨nnen wir die L¨nge von sequentiellen Container-
                            o              a
     Elementen bestimmen ?
152                                                     KAPITEL 14 QUESTIONS



 14. Mit welcher Anweisung k¨nnen wir einen Vektor platt machen (d.h. alle
                            o
     Elemente l¨schen) ?
               o
 15. Wie k¨nnen wir auf ein Vektor-Element, sagen wir das 17te Element des
          o
     Vektors vector<int>my vector, direkt zugreifen ?
 16. Quellcode verstehen: Erkl¨ren sie die Struktur (1,2,3) der DB-Lese-Funktion
                              a
                                          ¨
     STDRead(ifstream& std file) in der Ubung 8.2.2. Beginnen sie mit der Pa-
     rameterliste.
 17. Wie k¨nnen wir unsere Studenten-Klasse CStudent in die DB-Anwendung
          o
      ¨
     (Ubung 8.2.1) einbinden ?
                                       u                          a     ¨
 18. Was ist eigentliche Lesefunktion f¨ r unsere Studenten-Datens¨tze (Ubung
     8.2.2) ?
 19. Mit welchem Befehl k¨nnen wir die Reihenfolge von Listen-Elementen
                         o
     umkehren ?
 20. K¨nnen wir Listen-Elemente sortieren, wenn ja wie, mit welcher Instruk-
       o
     tion ?
 21. Mit welchem Befehl k¨nnen wir mehrere Listen zusammenf¨ hren ?
                         o                                 u
 22. K¨nnen wir doppelte Elemente aus einer Liste entfernen sortieren, wenn
       o
     ja wie, mit welcher Instruktion ?
 23. Was ist ein Iterator ?
 24. Quellcode verstehen: Erkl¨ren sie die Funktion void display(list<int>my list)
                              a
         ¨
     der Ubung 8.3. Beginnen sie mit der Parameterliste.
 25. Wie k¨nnen wir Elemente aus einer Liste entfernen ?
          o


14.9     Testfragen - Kapitel 9 - Andere Sprachele-
         mente
  1. Was sind Kontrollstrukturen, welche kennen sie ?
  2. Bei welcher logischen Bedingung wird eine if-Anweisung ausgef¨ hrt ?
                                                                  u
  3. Lassen sich Kontroll-Strukturen verschachteln ?
  4. Mit welcher Kontrollstruktur k¨nnen wir Fallunterscheidungen program-
                                   o
     mieren ?
  5. Welche Ausdr¨ cke k¨nnen wir bei der switch-case Kontrollstruktur be-
                 u      o
     nutzen ?
  6. Wie kann ich eine Kompiler-Direktive an- und ausschalten ?
14.10 TESTFRAGEN - KAPITEL 10 - DIALOGE                                   153



                       ¨
  7. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle
                                      u
     von #ifdef um.

  8. Erl¨utern sie den Kopf der for-Schleife: for(int i=0;i<stop;i++), wel-
        a
     chen Daten-Typ hat stop ?

  9. Was ist eine Endlos-Schleife, wie kommen wir daraus ?

 10. Was sind Namensbereiche ?

 11. Was m¨ ssen wir tun, um die Arbeit mit C++ Standard-Klassen zu verein-
            u
     fachen, d.h anstelle von std::my string() direkt my string() benutzen
     zu k¨nnen ?
         o

 12. Was sind Kompiler-Direktiven, was bewirken diese ?

 13. Wie k¨nnen wir Kompiler-Direktiven an- und ausschalten ?
          o

 14. Worin besteht der Unterschied bei Includes mit eckigen Klammern < ... >
     bzw. mit G¨nsef¨ ßchen ”...” ?
               a    u
                       ¨
 15. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle
                                      u
     von #ifdef um ?

 16. Was sind Makros ?

 17. Welche beiden Einsatzm¨glickeiten von Makros gibt es ?
                           o
 18. Worin besteht die Gefahr, Makros als Funktionsersatz zu benutzen ?


14.10      Testfragen - Kapitel 10 - Dialoge
MFC

  1. Welche Typen von grafischen Windows-Applikationen kennen sie ?

  2. Was ist eine Dialog-Resource ?

  3. Welche Dialog-Elemente haben wir in unserer Windows-Applikation be-
     nutzt (Abb. 10.3) ?

  4. Was sind IDs ?

  5. Was ist eine MESSAGE MAP ?

  6. Wie wird die Verbindung zwischen Funktionen und grafischen Dialog-
     Elementen hergestellt ?

  7. Wie wird die Verbindung zwischen Daten und grafischen Dialog-Elementen
     hergestellt ?
154                                                 KAPITEL 14 QUESTIONS



  8. Was bedeutet die Definition: class CMyDialog : public CDialog ?
  9. Wie wird ein Dialog aufgerufen (Funktion der Klasse CDialog)?
 10. Was bewirkt die Dialog-Funktion UpdateData() ?
 11. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten-
     Klasse ?
 12. Wie kann ich Files unter Windows ¨ffnen (welche Klasse) ?
                                      o
 13. Was ist ein BMP ?

.NET

  1. Was ist eine Formular-Resource ?
  2. Welche Formular-Elemente haben wir in unserer .NET-Applikation be-
     nutzt (Abb. 10.10) ?
  3. Wie wird die Verbindung zwischen Funktionen und grafischen Formular-
     Elementen hergestellt ?
  4. Wie wird die Verbindung zwischen Daten und grafischen Formular-Elementen
     hergestellt ?
  5. Was bedeutet die Definition: private: System::Windows::Forms::Button
     MyButton ?
  6. Was bedeutet die Definition: private: System::Void button3 Click()
     ?
  7. Wie wird ein Formular aufgerufen (Funktion der Klasse Form1)?
  8. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten-
     Klasse ?
  9. Wie kann ich Files mit .NET ¨ffnen (welche Klasse) ?
                                 o

= 158.
Literaturverzeichnis

[1] Stroustrup B. The programming languages C++. Addison-Wesley, Reading,
    1991.
[2] Blanchette J and Summerfield M. C++ GUI Programming with Qt 4. Pren-
    tice Hall, Boston, 2006.
[3] Kolditz O. Computational methods in environmental fluid mechanics. Sprin-
    ger, Berlin-Heidelberg, 2002.
[4] Breymann U. C++ Einf¨hrung und professionelle Programmierung. Hanser,
                         u
    M¨ nchen-Wien, 2001.
      u
[5] Kirch-Prinz U and Prinz P. C++ Lernen und professionell anwenden. mitp,
    Heidelberg, 2007.




                                    155
Inhaltsverzeichnis

Part I - C++ Basics                                                                 6

1 Einf¨hrung
      u                                                                             7
  1.1   Historisches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     8
  1.2   Paradigmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       9
  1.3   Compiler    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   11
        1.3.1   GNU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     12
        1.3.2   MS Visual C++ . . . . . . . . . . . . . . . . . . . . . . .         13
        1.3.3   Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    13
  1.4   ”Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     14
        1.4.1   Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . .      14
        1.4.2   Exercise E1 . . . . . . . . . . . . . . . . . . . . . . . . . .     15
  1.5   Students Forum . . . . . . . . . . . . . . . . . . . . . . . . . . . .      16
  1.6   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    17

2 Datentypen                                                                        18
  2.1   Elementare Datentypen . . . . . . . . . . . . . . . . . . . . . . .         18
  2.2   Speicherbedarf . . . . . . . . . . . . . . . . . . . . . . . . . . . .      19
  2.3   Escape-Sequenzen . . . . . . . . . . . . . . . . . . . . . . . . . .        19
  2.4   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    20

3 Ein- und Ausgabe                                                                  21
  3.1   Die Standard-Streams . . . . . . . . . . . . . . . . . . . . . . . .        23
  3.2   Formatierte Ausgaben . . . . . . . . . . . . . . . . . . . . . . . .        23
        3.2.1   Formatierte Ausgabe von Ganzzahlen . . . . . . . . . . .            23

                                       156
INHALTSVERZEICHNIS                                                                   157



         3.2.2   Formatierte Ausgabe von Gleitpunktzahlen . . . . . . . .            24
         3.2.3   Ausgabe von Speicherbedarf . . . . . . . . . . . . . . . . .        24
   3.3   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    25

4 Klassen                                                                            26
   4.1   Daten-Abstraktion . . . . . . . . . . . . . . . . . . . . . . . . . .       27
   4.2   Klassen-Deklaration . . . . . . . . . . . . . . . . . . . . . . . . .       28
   4.3   Instanzen einer Klasse . . . . . . . . . . . . . . . . . . . . . . . .      28
   4.4   Konstruktor und Destruktor . . . . . . . . . . . . . . . . . . . . .        30
   4.5   Dateninitialisierung mit dem Konstruktor . . . . . . . . . . . . .          31
   4.6   Datenschutz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     32
   4.7   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    34

5 Strings                                                                            35
   5.1   Die Standardklasse string . . . . . . . . . . . . . . . . . . . . . .       35
   5.2   Operationen mit strings . . . . . . . . . . . . . . . . . . . . . . .       36
         5.2.1   Initialisieren von strings . . . . . . . . . . . . . . . . . . .    36
         5.2.2   Zuweisen von strings . . . . . . . . . . . . . . . . . . . . .      37
         5.2.3   Verketten von strings     . . . . . . . . . . . . . . . . . . . .   37
         5.2.4   Vergleichen von strings . . . . . . . . . . . . . . . . . . . .     37
         5.2.5   Suchen in strings . . . . . . . . . . . . . . . . . . . . . . .     38
         5.2.6   Einf¨ gen in strings . . . . . . . . . . . . . . . . . . . . . .
                     u                                                               38
         5.2.7   Ersetzen in strings . . . . . . . . . . . . . . . . . . . . . .     39
         5.2.8   L¨schen in strings . . . . . . . . . . . . . . . . . . . . . .
                  o                                                                  39
         5.2.9   Umwandeln von strings in char . . . . . . . . . . . . . . .         40
         5.2.10 Auswerten von Strings: Stringstreams . . . . . . . . . . .           40
   5.3   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    41

6 Ein- und Ausgabe - II                                                              42
   6.1   Die fstream Klassen . . . . . . . . . . . . . . . . . . . . . . . . .       42
   6.2   Arbeiten mit File-Streams . . . . . . . . . . . . . . . . . . . . . .       43
         6.2.1   File-Streams anlegen . . . . . . . . . . . . . . . . . . . . .      43
         6.2.2   File-Streams schließen . . . . . . . . . . . . . . . . . . . .      43
         6.2.3   ¨
                 Ubung: Eine einfache Kopierfunktion . . . . . . . . . . . .         43
158                                                                INHALTSVERZEICHNIS



            6.2.4   ¨
                    Ubung: Ein einfacher Konverter . . . . . . . . . . . . . . .        45
            6.2.5   Einschub: Erstes Arbeiten mit MS VC++ . . . . . . . . .             46
      6.3   File-Streams und Klassen . . . . . . . . . . . . . . . . . . . . . .        49
      6.4   fstream Methoden . . . . . . . . . . . . . . . . . . . . . . . . . .        52
      6.5   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    53

7 Referenzen und Zeiger                                                                 54
      7.1   Referenzen    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   55
            7.1.1   Das Call-by-reference Prinzip - Referenzen als Parameter            55
            7.1.2   Referenzen als R¨ ckgabe-Wert . . . . . . . . . . . . . . .
                                    u                                                   56
      7.2   Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    56
            7.2.1   Definition von Zeigern . . . . . . . . . . . . . . . . . . . .       57
            7.2.2   NULL Zeiger . . . . . . . . . . . . . . . . . . . . . . . . .       57
            7.2.3   Zeiger als Parameter . . . . . . . . . . . . . . . . . . . . .      58
      7.3   Zeiger und Arrays . . . . . . . . . . . . . . . . . . . . . . . . . .       58
            7.3.1   Statische Objekte . . . . . . . . . . . . . . . . . . . . . . .     58
            7.3.2   Dynamische Objekte . . . . . . . . . . . . . . . . . . . . .        58
      7.4   Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       59
      7.5   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    61

8 Container                                                                             62
      8.1   Sequentielle Container . . . . . . . . . . . . . . . . . . . . . . . .      63
      8.2   Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     64
            8.2.1   Defining vectors . . . . . . . . . . . . . . . . . . . . . . .       66
            8.2.2   Vectors and data base . . . . . . . . . . . . . . . . . . . .       66
            8.2.3   Updating your data base entry . . . . . . . . . . . . . . .         68
      8.3   Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   69
      8.4   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    71

9 Andere Sprachelemente                                                                 73
      9.1   Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . .      73
            9.1.1   if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . .     74
            9.1.2   switch-case . . . . . . . . . . . . . . . . . . . . . . . . .       74
            9.1.3   for   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   75
INHALTSVERZEICHNIS                                                                   159



         9.1.4   while . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      75
         9.1.5   continue, break, return . . . . . . . . . . . . . . . . .            75
   9.2   G¨ ltigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . .
          u                                                                           76
         9.2.1   Namensbereiche . . . . . . . . . . . . . . . . . . . . . . .         76
         9.2.2   Compiler-Direktiven – #       . . . . . . . . . . . . . . . . . .    76
   9.3   Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     78

Part II - Visual C++                                                                 80

10 Dialoge                                                                           82
   10.1 What have we (i.e. MFC) created ? . . . . . . . . . . . . . . . . .           82
   10.2 Gestaltung des Dialogs . . . . . . . . . . . . . . . . . . . . . . . .        85
   10.3 Programmierung des Dialogs – MyDialogDlg . . . . . . . . . . .                87
         10.3.1 Dialog-Funktionen . . . . . . . . . . . . . . . . . . . . . .         87
         10.3.2 Dialog-Daten . . . . . . . . . . . . . . . . . . . . . . . . .        87
         10.3.3 Implementierung des Dialogs . . . . . . . . . . . . . . . .           88
         10.3.4 Schnittstelle zwischen Dialog- und Studenten-Klasse . . .             89
         10.3.5 N¨ tzliche Windows-Funktionen . . . . . . . . . . . . . . .
                 u                                                                    92
   10.4 Das .NET Formular . . . . . . . . . . . . . . . . . . . . . . . . .           94
         10.4.1 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . .        95
         10.4.2 Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       96
                ¨
         10.4.3 Ubung: Hinzuf¨ gen von Funktionen . . . . . . . . . . . .
                             u                                                        97
   10.5 HomeWorks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
   10.6 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

11 Qt                                                                                104
   11.1 Hello Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
   11.2 Executable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
   11.3 Quit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
   11.4 Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

Part III - Anlagen / Software                                                        111
12 Software-Installation                                                      112
   12.1 cygwin Installation . . . . . . . . . . . . . . . . . . . . . . . . . . 113
   12.2 LINUX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
               ¨
        12.2.1 Ubersicht einiger grundlegenden Linux-Befehle . . . . . . 122
        12.2.2 Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
        12.2.3 Make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
   12.3 Sch¨ sselworte in C++ . . . . . . . . . . . . . . . . . . . . . . . . 129
           u
   12.4 MS VC++ Projekt #1 - Eine Konsolenanwendung . . . . . . . . 130
   12.5 MFC-Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
   12.6 .NET Formular . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
   12.7 UBUNTU & Wine . . . . . . . . . . . . . . . . . . . . . . . . . . 141
   12.8 Qt Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

13 Students Forum                                                             145
   13.1 Vorlesung 1: 17.04.2009 . . . . . . . . . . . . . . . . . . . . . . . 145

14 Questions                                                                  146
   14.1 Testfragen - Kapitel 1 - Einf¨ hrung . . . . . . . . . . . . . . . . . 146
                                     u
   14.2 Testfragen - Kapitel 2 - Datentypen . . . . . . . . . . . . . . . . 147
   14.3 Testfragen - Kapitel 3 - Ein- und Ausgabe I . . . . . . . . . . . . 147
   14.4 Testfragen - Kapitel 4 - Klassen . . . . . . . . . . . . . . . . . . . 148
   14.5 Testfragen - Kapitel 5 - Strings . . . . . . . . . . . . . . . . . . . 148
   14.6 Testfragen - Kapitel 6 - Ein- und Ausgabe II . . . . . . . . . . . 149
   14.7 Testfragen - Kapitel 7 - Referenzen und Zeiger . . . . . . . . . . 150
   14.8 Testfragen - Kapitel 8 - Container . . . . . . . . . . . . . . . . . 151
   14.9 Testfragen - Kapitel 9 - Andere Sprachelemente . . . . . . . . . . 152
   14.10Testfragen - Kapitel 10 - Dialoge . . . . . . . . . . . . . . . . . . 153
Script hydroinformatik i

Weitere ähnliche Inhalte

PDF
T4 S1 Objektorienierte Entwicklung
PPT
Webinar Facebook_2013
PDF
Propuesta para reglamento general para la fijación, revisión y control de pre...
PPTX
Webquest cuerpo humano copia
PPTX
Segundo
DOCX
Va de mitos
PPT
Présentationlirelaville
DOC
Evaluación de habilidades de lenguaje y comunicacion 4º año
T4 S1 Objektorienierte Entwicklung
Webinar Facebook_2013
Propuesta para reglamento general para la fijación, revisión y control de pre...
Webquest cuerpo humano copia
Segundo
Va de mitos
Présentationlirelaville
Evaluación de habilidades de lenguaje y comunicacion 4º año

Andere mochten auch (16)

PPT
Pepeers
PPTX
Dn11 u3 a1_ile
PPS
Origen de vete_al_carajo
PDF
Borrador para discusión del Comercio Exterior
PPTX
Séance d'information présentation ppt
DOC
Informe climas sociales toxicos y climas sociales nutritivos
PDF
Prof segundo0ciclobasico
PDF
tatkräftig-Präsentation
PPTX
Bicentenario de colombia 15
PDF
EMPLEO, EQUIDAD E INNOVACIÓN, EJES CLAVES DE LA POLÍTICA PRODUCTIVA DEL GOBI...
PDF
Bogota underground
PPTX
Examen trimestral power point
PPTX
La vision du groupe AZNetwork
PDF
le printemps arrive 1
PDF
LES ENERGIES RENOVABLES
Pepeers
Dn11 u3 a1_ile
Origen de vete_al_carajo
Borrador para discusión del Comercio Exterior
Séance d'information présentation ppt
Informe climas sociales toxicos y climas sociales nutritivos
Prof segundo0ciclobasico
tatkräftig-Präsentation
Bicentenario de colombia 15
EMPLEO, EQUIDAD E INNOVACIÓN, EJES CLAVES DE LA POLÍTICA PRODUCTIVA DEL GOBI...
Bogota underground
Examen trimestral power point
La vision du groupe AZNetwork
le printemps arrive 1
LES ENERGIES RENOVABLES
Anzeige

Ähnlich wie Script hydroinformatik i (20)

PDF
PDF
Solution Manual for C How to Program, 7/E 7th Edition Paul Deitel, Harvey Deitel
PDF
Solution Manual for C How to Program, 7/E 7th Edition Paul Deitel, Harvey Deitel
PPT
Onno Reiners: E-Learning einfach selbst erstellen
PDF
Solution Manual for C++ How to Program: Late Objects Version, 7/E 7th Edition...
PPTX
Bit WiSe 2013 | Basisinformationstechnologie I - 08: Programmiersprachen I
DOC
Klassen
PPTX
C/ C++ for Notes & Domino Developers
PDF
Android doc
PPT
Top 10 Internet Trends 2001
PDF
Dokumentation
PDF
Dokumentation
PPT
Einsatz von Subversion bei der Entwicklung technisch-wissenschaftlicher Software
PDF
Analyse-Methodik
PPT
Python, Plone und Zope in der Luft- und Raumfahrtforschung
PDF
Dnug dresden blend 5. 5. 2010
PDF
DNUG Dresden Blend
PDF
GUIs mit Expression Blend
PPT
Python in der Luft- und Raumfahrt
PDF
javawork2015-ConfirmationOfParticipation
Solution Manual for C How to Program, 7/E 7th Edition Paul Deitel, Harvey Deitel
Solution Manual for C How to Program, 7/E 7th Edition Paul Deitel, Harvey Deitel
Onno Reiners: E-Learning einfach selbst erstellen
Solution Manual for C++ How to Program: Late Objects Version, 7/E 7th Edition...
Bit WiSe 2013 | Basisinformationstechnologie I - 08: Programmiersprachen I
Klassen
C/ C++ for Notes & Domino Developers
Android doc
Top 10 Internet Trends 2001
Dokumentation
Dokumentation
Einsatz von Subversion bei der Entwicklung technisch-wissenschaftlicher Software
Analyse-Methodik
Python, Plone und Zope in der Luft- und Raumfahrtforschung
Dnug dresden blend 5. 5. 2010
DNUG Dresden Blend
GUIs mit Expression Blend
Python in der Luft- und Raumfahrt
javawork2015-ConfirmationOfParticipation
Anzeige

Script hydroinformatik i

  • 1. Version 2.01 - 27. April 2010 Hydroinformatik I ”C++ und Visual C++” Olaf Kolditz und Bastian Kolditz TU Dresden / UFZ Leipzig Angewandte Umweltsystemanalyse Umweltinformatik SS 2010 c OGS Publisher 2010
  • 2. 2 Vorlesungskonzept Ein wesentlicher Bestandteil der Hydroinformatik ist die Informationsverarbei- tung. Typische Hydrodaten sind z.B: digitale Gel¨ndemodelle (DGM), Nieder- a schlagsmessungen, Wasserpegel, Bodentemperaturen, Bodenkarten (Bodenty- pen), geologische Schnitte u.v.a. (s. Abb. 1 und 2) Abbildung 1: Informationsverarbeitung in der Hydrologie - Datentypen Eine grundlegende Methodik f¨ r die Informationsverarbeitung ist die wissen- u schaftliche Programmierung. Daher besch¨ftigen wir uns im ersten Semester a der Veranstaltung ’Hydroinformatik’ mit der objekt-orientierten Programmie- rung in C++. Es gibt zwei M¨glichkeiten eine Programmiersprache zu erlernen: mehr theore- o tisch oder mehr praktisch. Wir beschreiten den zweiten Weg. Das heißt anhand von dem, was wir f¨ r das Programmieren ben¨tigen, erarbeiten wir uns die u o Theorie. Unser Motto ist ’Learning by doing’.
  • 3. 3 . Abbildung 2: Informationsverarbeitung in der Hydrologie - Beispiel aus der Hy- drogeologie Organisatorisches Die Pr¨ fung ’Hydroinformatik I’ (erstes Semester) ist eine Klausur. Die Pr¨fung u u ’Hydroinformatik II’ (zweites Semester) besteht aus zwei Teilen, einer Klausur und einer Programmier-Hausarbeit. Bei den Klausuren geht es um die Beant- wortung von Verst¨ndnisfragen (siehe Testfragen zu jeder Vorlesung). a Sprache: normalerweise in Deutsch. Da die Syntax von Computersprachen (wie C++) immer in Englisch ist, w¨ rde ich auch mal eine Vorlesung in Englisch u anbieten. Konsultationen: immer nach der Vorlesung (Freitag ab 11 Uhr). Kontakt: jederzeit by e-mail (olaf.kolditz@ufz.de), in dringenden F¨llen auch a per Handy (0151 52739034), ich empfehle auch eine mailing Liste der Studenten anzulegen, wenn alle damit einverstanden sind. Vorlesungsunterlagen: lege ich erstmal auf meinem UFZ Server ab (http://www.ufz.de/index.php?de=11877).
  • 4. 4 Es gibt viele und sehr gute C++ B¨ cher. Bei Amazon finden sie locker uber u ¨ 50 C++ B¨ cher (Abb. 3). Sehr gut finde das Buch von Prinz & Prinz ”C++ u - Lernen und professionell anwenden”, da es eine gute Kombination aus Theo- rie und Programm-Beispielen ist. Zu diesem Lehrbuch gibt es auch ein extra ¨ Ubungsbuch. Unsere Vorlesung lehnt sich an dieses Buch an. Abbildung 3: C++ Literatur Das heisst, etwas anders wird unsere Vorgehensweise sein. Im ersten Semester wollen wir zielgerichtet die C++ Grundlagen anhand der Entwicklung einer einfachen ’Datenbank’-Anwendung erlernen - learning-by-doing - und die Daten schließlich in einer graphischen Benutzerschnittstelle (GUI) sichtbar machen. Somit besch¨ftigen wir uns auch zielgerichtet mit den Grundlagen von Visual a C++. Das Vorlesungskonzept: • Zielgerichtetes Erlernen der C++ Grundlagen, • Entwicklung einer ’Datenbank’-Anwendung, • Umsetzung in eine graphische Benutzerschnittstelle (Visual C++, C++ GUI), siehe Abb. 4.
  • 5. 5 . Abbildung 4: Vorlesungs-Konzept Die Implementierung des Dialogs in Abb. 4 ist das erste greifbare Ziel der Ver- anstaltung Hydroinformatik I. In dieser GUI-Anwendung k¨nnen sie (fast) alles, o was wir lernen werden, wiederfinden: Datentypen, Ein- und Ausgabe mit ver- schiedene Ger¨ten (Tastatur, Bildschirm, Dateien), Klassen, Vererbung, Con- a tainer (Listen, Vektoren) und graphische Programmierung unter Windows. Es lohnt sich also dranzubleiben ...
  • 6. Part I C ++ Basics
  • 8. 8 ¨ KAPITEL 1 EINFUHRUNG 1.1 Historisches Die Programmiersprache C++ wurde von dem d¨nischen Informatiker Bjar- a ne Stroustrup in den Bell Labs des nordamerikanischen Telekommunikations- konzerns AT&T (American Telephone & Telegraph Corporation) ab 1979/80 entwickelt. C++ stellt eine Weiterentwicklung der ebenfalls von AT&T ent- wickelten, Programmiersprache C dar. Die Programmiersprache C wurde als Grundlage f¨ r C++ aufgrund seiner effizienten Codeverarbeitung und einfachen u ¨ Ubertragbarkeit auf anderen Plattformen verwendet. C wurde in C++ nach dem Vorbild der Programmiersprache Simula-67 (1967), der ersten objektorientierten Programmiersprache, im Wesentlichen um ein Klassenkonzept, d.h. die Abbil- dung von Objekten in verschiedenen Klassen mit unterschiedlichen Attributen, erweitert. Daher wurde C++ zun¨chst unter dem Namen ’C mit Klassen’ (C a with classes) entwickelt. Der Name C++ wurde 1983 von Rick Mascitti erst- mals angewandt. Dabei ist das ++ eine Andeutung an den Inkrement-Operator (Inkrement: Erh¨hung einer Variable um 1), der die Verbesserungen gegen¨ ber o u dem Vorg¨nger C zum Ausdruck bringen soll. Im Jahr 1985 erschien die erste a Version von C++, die eine wichtige Grundlage f¨ r die weitere Entwicklung und u Standardisierung von C++ darstellte, da die Sprache zu dieser Zeit noch nicht akzeptiert war. Im Jahre 1989 erschien die erweiterte Version 2.0 von C++. In den 90er Jahren begann nun der Standardisierungs- und Vereinheitlichungs- prozess von C++, der eingeleitet wurde durch das Buch ’The Annotated C++ Reference Manual’ (1990) von Margaret Ellis und Bjarne Stroustrup. Die ge- normte Fassung von C++ erschien 1998 (ISO/IEC 14882:1998), die 2003 mit einer neuen Version (ISO/IEC 14882:2003) nochmals nachgebessert wurde. Abbildung 1.1: Bjarne Stroustrup (http://www.research.att.com/bs/)
  • 9. 1.2 PARADIGMEN 9 1.2 Paradigmen Programmier-Paradigmen sind sogenannte Leitlinien / Konzepte f¨ r die Ge- u staltung von Programmen, diese k¨nnen durch entsprechende Sprachmittel un- o terst¨ tzt werden. Allerdings bedeutet die Benutzung einer objekt-orientierten u Sprache nicht automatisch ein objekt-orientiertes Programm (OOP). • Prozedurales Programmieren: Welche Prozeduren ben¨tigen Sie f¨ r Ihr o u Programm ? Verwenden Sie die optimalen Algorithmen. • Modulares Programmieren: Welche Module ben¨tigen Sie f¨ r Ihr Pro- o u gramm ? Strukturieren Sie Ihr Programm entsprechend modular. Die Da- ten sollten in den Modulen gekapselt sein. • Objekt-orientiertes Programmieren: Welche Klassen ben¨tigen Sie f¨ r Ihr o u ¨ Programm ? Uberlegen Sie, welche Gemeinsamkeiten die Klassen haben, benutzen Sie das Konzept der Vererbung. • Datenabstraktion: Welche Datentypen ben¨tigen Sie f¨ r Ihr Programm ? o u Erstellen Sie f¨ r jeden benutzerdefinierten Typen m¨glichst viele Opera- u o tionen.
  • 10. 10 ¨ KAPITEL 1 EINFUHRUNG . Abbildung 1.2: Objekt-orientiertes Programmieren - OOP Die Abb. 1.2 soll das Konzept des Objekt-Orientierten Programmierens (OOP) mal aus einer anderen Sichtweise erl¨utern. Normalerweise bedeutet die Pro- a grammentwicklung (prozedural und modular) eine stetige Erweiterung des Co- des (Abb. oben). Irgendwann ist das Programm dann so un¨ bersichtlich ge- u worden, dass eigentlich niemand mehr durchblickt. Die grundlegenden Idee von OOP dagegen sind, dass, erstens Objekte (logische Einheiten des Programms) streng gekapselt sind (sich also nicht gegenseitig beeinflussen) und, zweitens, dass es ganz schmale Schnittstellen zwischen diesen Objekten gibt (z.B. nur uber eine Adresse (sogenannte pointer)) (Abb. unten). Nat¨ rlich wachsen auch ¨ u diese Objekte weiter und stoßen irgendwann an Grenzen ... Ein Beispiel aus der Praxis unserer eigenen Programmentwicklung OpenGeo- Sys. Die Abb. 1.3 zeigt das objekt-orientierte Konzept der Kernels von Open- GeoSys zur L¨sung von partiellen Differentialgleichungen. Letztlich f¨ hren alle o u numerischen Methoden zur L¨sung von linearen Gleichungssystemen Ax = b. o Daher haben wir ein Objekt konstruiert (PCS von ProCesS), das die Aufgabe ubernimmt, alle Bausteine f¨ r die Assemblierung und L¨sung der Gleichungs- ¨ u o systeme einzusammeln. Dabei geht es um geometrische (Punkte, Polylinien, Fl¨chen, Volumen), topologische (Element-Netze), numerische und physikali- a sche Daten (z.B. Materialeigenschaften, Anfangs- und Randbedingungen). Ent- scheidend f¨ r die Machbarkeit eines objekt-orientierten Konzepts ist, dass der u Algorithmus zum Aufstellen und L¨sen der Gleichungssysteme vollkommen o unabh¨ngig von dem spezifischen physikalischen Problem ist. Die Basisklasse a
  • 11. 1.3 COMPILER 11 f¨ r das PCS-Objekt ist CProcess, davon abgeleitet werden die speziellen Klas- u sen f¨ r die spezifischen Probleme (z.B. Str¨mung, Stoff- und W¨rmetransport, u o a Deformation). Wenn Sie diesen Abschnitt noch mal durchlesen, sollten sie aller- dings stutzig werden, da neben dem erwarteten Begriff der Objekt-Orientierung auf der des Algorithmus auftaucht. Richtig, OpenGeoSys ist kein reines OOP sondern eine Kombination von objekt-orientierten und prozeduralen Konzepten. Anyway, der Schritt von C zu C++ (3. zur 4. Version, Abb. 1.3) bedeutete eine Reduzierung des Quellcodes von 10MB auf 3MB, also um 70% !!! Abbildung 1.3: Objekt-orientiertes Konzept des Kernels von OpenGeoSys 1.3 Compiler Bevor wir irgendetwas programmieren k¨nnen, ben¨tigen wir zwei Werkzeuge: o o einen Editor und einen Compiler. In der Abb. 1.4 sind die wichtigsten Schritte der Programmerstellung zu sehen. In der Computer-Welt (und deshalb auch in der Programmier-Welt) gibt es zwei verschiedene Philosophien: Microsoft (MS) und ’den Rest’. Um diesem Problem ’auszuweichen’ und fair zu sein, benutzen wir Werkzeuge aus beiden Welten. Wir beleuchten dieses ’Problem’ sp¨ter noch mal, wenn wir uber Open Source a ¨ Projekte (z.B. OpenGeoSys, unsere eigene Software-Entwicklung) sprechen. Wir installieren uns zun¨chst den GNU Compiler (Abschn. 1.3.1) und sp¨ter den MS a a Compiler (Abschn. 1.3.2) f¨ r das visuelle C++ Programmieren. u
  • 12. 12 ¨ KAPITEL 1 EINFUHRUNG Editor Source file Header file Compiler Object file Linker Libraries Executable Abbildung 1.4: Quell-Code Kompilation 1.3.1 GNU Das GNU-Projekt wurde von Richard Stallman mit dem Ziel gegr¨ ndet, ein u vollst¨ndig freies Betriebssystem, genannt GNU (GNU is not Unix), zu ent- a wickeln. Bekannt geworden ist das Projekt vor allen Dingen auch durch die von ihm eingef¨ hrte GNU General Public License (GPL), unter der viele bekannte u Softwareprojekte ver¨ffentlicht werden (Quelle: Wikipedia). o Wenn ihr mehr uber das GNU Projekt erfahren wollt, schaut nach unter ¨ http://de.wikipedia.org/wiki/GNU-Projekt Als Kompromiss benutzen wir cygwin (Abb. 1.5). Dass erm¨glicht uns, auch o unter Windows mit GNU Software arbeiten zu k¨nnen. Die Linux / Ubuntu o ’Freaks’ haben die GNU Software automatisch mit dem Betriebssystem auf ih- rem Rechner. Die Anleitung zur Installation finden sie im Anhang, Abschn. 12.2.2.2 (und wird nat¨ rlich in der Vorlesung besprochen) u
  • 13. 1.3 COMPILER 13 . Abbildung 1.5: Ein Kompromiss: cygwin 1.3.2 MS Visual C++ Auch die nicht-MS-Fans m¨ ssen zugeben, das MS Visual C++ Studio ist eine u tolle Entwicklungsumgebung. Die wird uns enorm helfen, wenn wir uns sp¨ter a mit GUI Programmierung besch¨ftigen. Die Express-Version von VC++ kann a kostenlos direkt bei Microsoft unter http://www.microsoft.com/germany/express/download/webdownload.aspx her- untergeladen werden. 1.3.3 Qt Als plattformunabh¨ngiges visuelles C++ empfehle ich Qt (siehe Abschn. 11 a und 12.8)
  • 14. 14 ¨ KAPITEL 1 EINFUHRUNG 1.4 ”Hello World” Unser allererstes C++ Programm. 1.4.1 Grundlagen Jedes C/C++ Programm ben¨tigt eine main() Funktion o int main() { return 0; } Die main() Funktion ist der ’Startpunkt’ eines jeden C/C++ Programms. Die wichtigsten Bausteine einer Funktion sind: • Typ (R¨ ckgabewert): int (return 0) u • Name: main • Argumente: (), man kann die main Funktion auch mit Argumenten auf- rufen, z.B. der Name der Eingabe-Datei, • Funktionsrumpf: ... Die Struktur der main() Funktion ist in der Abb. 1.6 dargestellt. function type function name function arguments int main() function start { ... function block return 0; function end } Abbildung 1.6: Struktur der Funktion main()
  • 15. 1.4 ”HELLO WORLD” 15 1.4.2 Exercise E1 Abbildung 1.7: cygwin aufrufen Abbildung 1.8: cygwin drive ist /cygwin/home/user, wechseln zum Arbeitsver- zeichnis cd c:/myworkdirectory (oder copy und paste) Abbildung 1.9: slash (/) ist nicht gleich slash () ¨ Die einzige C Ubung: #include <stdio.h> int main() { printf("Hello World"); return 0; } Abbildung 1.10: Kommandozeile: gcc main.c, das Ergebnis ist a.exe, Aufruf des Programms: ./a Jetzt endlich zu C++ ...
  • 16. 16 ¨ KAPITEL 1 EINFUHRUNG #include <iostream> using namespace std; int main() { cout << "Hello World" << endl; return 0; } Abbildung 1.11: Kommandozeile: g++ main.cpp, mit ls den Inhalt des Verzeich- nisses ansehen, das Ergebnis ist a.exe, Aufruf des Programms: ./a 1.5 Students Forum Vielen Dank f¨ r Ihre Fragen zur ersten Vorlesung! u JB Der C compiler funktioniert, der C++ aber nicht: Wahrscheinlich haben sie nur den C Compiler (GCC) installiert. Die k¨nnen jederzeit cygwin o Komponenten nachinstallieren, siehe Abschn. 12.2.2.2. ¨ DB Ich habe den MS VC++ installiert und kann die Ubungen nachvollziehen. Brauche ich den GNU Compiler von cygwin wirklich noch ?: Eigentlich nicht, mit MS VC++ haben sie einen kompletten Compiler mit allem drum und dran, dennoch kann ein Ausflug in die Konsolenwelt ja nicht schaden ... und sie k¨nnen sp¨ter in ihre Bewerbungen schreiben, dass sie o a auch unter Linux Programme entwickelt haben. MF Die aktuelle cygwin Installation sieht anders aus als im Skript beschrieben: [OK] Im Anhang (Abschn. 12.2.2.2) finden sie eine bessere Beschreibung der cygwin Installation. C++ und Mac: erstmal eine Adresse http://developer.apple.com/TOOLS/xcode/
  • 17. 1.6 TESTFRAGEN 17 1.6 Testfragen 1. Was bedeutet das ++ im Namen der Programmiersprache C++ ? 2. Ist C++ eine standardisierte Programmiersprache ? 3. Was ist der Unterschied zwischen C und C++ ? 4. Was sind sogenannte Programmier-Paradigmen ? 5. Welche verschiedenen Programmier-Paradigmen kennen sie und worin un- terscheiden sie sich ? 6. Welches Paradigma verfolgen wir in der Vorlesung ? 7. Was ist objekt-orientierte Programmierung ? 8. Was ist ein Kompiler ? 9. Erkl¨ren sie die einzelnen Schritte bei einer Kompilierung (s. Abb. 1.4). a ¨ 10. Welchen Kompiler benutzen sie f¨ r die C++ Ubungen ? u 11. Welche Funktion ben¨tigt jedes C oder C++ Programm ? o 12. Was ist der Typ einer Funktion ? 13. Was ist eine Parameterliste einer Funktion ? 14. Was ist der R¨ ckgabewert einer Funktion ? u
  • 18. Kapitel 2 Datentypen Jede Programmiersprache bietet die Verwendung elementarer Datentypen an, wie z.B. Ganzzahlen oder Gleitkommazahlen, logische Ausdr¨ cke oder Zeichen- u ketten. Die Besonderheit von objekt-orientierten (OO) Sprachen ist die Erstel- lung benutzerdefinierter Datentypen. Dies war schon in der Sprache C mit sog. ’typedef struct’ Typen m¨glich. OO Sprachen, wie C++, bieten aber noch mehr o an, die Verkn¨ pfung von benutzerdefinierten Datentypen mit den entsprechen- u den Methoden. Diese Konstrukte nennt man Klassen, aber darum geht es erst im n¨chsten Kapitel. Zun¨chst m¨ ssen wir uns (kurz) mit den handels¨ blichen a a u u Datentypen herumschlagen. 2.1 Elementare Datentypen ¨ Die nachfolgende Tabelle zeigt eine Ubersicht der elementaren Datentypen. Typ Bezeichner Erl¨uterung a Wahrheitswerte bool Wert kann true (=1) oder false (=0) sein Zeichen char Zeichen, statische Zeichenketten wchar t ’wide character type’ (≥ 2 Byte) string Dynamische Zeichenketten Ganzzahlen short Ganze Zahlen mit geringer Genauigkeit int Ganze Zahlen mit hoher Genauigkeit long Ganze Zahlen mit sehr hoher Genauigkeit Gleitpunktzahlen float Reelle Zahlen mit geringer Genauigkeit double Reelle Zahlen mit hoher Genauigkeit long double Reelle Zahlen mit sehr hoher Genauigkeit ¨ Tabelle 2.1: Ubersicht elementarer Datentypen 18
  • 19. 2.2 SPEICHERBEDARF 19 2.2 Speicherbedarf Die unterschiedlichen Datentypen werden durch den Compiler verschieden ver- arbeitet und gespeichert (Gr¨ße des ben¨tigten Speicherplatzes). o o Typ Speicherplatz Wertebereich bool 1 Byte (weniger geht leider nicht) char 1 Byte -128 bis + 127 bzw. 0 bis 255 int 2/4 Byte -32768 bis +32767 bzw. -2147483648 bis + 2147483647 short 2 Byte -32768 bis +32767 long 4 Byte -2147483648 bis + 2147483647 float 4 Byte ± 3.4E+38, 6 Stellen Genauigkeit double 8 Byte ± 1.7E+308, 15 Stellen Genauigkeit long double 10 Byte ± 1.7E+4932, 19 Stellen Genauigkeit Tabelle 2.2: Speicherbedarf elementarer Datentypen Der sizeof Operator ermittelt die ben¨tigte Speichergr¨ße f¨ r einen bestimm- o o u ten Datentypen, z.B. sizeof(float) = 4: eine einfach genaue Gleitkommazahl ¨ ben¨tigt 4 Byte Speicher. Wir verwenden den sizeof Operator in der Ubung E34. o 2.3 Escape-Sequenzen Escape-Sequenzen sind n¨ tzliche Helfer, z.B. zum Formatieren von Ausgaben u oder f¨ r die Benutzung von Sonderzeichen in der Ausgabe. u Zeichen Bedeutung Wirkung a alert (BEL) Ausprobieren b backspace (BS) eine Position zur¨ ck u t horizontal tab (HT) horizontaler Tabulator n line feed (LF) Zeilenumbruch v vertical tab (VT) vertikaler Tabulator r carriage return (CR) Zeilenumbruch 0 end of string Zeilenende ” ” Zeichen ’ ’ Zeichen ? ? Zeichen Zeichen Tabelle 2.3: N¨ tzliche Escape-Sequenzen u
  • 20. 20 KAPITEL 2 DATENTYPEN 2.4 Testfragen 1. Was ist der genaueste Datentyp in C++ ? 2. Wie groß ist der Speicherbedarf von einem string Datentyp ? 3. Mit welcher Anweisung k¨nnen wir den Speicherbedarf von elementaren o Datentypen ermitteln ? 4. Was sind Escape-Sequenzen ? 5. Was ist der Unterschied zwischen den Escape-Sequenzen n und r ? 6. Was ist die C++ Entsprechung der Klasse cout f¨ r einen Zeilenumbruch u ?
  • 21. Kapitel 3 Ein- und Ausgabe Ein Programm (ob prozedural, modular, objekt-orientiert) ist eigentlich nichts weiter als eine Datenverarbeitung zwischen einer Eingabe (Input) und einer Ausgabe (Output). I und O k¨nnen mehr oder weniger schick gemacht sein: o 1. I/O Standardger¨te, a 2. I/O Dateien, 3. Datenbanken (I) und Visualisierung (O). Aus didaktischen Gr¨ nden m¨ ssen wir leider mit dem Langweiligsten - I/O u u Standardger¨te - anfangen. Spannend wird’s, wenn Daten durch die Visualisie- a rung ’lebendig’ werden. Die Abb. 3.1 zeigt eine professionelle Datenaufbereitung einen Porenraummodells in unserem Labor f¨ r wissenschaftliche Visualisierung u (TESSIN-VISLab) am UFZ in Leipzig. Die iostream Klasse Die Ein- und Ausgabe in C++ erfolgt mit sogenannten Str¨men (streams). Die o I/O-Stream-Klassen (Abb. 3.2) bieten vielf¨ltige M¨glichkeiten, die wir uns in a o ¨ den nachfolgenden Ubungen n¨her anschauen. a 21
  • 22. 22 KAPITEL 3 EIN- UND AUSGABE . Abbildung 3.1: Wissenschaftliche Visualisierung ios istream ostream iostream Abbildung 3.2: I/O stream Klassen Die Klasse iostream geht durch Mehrfachvererbung aus den Klassen istream und ostream hervor. iostream stellt damit die Funktionalit¨t beider I/O Klas- a sen zu Verf¨ gung. u
  • 23. 3.1 DIE STANDARD-STREAMS 23 3.1 Die Standard-Streams Es gibt vier Standard-Streams: • cin: Standard-Eingabe uber die Tastatur, Objekt der Klasse istream ¨ • cout: Standard-Ausgabe auf dem Bildschirm, Objekt der Klasse ostream • cerr und clog: zwei Objekte der Klasse ostream f¨ r die Fehlerausgabe. u Exercise E3.1: #include <iostream> using namespace std; int main() { int zahl; cout << "Bitte eine ganze Zahl eingeben: "; cin >> zahl; cout << zahl << endl; return 0; } Die Ein- >> und Ausgabeoperatoren << transportieren die Str¨me von und zu o den Eingabe- bzw. Ausgabeger¨ten. Dabei formatieren sie die Datentypen (z.B. a ¨ int in der Ubung E3.1) entsprechend den Einstellungen der Klasse ios. Diese Einstellungen k¨nnen durch Flags ver¨ndert werden (siehe n¨chsten Abschnitt). o a a 3.2 Formatierte Ausgaben redmehr Beschreibung notwendig 3.2.1 Formatierte Ausgabe von Ganzzahlen ¨ In der nachfolgenden Ubung besch¨ftigen wir uns mit den verschiedenen Aus- a gabem¨glichkeiten von ganzen Zahlen. o Exercise E3.2.1: #include <iostream> using namespace std; int main() { int zahl; cout << "Bitte eine ganze Zahl eingeben: "; cin >> zahl;
  • 24. 24 KAPITEL 3 EIN- UND AUSGABE cout << uppercase // f¨r Hex-Ziffern u << " oktal tt dezimal t hexadezimal n " << oct << zahl << " tt " << dec << zahl << " tt " << hex << zahl << endl; return 0; } 3.2.2 Formatierte Ausgabe von Gleitpunktzahlen ¨ In der nachfolgenden Ubung besch¨ftigen wir uns mit den verschiedenen Aus- a gabem¨glichkeiten von realen Zahlen. o Methoden Wirkung int precision(int n) Genauigkeit wird auf n gesetzt Exercise E3.2.2: #include <iostream> using namespace std; int main() { double zahl; cout << "Bitte eine Gleitkommazahl eingeben: "; cin >> zahl; cout.precision(7); // auf sieben Stellen genau cout << "Standard: t" << zahl << endl; cout << "showpoint: t" << showpoint << zahl << endl; cout << "fixed: tt" << fixed << zahl << endl; cout << "scientific: t" << scientific << zahl << endl; return 0; } 3.2.3 Ausgabe von Speicherbedarf ¨ In dieser Ubung benutzen wir den sizeof Operator, um den Speicherbedarf von Standard Daten-Typen zu bestimmen. Exercise E3.2.3: #include <iostream> using namespace std; int main() {
  • 25. 3.3 TESTFRAGEN 25 cout << "TypetNumber of bytesn"; cout << "-----------------------n"; cout << "booltt" << sizeof(bool) << endl; cout << "chartt" << sizeof(char) << endl; cout << "shorttt" << sizeof(short) << endl; cout << "inttt" << sizeof(int) << endl; cout << "longtt" << sizeof(long) << endl; cout << "floattt" << sizeof(float) << endl; cout << "doublett" << sizeof(double) << endl; cout << "long doublet" << sizeof(long double) << endl; return 0; } 3.3 Testfragen 1. Sind sie mit der Tab. 2.2 einverstanden ? 2. Welche Ein- und Ausgabeger¨te kennen sie ? a 3. Welche Klasse ben¨tigen wir f¨ r die Standard-Ein- und Ausgabe ? o u 4. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ? u 5. Mit welcher Klasse k¨nnen wir sowohl Eingabe- als auch Ausgabestr¨me o o benutzen ? 6. Welche Include-Datei ist notwendig, um mit I/O-Str¨men arbeiten zu o k¨nnen ? o 7. Wozu dient der Zusatz using namespace std; nach dem Include von Standard-Klassen, wie I/O Streams ? 8. Was bewirken die Stream-Operatoren << und >> ? 9. Was bewirken die Flags oct, dec, hex f¨ r die formatierte Ausgabe von u Ganzzahlen ? (ToDo) 10. Wie kann ich die Genauigkeit der Ausgabe von Gleikomma-Zahlen festle- gen ? 11. Wie kann man den Speicherbedarf einer Variable ermitteln ? Schreiben sie die C++ Anweisung f¨ r die Berechnung des Speicherbedarfs f¨ r eine u u doppelt-genaue Gleitkomma-Zahl.
  • 26. Kapitel 4 Klassen source: TU Dresden Data abstraction class CStudent properties ... Instances methods ... CStudent *m_std; Abbildung 4.1: Das Klassen-Konzept - CStudent 26
  • 27. 4.1 DATEN-ABSTRAKTION 27 Das Sprachelement der Klassen sind das entscheidende Kriterium von objekt- orientierten Konzepten und die objekt-orientierte Programmierung (OOP). Klas- sen sind eine Art Schablone f¨ r einen benutzerdefinierten Datentypen. Dar¨ ber u u hinaus enth¨lt die Klasse neben den Daten auch alle Methoden (Funktionen), a um mit den Daten der Klasse operieren zu k¨nnen. Unser Beispiel f¨ r Klassen, o u das uns im Verlaufe der Vorlesung besch¨ftigen wird, ist - wie k¨nnte es an- a o ders sein - CStudent (Abb. 4.1). F¨ r die Konzipierung von Klassen spielt die u Abstraktion der Daten einer Klasse eine besonders wichtige Rolle. 4.1 Daten-Abstraktion Die Abb. 4.1 illustriert uns, dass eine Abstraktion von Daten (d.h. Eigenschaf- ten) der Klasse Studenten eine durchaus vielschichtige Angelegenheit sein kann. Eine Aufstellung von Daten / Eigenschaften, die es aus ihrer Sicht zu ber¨ ck- u sichtigen gilt, ist ihre n¨chste Hausaufgabe. a Der n¨chste Block zeigt ihnen das Schema der Syntax der Klassen-Definition a CStudent. Das Schl¨ sselwort f¨ r die Klassen-Definition ist class, der Name ist u u CStudent. Der Klassen-Rumpf ist in geschweifte Klammer eingebettet. Wichtig ist der Abschluss mit einem Semikolon. Wie bereits erw¨hnt, eine Klasse enth¨lt a a Daten (Eigenschaften) und Methoden (Funktionen) auf den Daten. Prinzipiell geht diese Datenabstraktion auch mit anderen Sprachen wie C. A data construct typedef struct {...} in C can be seen as an analogue to a C++ class. Die C Version: typedef struct { char* name_first; char* name_last; long matrikel_number; } TDStudent; TDStudent *student = NULL; Die C++ Version: class CStudent { data: ... methods: ... }; Bei der Namensgebung von Klassen wird oft ein ’C’ (CStudent) vorangestellt, um die Bedeutung als Klasse (wesentlicher Baustein des Programm-Konzepts) herauszustellen.
  • 28. 28 KAPITEL 4 KLASSEN Ein weiterer Vorzug von OO-Sprachen ist z.B. die Sichtbarkeit / Zugreifbarkeit von Daten zu regeln. Der nachfolgende Block zeigt das Datenschutz-Konzept von C++ (Sicherheitsstufen): Daten k¨nnen ¨ffentlich sein (public) oder gezielt o o f¨ r ’Freunde’ verf¨ gbar gemacht werden (protected) oder nur exklusiv f¨ r die u u u eigene Klasse sichtbar zu sein (private). class CStudent { private: ... protected: ... public: ... }; 4.2 Klassen-Deklaration Im vorangegangenen Abschnitt haben wir uns mit der Datenabstraktion mittels Klassen besch¨ftigt. So sollte konsequenterweise jede Klasse auch ihre eigenen - a sorry - eigenen Quelldateien besitzen. Die Deklaration von Klassen erfolgt ubli- ¨ cherweise in einer sogenannten Header-Datei *.h. F¨ r die Methoden / Funk- u tionen der Klasse ist eine *.cpp Datei reserviert. F¨ r uns bedeutet dies, zwei u Dateien anlegen: • student.h - die Deklaration der Klasse CStudent • student.cpp - die Methoden der Klasse CStudent Um mit der Klasse arbeiten zu k¨nnen, m¨ ssen wir das entsprechende Header- o u File inkludieren. Dies erfolgt mit der Anweisung #include ”student.h” am An- fang unseres Main-Files. #include "student.h" int main { return 0; } 4.3 Instanzen einer Klasse An dieser Stelle m¨chten wir unsere Eingangsgraphik (Abb. 4.1) erinnern. In- o stanzen sind Kopien einer Klasse mit denen wir arbeiten k¨nnen, dass heißt o
  • 29. 4.3 INSTANZEN EINER KLASSE 29 diese bekommen echten Speicher f¨r ihre Daten (die nat¨ rlich f¨ r jede Instanz u u u einer Klasse unterschiedlich sein k¨nnen). o Es gibt zwei M¨glichkeiten, Instanzen einer Klasse zu erzeugen: o #include "student.h" void main() { // Creating an instances of a class - 1 CStudent m_std_A; // Creating an instances of a class - 2 CStudent *m_std_B; } Der direkte und der mittels eines sogenannten Zeigers (hierf¨ r gibt ein Extra- u Kapitel). Wir werden sehen, dass der zweite Weg oft der bessere ist, da wir z.B. die Initialisierung und das Speichermanagement f¨ r unsere Daten selber in die u Hand nehmen k¨nnen. Dies k¨nnen wir mittels sogenannter Konstruktoren und o o Destruktoren erledigen. Damit besch¨ftigen wir uns im n¨chsten Abschnitt. a a Exercise E4.3: #include "student.h" #include <iostream> using namespace std; int main() { CStudent *m_std_cpp; // pointer to an instance cout << "E41: Instances of classes" << endl; cout << "What have we created?t : " << m_std << endl; cout << "What size has it?t : " << sizeof(m_std) << endl; TDStudent *m_std_c; // pointer to TD return 0; } -> student.h // Class definition class CStudent { public: protected: private: }; // Type definition typedef struct { } TDStudent;
  • 30. 30 KAPITEL 4 KLASSEN 4.4 Konstruktor und Destruktor Wohl die wichtigsten Methoden von Klassen sind deren Konstruktoren CStudent() und Destruktoren ∼ CStudent(). Diese Funktionen haben den gleichen Namen wie die Klasse selbst. Der nachfolgende Block zeigt die Deklaration unserer er- sten beiden Klassen-Funktionen in der Header-Datei students.h. class CStudent { public: CStudent(); // constructor ~CStudent(); // destructor }; Wie sehen die Konstruktor/Destruktor-Funktionen aus. #include "student.h" CStudent::CStudent() { } CStudent::~CStudent() { } Die Konstruktor/Destruktor-Funktionen werden ’automatisch’ aufgerufen beim Erzeugen (¨ ber die Zeiger-Version) und Zerst¨ren der Klassen-Instanz: u o • new ruft den dazugeh¨rigen Konstruktor auf, o • delete ruft den dazugeh¨rigen Destruktor auf. o Die Anwendung der Konstruktor/Destruktor-Funktionen ist im folgenden Quellcode- Abschnitt dargestellt. Exercise E4.4: #include <iostream> using namespace std; #include "student.h" int main() { CStudent* m_std = new CStudent(); // instance using constructor cout << "E44: Constructor of class CStudent" << endl; cout << "What have we created? m_stdt : " << m_std << endl; cout << "What size has it?t : " << sizeof(m_std) << endl; cout << "What have we created? &m_stdt : " << &m_std << endl; cout << "What size has it?t : " << sizeof(&m_std) << endl; return 0; }
  • 31. 4.5 DATENINITIALISIERUNG MIT DEM KONSTRUKTOR 31 4.5 Dateninitialisierung mit dem Konstruktor Der Klassen-Konstruktor kann dar¨ ber hinaus auch zur Initialisierung von Da- u ten f¨ r die Klassen-Instanz benutzt werden. Ganz nebenbei schreiben wir unsere u erste Klassen-Funktion in der Quell-Datei der Klasse students.cpp. Wir initiali- sieren den Namen unseres ersten Studenten. Exercise E4.5: CStudent::CStudent() { // Initializations name_first = "James"; name_last = "Bond"; } Daf¨ r m¨ ssen wir die notwendigen Klassen-Variablen (member variables) f¨ r u u u den Namen bereitstellen. Praktischerweise ist es ratsam, die Daten und Metho- den der Klasse zu trennen. Unsere Klassen-Deklaration nimmt langsam Gestalt an ... #include <string> using namespace std; class CStudent { // Data / Properties public: string name_first; string name_last; // Methods / Functions public: CStudent(); // constructor ~CStudent(); // destructor }; F¨ r die Namen benutzen wir die string Klasse von C++ (auch hierzu gibt’s u ein Extra-Kapitel). Um den Daten-Typ string aus dieser Klasse benutzen zu k¨nnen, m¨ ssen wir die Klasse wie folgt inkludieren. o u #include <string> using namespace std; Exercise E4.5: #include <iostream> using namespace std; #include "student.h"
  • 32. 32 KAPITEL 4 KLASSEN int main() { CStudent* m_std = new CStudent(); // instance using constructor cout << "E45: Data initialisation by constructor of class CStudent" << endl; cout << "m_std->name_firstt : " << m_std->name_first << endl; cout << "m_std->name_lastt : " << m_std->name_last << endl; delete(m_std); return 0; } 4.6 Datenschutz Eine wichtige Eigenschaft der Sprache C++ ist die M¨glichkeit, Daten unter- o schiedlich sichtbar zu machen. Eingangs des Kapitels haben wir gesehen, dass es verschiedene Schl¨ sselw¨rter gibt, um Variablen zu klassifizieren: public, pro- u o tected und private. Daten des Typs ’public’ sind uberall sichtbar, aus sie kann ¨ von uberall im Programm zugegriffen werden - also auch ver¨ndert werden. Dies ¨ a kann sehr schnell problematisch werden, wenn das Programm sehr groß ist oder mehrere Programierer gleichzeitg entwickeln. Daten des Typs ’private’ sind nur f¨ r die eigene Klasse sichtbar, dass auf sie k¨nnen nur durch Klassen-eigene u o Methoden zugegriffen werden. Private data sind f¨ r andere Klassen verborgen. u Nat¨ rlich gibt es noch einen Kompromiss: Mit dem Schl¨ sselwort ’protected’ u u kann man gewisse Daten f¨ r ’befreundete’ Klassen offnen. Dies ist im Wesentli- u ¨ chen das Datenschutz-Konzept von C++. ¨ In der folgenden Ubung sehen wir, wie man mit ’private’ data (Kontonummer) umgehen kann. Die Variable bank account ist als private Typ deklariert. class CStudent { public: long GetBankAccount(); void SetBankAccount(long); private: long bank_account; }; Die Zugriffsfunktion GetBankAccount() der Klasse CStudent gibt lediglich den Wert der Variable zur¨ ck, ihr Typ ist nat¨ rlich public. Die Kontonummer kann u u also zun¨chst nicht von ’außen’ ge¨ndert werden. a a long CStudent::GetBankAccount() { return bank_account; }
  • 33. 4.6 DATENSCHUTZ 33 void CStudent::SetBankAccount(long new_bank_account) { bank_account = new_bank_account; } Nat¨ rlich l¨sst sich auch eine Funktion schreiben, mit der man private Daten u a von außen ¨ndern kann: SetBankAccount(long). Letztlich entscheidet der Pro- a grammierer, ob dieser Zugriff zul¨ssig sein soll, wenn nicht gew¨ nscht, werden a u die Get und Set Zugriffsfunktionen einfach nicht bereitgestellt. ¨ Die nachfolgende Ubung zeigt zusammenfassend den Zugriff auf private Varia- blen von Außen. Exercise E4.6: int main() { CStudent* m_std = new CStudent(); // instance using constructor cout << "E46: Data security - using private data" << endl; cout << "m_std->GetBankAccount()t : " << m_std->GetBankAccount() << endl; m_std->SetBankAccount(987654321); // changing private data cout << "m_std->GetBankAccount()t : " << m_std->GetBankAccount() << endl; delete(m_std); return 0; }
  • 34. 34 KAPITEL 4 KLASSEN 4.7 Testfragen 1. Geben sie eine Definition von C++ Klassen mit eigenen Worten (max 5 S¨tze). a 2. Was ist ein benutzerdefinierter Datentyp ? 3. Welches Datennschutz-Konzept gibt es f¨ r Klassen ? u 4. Wozu brauchen wir zwei Dateien f¨ r Klassen, eine H (Header) Datei und u eine CPP (Quelltext) Datei ? 5. Was ist ein Inklude / Include ? 6. Was ist eine Instanz einer Klasse ? 7. Worin besteht der Unterschied zwischen den Anweisungen: CStudent m std 1 und CStudent* m std 2 ? 8. Was ist ein Konstruktor einer Klasse ? 9. Was ist das Gegenst¨ ck zum Klassen-Konstruktor ? u 10. Wie k¨nnen Daten / Variablen einer Klasse initialisiert werden ? o 11. Schreiben sie den Quelltext f¨ r den Klassen-Konstruktor und weisen sie u den Variablen name first und name last ihren eigenen Namen zu. 12. Was verbirgt sich hinter der Anweisung: CStudent* m std = new CStudent() ? 13. Was ist der Unterschied zwischen CStudent und CStudent() ? 14. Wie kann ich meine Daten gegen einen externen Zugriff sch¨ tzen ? u
  • 35. Kapitel 5 Strings ¨ Wir haben schon in mehreren Ubungen den Datentyp string benutzt, ohne diesen Datentyp etwas n¨her zu beleuchten. Dieses Vers¨umnis soll in diesem Kapitel a a nachgeholt werden. 5.1 Die Standardklasse string String (in Deutsch Zeichenkette) ist vielmehr als nur ein Datentyp, string ist eine Standard-Klasse in C++. String ist eine der genialsten Weiterentwicklungen des C-Datentyps char, die das Hantieren mit Zeichen und Zeichenketten zu einem Kinderspiel macht, na sagen wir mal - uns das Programmierleben erheblich vereinfachen wird, wenn wir mit Zeichenketten operieren werden. So wird z.B. der erforderliche Speicherplatz f¨ r Zeichenketten automatisch reserviert und bei u Ver¨nderungen angepasst. a Wenn wir strings benutzen wollen, m¨ ssen den Header der string-Klasse wie u folgt inkludieren. #include <string> // for using strings using namespace std; // for using standard names Wichtig ist auch die zweite Zeile using namespace std. Diese Anweisung besagt, dass wir im folgenden Standard-Namen benutzen. Sonst m¨ ssten wir vor jeder u string-Operation noch den Zusatz std:: setzen. Zur Benutung von namespace f¨ r u die Strukturierung und Kapselung von Programmteilen gibt es sp¨ter ein Extra- a kapitel (9.2.2). An dieser Stelle zeigen wir die Bedeutung von using namespace std; in bew¨hrter Weise an einem Beispiel. a Sie haben sicher schon bemerkt, dass wir bei #include manchmal eckige Klam- mern <> und manchmal G¨nsef¨ ßchen ” benutzen. Wir schauen uns dies, wie a u 35
  • 36. 36 KAPITEL 5 STRINGS gesagt, genauer im Kapitel 9.2.2 an. Hier nur soviel, dass mit eckigen Klammern <> an Header-Dateien im Systemverzeichnis von C++ gesucht wird, w¨hrend a ” benutzerdefinierte, eigene Header (z.B. student.h) kennzeichnet und somit im aktuellen Arbeitsverzeichnis (also ./) nachgeschaut wird. 5.2 Operationen mit strings ¨ Die nachfolgende Tabelle zeigt eine Ubersicht der wichtigsten string Operatio- nen, die wir in diesem Kapitel verwenden. Methode Erl¨uterung a .append() verl¨ngert den String a .c str() erzeugt Zeichenfeld mit dem Inhalt des Strings .clear() l¨scht den Inhalt des Strings o .compare() vergleicht Strings .erase() l¨scht Zeichen im String o .find() sucht Zeichen in einem String .insert() f¨ gt in den String ein u .length() ermittelt die L¨nge des Strings a .replace() ersetzt Zeichen im String wichtig f¨ r die Konvertierung von string zu char* u .resize() a ¨ndert L¨nge des Strings a .substr() gibt einen Substring zur¨ ck u >> Eingabeoperator f¨ r Strings u << Ausgabeoperator f¨ r Strings u getline() liest Zeichen aus der Eingabe Tabelle 5.1: string Methoden 5.2.1 Initialisieren von strings Eine M¨glichkeit f¨ r die Initialisierung von strings haben wir uns bereits in o u der Exercise E4.5 angesehen bei der Verwendung von Klassen-Konstruktoren. Der Standard-Konstruktor string() erzeugt einen leeren String. Eine zweite M¨glickeit besteht direkt bei der Deklaration des strings, wie folgt: o Exercise E5.2.1: string exercise("Exercise: string initialisation"); cout << exercise.length() << endl;
  • 37. 5.2 OPERATIONEN MIT STRINGS 37 5.2.2 Zuweisen von strings ¨ In der folgenden Ubung schauen wir uns an, wie wir mittels Tastatureingabe (Standard-Eingabe-Ger¨t) strings zuweisen und Teile von strings in andere ko- a pieren zu k¨nnen. o Exercise E5.2.2: #include ... // Bitte f¨gen sie die notwendigen Header selbst ein u main() {... string eingabe; string eingabe_anfang; string message("Bitte geben Sie eine Zeile mit der Tastatur ein. Schliessen Sie die Eingabe mit Enter ab"); //------------------------------------------------------------------- cout << message << endl; // Ausgabe der Eingabeaufforderung getline(cin,eingabe); // Eingabe einer Zeile uber Tastatur ¨ eingabe_anfang(eingabe,0,10); // die ersten 10 Zeichen von eingabe werden nach eingabe_anfang kopiert cout << "Ihr Eingagetext: " << eingabe << endl; cout << "Die ersten 10 Zeichen des Eingagetextes: " << eingabe_anfang << endl; ...} 5.2.3 Verketten von strings Mit dem Operator + k¨nnen Strings miteinander verkn¨ pft werden und in einem o u ¨ neuen string name kopiert. In der folgenden Ubung produzieren wird aus Vor- und Nachnamen den ganzen Namen. Exercise E5.2.3: string name; CStudent* m_std = new CStudent(); name = m_std->name_first + m_std->name_last; // oder name = m_std->name_first; name += m_std->name_last; Wie bekommen wir einen Zwischenraum (Leerzeichen) zwischen Vor- und Nach- namen ? 5.2.4 Vergleichen von strings Oft sind Abfragen notwendig, ob gewisse Zeichenketten gefunden wurden, um dann gewisse Operationen durchzuf¨ hren. Hierf¨ r bietet die String-Klasse meh- u u rere M¨glichkeiten an, z.B. den exakten Vergleich (string::compare) oder einen o
  • 38. 38 KAPITEL 5 STRINGS ¨ Teil von Zeichenketten (string::find). Die nachfolgende Ubung zeigt, wenn der Nachname BOND gefunden wurde, dann wird der Vorname auf JAMES gesetzt (und nat¨ rlich der russische Geheimdienst informiert). u Exercise E5.2.4: if(m_std->name_last.compare("BOND")==0) { m_std->name_first = "JAMES"; } ¨ Die nachfolgende Ubung zeigt, wie ein Programm beendet werden kann, wenn eine bestimmte Taste gedr¨ ckt wird. Hierf¨ r werden einzelne Zeichen mit dem u u Operator == verglichen. string Taste("N"); while(Taste == "J") { cout << "Soll dieses Programm endlich beendet werden? (J/N)" << endl; getline(cin,Taste); } cout << "Programm-Ende" << endl; 5.2.5 Suchen in strings ¨ Diese Ubung zeigt ihnen, wie nach Zeichenketten in string suchen k¨nnen. Sie o sehen, je nach Sorgfalt des Programmierers haben sie eventuell schlechte Karten, wenn ihr Vorname die Zeichenkette ’BON’ enth¨lt. a Exercise E5.2.5: if(m_std->name_last.find("BON")!=string::npos) { m_std->name_first = "JAMES"; } 5.2.6 Einfugen in strings ¨ Nun benutzen wir die Einf¨ ge-Funktion von strings (string::insert), um Vor- u und Nachnamen zusammenzusetzen. Dabei ermitteln wir zun¨chst die L¨nge des a a Vornamen mit string::length, setzen dann den Positionsz¨hler pos um Eins hoch a (Leerzeichen zwischen Vor- und Nachnamen) und f¨ gen dann den Nachnamen u mit string::insert ein. Exercise E5.2.6:
  • 39. 5.2 OPERATIONEN MIT STRINGS 39 string name; int pos; if(m_std->name_first.find("JAMES")!=string::npos) { pos = m_std->name_first.length(); name.insert(pos+1,"BOND"); } 5.2.7 Ersetzen in strings Eine weitere n¨ tzliche String-Funktion ist das Ersetzen von Zeichen. In der u ¨ nachfolgenden Ubung andern wir den Nachnamen. Dazu wird zun¨chst wieder ¨ a die L¨nge des Vornamens mit string::length ermittelt und dann der neue Nach- a name eingef¨gt. So k¨nnen sie ihre Spuren verwischen ... ist auch praktisch bei u o Namens¨nderungen z.B. infolge Heiraten (Beachten sie, dass Triple-Namen wie a M¨ ller-Graf-Kleditsch nicht mehr zul¨ssig sind). u a Exercise E5.2.7: string name; int pos; name = "JAMES" + " " + "CHRISTIE" if(m_std->name_first.find("JAMES")!=string::npos) { pos = m_std->name_first.length(); name.replace(pos+1,"BOND"); } Was passiert, wenn der neue Nachname l¨nger ist als der alte ? a 5.2.8 Loschen in strings ¨ Nat¨ rlich k¨nnen auch Zeichen in einem string gel¨scht werden. Diese Funktion u o o passt den Speicherbedarf des gek¨ rzten Strings automatisch an. u Exercise E5.2.8: string name; int pos; name = "JAMES" + " " + "CHRISTIE" if(m_std->name_first.find("JAMES")!=string::npos) { pos = m_std->name_first.length(); name.erase(pos); name.replace(pos+1,"BOND"); } Abschliessend kommen wir zu zwei weiteren Punkten, (1) das Umwandeln von C++ strings in C char und (2) das Auslesen von string Teilen.
  • 40. 40 KAPITEL 5 STRINGS 5.2.9 Umwandeln von strings in char Manchmal ist es notwendig C++ strings in C char umzuwandeln (wir ben¨tigen o dies sp¨ter, wenn wir mit der MFC Klasse CStrings f¨ r grafische Benutzerober- a u fl¨chen arbeiten). Die String-Methoden c str() und data() wandeln strings in a char um. Aufgepasst, ab char m¨ ssen wir uns selber um das Speichermanage- u ment k¨ mmern. u fprintf(f," %sn",name.c_str()); name.clear(); const char *char_string; char_string = name.data(); 5.2.10 Auswerten von Strings: Stringstreams Stringstreams ... l¨sst sich kaum aussprechen .. es handelt sich aber definitiv a nicht um stringdreams ... (sie erinnern sich an die Eingangsfolie der Vorlesung). Stringstreams sind eine sehr n¨ tzliche Sache, damit lassen sich Eingabedaten u (von Tastatur und Datei) bequem als Stream auswerten. Um Stringstreams ¨ nutzen zu k¨nnen, muss die Klasse sstream inkludiert werden. Die Ubung zeigt, o wie man eine eingegebene Zeile (Vor- und Nachnahme) elegant zerlegen kann. Dabei wird die eingebene Zeile zun¨chst in den stringstream kopiert, danach a wird input line wie ein normaler stream ausgelesen. Exercise E5.2.10: #include <iostream> #include <string> #include <sstream> using namespace std; int main() { string name; string name_first; string name_last; stringstream input_line; cout << "Geben Sie bitte Ihren Namen (Vor- und Nachnamen) ein: "; getline(cin,name); input_line.str(name); // Der Name wird nun zerlegt input_line >> name_first; cout << "Vorname:t" << name_first << endl; input_line >> name_last; cout << "Nachname:t" << name_last << endl; input_line.clear(); return 0; }
  • 41. 5.3 TESTFRAGEN 41 5.3 Testfragen 1. Welche Klasse bietet uns C++ zur Verarbeitung von Zeichenketten an ? 2. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Zeichenketten ? o u 3. Wof¨ r ist die Anweisung using namespace std n¨ tzlich ? u u 4. M¨ ssen wir selber Speicherplatz f¨ r C++ Zeichenketten (Strings) reser- u u vieren ? 5. Wie k¨nnen wir einen String, sagen wir mit der Zeichenkette ”Das ist eine o gute Frage”, initialisieren ? 6. Wie k¨nnen wir zwei Strings, ihren Vor- und Nachnahmen, miteinander o verbinden ? 7. Mit welcher string Funktion kann ich Zeichenketten miteinander verglei- chen ? 8. Schreiben sie eine Anweisung zum Vergleich der Klassen-Variable m std− >name last mit ihrem Nachnamen ? 9. Mit welcher string Funktion kann ich Zeichenketten suchen ? 10. Schreiben sie eine Anweisung zum Suchen ihres Vornamens in der Klassen- Variable m std− >name first ? 11. Mit welcher string Funktion kann ich Teile in Zeichenketten erstetzen ? 12. Wie k¨nnen wir die L¨nge von Strings ermitteln ? o a 13. Schreiben sie die Anweisungen, um ihren Nachnamen in die Zeichenkette ”JAMES BOND” nach ”JAMES” einzuf¨ gen ?u 14. Was passiert, wenn ihr Nachname l¨nger als ”BOND” ist ? a 15. Mit welcher string Funktion k¨nnen wir Zeichen in einem String l¨schen ? o o 16. Wir haben gesehen, dass es verschiedene Daten-Typen f¨ r Zeichenketten u in C, C++, MFC, .NET und Qt gibt. Zeichenketten geh¨ren zu den wich- o tigsten Daten-Typen bei der Programmierung. Wie k¨nnen wir einen C++ o string in eine C Zeichenkette (char) umwandeln ? 17. K¨nnen wir eine .NET Zeichenkette (String∧) in eine C++ Zeichenkette o (string) umwandeln ? 18. Was ist ein stringstream ? 19. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Stringstreams ? o u
  • 42. Kapitel 6 Ein- und Ausgabe - II Nachdem wir uns im Kapitel 3 bereits mit der Ein- und Ausgabe uber die¨ Standard-Ger¨te (Tastatur und Bildschirm) besch¨ftigt haben, geht es in diesem a a Teil um die Dateiverarbeitung. 6.1 Die fstream Klassen Abb. 6.1 zeigt die Hierarchie der fstream Klassen. ios istream ostream iostream ifstream ofstream fstream Abbildung 6.1: Die fstream Klassen Diese sind von den bereits bekannten ios stream Klassen abgeleitet. 42
  • 43. 6.2 ARBEITEN MIT FILE-STREAMS 43 • ifstream: ist von istream abgeleitet f¨ r das Lesen von Dateien. u • ofstream: ist von ostream abgeleitet f¨ r das Schreiben von Dateien. u • fstream: ist von iostream abgeleitet f¨ r das Lesen und Schreiben von Da- u teien. 6.2 Arbeiten mit File-Streams 6.2.1 File-Streams anlegen Er¨ffnungsmodus: Um eine Datei benutzen zu k¨nnen, muss diese zun¨chst o o a ge¨ffnet werden. Daf¨ r gibt es verschiedene M¨glichkeiten (siehe Tab. 6.1). o u o Flag Funktion ios::in Eine (existierende) Datei wird zum Lesen ge¨ffnet. o ios::out Eine Datei wird zum Schreiben ge¨ffnet. o Existierende Inhalte werden uberschrieben. ¨ ios::app Die neuen Inhalten werden an die existierenden angeh¨ngt. a ios::trunc ¨ Eine bestehende Datei wird beim Offnen auf die L¨nge 0 gek¨ rzt. a u ios::ate Schreib- und Leseposition werden auf das Dateiende gesetzt. ios::binary Schreib- und Leseoperationen werden im Bin¨rmodus ausgef¨hrt. a u Tabelle 6.1: Er¨ffnungsmodi f¨ r Dateien o u Die default Werte sind: • ios::in f¨ r ifstream u • ios::out | ios::trunc f¨ r ofstream u 6.2.2 File-Streams schließen Wir wissen schon, dass es bei objekt-orientierten Sprachen immer zwei passende Dinge gibt, z.B. Klassen-Konstruktoren und -Destruktoren. So ist zu erwarten, dass es zu einer Methode ’Datei ¨ffnen’ (open()) auch eine Methode ’Datei o schließen’ gibt (close()) (Tab. 6.4) 6.2.3 ¨ Ubung: Eine einfache Kopierfunktion ¨ In unserer ersten Ubung zur Dateiverarbeitung schreiben wir eine einfache Ko- pierfunktion. Exercise E6.2.3: Eine einfache file copy Funktion
  • 44. 44 KAPITEL 6 EIN- UND AUSGABE - II #include <iostream> // for using cout #include <fstream> // for using ifstream / ofstream #include <string> // for using string using namespace std; // namespace for std functions int main() { //---------------------------------------------------------------- ifstream input_file; // Instance of class ifstream input_file.open("input_file.txt"); // Open file "text_file.txt" string my_string; // Instance of class string input_file >> my_string; // Reading a string from file cout << my_string.data() << endl; // Output of string to screen //---------------------------------------------------------------- ofstream output_file; // Instance of class ifstream output_file.open("output_file.txt"); // Open file "text_file.txt" output_file << my_string; // Writing a string to a file //---------------------------------------------------------------- return 0; } Die Ein- >> und Ausgabeoperatoren << formatieren die Datentypen (z.B. int ¨ in der Ubung E6.2.3) entsprechend den Einstellungen der fstream Klasse. Diese Einstellungen k¨nnen durch Flags ver¨ndert werden (siehe n¨chsten Abschnitt). o a a Die main() Funktion kann auch mit einer Parameterliste (int argc, char *argv[]) versehen werden. Die Anzahl der Parameter (argc) wird automatisch erkannt. MIt jedem Leerzeichen in der Tastatureingabe entsteht ein neuer Ein- gabeparameter (Abb. 6.2). int main(int argc, char *argv[]) { ifstream input_file; // Instance of class ifstream input_file.open(argv[1]); // Open file, name from cin ofstream output_file; // Instance of class ifstream output_file.open(argv[2]); // Open file, name from cin return 0; } Die Benutzung der main Funktion mit Eingabeparametern ist in der folgenden Abbildung zu sehen. Abbildung 6.2: Die main Funktion mit Parametern
  • 45. 6.2 ARBEITEN MIT FILE-STREAMS 45 6.2.4 ¨ Ubung: Ein einfacher Konverter ¨ Ihre Frage nach dem Sinn der Ubung 6.2.3 ist vollkommen berechtigt, wozu ein Programm schreiben, um eine Datei zu kopieren. Das kann ich doch auch mit dem Windows-Explorer oder mit cp file1 file2 machen. Richtig, aber genauso funktionieren Kopierprogramme, Windows-Explorer ruft ’unser’ Ko- ¨ pierprogramm auf. Wenn wir auch nur kleine Anderungen in unserer Datei vor- nehmen wollen (z.B. eine laufenden Nummer in jede Zeile einf¨ gen), kann uns u der Windows-Explorer nicht mehr weiter helfen. Dies ist insbesondere dann a ¨rgerlich, wenn die Datei ziemlich groß ist ... Auch hier sagen sie zu Recht, eine Nummerierung in eine gr¨ßere Datei einf¨ gen, das kann ich z.B. auch mit EX- o u ¨ CEL machen. In der n¨chsten Ubung schreiben wir einen kleinen Konverter, also a genau was EXCEL im Hintergrund macht, wenn wir eine neue Spalte einf¨ gen. u Exercise E6.2.4: Ein einfacher Konverter int main() { //---------------------------------------------------------------- ifstream input_file; // Instance of class ifstream input_file.open("input.txt"); // Open file "text_file.txt" ofstream output_file; // Instance of class ifstream output_file.open("output.txt"); // Open file "text_file.txt" //---------------------------------------------------------------- char line[80]; int i=0; while(input_file.getline(line,80)) // Loop condition { output_file << i << " " << line << endl; i++; // Incrementor (+1) } //---------------------------------------------------------------- return 0; } Unser Konverter macht nichts anderes, als die Datei input.txt zu ¨ffen, nach- o einander alle Zeilen lesen und am Anfang der Zeile eine Nummer (i) einzuf¨ gen u und dann in die neue Datei output.txt zu schreiben. ¨ Was ist neu bei dieser Ubung. C++ Ding Was tut’s while() eine Kontrollstruktur f¨ r Schleifen u (solange der Ausdruck in () wahr (true) ist wird die Schleife ausgef¨hrt) u i++ der Inkremetor (z¨hlt Eins hoch) a Tabelle 6.2: C++ news
  • 46. 46 KAPITEL 6 EIN- UND AUSGABE - II Alle benutzten fstream Methoden finden sie in Tab. 6.4. 6.2.5 Einschub: Erstes Arbeiten mit MS VC++ Wir haben den Editor von MS VC++ ja schon mehrfach benutzt, da die Syntax ¨ des Quelltextes sehr sch¨n angezeigt wird (Abb. 6.3). Uberhaupt ist MS VC++ o ein sehr sch¨nes Entwicklungssystem f¨ r Programmentwicklung ... Wir f¨ hren o u u ¨ die Ubung E6.2.4 jetzt mal mit MS VC++ aus. Abbildung 6.3: Der MS VC++ Editor Standardm¨ßig werden folgende Einf¨rbungen benutzt f¨ r a a u • Keywords: Blau • Kommentare: Gr¨ n u • Normaler Quelltext: Schwarz • Includes: Rot
  • 47. 6.2 ARBEITEN MIT FILE-STREAMS 47 • Zeichenketten: Rot Ich bin mir ziemlich sicher, dass man in einem gut versteckten MS VC++ Menu- punkt alles selber einstellen kann ... Highlighting of sytax ... ist nur eines der sehr n¨ tzliches features (langsam gleiten u wir in IT slang ab). Um MS VC++ richtig nutzen zu k¨nnen, m¨ ssen wir o u ein sogenanntes Projekt anlegen (mal sehen, ob ihre Begeisterung danach noch anh¨lt). Die Schritte f¨ r die Projekterstellung finden sie in der Anlage (Abschn. a u 12.4) ... Nachdem das Projekt angelegt ist, k¨nnen wir damit arbeiten. o ¨ Abbildung 6.4: Ubersetzen sie das Projekt mit F7 (build solution) Abbildung 6.5: Das Debug Verzeichnis
  • 48. 48 KAPITEL 6 EIN- UND AUSGABE - II MSVS legt allerhand Zeug’s an. Das executable finden sie im Unterverzeichnis Debug und kann nat¨ rlich mit einem Doppelklick gestartet werden. Wir starten u die Konsolenanwendung aus MSVS mit Ctrl-F5 (Abb. 6.6). Abbildung 6.6: Starten der Konsolenanwendung mit Ctrl-F5 oder Menu- Auswahl (Start without debugging) ¨ Hier wartet schon die erste Uberraschung auf uns: pwd wird nicht erkannt und wir werden aufgefordert eine Zeit einzugeben (Abb. 6.7). Abbildung 6.7: Das Debug Verzeichnis Was ist passiert ? • pwd ist ein Linux-Befehl, den kennt der Windows-Compiler nicht. • time gibt es auch als DOS-Befehl, hat aber eine ganz andere Bedeutung: nicht Ausgabe der Zeit sondern Zeit ¨ndern. a Wir sehen also, dass unser Quellcode von verschiedenen Compilern unterschied- lich interpretiert wird.
  • 49. 6.3 FILE-STREAMS UND KLASSEN 49 . Abbildung 6.8: Der Windows bereinigte Quelltext Sie sehen ’Sch¨nheit’ hat auch ihren Preis ... dennoch die Funktionalit¨t der MS o a VC++ Entwicklungsumgebung, das muss man neidlos anerkennen, ist einfach Klasse. 6.3 File-Streams und Klassen Wir wollen eine Lesefunktion f¨ r die Klasse CStudent schreiben. Bevor wir u damit beginnen, m¨ ssen wir uns Gedanken uber eine geeignete Struktur f¨ r die u ¨ u Darstellung eines CStudent Datensatzes in einer Datei machen. Der Vorschlag f¨ r die Strukturierung von Datens¨tzen ist die Benutzung von Schl¨ sselw¨rtern u a u o zur Trennung von Datenbl¨cken, z.B. o #STUDENT $NAME_FIRST James $NAME_LAST Bond ... #STOP Wir benutzen zwei verschiedene Symbole f¨ r Schl¨ sselw¨rter: u u o
  • 50. 50 KAPITEL 6 EIN- UND AUSGABE - II • keyword # : zur Trennung von Datens¨tzen f¨ r eine Instanz von CStudent, a u • subkeyword $ : zur Identifizierung der einzelnen Daten f¨ r die CStudent u Instanz. • #STOP zeigt das Ende der Datenbasis an. (Eigentlich w¨re dies nicht a n¨tig, da das Dateiende auch mit dem Parameter eof (end-of-file) ab- o gefragt werden kann. Wir werden aber sehen, dass mit #STOP einiges einfacher zu programmieren ist.) Exercise E6.3: Implementierung der CStudent Lesefunktion ios::pos_type CStudent::Read(ifstream& input_file) { //---------------------------------------------------------------------- string input_line; char buffer[256]; // MAX_LINE ios::pos_type position; //---------------------------------------------------------------------- while(true) { position = input_file.tellg(); input_file.getline(buffer,256); input_line = buffer; if(input_line.size()<1) // empty line continue; // Dealing with keywords if(input_line.find(’#’)!=string::npos) // keyword found return position; // Dealing with subkeywords if(input_line.find("$NAME_FIRST")!=string::npos) { input_file.getline(buffer,256); input_line = buffer; name_first = input_line; } if(input_line.find("$NAME_LAST")!=string::npos) { input_file >> name_last; } if(input_line.find("$subkeyword")!=string::npos) { input_file >> member; } } //---------------------------------------------------------------------- return position; }
  • 51. 6.3 FILE-STREAMS UND KLASSEN 51 Der Lesealgorithmus funktioniert wird folgt: Nach dem Auffinden eines Schl¨ ssel- u worts #STUDENT, wird in einer while Schleife nach subkeywords ($) gesucht, wenn gefunden, werden der CStudent Instanz die Werte aus der Eingabedatei zugewiesen (also die Namen). Wenn das n¨chste Schl¨ sselwort (#STUDENT a u oder #STOP) gefunden wird, geht’s mit der vorletzten Position raus aus der Funktion. Die vorletzte position ist wichtig, damit die letzte Zeile sp¨ter noch- a mal gelesen werden kann, um das Schl¨ sselwort auswerten zu k¨nnen ... u o Die Implementierung der main Funktion, in der die CStudent::Read() Funktion aufgerufen wird, ist im folgenden Block dargestellt. #include <iostream> // for using cout #include <fstream> // for using ifstream / ofstream #include <string> // for using string #include "student.h" // for using CStudents using namespace std; // for std functions int main() { //---------------------------------------------------------------- // File handling ifstream input_file; // ifstream instance input_file.open("data_set.txt"); if(!input_file.good()) // Check is file existing { cout << "! Error in STD::Read: file could not be opened" << endl; return 0; } input_file.seekg(0L,ios::beg); // Rewind file //---------------------------------------------------------------- CStudent* m_std = new CStudent(); // CStudent instance m_std->Read(input_file); //---------------------------------------------------------------- input_file.close(); return 0; } Die main Funktion besteht aus zwei Teilen, dem File-Handling und dem Aufruf der Lesefunktion. Beim File-Handling wird der stream aus der Datei data set.txt ge¨ffnet, anschließend erfolgt der Test, ob das File erfolgreich ge¨ffnet werden o o konnte; wenn nicht, wir die main Funktion sofort beendet. ¨ Was ist neu bei dieser Ubung. Wir benutzen den Referenz-Operator & (Kapitel 7) als Parameter der Funktion CStudent::Read(). Eine Referenz ist eigentlich nicht anderes als ein anderer Bezeichner (Alias) f¨ r eine bereits existierende Instanz eines Objekts. Es kann u also mehrere solcher Referenzen geben und vor Benutzung einer Referenz muss die Instanz des Objekts physikalisch (also speicherm¨ßig) vorhanden sein, sonst a ’crashed’ unser Programm.
  • 52. 52 KAPITEL 6 EIN- UND AUSGABE - II C++ Ding Was tut’s ifstream& input file eine Reference auf ein Objekt wird in Kapitel 7 ausf¨ hrlich abgehandelt u Tabelle 6.3: C++ news 6.4 fstream Methoden Die bisher benutzten fstream Methoden sind in der Tab. 6.4 zusammengestellt. Methode Funktion open() o ¨ffnet die Datei good() ¨ tested erfolgreiche Offnung der Datei seekg(pos,ios::beg) geht zur Position pos in der Datei seekg(0L,ios::beg) spoolt zum Dateianfang zur¨ ck u tellg() merkt sich die aktuelle Position im stream getline(buffer,256) holt eine Zeile der L¨nge 256 (Zeichen) aus dem stream a und kopiert diese in buffer close() schließt Datei >> Eingabeoperator f¨ r Dateien u << Ausgabeoperator f¨ r Dateien u Tabelle 6.4: fstream Methoden Die string Auswertung spielt bei der Lesefunktion eine wichtige Rolle, daher ha- ben wir uns wir uns im vorangegangenen Kapitel mit der string Klasse besch¨ftigt. a
  • 53. 6.5 TESTFRAGEN 53 6.5 Testfragen 1. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ? u 2. Was sind die C++ Klassen f¨ r das Lesen und Schreiben von Dateien ? u 3. Welchen Include ben¨tigen wir f¨ r das Arbeiten mit I/O File-Klassen ? o u 4. Was sind die Standard-Flags f¨ r File-Streams (Lesen und Schreiben) ? u 5. Mit welchem Flag k¨nnen wir zu schreibende Daten an eine existierende o Datei anh¨ngen ? a 6. Was ist der Unterschied zwischen ASCII- und Bin¨r-Formaten ? a 7. Mit welchem Flag k¨nnen wir Daten in einem Bin¨r-Format schreiben ? o a Mit welcher Anweisung wird ein File ge¨ffnet ? Mit welcher Anweisung o wird ein File geschlossen ? 8. Was bewirken die Stream-Operatoren << und >> ? 9. Wie k¨nnen wir mit Dateinamen in unserem Hauptprogramm main(...) o arbeiten ? 10. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen o u u Eingabe-Strom ? 11. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen o u u Ausgabe-Strom ? 12. F¨ r die Erstellung einer Datenbank ist es wichtig einzelnen Datens¨tze zu u a trennen. Wie k¨nnen wir soetwas in der Datenbank-Datei bewerkstelligen o ? 13. Ist es wichtig das Ende einer Datenbank-Datei, z.B. mit einem Schl¨ ssel- u wort #STOP, zu markieren ? o u ¨ 14. Mit welcher Abfrage k¨nne wir pr¨ fen, ob die Offnung einer Datei erfolg- reich war ? 15. Mit welcher Anweisung k¨nnen wir die aktuell gelesene Position in einer o ge¨ffneten Datei abfragen ? o 16. Mit welcher Anweisung k¨nnen wir zu einer bestimmten Position in einer o ge¨ffneten Datei springen ? o 17. Mit welcher Anweisung k¨nnen wir eine komplette Zeile aus ge¨ffneten o o Datei auslesen ?
  • 54. Kapitel 7 Referenzen und Zeiger Referenzen und Zeiger (pointer), d.h. die Symbole & und * sind uns bereits mehrfach begegnet, z.B. in der Parameterliste der main() Funktion ... Generell k¨nnen Zeiger und Referenzen als einfache Variable, Parameter oder R¨ ckgabe- o u wert (return) einer Funktion auftauchen. ¨ In der Ubung E6.3 haben wir bereits mit Referenzen gearbeitet und festgestellt, dass Referenzen eigentlich nichts anderes als andere Bezeichner (Alias) f¨ r eine u bereits existierende Instanz eines Objekts sind. Es kann also mehrere solcher Referenzen geben. Bei der Definition eines Zeigers wird also kein neuer Spei- cher reserviert. Die Instanz des Objekts muss physikalisch (also speicherm¨ßig) a nat¨ rlich vorhanden sein, sonst ’verabschiedet’ sich unser Programm gleich wie- u der. x &ref_x x Referenz auf das Objekt y Objekt im Speicher Abbildung 7.1: Referenzen auf Objekte 54
  • 55. 7.1 REFERENZEN 55 7.1 Referenzen 7.1.1 Das Call-by-reference Prinzip - Referenzen als Pa- rameter Def: Eine Referenz ist nichts anderes als ein anderer Name (Alias) f¨ r ein bereits u existierendes Objekt. Bei der Definition einer Referenz wird also kein neuer Speicherplatz f¨ r das Objekt belegt (außer nat¨ rlich die 4 Byte f¨ r die Referenz u u u selbst). Die Abb 7.2 soll das Konzept des Referenzierens noch einmal verdeutlichen. • x ist die Instanz eines Datentyps T • &ref x ist eine Referenz (Verweis) auf x ¨ In der ersten Ubung sehen die Definition von Referenzen und Zeigern im Quell- text ¨ Ubung: E7.1.1 double x = 1.23456789; double* ptr_x; double& ref_x = x; // initialisation is needed ¨ Die Bildschirmausgabe der ersten Ubung zeigt Folgendes: Abbildung 7.2: Referenzen auf Objekte Eine Referenz (ref x) muss bei der Definition initialisiert werden (mit x), sonst bekommen sie eine Fehlermeldung beim Kompilieren. Der Referenztyp-Parameter (&) ist ein Aliasname f¨ r das ’richtige’ Argument. u Beim Aufruf der Funktion wird der Referenz-Parameter mit dem Objekt initia- lisiert. Die Funktion arbeitet also direkt mit dem von außen ubergebenen Argu- ¨ ¨ ment. Das ’Call-by-reference’ Prinzip ist sozusagen eine Ubergabe-von-Außen. Wir schauen uns dies mal an bei der CStudent-Lesefunktion aus der letzten Vorlesung. ¨ Ubung: E7.1.1
  • 56. 56 KAPITEL 7 REFERENZEN UND ZEIGER Definition: CStudent::Read(ifstream& ref_input_file) Aufruf: ifstream input_file; CStudent* m_std = new CStudent(); // CStudent instance m_std->Read(input_file); Was passiert ? Beim Aufruf der Lese-Funktion Read wird die Adresse des ifstream Objekts (input file) an die Funktion ubergeben. Das heisst die Lese-Funktion ¨ arbeitet intern mit dem ’richtigen’ Objekt. ’Call-by-reference’ Prinzip erm¨glicht o es also der Funktion einen Zugriff auf Daten des Aufrufers. Beim sogenannten ’Call-by-value’ Prinzip k¨nnen Funktions-Argumente inner- o halb der Funktion nicht ge¨ndert werden. a 7.1.2 Referenzen als Ruckgabe-Wert ¨ Referenzen auf Objekte k¨nnen auch R¨ ckgabe-Werte von Funktionen sein. o u ¨ Ubung: E7.1.2 (aus [5]) Definition: string& message() { static string m_str("Vorsicht Speicher-Falle"); return m_str; } Aufruf: !!! Das Objekt muss nach dem Verlassen der Funktion noch existieren ¨ Was ist neu bei dieser Ubung. C++ Ding Was tut’s static Speicherklasse: der Speicher f¨ r das Objekt bleibt w¨hrend u a der gesamten Programmausf¨ hrung bestehen, u wird in Kapitel 7.3 ausf¨ hrlich abgehandelt. u Tabelle 7.1: C++ news 7.2 Zeiger Zeiger sind eine der Grundideen moderner Programmiersprachen. Dabei arbei- tet man nicht direkt mit den Daten-Bl¨cken im Speicher sondern mit deren o Adressen. Dies macht insbesondere Sinn, wenn es um große Daten-Objekte geht
  • 57. 7.2 ZEIGER 57 oder bei Objekten, die erst zur Laufzeit angelegt werden (z.B. Vektoren, Li- sten, Strings). Das Klassen-Prinzip unterst¨ tzt die Zeigertechnik optimal, da u die Klasse ihre Daten ja selber verwaltet (siehe Klassenkonstruktur) Der Zeiger (pointer) auf ein Objekt repr¨sentiert dessen Adresse und Daten-Typ. a 7.2.1 Definition von Zeigern ¨ Die nachfolgende Ubung zeigt, wie wir Zeiger definieren und mit ihnen arbeiten k¨nnen. F¨ r den Zugriff auf Zeiger gibt es den sogenannten Verweisoperator ’*’. o u ¨ Ubung: E7.2 (aus [5]) int main() { int i, *ptr_i; // Definitionen i = 100; // Zuweisung ptr_i = &i; // Dem Zeiger wird die Adresse der integer Variable i zugewiesen *ptr_i += 1; // Die integer Variable i wird um Eins erh¨ht (i += 1;) o } ⇒Geben sie Werte und Adressen der Integer-Variable i und den Zeiger auf i (i ptr) aus. Unabh¨ngig vom Daten-Typ ist der ben¨tigte Speicher f¨ r eine Zeigervariable a o u immer gleich groß - der zur Speicherung ben¨tigte Platz f¨ r die Adresse des o u Objekts (4 Byte auf einer 32-Bit-Rechner-Architektur, siehe auch Abb. 7.2). ¨ Was ist neu bei dieser Ubung. C++ Ding Was tut’s *ptr Verweisoperator (un¨r: ein Operand) a i*i Multiplikations-Operator (bi¨r: zwei Operanden) a Tabelle 7.2: C++ news: Operatoren 7.2.2 NULL Zeiger Wir haben gesehen, dass Referenzen auf Daten-Objekte zwingenderweise in- itialisiert werden m¨ ssen (sonst streikt der Kompiler). Zeiger m¨ ssen eigentlich u u nicht initialisiert werden, ihnen wird bei der Definition eine ’vern¨ nftige’ Adres- u se zu gewiesen. Dies bedeutet noch lange nicht, dass sich hinter dieser Adresse etwas Vern¨ nftiges verbirgt. Daher ist es ratsam, auch Zeiger zu initialisieren, u um Nachfragen zu k¨nnen, ob sie tats¨chlich auf existierende Objekte zeigen. o a Zum Initialisieren von Pointern gibt es den NULL-Zeiger.
  • 58. 58 KAPITEL 7 REFERENZEN UND ZEIGER double* ptr_x = NULL; ptr_x = &x; if(!ptr_x) cout << "Warning: ptr_x does not have a meaningful adress"; Der linke Operand der Operators = muss immer auf eine ’sinnvolle’ Speicher- stelle verweisen. Dieser wird daher auch als so genannter L-Wert (L(eft) value) bezeichnet. Wenn eine Fehlermeldung ’wrong L-value’ erscheint, wissen sie, dass keine ’sinnvolle’ Adresse vergeben wurde, dies spricht wiederum f¨ r eine Initia- u lisierung von Zeigern mit Zero-Pointer. 7.2.3 Zeiger als Parameter Der Verweisoperator ist uns unl¨ngst schon mal begegnet bei der erweiterten a main() Funktion mit Eingabeparametern: int main(int argc, char* argv[]) 7.3 Zeiger und Arrays Wie bereits gesagt, die Verzeigerungs-Technik ist eine der Besonderheiten von objekt-orientierten Sprachen, wie z.B. von C++. Mit solchen Pointern k¨nnen o wir auch gr¨ßere Daten-Objekte wie Vektoren verwalten. Die zentrale Idee ist: o Wenn Startpunkt (id Adresse) und L¨nge des Vektors bekannt sind, wissen wir a eigentlich alles und k¨nnen auf alle Vektor-Daten zugreifen. o 7.3.1 Statische Objekte Bei der Einf¨ hrung der String-Klasse hatten wir bereits mit Zeichenketten zu u tun. Aus der Sicht des Speichers ist eine Zeichenkette ein Vektor der eine be- stimmte Anzahl von Zeichen enth¨lt. Vektoren k¨nnen nat¨ rlich f¨r (fast) alle a o u u Datentypen definiert werden. Im n¨chsten Kapitel (8) besch¨ftigen wir uns mit a a sogenannten Containern, damit k¨nnen z.B. Vektoren, Listen etc. f¨ r ganze o u Klassen generiert werden. char Zeichenkette[80]; int iVektor[50]; double dVektor[50]; 7.3.2 Dynamische Objekte Bisher haben wir uns fast ausschließlich mit Datentypen besch¨ftigt, deren a Speicherbedarf bereits w¨hrend der Kompilierung fest steht und reserviert wird a (bis auf Strings-Objekte). Es gibt aber auch die M¨glichkeit, den Speicherbe- o darf w¨hrend der Programmausf¨ hrung zu ¨ndern - dies geht mit dynamischen a u a Daten-Objekten. Die werden wir folgt deklariert.
  • 59. 7.4 SUMMARY 59 char* Zeichenkette; int* iVektor; double* dVektor; Nun m¨ ssen wir uns allerdings selber um die Speicherreservierung k¨ mmern. u u ¨ Dies erfolgt mit dem new-Operator und wird in der n¨chsten Ubung gezeigt. a Wir ahnen schon, wenn es etwas zum Vereinbaren von Speicher gibt, muss es wohl auch das Gegenst¨ ck - freigeben von Speicher - geben. Nat¨ rlich habe sie u u Recht. Dies erledigt der delete-Operator. double* dVektor; dVektor = new double[1000]; delete [] dVektor; Die Anwendung beider Operatoren zum Speichermanagement sowie eine M¨glich- o ¨ keit, den verbrauchten Speicher zu messen, werden in der folgenden Ubung ge- zeigt. ¨ Ubung: E7.3.2 #include <iostream> // for using cout #include <malloc.h> // for using malloc_usable_size using namespace std; int main() { char* Zeichenkette; // Definitions long size_memory; // Auxiliary variable for memory size Zeichenkette = new char[1000]; // Memory allocation size_memory = malloc_usable_size(Zeichenkette); // calculation of memomry delete [] Zeichenkette; // Memory release return 0; } HomeWork: HW7.3.2 Schreiben sie ein kleines Programm, mit der sie den ben¨tigten Speicher ermit- o teln k¨nnen und pr¨ fen sie, ob die Freigabe des Speichers funktioniert hat. o u Zeiger k¨nnen auch verschachtelt werden: Zeiger auf Zeiger ... Damit lassen sich o mehrdimensionale Datenstrukturen schaffen, z.B. Matrizen. 7.4 Summary Das Verstehen und Arbeiten mit Zeigern und Referenzen ist nicht ganz ein- fach und braucht eine ganze Zeit der praktischen Anwendung. Der *Operator
  • 60. 60 KAPITEL 7 REFERENZEN UND ZEIGER **matrix *matrix[0] *matrix[1] *matrix[2] *matrix[1][0] *matrix[1][1] *matrix[1][2] Abbildung 7.3: Die Definition einer Matrix mittels Pointer kann beispielsweise als Zeiger auf etwas und gleichzeitig f¨ r dynamische Vek- u toren benutzt werden. Dies scheint zun¨chst absolut verwirrend zu sein, beim a ¨ genaueren Uberlegen aber: * ist lediglich die Startadresse f¨ r den Vektor. Mer- u ken sie sich erst einmal nur, dass es geschickter (und schneller) ist, nicht mit den Daten-Objekten direkt sondern mit Verweisen darauf (also deren Adres- sen) zu arbeiten. Die nachfolgende Tabelle und Abbildung sollen das Thema ’Referenzen und Zeiger’ noch einmal illustrieren. Syntax Bedeutung double x Definition einer doppelt-genauen Gleitkommazahl (Speicherbedarf 8 Byte) double* ptr Zeiger auf eine doppelt-genauen Gleitkommazahl (Speicherbedarf 4 Byte) double& ref Referenz auf eine doppelt-genaue Gleitkommazahl (Speicherbedarf 4 Byte) double* dVektor Zeiger auf einen Gleitkommazahl-Vektor Tabelle 7.3: Zeiger und Referenzen ptr_x x &x x &ptr_x ptr_x *ptr_x Adresse von ptr_x Adresse von x Wert von x Wert von ptr_x Abbildung 7.4: Referenzen und Zeiger (nach [5])
  • 61. 7.5 TESTFRAGEN 61 7.5 Testfragen 1. Was ist &x ? (x ist ein beliebiger Datenobjekt T, z.B. eine Gleitkomma- zahl: double x) 2. Was ist eine Referenz &ref? 3. Was bedeutet die Anweisung: &ref = x? 4. Erkl¨ren sie kurz (mit eigenen Worten) das Zeiger-Konzept in C++? a 5. Was bewirkt der NULL Zeiger, d.h. *ptr = NULL ? 6. Was bedeutet die Anweisung: ptr = x? 7. M¨ ssen Referenzen (&) und Zeiger (*) auf Daten-Objekte initialisiert wer- u den ? 8. Was bewirkt die Definition long l[1000] speichertechnisch ? 9. Wie groß ist der Speicherbedarf des statischen Datenobjekts long l[1000] ? 10. Wie groß ist der Speicherbedarf des dynamische Datenobjekts long* ptr l = new long[1000] ? 11. Woher kommt der Unterschied (4 Byte auf einem 32Bit Rechner) im Speicherbedarf zwischen statischen und dynamischen Datenobjekten. 12. Zusatzfrage: Was bedeutet die Definition **ptrptr (Zeiger auf Zeiger), was f¨ r ein Datenkonstrukt entsteht ? u
  • 62. Kapitel 8 Container Wir haben bereits mit der String-Klasse gesehen, dass C++ neben der Ba- sisfunktionalit¨t einer Programmiersprache auch sehr n¨ tzliche Erweiterungen, a u wie das Arbeiten mit Zeichenketten, anbietet. Diese Erweiterungen geh¨ren o zum Standard von C++, geh¨ren also zum ’Lieferumfang’ des Compilers dazu o und heißen daher auch Standard-Klassen. Diese Klassen bilden die sogenannte Standard-Bibliothek (STL - STandard Library). In diesem Kapitel besch¨ftigen wir uns mit sogenannten Containern mit de- a nen Daten organisiert, gespeichert und verwaltet werden k¨nnen, z.B. Listen o und Vektoren. In der Abb. 8.1 sind die wichtigsten Elemente der Container dargestellt. Der Begriff Container soll verdeutlichen, dass Objekte des gleichen Typs z.B. in einer Liste gespeichert werden. Und wie immer bei Klassen, werden nat¨ rlich auch die Methoden f¨ r den Zugriff oder die Bearbeitung von diesen u u Objekten bereitgestellt. Die Speicherverwaltung f¨ r Container-Elemente erfolgt u dynamisch zur Laufzeit (siehe Kapitel Speicherverwaltung). Die Abb. 8.1 zeigt auch, welche verschiedenen Typen von Containern es gibt: Sequentielle Container: sind z.B. Vektoren, Listen, Queues und Stacks. Vek- toren sind Felder (arrays) in denen die einzelnen Elemente nacheinander angeordnet sind. Bei einer Liste kennt jedes Element nur seine Nach- barn (Vorg¨nger- und Nachfolgeelement). Queues (wir kennen dies von a Druckern) sind Warteschlangen, die nach dem FIFO-Prinzip (first in, first out) funktionieren. Das heißt, dass zuerst eingef¨ gte Element wird auch u zuerst verarbeitet (z.B. Druckjobs). Stacks sind sogenannte Kellerstapel, die nach dem LIFO-Prinzip (last in, first out) funktionieren. Das bedeutet, das zuletzt eingef¨ gte Element wird zuerst verarbeitet. u Assoziative Container: sind z.B. Maps (Karten) und Bitsets. Die Elemen- te sind nicht wie bei sequentiellen Container linear angeordnet sondern in bestimmtem Strukturen (z.B. Baumstrukturen). Dies erm¨glicht einen o besonders schnellen Datenzugriff, der uber eine Verschl¨ sselung erfolgt. ¨ u 62
  • 63. 8.1 SEQUENTIELLE CONTAINER 63 Container sequential associative Container Container Vectors Stacks Queues Sets Maps Bitsets Abbildung 8.1: C++ Container (Bildquellen: www.prachensky.com) Die Besonderheit der C++ Container ist die dynamische Speicherverwaltung. Das heisst, Einf¨ gen und Entfernen von Container-Elementen ist sehr einfach, u wir brauchen uns nicht selbst um das Speichermanagement zu k¨ mmern. Dies u ubernehmen die Konstruktoren und Destruktoren (siehe Abschnitt 4.4) der je- ¨ weiligen Container-Klasse. 8.1 Sequentielle Container Ein weiterer Grund f¨ r die Bereitstellung von Containern ist, dass die Elemente u gemeinsame Datentypen und Methoden haben. Der Datentyp T eines Containers ist nat¨ rlich eine (beliebige) Klasse. Die Tab. 8.1 listet die Klassentemplates f¨ r u u einige sequentielle Container sowie die ben¨tigen Include-Files auf. o Ein Klassentemplate ist nichts weiter als eine formale Beschreibung der Syntax.
  • 64. 64 KAPITEL 8 CONTAINER Klassen-Template Include-Files vector<T,Allocator> <vector> list<T,Allocator> <list> stack<T,Container> <stack> queue<T,Container> <queue> Tabelle 8.1: Klassentemplates f¨ r sequentielle Container u • vector: Schl¨ sselwort u • < ... >: Parameterliste • T: erster Parameter, Datentyp des Vektors • Allocator: zweiter Parameter, Speichermodell des Vektors Die Methoden sequentieller Container sind sehr einfach, intuitiv zu bedienen und sie sind gleich f¨ r Vektoren, Listen etc. Ein Auswahl der wichtigsten ge- u meinsamen Methoden finden sie in der nachfolgenden Tabelle. Methode Bedeutung size() Anzahl der Elemente, L¨nge de Containers a push back(T) Einf¨ gen eines Elements am Ende u pop back() L¨schen des letzten Elements o insert(p,T) Einf¨ gen eines Elements vor p u erase(p) L¨schen des p-Elements (an der Stelle p) o clear() L¨scht alle Elemente o resize(n) ¨ Andern der Containerl¨nge a Tabelle 8.2: Methoden f¨ r sequentielle Container u 8.2 Vectors The standard vector is a template defined in namespace std and presented in <vector>. The vector container is introduced in stages: member types, iterators, element access, constructors, list operations etc. The structure of a vector is illustrated in Fig. 8.2. Abbildung 8.2: Structure of vectors Following lines are necessary in order to use the vector container in your sources code.
  • 65. 8.2 VECTORS 65 #include <vector> using namespace std; Types: Very different types can be used in vectors. A vector e.g. of integers can be declared in this way. // Declaration and construction vector<int> v; Constructors: With the above source code a vector of integer types is constructed as well. Stack operators: The functions push back and pop back treat the vector as a stack by adding and removing elements from its end. // Input elements to vector for(i=0;i<9;i++) { v.push_back(i+1); } Iterators: Iterators can be used to navigate containers without the programmer having to know the actual type to identify the elements, e.g. for inserting and deleting elements. A few number of key functions allow to step through the elements, such as begin() pointing to first element and end() pointing to the one-past-last element. An example of a loop through all vector elements using the iterator is given below. // Navigating vector elements for(vector<int>::iterator it=v.begin(); it!=v.end(); ++it) { cout << *it << ’n’; } Vector elements can be addressed directly by element number. Fast data access is an advantage of vectors. Abbildung 8.3: Access to vector elements In contrast, vectors are not as flexible as lists. Deleting and adding of elements within the vector is complicated (Fig. 8.4).
  • 66. 66 KAPITEL 8 CONTAINER Abbildung 8.4: Deleting elements Programming exercises 8.2.1 Defining vectors In the first exercise we just define a vector and insert some elements into it in order to show the concept. Exercise 8.2.1 #include <iostream> // for using cout #include <vector> // for using vectors using namespace std; // for std functions void main() { //------------------------------------------------------- cout << "E81 - Working with vectors" << endl; //------------------------------------------------------- vector<int>my_vector; // Declaration of vector my_vector.push_back(1); // Inserting an element to vector my_vector.push_back(3); my_vector.push_back(5); for(int i=0;i<(int)my_vector.size();i++) { cout << my_vector[i] << endl; // Access to vector elements } //------------------------------------------------------- } 8.2.2 Vectors and data base ¨ In der n¨chsten Ubung werden einige Dinge, die wir bisher gelernt haben, zu- a sammenbringen. Sie werden sehen, dass ’gut’ programmierte Dinge einfach ’zu- sammengebaut’ werden k¨nnen: Objekte (Kapitel 4), IO-Methoden (Kapitel 6), o Stringverarbeitung (Kapitel 5).
  • 67. 8.2 VECTORS 67 Exercise 8.2.2 #include <iostream> // for using cout #include <fstream> // for using ifstream / ofstream #include <string> // for using string #include <vector> // for using vectors #include "student.h" // for using CStudents using namespace std; // for std functions #define MAX_ZEILE 256 bool STDRead(ifstream&); int main() { //---------------------------------------------------------------- cout << "E82: an object-oriented DB read function" << endl; //---------------------------------------------------------------- // 1 File handling ifstream input_file; // ifstream instance input_file.open("data_base.txt"); if(!input_file.good()) // Check is file existing { cout << "! Error: input file could not be opened" << endl; return 0; } //---------------------------------------------------------------- // 2 Read data base STDRead(input_file); //---------------------------------------------------------------- return 0; } Unser Programm besteht aus drei gekapselten Teilen: • main(): Das Hauptprogramm: die Steuerzentrale, hier wir i.W. das Da- teimanagement erledigt. • STDRead(ifstream&): Die ubergeordnete Lesefunktion f¨ r die komplet- ¨ u te Datenbank, hier befindet sich eigentlich nur eine Schleife, welche die Objekt-Lesefunktion aufruft, solange Daten in der Datei vorhanden sind. • CStudent::Read(ifstream): Die Objekt-Lesefunktion, die liest die ei- gentlichen Daten f¨ r jeden Datensatz aus der Datenbankdatei. u ¨ Der einzige Ubergabeparameter ist die Datenbank-Datei: std file.
  • 68. 68 KAPITEL 8 CONTAINER Exercise 8.2.2 continued /************************************************************************** STDLib-Method: Task: Reading all STD objects 06/2009 OK Implementation **************************************************************************/ bool STDRead(ifstream& std_file) { //-1-------------------------------------------------------------------- char line[MAX_ZEILE]; string line_string; ios::pos_type position; vector<CStudent*>std_vector; CStudent* m_std = NULL; //---------------------------------------------------------------------- //OK STDDelete(); //-2-------------------------------------------------------------------- // rewind the file std_file.seekg(0,ios::beg); //-3-------------------------------------------------------------------- // OBJ reading, keyword loop cout << "STDRead" << endl; while (!std_file.eof()) { std_file.getline(line,MAX_ZEILE); line_string = line; if(line_string.find("#STOP")!=string::npos) break; if(line_string.find("#STUDENT")!=string::npos) { m_std = new CStudent(); position = m_std->Read(std_file); // from E63 std_vector.push_back(m_std); std_file.seekg(position,ios::beg); } } // eof //---------------------------------------------------------------------- cout << "Number of data sets: " << std_vector.size() << endl; return true; } 8.2.3 Updating your data base entry Homework 8.2.3a: Please update your data base entries and send it by mail to me (olaf.kolditz@ufz.de). Homework 8.2.3b: Please write a print function for the CStudent class.
  • 69. 8.3 LISTS 69 8.3 Lists A list is a sequence optimized for insertion and deletion of elements. They allow a very flexible organization of elements. But the price for flexibility is a relatively slow access to data. List provides bidirectional iterators (Fig. 8.3). This implies that a STL list will typically be implemented using some form of a doubly-linked list. Abbildung 8.5: Structure of lists Following lines are necessary in order to use the list container in your sources code. #include <list> using namespace std; Types: All data types are possible for lists, e.g. a class. // Declaration list<CStudent*> std_list; list<int> int_list; Constructors: With the above source code a list for class instances is constructed as well. Stack operators: Lists provide same typical member functions as for vectors. // Insert list elements at end CStudent* m_std; my_list.push_back(m_std); Iterators: Again iterators can be used to navigate lists. We show an example for deleting a specific element from the list. Identification of the list element is by name (Fig. 8.6). Abbildung 8.6: Deleting list elements The following exercise shows how conveniently we can deal with lists, i.e. in order to sort, reverse, merge, and unify lists. The unifying function removes
  • 70. 70 KAPITEL 8 CONTAINER multiple entries from lists, which is a very nice tool in order to clean a data base. Exercise 8.3 #include <iostream> // for using cout #include <list> // for using lists using namespace std; // for std functions typedef list<int>INTLIST; void display(list<int>); int main() { int i; list<int>list1; INTLIST list2; // Filling the list with random numbers for(i=0;i<4;i++) { list1.push_back(rand()%10); list2.push_back(rand()%10); } display(list1); // Display the list display(list2); // Putting first element to the end as well list1.push_back(list1.front()); list1.reverse(); // Reverse list list1.sort(); // Sort list list1.merge(list2); // Merge two lists list1.sort(); // Remove multiple entries #1 list1.unique(); // Remove multiple entries #2 return 0; } void display(list<int>my_list) { int i; list<int>::const_iterator iterator; iterator = my_list.begin(); while(iterator != my_list.end()) { i = *iterator; cout << i << endl; ++iterator; } } The concept of the data base read function is illustrated in Fig. 8.7.
  • 71. 8.4 TESTFRAGEN 71 main() Files STDRead(ifstream&) STD::Read() Abbildung 8.7: Data base read concept The last exercise shows how we can delete entries from the students data base (i.e. people we don’t like) // Deleting list elements CStudent* m_std = NULL; list<CStudent*>::const_iterator p = std_list.begin(); while(p!=std_list.end()) { m_std = *p; if(m_std->GetStudentName()=="James Bond") { my_list.remove(*p); break; } ++p; } // Deleting repeated entries std_list.unique(); 8.4 Testfragen 1. Was sind C++ Container ? 2. Welche Typen von C++ Containern kennen sie ? 3. Worin besteht der Unterschied zwischen sequentiellen und assoziativen Containern ? 4. Welche sequentiellen Container kennen sie ? 5. Erkl¨ren sie die Syntax des Vektor-Containers: vector<int>my vector . a 6. Was ist der Unterschied zwischen Vektoren und Listen ? 7. Was sind die Gemeinsamkeiten von Vektoren und Listen ? 8. Welcher Include ist notwendig f¨ r das Arbeiten mit Vektoren ? u 9. Welcher Include ist notwendig f¨ r das Arbeiten mit Listen ? u
  • 72. 72 KAPITEL 8 CONTAINER 10. Ben¨tigen wir den Zusatz (Namensraum) using namespace std, wenn ja o warum ? 11. Mit welcher Instruktion k¨nnen Elemente in Vektoren und Listen einf¨ gen o u ? 12. Wo werden sequentielle Container-Elemente mit der Instruktion push back(T) eingef¨ gt ? u 13. Mit welcher Anweisung k¨nnen wir die L¨nge von sequentiellen Container- o a Elementen bestimmen ? 14. Mit welcher Anweisung k¨nnen wir einen Vektor platt machen (d.h. alle o Elemente l¨schen) ? o 15. Wie k¨nnen wir auf ein Vektor-Element, sagen wir das 17te Element des o Vektors vector<int>my vector, direkt zugreifen ? 16. Quellcode verstehen: Erkl¨ren sie die Struktur (1,2,3) der DB-Lese-Funktion a ¨ STDRead(ifstream& std file) in der Ubung 8.2.2. Beginnen sie mit der Pa- rameterliste. 17. Wie k¨nnen wir unsere Studenten-Klasse CStudent in die DB-Anwendung o ¨ (Ubung 8.2.1) einbinden ? u a ¨ 18. Was ist eigentliche Lesefunktion f¨ r unsere Studenten-Datens¨tze (Ubung 8.2.2) ? 19. Mit welchem Befehl k¨nnen wir die Reihenfolge von Listen-Elementen o umkehren ? 20. K¨nnen wir Listen-Elemente sortieren, wenn ja wie, mit welcher Instruk- o tion ? 21. Mit welchem Befehl k¨nnen wir mehrere Listen zusammenf¨ hren ? o u 22. K¨nnen wir doppelte Elemente aus einer Liste entfernen sortieren, wenn o ja wie, mit welcher Instruktion ? 23. Was ist ein Iterator ? 24. Quellcode verstehen: Erkl¨ren sie die Funktion void display(list<int>my list) a ¨ der Ubung 8.3. Beginnen sie mit der Parameterliste. 25. Wie k¨nnen wir Elemente aus einer Liste entfernen ? o
  • 73. Kapitel 9 Andere Sprachelemente Wir haben das Ende der C++ Grundvorlesung erreicht (hoffentlich ein Grund zur Freude). Das Ziel der Vorlesung ’Hydroinformatik’ ist allerdings bei Weitem noch nicht erreicht. Sie erinnern sich, wir wollen eine Dialog-gef¨hrte Datenbank- u Anwendung (Fig. 4) mit C++ entwickeln. Sie werden sehen, dass wir fast al- le Bausteine beisammen haben (außer die Grafik-Programmierung mit Visual C++) und die Realisierung unser Applikation (nach der langen Vorbereitung) dann sehr schnell geht. Bevor wir zum graphischen (Visual) C++ kommen, wollen wir Sprachelemen- te (C++ news), die wir zuvor schon benutzt haben, aber noch nicht explizit besprochen haben, hier kurz einf¨ hren. u 9.1 Kontrollstrukturen Bei Kontrollstrukturen handelt es sich um Sprachelemente f¨ r bedingte Anwei- u sungen und Schleifen mit Z¨hlern und Bedingungen. a Control Bedeutung if-else Anweisungen mit Bedingungen switch-case Fallunterscheidungen for Schleifen mit Z¨hlern a while Schleifen mit Bedingungen Tabelle 9.1: Kontrollstrukturen Verschachtelungen von Kontrollstrukturen sind nat¨ rlich m¨glich. u o 73
  • 74. 74 KAPITEL 9 ANDERE SPRACHELEMENTE 9.1.1 if-else Es geht um die Ausf¨ hrung von Anweisungen und Alternativen unter bestimm- u ten Bedingungen. Ausf¨ hrung einer Anweisung unter einer Bedingung (siehe, u ¨ z.B. Ubung 8.2.2): if(logische Bedingung) {...} // Ausf¨hrung, wenn Bedingung erf¨llt ist u u Ausf¨ hrung einer Anweisung unter einer Bedingung mit Alternative (else) (sie- u ¨ he, z.B. Ubung 8.2.2): if(logische Bedingung) {...} // Ausf¨hrung, wenn Bedingung erf¨llt ist u u else {...} // Ausf¨hrung, wenn Bedingung nicht erf¨llt ist u u 9.1.2 switch-case Die Kontrollstruktur switch-case bietet die M¨glichkeit von Fallunterscheidun- o gen durch Ausdr¨ cke (z.B. Aufz¨hlungen durch Zahlen). Der Schalter switch u a springt entsprechend dem Zahlenausdruck in einen Fall case. switch(Ausdruck) { case 0: // wenn Ausdruck == 0 ... // Anweisungen break; // Verlassen default: // wenn kein Ausdruck zutrifft } Es gibt eine weitere Variante, wo der Ausdruck ein Zeichen sein kann. switch(Ausdruck) { case ’A’: // wenn Ausdruck == A ... // Anweisung break; // Verlassen } Eine weitere M¨glichkeit diese Kontrollstruktur elegant einzusetzen ist die Be- o nutzung von enum - einem Konstrukt f¨ r eigene Z¨hler. u a enum Wochentag {Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag} Die einzelnen Wochentage bekommen dann aufsteigende Werte (von 0 begin- nend) zugewiesen. Dann k¨nnen wir unsere Fallunterscheidung (z.B. f¨ r das o u Mensa-Men¨ ) wie folgt schreiben: u
  • 75. 9.1 KONTROLLSTRUKTUREN 75 switch(Wochentag) { case Montag: // wenn Wochentag == 0 case Dienstag: // wenn Wochentag == 1 ... case Sonntag: // wenn Wochentag == 6 } 9.1.3 for Die for Schleife ist eine Schleife mit einem Z¨hler. a for(int i=0;i<stop;i++) { ... // Anweisungen } Die Anweisungen im Funktionsrumpf {...} werden solange ausgef¨ hrt, bis der u Z¨hler den Wert stop erreicht (das heißt, f¨ r den Wert stop wird die Schleife a u nicht mehr ausgef¨ hrt). Bei jedem Schleifendurchlauf wird der Z¨hler i um Eins u a (i++) hochgez¨hlt. Ich habe gerade mal nachgesehen. In unserem Programm- a system OpenGeoSys wird die for-Schleife uber 4000 mal verwendet! Wir haben ¨ ¨ sie z.B. in der Ubung 8.2.1 zum Generieren von Vektor-Elementen benutzt. 9.1.4 while Die while Schleife ist eine Endlos-Schleife mit einer Bedingung. while(Bedingung) { ... // Anweisungen } Die Anweisungen im Funktionsrumpf {...} werden ausgef¨ hrt, solange die Be- u dingung erf¨ llt (das heißt, der numerische Wert Bedingung muss gr¨ßer als 0 u o sein). Um aus der Schleife herauszukommen, muss also der Wert der Bedingung ge¨ndert werden - oder ’hart’ abgebrochen werden (siehe n¨chster Abschn. 9.1.5) a a In unserem Programmsystem OpenGeoSys wird die while-Schleife fast 500 mal ¨ verwendet! Wir haben sie f¨ r unsere Lesefunktion (Ubung 8.2.1) und beim Ite- u ¨ rieren in Listen (Ubung 8.2.1) verwendet. 9.1.5 continue, break, return Es gibt mehrere M¨glichkeiten, um Kontrollstrukturen (vorzeitig) verlassen zu o k¨nnen. o
  • 76. 76 KAPITEL 9 ANDERE SPRACHELEMENTE 9.2 Gultigkeitsbereiche ¨ F¨ r alles, was wir deklarieren, Funktionen, Klassen, Variablen gibt es G¨ ltig- u u keitsbereiche. Wenn irgendwo etwas definieren, ist es also nicht uberall sicht- ¨ bar. Wir hatten uns mit diesem Thema schon bei der Definition von ’privaten’ Klassen-Elementen besch¨ftigt (Abschn. 4.6). Die Abb. ?? zeigt das Prinzip von a lokalen und globalen G¨ ltigkeitsbereichen. Wir sollen immer versuchen soviel u wie m¨glich lokal zu definieren, das unterst¨ tzt die Daten-Kapselung in unse- o u rem Programm. Klassen sind immer nur dort sichtbar, wo ihre Header-Dateien inkludiert worden sind. 9.2.1 Namensbereiche Sind uns auch schon mehrfach begegnet bei der Verwendung von Strings, Vekto- ren und Listen. Dabei wurde nach dem Includieren der entsprechenden Header- Dateien die Anweisung using namespace std benutzt. Strings, Vektoren und Listen geh¨ren zum Namensraum der Standard-Bibliothek STL. o #include <strings> std::my_string("Beispiel ohne Namensbereich"); using namespace std; my_string("Beispiel mit Namensbereich"); Wir k¨nnen auch eigene Namensbereiche definieren. o namespace Meins { // hier sind Funktionen des Namensbereichs class CStudent } using namespace Meins; Wozu ? Wenn sie ihren Programmcode mit einem anderen Entwickler zusam- menf¨ hren wollen und es gibt mehrere Klassen CStudent, dann k¨nnen sie sicher u o auf ihre Funktion zugreifen, wenn sie ihren Namensraum gesetzt haben. 9.2.2 Compiler-Direktiven – # Alles was mit # anf¨ngt, versetzt den Kompiler in den Alarmzustand - es sind a sogenannte Kompiler-Direktiven, das heißt beim Kompilieren werden gewisse Weichen gestellt.
  • 77. ¨ 9.2 GULTIGKEITSBEREICHE 77 Direktive Wirkung #include Einf¨ gen einer Header-Datei u #define Definition einer Direktive #ifdef Wenn die Direktive gilt #ifndef Wenn sie nicht gilt #endif Ende der Direktive #define Definition eines Makros Tabelle 9.2: Compiler-Direktiven 9.2.2.1 Includes Ohne Includes geht gar nichts, sie erinnern sich, selbst um einfache Bildschirm- ausgaben mit cout machen zu k¨nnen mussten wir Klasse iostream einf¨ gen. o u An dieser Stelle nochmal zur Erinnerung. Es gibt Arten von Includes: <Header> Die eckigen Klammern bedeuten, es geht um einen System-Inklude. Es wird im Systemverzeichnis (dort wo C++ installiert ist) gesucht. ”Header” Die G¨nsef¨ ßchen bedeuten, es geht um einen eigenen Inklude. Es a u wird lokalem Verzeichnis gesucht. Wenn der Programm-Code verzweigt ist, also eine komplexere Verzeichnisstruk- tur hat, m¨ ssen Pfade der Inklude-Dateien mit angegeben werden, sonst werden u sie nicht gefunden. Keine Angst, in diesem Falle bekommen sie sofort eine ein- deutige Fehler-Meldung beim Versuch zu Kompilieren. 9.2.2.2 Bedingte Kompilation Eine sehr n¨ tzliche Sache sind Direktiven f¨ r die Kompilation von Test-Versionen. u u Gerade w¨hrend der Entwicklung m¨chte man neue Programmteile einfach an- a o und ausschalten k¨nnen. Dies geht mit der Kompiler-Direktive (KD) #ifdef. o #define TEST // Anschalten der Direktive TEST #ifdef TEST ... #endif Wenn die Kompiler-Direktive TEST an ist, wird der Programmtext von der Stel- le #ifdef bis #endif beim Kompilieren ubersetzt, ansonsten einfach ignoriert. ¨ Kompiler-Direktiven sind immer aus, wenn sie nicht explizit eingeschaltet wer- den. Das Gegenst¨ ck von #ifdef ist #infdef, also wenn die Kompiler-Direktive u aus ist. Oft m¨ ssen Funktionen uberarbeitet werden. Mit Kompiler-Direktiven u ¨ kann man sehr sch¨n eine neue Variante der Funktion entwickeln und die alte o
  • 78. 78 KAPITEL 9 ANDERE SPRACHELEMENTE erstmal zu Vergleichszwecken beibehalten. Erst wenn alles richtig funktioniert, schmeißt man das alte Zeug weg. ¨ Ubung 9.2.2.2: #define NEW_VERSION // Anschalten der Direktive NEW_VERSION #ifdef NEW_VERSION ... // wenn NEW_VERSION an ist #else ... // wenn NEW_VERSION aus ist #endif ¨ Ich empfehle ihnen, das mal in irgendeiner Ubung auszuprobieren. Wichtig: Denken sie immer an das #endif zum Ausschalten, sonst gilt die Kompiler- Direktive bis zum Ende des gesamten Programms. 9.2.2.3 Makros Die Kompiler-Direktive #define kann auch zur Definition sogenannter Makros verwendet werden, z.B. f¨ r Konstanten, die man oft benutzt. Es geht aber auch u f¨ r einfache Funktionen oder sogar Print-Anweisungen. u #define PI 3.1416 // Definition der Zahl PI #define MULT(a,b) ((a)*(b)) #define PRINT(x) cout << (#x) << ": " << (x); Der Makro-Einsatz sollte aber nicht ubertrieben werden, eigentlich gibt es daf¨ r ¨ u richtige Funktionen. Bei Makros werden z.B. keine Pr¨ fungen durch den Kom- u piler gemacht, daher sind sie fehleranf¨llig. a 9.3 Testfragen 1. Was sind Kontrollstrukturen, welche kennen sie ? 2. Bei welcher logischen Bedingung wird eine if-Anweisung ausgef¨ hrt ? u 3. Lassen sich Kontroll-Strukturen verschachteln ? 4. Mit welcher Kontrollstruktur k¨nnen wir Fallunterscheidungen program- o mieren ? 5. Welche Ausdr¨ cke k¨nnen wir bei der switch-case Kontrollstruktur be- u o nutzen ? 6. Wie kann ich eine Kompiler-Direktive an- und ausschalten ?
  • 79. 9.3 TESTFRAGEN 79 ¨ 7. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle u von #ifdef um. 8. Erl¨utern sie den Kopf der for-Schleife: for(int i=0;i<stop;i++), wel- a chen Daten-Typ hat stop ? 9. Was ist eine Endlos-Schleife, wie kommen wir daraus ? 10. Was sind Namensbereiche ? 11. Was m¨ ssen wir tun, um die Arbeit mit C++ Standard-Klassen zu verein- u fachen, d.h anstelle von std::my string() direkt my string() benutzen zu k¨nnen ? o 12. Was sind Kompiler-Direktiven, was bewirken diese ? 13. Wie k¨nnen wir Kompiler-Direktiven an- und ausschalten ? o 14. Worin besteht der Unterschied bei Includes mit eckigen Klammern < ... > bzw. mit G¨nsef¨ ßchen ”...” ? a u ¨ 15. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle u von #ifdef um ? 16. Was sind Makros ? 17. Welche beiden Einsatzm¨glickeiten von Makros gibt es ? o 18. Worin besteht die Gefahr, Makros als Funktionsersatz zu benutzen ?
  • 80. Part II Visual C++ Wir kommen zur grafischen Programmierung - ’Visual C++’. Leider m¨ ssen wir u uns nun f¨ r ein Betriebssystem entscheiden, da die Grafikprogrammierung platt- u formabh¨ngig ist. Es gibt zwar auch plattformunabh¨ngige Grafik-Bibliotheken a a aber die kosten aber in der Regel ... Die Entscheidung ist nicht leicht (die Mac’s und Ubuntu’s werden jetzt zu Recht schimpfen) aber sie f¨ hrt unweigerlich zu u Windows. Die Ideen und Techniken der Grafik-Programmierung sind gr¨ßten- o teils unabh¨ngig vom Betriebssystem, so werden auch die nicht-Windows’ler a eine Menge lernen. Man kann Windows unter Ubuntu emulieren, na schauen wir mal (siehe Anlage 12.7) ... Mittlerweile gibt es auch plattformunabh¨ngige a Grafik-Bibliotheken wie z.B. Qt (siehe Anlage 11) die open source sind. Abbildung 9.1: Eine der bekanntesten Dialog-Applikationen: Der RAR-Packer
  • 81. 9.3 TESTFRAGEN 81 Prinzipiell gibt es folgende Konzepte f¨ r die Grafik-Programmierung: u • Dialoge (Abschn. 10), • Dokumente und Ansichten (Doc-View concept), • und nat¨ rlich diverse Kombinationen. u Eine typische Dialog-Applikation ist z.B. der RAR-Packer zum Komprimie- ren von Dateien unter Windows (Abb. 9.1). MS-Word ist eine Anwendung des Doc-View-Konzepts, dabei k¨nnen gleichzeitig mehrere Dokumente (d.h. Word- o Dateien) ge¨ffnet und bearbeitet werden (Abb. 9.2) o Abbildung 9.2: Eine der bekanntesten Doc-View-Applikationen: MS Word
  • 82. Kapitel 10 Dialoge Dialoge geh¨ren zu den einfachsten Anwendungen von grafischen Benutzer- o schnittstellen (GUI graphical user interface). Ihre Aufgabe ist, es eine grafisch- gest¨ tzte Interaktion (Dialog) mit einem Programm zu erm¨glichen. Wir besch¨fti- u o a gen uns mit drei Varianten grafische Dialoge zu produzieren: • dem MFC Dialog (Abschn. 10.1), • dem .NET Formular (Abschn. 10.4), • dem Qt Dialog (Abschn. 11). Mit dem .NET Formular m¨ ssen wir uns ’notgedrungen’ besch¨ftigen, da die u a freien Express Editionen von VC++ (2005 und 2008) die Microsoft-Foundation- Classes (MFC) nicht mehr unterst¨ tzen. Die Erzeugung der leeren Dialoganwen- u dungen mit MFC, .NET und Qt finden sie in der Anlage. 10.1 What have we (i.e. MFC) created ? Finden sie es nicht auch etwas unheimlich, mit 5 Maus-Klicks etwas kreiert zu haben, was sich auf unserem Bildschirm hin- und her verschieben l¨sst (Ab- a schn. 12.5) ... Schauen wir uns in Ruhe an, was VC++ f¨ r uns erledigt hat. u Der ’Solution-Explorer’ auf der rechten Seite von VC++ (Abb. 10.1) gibt uns Aufschluss uber den automatisch erzeugten Code. Den kompletten Quellcode ¨ ¨ der leeren Dialog-Anwendung finden sie in der Ubung E10.1. 82
  • 83. 10.1 WHAT HAVE WE (I.E. MFC) CREATED ? 83 . Abbildung 10.1: Der ’Solution-Explorer’ • Header Files: wie gewohnt, unsere Klassen-Definitionen, • Resource Files: neu, unsere grafischen Elemente, • Source Files: unser aktives Bet¨tigungsfeld zum Programmieren. a • ReadMe.txt: ... endlich eine Erkl¨rung, es lohnt sich diese ReadMe-Datei a zu lesen. oder file-m¨ßig aufgedr¨selt: a o • MyDialog.*: Die Windows-Applikation • MyDialogDlg.*: Unser Ding, • Resource.h: Die IDs unserer grafischen Elemente (wird automatisch ak- tualisiert ...), • stdafx.*: Irgendwas, das Windows standartm¨ßig braucht ... a Die Abb. 10.2 soll illustrieren, was VC++ f¨ r uns freundlicherweise erzeugt hat. u • MyDialog.cpp/h enth¨lt die Windows-Applikation, die erzeugt und ruft a den Dialog auf: CMyDialogApp::InitInstance(). • MyDialog.rc ist die Dialog-Resource, der grafische Dialog mit seinen Ele- menten. Dialog-Resourcen und Dialog-Elemente werden uber Nummern ¨ (IDD/IDs) zugeordnet.
  • 84. 84 KAPITEL 10 DIALOGE IDD_MYDIALOG Dialog Resource Funktionen ‘hinter’ den Dialog-Elementen Windows Application MyDialogDlg.cpp/h MyDialog.cpp/h Abbildung 10.2: What have ’we’ created? • MyDialogDlg.cpp/h enth¨lt alle Funktionen des Dialogs, also das was hin- a ter den Kn¨pfchen steckt ... o Die Windows-Applikation macht nichts anderes, als den Dialog aufzurufen. CMyDialogApp theApp; BOOL CMyDialogApp::InitInstance() { CMyDialogDlg dlg; // Instanz der Dialog-Klasse dlg.DoModal(); // Aufruf des Dialogs
  • 85. 10.2 GESTALTUNG DES DIALOGS 85 10.2 Gestaltung des Dialogs Zum Design des Dialogs bietet MS-VC++ viele M¨glichkeiten. Hierf¨ r benutzen o u wir den Resourcen-Editor (Abb. 10.3). Abbildung 10.3: Die Dialog-Resource und der Dialog-Editor Die Resourcen-Elemente der ToolBox k¨nne einfach auf das Dialog-Feld ’gezo- o gen’ werden (’Drag and drop’). Die Gestaltung des Dialogs (also die Positionen und IDs von jedem Element) ist dann in der Datei Resources.rc gespeichert.
  • 86. 86 KAPITEL 10 DIALOGE Resources.rc ... IDD_MYFIRSTWINDOWS_DIALOG DIALOGEX 0, 0, 320, 246 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "MyFirstWindows" FONT 8, "MS Sans Serif" BEGIN CONTROL "Geoecology",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,10, 110,54,10 CONTROL "Geology",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,10,124, 42,10 CONTROL "AEG",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP, 10,95,31,10 DEFPUSHBUTTON "OK",IDOK,265,230,50,14 PUSHBUTTON "Cancel",IDCANCEL,5,230,50,14 GROUPBOX "Student data",IDC_STATIC,0,0,170,225 GROUPBOX "Students data base",IDC_STATIC,175,0,140,85 GROUPBOX "Biometric picture",IDC_STATIC,175,90,140,135 LTEXT "First name",IDC_STATIC,5,15,33,8 LTEXT "Last name",IDC_STATIC,5,30,34,8 LTEXT "Birthday",IDC_STATIC,5,45,26,8 LTEXT "Matrikel",IDC_STATIC,5,60,26,8 LTEXT "Bank account",IDC_STATIC,5,75,46,8 EDITTEXT IDC_EDIT1,60,15,105,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT2,60,30,105,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT3,60,45,105,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT4,60,60,105,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT5,60,75,105,14,ES_AUTOHSCROLL | WS_DISABLED EDITTEXT IDC_EDIT6,60,205,105,14,ES_AUTOHSCROLL | WS_DISABLED PUSHBUTTON "Read DB",IDC_BUTTON1,180,15,50,14 PUSHBUTTON "Write DB",IDC_BUTTON2,260,15,50,14 LISTBOX IDC_LIST1,180,35,75,45,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Add",IDC_BUTTON3,260,35,50,14 PUSHBUTTON "Edit",IDC_BUTTON4,260,50,50,14 PUSHBUTTON "Remove",IDC_BUTTON5,260,65,50,14 LTEXT "Mark",IDC_STATIC,5,205,17,8 LTEXT "Home work I",IDC_STATIC,5,160,41,8 LTEXT "Home work II",IDC_STATIC,5,175,43,8 EDITTEXT IDC_EDIT7,60,145,105,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT8,60,160,30,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT9,60,175,30,14,ES_AUTOHSCROLL LTEXT "e-mail",IDC_STATIC,5,145,19,8 EDITTEXT IDC_EDIT10,95,160,70,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT11,95,175,70,14,ES_AUTOHSCROLL PUSHBUTTON "Info",IDC_BUTTON7,5,185,50,14 END
  • 87. 10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG 87 10.3 Programmierung des Dialogs – MyDialogDlg Um jetzt mit dem Programmieren unseres Dialogs beginnen zu k¨nnen, m¨ ssen o u wir uns den Zusammenhang zwischen Dialog-Resource (also seine grafische Ge- stalt) mit seinen Elementen (Kn¨pfchen ...) anschauen. Alle Funktionen und o Daten unseres Dialogs befinden sich in der Klasse CMyDialogDlg, die von der (Windows) Basis-Klasse CDialog abgeleitet wird (dies nennt man auch Verer- bung). class CMyDialogDlg : public CDialog 10.3.1 Dialog-Funktionen Die alles entscheidende Stelle, die Verbindung zwischen Dialog-Resource und Funktionen erfolgt in der sogenannten MESSAGE MAP (Nachrichten-Schleife) durch die Anweisung (Abb. 10.6) BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog) ... ON_BN_CLICKED(IDC_BUTTON, OnButtonReadDB) ... END_MESSAGE_MAP() die nichts anderes besagt, wenn das Kn¨pfchen IDC BUTTON gedr¨ ckt wird, dann o u f¨ hre die Funktion OnButtonReadDB aus. u ID = IDC_BUTTON CMyDialogDlg Resource.h BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog) #define IDD_DIALOG 129 ... #define IDB_MARTIN_ZIPPEL 201 ON_BN_CLICKED(IDC_BUTTON, OnButtonReadDB) #define IDC_BUTTON 1009 ... END_MESSAGE_MAP() MyDialog.rc Abbildung 10.4: Dialog-Resource und Dialog-Klasse - Teil 1: Funktionen 10.3.2 Dialog-Daten Wie der Datenaustausch zwischen der Dialog-Resource und der Dialog-Klasse erfolgt, ist in der Abb. 10.7 dargestellt.
  • 88. 88 KAPITEL 10 DIALOGE ID = IDC_EDIT1 CMyDialogDlg Resource.h DoDataExchange() #define IDC_EDIT1 1000 ... DDX_Text(pDX, IDC_EDIT1, m_str_FirstName); ... Abbildung 10.5: Dialog-Resource und Dialog-Klasse - Teil 2: Daten Das Entscheidende passiert in der Funktion DoDataExchange(). Hier wird das, was wir z.B. in das Editier-Feld (First name) eintippen an die (string) Variable m strFirstName weitergeben. Aufgepasst, die Datenaustausch-Funktion wird nicht automatisch aufgerufen, wie die Funktionen in der MESSAGE MAP. Daf¨ r u gibt es einen triftigen Grund, der Datenaustausch kann in beide Richtungen zwischen Dialog und Klasse erfolgen. Wir schauen uns das sp¨ter in der Imple- a mentierung des Dialogs genau an. void CMyDialogDlg::DoDataExchange(CDataExchange* pDX) {... CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, m_strFirstName); ...} 10.3.3 Implementierung des Dialogs MyDialogDlg.h Im Header-File der Klasse erfolgt die Deklaration der Daten und Funktionen. Das Einf¨ gen von neuen Daten-Elementen und Funktionen ist Bestandteil der u ¨ Ubung 10.3. Schritte f¨ r neue Daten-Elemente: u 1. Erzeugen des Daten-Elements (IDC EDIT1) mit dem Resourcen-Editor (z.B. Editier-Feld), 2. Deklarieren der Dialog-Variable: CString m strFirstName, 3. Datenaustausch zwischen Resource und Variable: DDX Text(pDX, IDC EDIT1, m strFirstName). Schritte f¨ r neue Funktionen: u 1. Erzeugen des Funktions-Elements (IDC BUTTON) mit dem Resourcen-Editor (z.B. Button),
  • 89. 10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG 89 2. Deklarieren der Funktion: void OnButtonReadDB(), 3. Verkn¨ pfen von Resource mit Funktion: ON BN CLICKED(IDC BUTTON, OnButtonReadDB). u Das komplette Ergebnis finden sie im Header-File des Dialogs MyDialogDlg.h. class CMyDialogDlg : public CDialog {... // Dialog data CListBox m_STDVector; // Studenten-Liste CString m_strFirstName; // Vorname CString m_strLastName; // Nachname ... // Dialog functions afx_msg void OnButtonReadDB(); // Lesen der DB afx_msg void OnButtonWriteDB(); // Schreiben der DB afx_msg void OnSelchangeList(); // ¨nderungen anzeigen A afx_msg void OnButtonAdd(); // Hinzuf¨gen eines Datensatzes u afx_msg void OnButtonRemove(); // L¨schen eines Datensatzes o afx_msg void OnButtonEdit(); // Editieren eines Datensatzes ...}; 10.3.4 Schnittstelle zwischen Dialog- und Studenten-Klasse Im CPP-File der Klasse (MyDialogDlg.cpp) stehen unsere Funktionen also die Schnittstelle zwischen dem Dialog und unserer Studenten-Klasse CStudent. Da- her darf nat¨ rlich auch nicht der entsprechende Include fehlen. u #include "student.h" Wir schauen uns nun zwei Funktionen im Detail an, das Lesen der Datenbank OnButtonReadDB() und das Anzeigen der Datens¨tze OnSelchangeList(). Da- a bei sehen wir, wie die Interaktion zwischen Dialog und unserer Studenten-Klasse ¨ funktioniert. Den kompletten Quelltext finden sie in der Ubung E10.3. Lesen der Datenbank - OnButtonReadDB() Die Funktion hinter dem Kn¨pfchen ’Read DB’ macht drei Dinge: o • File handling, Offen der DB Datei (Details in Abschn. 10.3.5), ¨ • Lesen der DB, dies ist 1-zu-1 unser DB Lesefunktion (Ubung E8.2.2), ¨ • Die Listen-Box (CListBox m STDVector) mit den gelesenen Datens¨tzen a (Namen) wird gef¨ llt u
  • 90. 90 KAPITEL 10 DIALOGE void CMyDialogDlg::OnButtonReadDB() { //------------------------------------------------------- // 1 File handling see section "File handling" //------------------------------------------------------- // 2 Read DB file STDRead((string)file_name); //------------------------------------------------------- // 3 Fill list box CStudent* m_std = NULL; string m_str; for(int i=0;i<std_vector.size();i++) { m_std = std_vector[i]; m_str = m_std->name_first + " " + m_std->name_last; m_STDVector.AddString(m_str.c_str()); } } Anzeigen der Datens¨tze - OnSelchangeList() a Wenn wir auf einen Namen in der Listen-Box klicken, wird eine Funktion aus- gef¨ hrt, welche uns die Daten des ausgew¨hlten Studenten anzeigt. u a Diese Funktion besteht aus vier Teilen: • Bestimmen der Position des Mausklicks im der Listen-Box (nSel), • Zugriff auf den Datensatz (m std) aus der DB entsprechend der angeklick- ten Position und Kopieren der Daten in die Daten-Elemente des Dialogs, • Anzeigen des BMPs (Foto) (Details in 10.3.5), • Aktualisieren des Daten-Elemente des Dialogs. void CMyFirstWindowsDlg::OnSelchangeList() { //-1-------------------------------------------------------------------- int nSel = m_STDVector.GetCurSel(); //-2-------------------------------------------------------------------- if(nSel>-1) { m_std = student_vector[nSel]; m_strFirstName = m_std->name_first.c_str(); m_strLastName = m_std->name_last.c_str(); m_strBirthDay = m_std->birthday.c_str(); m_lMatrikelNumber = m_std->id; m_strEMail = m_std->email.c_str();
  • 91. 10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG 91 m_strHomeWorkI_submitted = m_std->home_work_I_submitted.c_str(); m_strHomeWorkI_submitted = m_std->message.c_str(); m_iHomeWorkI = m_std->home_work_I; m_strHomeWorkII_submitted = m_std->home_work_II_submitted.c_str(); m_iHomeWorkII = m_std->home_work_II; m_iCredit = m_std->credit; } //-3-------------------------------------------------------------------- // BMP //-4-------------------------------------------------------------------- UpdateData(FALSE); // Akualisieren der Dialog-Elemente } Sortieren der Datens¨tze - OnBnClickedButtonDBSort() a Beim alphabetischen Sortieren der Datens¨tze k¨nnen wir uns die Sortier-Funktion a o der Listen zu Nutze machen. void CMyDialog::OnBnClickedButtonDBSort() { STDSort(); UpdateSTDVector(); } void STDSort() { //---------------------------------------------------------------- int i; CStudent* m_std = NULL; list<string>name_list; for(i=0;i<(int)std_vector.size();i++) { m_std = std_vector[i]; name_list.push_back(m_std->name_last); } //---------------------------------------------------------------- name_list.sort(); //---------------------------------------------------------------- // list<string>::const_iterator iterator; iterator = name_list.begin(); string name_last; while(iterator != name_list.end()) { name_last = *iterator; for(i=0;i<(int)std_vector.size();i++) { m_std = std_vector[i]; if(m_std->name_last.compare(name_last)==0)
  • 92. 92 KAPITEL 10 DIALOGE { std_vector_sorted.push_back(m_std); } } ++iterator; } } void CMyDialog::UpdateSTDVector() { std_vector.clear(); for(int i=0;i<(int)std_vector_sorted.size();i++) { std_vector.push_back(std_vector_sorted[i]); } std_vector_sorted.clear(); UpdateSTDVectorList(); } 10.3.5 Nutzliche Windows-Funktionen ¨ Wir benutzen fertige Windows-Funktionen / MFC Klassen f¨ r die Datei-Auswahl u (CFileDialog) und das Anzeigen von BMPs (DrawBitmap). File handling CString file_name; CFileDialog fileDlg(TRUE,"dat",NULL,OFN_ENABLESIZING,"DAT Files(*.dat)|*.dat||"); if(fileDlg.DoModal()==IDOK) { file_name = fileDlg.GetFileName(); } Bitmaps Die Schritte zum Zeichnen des BMPs (Fotos) sind folgende: • Auswahl des rechteckigen Zeichenbereichs (CRect rc), • Auswahl des entsprechenden BMPs (IDB BITMAP1), • Zeichnen des ausgew¨hlten BMPs (DrawBitmap()) a void CMyFirstWindowsDlg::OnButtonReadDB() {... CRect rc; GetClientRect(&rc);
  • 93. 10.3 PROGRAMMIERUNG DES DIALOGS – MYDIALOGDLG 93 rc.top = 160; rc.left= 290; CBitmap m_bmpStudent; m_bmpStudent.DeleteObject(); m_bmpStudent.LoadBitmap(IDB_BITMAP1); DrawBitmap(rc,m_bmpStudent); ...} Dies ist die Zeichenfunktion des ausgew¨hlten BMBs. a void CMyDialogDlg::DrawBitmap(CRect& rc,CBitmap& bm) { CPaintDC dc(this); HBITMAP hbmpOld; CDC dcMem; dcMem.CreateCompatibleDC(&dc); hbmpOld = (HBITMAP)dcMem.SelectObject(bm); GetDC()->BitBlt(rc.left,rc.top,rc.right,rc.bottom,&dcMem,0,0,SRCCOPY); dcMem.SelectObject(hbmpOld); }
  • 94. 94 KAPITEL 10 DIALOGE 10.4 Das .NET Formular .NET (sprich dotnet) ist eine von Microsoft entwickelte Software-Plattform. Die- se umfasst eine Laufzeitumgebung, eine f¨ r Programmierer bestimmte Samm- u lung von Klassenbibliotheken (API) und angeschlossene Dienstprogramme (Ser- vices) (Quelle http://de.wikipedia.org/wiki/.NET). Mit .NET soll i.W. auch Vereinheitlichung der (MS) Programmiersprachen VisualBasic (VC), C sharp (C#) und C++ erreicht werden. Die Gestaltung des Formulars mit dem Resourcen- Editor (siehe Anlage 12.6) funktioniert genauso so einfach wie bei den MFC- Dialogen (Anlage 10.2). Abbildung 10.6: Die Formular-Resource In der ReadMe.txt finden wir eine Beschreibung, was der Anwendungs-Assistent f¨ r uns erstellt hat. u ======================================================================== ANWENDUNG: MyForm-Projekt¨bersicht u ======================================================================== Diese MyForm-Anwendung wurde vom Anwendungs-Assistenten f¨r Sie erstellt. u Diese Datei enth¨lt eine Zusammenfassung dessen, was Sie in jeder der Dateien a finden, aus denen Ihre MyForm-Anwendung besteht. MyForm.vcproj Dies ist die Hauptprojektdatei f¨r VC++-Projekte, die mit dem Anwendungs- u Assistenten generiert werden. Sie enth¨lt Informationen uber die Version von Visual C++, in der die Datei a ¨ generiert wurde, sowie uber die Plattformen, Konfigurationen und ¨ Projektfeatures, die im Anwendungs-Assistenten ausgew¨hlt wurden. a MyForm.cpp Dies ist die Hauptquelldatei der Anwendung.
  • 95. 10.4 DAS .NET FORMULAR 95 Enth¨lt den Code zum Anzeigen des Formulars. a Form1.h Enh¨lt die Implementierung der Formularklasse und a der InitializeComponent()-Funktion. AssemblyInfo.cpp Enth¨lt benutzerdefinierte Attribute zum ¨ndern von Assemblymetadaten. a A ///////////////////////////////////////////////////////////////////////////// Weitere Standarddateien: StdAfx.h, StdAfx.cpp Diese Dateien werden verwendet, um eine vorkompilierte Headerdatei (PCH-Datei) mit dem Namen "MyForm.pch und eine vorkompilierte Typendatei mit dem Namen "StdAfx.obj" zu erstellen. ///////////////////////////////////////////////////////////////////////////// Um eine Funktion anzulegen (z.B. mit einem Doppelklick auf eine Schaltfl¨che) a erstellt der Anwendungs-Assistent einen Funktionsrumpf in der Form1.h vor. F¨ r unsere Formular-Funktionen legen wir besser eine neue Quell-Datei Form1.cpp u an (enspricht MyDialogDlg.cpp f¨ r den MFC Dialog). In der nachfolgenden Ta- u belle finden sie die Entsprechungen der Funktionen f¨ r MFC-Dialog und .NET- u Formular. Bedeutung MFC-Dialog CMyDialog:: .NET-Formular Form1:: DB lesen OnButtonReadDB button1 Click DS ausw¨hlen a OnSelchangeList listBox1 SelectedIndexChanged DB sortieren OnBnClickedButtonDBSort button2 Click ListBox f¨ llen u UpdateSTDVector listBox1 Fill Tabelle 10.1: Die gute Nachricht ist, unsere eigenen C++ Funktionen k¨nnen wir 1-zu-1 wei- o terverwenden. Andererseits m¨ ssen wir uns mit den neuen Formular-Elementen u und Daten-Typen vertraut machen, wir sehen auch erhebliche Unterschiede in der Nachrichten-Signal-Verarbeitung. Es ist einfacher geworden, es gibt z.B. kei- ne IDs mehr, die grafischen Elemente sind direkte Bestandtteile (member) der Formular-Klasse. 10.4.1 Funktionen Eine Funktion f¨ r Schaltfl¨che erstellen wir mit einem Doppelklick auf die ent- u a sprechende Formular-Resource. Damit generieren wir ein Ereignis button1→Click, das mit einer Funktion vern¨ pft ist. Eine weitere Besonderheit ist, dass das Er- u eignis dynamisch zur Laufzeit erzeugt wird.
  • 96. 96 KAPITEL 10 DIALOGE Form1.h: Verkn¨ pfung von Ereignis (Klick auf button1) und Funktion u .NET: this->button1->Click += gcnew System::EventHandler(this,&Form1::button1_Click); MFC: ON_BN_CLICKED(IDC_BUTTON1, OnButtonReadDB) Die Definition der Klick-Funktion button1 Click in der Quell-Datei ist im fol- genden dargestellt sowie der Vergleich mit der entsprechenden MFC-Funktion. Nat¨ rlich k¨nnen wir die .NET Funktionen auch umbenennen. Nat¨ rlich k¨nnen u o u o wir die .NET Funktionen auch umbenennen, z.B. button1 Click in ReadDB. ¨ Die Anderung muss an allen Stellen wo der alte Funktionsname button1 Click auftaucht erfolgen. Keine Angst, der Kompiler meldet sich sofort, wenn sie es irgendwo vergessen haben sollten ... Form1.cpp: Klick-Funktion .NET: Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) MFC: void CMyDialog::OnButtonReadDB() ¨ Wir sehen uns die Funktion sp¨ter in der Ubung genauer an. a 10.4.2 Daten Wie schon erw¨hnt, .NET benutzt komplett neue Daten-Typen (Kommentar). a Die Tabelle 10.2 am Ende des Abschnitts gibt einen kleinen Vergleich. Die Hier- archie der Namensr¨ume ist f¨ r .NET Formulare ist: System::Windows::Forms. a u Der Datenaustausch zwischen den Variablen und den Resourcen ist in .NET ein- facher geworden und erfolgt direkt ohn den Umweg uber IDs. Es gibt also keine ¨ DDX Datenaustausch-Funktionen mehr. Form1.h: .NET: private: System::Windows::Forms::TextBox^ textBox1; private: System::Windows::Forms::ListBox^ listBox1; MFC: CString m_strFirstName; CListBox m_STDVector; MFC: DDX_Text(pDX, IDC_EDIT1, m_strFirstName); DDX_Control(pDX, IDC_LIST1, m_STDVector); Nachfolgend sehen wir, wie Werte der Variablen an die grafischen Resourcen weitergegeben werden. Form1.cpp: .NET: textBox1->AppendText(name_first_trimmed); listBox1->Items->Add(Str);
  • 97. 10.4 DAS .NET FORMULAR 97 Bedeutung C++ MFC .NET Zeichenkette string CString String^ ListBox - CListBox ListBox Tabelle 10.2: Vergleich von Daten-Typen 10.4.3 ¨ Ubung: Hinzufugen von Funktionen ¨ ¨ Schritt 1: Uberlegen Was wollen wir tun ? Eine Funktion zum Anlegen eines neuen Datensatzes erstellen. Eine perfekte Vorbereitung w¨re es gewesen, diese Funktion bereits a geschrieben und in einem kleinen Konsolenprogramm getestet zu haben ... Schritt 2: Resourcen-Element anlegen Die Schaltfl¨che einfach auf das Formualfeld ziehen (Abb. 10.7). a Abbildung 10.7: Die Formular-Resource bearbeiten Um herauszubekommen, was passiert ist, suchen wir einfach mal nach button3 in unserem Projekt. Das Suchergebnis sehen wir in Abb. 10.8.
  • 98. 98 KAPITEL 10 DIALOGE . Abbildung 10.8: What have we created Die Treffer betreffen ausschließlich die Header-Datei Form1.h. Dort finden wir die Deklaration der Schaltfl¨che button3 als Daten-Typ Button^ sowie die Defi- a nition der dazugeh¨rigen grafischen Resource (Position, Gr¨ße etc.) in der Funk- o o tion InitializeComponent(). Form1.h Windows Form Designer generated code private: System::Windows::Forms::Button^ button3; // Daten-Typ void InitializeComponent(void) {... this->button3 = (gcnew System::Windows::Forms::Button()); ... // button3 this->button3->Location = System::Drawing::Point(160, 145); this->button3->Name = L"button3"; // andern in L"Add" ¨ this->button3->Size = System::Drawing::Size(75, 23); this->button3->TabIndex = 8; this->button3->Text = L"button3"; this->button3->UseVisualStyleBackColor = true; ...} Schritt 3: Funktion anlegen Wie schon erw¨hnt, mit einem Doppelklick auf das Resourcen-Element wird die a Funktion automatisch im Header-File angelegt. Form1.h private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) { } In der Parameterliste der Funktion sehen wir ein Objekt sender und Ereignisse EventArgs, welche die Nachrichtenliste (message map) in MFC ersetzen.
  • 99. 10.4 DAS .NET FORMULAR 99 Schritt 4: Funktion in CPP File Eigentlich k¨nnten wir die Funktion button3 Click auch im Header-File belas- o sen. Ich empfehle aber, die Funktion in das CPP-File zu kopieren und nur ihre Deklaration im H-File zu hinterlassen. Form1.h/cpp private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e); Void Form1::button3_Click(System::Object^ sender, System::EventArgs^ e) { } Schritt 5: Funktion schreiben Unsere Funktion ’hinter dem Kn¨pfchen’ ist erfreulich kurz und enth¨lt folgende o a Schritte: (1) Erzeugen einer neuen Instanz unser Klasse CStudent, (2) Einf¨ gen u dieser Instanz in den Datenbank (DB) Vektor, (3) Aktualisieren unserer ListBox im Formular. Form1.h/cpp Void Form1::button3_Click(System::Object^ sender, System::EventArgs^ e) { CStudent* m_std = new CStudent(); // neue CStudent Instanz std_vector.push_back(m_std); // in Vektor eintragen listBox1_Fill(); // ListBox aktualisieren } Abbildung 10.9: Neuen Datensatz einf¨ gen u
  • 100. 100 KAPITEL 10 DIALOGE Schritt 6: Funktion testen Der letzte Schritt ist das Testen der neuen Funktion. Dabei m¨ ssen wir alle u Kombinationen von Kn¨pfchen ausprobieren. Der Unterschied von interaktiven o zu Konsolen-Programmen ist, das jede Funktion beliebig oft ausgef¨ hrt wer- u den k¨nnen muss. Daher m¨ ssen vor Ausf¨ hren der Funktion i.d.R. alle Daten o u u gel¨scht und wieder neu erzeugt werden. o Abbildung 10.10: DB sortieren Die soll zur MS-Windows-Programmierung mit MFC und .NET gen¨ gen, um u ihnen den ’flavour’ vermittelt zu haben.
  • 101. 10.5 HOMEWORKS 101 10.5 HomeWorks MFC (obsolet f¨ r VC++ Express) u 1. Implementieren sie die Funktion zum Einf¨ gen eines neuen Datensatzes – u CMyDialogDlg::OnButtonAdd(). 2. Implementieren sie die Funktion zum L¨schen eines Datensatzes – o CMyDialogDlg::OnButtonRemove(). 3. Implementieren sie die Funktion zum Editieren eines Datensatzes – CMyDialogDlg::OnButtonEdit(). 4. Implementieren sie die Funktion zum Schreiben der Datenbank – CMyDialogDlg::OnButtonWriteDB(). 5. Bauen sie einen Z¨hler f¨ r die Anzahl der existierenden Datens¨tze ein. a u a Hinweis: Benutzen sie dazu ein Editier-Feld. .NET 1. Implementieren sie die Funktion zum L¨schen eines Datensatzes – o button4 Click. 2. Implementieren sie die Funktion zum Editieren eines Datensatzes – button5 Click. 3. Implementieren sie die Funktion zum Schreiben der Datenbank – button5 Click. 4. Bauen sie einen Z¨hler f¨ r die Anzahl der existierenden Datens¨tze ein. a u a Hinweis: Benutzen sie dazu ein Editier-Feld.
  • 102. 102 KAPITEL 10 DIALOGE 10.6 Testfragen MFC 1. Welche Typen von grafischen Windows-Applikationen kennen sie ? 2. Was ist eine Dialog-Resource ? 3. Welche Dialog-Elemente haben wir in unserer Windows-Applikation be- nutzt (Abb. 10.3) ? 4. Was sind IDs ? 5. Was ist eine MESSAGE MAP ? 6. Wie wird die Verbindung zwischen Funktionen und grafischen Dialog- Elementen hergestellt ? 7. Wie wird die Verbindung zwischen Daten und grafischen Dialog-Elementen hergestellt ? 8. Was bedeutet die Definition: class CMyDialog : public CDialog ? 9. Wie wird ein Dialog aufgerufen (Funktion der Klasse CDialog)? 10. Was bewirkt die Dialog-Funktion UpdateData() ? 11. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten- Klasse ? 12. Wie kann ich Files unter Windows ¨ffnen (welche Klasse) ? o 13. Was ist ein BMP ? .NET 1. Was ist eine Formular-Resource ? 2. Welche Formular-Elemente haben wir in unserer .NET-Applikation be- nutzt (Abb. 10.10) ? 3. Wie wird die Verbindung zwischen Funktionen und grafischen Formular- Elementen hergestellt ? 4. Wie wird die Verbindung zwischen Daten und grafischen Formular-Elementen hergestellt ? 5. Was bedeutet die Definition: private: System::Windows::Forms::Button MyButton ? 6. Was bedeutet die Definition: private: System::Void button3 Click() ?
  • 103. 10.6 TESTFRAGEN 103 7. Wie wird ein Formular aufgerufen (Funktion der Klasse Form1)? 8. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten- Klasse ? 9. Wie kann ich Files mit .NET ¨ffnen (welche Klasse) ? o
  • 104. Kapitel 11 Qt Die Panne mit dem Dialog war echt nicht geplant, d.h. dass MFC Dialoge mit der freien MSVC++ Express Version nicht mehr verf¨ gbar sind. Dies zeigt uns u aber, auch beim Programmieren niemals nur auf ein Pferd setzen. Wichtig ist, unser eigener Code muss C++ Standard sein, den k¨nnen wir dann problemlos o in verschiedene GUI Frameworks, wie MSVC++, Qt etc. einbauen. ¨ Warum jetzt noch Qt ? Wir werden in den Ubungen sehen, dass Qt sehr dicht an C++ Standards dran ist und Qt ist ’a cross-platform GUI’. Qt l¨uft auf Win- a dows, Linux, Mac ... In der Anlage 12.8 finden sie eine Anleitung zur Installation von Qt. 11.1 Hello Qt Wie es sich f¨ r ein ordentliches Programmier-Framework geh¨rt, ist die erste u o ¨ Ubung ”Hello World” auf graphisch. ¨ Ubung: 11.1 #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc,argv); QLabel *label = new QLabel("Hello Qt!"); label->show(); return app.exec(); } Sehr erfreulich ist die N¨he von Qt zum Standard C++, es gibt eine klassische a main() Funktion. Die Komposition von ”Hello Qt” ist sehr einfach: 104
  • 105. 11.2 EXECUTABLE 105 • Es wird eine Qt Application angelegt (¨hnlich wie bei Windows, aber doch a irgendwie einfacher), • Es wird ein Label angelegt, das mit der Methode →show() angezeigt wird. Qt bietet auch die M¨glichkeit, einfach HTML code zu integrieren. Ersetzen sie o die QLabel Zeile wie folgt. QLabel *label = new QLabel("<h2><i>Hello<!i>""<font color=red>Qt!</font></h2>"); Abbildung 11.1: Hallo Qt 11.2 Executable Um ein ausf¨ hrbares Qt Programm zu erzeugen ben¨tigen wir 3+1 Schritte: u o • Gehen sie in ihre Start - Programme Men¨ (Windows) und starten sie die u den Qt command prompt (Fig. 11.2). Abbildung 11.2: Qt Kommando Zeile • Mit qmake -project erzeugen sie ein Qt Projekt. • Mit qmake legen sie ein makefile an. • Mit mingw32-make (kein Leerzeichen) kompilieren sie das Projekt und generieren ein ausf¨ hrbares Programm. u • Mit E10 1 HelloQt.exe starten sie das Programm.
  • 106. 106 KAPITEL 11 QT . Abbildung 11.3: Die Schritte in Bildern ... 11.3 Quit a ¨ Die n¨chste Ubung zeigt uns, wie einfach mit Schaltfl¨chen (Push Button) ge- a arbeitet werden kann. #include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc,argv); QPushButton *button = new QPushButton("Quit"); QObject::connect(button, SIGNAL(clicked()),&app, SLOT(quit())); button->show(); return app.exec(); } Im Unterschied zu ”Hello Qt” ist eine Kommunikation mit dem Anwender (dr¨ cken der Schaltfl¨che) notwendig. Die Signalverarbeitung erfolgt uber die u a ¨ Object-Methode connect. QObject::connect(button, SIGNAL(clicked()),&app, SLOT(quit()));
  • 107. 11.4 DIALOG 107 Dabei wird die Nachricht SIGNAL(clicked()) mit der Schaltfl¨che Quit mit a einem sogenannten SLOT(quit())) verbunden. Abbildung 11.4: Hallo Qt 11.4 Dialog Zum Abschluss unsere Dialog-Anwendung. Dabei wird in der main Funktion eine Instanz der Klasse QDialog erzeugt. #include <QtGui/QApplication> #include "dialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); } Der Header des Dialogs enth¨lt im Wesentlichen die Resourcen-Elemente, z.B. a die Schaltfl¨che pushButtonReadDB zum Lesen der Datenbank sowie die dazu- a geh¨rigen Funktionen on pushButtonReadDB clicked(). o class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; QListWidget *listWidget; QPushButton *pushButtonReadDB; QPushButton *pushButtonAdd; QPushButton *pushButtonDelete;
  • 108. 108 KAPITEL 11 QT QLineEdit *lineEditNameFirst; QLineEdit *lineEditNameLast; private slots: void on_pushButtonReadDB_clicked(); void on_pushButtonAdd_clicked(); void on_pushButtonDelete_clicked(); void on_listWidget_clicked(); }; Die Implementierung des Dialogs besteht aus drei Teilen: 1. Konstruktion der grafischen Resourcen-Elemente: pushButton (Schaltfl¨chen), a listWidget (Liste), lineEdit (Editierfelder), 2. Signalverarbeitung: Wenn pushButtonReadDB gedr¨ ckt wurde, f¨ hre die u u Funktion on pushButtonReadDB clicked aus, 3. Layout: Es werden horizontale und vertikale Boxen angelegt. Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); // 1.1 - pushButton pushButtonReadDB = new QPushButton(tr("&Read DB")); pushButtonAdd = new QPushButton(tr("&Add DS")); pushButtonDelete = new QPushButton(tr("&Delete DS")); // 1.2 - listWidget QString name = "Tom Hanks"; QStringList names; names << name << "Alice Wunderland" << "Bob Dylan" << "Carol Crow" << "Donald Dug" << "Emma Thomson"; listWidget = new QListWidget(); for (int row = 0; row < 5; ++row) { listWidget->addItem(names[row]); } //1.3 - lineEdit lineEditNameFirst = new QLineEdit(); lineEditNameFirst->insert("Tom"); lineEditNameLast = new QLineEdit(); lineEditNameLast->insert("Hanks"); // 2 - connect connect(pushButtonReadDB,SIGNAL(clicked()),this,SLOT(on_pushButtonReadDB_clicked())); connect(pushButtonAdd,SIGNAL(clicked()),this,SLOT(on_pushButtonAdd_clicked())); connect(pushButtonDelete,SIGNAL(clicked()),this,SLOT(on_pushButtonDelete_clicked())); connect(listWidget,SIGNAL(itemSelectionChanged()),this,SLOT(on_listWidget_clicked())); //3 - Layout
  • 109. 11.4 DIALOG 109 QHBoxLayout *leftTopLayout = new QHBoxLayout; leftTopLayout->addWidget(lineEditNameFirst); leftTopLayout->addWidget(lineEditNameLast); QVBoxLayout *leftLayout = new QVBoxLayout; leftLayout->addLayout(leftTopLayout); leftLayout->addWidget(listWidget); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addWidget(pushButton); rightLayout->addWidget(pushButtonAdd); rightLayout->addWidget(pushButtonDelete); rightLayout->addStretch(); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(leftLayout); mainLayout->addLayout(rightLayout); setLayout(mainLayout); } Das Ergebnis der Dialog-Implementierung sehen wir in Abb. 11.5. Abbildung 11.5: Qt Dialog Um zu pr¨ fen, ob die Signalverarbeitung hinter den Kn¨pfchen funktioniert, u o rufen wir eine MessageBox auf. void Dialog::on_pushButtonAdd_clicked() { QMessageBox msgBox; msgBox.setText("pushButtonAdd clicked"); msgBox.exec(); }
  • 110. 110 KAPITEL 11 QT Dies soll als kurze Einf¨ hrung in Qt erstmal gen¨ gen, es geht weiter im n¨chsten u u a Semester.
  • 111. Part III Anlagen / Software
  • 113. 12.1 CYGWIN INSTALLATION 113 12.1 cygwin Installation In dieser Anlage finden sie eine Anleitung zur Installation von cygwin - dies ist eine Linux-Umgebung f¨ r Windows. In dieser Umgebung k¨nnen sie die GNU u o C und C++ Compiler verwenden. Abbildung 12.1: Schritt 1: Gehen sie auf cygwin Web Seite - www.cygwin.com. Klicken sie auf das cygwin Symbol (Install or update now!). Abbildung 12.2: Schritt 2: Laden sie die setup.exe Datei auf ihren Rechner herunter und f¨ hren sie die setup.exe aus. u
  • 114. 114 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.3: Schritt 3: Das cygwin setup Programm wird gestartet. Hier se- hen sie auch die aktuelle Versionsnummer (2.573.2.3). Best¨tigen sie mit Weiter. a Abbildung 12.4: Schritt 4: W¨hlen sie das Verzeichnis zur Installation von a cygwin aus, z.B. das Verzeichnis, in dem die Anwendungsprogramme sind (C:/Programme). Behalten sie die Voreinstellungen. Best¨tigen sie mit Weiter. a
  • 115. 12.1 CYGWIN INSTALLATION 115 . Abbildung 12.5: Schritt 5: cygwin ben¨tigt ein tempor¨res Verzeichnis f¨ r die o a u Installation, das sp¨ter gel¨scht werden kann. Behalten sie die Voreinstellungen. a o Best¨tigen sie mit Weiter. a Abbildung 12.6: Schritt 6: Benutzen sie die voreingestellte direkte Internetver- bindung. Best¨tigen sie mit Weiter. a
  • 116. 116 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.7: Schritt 7: W¨hlen sie die download site, am besten die Dresdner: a http://ftp.inf.tu-dresden.de; Best¨tigen sie mit Weiter. a Liste der 6 zu installierenden Pakete aus der Kategorie ’Devel’: • binutils: The GNU assembler linker and binary utilities (release 20080624- 2) [6MB] • gcc-core: C compiler (release 3.4.4.999) [3.6MB] • gcc-g++: C++ compiler (release 3.4.4.999) [7.8MB] • gcc-mingw-core: support headers and libraries for GCC (release 20050522- 1) [69kB] • gcc-mingw-g++: support headers and libraries for GCC C++ (release 20050522-1) [1.9MB] • mingw-runtime library (release 3.15.2-1) [372kB]
  • 117. 12.1 CYGWIN INSTALLATION 117 . Abbildung 12.8: Schritt 8: Nun erscheint die Liste der packages, die installiert ¨ werden k¨nnen. Offnen sie dem Baum Devel (klicken Sie auf das Plus-Symbol). o W¨hlen sie die oben aufgef¨ hrten Pakete aus, welche f¨ r die Installation von C a u u und C++ ben¨tigt werden. Best¨tigen sie mit Weiter. o a Die nachfolgenden Abbildungen zeigen ihnen, welche Markierungen aktiviert sein m¨ ssen, um den C (GCC) und den C++ (G++) zu installieren. Eigentlich u reicht es, die binutils, gcc-core und gcc-g++ auszuw¨hlen, die restlichen a Pakete (mingw) m¨ ssten automatisch aktiviert werden. Egal, uberpr¨ fen sie, ob u ¨ u alles wie in den nachfolgenden Abbildungen markiert ist. Viel Erfolg!
  • 118. 118 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.9: Schritt 8a: (aktive) Auswahl der binutils Abbildung 12.10: Schritt 8b: (aktive) Auswahl der C und C++ Compiler Die nachfolgenden Pakete sollte automatisch markiert werden, bitte uberpr¨ fen ¨ u sie dies sicherheitshalber.
  • 119. 12.1 CYGWIN INSTALLATION 119 . Abbildung 12.11: Schritt 8c: (automatische) Auswahl von Hilfspaketen Abbildung 12.12: Schritt 8d: (automatische) Auswahl von Hilfspaketen Abbildung 12.13: Schritt 9: Behalten sie die Voreinstellungen, um eine cygwin Verkn¨ pfung auf ihrem desktop zu erstellen. Schließen sie die Installation ab. u
  • 120. 120 KAPITEL 12 SOFTWARE-INSTALLATION Im Ergebnis der Installation erhalten sie eine desktop Verkn¨ pfung mit cygwin, u das nun mit einem Doppelklick gestartet werden kann. Abbildung 12.14: Schritt 8d: cygwin desktop Verkn¨pfung u Starten sie cygwin mit einem Doppelclick auf die desktop Verkn¨pfung. u Abbildung 12.15: Start von cygwin Mit einem Rechtsklick auf den oberen Balken gelangen sie in das Eigenschaften- Menu und k¨nnen Einstellungen (z.B. Farben) nach ihrem Geschmack andern. o ¨
  • 121. 12.1 CYGWIN INSTALLATION 121 . Abbildung 12.16: Das Eigenschaften-Menu von cygwin Testen sie, ob die Compiler einsetzbar sind, indem sie diese einfach aufrufen: • gcc - Aufruf des C Compilers • g++ - Aufruf des C++ Compilers Da sie die Compiler ohne etwas zu tun aufrufen, erhalten sie die Meldung: keine Eigabedateien. Abbildung 12.17: Aufruf der Compiler Nun kann es also endlich losgehen mit der ersten Ubung ⇒ Abschnitt 1.4. ¨
  • 122. 122 KAPITEL 12 SOFTWARE-INSTALLATION 12.2 LINUX 12.2.1 ¨ Ubersicht einiger grundlegenden Linux-Befehle Befehl / command Bedeutung Hilfe man Klassische Hilfe (verlassen mit Q) info Online Hilfe von GNU (verlassen mit Q) apropos Schl¨ sselw¨rtersuche bei “man“-Seiten u o whatis Kurzbeschreibung zu einem Kommando oder Schl¨ sselwort u Dateien ls Dateien auflisten ls -attr Dateiattribute auflisten file Dateityp ermitteln cp Quelle Ziel Kopiert Quelle nach Ziel mv Datei1 Datei2 Datei1 umbenennen in Datei2 mv Datei V1 Verschiebt Datei in das Verzeichnis V1 rm Dateien Dateien l¨schen o rmdir Verzeichnis Verzeichnis l¨schen o find Suche nach Dateien find/ Suche startet im Root-Verzeichnis / im ganzen System Verzeichnisse pwd gibt aktuelles Arbeitsverzeichnis an ./ aktuelles Verzeichnis cd Wechsel des aktuellen Verzeichnisses mkdir ein Verzeichnis anlegen rm Verzeichnis ein Verzeichnis l¨schen o rmdir ein leeres Verzeichnis l¨schen o ls Verzeichnisinhalt auflisten Systembefehle shutdown -h Herunterfahren des Systems shutdown Uhrzeit Herunterfahren des Systems bei Uhrzeit (z.B.: 14.00) shutdown -t Sekunden Herunterfahren des Systems nach Anzahl der Sekunden reboot oder shutdown -r Neustart des Systems uname Systeminformationen ausgeben ¨ Diese Ubersicht basiert auf ’Linux auf einem Blatt’ von Christian Helmbold (www.helmbold.de) (siehe n¨chste Seite) a
  • 123. 12.2 LINUX 123 weitere Informationen und Erkl¨rungen a ¨ deutsche Ubersichten: ¨ - Pdf-Ubersicht ’Linux auf einem Blatt’ (auch zum Download) www.helmbold.de/linux - Linux-Befehle f¨ r Einsteiger u http://www.linux-fuer-alle.de/doc show.php?docid=33 ¨ - Ubersicht f¨ r wichtige Linux-Befehle und Programme u http://www.tnt-computer.de/yanip/lbefehle.html ¨ englische Ubersichten ¨ - umfangreiche Ubersicht mit Parametern und Beispielen http://www.computerhope.com/unix.htm#04 - Vergleich zwischen MS-DOS- und Linux-Befehlen http://www.yolinux.com/TUTORIALS/unix for dos users.html Wir arbeiten uns jetzt mal mit der online-Hilfe ’man’ (steht f¨ r Manual) weiter u vor. Abbildung 12.18: Benutzen der online Hilfe Mit dem Befehl man ls k¨nnen wir uns die Optionen von ls (Dateien auflisten) o anzeigen lassen.
  • 124. 124 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.19: Optionen von ls (Dateien auflisten)
  • 125. 12.2 LINUX 125 12.2.2 Profile Wir n¨hern uns der L¨sung, einfach in das Verzeichnis zu gelangen, in dem sich a o ¨ ¨ unsere Ubungen befinden. Ahnlich wie in DOS die Programme autoexec.bat und config.sys beim Start des Betriebsystems automatisch ausgef¨ hrt werden, u ist es bei LINUX ein so genanntes Profile: .bash profile. In diese Datei k¨nnen o eigene Befehle eingetragen werden. Eigentlich ist es ganz einfach .... cd C:/User/TEACHING/C++/EXERCISES Durch diese Instruktion in der .bash profile wechseln wir direkt in das Ver- ¨ zeichnis, in dem sich unsere Ubungen befinden. Nachdem wir verschiedene Editoren ausprobiert haben (und erhebliche Unter- schiede in der Behandlung von Zeilenenden (CR) gesehen haben), ließ sich zu ¨ allem Ubel unsere m¨ hsam editierte .bash profile mit dem Windows-Explorer u nicht speichern (es liegt an dem Punkt am Anfang des Datei-Namens). Ich kann ihre Entt¨uschung gut verstehen, nicht umsonst gibt es Windows und Linux- a Anh¨nger. Dennoch m¨ ssen wir eine L¨sung finden oder ? a u o 12.2.2.1 L¨sung 1: unix2dos o Nach unserem Schiffbruch mit dem Speichern einer ’.bash profile’ unter Win- dows (’denkt’ vor dem Punkt kommt der Datei-Name und nach dem Punkt die File-Extension, also nix vor dem Punkt heißt f¨ r Windows, kein Datei-Name ... u so ist das, wenn Programme zu viel denken). Die zweite L¨sung ist eine Dateikonvertierung. Linux bietet zwei Programme an: o dos2unix und unix2dos, mit denen man Dateien plattformgerecht konvertieren kann (Fig. 12.20) Abbildung 12.20: Wandeln zwischen Linux und Dos-Dateien
  • 126. 126 KAPITEL 12 SOFTWARE-INSTALLATION 12.2.2.2 L¨sung 2: Cygwin (the Linux point of view) o Wir brauchen einen ’einfachen’ Editor f¨ r cygwin, d.h. wir m¨ ssen nachinstal- u u lieren (siehe Abschn. ) Abbildung 12.21: Nachinstallieren des vi Editors Nach der vi Installation m¨ ssen wir in das Verzeichnis (home directory) gelan- u gen, wo sich die .bash profile Datei befindet. Abbildung 12.22: home directory und dessen Inhalt
  • 127. 12.2 LINUX 127 Wir ¨ffnen die .bash profile Datei mit dem vi Editor wie folgt: o Abbildung 12.23: Starten des vi Editors Jetzt k¨nnen wir mal einen Linux-Editor live erleben (danach werden sie Win- o ¨ dows noch mehr ’lieben’ ...). Nach dem Offnen der Datei gehen sie mit dem Kursor dorthin, wo sie Text einf¨ gen m¨chten. Dann dr¨ cken sie die ’i’ Taste, u o u der insert Modus wird gestartet. Nun k¨nnen sie den Befehl zum Wechseln in ihr o ¨ ¨ Ubungsverzeichnis eingeben cd ... Um die Anderungen zu speichern, dr¨ cken sie u ’Esc’ ’:’ ’w’. vi wechselt nun in den File-Modus ’w’ steht f¨ r write ... so einfach u ist das. Abbildung 12.24: Editieren und speichern
  • 128. 128 KAPITEL 12 SOFTWARE-INSTALLATION Befehl Wirkung i Wechseln in den Insert/Einf¨ ge-Modus u a Wechseln in den Append/Anh¨ngen-Modus a Esc: Wechseln in den Kommando-Modus w Write: Datei speichern (im Kommando-Modus) q ¨ Quit: Datei ohne Anderung verlassen (im Kommando-Modus) q! ¨ Quit: Datei ohne Anderung verlassen (im Kommando-Modus) 12.2.3 Make Mit den Make utilities k¨nnen ganze Projekte kompiliert werden, die aus vielen o Quelltext-Dateien bestehen. Nachfolgend sehen sie die Instruktionen des ma- kefile f¨ r die Kompilierung unseres Projekts. Dabei werden die Quell-Dateien u main.cpp und student.cpp kompiliert, gelinkt und die ausf¨ hrbare Datei a.exe u erzeugt. # OPTFLAG = -O3 C++ = g++ $(OPTFLAG) -Wall CFile = main.cpp student.cpp OFile = main.o student.o .SUFFIXES: .o .cpp .h .cpp.o: $(C++) -c -o $*.o $< main: $(OFile) $(C++) -o main $(OFile) clean: rm -f *.o
  • 129. ¨ 12.3 SCHUSSELWORTE IN C++ 129 12.3 Schusselworte in C++ ¨ ¨ Die nachfolgende Tabelle gibt ihnen eine Uberblick der C++ Schl¨ sselworte. u Wir werden die Tabelle sukzessive f¨ llen aber nicht alle Keywords benutzen. u Keyword Bedeutung Benutzung im Kapitel bool Datentyp 2 char Datentyp 2 double Datentyp 2 float Datentyp 2 int Datentyp 2 long Datentyp 2 short Datentyp 2 void Datentyp 2 wchar t Datentyp 2 Tabelle 12.1: Schl¨ sselworte u
  • 130. 130 KAPITEL 12 SOFTWARE-INSTALLATION 12.4 MS VC++ Projekt #1 - Eine Konsolenan- wendung In dieser Anlage finden sie eine Anleitung zur Erstellung eines MS VC++ Pro- jekts. Abbildung 12.25: Schritt 1: Starten sie MS Visual Studio (MSVS)
  • 131. 12.4 MS VC++ PROJEKT #1 - EINE KONSOLENANWENDUNG 131 . Abbildung 12.26: Schritt 2: Gehen sie zu File - New und w¨hlen sie ’Project a from existing code’ Abbildung 12.27: Schritt 3: W¨hlen sie ein ’Visual C++’ Projekt. Sie sehen, a dass mit MSVS auch andere Projekte (z.B. Java) erzeugen k¨nnen o
  • 132. 132 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.28: Schritt 4: Richten sie am besten vorher ein neues Unterver- zeichnis ein, in dem die Projektdateien gespeichert werden sollen ... es werden einige Dateien sein. Kopieren sie das/die Quell-Files (hier copy.cpp) in dieses Verzeichnis. W¨hlen sie mit ’Browse’ (nur) das Verzeichnis aus und vergeben a sie einen Projektnamen (hier ’msvcp1’). Gehen sie weiter ’next’ Abbildung 12.29: Schritt 5: W¨hlen sie als Projekt-Typ ’Console application a project aus’. (Sp¨ter werden wir auch Windows-Applikationen erstellen, nur a Geduld). Schließen sie ab ’finish’
  • 133. 12.4 MS VC++ PROJEKT #1 - EINE KONSOLENANWENDUNG 133 . Abbildung 12.30: Nun m¨ ssten sie folgendes Bild sehen. Der ’solution explorer’ u auf der linken Seite zeigt ihnen ihr Projekt ’msvcp1’ an und hat automatisch das Quell-File copy.cpp in das Projekt eingetragen. Abbildung 12.31: Wenn wir in unser Projekt-Verzeichnis schauen, sehen wir, dass MSVS einige Dateien f¨ r uns angelegt hat. Das eigentlich Projekt-File ist: u msvcp1.vcproj. Mit einem Doppelklick darauf wird das Projekt geladen. Das war’s erstmal.
  • 134. 134 KAPITEL 12 SOFTWARE-INSTALLATION 12.5 MFC-Dialog Dialoge geh¨ren zu den einfachsten Anwendungen von grafischen Benutzer- o schnittstellen (GUI graphical user interface). Ihre Aufgabe ist, es eine grafisch- gest¨ tzte Interaktion (Dialog) mit einem Programm zu erm¨glichen. In der u o Anlage finden sie die entsprechenden Schritte f¨ r die Dialog-Anwendung mit u VC++2005 Abbildung 12.32: Starten von VC++2005 Nach dem Starten von VC++ (Fig. 12.32) m¨ ssen wir ein neues Projekt anlegen u (Fig. 12.33).
  • 135. 12.5 MFC-DIALOG 135 . Abbildung 12.33: Klick 1: Neues Projekt anlegen W¨hlen sie ’MFC Application’ aus. W¨hlen Sie im unteren Teil des Dialogs (Fig. a a 12.34) das Verzeichnis f¨ r ihr Dialog-Projekt und geben sie ihm einen Namen. u Der ’Projektgruppen-Name’ wird automatisch vergeben. Abbildung 12.34: Klick 2: MFC Applikation ausw¨hlen a
  • 136. 136 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.35: Klick 3: Einfach weiter (next) W¨hlen sie ’Dialog based’ und ihre Sprache aus (Abb. 12.36) und schließen sie a ab (Finish). Abbildung 12.36: Klick 4: Auswahl des Applikations-Typs (Dialog, SDI, MDI)
  • 137. 12.5 MFC-DIALOG 137 In dem Moment, wenn sie ’Finish’ dr¨ cken (Klick 5), wird der gesamte Quell- u Code f¨ r ihre Dialog-Anwendung erzeugt. Mit ’Ctrl-F5’ oder Debug → ’Start u without debugging’ ubersetzen sie den Quell-Code und starten ihre erste Dialog- ¨ Applikation (Fig. 12.37). Abbildung 12.37: Die leere Dialog-Anwendung
  • 138. 138 KAPITEL 12 SOFTWARE-INSTALLATION 12.6 .NET Formular Mit dem MSDS (Micro-Soft Developer Studio) 2005 braucht man genau 5 Mausklicks, um eine Dialog-Anwendung zu erstellen (siehe Anlage 12.5), mit der 2008er Version sind es nur noch 3 f¨ r ein sogenanntes Formular (die Weiter- u entwicklung von Dialogen). Wir schauen uns jetzt die Erzeugung der Formular- Applikation mit VC++2008 an, machen aber dann in Abschn. 10.1 mit der Dialog-Anwendung weiter. Abbildung 12.38: Starten von VC++2008
  • 139. 12.6 .NET FORMULAR 139 Nach dem Starten von VC++ (Fig. 12.38) m¨ ssen wir ein neues Projekt anlegen u (Fig. 12.39). Abbildung 12.39: Klick 1: Neues Projekt anlegen Abbildung 12.40: Klick 2: Windows Form-Anwendung W¨hlen sie ’CLR’ (Erkl¨rung folgt) → ’Windows Form-Anwendung’ aus. ’Win- a a
  • 140. 140 KAPITEL 12 SOFTWARE-INSTALLATION dows Forms’ sind die neue Form von ’Windows Dialogen’. W¨hlen Sie im unteren a Teil des Dialogs (Fig. 12.40) das Verzeichnis f¨ r ihr Dialog-Projekt und geben u sie ihm einen Namen. Der ’Projektgruppen-Name’ wird automatisch vergeben. In dem Moment, wenn sie ’OK’ dr¨ cken (Klick 3), wird der gesamte Quell-Code u f¨ r ihre Dialog-Anwendung erzeugt. Mit ’Ctrl-F5’ oder Debug → ’Start without u debugging’ ubersetzen sie den Quell-Code (Fig. 12.41) und starten ihre erste ¨ Dialog-Applikation (Fig. 12.42). ¨ Abbildung 12.41: ’Ctrl-F5’: Ubersetzen und starten des Dialogs Abbildung 12.42: Eine ’leere’ Windows Formular-Anwendung
  • 141. 12.7 UBUNTU & WINE 141 12.7 UBUNTU & Wine Man kann Windows-Applikationen unter UBUNTU starten. Dazu muss das Pro- gramm ’Wine’ installiert werden. Hier kommt eine kurze Installationsanleitung. F¨ r den Download und die Installation von Wine Microsoft Windows Com- u patibility Layer ben¨tigen sie nat¨ rlich eine Internetverbindung. Gehen sie zu o u Anwendungen > Hinzuf¨ gen/Entfernen > Suche: Wine. u Abbildung 12.43: Anwendung Wine hinzuf¨ gen u Nun werden die Paketdateien f¨ r Wine heruntergeladen. u Abbildung 12.44: Paketdateien f¨ r Wine werden heruntergeladen u Danach werden die Software-Pakete f¨ r Wine installiert. u
  • 142. 142 KAPITEL 12 SOFTWARE-INSTALLATION . Abbildung 12.45: Installation der Software-Pakete Zur Ausf¨ hrung der Windows exe Datei gehen sie wie folgt vor: Rechtsklick auf u Datei > Mit >>Wine Windows-Programmstarter<< ¨ffnen, die Anwendung o wird nun wie unter Windows ausgef¨hrt. u Installierte Programme werden in einem Windows nachempfundenen Verzeich- nissystem installiert z.B. home/user/.wine/dosdevices/c: sowie home/user/.wine/dosdevices/c:/Programme. Installierte Programme/Anwendun- gen k¨nnen unter Anwendungen > Wine > Programme bzw. Durchsuche C: o gefunden werden.
  • 143. 12.8 QT INSTALLATION 143 12.8 Qt Installation Qt installation
  • 144. 144 KAPITEL 12 SOFTWARE-INSTALLATION Zur Qt Installation gehen sie auf folgende Web-Seite und folgen den Schritten gem¨ß den Abbildungen: http://www.qtsoftware.com/products/. W¨hlen die a a freie LGPL Lizenz. Dabei wird die Installationsdatei f¨ r das entsprechende Betriebssystem herun- u tergeladen (Abb. 12.46). Abbildung 12.46: Qt Installationsdatei f¨ r Windows u Nach der Installation haben sie den Qt Creator zur Verf¨ gung (Abb. 12.47). u Abbildung 12.47: Qt Creator
  • 145. Kapitel 13 Students Forum Vielen Dank f¨ r Ihre Fragen zur ersten Vorlesung! u 13.1 Vorlesung 1: 17.04.2009 JB Der C compiler funktioniert, der C++ aber nicht: Wahrscheinlich haben sie nur den C Compiler (GCC) installiert. Die k¨nnen jederzeit cygwin o Komponenten nachinstallieren , siehe Abschn. 12.2.2.2. ¨ DB Ich habe den MS VC++ installiert und kann die Ubungen nachvollziehen. Brauche ich den GNU Compiler von cygwin wirklich noch ?: Eigentlich nicht, mit MS VC++ haben sie einen kompletten Compiler mit allem drum und dran, dennoch kann ein Ausflug in die Konsolenwelt ja nicht schaden ... und sie k¨nnen sp¨ter in ihre Bewerbungen schreiben, dass sie o a auch unter Linux Programme entwickelt haben. MF Die aktuelle cygwin Installation sieht anders aus als im Skript beschrieben: [OK] Im Anhang (Abschn. 12.2.2.2) finden sie eine bessere Beschreibung der cygwin Installation. C++ und Mac: erstmal eine Adresse http://developer.apple.com/TOOLS/xcode/ 145
  • 146. Kapitel 14 Questions 14.1 Testfragen - Kapitel 1 - Einfuhrung ¨ 1. Was bedeutet das ++ im Namen der Programmiersprache C++ ? 2. Ist C++ eine standardisierte Programmiersprache ? 3. Was ist der Unterschied zwischen C und C++ ? 4. Was sind sogenannte Programmier-Paradigmen ? 5. Welche verschiedenen Programmier-Paradigmen kennen sie und worin un- terscheiden sie sich ? 6. Welches Paradigma verfolgen wir in der Vorlesung ? 7. Was ist objekt-orientierte Programmierung ? 8. Was ist ein Kompiler ? 9. Erkl¨ren sie die einzelnen Schritte bei einer Kompilierung (s. Abb. 1.4). a ¨ 10. Welchen Kompiler benutzen sie f¨ r die C++ Ubungen ? u 11. Welche Funktion ben¨tigt jedes C oder C++ Programm ? o 12. Was ist der Typ einer Funktion ? 13. Was ist eine Parameterliste einer Funktion ? 14. Was ist der R¨ ckgabewert einer Funktion ? u 146
  • 147. 14.2 TESTFRAGEN - KAPITEL 2 - DATENTYPEN 147 14.2 Testfragen - Kapitel 2 - Datentypen 1. Was ist der genaueste Datentyp in C++ ? 2. Wie groß ist der Speicherbedarf von einem string Datentyp ? 3. Mit welcher Anweisung k¨nnen wir den Speicherbedarf von elementaren o Datentypen ermitteln ? 4. Was sind Escape-Sequenzen ? 5. Was ist der Unterschied zwischen den Escape-Sequenzen n und r ? 6. Was ist die C++ Entsprechung der Klasse cout f¨ r einen Zeilenumbruch u ? 14.3 Testfragen - Kapitel 3 - Ein- und Ausgabe I 1. Sind sie mit der Tab. 2.2 einverstanden ? 2. Welche Ein- und Ausgabeger¨te kennen sie ? a 3. Welche Klasse ben¨tigen wir f¨ r die Standard-Ein- und Ausgabe ? o u 4. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ? u 5. Mit welcher Klasse k¨nnen wir sowohl Eingabe- als auch Ausgabestr¨me o o benutzen ? 6. Welche Include-Datei ist notwendig, um mit I/O-Str¨men arbeiten zu o k¨nnen ? o 7. Wozu dient der Zusatz using namespace std; nach dem Include von Standard-Klassen, wie I/O Streams ? 8. Was bewirken die Stream-Operatoren << und >> ? 9. Was bewirken die Flags oct, dec, hex f¨ r die formatierte Ausgabe von u Ganzzahlen ? (ToDo) 10. Wie kann ich die Genauigkeit der Ausgabe von Gleikomma-Zahlen festle- gen ? 11. Wie kann man den Speicherbedarf einer Variable ermitteln ? Schreiben sie die C++ Anweisung f¨ r die Berechnung des Speicherbedarfs f¨ r eine u u doppelt-genaue Gleitkomma-Zahl.
  • 148. 148 KAPITEL 14 QUESTIONS 14.4 Testfragen - Kapitel 4 - Klassen 1. Geben sie eine Definition von C++ Klassen mit eigenen Worten (max 5 S¨tze). a 2. Was ist ein benutzerdefinierter Datentyp ? 3. Welches Datennschutz-Konzept gibt es f¨ r Klassen ? u 4. Wozu brauchen wir zwei Dateien f¨ r Klassen, eine H (Header) Datei und u eine CPP (Quelltext) Datei ? 5. Was ist ein Inklude / Include ? 6. Was ist eine Instanz einer Klasse ? 7. Worin besteht der Unterschied zwischen den Anweisungen: CStudent m std 1 und CStudent* m std 2 ? 8. Was ist ein Konstruktor einer Klasse ? 9. Was ist das Gegenst¨ ck zum Klassen-Konstruktor ? u 10. Wie k¨nnen Daten / Variablen einer Klasse initialisiert werden ? o 11. Schreiben sie den Quelltext f¨ r den Klassen-Konstruktor und weisen sie u den Variablen name first und name last ihren eigenen Namen zu. 12. Was verbirgt sich hinter der Anweisung: CStudent* m std = new CStudent() ? 13. Was ist der Unterschied zwischen CStudent und CStudent() ? 14. Wie kann ich meine Daten gegen einen externen Zugriff sch¨ tzen ? u 14.5 Testfragen - Kapitel 5 - Strings 1. Welche Klasse bietet uns C++ zur Verarbeitung von Zeichenketten an ? 2. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Zeichenketten ? o u 3. Wof¨ r ist die Anweisung using namespace std n¨ tzlich ? u u 4. M¨ ssen wir selber Speicherplatz f¨ r C++ Zeichenketten (Strings) reser- u u vieren ? 5. Wie k¨nnen wir einen String, sagen wir mit der Zeichenkette ”Das ist eine o gute Frage”, initialisieren ? 6. Wie k¨nnen wir zwei Strings, ihren Vor- und Nachnahmen, miteinander o verbinden ?
  • 149. 14.6 TESTFRAGEN - KAPITEL 6 - EIN- UND AUSGABE II 149 7. Mit welcher string Funktion kann ich Zeichenketten miteinander verglei- chen ? 8. Schreiben sie eine Anweisung zum Vergleich der Klassen-Variable m std− >name last mit ihrem Nachnamen ? 9. Mit welcher string Funktion kann ich Zeichenketten suchen ? 10. Schreiben sie eine Anweisung zum Suchen ihres Vornamens in der Klassen- Variable m std− >name first ? 11. Mit welcher string Funktion kann ich Teile in Zeichenketten erstetzen ? 12. Wie k¨nnen wir die L¨nge von Strings ermitteln ? o a 13. Schreiben sie die Anweisungen, um ihren Nachnamen in die Zeichenkette ”JAMES BOND” nach ”JAMES” einzuf¨ gen ?u 14. Was passiert, wenn ihr Nachname l¨nger als ”BOND” ist ? a 15. Mit welcher string Funktion k¨nnen wir Zeichen in einem String l¨schen ? o o 16. Wir haben gesehen, dass es verschiedene Daten-Typen f¨ r Zeichenketten u in C, C++, MFC, .NET und Qt gibt. Zeichenketten geh¨ren zu den wich- o tigsten Daten-Typen bei der Programmierung. Wie k¨nnen wir einen C++ o string in eine C Zeichenkette (char) umwandeln ? 17. K¨nnen wir eine .NET Zeichenkette (String∧) in eine C++ Zeichenkette o (string) umwandeln ? 18. Was ist ein stringstream ? 19. Welchen Include ben¨tigen wir f¨ r die Arbeit mit Stringstreams ? o u 14.6 Testfragen - Kapitel 6 - Ein- und Ausgabe II 1. Was ist die Basis-Klasse f¨ r alle Ein- und Ausgaben in C++ ? u 2. Was sind die C++ Klassen f¨ r das Lesen und Schreiben von Dateien ? u 3. Welchen Include ben¨tigen wir f¨ r das Arbeiten mit I/O File-Klassen ? o u 4. Was sind die Standard-Flags f¨ r File-Streams (Lesen und Schreiben) ? u 5. Mit welchem Flag k¨nnen wir zu schreibende Daten an eine existierende o Datei anh¨ngen ? a 6. Was ist der Unterschied zwischen ASCII- und Bin¨r-Formaten ? a
  • 150. 150 KAPITEL 14 QUESTIONS 7. Mit welchem Flag k¨nnen wir Daten in einem Bin¨r-Format schreiben ? o a Mit welcher Anweisung wird ein File ge¨ffnet ? Mit welcher Anweisung o wird ein File geschlossen ? 8. Was bewirken die Stream-Operatoren << und >> ? 9. Wie k¨nnen wir mit Dateinamen in unserem Hauptprogramm main(...) o arbeiten ? 10. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen o u u Eingabe-Strom ? 11. Welche Anweisung ben¨tigen wir f¨ r die Erzeugung einer Instanz f¨ r einen o u u Ausgabe-Strom ? 12. F¨ r die Erstellung einer Datenbank ist es wichtig einzelnen Datens¨tze zu u a trennen. Wie k¨nnen wir soetwas in der Datenbank-Datei bewerkstelligen o ? 13. Ist es wichtig das Ende einer Datenbank-Datei, z.B. mit einem Schl¨ ssel- u wort #STOP, zu markieren ? o u ¨ 14. Mit welcher Abfrage k¨nne wir pr¨ fen, ob die Offnung einer Datei erfolg- reich war ? 15. Mit welcher Anweisung k¨nnen wir die aktuell gelesene Position in einer o ge¨ffneten Datei abfragen ? o 16. Mit welcher Anweisung k¨nnen wir zu einer bestimmten Position in einer o ge¨ffneten Datei springen ? o 17. Mit welcher Anweisung k¨nnen wir eine komplette Zeile aus ge¨ffneten o o Datei auslesen ? 14.7 Testfragen - Kapitel 7 - Referenzen und Zeiger 1. Was ist &x ? (x ist ein beliebiger Datenobjekt T, z.B. eine Gleitkomma- zahl: double x) 2. Was ist eine Referenz &ref? 3. Was bedeutet die Anweisung: &ref = x? 4. Erkl¨ren sie kurz (mit eigenen Worten) das Zeiger-Konzept in C++? a 5. Was bewirkt der NULL Zeiger, d.h. *ptr = NULL ? 6. Was bedeutet die Anweisung: ptr = x?
  • 151. 14.8 TESTFRAGEN - KAPITEL 8 - CONTAINER 151 7. M¨ ssen Referenzen (&) und Zeiger (*) auf Daten-Objekte initialisiert wer- u den ? 8. Was bewirkt die Definition long l[1000] speichertechnisch ? 9. Wie groß ist der Speicherbedarf des statischen Datenobjekts long l[1000] ? 10. Wie groß ist der Speicherbedarf des dynamische Datenobjekts long* ptr l = new long[1000] ? 11. Woher kommt der Unterschied (4 Byte auf einem 32Bit Rechner) im Speicherbedarf zwischen statischen und dynamischen Datenobjekten. 12. Zusatzfrage: Was bedeutet die Definition **ptrptr (Zeiger auf Zeiger), was f¨ r ein Datenkonstrukt entsteht ? u 14.8 Testfragen - Kapitel 8 - Container 1. Was sind C++ Container ? 2. Welche Typen von C++ Containern kennen sie ? 3. Worin besteht der Unterschied zwischen sequentiellen und assoziativen Containern ? 4. Welche sequentiellen Container kennen sie ? 5. Erkl¨ren sie die Syntax des Vektor-Containers: vector<int>my vector . a 6. Was ist der Unterschied zwischen Vektoren und Listen ? 7. Was sind die Gemeinsamkeiten von Vektoren und Listen ? 8. Welcher Include ist notwendig f¨ r das Arbeiten mit Vektoren ? u 9. Welcher Include ist notwendig f¨ r das Arbeiten mit Listen ? u 10. Ben¨tigen wir den Zusatz (Namensraum) using namespace std, wenn ja o warum ? 11. Mit welcher Instruktion k¨nnen Elemente in Vektoren und Listen einf¨ gen o u ? 12. Wo werden sequentielle Container-Elemente mit der Instruktion push back(T) eingef¨ gt ? u 13. Mit welcher Anweisung k¨nnen wir die L¨nge von sequentiellen Container- o a Elementen bestimmen ?
  • 152. 152 KAPITEL 14 QUESTIONS 14. Mit welcher Anweisung k¨nnen wir einen Vektor platt machen (d.h. alle o Elemente l¨schen) ? o 15. Wie k¨nnen wir auf ein Vektor-Element, sagen wir das 17te Element des o Vektors vector<int>my vector, direkt zugreifen ? 16. Quellcode verstehen: Erkl¨ren sie die Struktur (1,2,3) der DB-Lese-Funktion a ¨ STDRead(ifstream& std file) in der Ubung 8.2.2. Beginnen sie mit der Pa- rameterliste. 17. Wie k¨nnen wir unsere Studenten-Klasse CStudent in die DB-Anwendung o ¨ (Ubung 8.2.1) einbinden ? u a ¨ 18. Was ist eigentliche Lesefunktion f¨ r unsere Studenten-Datens¨tze (Ubung 8.2.2) ? 19. Mit welchem Befehl k¨nnen wir die Reihenfolge von Listen-Elementen o umkehren ? 20. K¨nnen wir Listen-Elemente sortieren, wenn ja wie, mit welcher Instruk- o tion ? 21. Mit welchem Befehl k¨nnen wir mehrere Listen zusammenf¨ hren ? o u 22. K¨nnen wir doppelte Elemente aus einer Liste entfernen sortieren, wenn o ja wie, mit welcher Instruktion ? 23. Was ist ein Iterator ? 24. Quellcode verstehen: Erkl¨ren sie die Funktion void display(list<int>my list) a ¨ der Ubung 8.3. Beginnen sie mit der Parameterliste. 25. Wie k¨nnen wir Elemente aus einer Liste entfernen ? o 14.9 Testfragen - Kapitel 9 - Andere Sprachele- mente 1. Was sind Kontrollstrukturen, welche kennen sie ? 2. Bei welcher logischen Bedingung wird eine if-Anweisung ausgef¨ hrt ? u 3. Lassen sich Kontroll-Strukturen verschachteln ? 4. Mit welcher Kontrollstruktur k¨nnen wir Fallunterscheidungen program- o mieren ? 5. Welche Ausdr¨ cke k¨nnen wir bei der switch-case Kontrollstruktur be- u o nutzen ? 6. Wie kann ich eine Kompiler-Direktive an- und ausschalten ?
  • 153. 14.10 TESTFRAGEN - KAPITEL 10 - DIALOGE 153 ¨ 7. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle u von #ifdef um. 8. Erl¨utern sie den Kopf der for-Schleife: for(int i=0;i<stop;i++), wel- a chen Daten-Typ hat stop ? 9. Was ist eine Endlos-Schleife, wie kommen wir daraus ? 10. Was sind Namensbereiche ? 11. Was m¨ ssen wir tun, um die Arbeit mit C++ Standard-Klassen zu verein- u fachen, d.h anstelle von std::my string() direkt my string() benutzen zu k¨nnen ? o 12. Was sind Kompiler-Direktiven, was bewirken diese ? 13. Wie k¨nnen wir Kompiler-Direktiven an- und ausschalten ? o 14. Worin besteht der Unterschied bei Includes mit eckigen Klammern < ... > bzw. mit G¨nsef¨ ßchen ”...” ? a u ¨ 15. Schreiben sie die Ubung 9.2.2.2 f¨ r die Benutzung von #ifndef anstelle u von #ifdef um ? 16. Was sind Makros ? 17. Welche beiden Einsatzm¨glickeiten von Makros gibt es ? o 18. Worin besteht die Gefahr, Makros als Funktionsersatz zu benutzen ? 14.10 Testfragen - Kapitel 10 - Dialoge MFC 1. Welche Typen von grafischen Windows-Applikationen kennen sie ? 2. Was ist eine Dialog-Resource ? 3. Welche Dialog-Elemente haben wir in unserer Windows-Applikation be- nutzt (Abb. 10.3) ? 4. Was sind IDs ? 5. Was ist eine MESSAGE MAP ? 6. Wie wird die Verbindung zwischen Funktionen und grafischen Dialog- Elementen hergestellt ? 7. Wie wird die Verbindung zwischen Daten und grafischen Dialog-Elementen hergestellt ?
  • 154. 154 KAPITEL 14 QUESTIONS 8. Was bedeutet die Definition: class CMyDialog : public CDialog ? 9. Wie wird ein Dialog aufgerufen (Funktion der Klasse CDialog)? 10. Was bewirkt die Dialog-Funktion UpdateData() ? 11. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten- Klasse ? 12. Wie kann ich Files unter Windows ¨ffnen (welche Klasse) ? o 13. Was ist ein BMP ? .NET 1. Was ist eine Formular-Resource ? 2. Welche Formular-Elemente haben wir in unserer .NET-Applikation be- nutzt (Abb. 10.10) ? 3. Wie wird die Verbindung zwischen Funktionen und grafischen Formular- Elementen hergestellt ? 4. Wie wird die Verbindung zwischen Daten und grafischen Formular-Elementen hergestellt ? 5. Was bedeutet die Definition: private: System::Windows::Forms::Button MyButton ? 6. Was bedeutet die Definition: private: System::Void button3 Click() ? 7. Wie wird ein Formular aufgerufen (Funktion der Klasse Form1)? 8. Was ist die Schnittstelle zwischen dem Dialog und unserer Studenten- Klasse ? 9. Wie kann ich Files mit .NET ¨ffnen (welche Klasse) ? o = 158.
  • 155. Literaturverzeichnis [1] Stroustrup B. The programming languages C++. Addison-Wesley, Reading, 1991. [2] Blanchette J and Summerfield M. C++ GUI Programming with Qt 4. Pren- tice Hall, Boston, 2006. [3] Kolditz O. Computational methods in environmental fluid mechanics. Sprin- ger, Berlin-Heidelberg, 2002. [4] Breymann U. C++ Einf¨hrung und professionelle Programmierung. Hanser, u M¨ nchen-Wien, 2001. u [5] Kirch-Prinz U and Prinz P. C++ Lernen und professionell anwenden. mitp, Heidelberg, 2007. 155
  • 156. Inhaltsverzeichnis Part I - C++ Basics 6 1 Einf¨hrung u 7 1.1 Historisches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.2 Paradigmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3 Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3.1 GNU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3.2 MS Visual C++ . . . . . . . . . . . . . . . . . . . . . . . 13 1.3.3 Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4 ”Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4.2 Exercise E1 . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.5 Students Forum . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.6 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2 Datentypen 18 2.1 Elementare Datentypen . . . . . . . . . . . . . . . . . . . . . . . 18 2.2 Speicherbedarf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 Escape-Sequenzen . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.4 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3 Ein- und Ausgabe 21 3.1 Die Standard-Streams . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2 Formatierte Ausgaben . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.1 Formatierte Ausgabe von Ganzzahlen . . . . . . . . . . . 23 156
  • 157. INHALTSVERZEICHNIS 157 3.2.2 Formatierte Ausgabe von Gleitpunktzahlen . . . . . . . . 24 3.2.3 Ausgabe von Speicherbedarf . . . . . . . . . . . . . . . . . 24 3.3 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4 Klassen 26 4.1 Daten-Abstraktion . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4.2 Klassen-Deklaration . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.3 Instanzen einer Klasse . . . . . . . . . . . . . . . . . . . . . . . . 28 4.4 Konstruktor und Destruktor . . . . . . . . . . . . . . . . . . . . . 30 4.5 Dateninitialisierung mit dem Konstruktor . . . . . . . . . . . . . 31 4.6 Datenschutz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 4.7 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 5 Strings 35 5.1 Die Standardklasse string . . . . . . . . . . . . . . . . . . . . . . 35 5.2 Operationen mit strings . . . . . . . . . . . . . . . . . . . . . . . 36 5.2.1 Initialisieren von strings . . . . . . . . . . . . . . . . . . . 36 5.2.2 Zuweisen von strings . . . . . . . . . . . . . . . . . . . . . 37 5.2.3 Verketten von strings . . . . . . . . . . . . . . . . . . . . 37 5.2.4 Vergleichen von strings . . . . . . . . . . . . . . . . . . . . 37 5.2.5 Suchen in strings . . . . . . . . . . . . . . . . . . . . . . . 38 5.2.6 Einf¨ gen in strings . . . . . . . . . . . . . . . . . . . . . . u 38 5.2.7 Ersetzen in strings . . . . . . . . . . . . . . . . . . . . . . 39 5.2.8 L¨schen in strings . . . . . . . . . . . . . . . . . . . . . . o 39 5.2.9 Umwandeln von strings in char . . . . . . . . . . . . . . . 40 5.2.10 Auswerten von Strings: Stringstreams . . . . . . . . . . . 40 5.3 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 6 Ein- und Ausgabe - II 42 6.1 Die fstream Klassen . . . . . . . . . . . . . . . . . . . . . . . . . 42 6.2 Arbeiten mit File-Streams . . . . . . . . . . . . . . . . . . . . . . 43 6.2.1 File-Streams anlegen . . . . . . . . . . . . . . . . . . . . . 43 6.2.2 File-Streams schließen . . . . . . . . . . . . . . . . . . . . 43 6.2.3 ¨ Ubung: Eine einfache Kopierfunktion . . . . . . . . . . . . 43
  • 158. 158 INHALTSVERZEICHNIS 6.2.4 ¨ Ubung: Ein einfacher Konverter . . . . . . . . . . . . . . . 45 6.2.5 Einschub: Erstes Arbeiten mit MS VC++ . . . . . . . . . 46 6.3 File-Streams und Klassen . . . . . . . . . . . . . . . . . . . . . . 49 6.4 fstream Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . 52 6.5 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 7 Referenzen und Zeiger 54 7.1 Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.1.1 Das Call-by-reference Prinzip - Referenzen als Parameter 55 7.1.2 Referenzen als R¨ ckgabe-Wert . . . . . . . . . . . . . . . u 56 7.2 Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 7.2.1 Definition von Zeigern . . . . . . . . . . . . . . . . . . . . 57 7.2.2 NULL Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . 57 7.2.3 Zeiger als Parameter . . . . . . . . . . . . . . . . . . . . . 58 7.3 Zeiger und Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 58 7.3.1 Statische Objekte . . . . . . . . . . . . . . . . . . . . . . . 58 7.3.2 Dynamische Objekte . . . . . . . . . . . . . . . . . . . . . 58 7.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7.5 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 8 Container 62 8.1 Sequentielle Container . . . . . . . . . . . . . . . . . . . . . . . . 63 8.2 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 8.2.1 Defining vectors . . . . . . . . . . . . . . . . . . . . . . . 66 8.2.2 Vectors and data base . . . . . . . . . . . . . . . . . . . . 66 8.2.3 Updating your data base entry . . . . . . . . . . . . . . . 68 8.3 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 8.4 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 9 Andere Sprachelemente 73 9.1 Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . 73 9.1.1 if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 9.1.2 switch-case . . . . . . . . . . . . . . . . . . . . . . . . . 74 9.1.3 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
  • 159. INHALTSVERZEICHNIS 159 9.1.4 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 9.1.5 continue, break, return . . . . . . . . . . . . . . . . . 75 9.2 G¨ ltigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . u 76 9.2.1 Namensbereiche . . . . . . . . . . . . . . . . . . . . . . . 76 9.2.2 Compiler-Direktiven – # . . . . . . . . . . . . . . . . . . 76 9.3 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Part II - Visual C++ 80 10 Dialoge 82 10.1 What have we (i.e. MFC) created ? . . . . . . . . . . . . . . . . . 82 10.2 Gestaltung des Dialogs . . . . . . . . . . . . . . . . . . . . . . . . 85 10.3 Programmierung des Dialogs – MyDialogDlg . . . . . . . . . . . 87 10.3.1 Dialog-Funktionen . . . . . . . . . . . . . . . . . . . . . . 87 10.3.2 Dialog-Daten . . . . . . . . . . . . . . . . . . . . . . . . . 87 10.3.3 Implementierung des Dialogs . . . . . . . . . . . . . . . . 88 10.3.4 Schnittstelle zwischen Dialog- und Studenten-Klasse . . . 89 10.3.5 N¨ tzliche Windows-Funktionen . . . . . . . . . . . . . . . u 92 10.4 Das .NET Formular . . . . . . . . . . . . . . . . . . . . . . . . . 94 10.4.1 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . 95 10.4.2 Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 ¨ 10.4.3 Ubung: Hinzuf¨ gen von Funktionen . . . . . . . . . . . . u 97 10.5 HomeWorks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 10.6 Testfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 11 Qt 104 11.1 Hello Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 11.2 Executable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 11.3 Quit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 11.4 Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Part III - Anlagen / Software 111
  • 160. 12 Software-Installation 112 12.1 cygwin Installation . . . . . . . . . . . . . . . . . . . . . . . . . . 113 12.2 LINUX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 ¨ 12.2.1 Ubersicht einiger grundlegenden Linux-Befehle . . . . . . 122 12.2.2 Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.2.3 Make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 12.3 Sch¨ sselworte in C++ . . . . . . . . . . . . . . . . . . . . . . . . 129 u 12.4 MS VC++ Projekt #1 - Eine Konsolenanwendung . . . . . . . . 130 12.5 MFC-Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 12.6 .NET Formular . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 12.7 UBUNTU & Wine . . . . . . . . . . . . . . . . . . . . . . . . . . 141 12.8 Qt Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 13 Students Forum 145 13.1 Vorlesung 1: 17.04.2009 . . . . . . . . . . . . . . . . . . . . . . . 145 14 Questions 146 14.1 Testfragen - Kapitel 1 - Einf¨ hrung . . . . . . . . . . . . . . . . . 146 u 14.2 Testfragen - Kapitel 2 - Datentypen . . . . . . . . . . . . . . . . 147 14.3 Testfragen - Kapitel 3 - Ein- und Ausgabe I . . . . . . . . . . . . 147 14.4 Testfragen - Kapitel 4 - Klassen . . . . . . . . . . . . . . . . . . . 148 14.5 Testfragen - Kapitel 5 - Strings . . . . . . . . . . . . . . . . . . . 148 14.6 Testfragen - Kapitel 6 - Ein- und Ausgabe II . . . . . . . . . . . 149 14.7 Testfragen - Kapitel 7 - Referenzen und Zeiger . . . . . . . . . . 150 14.8 Testfragen - Kapitel 8 - Container . . . . . . . . . . . . . . . . . 151 14.9 Testfragen - Kapitel 9 - Andere Sprachelemente . . . . . . . . . . 152 14.10Testfragen - Kapitel 10 - Dialoge . . . . . . . . . . . . . . . . . . 153