Gerd Küveler Dietrich Schwoch
Informatik für Ingenieure und Naturwissenschaftler 1
Aus dem Programm Elektro- und Info...
67 downloads
768 Views
3MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Gerd Küveler Dietrich Schwoch
Informatik für Ingenieure und Naturwissenschaftler 1
Aus dem Programm Elektro- und Informationstechnik
Elemente der angewandten Elektronik von E. Böhmer Digitaltechnik von K. Fricke Aufgabensammlung Elektrotechnik 1 und 2 von M. Vömel und D. Zastrow Bussysteme in der Automatisierungsund Prozesstechnik herausgegeben von G. Schnell Digitale Schnittstellen und Bussysteme von F. Wittgruber Automatisieren mit SPS Theorie und Praxis von G. Wellenreuther und D. Zastrow Automatisieren mit SPS Übersicht und Übungsaufgaben von G. Wellenreuther und D. Zastrow Steuerungstechnik mit SPS von G. Wellenreuther und D. Zastrow Mikroprozessortechnik von K. Wüst Softwareengineering für Ingenieure und Informatiker von P. Zöller-Greer
vieweg
Gerd Küveler Dietrich Schwoch
Informatik für Ingenieure und Naturwissenschaftler 1 Grundlagen Programmieren mit C/C++ Großes C/C++-Praktikum 5., vollständig überarbeitete und aktualisierte Auflage
Viewegs Fachbücher der Technik
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar.
Das Buch erschien bis zur 4. Auflage unter dem Titel „ Informatik für Ingenieure“ im selben Verlag.
1. Auflage 1996 2., vollständig überarbeitete Auflage 1999 3., vollständig überarbeitete und erweiterte Auflage Januar 2001 4., durchgesehene und erweiterte Auflage April 2003 5., vollständig überarbeitete und aktualisierte Auflage Februar 2006 Alle Rechte vorbehalten © Friedr. Vieweg & Sohn Verlag/ GWV Fachverlage GmbH, Wiesbaden 2006 Lektorat: Reinhard Dapper Der Vieweg Verlag ist ein ist ein Unternehmen von Springer Science+Business Media. www.vieweg.de
Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlags unzulässig und strafbar. Das gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.
Umschlaggestaltung: Ulrike Weigel, www.CorporateDesignGroup.de Technische Redaktion: Andreas Meißner, Wiesbaden Druck und buchbinderische Verarbeitung: Wilhelm & Adam, Heusenstamm Gedruckt auf säurefreiem und chlorfrei gebleichtem Papier. Printed in Germany ISBN 3-8348-0035-X
V
Vorwort Erstmals mit der neuen Auflage erscheint das vorliegende Werk in geteilter Form. Das eröffnet zum einen die Möglichkeit zu größerer Ausführlichkeit, zum anderen ist der Leser nicht gezwungen, viele Seiten zu erwerben, die ihn persönlich nicht interessieren. Zunächst sind zwei Bände geplant. Der vorliegende erste führt in die Hochsprachen-Programmierung ein. Nicht zufällig wurde als Sprache C/C++ gewählt, weil sie sich im Laufe der letzten Jahre zu bedeutendsten Universalsprache mit breitestem Anwendungsspektrum entwickelt hat. Der zweite Band soll in etwa einem Jahr erscheinen und wird sich schwerpunktmäßig mit PC-Technik und Computernetzen beschäftigen. Die Teile I bis III dieses ersten Bandes entsprechen inhaltlich einer zweisemestrigen Einführung in die Informatik für Ingenieurstudenten oder Studenten der Naturwissenschaften. Der Stundenumfang wird dabei mit insgesamt 4 Semesterwochenstunden Vorlesung und ebenso vielen Übungen angesetzt. Der Text erlaubt jedoch durchaus auch ein Selbststudium. Teil I bietet einen kurzen Überblick über die technische Informatik. Nach dieser Einstimmung geht es dann mit Teil II richtig los: Ab hier setzen wir den Zugang zu einem PC mit C++-Compiler voraus. Die Einführung ist zwar systematisch aber dennoch sehr praxisnah angelegt, d. h. der Leser erhält die Gelegenheit, das Gelernte komplett nachzuvollziehen. Aus diesem Grund ergänzen zahlreiche Übungsaufgaben die einzelnen Kapitel. Vor allem aber der Teil III mit seinen Praktikumsaufgaben macht aus jedem Leser einen brauchbaren C-Programmierer, zumindest wenn er sich durch die nicht immer ganz einfachen Aufgaben „kämpft“. Um gelegentlichen Frust zu vermeiden, haben wir für sämtliche Praktikumsaufgaben die Komplettlösungen angegeben. Die Praktikumsaufgaben sollten Sie lernbegleitend zu Teil II lösen. Die Sprache C/C++ ist nicht nur Selbstzweck, sondern eröffnet einen fundierten Zugang zu anderen Spezialsprachen im technisch-wissenschaftlichen Bereich, wie etwa LabVIEW. Java, besonders für Web-Anwendungen interessant, basiert auf C++. Aber selbst zu komplexen Anwendungsprogrammen bzw. Tools wie Excel, MATLAB und Simulink oder Mathematica findet man als geübter Programmierer leichteren Zugang. Die Quelltexte der im Buch abgedruckten Programme, die Lösungen zu den Übungsaufgaben sowie eventuelle aktuelle Ergänzungen und Fehlerkorrekturen finden Sie im Internet unter http://r5.mnd.fh-wiesbaden.de/infobuch Sie haben dort auch die Möglichkeit, uns eine E-Mail zu schicken. Über Hinweise auf Fehler, Anregungen und Kritiken würden wir uns freuen. Unser Dank gilt allen, die einen Beitrag zu diesem Buches geleistet haben. Viele Hinweise auf Fehler in den vorherigen Auflagen stammen von Kollegen, denen wir hiermit ebenfalls danken. Glashütten, im Januar 2006 Dieburg, im Januar 2006
Gerd Küveler Dietrich Schwoch
VI
Inhaltsverzeichnis Inhaltsverzeichnis
I Grundlagen ................................................................................................................... 001 1 Grundprinzipien der Datenverarbeitung ....................................................... 002 1.1 Historische Entwicklung der Datenverarbeitung ........................................................ 002 1.1.1 Von A wie Abakus bis Z wie Zuse.................................................................. 002 1.1.2 Die Rechnergenerationen ................................................................................ 003 1.1.3 Computer und Science Fiction ........................................................................ 005 1.2 Funktion und Aufbau eines Rechners ......................................................................... 006 1.3 Aufgaben .................................................................................................................... 011
2 Das Betriebssystem ................................................................................................... 012 2.1 Single- und Multitasking ............................................................................................ 012 2.2 Dateien und Dateiensysteme....................................................................................... 016
3 Algorithmen und Struktogramme ...................................................................... 019 3.1 Algorithmen................................................................................................................ 019 3.2 Struktogramme ........................................................................................................... 019 3.3 Aufgaben .................................................................................................................... 026
4 Programmiersprachen ............................................................................................. 028 4.1 Maschinen- und Hochsprachen................................................................................... 028 4.2 Die Hochsprachen-Programmentwicklung ................................................................. 032
II Programmieren in C/C++ ...................................................................................... 034 5 Über C und C++ ......................................................................................................... 035 6 Grundlagen .................................................................................................................. 036 6.1 Ein einführendes Beispiel ........................................................................................... 036 6.2 Anweisungen, Wertzuweisungen und Datentypen ..................................................... 037 6.3 Der Aufbau eines C++-Programms ............................................................................ 040 6.3.1 Die Bausteine der Sprache .............................................................................. 040 6.3.2 Der Blockaufbau eines Programms ................................................................. 042 6.3.3 Separationszeichen .......................................................................................... 044
Inhaltsverzeichnis
VII
6.3.4 Kommentare.................................................................................................... 045 6.3.5 Die Freiheit der äußeren Form ........................................................................ 045 6.4 Fehler.......................................................................................................................... 046 6.4.1 Syntaxfehler .................................................................................................... 046 6.4.2 Laufzeitfehler .................................................................................................. 047 6.4.3 Logische Fehler............................................................................................... 048 6.5 Die Entwicklung von C/C++ -Programmen ............................................................... 048 6.6 Aufgaben .................................................................................................................... 049
7 Vordefinierte Standard-Datentypen und einfache Operationen ........... 051 7.1 Der Umgang mit Zahlen ............................................................................................. 051 7.1.1 Ein wesentlicher Unterschied: int oder float.................................................. 051 7.1.2 Ganzzahlige Datentypen ................................................................................. 053 7.1.3 Reelle Datentypen ........................................................................................... 058 7.1.4 Standardfunktionen mit Zahlen ....................................................................... 061 7.2 Verarbeitung von Einzelzeichen: Der Datentyp char ................................................. 063 7.2.1 Der Umgang mit der ASCII-Tabelle ............................................................... 065 7.2.2 Standardfunktionen mit char ........................................................................... 067 7.3 Logische Ausdrücke ................................................................................................... 069 7.4 Operatoren und Ausdrücke ......................................................................................... 072 7.5 Benutzerdefinierte Konstanten ................................................................................... 078 7.6 Aufgaben .................................................................................................................... 079
8 Interaktive Ein-/Ausgabe ....................................................................................... 081 8.1 8.2 8.3 8.4 8.5
Standard Ein-/Ausgabe mit C++................................................................................. 081 Formatierte Bildschirm-Ausgabe................................................................................ 086 Standard-Eingabe ....................................................................................................... 089 Standard Ein-/Ausgabe mit C ..................................................................................... 092 Aufgaben .................................................................................................................... 096
9 Programm - Ablaufstrukturen ............................................................................. 098 9.1 Die Selektion .............................................................................................................. 098 9.1.1 Die einseitige Verzweigung: if ........................................................................ 098 9.1.2 Die Alternative: if ... else ................................................................................. 100 9.1.3 Die Mehrfach-Fallunterscheidung: switch ... .................................................. 101 9.2 Die Iteration................................................................................................................ 104 9.2.1 Die Zählschleife: for ....................................................................................... 104 9.2.2 Bedingungsschleifen ........................................................................................ 108 9.2.2.1 Die abweisende Bedingungsschleife: while...................................... 108 9.2.2.2 Die nicht-abweisende Bedingungsschleife: do...while...................... 113 9.3 Die Schachtelung von Kontrollstrukturen .................................................................. 117 9.4 Aufgaben .................................................................................................................... 120
VIII
Inhaltsverzeichnis
10 Modularisierung von Programmen: Functions...................................... 126 10.1 10.2 10.3 10.4 10.5 10.6 10.7
Vereinbarungen von Functions ................................................................................. 129 Der Aufbau von Funktionen ..................................................................................... 131 Die Parameterübergabe............................................................................................. 134 Die return-Anweisung .............................................................................................. 138 Der Geltungsbereich von Vereinbarungen................................................................ 140 Rekursionen .............................................................................................................. 143 Aufgaben .................................................................................................................. 146
11 Höhere Datenstrukturen .......................................................................... 148 11.1 Felder ....................................................................................................................... 148 11.1.1 Eindimensionale Felder................................................................................. 148 11.1.2 Mehrdimensionale Felder.............................................................................. 156 11.1.3 Zeichenketten: Strings................................................................................... 158 11.1.4 Initialisierung von Feldern ............................................................................ 163 11.2 Pointer....................................................................................................................... 165 11.2.1 Pointer und Felder ......................................................................................... 168 11.2.2 Dynamische Speicherverwaltung .................................................................. 170 11.3 Datenverbunde: Strukturen ....................................................................................... 172 11.3.1 Übergabe von Strukturen an Funktionen....................................................... 176 11.3.2 Struktur-Pointer............................................................................................. 177 11.3.3 Der typedef-Operator .................................................................................... 180 11.4 Aufgaben .................................................................................................................. 180
12 Arbeiten mit Dateien................................................................................. 183 12.1 ASCII-Dateien: Der Dateityp Text ........................................................................... 185 12.2 Binärdateien.............................................................................................................. 189 12.3 Aufgaben .................................................................................................................. 194
13 Einführung in die OOP mit C++ ............................................................. 195 13.1 Klassen...................................................................................................................... 195 13.2 Der ObjektOrientierte Ansatz ................................................................................... 199 13.3 Konstruktoren und Destruktoren............................................................................... 200 13.4 Dateiorganisation...................................................................................................... 207 13.5 Friend Funktionen und –Klassen .............................................................................. 210 13.6 Überladen von Funktionen........................................................................................ 213 13.7 Überladen von Operatoren........................................................................................ 215 13.8 Der this-Zeiger.......................................................................................................... 228 13.9 Übergabe von Objekten an Funktionen .................................................................... 231 13.10 Dynamischer Speicher und Klassen........................................................................ 235 13.11 Vererbung ............................................................................................................... 239 13.12 Abschlussbemerkungen .......................................................................................... 243 13.13 Aufgaben ................................................................................................................ 244
Inhaltsverzeichnis
IX
III C/C++ Praktikum.................................................................................... 247 14 Einführungs-Praktikum ........................................................................... 248 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9
Erstes Praktikum....................................................................................................... 249 Zweites Praktikum.................................................................................................... 250 Drittes Praktikum...................................................................................................... 250 Viertes Praktikum ..................................................................................................... 252 Fünftes Praktikum..................................................................................................... 253 Sechstes Praktikum................................................................................................... 255 Siebentes Praktikum ................................................................................................. 256 Achtes Praktikum ..................................................................................................... 257 Praktischer Programmiertest..................................................................................... 260
15 Fortgeschrittenen-Praktikum .................................................................. 261 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9
Erstes Praktikum....................................................................................................... 261 Zweites Praktikum.................................................................................................... 262 Drittes Praktikum...................................................................................................... 265 Viertes Praktikum ..................................................................................................... 266 Fünftes Praktikum..................................................................................................... 267 Sechstes Praktikum................................................................................................... 268 Siebentes Praktikum ................................................................................................. 270 Achtes Praktikum ..................................................................................................... 272 Neuntes Praktikum ................................................................................................... 273
16 Lösungen zum Einführungs-Praktikum ................................................. 275 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9
Lösungen zum ersten Praktikum .............................................................................. 275 Lösungen zum zweiten Praktikum............................................................................ 276 Lösungen zum dritten Praktikum.............................................................................. 278 Lösungen zum vierten Praktikum............................................................................. 281 Lösungen zum fünften Praktikum ............................................................................ 284 Lösungen zum sechsten Praktikum........................................................................... 287 Lösungen zum siebenten Praktikum ......................................................................... 288 Lösungen zum achten Praktikum.............................................................................. 291 Lösung zum praktischen Programmiertest ............................................................... 296
17 Lösungen zum Fortgeschrittenen-Praktikum ........................................ 298 17.1 17.2 17.3 17.4 17.5 17.6
Lösung zum ersten Praktikum .................................................................................. 298 Lösung zum zweiten Praktikum ............................................................................... 301 Lösung zum dritten Praktikum ................................................................................. 303 Lösung zum vierten Praktikum................................................................................. 305 Lösung zum fünften Praktikum ................................................................................ 308 Lösung zum sechsten Praktikum .............................................................................. 312
X
Inhaltsverzeichnis 17.7 Lösung zum siebten Praktikum................................................................................. 318 17.8 Lösung zum achten Praktikum ................................................................................. 321 17.9 Lösung zum neunten Praktikum ............................................................................... 327
Anhang ............................................................................................................ 332 Sachwortverzeichnis ...................................................................................... 333
1
I Grundlagen In diesem Teil geht es darum, einen Überblick über wichtige Grundlagen der technischen Informatik zu vermitteln, die wir später ausführlich behandeln. Dabei fangen wir zwar im wahrsten Sinne des Wortes bei (Adam und) EVA an, stellen uns aber dennoch einen Leser vor, für den Computer selbstverständliche Gegenstände seiner Umgebung darstellen wie Autos und Fernsehgeräte. So werden Sie wissen, dass ein PC mindestens über eine Zentraleinheit, ein Bildschirmgerät und eine Tastatur verfügt. Wahrscheinlich haben Sie Computerspiele gespielt, mit Office-Software wie Word, Excel oder Power Point gearbeitet, CDs gebrannt und wissen, was eine Datei ist. Auch der Umgang mit Windows dürfte Ihnen vertraut sein. Wenn nicht, wird es höchste Zeit, Computererfahrungen zu sammeln. Doch selbst ein geübter Computeranwender sollte diese kleine Einführung lesen (es sind ja nur 33 Seiten), denn sie wird auch ihm einiges Neue zu bieten haben.
2
1 Grundprinzipien der Datenverarbeitung
1 Grundprinzipien der Datenverarbeitung 1 Grundprinzipien der Datenverarbeitung
Datenverarbeitung (DV) wird nicht erst seit Einführung des Computers betrieben. Das menschliche Gehirn kann offensichtlich auch ohne technische Hilfsmittel Daten verarbeiten. Beispiel Kopfrechenaufgabe: addiere 3 zu 2 Untergliederung in 3 Schritte 1. Aufnehmen der Daten mit unseren Sinnen 2. Verarbeiten der Daten im Gehirn 3. Mitteilen des Ergebnisses durch Wort oder Schrift
■
Hieraus leitet sich das Hauptprinzip der DV ab: E i n g a b e
V A e u r s a g r a b b e e i t u n g Dieses „EVA“-Prinzip liegt allen klassischen technischen DV-Anlagen zugrunde.
1.1 Historische Entwicklung der Datenverarbeitung 1.1 Historische Entwicklung der Datenverarbeitung
Der moderne Allzweckrechner entwickelte sich erst nach Ende des Zweiten Weltkrieges. Trotzdem hat er eine lange Vorgeschichte. Bei den elektronischen Rechnern haben technologische Entwicklungssprünge zu den verschiedenen Computergenerationen geführt.
1.1.1 Von A wie Abakus bis Z wie Zuse Die technische Geschichte der Rechenmaschinen weist folgende Meilensteine auf: –
ca. 1000 v. Chr.
Abakus (= Rechenbrett, Rechentafel) • • •
–
1623
Speicherfunktion Rechenfunktion: Addition und Subtraktion noch heute meistbenutzte „Rechenmaschine“ der Welt
Schickard`sche Rechenmaschine •
Zahnradgetriebe: 10 Räder mit je 10 Zähnen
1.1 Historische Entwicklung der Datenverarbeitung • • –
1642
1672
1833
• 1886
• • 1941
Babbage entwarf das Konzept eines programmierbaren Universalrechners mit Zahlenspeicher, Rechenwerk, Leitwerk sowie Ein- und Ausgabeeinheiten. Programmierung mit Lochkarten nach dem Vorbild der automatischen Webstühle nach Jacquard (um 1800). Babbages „Analytical Engine“ konnte nicht gebaut werden, da bis zu 25 Zahnräder ineinander greifen mussten, was damals mechanisch noch nicht lösbar war. 1991 wurde sie jedoch erfolgreich nachgebaut. sehr wichtig für die Theorie des Computers!
Papplochkarte nach Hermann Hollerith •
–
zusätzlich verschiebbare Staffelwalze zum schnellen Addieren und Multiplizieren
Differenzenmaschine nach Charles Babbage •
–
Prinzip wie bei Schickard, jedoch mit verbesserter Mechanik
Rechenmaschine von Leibniz •
–
Stellenwertübertrag wie beim Kilometerzähler Addition und Subtraktion
Pascalsche Rechenmaschine •
–
3
Einsatz zur Auswertung der 11. amerikanischen Volkszählung Format einer 1-Dollar-Note Hollerith gründete 1896 die Tabulating Machine Company. Fusionen führten 1924 zur IBM.
Z3 nach Konrad Zuse • • •
erster programmierbarer Computer der Welt Schaltelemente waren Relais. 1944 das amerikanische Gegenstück Mark I nach Howard Aikens
1.1.2 Die Rechnergenerationen Die im zweiten Weltkrieg entwickelten Rechner werden heute der Vorgeneration zugerechnet (bis 1946). In Deutschland „Z3“ (Konrad Zuse, 1941) Anzahl der Additionen pro Sekunde: Anzahl der Multiplikationen pro Sekunde:
20 15
In Amerika „Mark1“ (Howard Aikens, 1944) Anzahl der Additionen pro Sekunde: Anzahl der Multiplikationen pro Sekunde:
3 0.16
4
1 Grundprinzipien der Datenverarbeitung
Für die Entwicklung an der Z4 gründete Konrad Zuse noch während des Krieges die erste Computerfirma der Welt. Das Kernteam bestand aus einem Konstrukteur, frisch aus der Nervenheilanstalt, einem blinden Programmierer und einem vorbestraften Buchhalter. Übersicht über die Rechnergenerationen Generation
Hardwarebeispiele
Technologien
Speicherkapazität/ Verarbeitungsgeschwindigkeit
Software: Sprache/ Betriebssystem
1. 1946 bis 1958
ENIAC Z22 (Zuse) UNIVAC IBM 650 SIEMENS 704
Elektronenröhren
0.02 MIPS/
Maschinensprache/
1–2 KByte
_________
IBM 1400 AEG TR CDC 6600 SIEMENS-2002
Transistoren
0.1 MIPS/
Assembler, FORTRAN/
Kernspeicher
32 KByte
IBM /370 DEC PDP-11 SIEMENS-7000 Cray 1
ICs
5 MIPS/
Halbleiterspeicher
1–2 MByte
PC Cray XMP Sperry 1100 IBM 309x DEC VAX
Mikroprozessoren
50 MIPS/
Optische Speicher
8–32 MByte
Workstations Hochleistungs-PC
Pentium IV Computer-Netze
1 000 MIPS GByte
Netzsoftware, Objektorientierte Sprachen: C++, LabVIEW/ UNIX/Linux Windows XP
supraleitende Keramiken, Nanotechnik
> 10 000 MIPS viele TByte
?
2. 1959 bis 1964
3. 1965 bis 1980
4. 1981 bis heute
Gegenwart
5. Entwicklung der Nanocomputer Zukunft Quantencomputer
Erläuterungen
Trommelspeicher
Stapelverarb./ Mehrprogrammbetrieb div. Hochsprachen: C, Pascal, .../ Multiuserdialog Sprachen der 4. Generation CodeParallelisierung
MIPS =
Megainstructions per Second (Millionen Befehle pro Sekunde)
KByte =
Kilobyte (1 024 Byte, siehe Teil III)
MByte =
Megabyte
GByte =
Gigabyte
Tbyte =
Terabyte
1.1 Historische Entwicklung der Datenverarbeitung
5
1.1.3 Computer und Science Fiction Der erste Großrechner der Welt hieß ENIAC (1946). Dieses Monstrum mit 18 000 Röhren wog nicht weniger als 30 Tonnen. Er konkurrierte noch mit Relaisrechnern wie der Z5, die zwar langsamer, aber zuverlässiger waren. Die Autoren von Zukunftsromanen glaubten damals mit Recht, dass es bald immer bessere Computer geben würde. In einem wichtigen Punkt allerdings irrten sie: Je leistungsfähiger ein Rechner, umso größer muss er wohl sein, so dachten sie. Clifford D. Simak veröffentlichte 1949 die Geschichte „An der Grenze“. Die Hauptrolle spielte ein Computer, der so groß ist wie die ganze Erde. Noch 1966 hieß ein anderer Science Fiction Computer „Colossus“, auch ein Riese, wie schon sein Name verrät (verfilmt als „Colossus: The Forbin Projekt, USA 1969). Die Wirklichkeit kam ganz anders: mit rasantem Tempo wurden die Computer immer besser und schneller. Dabei nahm ihre Größe nicht zu, sondern ab. Der Grund: immer kleinere und schneller Bauteile wurden erfunden. Die Erfindung des Transistors und später des Chips (IC) revolutionierte die Elektronik. Kein Science Fiction Autor hat diese Entwicklung vorausgeahnt. Mehr Glück hatten sie mit den Robotern. Science Fiction Autoren haben sogar interessante Beiträge zur Robotergeschichte geleistet. Im Jahre 1922 erschien in Prag das Theaterstück „WUR“. Karel ýapek, der Autor, ist der Urheber der Bezeichnung „Roboter“, denn WUR bedeutet „Werstands Universal Robots“ und handelt von einer Fabrik, die massenweise Roboter herstellt. Den Titel „Miss Robot“ verdient bis heute das elgante Metallgeschöpf aus dem Fritz LangFilm „Metropolis“ (D 1927) nach dem Drehbuch Thea von Harbous. Der Traum von künstlicheren Helfern ist jedoch viel älter. An eine alte Sage aus dem jüdischen Prag knüpft der Roman „Der Golem“ von Gustav Meyrink (1915) an. Hundert Jahre zuvor erschien in den „Nachtstücken“ von E.T.A. Hoffmann (1815) die Geschichte „Der Sandmann“. Dort tritt ein menschenähnlicher Automat, die Puppe Olimpia, auf. Sie spielt auch in der Jacques-Offenbach-Oper „Hoffmanns Erzählungen“ eine Hauptrolle. Um 1900 hielten die Maschinenmenschen auch Einzug in die triviale Unterhaltungsliteratur. Ein Beispiel ist der Roman von John Merriman „Die künstlichen Menschen“ aus der fünfbändigen Reihe „Thomas Alva Edison der große Erfinder“ (1908). Einen sehr interessanten Beitrag zur Roboterforschung leistete der amerikanische Schriftsteller Isaac Asimov, der 1940 in seiner Zukunftserzählung „Ich, der Robot“ seine drei Robotergesetze aufstellte:
1.
Ein Roboter darf einen Menschen nicht verletzen oder durch Untätigkeit zulassen, dass ein Mensch zu Schaden kommt.
2.
Ein Roboter muss den Befehlen gehorchen, die er von Menschen erhalten hat, mit Ausnahme solcher Befehle, die zu dem ersten Gesetz in Widerspruch stehen.
3.
Ein Roboter muss seine eigene Existenz schützen, solange dieses nicht zu dem ersten oder zweiten Gesetz im Widerspruch steht.
Vor allem das 1. Gesetz ist in der Praxis schwer umzusetzen, da es keine absolut sicheren technischen Systeme gibt. Menschen sind bereits Opfer von Unfällen mit Industrierobotern geworden. Außerdem haben die Schriftsteller sich wieder geirrt: die echten Roboter sehen
6
1 Grundprinzipien der Datenverarbeitung
nicht menschenähnlich aus. Solche Roboter wurden bisher nur für Ausstellungen oder als Spielzeuge gebaut. Roboter, wie sie heute vieltausendfach in der Industrie eingesetzt werden, gleichen eher riesenhaften Armen. Gebaut werden sie für spezielle Aufgaben, z. B. schweißen sie Karosserieteile in Autofabriken zusammen. Herz und Hirn eines realen Roboters ist ein kleiner Mikrocomputer mit einem Steuerungsprogramm. Spezielle „Sensoren“ erlauben es dem Roboter, zu „fühlen“ oder gar zu „sehen“, je nach seiner Aufgabe. Das Programm wertet alles aus. Es erteilt dann die notwendigen Befehle an die „Aktoren“. Solche Aktoren bewegen z. B. eine „Eisenhand“ mit einem Lackiergerät für Autos.
Fazit
Nur selten gelingt es, Entwicklungen einigermaßen zutreffend vorherzusehen. Weder Wissenschaftler, noch Schriftsteller oder Politiker sind auf diesem Gebiet sonderlich erfolgreich. Forschung lässt sich nur in begrenztem Maße sinnvoll planen: was heute sonnenklar erscheint, kann morgen Schnee von gestern sein.
Die Vorstellung von beseelten Computern und menschenähnlichen Robotern hat bis heute nichts von ihrer Faszination eingebüßt. Und so entstehen immer noch Bücher und v.a. äußerst erfolgreiche Filme zu diesen Themen. Herausragend sind „2001 – Odyssee im Weltall“ (E 1968, menschlich fühlender Computer) und „Bladerunner“ (USA 1982, dürfen wir denkende und fühlende Androiden als Sklaven halten?). Glauben wir Filmen wie „Welt am Draht“ (D 1973) oder „The Matrix“ (USA 1999), so sind wir selbst nur Teil einer Computersimulation einer höheren Intelligenz.
1.2 Funktion und Aufbau eines Rechners 1.2 Funktion und Aufbau eines Rechners
Ab Mitte der 40er Jahre entwickelte John von Neumann ein theoretisches Rechnermodell. Seine Vorschläge (Entwicklung und Ausnutzung neuerer mathematischer Maschinen, 1954) lauteten: Rechner sollen nicht mehr von „außen“ mit Lochstreifen gesteuert werden, sondern die Programmbefehle sind wie Daten in den Zentralspeicher zu laden (Geschwindigkeitsvorteile), Einführung bedingter Befehle (wenn A > 0 dann ...), damit höhere Flexibilität Von Neumann stellte folgendes, bis heute gültiges Modell eines Rechners auf, das ebenfalls das EVA-Prinzip widerspiegelt. In aktualisierter Form lässt es sich so schematisieren:
1.2 Funktion und Aufbau eines Rechners
Programm
7
Daten
Eingabeeinheiten
Zentraleinheit Zentralspeicher
Prozessor periphere Speicher
Leitwerk
Dialogeinheiten
Rechenwerk
Ausgabeeinheiten
Von-Neumannsches-Rechnermodell
Dieses Modell gilt für alle sequentiell arbeitenden Computer. Das sind Rechner, die ein Programm der Reihe nach, Schritt für Schritt, abarbeiten. Dazu gehören, mit Modifikationen, auch PC. Am Beispiel eines PC kann man sich veranschaulichen, welche Komponenten den Funktionsblöcken des von-Neumann-Modells entsprechen (→ siehe Übungsaufgaben 1.3). So genannte Parallelrechner, die mehrere Prozessoren besitzen, entsprechen nicht mehr dem vonNeumann-Prinzip. Mit dem Pentium entwickelt sich auch der PC immer mehr in Richtung Parallelarchitektur. Auf diese speziellen Rechner soll hier jedoch nicht näher eingegangen werden. Wir wollen nun die Zentraleinheit eines „einfachen“ Rechners gewissermaßen unter der Lupe betrachten.
8
1 Grundprinzipien der Datenverarbeitung
Einfaches Modell derZentraleinheit Zentralspeicher Prozessor (CPU)
Adr. 0 1
Leitwerk
2 3
Rechenwerk
Bus
Datenregister Steuerregister Programmschrittzähler Status(Flag)register N
Einfaches Modell der Zentraleinheit
Ein Prozessor – heute meist als Mikroprozessor realisiert – besitzt neben Leit- und Rechenwerk noch einige Register, sozusagen als „Privatspeicher“. Gemäß dem von-Neumann-Modell werden sowohl das Programm als auch die zu verarbeitenden Daten in den Zentralspeicher geladen. Der Prozessor hat über ein System von Leitungen, den Bus, Zugriff auf diesen Speicher. Weil der Computer ein digital arbeitender Automat ist, sind alle Programmbefehle (Maschinenbefehle) binär codiert, d. h. sie bestehen aus Folgen von Nullen und Einsen. Im 2. Band werden wir näher darauf eingehen. Das Programm wird sequentiell, Maschinenbefehl für Maschinenbefehl, vom Leitwerk interpretiert und ausgeführt. Bei arithmetischen und logischen Operationen zieht es das Rechenwerk zu Hilfe. Dieses wiederum ist beispielsweise in der Lage, zwei Daten zu addieren. Im Allgemeinen müssen diese zuvor vom Zentralspeicher über den Datenbus in die Datenregister transportiert werden. Das Ergebnis kann später auf dem gleichen Weg zurück in den Speicher gebracht werden. Den Zentralspeicher kann man sich als ein „überhohes“ Schubladenelement vorstellen, dessen einzelne Schubladen Daten oder Programmbefehle enthalten können. Jede „Schublade“ (jeder Speicherplatz) wird über seine numerische Adresse angesprochen. Das geschieht per Adressbus. Ein Speicherplatz kann 1 Byte (8 Bit) aufnehmen. Längere „Worte“ belegen mehrere Speicherplätze, typischerweise 16, 32 oder 64 Bit, entsprechend 2, 4 oder 8 Byte.
1.2 Funktion und Aufbau eines Rechners
9
Das Programm wird mit Hilfe des Programmschrittzählers verwaltet. Dieses spezielle Steuerregister enthält stets die Speicheradresse, unter welcher der Maschinenbefehl zu finden ist, der als nächster vom Leitwerk ausgeführt werden muss. Zur Speicherung des augenblicklichen Prozessorzustands dient das Zustands- oder Flagregister (Flag = Flagge). Die einzelnen Flags zeigen an, ob beispielsweise das Ergebnis der letzen arithmetischen Operation Null ergab (Zero Flag), oder ob ein arithmetischer Übertrag notwendig ist, weil das „zu große“ Ergebnis nicht vollständig in ein Datenregister passt (Carry Flag). Einige Prozessoren besitzen weitere Steuerregister. Ein PC, wie er am Arbeitsplatz oder zu Hause steht, ist heute typischerweise so konfiguriert: Motherboard mit Pentium- oder AMD-Prozessor; 128, 256, 512 oder 1024 MB RAM-Speicher PCI-Bus 100 bis 300 GB-Festplatte; 3 ½“-Diskettenlaufwerk (nicht mehr immer vorhanden); CDRW/DVD-Laufwerk Tastatur; Maus; evtl. Scanner Tintenstrahl- oder Laserdrucker 17“ RGB-Monitor oder 15“ LCD-Flachbildschirm (TFT Monitor) Soundkarte mit Lautsprechern Internet-Zugang über Modem (analog) oder ISDN-Karte (digital) oder NetzwerkKarte (100 MBit) + DSL-Modem (digital, Breitband) ggf. Netzwerkkarte für Intranet-Zugang diverse Schnittstellen (V.24, PS/2, Parallel, USB, Firewire) Alle externen Einheiten sind über Schnittstellen mit der Zentraleinheit verbunden. Der Drucker ist meist über die USB- oder die parallele (Centronics-) Schnittstelle angebunden, die Maus über die PS/2- oder USB-Schnittstelle. Für Bildschirm, Tastatur und externe Speicher existieren spezielle Schnittstellen. Wer heute einen Computer erwirbt, wird sich in der Regel nicht mit der bloßen Hardware zufrieden geben. Wenn der Computer ein „IBM-kompatibler“ PC ist, ist das Betriebssystem, meist eine der Windows-Varianten, häufig vorinstalliert. Erst ein solches Betriebssystem macht für den Normalkunden einen Allzweckrechner zu einem brauchbaren Hilfsmittel. Das Betriebssystem gestaltet den Umgang mit der Computerhardware komfortabel. Ohne Betriebssystem wäre das Einlesen einer Tastatureingabe eine schwierige Aufgabe für einen Spezialisten. Das Betriebssystem „vermittelt“ zwischen der Hardware und der Anwendungssoftware (Spiele, Textverarbeitung, Datenbankprogramme, selbst geschriebene Programme). Wir können somit für ein Computersystem folgendes einfache Dreischichtenmodell aufstellen:
10
1 Grundprinzipien der Datenverarbeitung
ANWENDUNGSSOFTWARE Access Word Excel Power Point Eigene Programme ... BETRIEBSSYSTEM DOS UNIX Linux OS/2 Windows 98 Windows NT Windows 2000 Windows XP ...
+
SYSTEMSOFTWARE Compiler Diverse Tools (Werkzeuge)
HARDWARE Professor RAM-Speicherbausteine ROM-Speicherbaustein Controller-Bausteine Festplatte Memory-Stick Bildschirm Tastatur Netzwerkkarte Maus ...
Auf Betriebssysteme werden wir in Kap. 2 näher eingehen.
1.3 Aufgaben
11
1.3 Aufgaben 1.3 Aufgaben
1. Ordnen Sie die Bauteile eines modernen PC den Komponenten des von-NeumannschenRechnermodells zu.
PC Bauteil
von-Neumann-Modellkomponente
Bildschirm Tastatur Mutterplatine Disketten-Laufwerk Mikroprozessor RAM-Bausteine Maus Festplatte Scanner Modem Soundkarte Joystick ROM-Speicherbaustein Drucker Netzwerkkarte CD-ROM-Laufwerk 2. Welcher seiner historischen Vorgänger beeinflusste John von Neumann offensichtlich beim Entwurf seines Rechnermodells? 3. Beschreiben Sie, welche Schritte bei der Abarbeitung eines Subtraktionsbefehls notwendig sind.
12
2 Das Betriebssystem 2 Das Betriebssystem
In Kap. 1.2 stellten wir ein einfaches Dreischichtenmodell eines EDV-Systems vor: zwischen Hardware und Anwendersoftware ordneten wir das Betriebssystem ein. Unter einem Betriebssystem versteht man nach DIN „diejenigen Programme eines digitalen Rechensystems, die zusammen mit den Eigenschaften der Rechenanlage die Basis der möglichen Betriebsarten des digitalen Rechensystems bilden und insbesondere die Abwicklung von Programmen steuern und überwachen“. Infolgedessen umfasst das Betriebssystem nur die Basissoftware, die es einem Benutzer der Anlage erst ermöglicht, seine eigene (Anwendungs-)Software mehr oder weniger komfortabel ablaufen zu lassen. Der durchschnittliche Benutzer eines modernen Rechners sieht sich immer seltener mit der Hardware konfrontiert, umso mehr dagegen mit dem Betriebssystem (BS). Das BS entlastet den Benutzer von Routineproblemen. Typische Aufgaben sind: Verwalten des Zentralspeichers Starten und Beenden von Programmen Verwalten des peripheren Speichers (Festplatten und Disketten) Durchführung von Ein- und Ausgabeoperationen Bereitstellung von Dienstprogrammen (Kommandos)
2.1 Single- und Multitasking 2.1 Single- und Multitasking
BS lassen sich grob in Singletasking- und Multitasking-Systeme unterteilen. Während erstere ein Programm komplett abarbeiten, bevor das nächste gestartet wird, unterstützen letztere die „gleichzeitige“ Ausführung mehrerer Programme. Beim kooperativen Multitasking unterbricht sich eine Anwendung selbst, um einer anderen vorübergehend den Vortritt zu lassen. Beim echten (preemtive) Multitasking ist die Verteilung der Rechenzeit auf die einzelnen Programme (genauer: Tasks oder Prozesse) Aufgabe einer Komponente des Betriebssystems, des Schedulers. Dieser teilt jedem Prozess eine Zeitscheibe zu. Ist diese abgelaufen, wird der Prozess unterbrochen, wobei alle Prozesszustände gesichert werden, und der nächste kommt an die Reihe. In der Regel sind die Zeitscheiben gleich groß, bei einigen BS lassen sich Prioritäten vergeben, die über breitere oder schmalere Zeitscheiben realisiert werden können. Wichtige Betriebssysteme Singletasking
Kooperatives Multitasking
Preemtive Multitasking
MS-DOS
Windows 3.1
Windows 98
div. μC-Monitore
Windows 3.11
Windows NT Windows 2000 Windows XP OS/2 Warp3 UNIX Linux
2.1 Single- und Multitasking
13
Betrachten wir zunächst das vergleichsweise einfach gestaltete Singletasking-BS MS-DOS (Microsoft-Disk Operating System). Es ist zugeschnitten auf die INTEL-Prozessorlinie 80(X)86, denn es ist in der Assemblersprache dieser Prozessoren programmiert. Das wiederum hat auch Vorteile: DOS ist sehr kompakt und schnell. Wegen der starken Verbreitung der „IBMkompatiblen" PC wurde DOS zu einem Industriestandard (nicht genormter Standard), der jedoch mittlerweile von Windows abgelöst wurde. Da DOS für jedermann zugänglich dokumentiert, modellhaft aufgebaut und daher verhältnismäßig leicht durchschaubar ist, eignet es sich als Lehrbeispiel für ein einfaches Betriebssystem. Der Aufbau von DOS folgt einem Schichtenmodell, das sich stark abstrahiert so darstellen lässt: Anwendungen Benutzeroberfläche DOS BIOS Hardware
Die oberste Schicht, die Benutzeroberfläche, ermöglicht den Zugriff auf die Dienstprogramme. Darunter versteht man Kommandos wie “copy“ (Kopiere Datei) und “del“ (Lösche Datei). Außerdem ermöglicht sie den Start eigener Anwendungen. Die übrigen genannten Aufgaben des Betriebssystems fallen den Schichten DOS und BIOS zu. Als Schnittstelle zu den Anwendungsprogrammen existieren so genannte Systemaufrufe (system calls). Unter DOS werden diese durch Softwareinterrupts realisiert. Das DOS erschließt die Rechnerhardware auf logischer Ebene, z. B. den Plattenspeicher über Dateinamen. DOS selbst bedient sich seinerseits des BIOS (Basic Input Output System), ein in jedem PC enthaltene Software, die den Hardwarezugriff auf die physikalischer Ebene ermöglicht, z. B. den Plattenspeicherzugriff über Spuren und Sektoren. Das BIOS ist somit hardwareabhängig, was dem Benutzer allerdings verborgen bleibt, solange er sich der Systemaufrufe bedient. Die klassische DOS-Benutzerschnittstelle ist Kommando-orientiert (Zeilen-orientiert): Der Benutzer tippt über die Tastatur ein Kommando ein, das anschließend abgearbeitet wird. Danach gibt der Kommando-Interpreter erneut den Prompt aus, um die Bereitschaft zur Entgegennahme des nächsten Kommandos zu signalisieren. Ebenfalls klassischerweise Kommando-orientiert ist UNIX (Universal Exchange). UNIX ist das Ergebnis des Versuchs, Betriebssysteme hardwareunabhängig (UNIX ist in C geschrieben, C wurde eigens für UNIX entwickelt) zu gestalten, d. h. ein und dasselbe Betriebsystem ist auf verschiedenen Rechnersystemen mit unterschiedlichen Prozessoren lauffähig. UNIX stellt allerdings kein „einfaches“ Betriebssystem wie DOS dar, denn es erlaubt neben Mehrprogramm- auch Mehrbenutzer-Betrieb (Multitasking/Multiuser). Wichtige Leistungen sind: Systemaufrufe, um Hardwarefunktionen leichter zugänglich zu machen Ein hierarchisches (baumartiges) Dateiensystem (→ siehe Kap. 2.2) Dienstprogramme (Befehle), die man in einer Kommandozeile aufrufen (starten) kann Möglichkeit der Kommandoverkettung Ein-/Ausgabe-Umlenkung Eine Prozedursprache zur Erstellung eigener Superkommandos.
14
2 Das Betriebssystem
DOS hat sich in seiner Struktur weitgehend am älteren UNIX orientiert. Die Kommandos unterscheiden sich jedoch: Beispiele für Kommandos unter DOS und UNIX DOS
UNIX
Bedeutung
dir
ls –l
Inhaltsangabe des aktuellen Verzeichnisses
copy dat1 dat2
cp dat1 dat2
Kopiere Quelldatei dat1 auf Zieldatei dat2
type a.txt
cat a.txt
Ausgabe der Datei a.txt auf den Bildschirm
Besonders bei UNIX spielen selbst geschriebene “Super-Kommandos“, die sogenannte ShellProzeduren, eine bedeutende Rolle. Dazu stellt das BS eine Interpreter-Sprache zur Verfügung. Dabei werden die Programme nicht in die Maschinensprache übersetzt sondern Befehl für Befehl vom BS interpretiert und ausgeführt. In eine solche Prozedur können BS-Kommandos und eigene Programme integriert werden. Dadurch lassen sich komplizierte Abläufe, wie periodische Datensicherungen nach gewünschten Kriterien, automatisieren. Shell-Prozeduren können sehr komplex und entsprechend umfangreich sein. Nachstehend eine Mini-Prozedur als Beispiel: Beispiel # Diese UNIX Shell-Prozedur laeuft so lange, bis ein existierender Dateiname # ueber die Tastatur eingegeben wird until test –f “$datei_name“ do echo “Eingabe: \c“ read datei_name done echo “Datei $datei_name existiert“
■
Von UNIX gibt es zahlreiche Varianten, die populärste ist LINUX, das kostenlos erhältlich und somit besonders für Hochschulen und fortgeschrittene Privatnutzer äußerst attraktiv ist. Inzwischen haben sich Windowsoberflächen zum Standard entwickelt, zumindest in der PCWelt. Während Windows 3.11 noch einen Aufsatz auf DOS darstellt, sind Windows 98, XP und NT eigenständige Betriebssysteme. Für UNIX und LINUX existieren verschiedene Oberflächen wie X-Windows mit KDE als Alternative zu den Standardsshells (Shell = Schale (Benutzeroberfläche)). Bei den Windows-Oberflächen kommuniziert man über Fenster mit dem BS und den Anwendungsprogrammen. Neben der herkömmlichen alphanumerischen Eingabe per Tastatur wird auch die grafische Eingabe, meist per Maus, unterstützt. Fenster können geöffnet, vergrößert, verkleinert (bis auf Icon-Größe), verschoben und wieder geschlossen werden. Zusammengehörende Gruppen von Funktionen werden anwendungsbezogen über Menüs (starr, pulldown oder popup) ausgewählt.
2.1 Single- und Multitasking
15
Vor- und Nachteile von Windows-Oberflächen Vorteile – einheitliche Benutzerschnittstelle für alle Programme – standardisierte Zwischenablage (clipboard) für den Datenaustausch zwischen verschiedenen Programmen Nachteile – starke Inanspruchnahme von Prozessorleistung, Haupt- und Plattenspeicher – keine Shellprozeduren zur Automatisierung wiederkehrender komplizierter Abläufe
Windows 98, 2000, ME, NT und XP sind 32-Bit-Betriebssysteme, welche die Leistungsfähigkeit der Intel-Rechner erheblich besser nutzen als beispielsweise DOS. Leider beanspruchen sie aber auch sehr viel Leistung für sich selbst. Windows 98 ist in erster Linie für den Privatnutzer konzipiert. So gibt es keine Benutzerverwaltung mit der Möglichkeit des Dateienschutzes vor anderen Benutzern. Es ist teilweise noch in 16-Bit-Technik realisiert und daher langsamer als NT oder XP. Speicherschutzverletzungen alter Windows 3.x Anwendungen können zu Abstürzen führen. Windows 98 bietet auch noch, wie unter DOS, die Möglichkeit, direkt auf Hardware-Komponenten zuzugreifen. So kann man beispielsweise den System-Timer umprogrammieren oder den Tastatur-Interrupt abschalten. So etwas ist in der Regel „tödlich“, kann jedoch besonders bei hardwarenahen technischen Anwendungen gewünscht und hilfreich sein. Windows NT ist das leistungsfähigere Profi-System: volle 32-Bit-Architektur, damit schneller als Windows 98 Mehrbenutzerverwaltung durch Administrator, der die Benutzerrechte verwaltet unterstützt Multiprocessing (Systeme mit mehreren Prozessoren) getrennte Speicherbereiche für BS und Anwendungsprogramme; Speicherschutzverletzungen werden abgefangen bessere Schichtentrennung als bei Windows 98, daher im Prinzip Prozessorunabhängig kein direkter Zugriff von Anwendungsprogrammen auf die Hardware möglich (s. o.) in Workstation- und Server-Version erhältlich, damit zur Verwaltung großer Netzwerke gut geeignet. Windows 2000 und XP führen die beiden Windows-Linien mehr und mehr zusammen. Windows XP verschickt ungefragt Daten über das Internet an Microsoft. Möchten Sie das verhindern, sollten Sie ein entsprechendes „Antispionage-Programm“ installieren und aktivieren. Für sehr flexible Anwendungen, wie sie v. a. für die Forschung typisch sind, bleiben häufig zeilenorientierte Shells, mit der Möglichkeit, Prozeduren zu schreiben, deutlich überlegen. In diesem Bereich ist UNIX bzw. Linux erste Wahl. Am unteren Ende der Leistungsskala für BS sind sog. Monitore angesiedelt. Das sind Minibetriebssysteme, meist für den Einsatz in Mikrocontrollern (μC). Ihr Umfang beträgt etwa 1 bis 8 KByte. Sie sind komplett auf einem EPROM untergebracht. Sie ermöglichen in erster Linie das Herunterladen von Programmen aus dem Software-Entwicklungs-Rechner in den Controller (Downloading). Außerdem bieten sie einfache Testfunktionen: Anschauen und Verändern von
16
2 Das Betriebssystem
Speicherstellen und Registern, Setzen von Breakpoints und Singlestep-Betrieb. Monitore kommunizieren über die serielle Schnittstelle, meist mit einem PC, auf dem eine Terminalemulation läuft. Nach Abschluss der Entwicklungsarbeiten und Abspeicherung der Software auf einem EPROM verschwinden die μC häufig in einem Gerät (Waschmaschine, Auto, Aufzug). Man spricht dann von Embedded Systems. Einen Sonderfall bei den Multitasking-Systemen im technischen Bereich bilden die Echtzeitsysteme. Manchmal erfordern bestimmte Tatbestände eine Reaktion des Rechners innerhalb einer bestimmten (kurzen) Zeit. Beispiele: – ein Messgerät möchte die aktuellen Daten übermitteln – ein Reaktor-Überwachungsgerät löst Alarm aus Ein gewöhnlicher Zeitscheiben-Scheduler kann darauf nicht angemessen reagieren, wenn das entsprechende Programm, welches das Messgerät oder den Alarm bedienen soll, gerade nicht an der Reihe ist. Dagegen reagiert ein Echtzeitsystem innerhalb einer garantierten Zeitspanne. Beim Echtzeit-BS OS-9 beispielsweise funktioniert das so: Das Gerät, das Aufmerksamkeit verlangt, löst einen Impuls (Interrupt-Request) aus. Das BS beendet die aktuelle Zeitscheibe ordnungsgemäß, speichert deren Status ab und weckt die Service-Routine auf, die sich bisher im Zustand "schlafend" befand. Die dafür benötigte Zeitspanne ist die Reaktionszeit des Echtzeit-BS. In der Regel wird die Service-Routine nun ohne Unterbrechung komplett abgearbeitet, bis sie sich selbst wieder „schlafen legt“. Nun geht der normale Nicht-Echtzeit-Betrieb weiter bis zum nächsten Interrupt. Aufgrund des hohen Verwaltungsaufwands sind Echtzeitsysteme nicht unbedingt sehr schnell, sie garantieren lediglich eine maximale Reaktionszeit. Liefert etwa der Paketdienst A jedes Paket ohne Ausnahme spätestens innerhalb von sieben Tagen beim Empfänger ab, so ist das eine Echtzeitgarantie. Der Paketdienst B liefert praktisch immer innerhalb von drei Tagen aber ohne feste Zusage. B ist also kein „Echtzeit-Paketdienst“, in Wirklichkeit aber fast immer schneller als A. Man sollte bei technischen Anwendungen immer sehr genau prüfen, ob man tatsächlich ein Echtzeit-BS benötigt. Häufig reicht ein schneller Rechner unter einem „normalen“ BS aus. Falls man gar kein Multitasking benötigt, kann ein Singletasking-BS wie DOS gute Dienste leisten, denn bei solchen Systemen kommt das Echtzeitproblem erst gar nicht auf.
2.2 Dateien und Dateiensysteme 2.2 Dateien und Dateiensysteme
Eine Datei besteht in der Regel aus mehreren Datensätzen, bei Personendaten z. B. Angaben über Namen und Anschriften dieser Personen. Oft vergleicht man eine Datei mit einem Karteikasten, einen Datensatz mit einer Karteikarte.
Unter einer Datei versteht man eine Menge logisch zusammengehörender Daten.
In seinen ersten Versionen besaß beispielsweise DOS ein ungegliedertes Dateiensystem, d. h. alle Dateien ordneten sich gleichwertig auf einer Ebene an. Man spricht von einem "flat-filesystem". Das war durchaus sinnvoll, weil als Datenträger lediglich Disketten dienten, die darüber hinaus nur Kapazitäten im Kilobyte-Bereich aufwiesen, so dass eine Diskette nur eine sehr begrenzte Zahl von Dateien aufnehmen konnte. Wollte der Benutzer Ordnung in seine
2.2 Dateien und Dateiensysteme
17
Dateiensammlung bringen, so konnte er dies über eine Vielzahl von Disketten erreichen: Die eine enthielt nur C-Programme, die andere ausschließlich Liebesbriefe. Mit den ersten Festplatten, die bereits 10 Megabyte speichern konnten, erschien ein flat-filesystem als zu unübersichtlich. Ab Version 2.0 übernahm DOS von UNIX das hierarchische Dateiensystem, dessen Struktur mit einem Baum vergleichbar ist. Zu diesem Zweck wurden Dateiverzeichnisse (directories, bei Windows auch „Ordner“ genannt) eingeführt, die die Funktion der Äste im Dateienbaum einnehmen. Die Dateien stellen die Blätter dar. Einen Stamm gibt es nicht, wohl aber eine Wurzel (root). Diese ist ebenfalls ein Verzeichnis, dass sich aber auf doppelte Weise auszeichnet: Es ist einzigartig (ein Baum hat viele Äste aber nur eine Wurzel) und es repräsentiert gleichzeitig die unterste Hierarchieebene. Die Verzeichnisse stellen nun die Verbindung zwischen einer Datei und ihrem Namen her. Jede Datei steht in genau einem Verzeichnis und ist nur über dieses eindeutig ansprechbar. Inzwischen verwenden alle modernen BS solche hierarchischen Dateiensysteme. In aller Regel wird der Dateienbaum auf dem Kopf stehend, d. h. mit der Wurzel nach oben, dargestellt. Das folgende Beispiel zeigt das Gerüst (nur Wurzel und Äste, keine Blätter) eines möglichen Dateienbaums:
Hierarchisches Dateiensystem (Beispiel)
In dieser Darstellung ist die Hierarchie gut zu erkennen. Die Verzeichnisse “WINDOWS“, “C“, “TEXT“ und “PASCAL“ hängen direkt an der Wurzel (root). Die “Äste“ “QUELLEN“ und “EXE“ hängen an dem “Ast“ “C“, usw. Für die Verzeichnisnamen gelten die gleichen Regeln wie für die Namen der "normalen" Dateien unter dem jeweiligen BS. Lediglich die Wurzel wird immer durch den Backslash “\“ (oder Slash “/“ bei UNIX) symbolisiert. Es können mehrere Dateien und sogar Verzeichnisse mit dem gleichen Namen vorkommen. Eindeutig werden sie erst mit ihrem Pfadnamen. Man unterscheidet
Absolute Pfadnamen
Relative Pfadnamen
erstrecken sich von der Wurzel bis zu der gewünschten Datei.
erstrecken sich relativ zum Arbeitsverzeichnis bis zu der gewünschten Datei.
18
2 Das Betriebssystem
Wir betrachten nun einen anderen Dateienbaum, der sogar mit ein wenig Laub versehen ist. Die Blätter (Dateien) sind durch runde Klammern symbolisiert, die Äste (Verzeichnisse) nach wie vor durch spitze Klammern. Bei modernen Betriebssystemen wie Windows können Dateinamen beliebig lang sein, bei DOS sind sie auf 8 Zeichen begrenzt.
Dateienbaum
< > = directory (Verzeichnis) ( ) = normale Datei Anhand von Beispielen wollen wir uns den Begriff des absoluten und relativen Pfadnamens klarmachen. Der absolute Pfadname der Datei “edv.dat“ lautet: \fhw\rh\et\edv.dat (DOS oder Windows), bzw. /fhw/rh/et/edv.dat (UNIX) Regel: Absolute Pfadnamen beginnen immer mit “\“ (Windows) oder “/“ (UNIX) dem Symbol für das Wurzelverzeichnis. Solche absoluten Pfadnamen können sehr lang und umständlich werden, deshalb kann man ein Verzeichnis seiner Wahl zum Arbeitsverzeichnis (working directory) bestimmen. Nehmen wir an, “rh“ sei Arbeitsverzeichnis, dann lautet der relative Pfadname von “edv.dat“: et\edv.dat oder bei UNIX et/edv.dat Regel: Relative Pfadnamen beginnen nie mit “\“ (oder “/“ bei UNIX).
19
3 Algorithmen und Struktogramme 3 Algorithmen und Struktogramme
Neben der technischen Seite weist die EDV eine logisch-mathematische auf. Bei ihr geht es um die Lösung konkreter Probleme mit Rechnern.
3.1 Algorithmen 3.1 Algorithmen
Möchte man ein Problem mit Hilfe eines Rechners lösen, ist zu prüfen, ob sich die Aufgabe in Algorithmen (Rechenregeln) formulieren lässt. Ein Algorithmus besteht aus elementaren Einzelschritten, diese müssen in einer bestimmten Reihenfolge ausgeführt werden, zahlenmäßig begrenzt und in endlicher Zeit abgearbeitet sein. Der Algorithmus selbst muss allgemeingültig und maschinell lösbar sein. Ist dies der Fall, kann man die Automatisierung des Problems in Angriff nehmen. Beispiel In einen Rechner soll eine unbestimmte Anzahl von ganzen Zahlen eingegeben werden. Die Aufgabe besteht darin, jeweils die Anzahl der positiven und der negativen Zahlen zu ermitteln und auszugeben. Die Verarbeitung soll enden, wenn eine “0“ eingegeben wird. Wir formulieren den Algorithmus zunächst umgangssprachlich: 1. Setze den Zähler der positiven Zahlen auf Null. 2. Setze den Zähler der negativen Zahlen auf Null. 3. Lies eine ganze Zahl ein. 4. Falls die Zahl kleiner als Null ist, erhöhe den Zähler der negativen Zahlen. 5. Falls die Zahl größer als Null ist, erhöhe den Zähler der positiven Zahlen. 6. Falls die Zahl nicht “0“ ist, gehe zurück nach 3. 7. Gib die Anzahl der positiven Zahlen aus. 8. Gib die Anzahl der negativen Zahlen aus. Diese Lösung erfüllt unsere Forderungen an einen Algorithmus (s. o.). Der Algorithmus besteht aus Befehlsfolgen (1., 2. und 7., 8.), Auswahlen (4. und 5.) sowie einer Schleife (3. bis 6.). Das sind die drei Grundstrukturen, aus denen sich jeder Algorithmus maximal zusammensetzen kann. ■
3.2 Struktogramme 3.2 Struktogramme
Eine umgangssprachliche Formulierung, wie im obigen Beispiel, kann bei derart überschaubaren Problemen durchaus sinnvoll sein, bei komplexeren Algorithmen ist sie zu unübersichtlich. Deshalb bedient man sich in der Informatik häufig einer formalisierten Darstellungsform, die man “Struktogramm“ nennt. Ein Struktogramm besteht aus einzelnen Strukturblöcken, die sich bausteinartig zu dem kompletten Struktogramm zusammensetzen. Es gelten folgende „Grundgesetze“:
20
3 Algorithmen und Struktogramme
1. Jeder Strukturblock ist rechteckig. 2. Jeder Block hat nur einen Eingang (oben) und einen Ausgang (unten). 3. Blöcke stehen entweder untereinander oder sie sind vollständig ineinander enthalten (aus 1. und 3. → das gesamte Struktogramm ist ebenfalls rechteckig). 4. Strukturblöcke sind knapp, aber verständlich zu kommentieren.
eintretende Kante
STRUKTURBLOCK
austretende Kante Strukturblock
Nachstehende Regeln sind nicht zwingend, sie sollten jedoch ebenfalls befolgt werden:
5. Kein Struktogramm sollte länger sein als eine Seite, daraus folgt: 6. Teilprobleme sollten als separate Modulblöcke ausgegliedert werden.
Wir unterscheiden folgende Grundtypen von Strukturblöcken, mit denen sich jeder Algorithmus formulieren lässt:
1. Sequenzblock
=
Folge (Sequenz) von unbedingten Anweisungen (mindestens eine Anweisung)
2. Selektionsblock
=
alternative Ausführung von Anweisungen (Auswahl)
3. Iterationsblock
=
wiederholte Ausführung von Anweisungen (Schleife)
4. Modulblock
=
black box für separat erläutertes Teilproblem (Modul)
Ein Modulblock besteht wiederum aus Sequenzen, Selektionen und Iterationen.
3.2 Struktogramme
21
Die Selektion gibt es in zwei Varianten, von denen die Alternative die elementare ist. Ein eigener Strukturblock existiert jedoch auch für die Fallfolge oder Mehrfachauswahl. Diese ließe sich aber auch durch ineinander geschachtelte Alternativblöcke ersetzen. Sequenz (Folge) Beschreibung der Programmschritte In diesem Block steht eine Folge der Programmschritte, die ohne “wenn und aber“ in dieser Reihenfolge auszuführen sind. Beispiel Setze den Zähler der positiven Zahlen auf Null. Setze den Zähler der negativen Zahlen auf Null. ■ Selektion (Verzweigungen) a) Alternative Bedingung 1. Alternative
2. Alternative
Es handelt sich um eine klare “entweder-oder“-Entscheidung. Ist die Bedingung wahr, wird der linke Block durchlaufen, ist sie unwahr, der rechte. Das folgende Beispiel prüft, ob “Zahl“ größer als Null ist. Ist diese Bedingung im aktuellen Fall wahr, wird “Zähler“ um eins erhöht. Beispiel Zahl < Null ja
Zähler = Zähler+1
nein
22
3 Algorithmen und Struktogramme
Wie dieses Beispiel zeigt, kann einer der beiden Alternativblöcke durchaus leer sein. Das be■ deutet, dass in diesem Fall nichts geschieht. b) Fallfolge (Mehrfachauswahl) Mehrfachauswahl mit Fehlerfall
Fall 1
Fall 2
Fall 3
Sonstfall
Fallfolgen eröffnen mehrere Alternativen. Sie eignen sich besonders gut zur Darstellung von Auswahlmenüs. Stets sollte man einen Sonstfall vorsehen, der immer dann greift, wenn keiner der gewünschten Fälle zutrifft. Der Sonstfall, manchmal auch als Fehlerfall bezeichnet, fängt alle „unerlaubten“ Fälle, z. B. eine falsche Eingabe, ab. Als Beispiel sollen mögliche Operationen auf eine Datenbank dienen. Datenbanken bestehen aus einer Vielzahl von Sätzen, die bestimmte Eigenschaften von Personen oder Dingen beschreiben. Ein Satz aus einer Studentendatenbank enthält mit Sicherheit Elemente wie Matrikelnummer, Name und Adresse eines Studenten. Der Benutzer der Datenbank möchte Sätze lesen, ändern, hinzufügen und löschen. Das sind die möglichen Operationen. Beispiel (Datenbankoperation)
Benutzereingabe
´C´
´R´
Satz lesen
Satz ändern
´D´
Satz löschen
´A´ Satz anfügen
Sonstfall Ausgabe: ´unerlaubte Eingabe´ ■
Fallfolgen sind, wie schon gesagt, erweiterte Alternativen. Jede Fallfolge lässt sich, wenn auch etwas umständlicher, mit ineinander geschachtelten Selektionen darstellen. Iterationsblock (Schleife)
Bei den Iterationen unterscheiden wir wiederum zwei Typen: Schleife mit Kopfprüfung (abweisende Schleife) Schleife mit Fußprüfung (nicht-abweisende Schleife)
3.2 Struktogramme
23
a) Schleife mit Kopfprüfung Bedingung Schleifenkern oder Schleifenkörper
Diese Schleife wird ausgeführt, solange die Bedingung wahr ist. Ist diese zu keinem Zeitpunkt wahr, wird die Schleife niemals durchlaufen. In unserem Beispiel wird ein Zähler solange erhöht, wie er kleiner als ein vorgegebener Endwert ist. Der Schleifenkörper besteht aus zwei Schritten: Summe um Zähler erhöhen und Zähler um eins erhöhen. Der Schleifenkörper ist in diesem Beispiel eine Sequenz. Beispiel solange Zähler < Endwert Summe = Summe + Zähler Zähler = Zähler + 1
■
b) Schleife mit Fußprüfung Schleifenkern oder Schleifenkörper Bedingung
Auch diese Schleife wird ausgeführt, solange die Bedingung wahr ist. Da die Bedingung jedoch erst am Schluss eines Schleifendurchlaufs geprüft wird, kommt es in jedem Fall zu mindestens einem Durchlauf. Beispiel
Eingabe
solange Eingabe falsch ■
24
3 Algorithmen und Struktogramme
Schleifen mit Fußprüfung benutzt man gerne, um Eingabefehler zu verhindern. Der Benutzer wird solange zur erneuten Eingabe gezwungen, bis er eine gültige Eingabe macht. Modulblock
Man kann sich leicht vorstellen, dass Struktogramme, die länger sind als eine Seite, schnell unübersichtlich werden. Wir leiten daraus die Forderung ab: jedes Struktogramm sollte auf eine Seite passen. Das scheint schwieriger als gesagt, wenn man an einen komplexen, umfangreichen Algorithmus denkt. Den Ausweg bieten Modulblöcke. Teilalgorithmen werden einfach als „Blackbox“ ausgegliedert und dann im Detail auf einer gesonderten Seite erläutert.
Modulname Modulfunktion
Im Beispiel wird ein Sortiervorgang als „Blackbox“ ausgegliedert. An anderer Stelle ist hierfür ein eigenes Struktogramm zu erstellen. Beispiel
Sort Daten in absteigender Reihenfolge sortieren
■
Ein Struktogramm setzt sich nun aus mehreren Strukturblöcken zusammen. Das GesamtStruktogramm bleibt dabei stets rechteckig, d. h. verändert seine Breite während des Programms nicht. Die beiden senkrechten Begrenzungen bilden „die Schienen“ für die Strukturblöcke. Wir erinnern uns, dass die Strukturblöcke entweder aufeinander folgen oder vollständig geschachtelt sind. Zunächst ein kleines Beispiel:
3.2 Struktogramme
25
Beispiel Eingabe N Summe Lauf
= 0 = 0
solange Lauf 0 ja
zneg
nein
= zneg + 1 zpos
= zpos + 1
solange x ungleich 0 Ausgabe zpos Ausgabe zneg
Struktogramme sind unabhängig von einer bestimmten Programmiersprache, in der das Problem evtl. gelöst werden soll. Struktogramme dienen als Planungsinstrument (allgemeine Formulierung eines Algorithmus) und als sprachunabhängiges Dokumentationsmittel.
3.3 Aufgaben 3.3 Aufgaben
1. Analysieren Sie das Struktogramm von der vorherigen Seite. a) Wie viele Elementarblöcke enthält es? b) Benennen Sie die einzelnen Blöcke nach ihrer Art. 2. Formulieren Sie ein Struktogramm zur Berechnung der Fakultät einer positiven ganzen Zahl und führen Sie einen „Schreibtischtest“ mit verschiedenen Eingabewerten durch. Fakultät N = N * (N-1) * ... * 1; Def.: Fakultät 0 = 1. 3. Welche Aufgabe löst der folgende, als Struktogramm formulierte Algorithmus?
3.3 Aufgaben Hinweis:
27 Führen Sie einen „Schreibtischtest“ durch, indem Sie das Struktogramm mit unterschiedlichen Wertepaaren von x und y „durchlaufen“. Notieren Sie die schrittweisen Wertänderungen von x und y.
Eingabe: x Eingabe: y x < 1 oder y < 1 ja
nein solange x ungleich y Ausgabe: "falsche Eingabe"
x>y ja
nein x=x-y
Ausgabe: x
y=y-x
28
4 Programmiersprachen 4 Programmiersprachen
Sprachen lassen sich allgemein nach folgendem Schema klassifizieren:
Sprachen
natürliche Sprachen
formale Sprachen
... Umgangssprachen
Fachsprachen
Programmiersprachen
math. Formelsprache
...
Die Programmiersprachen zählen demnach zu den formalen, „künstlichen“ Sprachen. Auch wenn Sie es uns im Moment noch nicht glauben: Programmiersprachen sind erheblich leichter und schneller zu erlernen als Fremdsprachen!
4.1 Maschinen- und Hochsprachen 4.1 Maschinen- und Hochsprachen
Die Rechner der ersten Generation mussten mühsam in ihrer Maschinensprache programmiert werden, die aus einem reinen Binärcode (Folge von „0“ und „1“) besteht. Die Assemblersprache brachte die erste Erleichterung für den Programmierer. Maschinenbefehle konnten nun in halbwegs lesbarer Form programmiert werden, statt beispielsweise
Maschinenbefehl:
Assemblerbefehl:
Bedeutung:
1000010100110001
Add R3,R1
Addiere Reg.1 zu Reg. 3
Eine Assemblersprache verwendet also gedächtnisstützende Kürzel (mnemonics) statt Binärziffernfolgen.
4.1 Maschinen- und Hochsprachen
29
Da jeder Rechner – auch heute noch – ausschließlich seine eigene Maschinensprache versteht, muss ein Assemblerprogramm zunächst, vor seiner Ausführung, in die Maschinensprache übersetzt werden. Dies besorgt ein (käufliches) Programm, das verwirrenderweise ebenfalls „Assembler“ heißt. Aus einem Assemblerbefehl wird ein Maschinenbefehl.
Assembler Assemblerprogramm
Maschinenprogramm 1:1 Übersetzung
Maschinensprache und Assemblersprache gehören zu den maschinenorientierten Programmiersprachen, denn sie sind auf einen bestimmten Prozessortyp abgestimmt. Wie die folgende Übersicht zeigt, gibt es daneben die heute wesentlich häufiger eingesetzten problemorientierten Programmiersprachen:
Programmiersprachen
maschinenorientierte Sprachen
Maschinensprachen
Assemblersprachen
problemorientierte Sprachen
Universalsprachen
Spezialsprachen
FORTRAN PASCAL C . .
Lisp SQL Prolog . .
Problemorientierte Sprachen sind unabhängig von einem bestimmten Rechnertyp. Es besteht auch keine 1:1 Zuordnung zwischen einem Befehl in einer „höheren“ Sprache und einem Maschinenbefehl. Der Begriff „höher“ bezieht sich auf das Abstraktionsniveau, die Sprache „schwebt“ hoch über der Hardware. Man kann durchaus erfolgreich FORTRAN- oder PASCAL-Programme schreiben, ohne viel über den Aufbau und die Arbeitsweise von Rechnern zu wissen. Selbstverständlich müssen auch problemorientierte Programme vor ihrer Ausführung in die jeweilige Maschinensprache ihres Zielrechners übersetzt werden. Dies über-
30
4 Programmiersprachen
nimmt ein käufliches Softwareprodukt, der Compiler. Aus einem Hochsprachenbefehl entstehen N Maschinenbefehle, wobei N meistens größer als 1 ist.
Quellprogramm: Programm in einer problemorientierten Programmiersprache
Compiler Maschinenprogramm 1:N Übersetzung
Der Vorgang des Übersetzens heißt „compilieren“. Die wichtigsten problemorientierten Sprachen im Ingenieurbereich sind heute FORTRAN, PASCAL und C. FORTRAN ist die älteste Hochsprache überhaupt (seit 1954) und für Probleme der numerischen Mathematik nach wie vor unschlagbar. PASCAL (seit 1968) ist eine hervorragend strukturierte Sprache. Sie eignet sich wegen ihrer Modellhaftigkeit v.a. für die Ausbildung. Auf PC ist sie mit ihrem „Dialekt“ TURBO PASCAL weit verbreitet und sehr attraktiv, weil sie die Möglichkeiten des PC recht einfach erschließt. C ist eine echte Universalsprache. Bei hardwarenahen Problemen macht sie sogar der Assemblersprache Konkurrenz, in der Systemprogrammierung ist C die Nummer eins, und auch normale Anwenderprobleme lassen sich sehr gut lösen. C hat die höchste Verfügbarkeit (kein Computer ohne C-Compiler), CProgramme sind sehr leicht von einer Hardware auf eine andere übertragbar (portabel). Die drei genannten Sprachen gehören der 3. Sprachgeneration an, inzwischen gibt es auch Sprachen der 4. und 5. Generation mit noch höherem Abstraktionsniveau. Diese Sprachen sind oftmals objektorientiert (strenge Modularität, Einheit von Daten und Programmen). Anders als bei FORTRAN-, PASCAL oder C-Programmen lassen sich aus der Befehlsreihenfolge nicht immer Rückschlüsse auf die Verarbeitungsreihenfolge im Rechner ziehen. Der Algorithmus (das „wie“) tritt gegenüber dem Problem (das „was“) immer mehr in den Hintergrund. Man spricht deshalb auch von nicht-prozeduralen Sprachen. Die Sprachen der 4. Generation sind allerdings oftmals weniger universell, es sind Spezialsprachen für Spezialprobleme (z.B. PROLOG für Probleme der künstlichen Intelligenz und SQL als Abfragesprache für Datenbanksysteme). So finden nach wie vor alle Sprachgenerationen ihre Anwendungen, abhängig vom Problem. C++ als Erweiterung von C kann bereits als Sprache der 5. Generation (objektorientiert) betrachtet werden. Die Übersicht auf der folgenden Seite, die wir einer Werbung entnehmen, charakterisiert die verschiedenen Computersprachen ausgezeichnet.
4.1 Maschinen- und Hochsprachen
31
Wenn Programmiersprachen Autos wären ...
BASIC:
Eine Ente – weder modern noch besonders schnell, aber für jeden erschwinglich. Und manch einer, der sich daran gewöhnt hat, will gar nichts anderes haben.
GFA-BASIC:
Eine Ente, bei der die Rückbank einem Super-Turbo-EinspritzKompressor-Hochdruck-Hochleistungsmotor geopfert wurde.
PASCAL:
Entwurf eines amerikanischen Straßenkreuzers, der nur durch ein Versehen in die Serienproduktion gelangte
TURBO-PASCAL:
Eine verbesserte Version des amerikanischen Straßenkreuzers; neben dem praktischen Nutzen auch hervorragend zum Angeben geeignet. Passt aber leider in keine Parklücke.
MODULA II:
Wie PASCAL, aber mit dreifachen Sicherheitsgurten, seitlichen Stoßstangen und separatem Gaspedal für jeden der fünf Gänge.
ADA:
Ein als amerikanischer Straßenkreuzer getarnter Schützenpanzer.
FORTH:
Ein englischer Sportwagen aus den 60er Jahren mit dem Lenkrad auf der falschen Seite.
C:
Ein offener Geländewagen. Kommt durch jeden Match und Schlamm, aber der Fahrer sieht hinterher auch entsprechend aus.
COBOL:
Ein dunkelroter Daimler mit getöntem Panzerglas und kostbaren Intarsien-Arbeiten im Fond. Kein Mensch fährt diesen Wagen selbst, man lässt ihn fahren.
ASSEMBLER:
Ein Go-Cart ohne Sicherheitsgurte und Überrollbügel. Gewinnt jedes Rennen, wenn man nicht vorher im Graben landet.
FORTRAN:
Ein Schlitten aus den 50er Jahren mit riesigen Heckflossen. Erntet beim TÜV stets misstrauische Blicke, überholt aber noch manches neuere Gefährt.
LOGO:
Ein Tretauto in Form einer Schildkröte.
PROLOG:
Enthält statt des Lenkrades eine Automatik, die alle Straßen solange absucht, bis das gewünschte Ziel erreicht ist. Gegen Aufpreis sind Tank- und Erweiterungsmodule in Stufen zu 64, 128 und 256 Litern möglich.
APL:
Ein Wagen in Kompaktbauweise. Alle Funktionen wie Gasgeben. Schalten oder Lenken werden durch Drehen, Drücken, Ziehen, Kneten oder Verkanten eines Bedienungshebels ausgelöst.
PEARL:
Ein Kraftfahrzeugsverbund, bei dem mehrere unbemannte Kfz von einem zentralen Prüfstand aus gesteuert werden.
32
4 Programmiersprachen
4.2 Die Hochsprachen-Programmentwicklung 4.2 Die Hochsprachen-Programmentwicklung
Auch bei der Softwareentwicklung spielt das EVA-Prinzip eine wichtige Rolle. Mit Befehlen wie READ oder WRITE werden Daten eingelesen und ausgegeben. Eingabemedium ist meist die Tastatur, während Bildschirm und Drucker zu den bevorzugten Ausgabemedien zählen. Zwischendurch wird gerechnet oder allgemein verarbeitet. Das EVA-Prinzip gibt jedoch keine feste Reihenfolge vor. Vor allem bei großen Programmen wechseln sich E-, V- und A-Schritte in bunter Vielfalt ab. Eine typische Softwareentwicklung erfolgt in Stufen:
Stufe
Tätigkeit
Werkzeug oder Methode
0
Programmplanung
Struktogramm
1
Quellprogramm eingeben
Editor
2
Programm übersetzen
Compiler
3
Evtl. Fehler beseitigen
Schreibtischtest, Debugger
4
Programm „linken“
Linker
5
Programm starten
Kommandointerpreter
Unter einem Quellprogramm verstehen wir den Programmtext in lesbarer Form (s. folgendes Kapitel). Der Editor ist ein Programm, das die Tastatureingabe von Texten auf komfortable Weise ermöglicht. Das Quellprogramm muss streng den Regeln der gewählten Programmiersprache, den Syntaxregeln, entsprechen. Diese zu erlernen, macht den Schwerpunkt eines Programmierkurses aus. Teil II ist eine solche Einführung in die Sprache C / C++. Durch den Linker in Stufe 4 werden evtl. mehrere vorhandene übersetzte Programmodule oder Bibliotheksroutinen zu einem lauffähigen Gesamtprogramm zusammengebunden. Jeder Compiler enthält Bibliotheken für häufig auftretende Standardfunktionen. Generell sind problemorientierte Sprachen alle nach einem ähnlichen Muster aufgebaut. Typischerweise lässt sich ein Programm in drei Teile untergliedern:
1. Überschrift 2. Vereinbarungsteil 3. Anweisungsteil
Die Überschrift besteht nur aus einer Zeile, die je nach Sprache unterschiedlich aussieht.
4.2 Die Hochsprachen-Programmentwicklung
33
Es folgt der Vereinbarungsteil; dort werden die im Programm benötigten Variablen und Konstanten vereinbart (deklariert), d. h. es wird Platz im Zentralspeicher des Rechners reserviert. Speicherplätze werden, wie bereits weiter oben erläutert, über ihre numerische Adresse angesprochen. Hochsprachen arbeiten jedoch mit symbolischen Adressen, deren Namen im Rahmen gewisser Regeln vom Programmierer frei wählbar sind. Dies erleichtert die Arbeit sehr, weil sich der Programmierer über die exakte Länge und Verfügbarkeit von Speicherplätzen keine Gedanken machen muss. Variablen und Konstanten können im Programm Werte zugewiesen werden, Konstanten nur einmal zu Beginn des Programms, Variablen beliebig oft. Der Anweisungsteil entspricht dem in die jeweilige Programmiersprache umgesetzten Struktogramm. Der Anweisungsteil besteht aus den einzelnen Befehlen, die den strengen Syntaxregeln der jeweiligen Sprache unterliegen. Syntaxfehler entdeckt der Compiler, den man nach Eingabe des Quelltextes aufruft. Ist das Quellprogramm syntaktisch fehlerfrei, übersetzt es der Compiler in die Maschinensprache des verwendeten Rechners. Dennoch ist es möglich, dass unser Programm fehlerhaft ist. Es produziert u. U. falsche Ergebnisse. Der Grund: es enthält logische Fehler (Semantikfehler). Die Fehlersuche nennt man debugging (= Entwanzung). Sie erfolgt entweder durch aufmerksames Studium des Quelltextes (evtl. „Schreibtischtest“) oder mit Hilfe eines Debuggers, einer speziellen Software zur Fehlersuche. Entsprechend der Erkenntnisse wird nun der Quelltext verbessert. „Läuft“ das Programm zufriedenstellend, ist der Entwicklungskreislauf abgeschlossen. Übrigens startet man ein Programm in der Regel – bei einfachen Zeilen-Benutzeroberflächen – durch Eingabe des Programmnamens. Diese Eingabe wird vom Kommandointerpreter des Betriebssystems ausgewertet. Moderne Compiler bieten meist eine integrierte Arbeitsumgebung, aus der heraus man auch Programme starten kann. Im folgenden Teil II, dem Kernstück dieses Lehrbuchs, werden wir uns intensiv mit der Programmentwicklung befassen. Als Sprache wählen wir, aufgrund ihrer z. Zt. überragenden Bedeutung, C/C++.
34
II Programmieren in C/C++ Dieses Kapitel soll in die Grundlagen der Programmierung einführen. Aufgrund ihrer zunehmenden praktischen Bedeutung wählen wir dazu die Sprache C bzw. C++. Als Entwicklungsumgebung stellen wir uns einen PC unter Windows vor. Allerdings ist C hervorragend portabel, d. h. Programme lassen sich ohne großen Änderungsaufwand auf andere Betriebssysteme oder andere Rechner, z. B. UNIX-Workstations, übertragen, sofern man sich an den Standard hält und auf compilerspezifische Funktionen verzichtet Es ist nicht beabsichtigt, die Möglichkeiten von C/C++ erschöpfend darzustellen. Vielmehr möchten wir am Beispiel von C/C++ die sich in verschiedenen Sprachen oft ähnelnden Konzepte einer Höheren Programmiersprache vorzustellen. C++ stellt eine Spracherweiterung von C dar. Während C v. a. system- und hardwarenahe Probleme unterstützt, strebt C++ eine bessere Unterstützung der Anwendungsprogrammierung an, v. a. durch Objektorientierung. Die Ideen der objektorientierten Programmierung können hier nur in ihren Grundzügen dargestellt werden. Ignoriert man weitgehend die objektorientierten Elemente, so ist C++ eine prozedurale Sprache, die den C-Standard nutzbringend erweitert. Das Programm läuft später im Rechner so ab, wie es programmiert wurde. Die Reihenfolge der Befehle bestimmt exakt die Reihenfolge der Abarbeitung. Diese prozessorientierte (strukturierte) Vorgehensweise bestimmt nach wie vor die Lösung der meisten technischen Softwareprobleme. Die so entwickelten Programme sind konkurrenzlos schnell. Soweit sich die Aussagen der folgenden Kapitel nicht nur auf C++ sondern auch auf C beziehen, sprechen wir von C/C++. Für technische Anwendungen, also Aufgaben aus dem Bereich der Automatisierung und Messdatenerfassung, ist C/C++ Standard, auch wenn immer häufiger graphische Entwicklungstools, z. B. LabVIEW, eingesetzt werden. Der sichere Umgang mit solchen Tools setzt jedoch ebenfalls fundierte „klassische“ Programmierkenntnisse voraus, denn auch in solchen Tools findet man die Grundstrukturen der klassischen Programmierung wieder. Sequenzen, Verzweigungen und Schleifen bleiben die Grundlagen jeglicher Programmierung. Und auch die Lösungsidee, die Entwicklung eines Algorithmus, nimmt einem leider kein Tool ab. Natürlich ist das Erlernen einer Programmiersprache für den Anfänger keine ganz leichte Aufgabe. In der Praxis stellt jedoch die Entwicklung einer Lösungsidee für das jeweilige Problem die weitaus größere Schwierigkeit dar. Das Einmaleins der Programmierung lernt man am Besten anhand einer prozeduralen Sprache, zumal sie zusätzlich ein „sicheres Gefühl“ für die Arbeitsweise eines Rechners vermittelt. Und wenn sie darüber hinaus auch noch die Objektorientierung unterstützt und eine so große praktische Bedeutung wie C++ aufweist, dann umso besser. Die zahlreichen Beispiele dieses Teils sollten mit jedem C/C++-Compiler auf jedem Rechner, sofern er über die entsprechende Peripherie (Tastatur, Bildschirm, Festplatte) verfügt, unter jedem Betriebssystem funktionieren. Für alle gängigen Computer und Betriebssysteme gibt es Compiler, die man kostenlos aus dem Internet herunterladen kann. Die auf PC unter Windows am häufigsten eingesetzten kommerziellen Compiler sind der Borland C++-Builder und der Microsoft Visual C++-Compiler. Mehr zum Thema Compiler finden Sie zu Beginn von Teil III.
5 Über C und C++
35
5 Über C und C++ 5 Über C und C++
Die Entwicklung der Programmiersprache C ist eng mit der des Betriebssystems UNIX verknüpft. Nachdem die erste UNIX-Version noch in Assembler erstellt worden war (1969), entwickelte Ken Thomson 1970 die Sprache B zur Implementierung eines UNIX-Systems für eine PDP-7-Maschine. Aus der mit zu vielen Schwächen behafteten Sprache B entwickelte Dennis Ritchie 1972 C. Seit 1973 ist das Betriebssystem UNIX fast vollständig in C geschrieben. Zunächst gab es keinen offiziellen Sprachstandard. Stattdessen erreichte die Sprachdarstellung in einem Lehrbuch – deutsch: Kernigham, Ritchie; Programmieren in C. Hanser Verlag 1983 – den Status eines Quasi-Standards (Kernigham-Ritchie-Standard). Kleinere Erweiterungen und Verbesserungen führten zum ANSII-Standard. Die Sprache C++ wurde Anfangs der 80er Jahre von Bjarne Stroustrup an den Bell Laboratories entwickelt. Es handelt sich dabei um einen Zusatz für C.
C ist in C++ vollständig enthalten. (Fast) alles was in C funktioniert, funktioniert auch in C++ C ist eine Sprache der 3. Generation (strukturierte Sprache) und ist die wichtigste Höhere Programmiersprachen im Ingenieurbereich. Die wesentlichen Merkmale der Sprache sind: breites Anwendungsspektrum knappe Befehle (short is beautiful) sehr klares Sprachkonzept. Was oben als Vorteil erscheint, erweist sich als Nachteil bezüglich der Erlernbarkeit als "Erstsprache". Die "kappen Befehle" könnte man etwas böswillig auch als kryptisch bezeichnen und das "klare Sprachkonzept" verlangt vom Programmierer Grundkenntnisse über Aufbau und Arbeitsweise von Computern, deutlich mehr als Pascal und FORTRAN. Allerdings steigen diese Grundkenntnisse bei der jungen Generation von Jahrgang zu Jahrgang. Fast jeder (interessierte) kann mit einem PC umgehen. Viele haben bereits gelernt, kleinere Probleme in Basic oder Pascal zu lösen. Und so kann man es heute wagen, ernsthaft mit C zu starten. Die Mühe lohnt sich! Es klingt paradox aber es ist wahr: Obwohl C++ der 5. Sprachgeneration (objektorientiert) angehört und mächtiger als C ist, gelingt der Einstieg mit C++ leichter als mit C "pur". Der Grund: C++ bietet einige Erleichterungen, v. a. bei der Datenein- und Ausgabe, auch lassen sich die gefürchteten Pointer in der Anfangsphase umgehen. Im letzten Kapitel dieses Teils erhalten Sie eine kurze Einführung in die Objektorientierte Programmierung (OOP).
36
6 Grundlagen 6 Grundlagen
Eine Programmiersprache ist im Wesentlichen durch zwei Themenbereiche gekennzeichnet: Datenstrukturen Programm-Ablaufstrukturen Mit „Datenstrukturen“ werden die verschiedenen Organisationsmöglichkeiten von Daten beschrieben. Der Programmierer muss sich sehr gut überlegen, welche Datenstrukturen am ehesten seinem Problem angepasst sind. So kann es in dem einen Fall günstig sein, skalare Einzelwerte zu verarbeiten, während in einem anderen Fall die Zusammenfassung von Daten zu Feldern (z. B. Vektoren, Matrizen), Verbunden (z. B. Adressen von Studenten) oder ganzen Dateien (z. B. ein eine komplette Serie von Messwerten) erheblich sinnvoller ist. „Ablaufstrukturen“ kennzeichnen die Möglichkeiten, vom linearen Ablauf des Programms abzuweichen und Schleifen oder Verzweigungen durchzuführen. Der Programmierer muss anhand der von der Sprache unterstützten Ablaufstrukturen entscheiden, welche zur Lösung der jeweiligen Aufgabe optimal geeignet ist. Bei größeren Programmen sollte dies mit Hilfe von Struktogrammen geschehen, wie im Teil I vorgestellt.
6.1 Ein einführendes Beispiel 6.1 Ein einführendes Beispiel
Das Programm KUGEL.CPP vermittelt einen ersten Eindruck von der Sprache C++: /*
Programm zur Berechnung von 1. Kugelvolumen 2. Kugeloberflaeche bei Eingabe des Radius */ #include #include <math.h> using namespace std; int main(void) { float radius, volumen, oberflaeche; cout > radius; while(radius != 0) { /* Kugelberechnung */ volumen=4./3.*M_PI*radius*radius*radius; oberflaeche=4*M_PI* radius*radius; cout "; cin >> zahl; hunderter = zahl / 100; zahl = zahl % 100; zehner = zahl / 10; einer = zahl % 10; q_summe = hunderter + zehner + einer; cout in1 >> in2 >> in3; m_wert = (in1+in2+in3) / 3.0f; cout using namespace std; int main(void) /* Eingabe einer float-Zahl mit einer Nachkommastelle und Ausgabe der Nachkommastelle als int-Wert */
7.2 Verarbeitung von Einzelzeichen: Der Datentyp char
63
{ float zahl, ganz; int ziffer; cout > zahl; ganz = floor(zahl); ziffer = (zahl - ganz) * 10; cout eins; Eingabe: z cout > zwei; Eingabe: a cout zwei; Eingabe: 8 cout "; cin >> c ; i = toupper(c); ... → später keine zusätzlichen Abfragen für "j" und "n" nötig.
■
Beispiel 2: ... char c; int i; ... cout > c; i = isdigit(c); if(i != 0) cout > k; l1 = i == k; cout "); scanf("%d", &zahl);
96
8 Interaktive Ein-/Ausgabe
8.5 Aufgaben 8.5 Aufgaben
1) Was geben folgende Programme aus? Geben Sie die Programme ein und testen Sie: a) #include b) using namespace std; int main(void) { int i,j; i = 1110; j = 60; cout ch; cout > ch; cout ; - oder if() { <mehrere Anweisungen>; } Die nach if() folgenden Anweisungen (if-Block) werden nur ausgeführt, wenn die Auswertung des logischen Ausdrucks "wahr" ergibt, anderenfalls übersprungen. Das
9.1 Die Selektion
99
Ende des if-Blocks muss gegen die nachfolgenden Anweisungen eindeutig vom Compiler erkannt werden. Daher ist die { ... } - Blockung bei mehr als einer Anweisung erforderlich. Durch die eingerückte Schreibweise ist die Struktur schon optisch erkennbar. Beispiele: a)
if(zahl < 0) cout "; cin >> out->n_name; cout > out->v_name; cout > out->alter; } Möglicher Dialog: Nachname > Young Vorname > Neil Alter > 60 Sie heissen Neil Young und sind 60 Jahre alt. Ohne Adressübergabe könnte main() nicht auf die Eingaben zugreifen!
■
11.3 Datenverbunde: Strukturen
179
Wenn die letzte Komponente einer Struktur ein Strukturpointer ist, der auf die nächste Struktur zeigt, usw., spricht man von einer verketteten Liste. Folgendes Programmbeispiel zeigt das Prinzip einer verketteten Liste: Beispiel: Ein Programm soll eine nicht festgelegte Anzahl von Integer-Werten dynamisch auf dem Heap speichern. Bei Eingabe des Wertes 0 soll die Eingabe abgeschlossen sein und die Werte in der Reihenfolge der Eingabe wieder ausgegeben werden. Idee: Anlegen der Werte in der Form der Struktur daten start
daten → wert daten → zeiger
daten → wert daten → zeiger
...
Lösung: #include // lineare Liste using namespace std; struct dat_im_heap { int wert; struct dat_im_heap *zeiger; }; int main(void) { struct dat_im_heap *daten, *start; daten = new struct dat_im_heap; start = daten; //Startzeiger festhalten cout > daten->wert; while(daten->wert) { daten->zeiger = new struct dat_im_heap; daten = daten->zeiger; cout >daten->wert; }
cout