Einführung und erste Hilfe zur Programmiersprache Turbo
Transcription
Einführung und erste Hilfe zur Programmiersprache Turbo
Programmiertechnik Informationsblatt HansBöcklerSchule Klasse : Name : PASCAL-READER VERSION 2.3 Münster 25 Seiten Datum : Einführung und erste Hilfe zur Programmiersprache Turbo - Pascal Inhaltsverzeichnis : 1) 2) 3) 4) 5) 6) 7) 8) 9) 10 ) 11 ) 12 ) 13 ) 14 ) 15 ) 16 ) 17 ) 18 ) 19 ) 20 ) 21 ) 22 ) 23 ) 24 ) 25 ) Entstehung von Pascal Übersicht Programmiersprachen Bedienungshinweise zu Turbo-Pascal 6.0 / 7.0 Stufen der Programmentwicklung Sinnbilder für Struktogramme und PAP Aufbau eines Pascal-Programms und Datentypen wichtige Pascal-Befehle und Kontrollstrukturen Standard- Ein- Ausgabe- Funktionen Beispielentwurf für ein lineares Programm Regeln für die Dokumentation von Programmen Übungsaufgaben für lineare Programme Unterprogramme / Prozeduren Unterprogramme / Funktionen Unterprogrammsammlungen / Units Wiederholungsstrukturen Übungsaufgaben zur Schleifenprogrammierung Programmierung über die parallele Schnittstelle Verzweigungen Übungsaufgaben zu Verzweigungen Programm mit Loops und Verzweigungen Beispiellösung / Teil 1 Programm mit Loops und Verzweigungen Beispiellösung / Teil 2 Zusammengesetzte Datentypen : Array / Felder Records / Verbund Mengen ( SET ) Eigene Datentypen ( TYPE ) Literatur zum Einstieg : 1] Gregor Kuhlmann : 2] Peter Niehoff : 3] Reinhard Schuberth : 4] D. Häberle : Programmiersprache Turbo-Pascal; Eine strukturierte Einführung, rororo Computer Nr. 8148 ; Preis ca. 13.- € Informatik - Datenverarbeitung . mit Pascal, Verlag Handwerk und Technik, Hamburg; Preis ca. 13.- € Technologie , Eine Einführung für technische Ausbildungsrichtungen – mit Pascal Verlag Handwerk & Technik 2711 , Hamburg 1993, Preis ca. 13.- € Pascal für gewerbliche Schulen; 2. Auflage 1994, Verlag : Europa-Lehrmittel, Düsseldorf, Preis ca. 16.- € 5] Das erweiterte Online-Exemplar des Readers finden Sie unter : http://www.muenster.de/~m_frost 13.07.02 0-Inhalt HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : GESCHICHTE Münster 1/25 Datum : Programmiersprache Turbo-Pascal 1) Blaise Pascal, der französische Religionsphilosoph, Mathematiker und Physiker wurde am 19. Juni 1623 in Clermont-Ferrand als Sohn eines Steuerfachmanns geboren. Er starb 1662. Um seinem Vater bei Steuerberechnungen zu helfen, konstruierte er die erste Rechenmaschine , die Pascaline, nach deren Prinzip in Zukunft alle weiteren gebaut wurden. Die Programmiersprache hat ihren Ursprung in der Sprache Pascal, die 1972 von Niclas Wirth als "Universitätssprache" entworfen wurde, also als eine Programmiersprache, die den Studenten das Erlernen des Programmierens erleichtern sollte. Niklaus Wirth wurde im Februar 1934 in Winterthur, Schweiz geboren. Nach seiner Prüfung als Elektronik-Ingenieur am Federal Institute of Technology (ETH) in Zürich ( 1959 ) arbeitete er zunächst an der Laval University in Canada ( 1960 ) und an der University of California in Berkeley ( 1963 ). Bevor er wieder zurück an die Universität von Zürich zurückkehrte war er AssistenzProfessor für Computerwissenschaften an der Stanford University (1963 1967) wo er Pascal entwickelte. Der Name ist akademisch nach Blaise Pascal ausgewählt worden, dem bekannten Mathematiker und Philosophen. Zu Ehren dieses bedeutenden Genies und einem der Vorväter des Computers hat Nikolaus Wirth, Professor für Informatik an der ETH Zürich, seine zu Beginn der 70er Jahre aus "Algol 60" entwickelte Programmiersprache zur Unterstützung der strukturierten Programmierung "Pascal" genannt. Diese Bezeichnung wurde dann von Borland später übernommen. 1 ] Made in Borland® Copyright© 1994-2002 Borland Software Corporation 11.07.02 1-geschichte HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : PROGRAMMIERSPRACHEN Münster 2/25 Datum : Übersicht Programmiersprachen Um einen Computer zu programmieren, muss ein gemeinsamer Kode gefunden werden, auf dessen Basis man mit der Maschine kommuniziert Je mehr man sich der Sprache des Rechners nähert, um so schwieriger und umständlicher wird die Kommunikation. Man unterscheidet heute 5 verschiedene Generationen: 1) Programme in MASCHINENSPRACHE bestehen aus Maschinenbefehlen, die als Folge von Nullen und Einsen im Computer dargestellt werden. Die umständliche Eingabe Tausender von einzelnen Bits wird häufig abgekürzt durch die Eingabe der äquivalenten Hexadezimalzahlen z.B. 63 B1 0C statt 0110 0011 1011 0001 0000 1100 usw. Bei Fehleingaben wird die Fehlersuche sehr zeitaufwendig und schwierig. Maschinensprachen gelten immer nur für Mikroprozessoren des gleichen Typs. 2) Programmiersprachen, bei denen die Bitkombinationen der Maschinenbefehle durch ein leicht zu merkendes Symbolwort ( Mnemonics ) ausgedrückt werden, nennt man ASSEMBLER. Auch solche Assemblersprachen gelten immer nur für einen einzigen Mikroprozessortyp. 3) Höhere oder PROBLEMORIENTIERTE PROGRAMMIERSPRACHEN erlauben es die Anweisungen für den Computer so zu beschreiben, dass man keine Maschinenbefehle verwenden muss. Man ist dadurch unabhängig vom Mikroprozessortyp und die Programme können auf jedem Rechner ablaufen. 4) Sprachen der 4. Generation nennt man DESKRIPTIVE PROGRAMMIERSPRACHEN. Hier gibt der Anwender nur noch den Verarbeitungsbefehl ein, ohne dass er den Lösungsweg in Form eines Algorithmus beschreiben muss. Diese Sprachen sind immer auf ein bestimmtes Anwendungsgebiet zugeschnitten; z.B. SQL für relationale Datenbanken oder ADF, CSP, DMS (IBM) , Natural ,Oracle usw. 5) Im Bereich der Künstlichen Intelligenz findet man Programmiersprachen zur Erstellung von Expertensystemen. Hierunter fallen OBJEKTORIENTIERTE PROGRAMMIERSPRACHEN wie z.B. Java, Delphi, C++ oder Visual Basic. Auch funktionale Sprachen wie LISP, logische Sprachen wie Prolog und alle neuen Makro-Sprachen zählt man zur 5. Generation. Hier programmiert man keine Befehle, sondern man gibt an, was mit Objekten passieren soll, wenn bestimmte Ereignisse ( events ) im Programmablauf aktiviert werden. Die Objekte können Dialogelemente sein, Befehlsschaltflächen, Kontrollkästen, Bildlaufleisten usw. Maschinensprache Dualkode Hexadezimalkode 0011 1110 3E 0000 0011 03 Assembler Mnemonics MVI A, 03h oder LD A, 03h Problemorientierte Sprachen z.B. BASIC z.B. PASCAL 10 LET A = 3 A := 3; Assembler Objektkode Interpreter Compiler Quellkode ( Übersetzungsprogramme ) Einzelne Programmieranweisungen in einer höheren Programmiersprache können eine Menge von Maschinenbefehlen auslösen, die der Programmierer im einzelnen gar nicht kennt. Welche Befehle jeweils ausgelöst werden, teilt ein Übersetzungsprogramm dem Computer mit. Vor dem Programmieren ist daher unbedingt ein Übersetzungsprogramm in den RAM zu laden! Dabei unterscheidet man drei Grundversionen : 1) ASSEMBLER Leider hat sich für das Übersetzungsprogramm von Assemblersprache in Maschinensprache ebenfalls das Fachwort Assembler eingebürgert. 2) INTERPRETER Dies sind Übersetzer, die nach dem Start eines Quellprogramms jeweils eine einzige Anweisung in Maschinenbefehle übersetzen und sofort ausführen. Erst dann wird die nächste Anweisung bearbeitet. Vorteil : Man kann ein Programm bis zu Fehlerstelle im Quelltext testen. Nachteil: Da immer nur eine Zeile übersetzt wird, liegt das Programm nie komplett übersetzt vor. Man muss bei jedem Start den Quelltext neu übersetzen, was sehr lange dauert. Der Interpreter muss ständig im Speicher verbleiben. 3) COMPILER Sie übersetzen ein komplettes Quelltextprogramm auf einmal in Maschinensprache und legen das Ergebnis entweder auf Diskette oder im RAM als Maschinenspracheprogramm ab. Vorteil : Sie brauchen das Programm nur ein einziges mal zu übersetzen; anschließend läuft es in Maschinensprache sehr schnell ab. Nachteil : Ein Maschinenspracheprogramm ist nicht mehr ohne weiteres zu verändern. Außerdem - und das ist das Problem - übersetzt ein Compiler Ihr Programm nur dann, wenn es fertig durchdacht ist und fehlerfrei vorliegt. Testen von Programmteilen ist nur bedingt möglich. 11.07.02 2-sprachen HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : BEDIENUNGSHINWEISE Münster 3/25 Datum : Turbo-Pascal starten und beenden Sie können den Compiler ganz einfach starten, indem Sie von der Betriebssystemebene aus im entsprechenden Pfad die Startdatei TURBO.EXE aufrufen. Nach kurzer Zeit meldet sich Turbo-Pascal mit dem Einschaltbild und wartet auf Ihre weiteren Eingaben. Wird während des Ladevorgangs der Fehler gemeldet: „cannot create swap file“, so kann Pascal seine Auslagerungsdatei ( swap file ) nicht öffnen. Das liegt daran, dass Sie den Schreibschutz an Ihrer Diskette aktiviert haben oder im aktuellen Pfad keine Schreibrechte im Netzwerk besitzen. Beenden Sie Turbo-Pascal nie (!) , indem Sie einfach den Rechner ausschalten oder einen Reset auslösen, denn Pascal schließt dann die temporären Dateien nicht ordnungsgemäß. Auf Ihrer Diskette häufen sich dann Dateien, die etwa folgendermaßen aussehen : tp0dde7f.$$$ oder td2ed929.$$$. Verlassen Sie den Compiler immer nur über das Menue FILE mit dem Menuepunkt EXIT. Programme laden und speichern Über das Pull Down Menue FILE können Sie entweder alte Programme bearbeiten ( OPEN ) oder völlig neue Programme entwerfen ( NEW ). Dazu müssen Sie aber angeben, in welchem Pfad auf Ihrer Diskette oder der Festplatte das Programm gesucht werden soll. Stellen Sie dies im Menuepunkt CHANGE DIR vorher ein. Zum Speichern Ihres Quelltextes bietet das Pull Down Menue zwei Varianten. Mit SAVE wird der Quelltext unter dem Namen gespeichert, der im Rahmen des blauen Bildschirms oben aktuell eingeblendet ist; das ist meist noname00.pas. Mit dem anderen Menuepunkt SAVE AS .. können Sie vor dem Speichern den Programmnamen ändern. Der Pfad in dem der Quellkode abgelegt wird entspricht dem, unter welchem auch gelesen wurde. Programme compilieren und starten Ihre fertigen Programme übersetzen Sie in Maschinensprache mit dem Kommando COMPILE im Menue COMPILE. In Abhängigkeit von dem Schalter DESTINATION ( Zielort ) wird der Objektkode entweder im RAM abgelegt ( memory ) oder auf dem Datenträger ( disk ) gespeichert. Wo auf der Diskette oder der Festplatte Ihr Programm landet, hängt davon ab, welche Zielpfade Sie vorher eingestellt haben. Ihrer Wahl treffen Sie unter dem Menuepunkt OPTIONS und DIRECTORIES. Dort werden die Pfade für die EXE-Dateien vorgegeben. Sie können natürlich Ihr Programm nur dann erfolgreich compilieren lassen, wenn der Quelltext völlig fehlerfrei vorliegt. Treten Fehler auf, so stellt Pascal den Cursor an die Stelle des Quelltextes, wo die Übersetzung aufgrund eines Syntaxfehlers abgebrochen hat. Das Kommando RUN startet das Programm für den Normalbetrieb, wobei das Startkommando bereits den Compileraufruf enthält. Sie sollten ein Programm aber nie starten, bevor Sie es nicht abgesichert haben. Hängt sich Ihr Programm aufgrund eines Logikfehlers auf, so bleibt nur der Neustart des Rechners und Ihr Programm im RAM des PC ist unwiderruflich verloren. Sie müssen dann alles noch einmal neu schreiben. Programme eingeben und bearbeiten Diesen Vorgang nennt man Editieren. Demzufolge erreichen Sie die wichtigsten Bearbeitungsfunktionen auch über den Menuepunkt EDIT. Sie können zuvor markierte Textteile in eine Ablage ( CLIPBOARD ) legen ( CUT ), sie hinein kopieren ( COPY ), sie wieder aus der Ablage entnehmen ( PASTE ) oder sie in der Ablage löschen ( DELETE ). Solche Blockoperationen erleichtern die tägliche Arbeit beim Eintippen von Quelltexten ungemein. Wollen Sie einen Buchstaben oder mehrere überschreiben und nicht einfügen, so müssen Sie mit der Taste INS ( Einfügen ) zwischen dem Überschreibmodus und dem Einfügemodus wechseln. Den eingestellten Modus ( die Betriebsart ) erkennen Sie an der Form des Cursors. Können Sie keine Leerzeilen mit RETURN mehr einfügen, so sind Sie mit Sicherheit im Überschreibmodus und müssen zum Einfügemodus wechseln. ----------------------------------------------------------------------------------------Beachten Sie bitte : 1) Stellen Sie zunächst alle Quell- und Zielpfade exakt ein; Sie finden sonst Ihre Programme schlecht wieder ! 2) Speichern Sie Ihr Programm ca. alle 10 min als Sicherungskopie ab; es könnte der Strom ausfallen ! 3) Sichern Sie Ihre Programme auch auf Ihrer Diskette. Auf der Festplatte C: oder D: sind die Daten nicht sicher. 4) Speichern Sie Ihr Programm vor dem ersten Probelauf ab. Es könnte sich unwiderruflich „aufhängen“. 11.07.02 3-bedienung HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : PROGRAMMENTWURF Münster 4/25 Datum : Stufen der Programmentwicklung Der Weg von der Problemerkennung bis zur Lösung mittels Computer ist unter Umständen sehr lang und beschwerlich. Dabei liegen die Hauptprobleme weniger in der Programmierung als vielmehr darin, dass der Anwender das Problem und die Problemlösung nicht genau genug beschreiben kann. Ungefähre Vorstellungen führen grundsätzlich dazu, dass man sich verzettelt. Es hilft also nichts, wenn man sofort beginnt, mit seinen „Wurstfingern“ wild auf der Tastatur zu klappern bevor man nicht nachgedacht hat. Da der Pascal-Compiler unerbittlich ist, wenn Sie nicht planen, bin ich es auch und helfe nur, wenn die Vorarbeiten zum Programm sauber und eindeutig sind. PROGRAMMENTWICKLUNG 1) Lastenheft / Pflichtenheft - die Aufgabenstellung wird in einem ganzen Satz schriftlich u. grammatisch exakt beschrieben. - einzuhaltende Bedingungen werden geklärt, gewünschte Ergebnisse werden konkret definiert. 2) Problemanalyse - welche Daten werden eingegeben, welche werden ausgegeben ? - welche Variablen und welche Konstanten liegen vor ? Wie sollen sie heißen ? - welcher Art sind diese Variablen und in welcher Form sollen sie verwendet werden ? - welcher Algorithmus kann das Problem lösen ? ( Oft hilft eine Skizze weiter ! ) 3) Programmstrukturierung ( d.h. graphische Darstellung der Vorgehensweise ) - mit Hilfe eines Programmablaufplans PAP ( DIN 66001 ) - mit Hilfe eines Struktogramms nach den Herren Nassi und Shneiderman ( DIN 66261 ) 4) Codierung - Umsetzen der Algorithmen in eine Folge von Anweisungen ( Quelltext schreiben ) - Einstellen der Pfade zur definierten Abspeicherung - Abspeichern des Programmentwurfs als Sicherungskopie 5) Programmtest - Übersetzen des Quelltextes in den Maschinenkode - Prüfung auf Codierfehler / Syntaxfehler - Prüfung auf logische Fehler durch Testläufe - Testläufe, um die Grenzen des Programms zu erkennen - Abspeichern des getesteten, fertigen Programms ( Objektkode ) 6) Programmdokumentation - graphisches Einrücken der Anweisungen mit richtiger Schreibweise - Angaben zu Ort, Zeit, Version, Autor usw. im Quelltext - kurzer Kommentar mit Programmbeschreibung und Leistungsgrenzen - Kommentare zur Erläuterung von Variablen und Konstanten - Abspeichern des fertigen, kommentierten Programms Bei umfangreichen und komplexen Problemen zerlegt man die Gesamtaufgabe stufenweise in immer kleinere Teilprobleme, die dann einzeln nach der genannten Vorgehensweise bearbeitet werden ( Top Down Entwurf ). Solche in sich abgeschlossene und fertige Programmteile nennt man Module und fügt sie später durch Unterprogrammtechnik zusammen. Größere Unterprogrammsammlungen nennt man bei Turbo-Pascal UNITS. 11.07.02 4-prgentwurf HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : SINNBILDER FÜR STRUKTOGRAMME UND PAP’S Münster 5/25 Datum : Sinnbilder für Programmablaufpläne und Struktogramme : Die Programmdokumentation ist eine notwendige Voraussetzung zur Entwicklung und Wartung eines Programmes. Vor allem müssen die Programme grafisch dargestellt werden, weil nur so ein Überblick möglich ist. Speziell dafür verwendet man genormte Sinnbilder nach DIN 66261( Struktogramme nach Nassi und Shneiderman ) oder auch DIN 66001 ( Programmablaufplan ) . Sinnbilder für Programmablaufpläne Sinnbild Elem ente von S truktogram m en Benennung Operation allgemein S innbild B enennung A n w eisu n g 1 A nw eisung 2 A n w eisu n g 3 Unterprogrammaufruf Folgeblock für W ertzuw eisungen, R echenoperationen und B ildschirm befehle A n w eisu n g 1 ( nich t gen o rm t ) Ein- bzw Ausgabe A n w eisu n g 1 ( nich t gen o rm t ) Verzweigung A n w eisu n g 1 W iederholungsstruktur A n w eisu n g 2 m it E n d eb ed in gu n g w iederhole bis .. W iederholungsstruktur w iederhole solange A n w eisu n g 1 Übergangsstelle m it A n fan gsb ed in gu n g A n w eisu n g 2 Grenzstelle B edingung nein Ablauflinien ja A nw eisung a) einseitig b ) zw eiseitig B edingung Fall Schleifenbegrenzung für zählergesteuerte Wiederholungen 1 m eh rfach 2 3 4 .. A u fru f U -Prg a) Funktion b) P rozedur Bei umfangreichen Programmen mit vielen Programmverzweigungen erweist sich das Struktogramm als vorteilhaft. Es ist übersichtlicher. Das liegt auch daran, dass für Programmablaufpläne keine Symbolik genormt ist, mit der man eine Mehrfachverzweigung skizzieren kann. Nicht nur für das Hauptprogramm müssen Ablaufpläne gezeichnet werden, sondern für jedes Unterprogramm zusätzlich. Das heißt, ein Programm mit z.B. 5 Unterprogrammen basiert auf der Grundlage von 6 Ablaufplänen. 11.07.02 5-strukto HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : AUFBAU EINES PROGRAMMS Münster 6/25 Datum : Aufbau eines Programms Jedes Pascal-Programm muss nach bestimmten Regeln ( Syntax ) aufgebaut werden. Es besteht immer aus drei Teilen : 1) - dem Programmkopf 2) - dem Vereinbarungsteil ( Deklarationsteil ) 3) - dem Anweisungsteil ( Hauptprogramm ) Programmkopf : Er wird immer eingeleitet mit dem Schlüsselwort PROGRAM. Dahinter folgt nach einem Leerzeichen ( blank ) der Name des Programms. Er darf aus bis zu 127 Zeichen bestehen, mit Ausnahme von Leerzeichen. In manchen Pascal - Dialekten folgt nun die Angabe der benötigten Standard-Ein- und Ausgabeperipherie ( Tastatur und Bildschirm ). Allgemein gilt also : PROGRAM Name (input , output) ; Vereinbarungsteil : Damit alle benötigten Speicherplätze vom Programm richtig adressiert und wiedergefunden werden, müssen sie eingerichtet ( deklariert ) werden. In Turbo-Pascal vereinbart man : - Programmbibliotheken - Konstanten - Unterprogramme - Sprungadressen USES CONST PROCEDURE LABEL - Variable - Funktionen - eigene Datentypen VAR FUNCTION TYPE Damit der Rechner auch weiß, wie groß der vorzusehende Speicherplatz sein muss, wird hinter den deklarierten Speicherplätzen und einem Doppelpunkt der sogenannte Datentyp angegeben. Hier zunächst die einfachen Datentypen von Turbo - Pascal : 1) numerische Datentypen BYTE kleine positive ganze Zahl 0 .. 255 SHORTINT kurze ganze Zahl -128 .. +127 WORD positive ganze Zahl 0 .. 65535 INTEGER ganze Zahl -32768 .. +32767 LONGINT große ganze Zahl -2147483648 .. +2147486647 REAL reelwertige Zahl -2,9 • 1039 .. +1,7 • 1038 ( 1 Byte ) ( 1 Byte ) ( 2 Byte ) ( 2 Byte ) ( 4 Byte ) ( 6 Byte ) Die reellen Zahlentypen SINGLE, DOUBLE, EXTENDED und COMP können mit dem Compilerbefehl { $N+ } eingeschaltet werden, wenn ein mathematischer Coprozessor vorhanden ist. Diese Compilerdirektive { $N+ } steht dann unmittelbar vor dem einleitenden Schlüsselwort PROGRAM. 2) ein einzelnes Zeichen CHAR alle 256 Zeichen des ASCII - Zeichensatzes 3) Wahrheitswert BOOLEAN für zwei Wahrheitswerte : true / false ( 1 Byte ) ( 1 Byte ) Aus diesen einfachen Datentypen lassen sich dann, zum Abspeichern von Namen beispielsweise, auch größere Datentypen ( strukturierte Datentypen ) zusammensetzen. a) STRING[n] Zeichenkette mit n Daten vom Datentyp CHAR ARRAY[n.. m] Folge von n bis m Elementen mit jeweils gleichem Datentyp einfacher Art RECORD Verbund von Datenfeldern verschiedener Datentypen FILE nichttypisierte Datei, die unstrukturiert ist b) SET of Untermenge eines Grundmengentyps der einfachen Datentypen Anweisungsteil : Hier folgen nun die eigentlichen Pascal-Anweisungen zur Eingabe, Verarbeitung und Ausgabe. Die Anweisungen werden mit BEGIN und END. ( mit Punkt ! ) umklammert. 11.07.02 6-prgaufbau HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : STANDARD-PASCAL-BEFEHLE Münster 7/25 Datum : Pascal - Schlüsselwörter Programmkopf PROGRAM < .. >; USES < .. >; Vereinbarungsteil ( Deklarationsteil ) CONST ... VAR ... LABEL ... PROCEDURE ... FUNCTION ... TYPE ... Anweisungsteil Kontrollstrukturen BEGIN ... END; IF .. THEN IF .. THEN .. ELSE CASE .. OF .. ELSE REPEAT .. UNTIL .. WHILE .. DO .. FOR .. TO .. DO .. FOR..DOWNTO.. DO INLINE(Maschinencode) Standardprozeduren Write ( .. ); WriteLn ( .. ); Read( n ); ReadLn( n ); Nur in Verbindung n := ReadKey; mit der Unit CRT ! ClrScr; GotoXY(x,y); TextColor( n ); ClrEol; Standardfunktionen y := Sqr ( n ); y := Sqrt ( n ); y := Exp( n ); y := Sin( n ); y := Cos( n ); y := ArcTan( n ); y := Trunc( n ); y := Round( n ); y := Abs( n ); y := Ln ( n ); y := Succ ( n ); y := Pred ( n ); y := UpCase ( n ); y := Random( n ); Operatoren DIV ( n ); MOD ( n ); SHL; SHR AND, OR, NOT XOR Standardvariable Port [ Adresse ] := n; X := Port [ Adresse ]; Kopfzeile mit Namen des Programms Einbinden von externen Programmunits z.B. CRT, DOS; [ CRT = cathode ray tube ( Elektronenstrahlröhre ) ] Konstantenvereinbarung Variablenvereinbarung Sprungadressen ( möglichst nie verwenden !!! ) Unterprogramme mit Namen und evtl. Parameterliste Subroutinen mit Ergebnislieferung an eine Variable Vereinbarung eigener Datentypen z.B. vom Typ Monat Anweisungsklammern. Das letzte END schließt mit einem "•" das Hauptprogramm ab. einseitige bedingte Anweisung zweiseitige bedingte Anweisung mehrseitige bedingte Anweisung Schleife mit Austrittsbedingung ( post check loop ) Schleife mit Eintrittsbedingung ( pre check loop ) zählergesteuerte Schleife aufwärts zählergesteuerte Schleife abwärts Einbinden einzelner Maschinensprachebefehle Ausgabeanweisung ohne Zeilenvorschub Ausgabeanweisung mit Zeilenvorschub und "Wagenrücklauf" Eingabe mit Return Eingabe mit Return und anschließendem Zeilenvorschub Eingabe nur eines einzigen ASCII-Zeichens ohne Return Bildschirm löschen Cursor an die Bildschirmposition x,y positionieren Textfarbe verändern löscht den Rest der Zeile ab der Cursorposition Quadratfunktion Wurzelfunktion ( square root ) Exponentialfunktion zur Basis e ( e = 2,718281.. ) Sinusfunktion ( Ergebnisse liegen im Bogenmaß vor ! ) Cosinusfunktion .. ebenfalls im Bogenmaß Umkehrfunktion des Tangens ( n in rad ! ) Nachkommastellen abschneiden Wert runden Absolutbetrag ( Vorzeichen spielen keine Rolle mehr ) Logarithmus naturalis ( Basis = e ) logischer Nachfolger wird ermittelt ( nur für Ordinalzahlen ) logischer Vorgänger Buchstaben in Großbuchstaben umwandeln ergibt eine Zufallszahl zwischen 0 und der genannten Grenze n Division ohne Rest Modulodivision ( Rest bei ganzzahliger Division ) Binärzahlen im Register links/rechts schieben ( shift left/right ) logische Grundoperatoren logische Exclusiv-Oder Verknüpfung Ein Byte n über einen Schnittstellenport ausgeben Ein Byte über eine Schnittstelle in eine Variable X einlesen 11.07.02 7-befehle HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : STANDARD-EIN-, AUSGABE- FUNKTIONEN Münster 8/25 Datum : Turbo-Pascal hat bereits eine Reihe von Prozeduren ( und Funktionen ) vordefiniert. Sie sind in der Unit SYSTEM abgelegt und gehören zum Standard-Sprachumfang. Mit anderen Worten : Diese Unterprogramme stehen Ihnen in jedem Programm standardmäßig zur Verfügung und können sofort eingesetzt werden. Die wichtigsten sind die Ein- und Ausgabebefehle : Read Daten werden über die Tastatur eingelesen und in eine oder mehrere Variablen geschrieben. Eingabe ReadLn Write Ausgabe WriteLn Daten werden über die Tastatur eingelesen und in eine oder mehrere Variablen geschrieben. Anschließend erfolgt ein "Wagenrücklauf" und ein "Zeilenvorschub" Daten werden an der aktuellen Cursorposition unmittelbar auf den Bildschirm geschrieben. Daten werden an der Cursorposition unmittelbar auf den Bildschirm geschrieben. Anschließend erfolgt ein "Wagenrücklauf" und ein "Zeilenvorschub" Die Ausgabeanweisung Das Schlüsselwort zur Ausgabe von Daten auf den Bildschirm lautet zunächst Write oder WriteLn. Dahinter wird in runden Klammern angegeben, was ausgegeben werden soll. Und hier unterscheidet man grundsätzlich drei Möglichkeiten : Ausgabe des Inhalts von Ausgabe von Textkonstanten Ausgabe zum Drucker Variablen oder Konstanten WriteLn ( ' Text ' ); WriteLn ( Variable ); WriteLn ( Lst, ' Text ' ); Achten Sie darauf, dass Sie Texte zwischen Hochkommata setzen müssen, um sie von den Namen der deklarierten Variablen und Konstanten abzugrenzen. Jeder Befehl schließt übrigens am Ende der Zeile mit einem Semikolon ab. Wenn Sie in einer Anweisung mehrere Elemente gleichzeitig ausgeben wollen, so müssen Sie die einzelnen Komponenten in der Ausgabeanweisung durch Kommata trennen. Im folgenden Beispiel wird der Text "Die Entfernung beträgt :", der Inhalt der Variablen Länge und der Text "km" zusammen hintereinander ausgegeben. Beispiel : WriteLn ( ' Die Entfernung beträgt : ' , Laenge , ' km ' ); Ausgabeformatierung Damit Gleitkommazahlen ( Realzahlen ) am Bildschirm nicht mit 10 Stellen hinter dem Komma und mit Exponent zur Basis 10 ausgegeben werden ( das ist die wissenschaftliche Schreibweise ), wird die Ausgabeanweisung durch Parameter ergänzt, die eine Fließkomma-Notation ermöglichen. Das heißt, Sie müssen hinter dem Variablennamen, jeweils durch Doppelpunkte getrennt, die Gesamtzahl aller gewünschten Stellen - inclusive Dezimalpunkt und Vorzeichen - und die Nach-Stellen hinter dem Dezimalpunkt angeben. Bei der formatierten Ausgabe werden der Variablen Leerzeichen vorangestellt, wenn die Gesamtstellenzahl größer als die Stellenzahl der Variablen ist. Damit wird ermöglicht, Werte für Tabellen dezimalpunktgenau am Bildschirm oder auf dem Drucker untereinander ausgeben zu lassen. Sehen Sie hier nun ein Beispiel mit Ergebnisausgabe auf dem Bildschirm für eine formatierte und eine nichtformatierte Ausgabe. Befehl Ergebnis nichtformatierte Ausgabe WriteLn ( Strom ); 1.3421645E-02 formatierte Ausgabe WriteLn ( ' Ibe = ', Strom:5:1, ' mA' ); Ibe = 13.4 mA Die Eingabeanweisung Hier wird im Quelltext hinter dem Schlüsselwort Read oder ReadLn in Klammern der Variablenname angegeben, in der die Eingabe gespeichert werden soll. Also einfach : ReadLn ( Laenge ); und schon wird die Eingabe über die Tastatur in der zuvor deklarierten Variablen mit dem Namen Laenge abgespeichert. Mehrfacheingaben in einem Quelltextbefehl sind zwar möglich, aber nicht zu empfehlen. Besonderheiten bei der Eingabe • die Anweisung ReadLn; ohne folgende Klammer mit Variablenname wartet lediglich auf den Tastendruck der RETURN - bzw. ENTER Taste. • Reelwertige Zahlen werden mit Punkt statt mit Dezimalkomma eingegeben; also 27.12 statt 27,12 ! • sehr große oder sehr kleine Zahlen werden sinnvoller weise als Exponentialzahlen eingegeben, wobei der Großbuchstabe E die Angabe der Basis 10 ersetzt. So wird z.B. statt 0.00000003 besser 3E-8 und statt 6200000 besser 6.2E6 eingegeben. Tip : Durch Eingaben wie 999E32 oder 0.1E-32 lässt sich die Eingabe der beiden elektrotechnischen Grenzfälle Unendlich und Null simulieren, ohne eine -mathematisch nicht erlaubte- Division durch Null zu provozieren. 11.07.02 8-StEin- Ausgabe HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : BEISPIELLÖSUNG EVA-PRINZIP Münster 9/25 Datum : Entwicklung eines linearen Programms 1) Lastenheft ; Pflichtenheft : In Amerika wird die Temperatur nicht in Grad Celsius, sondern in Grad Fahrenheit gemessen. Es gilt : 0 °C ≡ 32 °F; 100 °C ≡ 212 °F Entwickeln Sie ein Programm, das nach Eingabe des Temperaturwertes in Grad Celsius den zugehörigen Wert in Grad Fahrenheit auf dem Bildschirm sauber geordnet und lesbar ausgibt. 2) Problemanalyse : a) Eingabevariable: T_Celsius ; Datentyp : kurze ganze Zahl, also SHORTINT; b) Ausgangsvariable T_Fahrenheit ; Datentyp : vermutlich reelwertig; also REAL c) Benötigt wird die Bildschirmbibliothek CRT ( cathode ray tube ) d) Algorithmus : Während die Temperatur in Celsius um 100 Grad steigt, steigt Sie in Fahrenheit um 180 Grad 212 °F - 32 °F = 180 °F ; d.h. das Verhältnis zwischen den Temperaturen beträgt 180/100 oder gekürzt 9/5. Außerdem ist die Temperatur in Fahrenheit um 32°F konstant höher. Daraus ergibt sich der Algorithmus zur Umrechnung : T_Fahrenheit = 9 °F/5 °C • T_Celsius °C + 32 °F 3) Programmstrukturierung a) Struktogramm Programm Fahrenheit b) Programmablaufplan Start Deklaration Beginn Bildschirm löschen Überschrift ausgeben Eingabe des Celsiuswertes Berechnung des Fahrenheitswertes Ausgabe des Fahrenheitswertes Ausgabebildschirm fixieren Ende 4) Codierung ohne Programmdokumentation Deklaration Bildsch. löschen Ausgabe Überschrift Eingabe T_Celsius Berechnung T_Fahrenheit Ausgabe PROGRAM Fahrenheit; T_Fahrenheit USES CRT; VAR T_Celsius : SHORTINT; Bildschirm T_Fahrenheit : REAL; fixieren BEGIN ClrScr; WriteLn(´Umrechnungsprogramm Grad Celsius in Grad Fahrenheit´); Ende Write (´Bitte geben Sie die Temperatur in Grad Celsius ein :´); ReadLn ( T_Celsius ); T_Fahrenheit := 9 / 5 * T_Celsius + 32; WriteLn(´Die Temperatur in Grad Fahrenheit beträgt : ´, T_Fahrenheit:6:2 ,´ °F´); ReadLn; END. 11.07.02 9-beispiel-eva HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : DOKUMENTATION Münster 10/25 Datum : 10 Regeln für die Dokumentation: Sie alle werden folgende Situation kennen lernen : Das Programm läuft, Codierfehler gibt es keine mehr und man ist fertig mit dem „Hacken“. Das Programm ist abgespeichert und man lehnt sich ruhig zurück. Zwar ist der Quelltext noch in einem chaotischen Zustand, aber was soll’s, das Problem ist ja gelöst. Wie der Lehrer mit dem Programm klarkommt ist sowieso unwichtig. Sein Problem ! Nach einigen Wochen aber benötigen Sie selbst Teile dieses Programms erneut. Zwar ist ihr altes Programm noch immer in chaotischem Zustand, aber kein Problem, es gibt ja Programmlistings über den Drucker, um den Überblick wieder zu bekommen. Der Programmablaufplan ist sowieso verschwunden und wenn nicht, dann weiß man nicht mehr zu welchem Programm er gehört. Darüber hinaus werden Sie sich fragen, welche Bedeutung die Variablen x, y und z damals hatten. Welche Taste war mit „ #69 “ gemeint ? Wieso ist an die Formel der Zusatz 2•π/180 angehängt worden ? Und so weiter ... Schließlich schreien Sie wieder nach dem Lehrer, der im hausgemachten Chaos zu retten versucht, was zu retten ist. Dies alles kostet Zeit, Papier und Nerven. Kurz und gut: Langsam aber sicher wächst das planlose Chaos Dies alles lässt sich vermeiden, wenn man sein Programm vernünftig dokumentiert. Schauen Sie sich deshalb das folgende Negativprogramm an. Obwohl es einfach ist, ist es dennoch schwer nachzuvollziehen. program test1; const x=60; var y,z :real; begin write(´gesamt´); readln(y); z:=100*x/y; write (´1/100KM´); writeln(z:10:2); end. 1) Befehle für Pascal Kontrollstrukturen schreibt man ausschließlich in Großbuchstaben; ebenso wie die Schlüsselwörter für den Programmkopf und den Vereinbarungsteil. Auch Operatoren schreibt man komplett groß; z.B.: PROGRAM, IF .. THEN .. ELSE oder XOR . 2) Bei Standardfunktionen und Standardprozeduren wird nur der erste Buchstabe groß geschrieben. Ausnahme bilden die aus zwei eigenen Wörtern zusammengesetzten Ausdrücke, bei denen jeweils der Anfangsbuchstabe alleine groß geschrieben wird; z.B.: ArcTan, WriteLn, KeyPressed oder ReadLn. 3) Pro Zeile wird im Quelltext nur ein einziger Befehl notiert. 4) Konstanten und Variablen erhalten eindeutige Bezeichnungen, die entweder genormt sind oder aus denen die Bedeutung klar hervorgeht. z.B. ist „ T “ nicht die Zeit, sondern die Periodendauer in Sek. 5) Variablen und Konstanten werden im Quelltext mit Kommentaren versehen, aus denen z.B. die Einheiten und der Einheitenvorsatz deutlich werden. Kommentare stehen entweder zwischen geschweiften Klammen { .... } oder zwischen den kombinierten Zeichen (* .... *). Sie werden nicht mit kompiliert. 6) Jedes Programm erhält einen Programmkopf als Kommentar, aus dem die Daten zur Ort, Zeit, Version und Autor; sowie zur verwendeten Hard- und Software hervorgehen. Darüber hinaus erhält der Programmkopf eine kurze Programmbeschreibung mit evtl. Besonderheiten als Hinweis. 7) Zwischen den einzelnen Programmteilen sind Leerzeilen im Quelltext vorzusehen. 8) Eingeklammerte Programmteile, z.B. Schleifenkörper oder Programmteile zwischen BEGIN und END werden um zwei Spatien eingerückt. Erfolgt dort eine weitere Einklammerung, wird nochmals um zwei Spatien eingerückt und so weiter. Mit Beendigung der Klammer entfällt das Einrücken. 9) Vor jeder Dateneingabe wird eine Anfrage des Rechners ausgegeben. Programmausgaben erfolgen in sinnvoller Art und Weise und nicht in Form von U = 1,3421645E-02, ohne Einheiten und ohne elektro-technische Notation, sondern in Form von : Uaus = 13,4 mV 10) Programme erhalten einen eindeutigen Namen, natürlich nach den Regeln von MS-DOS. Nur wenn Sie sich an alle diese Regeln halten, nehmen Dozenten oder Zeitschriften Ihre Programme an. Sie ersparen sich auch viel Ärger in Datennetzen und bei Kommilitonen während des Studiums. Nach einiger Zeit des Eingewöhnens werden Sie sehen, dass dies ganz normal ist und auch einen Sinn hat. 11.07.02 10-dokumentation HansBöcklerSchule Münster Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : ÜBUNGSAUFGABEN ZUM LINEAREN PROGRAMMABLAUF 11/25 Datum : Übungsaufgaben für lineare Programme Bevor Sie beginnen, Ihre ersten Programme in Turbo-Pascal zu programmieren erinnern Sie sich bitte daran, dass ein strukturiertes Vorgehen das Wichtigste überhaupt ist. Programmierknechte, die später Ihre gedankliche Arbeit in einen Quelltext umsetzen gibt es auf dem Arbeitsmarkt genug. Wenn überhaupt, dann entwickeln Sie als Ingenieur später nur das Konzept und die Dokumentation. Beachten Sie also die Hinweise zur Programmentwicklung auf dem Blatt 4/25 ! Aufgabe 1: Ein Messwerk mit einem Innenwiderstand von 1500Ω hat einen Endausschlag von 1,5 V. Schreiben Sie ein Programm, das nach der Eingabe eines gewünschten Messbereichs den benötigten Vorwiderstand in kΩ ausgibt. Folgende Bildschirmdarstellung sei fürs erste vorgeschlagen : Meßbereichserweiterung =================== Geben Sie bitte den gewünschten Messbereich in Volt ein ? Der erforderliche Vorwiderstand für das Instrument beträgt : xxx yyyy.yy kΩ Aufgabe 2: Schreiben Sie zwei Programme, die Vektoren - z.B. aus der Elektrotechnik - umrechnen. a) Von der Polarform in die Rechteckform P ==> R b) von der Rechteckform in die Polarform R ==> P In der Elektrotechnik ist dies ein grundlegendes Rechenverfahren beim Umgang mit komplexen Zahlen in der Wechselstromtechnik. z.B. für die Impedanz Z = 100 Ω + j 230 Ω oder Z = |Z| + e jϕ Die Ausgaben sollten in folgender Form auf dem Bildschirm dargestellt werden : Vektor = xx.xx [ Einheit ] • e^ j yy.yy ° bzw. Vektor = xxx.xxx [ Einheit ] + j yyy.yyy [ Einheit ] Aufgabe 3: Das Volumen eines Gases ( 3000 cm3 = 3 l ) bei 20 °C und einem Druck von 998 hPa soll für die Normalbedingung ( 1013 hPa und 0 °C ) umgerechnet werden. Die Umrechnung kann mit der allgemeinen Gasformel, die den Zusammenhang zwischen Gasvolumen, Druck und Temperatur beschreibt, berechnet werden. Aufgabe 4: Ein Programm soll Sie nach Vornamen, Namen, PLZ, Ort, Straße und Hausnummer fragen. Nach der hoffentlich geglückten Eingabe der 6 Daten, soll das Programm auf Anfrage [ j(a) oder y(es) ] Ihre Daten mitten auf dem Bildschirm in Form einer Visitenkarte geordnet wieder ausgeben. Aufgabe 5: Zerlegen Sie die Aufgaben 1 bis 3 in Prozeduren ( siehe dazu Blatt 12/25 ) . Aufgabe 6: Laden Sie ein Register mit der Binärzahl: 0101 0101(2) und schieben Sie alle Bits im Register um zwei Stellen nach links. Verknüpfen Sie das Ergebnis logisch UND mit der Maske 1100 000(2) und geben Sie an, welches Bit im Register zum Schluss noch gesetzt ist. Und denken Sie daran : Program testing can be used to show the presence of bugs, but never to show their absence ! Zitat nach E.W.DIJKSTRA 11.07.02 11-übung-eva HansBöcklerSchule Münster Programmiertechnik Informationsblatt Klasse : Name : PROZEDUREN ALS UNTERPROGRAMME 12/25 Datum : Prozeduren Ein langes Programm kann sehr schnell unübersichtlich werden. Man fasst deshalb Teilprobleme zu Unterprogrammen zusammen. Aus dem Hauptprogramm werden diese Unterprogramme dann entsprechend aufgerufen. Das bringt vor allem dann Vorteile, wenn ein Unterprogramm mehrfach genutzt werden kann. In Turbo-Pascal unterscheidet man zwei Arten von Unterprogrammen ( subroutines ). a) die Prozeduren ( PROCEDURE ) - sie bewirken etwas nur dadurch, dass sie aufgerufen werden Beispiel : ClrScr; GotoXY(x,y); Randomize; Delay(x) usw. b) die Funktionen ( FUNCTION ) - sie liefern bei ihrem Aufruf stets nur einen Wert an eine Variable Beispiel : y:= sin(x); y:= sqrt(x); y:= round(x); y:=int(x); usw. Subroutinen sind aber in Turbo-Pascal nicht nur fest vorgegeben, wie die obigen Beispiele, sondern sie können von uns auch selbst erstellt werden. Das ist z.B. unbedingt notwendig, wenn man ständig im Hauptprogramm die gleiche Berechnung durchzuführen hat oder mathematische Funktionen wie z.B.: y:= n! (Fakultät); y:= arcsin(x); y:= ab oder auch y:= log(x) benötigt, die in Turbo-Pascal nicht zur Verfügung stehen. Wenn man dann eine größere Anzahl von Prozeduren und Funktionen erstellt und gesammelt hat, kann man in einem späteren Arbeitsschritt diese Subroutinensammlung in einer eigenen UNIT zusammenfassen und im Deklarationsteil mit USES <Name>; aufrufen ( s.S.13/20 ). Alle Subroutinen sind dann stets verfügbar. a) einfache parameterlose Prozeduren Unterprogramme müssen im Hauptprogramm zunächst deklariert werden. Das geschieht mit dem Schlüsselwort PROCEDURE gefolgt vom selbst gewählten Namen des Unterprogramms und dem Semikolon. Der Anweisungsteil der Prozedur steht genau wie beim Hauptprogramm zwischen BEGIN und END; hier allerdings gefolgt von einem Semikolon ! PROCEDURE Eingabe; VAR .... BEGIN Anweisung 1; Anweisung ..; END; Im Hauptprogramm wird das Unterprogramm nur mit seinem Prozedur-Namen – und evtl. mit Parameterangaben - aufgerufen ( hier: Eingabe; ). Das Schlüsselwort Procedure entfällt beim Aufruf der Subroutine. b) Lokale und globale Variable in Prozeduren Prozeduren sind fast genau so aufgebaut wie Programme selbst. Sie können deshalb auch einen eigenen Deklarationsteil enthalten. Variable, die innerhalb der Prozedur deklariert worden sind, gelten nur innerhalb dieser Prozedur. Im übergeordneten Hauptprogramm sind sie unbekannt. Man nennt sie lokale Variable. Im Hauptprogramm deklarierte Variable sind im ganzen Programm, also auch in den Unterprogrammen gültig. Werden sie im Unterprogramm verändert, so haben sie auch im Hauptprogramm geänderte Werte. Es können also unerwünschte „Seiteneffekte“ entstehen. Man nennt solche Variablen globale Variable. Innerhalb einer Prozedur können im Vereinbarungsteil weitere ( Unter- ) Prozeduren definiert werden, die aber nur aus diesem Unterprogramm heraus aufgerufen werden können. c) Prozeduren mit Wert-Parameterübergabe ( call by value ) Einer Prozedur können Werte übergeben werden. Dazu wird der Prozedurkopf um Namen und Datentypenbezeichnung der empfangenen Variablen ergänzt. Also beispielsweise: PROCEDURE Addiere ( x, y : Byte ); Beim Aufruf der Prozedur im Hauptprogramm müssen natürlich die Parameter mit übergeben werden, wobei darauf zu achten ist, dass die Datentypen der einzelnen Parameter auch übereinstimmen. z.B.: Addiere ( 2,4 ); Da Wert-Parameter nicht verändert werden können ( es gibt ja keinen Speicherplatz, der für sie reserviert ist ), ist eine Rückgabe des veränderten Wertes an das Hauptprogramm nicht möglich. d) Prozeduren mit Variablen-Parameterübergabe ( call by reference ) Benötigt man veränderte Wert-Parameter später noch im Hauptprogramm, so muss man Variablen-Parameter im Prozedurkopf vereinbaren. Sie werden durch ein vorangestelltes VAR im Prozedurkopf gekennzeichnet. Beispiel : PROCEDURE Addiere ( VAR X, Y : Integer); Beim Aufruf im Hauptprogramm dürfen hinter dem Prozedurnamen aber nur Variable - und keine Konstanten oder arithmetischen Ausdrücke - angegeben werden, da diese ja an die geänderten Parameter zurückgegeben werden. Beispiel : Addiere ( a,b ); 11.07.02 12-prozeduren Programmiertechnik Informationsblatt HansBöcklerSchule Klasse : Name : FUNKTIONEN ALS UNTERPROGRAMME Münster 13/25 Datum : Funktionen Funktionen sind spezielle Prozeduren, die als Ergebnis genau einen einzigen Wert, den Funktionswert, an das aufrufende Programm zurückliefern. Auch sie müssen im Deklarationsteil des Hauptprogramms vereinbart werden. Das Schlüsselwort lautet FUNCTION gefolgt von dem Namen und der formalen Parameterliste. Zusätzlich wird hinter einem Doppelpunkt immer ein Datentyp als Ergebnistyp erwartet. Eine Funktion gehorcht daher folgender Syntax : FUNCTION < Name > (< Parameterliste> : < Datentyp > ) : < Ergebnistyp >; VAR ...; BEGIN .... < Anweisungen >; < Name > := < Berechnung der Funktion >; .... END; Auch bei Funktionen können Wert-Parameter und Variablen-Parameter übergeben werden. Allerdings ist die Verwendung von Variablen-Parametern in Funktionen wenig sinnvoll, da nun zusätzlich zum einzelnen Funktionswert noch weitere Variablen übergeben werden können, was dem eigentlichen Sinn der Funktion entgegensteht. Nutzen Sie in einem solchen Falle Prozeduren. Beispiel: Es soll eine Funktion mit dem Namen „Sinus“ geschrieben werden, die die Eingabe des Winkels im üblichen Gradmaß erlaubt und den berechneten Wert an die Variable y übergibt. PROGRAM Test_einer_Funktion; USES CRT; Programmkopf VAR X,Y : REAL; Deklarationsteil FUNCTION Sinus( Winkel : REAL ): REAL; BEGIN Sinus := Sin( Winkel * Pi / 180 ); END; BEGIN (* Hauptprogramm *) ClrScr; Write (´Bitte Winkel eingeben : ´); ReadLn(X); Y := Sinus (X); Write (´Der Sinus des Winkels ´, X:7:2,´ beträgt : ´, Y :7:5 ); END. Anweisungsteil E ingabe V erarbeitung A usgabe Der Vorteil von Funktionen gegenüber Prozeduren besteht darin, dass sie im Hauptprogramm wie eine Variable behandelt werden und nicht wie eine Prozedur als Anweisung. Deshalb können nur Funktionen direkt in allen Ausdrücken z.B. Ausgabeanweisungen aufgerufen werden, ohne den Ausgabewert zuvor einer Variablen zuweisen zu müssen. Für das obige Beispiel wäre also auch folgende Ausgabeanweisung erlaubt : WriteLn(´Der Sinus des Winkels ´,X:7:2,´ beträgt : ´, Sinus(X):7:5 ); Ruft man Prozeduren oder Funktionen in ihrem eigenen Anweisungsteil selbst immer wieder auf, so nennt man eine solche Subroutine rekursiv. Aber Vorsicht, der Heap-Speicher kann überlaufen. 11.07.02 13-funktionen HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : UNITS Münster 14/25 Datum : Hat man viele zusammengehörige Prozeduren und Funktionen gesammelt, die zum Beispiel die Maus unter Turbo-Pascal steuern, den Datenaustausch über die serielle Schnittstelle regeln oder auch selbstgebastelte, erweiterte mathematische Funktionen, so kann man diese Programmteile in UNITS zusammenfassen. Die Vorteile liegen auf der Hand : - Prozeduren / Funktionen müssen nur einmal geschrieben werden - Programme werden kürzer und übersichtlicher - zu einem Thema gehörende Subroutinen werden geordnet zusammengefasst Eine Unit besteht aus drei Teilen : 1) dem Interface ( der Schnittstelle ); 2) der Implementation ( d.h. dem tatsächlichen Programmkode ) und 3) der Initialisierung ( einer Art Hauptprogramm ). Die grundsätzliche Struktur der Unit ist weitgehend mit der eines Programms vergleichbar. Ihr Aufbau ist anschließend aufgeführt : UNIT < name >; { Das Schlüsselwort UNIT ersetzt hier den Begriff PROGRAM } INTERFACE { der Interface-Teil wird als „öffentlicher“ Teil bezeichnet. Er enthält alle Namen der Konstanten, Standard-Units, Variablen, Funktionen und Prozeduren, die dem Hauptprogramm zu gänglich sein sollen. Damit sind diese Elemente global vereinbart. Funktionen und Prozeduren werden allerdings nur mit ihren vollständigen Kopfteilen aufgeführt. } IMPLEMENTATION { Der eigentliche Quellkode der bereits im Interface-Teil genannten Funktionen oder Prozeduren erfolgt erst hier. Hier werden auch die lokalen Konstanten, Datentypen und Variablen vereinbart, die nur innerhalb der Unit gelten. BEGIN (* INITIALISIERUNG *) { bleibt meist leer, nur wenn beim Start des Programms bestimmte Einstellungen für diese Unit erforderlich sind, kann hier ein Anweisungsteil stehen; z.B. ein Reset. } END. Wird ein solches Unit-Programm mit dem Pascal Compiler übersetzt, so entsteht im gesetzten Pfad ( Menue OPTIONS; Schalter DIRECTORIES; EXE & TPU directory ) eine Objektkode - Datei mit der Extension: < Unitname > •TPU ( Turbo Pascal Unit ). Anschließend können Sie die Unit in Ihrem Programm mit der USES - Anweisung jederzeit aufnehmen. Aber das kennen Sie ja bereits von der Verwendung der Standard-Units her, die mit Turbo-Pascal bereits geliefert wurden; z.B.: USES CRT. Die anderen Standard Units heißen: SYSTEM, DOS, PRINTER, GRAPH, OVERLAY, TURBO3 und GRAPH3. Sie sind in der Datei Turbo.TPL ( Turbo Pascal Library ) zusammengefasst. Beispiel für eine Cursor-Unit ( mit Verwendung des Video-Interrupts 10hex ) UNIT Cursor; INTERFACE USES DOS; VAR regs : REGISTERS; PROCEDURE Cursor_weg; PROCEDURE Cursor_an; IMPLEMENTATION PROCEDURE Cursor_weg; BEGIN regs.ax:=$0100;regs.cx:=$2607;intr($10,regs); END; PROCEDURE Cursor_an; BEGIN regs.ax:=$0100; regs.cx:= $0C0D;intr($10,regs); END; BEGIN { Anweisungen entfallen } END. Mit dem Programm TPUMOVER.EXE ( im Pascal-Paket enthalten ) kann man seine eigenen Units in die Standard-Pascal-Library für Units ( TURBO.TPL ) fest mit aufnehmen bzw. wieder entfernen. Das heißt, man muss nicht mehr darauf achten, ob die eigene Unit im richtigen Pfad zur Verfügung steht. 11.07.02 14-units Programmiertechnik Informationsblatt HansBöcklerSchule Klasse : Name : WIEDERHOLUNGSSTRUKTUREN Münster 15/25 Datum : Schleifen; ( engl. loops ) In allen Programmen vorher befassten wir uns mit linearen Algorithmen; das waren Anweisungen, die eine nach der anderen schrittweise ausgeführt wurden. Nun kommt es aber häufiger vor, dass eine oder mehrere Anweisungen wiederholt durchlaufen werden müssen, weil Sie z.B. eine Eingabe falsch ausgeführt haben und nun noch einmal einlesen müssen. Oder Sie wollen die gleiche Rechnung noch einmal ausführen; allerdings mit geänderten Zahlenwerten. Wie auch immer, Sie müssen im Programm zurückspringen an die Stelle im Programm, die erneut durchlaufen werden soll. Allerdings nur so lange, bis eine Anweisung die Wiederholung verbietet. In Pascal stehen Ihnen dazu drei Möglichkeiten der Schleifenprogrammierung zur Verfügung : W iederholungsanweisungen nein Anzahl der W iederholungen bekannt ? zählergesteuerte Schleife bedingungsgesteuerte Schleife ja Abbruchbedingung am Anfang der Schleife kopfgesteuerte Schleife ( pre check loop ) Syntax der Anweisung : Abbruchbedingung am Ende der Schleife fußgesteuerte Schleife ( post check loop ) Ist die Anzahl der Schleifendurchläufe bekannt, so nutzt man die zählergesteuerte Schleife. Dazu gehört, dass man zunächst eine Zählervariable oder auch Laufvariable deklariert die mitzählt, wie oft die Schleife schon durchlaufen wurde. Es versteht sich von selbst, dass der Datentyp dieser Variablen eine Integerzahl bzw. eine ordinale Größe sein muss. Ist der Endstand erreicht, bricht die Schleife ab. FOR <Laufvariable> := <Anfangswert> (DOWN)TO <Endwert> DO BEGIN < Anweisungen > ; END; Im Gegensatz zu anderen Programmiersprachen ist es bei dieser Anweisung nicht möglich, die Schrittweite anzugeben. Man weicht dann auf die beiden anderen Schleifenanweisungen aus. Schleife mit Endebedingung Schleife mit Anfangsbedingung REPEAT < Anweisungen > ; UNTIL < Bedingung erfüllt > ; WHILE < Bedingung erfüllt > DO BEGIN < Anweisungen > ; END; Solange in beiden bedingungsgesteuerten Wiederholungen die Bedingung erfüllt, also wahr ist, werden die eingeklammerten Anweisungen wiederholt. Wird die Bedingung falsch, geht das Programm zum nächsten, der Schleife folgenden, Befehl über. Die eingeklammerten Anweisungen bezeichnet man auch als Schleifenkörper. Die graphische Darstellung der drei Schleifenkonstruktionen für das Struktogramm oder den PAP entnehmen Sie bitte dem Blatt 5/25. Im PAP müssen die bedingungsgesteuerten Schleifen durch Verzweigungen dargestellt werden. Zum Schluss noch eine Auswahl an Vergleichsoperatoren für die Bedingungsprüfung : = < gleich kleiner < > ungleich >= größer gleich > <= größer kleiner gleich Keypressed EoLn Durch logische Operatoren können auch mehrere Bedingungen gleichzeitig abgefragt werden, z.B. : (B1) AND (B2) (B1) OR (B2) (B1) XOR (B2) 11.07.02 15-schleifen HansBöcklerSchule Münster Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : ÜBUNGEN ZU WIEDERHOLUNGSSTRUKTUREN 16/25 Datum : Übungsaufgaben für Wiederholungsstrukturen Bevor Sie die einzelnen Aufgaben konkret angehen, denken Sie bitte daran, dass die strukturierte Vorgehensweise ( Seite 4/25 ) das vorrangige Lernziel darstellt. Gerade hier sind die Programmablaufpläne oder Struktogramme unbedingt erforderlich. Werden die Abbruchbedingungen vorher nicht genau geprüft, bleibt das Programm in der Wiederholungsschleife „hängen“ und kann nur mit Gewalt abgebrochen werden. Der Quelltext geht damit unweigerlich verloren. Aufgabe 1: a) Ein konstanter Widerstand von R = 330 Ω mit einer maximalen Leistung von P = 0,5 W wird an unterschiedlichen Spannungen U = 1 V bis 29 V in Schritten a´ 4 V betrieben. Ermitteln Sie für jeden Spannungswert den dazugehörigen Strom, und geben Sie die Werte tabellarisch geordnet auf dem Bildschirm aus. b) Ermitteln Sie zusätzlich jeweils auch den maximal zulässigen Strom durch den Widerstand. Geben Sie auch diese Werte mit Einheiten in der Tabelle mit aus. c) Zeichen Sie die Graphen sauber in ein beschriftetes Diagramm, und lesen Sie ab, welche Spannung Umax noch möglich ist, ohne den Widerstand zu zerstören. Welcher Strom IR fließt? Aufgabe 2: An eine Ersatzspannungsquelle Uo = 12 V mit konstantem Innenwiderstand Ri = 10 Ω wird ein passiver Zweipol angeschlossen. Leider ist der Widerstand des „Verbrauchers“ nicht konstant, sondern schwankt von 1 Ω bis 101 Ω ( wir beginnen erst bei 1 Ω, um im Programm die Division durch Null zu vermeiden ). Berechnen Sie den Strom I, die Klemmenspannung Uk und die am „Verbraucher“ abgegriffene Leistung Pab für die unterschiedlichen Belastungsfälle. Geben Sie die Werte I = f(RL), Uk = f(RL) und Pab = f(RL) tabellarisch am Bildschirm aus. Zeichen Sie in einem Diagramm sauber die Graphen, deren Werte Sie mit Ihrem Programm ermittelt haben. Was können Sie für Schlüsse ziehen, wenn es um die Leistungsaufnahme eines „Verbrauchers“ geht ? Welche Forderung stellen Sie an ein Netzteil, ein Ladegerät oder an eine Satellitenantenne ? Aufgabe 3: Innerhalb eines Programms soll eine Zahl eingelesen werden, die nicht kleiner als 20 aber auch nicht größer als 100 sein darf. Bei Falscheingaben muss der Wert neu eingelesen werden; und zwar solange, bis der Wert im Gültigkeitsbereich liegt. Programmieren Sie ein Unterprogramm, das diese Anforderung an die Eingabe übernimmt. Entwickeln Sie selbst ein Hauptprogramm, um die Subroutine zu kontrollieren. Aufgabe 4: Über die parallele Schnittstelle des Rechners, soll eine Platine mit 8 LEDs ( light emitting diode ) angesteuert werden. Die Leuchtdioden sollen dabei wie ein Lauflicht aufleuchten. Zur Programmierung über die parallele Schnittstelle siehe Blatt 17/25). Wie werden die LEDs angeschlossen ? Aufgabe 5: Ein Programm soll mitten auf dem Bildschirm in 10 Reihen und 10 Spalten das „Kleine Einmal-Eins“ in Form einer Tabelle ausgeben; so dass man sofort z.B. das Produkt von 7 * 6 ablesen kann. Aufgabe 6: Ein Potentiometer von 100 Ω wird als Spannungsteiler eingesetzt. An seinen Schleifer werden nacheinander die Lastwiderstände 5 Ω, 45 Ω, 85 Ω und 125 Ω angeschlossen. Berechnen Sie für jeden Lastwiderstand die Ausgangsspannung Uaus, wenn der Schleifer in 10 Ω – Schritten verändert wird. 11.07.02 16-übungen-loops Programmiertechnik Informationsblatt HansBöcklerSchule Klasse : Name : DIE PARALLELE SCHNITTSTELLE LPT Münster 17/25 Datum : Will man mit dem Computer reale Prozesse steuern oder überwachen, so erfordert dies zunächst einmal eine geeignete Verbindung zur Außenwelt. Ein Programm soll ja in der Lage sein, Informationen von außen zu erfassen und Steuersignale an äußere Geräte weiterzugeben. Das erforderliche Tor zur Außenwelt wird durch Interfaces geöffnet. Für PCs nach dem Industriestandard lassen sich, über die ohnehin vorhandenen Schnittstellen, die serielle Schnittstelle ( RS232 ), die Druckerschnittstelle ( Centronics ) und der Joystick-Anschluss direkt als Interface nutzen. Damit erübrigt sich jede weitere Hardware. Die parallele Schnittstelle ( LPT1 oder LPT2 ) des PCs stellt insgesamt 17 digitale Leitungen zur Verfügung, die sich für den schnellen Datenaustausch mit Interface-Schaltungen nutzen lassen. Die Einund Ausgänge sind TTL-kompatible Leitungen und nicht vor Überlastung geschützt ! Regeln : 1) Interfaceschaltungen nur bei ausgeschaltetem PC anschließen ! 2) An die Eingänge dürfen nur Gleichspannungen zwischen 0 V und 5 V gelegt werden ! 3) Ausgänge des Ports niemals kurzschließen oder mit anderen Ausgängen verbinden ! 4) An die Kontakte der 25-poligen Sub-D-Stecker keine Fremdspannungen anlegen ! 5) Alle Ausgänge dürfen nur mit maximal 10 mA „belastet“ werden ! 6) Induktive Lasten ( Relais, Motor ... ) grundsätzlich nur mit Freilaufdiode schalten ! Der Datenaustausch über den parallelen Port erfolgt über drei 8-Bit-Register, die jeweils unter einer Basisadresse ( BA ) und den beiden folgenden Adressen zu erreichen sind. Für die einzelnen Schnittstellen gelten folgende Basisadressen : Schnittstelle 1: LPT1 ⇒ $378 oder 888 Schnittstelle 2: LPT2 ⇒ $278 oder 632 Das erste Register heißt Datenregister und ist unter der Basisadresse zu erreichen. Es stellt ( in der Regel ) einen zusammenhängenden 8-Bit Ausgabeport zur Verfügung, dessen positive Spannungspegel sich im Bereich von 3,5 V bis 5 V bewegen (TTL-Pegel). Der Pascal-Befehl für die Ausgabe eines Bytes n über das Datenregister lautet : Datenausgabe Port [ BA ] := n ; Unter der Portadresse BA + 1 kann man das Byte des Statusregisters in eine Variable einlesen und auswerten. Diese Hilfsleitungen für den Drucker sind meist TTL-kompatibel, d.h. offene Eingänge erscheinen als High-Pegel. Das Lesen der Daten über das Statusregister mit gleichzeitiger Korrektur des invertierten Eingangs „ busy “und Ausblendung der unbenutzten Eingänge 20 bis 22 lautet : Datenregister Adresse : BA Variable := (Port [ BA+1 ] XOR 128) AND 248; 7 6 5 4 3 2 1 0 D0 .. D7 ausgeben 0 nur lesen Statusregister Adresse: BA + 1 7 6 5 4 3 2 1 error select paper empty acknow ledge busy (invertiert) Steuerregister Adresse: BA + 2 7 6 5 4 select-in (invertiert) init / reset autofeed (invertiert) strobe (invertiert) 3 2 1 0 ausgeben ( evtl. lesen ) Die Portadresse BA + 2 erlaubt den Zugriff auf das Steuer- oder Controlregister. Über die vier Steuerleitungen können Informationen ausgegeben werden. Da es sich aber um Open-Kollektor Ausgänge handelt, können sie auch gelesen werden, wenn man die Anschlüsse über 3,3 kΩ Widerstände gegen +5 V legt. Beachten Sie bitte, dass drei der vier Leitungen invertiert verwendet werden. Diese Invertierung kann aber bereits bei der Ein- oder Ausgabe über BA+2 wie folgt korrigiert werden : Ausgabe: Port [Ba+2] := n XOR 11; Eingabe: Variable:=(Port[Ba+2]XOR 11)AND 15; Das Bit 25 des Steuerregisters schaltet die Richtung des Datenflusses im Datenregister um, wenn die Schnittstelle bidirektional ist oder im ECP- oder EPP-Modus arbeitet (BIOS). 11.07.02 17-LPT Programmiertechnik Informationsblatt HansBöcklerSchule Münster Klasse : Name : ENTSCHEIDUNGS- BZW. VERZWEIGUNGSSTRUKTUREN 18/25 Datum : Im täglichen Leben müssen wir ständig Entscheidungen treffen. Meist sind es WENN .. DANN Entscheidungen, die oft erhebliche Auswirkungen haben. Auch in Programmen können wir solche Entscheidungen treffen. Solche Programme enthalten dann mindestens eine Bedingung, die darüber entscheidet, in welcher Reihenfolge die Anweisungen abgearbeitet werden. In Turbo-Pascal werden dabei folgende Auswahlstrukturen unterschieden : • Einfache Auswahl - einseitige Auswahl IF .. THEN .. Sie ist ein Sonderfall der zweiseitigen Auswahl, der sogenannten Alternative. - zweiseitige Auswahl ( Alternative ) IF .. THEN .. ELSE .. Die abgefragte Variable kann zwei Fälle abdecken. • Mehrfache Auswahl ( Fallstruktur ) CASE .. OF .. END; Die in der Bedingung abgefragte Variable kann beliebig viele Fälle annehmen. Bedingung erfüllt ja Anweisung 1 nein Anweisung 2 Bedingung erfüllt nein Anweisung a ja Ausdruck Anweisung 1 Anweisung 2 Fall1 Anweisung 1 Fall2 Anweisung 2 Fall3 Anweisung 3 Anweisung b IF < Bedingung=true > THEN BEGIN < Anweisungen > END ; IF < Bedingung=true > THEN BEGIN < Anweisungen 1,2 > END ELSE BEGIN < Anweisungen a,b> END ; CASE < Variable >OF < Wert1 > : BEGIN <Anweisungen 1> END; < Wert2 > : BEGIN <Anweisungen 2> END; < Wert3 > : BEGIN <Anweisungen 3> END; END; Die Verwendung der einzelnen Verzweigungsstrukturen können Sie den Ausschnitten der Programmablaufpläne entnehmen. Ihre zeichnerische Darstellung für die Struktogramme finden Sie auf der Seite 5/25. Es gibt eigentlich nur wenige Punkte bei der Programmierung zu beachten : • Wenn nach einer Auswahl nur eine Anweisung alleine ausgeführt werden soll, kann man die Einklammerung der Anweisung mit BEGIN und END entfallen lassen; man rückt sie dann etwas ein. • Vor ELSE darf bei der zweiseitigen Auswahl kein Semikolon stehen ( trotz END ), da der gesamte Befehl an dieser Stelle noch nicht beendet ist. • Bei der Mehrfachauswahl kann die Variable nur ordinale ( abzählbare ) Datentypen aufnehmen, d.h. der logische Vorgänger PRED( n ) oder Nachfolger SUCC( n ) muss bekannt sein. • Bei der Mehrfachauswahl kann deshalb die Variable auch aus „Characters“ bestehen. Sie steht/stehen dann in Hochkommata. Beispiel : CASE Variable OF ´A , a´ : BEGIN ... • Innerhalb eines Verzweigungsteils sind weitere Verzweigungen möglich; führen aber zu unübersichtlichen Programmen. Besser ist hier die Mehrfachauswahl geeignet. 13.07.02 18-verzweigungen HansBöcklerSchule Münster Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : ÜBUNGEN ZU VERZWEIGUNGSSTRUKTUREN 19/25 Datum : Übungsaufgaben Verzweigungsstrukturen : - Formulieren Sie das Problem in einem ganzen Satz. - Deklarieren Sie die notwendigen Konstanten, Variablen und deren Datentypen. - Skizzieren Sie den PAP und/oder das zugehörige Struktogramm. - Erstellen Sie den Quelltext und entfernen Sie alle Syntaxfehler. - Prüfen Sie Ihr Programm auf logische Fehler ( Testläufe ). - Dokumentieren Sie Ihr Programm. - Entfernen Sie Rechtschreibfehler aus Bildschirmmeldungen, und sorgen Sie für eine übersichtliche und sinnvolle Bildschirmdarstellung. Aufgabe 1: Prüfen Sie eine einzugebende Zahl auf ihr Vorzeichen; lassen Sie einen entsprechenden Kommentar ausgeben. Bedenken Sie auch die Grenzfälle des Zahlenbereichs ! Aufgabe 2: Lesen Sie das Statusbyte der parallelen Schnittstelle LPT2 ein, und lassen Sie ein Programm melden, ob die Leitung Acknowledge „high“ oder „low“ -Pegel hatte ( siehe Blatt 16/20 ). Aufgabe 3: Erweitern Sie Ihre linearen Programme, welche Vektoren umrechnen. Wahlweise von der Polarform in die Rechteckform ; oder von der Rechteckform in die Polarform. Die Wahl wird über ein Menue mit < P > und < R > gesteuert. Fehleingaben sollen zur Fehlermeldung führen; die Eingabe erfolgt dann erneut. Ihr Programm wird übersichtlicher, wenn Sie Ihre linearen Umrechnungsprogramme zunächst in Prozeduren verwandeln, die Sie im Hauptprogramm nur aufrufen müssen. Aufgabe 4: Der Laststrom und die Ausgangsspannung eines linearen Spannungsteilers soll berechnet werden. Dabei sollen Sie über ein Menue zwischen den drei Fällen : a) Kurzschluss; b) Leerlauf und c) Belastung wählen können. Als Referenzspannung sei hier 50 V vorgegeben. Wählen Sie mit <1>, <2> oder <3> . R1 = 220 Ω; R2 = 330 Ω; RL = 180 Ω . Schreiben Sie das Programm einmal mit IF .. THEN .. ELSE und einmal mit CASE .. OF .. END. Aufgabe 5: Ein Programm soll quadratische Gleichungen in der Form : ax2 + bx + c = 0 lösen können. Beachten Sie die Fälle, in denen die Diskriminante negativ oder gleich „Null“ wird ! Aufgabe 6: In den pascalinischen Sümpfen leben die vier Stämme der Asis, Belas, Cedis und Drudis. Forschungen haben ergeben, dass es vier Eigenschaften gibt, die eine Unterscheidung der Stämme erlauben : ein Bewohner der Sümpfe kann ( muss aber nicht ) manuseln, einen Knelt haben, löpsen und nopeln. Man weiß, dass nur die Asis einen Knelt haben und manuseln. Hat jemand keinen Knelt und nopelt, dann ist er gewiss ein Bela. Ein Bewohner mit Knelt, der nicht manuselt, ist ein Cedi, wenn er immer nopelt. Wer keinen Knelt hat und löpst, nie nopelt und stets manuselt, ist mit Bestimmtheit ein Cedi; würde er nicht manuseln, wäre er ein Drudi. Es ist geradezu typisch für Drudis, dass sie weder manuseln noch nopeln, aber einen ordentlichen Knelt haben. Ganz enthaltsame Bewohner, die keinen Knelt haben, nicht löpsen und nicht nopeln, sind Drudis, wenn sie manuseln, und Cedis, wenn sie nicht manuseln. Ein Programm soll nun die vier Eigenschaften eines Sumpfbewohners erfragen ( Antwort J/N ) und eine Diagnose liefern, zu welchem Stamm dieser gehört. Eine geschachtelte bedingte Anweisung, die genau der vorgegebenen Beschreibung folgt, löst das Problem. 11.07.02 19-übungen-verzw Programmiertechnik Informations- und Arbeitsblatt HansBöcklerSchule Klasse : Name : BEISPIEL KOMBINIERTE KONTROLLSTRUKTUREN TEIL 1 20/25 Datum : Münster Beispielaufgabe mit kombinierten Kontrollstrukturen: Zur Steuerung von Gleichstrom-Motoren sind Brückenschaltungen hervorragend geeignet. Man setzt die Gleichstrommotoren in deren Mitte und kann ohne großen Aufwand die Drehrichtungen ändern. Eine solche Schaltung, die zusätzlich vor späteren Softwarefehlern schützt, finden Sie in nachfolgender Skizze. Die Transistoren T1, T3 ( PNP ) und T2, T4 ( NPN ) bilden die Brückenschaltung, in deren Mitte der Motor sitzt. Die Dioden D1 bis D4 sind die Freilaufdioden für die Motorspule. D5 und D6 verhindern, dass bei falscher Ansteuerung nicht die beiden Komple120 metär-Transistoren der Brücke durchsteuern; so wird D6 Ue2 ein Kurzschluss zwischen Ground und Betriebsspannung vermieden. Die beiden Eingangstransisto2k7 2k7 ren T5 und T6 sind PNP - Transistoren und interpretieren offene Eingänge als logisch High. Angesteuert 120 werden sie über die Eingänge Ue1 und Ue2 mit loGround gisch Low. Ue1 und Ue2 liegen am Datenregister der parallelen Schnittstelle auf den beiden niederwertigsten Bits ( Adressen : s.S. 17/25 ) . +5V .. +12 V D1..D4 = 1N4001 D5, D6 = 1N4148 T1 , T3 = BD242 T2 , T4 = BD241 T5 , T6 = BD140 T1 T3 D1 D3 120 D5 M Ue1 2k7 2k7 T2 D2 D4 T4 120 Aufgabe : Schreiben Sie ein Pascal-Programm, das die Drehrichtung des Gleichstrommotors mit den Tasten < R > für Rechtslauf, < L > für Linkslauf und < S > für Stopp steuern kann. Der Motor soll im Programm mehrfach umgeschaltet werden können. Der Abbruch des Programms soll über die ESCAPE - Taste erfolgen. Problemanalyse : Der Motor lauft im Rechtslauf, wenn Ue1 = high und Ue2 = low Pegel erhält. Steuerbyte : 0000 0001 = 1 dez. Der Motor lauft im Linkslauf, wenn Ue1 = low und Ue2 = high Pegel erhält. Steuerbyte : 0000 0010 = 2 dez. Der Motor steht, wenn Ue1 = high und Ue2 = high Pegel erhält. Steuerbyte : 0000 0011 = 3 dez. Die Escape-Taste ist im ASCII-Kode durch „ #27 “ definiert und kann über eine Variable eingelesen werden. Programmentwurf : Programm Drehrichtungssteuerung S ta rt Deklaration Beginn R D e kla ra tion Bildschirm löschen L Steuerleitungen für den Motor auf Stillstand setzen Überschrift ausgeben S teu erleitun g en auf R ese t Menue zur Steuerung ausgeben Auswahl einlesen Ist die Auswahl = R Steuerbyte "2" Rechtslauf L Steuerbyte "1" B ild sch irm lö s ch e n Linkslauf Stopp S teuerbyte Linkslauf ausgeben S teuerb yte S topp ausgeb en Ü berschrift und M en ue ausgeben n e in S Steuerbyte "3" S S teuerb yte R echtslauf ausgeben A u s w ah l ein les en E sc ap e ? S teu erleitun ge n au f R eset wiederhole bis die Escape Taste betätigt wurde Schnittstellen Reset ( Motor Stillstand ) W ah l ? E nde Ende 13.07.02 20-beispiel-1 HansBöcklerSchule Münster Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : BEISPIEL KOMBINIERTE KONTROLLSTRUKTUREN TEIL II 21/25 Datum : Quelltext (**********************************************************************) (* Programm : Drehrichtungs-Steuerung *) (* Software : COMPILER Turbo Pascal 7.0 unter MS-DOS 6.22 *) (* Hardware : Pentium 133 MHz, VGA-Karte *) (* Ort/Datum : Hans-Böckler-Schule, 48155 Münster 11.07.02 *) (**********************************************************************) { Dieses Programm steuert die Drehrichtung eines Motors über die } { Leitungen Bit1 und Bit2 des Datenregisters der parallelen Schnitt- } { stelle LPT2. } { Der externe Motor sitzt in einer Brückenschaltung mit Transistoren } PROGRAM Drehrichtungs_Steuerung; USES CRT; CONST LPT = 632; (* Adresse LPT2 *) Zeitkonst = 3000; (* 3000 ms = 3 s *) VAR Eingabe : Char; BEGIN (* Hauptprogramm *) ClrScr; Port[LPT]:= 3; (* Bit1= 1 ; Bit2= 1 *) GotoXY(1,3); TextColor(6); WriteLn ('Drehrichtungssteuerung eines Motors'); TextColor(7); WriteLn; WriteLn('Geben Sie bitte die gewünschte Steuerung an :'); WriteLn; WriteLn('Rechtslauf < R >'); WriteLn('Linkslauf < L >'); WriteLn('Stopp < S >'); Write ('Abbruch mit < ESC > ==> '); REPEAT Eingabe := ReadKey; CASE Eingabe OF 'R','r' : BEGIN Port[LPT] := 1; (* Bit1= 1 ; Bit2= 0 *) GotoXY(1,13); ClrEol; WriteLn('Der Motor läuft nun im Rechtslauf.'); GotoXY(33,11); END; 'L','l' : BEGIN Port[LPT] := 2; (* Bit1= 0 ; Bit2= 1 *) GotoXY(1,13); ClrEol; WriteLn('Der Motor läuft nun im Linkslauf.'); GotoXY(33,11); END; 'S','s' : BEGIN Port[LPT] := 3; (* Bit1= 1 ; Bit2= 1 *) GotoXY(1,13); ClrEol; WriteLn('Der Motor steht nun.'); GotoXY(33,11); END; END; UNTIL Eingabe = #27; (* ASCII Nr.27≡Escape*) ClrScr; GotoXY(20,10); Textcolor(18); Write('That`s all folks ....'); Port[LPT]:=3; (* Bit1= 1 ; Bit2= 1 *) END. 11.07.02 21-beispiel-2 HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : ARRAYS / FELDER Münster 22/25 Datum : Information : Bei vielen Problemstellungen wäre eine Lösung nur sehr schwer und umständlich zu programmieren, wenn nur die einfachen Datentypen CHAR, REAL, INTEGER usw. zur Verfügung stünden. Deshalb bieten viele Programmiersprachen die Möglichkeit, aus den einfachen Datentypen weitere Datentypen zusammenzusetzen. Man nennt solche Datentypen strukturierte Datentypen. Je nachdem wie die neuen Datenstrukturen gebildet werden, unterscheidet man in Pascal zwischen • Feld : ARRAY ( Zusammenfassung mehrerer Elemente gleichen Datentyps ) • Menge : SET ( bestimmte Anzahl von Elementen eines ordinalen Datentyps ) • Satz : RECORD ( Zusammenfassung von Daten unterschiedlichen Datentyps ) • Datei : FILE ( Folge von Sätzen, die meist die Struktur eines Records haben ) Ziel : Hier soll zunächst nur der zusammengesetzte Datentyp ARRAY besprochen werden. Ein ARRAY – oft auch Feldvariable genannt – können Sie sich wie ein Regal mit vielen Fächern vorstellen. In jedem der Fächer kann ein Gegenstand gleichen Typs aufbewahrt werden. Dabei kann es vorkommen, dass die Fächer nicht nur nebeneinander, sondern in mehreren Reihen übereinander oder sogar zusätzlich noch hintereinander liegen. Wollen Sie nun jemanden beauftragen , einen Gegenstand zu holen, so bitten Sie ihn beispielsweise, den Gegenstand aus dem linken Fach in der zweiten Reihe von oben zu entnehmen. Um also auf eine Variable in einem Feld zuzugreifen, nennen Sie lediglich die Lage ( den Index ) im Feld. Dieser Index muss deshalb als Variable vorab deklariert werden. Natürlich muss das Feld selbst auch im Deklarationsteil vereinbart werden. Allgemein gilt für die Felddeklaration folgende Syntax : VAR < FeldBezeichner > : ARRAY [ < IndexAnfang > .. < IndexEnde > ] OF < Datentyp > ; Da wir hier nur einen einzigen Index verwenden, spricht man von einem eindimensionalen Feld ähnlich einer einzigen Reihe von nebeneinander gelegenen Schubladen im Regal. Nur .., die Schubladen sind im Moment noch leer, denn die Felder wurden noch nicht gefüllt. Auf sie kann, durch einen in eckigen Klammern angegebenen Index, während der Laufzeit des Programms lesend oder schreibend zugegriffen werden. Daten aus der Tabelle lesen Wert := FeldBezeichner [ Index ] ; Daten in die Tabelle schreiben FeldBezeichner [ Index ] := Wert ; Sie können aber nicht nur ein dynamisches Array zur Laufzeit erzeugen, sondern bereits zur Entwurfszeit können die Einträge in eine Feldvariable erfolgen. Dazu muss das Array lediglich als typisierte Konstante deklariert werden, dem die Einträge (Items) sofort zugewiesen werden. Beispiel : CONST Woche : ARRAY [ 1.. 7 ] OF STRING = (’Montag’, ’Dienstag’, ’Mittwoch’ , ... , ’Sonntag’); Soll die Feldvariable außer Zeilen auch noch Spalten enthalten so spricht man von einem zweidimensionalen Feld, oft auch als Matrix oder Tabelle bezeichnet. Auch hier müssen die Elemente vom gleichen Datentyp sein; lediglich ein zweiter Index muss vereinbart werden, um sowohl die Zeile als auch die Spalte richtig adressieren zu können. Auch dreidimensionale und noch höherdimensionale Felder sind möglich, sprengen jedoch schnell die Speichergrenzen und können jenseits der drei Dimensionen nur noch sehr schwer verstanden werden. Mit dem Compilerbefehl { $R+ } können sie eine Bereichsüberprüfung einschalten, um zu verhindern, dass ein Zugriff über die Grenzen eines Feldes hinaus erfolgt. Die Deklaration und der Zugriff auf ein zweidimensionales Feld erfolgt wie im Beispiel: Deklaration VAR Bezeichner : ARRAY [n..m, x.. y] OF WORD; Zugriff Wert : = Bezeichner [ Index1, Index2 ]; Ein mehrdimensionales Array kann auch anders deklariert werden; für welche Art Sie sich entscheiden bleibt Ihnen überlassen : VAR MyArray : ARRAY [ n..m ] OF ARRAY [ x..y ] OF DatenTyp; 11.07.02 22-arrays HansBöcklerSchule Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : RECORDS BZW. VERBUND Münster 23/25 Datum : Eine Vereinigung von Daten unterschiedlichen Typs wird als Datensatz bezeichnet. Pascal kennt zur Darstellung eines solchen Datensatzes den Datentyp Record - auch als Verbund bekannt, in dem sich viele unterschiedliche Datenfelder vereinen lassen. Im Gegensatz zum Array ( Feld ) können hier unterschiedliche Datentypen zu einer Einheit zusammengefasst werden. Die entstehenden Variablen nennt man deshalb Verbund- bzw. Recordvariable. Beispiel : Bei der Auswertung von Lottozahlen, die in einer Tippgemeinschaft spielen, muss sichergestellt sein, dass die einzelnen Tippreihen, die aus 6 Zahlen zwischen 1 und 49 bestehen, dem einzelnen Spieler zugeordnet werden können. Zunächst initiiert man daher eine Variable Spieler und deklariert sie als Record : VAR Spieler : Record Name : String[20]; Tippreihe : Array[1..6] OF Byte; End; Der Zugriff auf die Einzeldaten im Record erfolgt über den Variablennamen und den Feldnamen, die durch einen Punkt, den sogenannten Qualifizierer, getrennt sind. Hier z. B.: WriteLn ( Spieler.Name ); Es muss also ständig der Verbundvariablen_Name und der Feld_Name angegeben werden, was mit viel Schreibarbeit verbunden ist. Deshalb gibt es in Pascal die Möglichkeit, die Schreibweise mittels der WITH-Anweisung abzukürzen und auf den Verbundvariablen_Namen zu verzichten. In allgemeiner Form lautet die Anweisung : WITH Verbundvariable DO Begin Anweisung_1; Anweisung_2; …; end; Für unseren Fall gilt: WITH Spieler DO Begin WriteLn ( Name ); FOR n := 1 TO 6 DO Write ( Tippreihe [n] :6 ); end; Da die Datensätze für alle Spieler der Tippgemeinschaft gleich sind, liegt es nahe, dass man die Spieler in einem eindimensionalen Feld ( Array ) zusammenfasst. Man bildet dafür eine zusammengesetzte Datenstruktur das : Array Spielergemeinschaft mit 1.. n Records Spieler 1 Name Tippreihe Spieler 2 Name Tippreihe Spieler 3 Name Tippreihe Spieler n Name Tippreihe VAR Spielgemeinschaft : ARRAY [ 1 .. n ] OF Record Name : String[20]; Tippreihe : Array [ 1.. 6 ] OF Byte; End; Der allgemeine Zugriff auf diese Datenstruktur erfolgt über Feldvariablen_Name[Index].Feld_Name Aufgabe : Entwickeln Sie eine Musteranwendung für eine Tippgemeinschaft mit 5 Spielern. Per Zufallsgenerator sollen für alle 5 Spieler die Tippreihen gezogen werden. Über ein Menue kann auf die Daten der Spieler zugegriffen werden. 11.07.02 23-records HansBöcklerSchule Programmiertechnik Informations- und Arbeitsblatt Klasse : Name : MENGEN ( SETS ) Münster 24/25 Datum : Information: Interessanterweise gehören Mengen zu den Pascal-Strukturen, die am wenigsten eingesetzt werden. Das mag daran liegen, dass die Unterstützung von Mengen nur in Pascal unterstützt wird und in den meisten Programmiersprachen nicht. Der Begriff Menge oder Set stammt aus der Mengenlehre und beschreibt eine Ansammlung von Daten des gleichen Typs, die als eine Einheit ( Teilmenge ) gesehen werden. Der Basisdatentyp aus dem die (Teil-)Menge gebildet wird muss ordinal sein, d.h., sie müssen abzählbar sein. So sind z.B. alle Großbuchstaben eine Menge der ASCII-Zeichen oder alle Ziffern zwischen 1 und 9 eine Menge der Ganzzahlen bzw. wiederum eine Teilmenge der ASCII-Zeichen. Mengenwerte können nicht über die Tastatur eingegeben werden, sondern sie müssen per Anweisung gebildet werden. Die erste Möglichkeit besteht darin, die Elemente der Mengen zwischen eckigen Klammern anzugeben. Bei zusammenhängenden Bereichen genügt es das erste und letzte Element getrennt durch zwei Punkte anzugeben. Andere werden durch Kommata getrennt. Beispiele : [ ‘a‘ .. ‘z‘ ] oder [ ‘A‘, ‘E‘, ‘I‘, ‘O‘, ‘U‘ ] bzw. gemischt [ 0..9, 15,33,77 ] oder Leermenge [ ] Die zweite Möglichkeit ist die implizite Mengenverwendung. Als Beispiel möge die Benutzeroberfläche eines Programms in Form eines Menüs dienen. Die einzelnen Funktionen des Menüs können durch Tippen des Anfangsbuchstabens ausgelöst werden. Dabei dürfen natürlich nur ganz bestimmte Buchstaben eingegeben werden, anderenfalls soll die Eingabe wiederholt werden. Als zugelassene Buchstaben legen wir ( L)inks, (R)echts und (S)top sowie deren Kleinbuchstaben fest. VAR m:CHAR; .... Repeat m:= ReadKey; until m IN [ ‘L‘, ‘R‘, ‘S‘, ‘l‘, ‘r‘, ‘s‘ ]; ... Mit Hilfe des logischen Operators „IN“ wird festgestellt, ob der Wert der Variablen m in der Menge enthalten ist. Das Ergebnis dieser Prüfung ist stets vom Typ Boolean, alsowahr (true) oder falsch (false). Alternative : ..NOT m IN .. Mengen können natürlich auch explizit deklariert werden. Dazu dient die folgende Anweisung : VAR <name> : SET OF <mengendatentyp>; Beispiel : Dabei kann der Mengendatentyp ein einfacher Standarddatentyp, ein Teilbereichtstyp oder ein selbstdefinierter Typ sein. VAR Buchstabe : SET OF CHAR; .... Buchstabe := [ ‘A‘ .. ‘Z‘ ]; Beachten Sie bitte, dass die Variablen vom Typ Menge nicht ein Datum aus der Menge besitzen, sondern immer die gesamte Menge. Deswegen können Variablen vom Typ SET OF auch nicht direkt auf dem Bildschirm mit Write bzw. WriteLn ausgegeben werden. Die Kardinalität (Anzahl der Elemente) in einer Menge kann unter Extended Pascal mit anzahl:= card ( menge); ermittelt werden. Die Anzahl der zugeordneten Elemente im SET darf 256 nicht überschreiten ! Auf Mengendatentypen können logische Operatoren angewendet werden, deren Operatoren, Operanten und Resultate wiederum Mengen sind. Z.B.: Durchschnitt / Schnittmenge (M1 * M2 → ODER); Vereinigungsmenge ( M1 + M2 → UND ); Teilmenge ( M1 <= M2 ) usw. Aufgabe : Erstellen Sie ein Programm mit Hilfe von Mengen, dass aus einer Zahlenmenge von 256 alle geraden Zahlen, alle ungeraden Zahlen und alle Primzahlen isoliert und als Teilmengen anzeigt. Visualisieren Sie Ihren Programmentwurf mit Hilfe eines Struktogramms oder Programmablaufplans. 11.07.02 24-mengen HansBöcklerSchule Programmiertechnik Informationsblatt Klasse : Name : EIGENE DATENTYPEN Münster 25/25 Datum : Information: Die wichtigsten Standard-Datentypen von Turbo-Pascal wurden bereits behandelt. Natürlich gibt es noch mehr ( Pointer, Object, Text, File usw. ) aber hier soll nur vorgestellt werden, wie man mit Hilfe der TYPE-Vereinbarung im Deklarationsteil des Programms eigene Datentypen vereinbart und wozu das gut sein kann. Einschränkend muss natürlich darauf hingewiesen werden, dass neue Datentypen nur aus den von Pascal vordefinierten Datentypen, den daraus gebildeten Unterbereichen oder aus zusammengesetzten Pascal-Datentypen bestehen dürfen. allgemeine Deklaration : TYPE TypName : Definition; 1] Beispiel : TYPE TJahr : 1990..2060; 1) Eine Variable vom Typ TJahr könnte demzufolge nur einen Wert zwischen 1990 und 2060 anneh- men Um eine Verwechslung von neuen Datentypnamen mit Variablebezeichnern zu vermeiden, schlage ich vor, den neuen Datentypnamen ein „ T “ – für Typ – voranzustellen; also z.B. TJahr oder TFarbe; Hat man es mit Mengen zu tun ( 24/25 ), so machen selbstdefinierte Datentypen schnell Sinn, wenn man die Übersichtlichkeit des Quelltextes steigern möchte. Als Beispiel soll hier die Liste aller Tage einer Woche dienen : Datentypvereinbarung Variablendeklaration Zuweisung im Hauptprogramm : TYPE TMyWeekDays = ( ’ Montag ’,’ Dienstag ’, .. ‚’ Sonntag ’ ); : VAR Today, Birthday : TMyWeekDays; : Birthday := ’Mittwoch’; Richtig wichtig werden eigene Datentypen aber immer dann, wenn man z.B. Records ( 23/25 ) als Parameter an Subroutinen übergeben muss. Innerhalb der Parameterliste erwarten die Unterprogramme ja nicht nur den Namen des formalen Parameters, sondern auch den dazugehörigen Datentyp; und im Prozedur- bzw. Funktionskopf können Sie hier keinen neuen Record mehr definieren. Problem : Angenommen, Sie haben aus einer Zahlenreihe alle Primzahlen isoliert und in eine vorab deklarierte Mengenvariable mit dem Namen PrimZahl übernommen. Diese Menge wollen Sie nun ausdrucken. Da wir aber nicht nur ein Datum in der Menge besitzen, sondern die gesamte Menge, können wir die Variable PrimZahl nicht direkt auf dem Bildschirm z.B. mit WriteLn(); ausgegeben. Was also tun ? Wir definieren zunächst ein Unterprogramm, das uns den Inhalt der als Parameter übergebenen Menge bis zu einer festen Obergrenze ausgibt. Wie man sieht, ist für den formalen Parameter der Menge im Prozedurkopf bereits ein neuer Datentyp definiert worden. PROCEDURE Ausgabe ( Menge : TZahlen ); VAR Z : Word; BEGIN FOR Z := 1 TO ObereGrenze DO IF Z IN Menge THEN Write(Z:3); END; Im Deklarationsteil des Hauptprogramms muss vorab der neue Datentyp und die dazugehörige Variable deklariert werden. CONST ObereGrenze = 200; TYPE TZahlen = SET OF 0 .. ObereGrenze; VAR PrimZahl : TZahlen; Aufruf der Prozedur im Hauptprogramm Ausgabe ( PrimZahl ); In Pascal besteht auch die Möglichkeit, Prozeduren und Funktionen als Typen zu deklarieren. Nach der Vereinbarung z.B. eines solchen Prozedurtyps können dann zugehörige Prozedurvariablen vereinbart werden. Einziges Problem : die Routinen, die solchen Prozedurvariablen zugewiesen werden, müssen vorab als FAR vereinbart werden. Das geschieht mit der Compilerdirektive { $F+ }. Beachten Sie, dass nur globale Routinen an die Prozedurvariablen übergeben werden können. Beispiel : TYPE TProzedurName = Procedure ( Parameter ); 11.07.02 25-type