Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:

Slides:



Advertisements
Ähnliche Präsentationen
Imperative Programmierung
Advertisements

Programmierung 1 - Repetitorium
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Sortieren I - Bubblesort -
Zusammenfassung der Vorwoche
Kapitel 5. Stacks und Queues
3. Berechenbarkeit Wann ist eine Funktion (über den natürlichen Zahlen) berechenbar? Intuitiv: Wenn es einen Algorithmus gibt, der sie berechnet! Was heißt,
Gliederung Motivation / Grundlagen Sortierverfahren
Java: Dynamische Datentypen
Indirekte Adressierung
Java: Referenzen und Zeichenketten
Repräsentation von Datenstrukturen im -Kalkül Simon Pinkel, Betreuer: Guido Tack Seminar: Theorie kommunizierender Systeme: Der -Kalkül.
ARRAY oder FELD oder VEKTOR
Polymorphie (Vielgestaltigkeit)
Polymorphie (Vielgestaltigkeit)
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
Bestimmung des Next-Arrays im KMP-Algorithmus
6 Folgen (Teil II - Datenstrukturen und Algorithmen)
Beispiele für Ausdrucksalgebren
Eine (Gleichungs-)Spezifikation ist ein Paar SPEC = (, E),
Einführung Wat jibt´s denn? Mit Computa kenn´ ick mir aus! Guten Tag,
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung der Vorwoche Variable stehen für (einen) Wert, der sich im Programmablauf ändern kann. Variablen besitzen einen.
Vorbereitung: struct SX { int x; struct SX *p; } *px, *ph; px: Zeiger auf Listen- anfang ph: Hilfszeiger px = NULL; px zeigt auf leere Liste px.
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
DVG Klassen und Objekte
Einführung in die Programmierung Datensammlung
Stacks Referat im Fach Basisinformationstechnologien von Venelina Koleva.
Programmiersprachen II Integration verschiedener Datenstrukturen
Visualisierung funktionaler Programme
Wichtige Fachausdrücke in C
Java programmieren mit JavaKara
IT2 – WS 2005/20061Oct 10, 2005 Externes Verhalten – Quelltext (source code) Durch Aufrufe der Konstruktoren und Methoden kann das externe Verhalten (=die.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Informatik 1 Letzte Übung.
Vom Umgang mit Daten. public void myProgram() { int[] saeulenWerte = new int[world.getSizeX()]; for (int i = 0; i < saeulenWerte.length; i++) { saeulenWerte[i]
1.6 Die Datenstruktur Stapel Ein Stapel (Stack) ist ein Sonderfall einer Liste. Die Elemente werden nach dem Prinzip LIFO (Last In First Out) angefügt.
Dynamische Datentypen
Primär(x)f(x)a[x]new typeof sizeof checked unchecked Unär+-~!++x--x x++ x-- (T)x Multip./Divis.*/% Addition/Subtr.+- shift > kleiner/größer = is gleich/ungleich==!=
Variablenkonzept Klassisch, in Java Basistyp
Hochschule Fulda – FB ET Sommersemester 2014
Programmieren in C Grundlagen C 2
CuP - Java Achte Vorlesung Entspricht ungefähr Kapitel 4.1 des Skriptums Montag, 28. Oktober 2002.
Kapitel 5Strukturen Information aus der realen Welt werden in einem informationsverarbeitenden System als Daten abgelegt. Diese stellen also eine (vereinfachte)
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
Einführung in die Programmierung mit Java
1 Eine rationale Dekonstruktion von Landin’s SECD-Maschine Betreuerin: Prof. Dr. Rita Loogen Bearbeiter: Dong Liang.
Wann ist eine Funktion (über den natürlichen Zahlen) berechenbar?
 Sortigkeit oder Arität
 Am Ende der letzten Stunde hatten wir über die Grenzen unserer Automaten-Modell gesprochen. Dr. Lars Ettelt2  Tipp: Parkhaus.  Einfahrt erst wenn.
Variablen und Operatoren. C++ Teil 2: Grundstrukturen Variablen Operatoren Kontrollstrukturen Funktionen Header-Dateien Pointer und Referenzen.
Tutorium Software-Engineering SS14 Florian Manghofer.
Tutorium Software-Engineering SS14 Florian Manghofer.
Funktionen (Zweck und Eigenschaften) Funktionen sind Unterprogramme, die einen bestimmten Zweck erfüllen Sie zerlegen Probleme in kleine, abgeschlossene.
Pointer. * und &  Bei der Definition int var1; ○ // „normale“ Variable int *var2; ○ // Zeiger auf einen Integer int *var2 = NULL; ○ // … incl. Initialisierung.
Implementieren von Klassen
1. Die rekursive Datenstruktur Liste 1.6 Die Datenstruktur Stapel
 Präsentation transkript:

Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:

Programmierung 1 - Repetitorium Mittwoch, den Kapitel 13 Imperative Objekte

Programmierung 1 - Repetitorium 13.1 Speicher und Referenzen Unter einem Speicher stellen wir uns einen Kasten vor, der in sogenannte Zellen unterteilt ist. In jeder Zelle kann ein Wert abgelegt werden. Die Zellen eines Speichers sind durchnummeriert. Die Zellennummern werden als Referenzen bezeichnet. Ein Speicher stellt folgende drei Operationen mit konstanter Laufzeit zur Verfügung : 1.Allokation : Diese Operation legt einen Wert in eine bisher nicht belegte Zelle und liefert die Referenz der Zelle. 2.Dereferenzierung : Diese Operation liefert zu einer Referenz, den in der entsprechenden Zelle abgelegten Wert. 3.Zuweisung : Diese Operation legt einen Wert in die durch eine Referenz identifizierte Zelle. Falls die Zelle bereits mit einem Wert belegt war, geht dieser verloren. eqtype a ref ref : a -> a ref ! : a ref -> a := : a ref * a -> unit Referenztypen Allokation Dereferenzierung Zuweisung

Programmierung 1 - Repetitorium 13.1 Speicher und Referenzen Der Typkonstruktor ref liefert unendlich viele Referenztypen. Eine Referenz des Typs a ref identifiziert eine Zelle, in der Werte des Typs a abgelegt werden können. Durch die abstrakten Referenztypen wird gewährleistet, dass nur solche Referenzen im Umlauf sind, die belegte Zellen identifizieren. Die Reihenfolge der Speicheroperationen ist sehr bedeutend. Unter dem Wert einer Referenz verstehen wir den Wert in der durch die Referenz identifizierten Zelle. Eine Referenz zeigt auf ihren Wert. Eine Referenz wird auf einen Wert gesetzt, wenn wir den Wert mithilfe der Zuweisungsoperation in die durch die Referenz identifizierte Zelle legen. Einer Referenz wird ein Wert zugewiesen. Referenzen bezeichnen wir auch als Adressen. Dereferenzierung und Zuweisung bezeichnen wir auch als Lesen und Schreiben. Die Allokationsoperation verändert den Zustand des Speichers, da sie eine bisher nicht benutzte Zelle mit einem Wert belegt. Man sagt auch, dass die Allokationsoperation eine Zelle alloziert. Die Zuweisungsoperation kann den Zustand des Speichers dadurch ändern, dass sie eine bereits allozierte Zelle mit einem anderen Wert belegt.

Programmierung 1 - Repetitorium 13.1 Speicher und Referenzen Die Ausführung einer Phrase hat einen Speichereffekt, wenn diese den Zustand des Speichers verändern. Jede Allokation liefert eine neue Referenz. ref 0 = ref 0liefert den Wertfalse (Die beiden Teilausdrücke liefern verschiedene Referenzen.) !(ref 0) = !(ref 0)liefert den Werttrue (Die Werte der Referenzen werden verglichen.) ref, ! und := sind Operatoren für Referenzen. ! ( ! (ref (ref 1))) = 1 map ! (map ref [1,2,3]) = [1,2,3] e1 before e2 #1 ( e1, e2 ) Zuerst wird der Ausdruck e1 und dann der Ausdruck e2 ausgewertet. Die Auswertung liefert den bei der Auswertung von e1 erhaltenen Wert. fun swap x y = x := ( !y before y := !x ) val swap : a ref -> a ref -> unit

Programmierung 1 - Repetitorium 13.1 Speicher und Referenzen Das Wort ref kann in Mustern wie in Konstruktor benutzt werden. Ein Muster ref x trifft jede Referenz und bindet die Variable x an den aktuellen Wert der Referenz. fun deref (ref x) = x val deref : a ref -> a deref (ref 7) = 7

Programmierung 1 - Repetitorium 13.2 Prozeduren mit Zustand counter : unit -> int val r = ref 0 fun counter () = (r:=!r+1; !r) counter soll mitzählen, wie oft sie aufgerufen wurde und bei ihrem n-ten Aufruf die Zahl n liefern. counter ist eine Prozedur mit Zustand. counter kann seinen Zustand auch enkapsulieren : val counter = let val r = ref 0 in fn () => (r:=!r+1; !r) end fun newCounter i = let val r = ref (i-1) in fn () => (r:=!r+1; !r) end newCounter ist ein Generator für Zählprozeduren mit beliebig vorgegebenem Anfangswert.

Programmierung 1 - Repetitorium 13.3 Stapel Unter einem Stapel (stack) versteht man in der Programmierung ein imperatives Objekt, auf dem mehrere Werte gestapelt werden können. Der zuletzt abgelegte Wert liegt dabei oben. Ein Stapel ermöglicht folgende 3 Operationen : 1.push legt einen Wert auf einen Stapel 2.top liefert den obersten Wert eines Stapels 3.pop nimmt den obersten Wert von einem Stapel Eigenschaft : LAST IN – FIRST OUT (LIFO) push 2pop

Programmierung 1 - Repetitorium 13.3 Stapel Spezifikation von Stapeln signature STACK = sig eqtype a stack val stack : unit -> a stack val push : a stack * a -> unit val top : a stack -> a(* Empty *) val pop : a stack -> unit(* Empty *) val empty : a stack -> bool end structure Stack :> STACK = struct type a stack = a list ref fun stack () = ref nil fun push (s,x) = s:= x::!s fun top s = hd(!s) fun pop s = s:=tl(!s) fun empty s = null(!s) end

Programmierung 1 - Repetitorium 13.4 Reihungen Eine Reihung (array) ist ein imperatives Objekt, das aus einer Anzahl von Speicherzellen besteht, die als Komponenten bezeichnet werden. Die Komponenten einer Reihung werden durch natürliche Zahlen identifiziert, die als Indizes bezeichnet werden und sich durch Durchnummerierung beginnend mit Null ergeben. Alle Komponenten einer Reihung müssen Werte des gleichen Typs enthalten. Picard Kirk Sisko Archer Janeway Die Operation array liefert zu n und x eine Bindung mit n Komponenten, die zunächst alle mit dem initiallen Wert x belegt sind. Mit der Operation sub kann der Wert einer Komponente gelesen werden, mit der Operation update kann er gesetzt werden. Die Komponenten werden dabei durch ihren Index identifiziert. Die Operation length liefert die Anzahl der Komponenten einer Reihung. Wir implementieren Reihungen als Liste von Referenzen.

Programmierung 1 - Repetitorium 13.4 Reihungen Spezifikation von Reihungen : signature ARRAY = sig type a array val array : int * a -> a array(* Size *) val sub : a array * int -> a(* Subscript *) val update : a array * int * a -> unit(* Subscript *) val length = a array -> int end structure Array :> ARRAY = struct type a array = a ref list fun array (n,x) = List.tabulate (n, fn _ => ref x) fun sub (a,n) = !(List.nth(a,n)) fun update (a,n,x) = List.nth (a,n) := x val length = List.length end

Programmierung 1 - Repetitorium 13.4 Reihungen Reversieren von Reihungen : fun swap a i j = Array.update(a,i, Array.sub(a,j) before Array,update(a,j, Array.sub(a,i)) val swap : a array -> int -> int -> unit fun reverse a l u = if l<u then (swap a l u; reverse a (l+1) (u-1)) else () val reverse : a array -> int -> int -> unit swap vertauscht die Werte zweier Komponenten. reverse reversiert die Werte der Komponenten l bis u einer Reihung a. fun reverse a = reverse a 0 (Array.length a -1) Diese Prozedur reversiert eine Reihung der Länge n mit Laufzeit (n).

Programmierung 1 - Repetitorium 13.4 Reihungen Intervalltest : Wir wollen eine Prozedur test schreiben, die testet, ob eine Liste alle Zahlen enthält, die zwischen zwei gegebenen Zahlen l und u liegen. fun test xs l u = let val a = Array.array(l-u+1,false) fun test x = if l<=x andalso x<=u then Array.update(a,x-l,true) else () in app test xs; Array.foldl (fn (b,b) => b andalso b) true a end

Programmierung 1 - Repetitorium 13.5 Imperative Listen datatype a state = ref Nil | ref ( N of a * a state ref ) type a ilist = a state ref val xs = ref(N(1,ref(N(2,ref(N(3,ref Nil)))))) Eine imperative Liste stellen wir durch eine Referenz dar, die auf einen Zustand (state) zeigt. Ein Zustand ist entweder der Wert Nil oder ein Knoten Nil Knoten (node) Zeiger (pointer)

Programmierung 1 - Repetitorium 13.5 Imperative Listen empty soll testen, ob eine imperative Liste leer ist fun empty (ref Nil) = true | empty _ = false ilist soll eine neue leere imperative Liste liefern. fun ilist () = ref Nil head liefert den Kopf und tail den Rumpf einer imperativen Liste fun head (ref(N(x,_))) = x | head _ = raise Empty fun tail (ref(N(_,xr))) = xr | tail _ = raise Empty cons liefert zu einem Wert x und zu einer imperativen Liste xr eine neue imperative Liste, deren Kopf zunächst x und deren Rumpf zunächst xr ist. fun cons x xr = ref(N(x,xr))

Programmierung 1 - Repetitorium 13.5 Imperative Listen append soll den letzten Zeiger einer imperativen Liste xs auf den ersten Zustand einer imperativen Liste ys umbiegen. fun append xs ys = if empty xs then xs:=!ys else append (tail xs) ys val xs = cons 1 ( cons 2 ( cons 3 ilist() ) ) Der Hase-Igel-Algorithmus testet, ob eine imperative Liste zyklisch ist. Zu Beginn wird der Igel auf die erste Referenz und der Hase auf die zweite Referenz der Liste gesetzt. Bei jedem Spielzug wird der Igel um eine Position und der Hase um zwei Positionen vorgerückt. Es wird solange gezogen, bis... 1.Der Hase kann nicht weitergeschoben werden, da seine Referenz auf Nil zeigt. In diesem Fall ist die Liste nicht zyklisch. 2.Der Hase und der Igel stehen beide auf derselben Referenz. In diesem Fall ist die Liste zyklisch.

Programmierung 1 - Repetitorium 13.5 Imperative Listen Realisierung des Hase-Igel-Algorithmus : fun cyclic i h = i=h orelse cyclic (tail i) (tail(tail h)) fun cyclic xs = cyclic xs (tail xs) handle Empty => false Reversieren von Listen : fun reverse s Nil = s | reverse s (s as N(_,r)) = reverse s (!r before r:=s) fun reverse xs = xs:=reverse Nil (!xs) SML wurde für funktionalen Programmierstil entworfen, d.h. man solte imperative Objekte nur dann einsetzen, wenn dies klare Vorteile bringt.

Programmierung 1 - Repetitorium 13.6 Schleifen Schleifen sind ein Sprachkonstrukt, das zusammen mit Referenzen die Formulierung von rekursiven Berechnungen ermöglicht. fun sum n = let val i = ref 1 val a = ref 0 in while !i<=n do (a:=!a+!i; i:=!i+1); !a end sum n = n Eine Schleife ist ein Ausdruck der Form while e1 do e2 der aus zwei Unterausdrücken e1 und e2 besteht. Der Ausdruck e1 muss den Typ bool haben und wird als Bedingung der Schleife bezeichnet. Der Ausdruck e2 kann einen beliebigen Typ haben und heißt Rumpf der Schleife. Eine Schleife hat immer den Typ unit.

Programmierung 1 - Repetitorium 13.6 Schleifen Semantik : while e1 do e2 = if e1 then while e1 do e2 else ( ) while e1 do e2 = let fun loop () = if e1 then (e2; loop()) else () in loop () end; Beispiel : Länge von Listen fun length xs = let val xr = ref xs val n = ref 0 in while not(null(!xr)) do (xr:=tl(!xr);n:=!n+1); !n end

Programmierung 1 - Repetitorium 13.7 Referenzen und ambige Deklarationen let val r = ref (fn x => x) in r := (fn () => ()); 1 + (!r 4) end Dieser Ausdruck ist nicht zulässig, da... 1.Das erste benutzende Auftreten von r verlangt den Typ (unit unit) ref. 2.Das zweite benutzende Auftreten von r verlangt den Typ (int int) ref. 3.Bezeichner r kann nicht polymorph typisiert werden, da die Deklaration von r ambig ist (da ihre rechte Seite eine Applikation ist)

Programmierung 1 - Repetitorium 13.8 Semantik von F mit Referenzen Erweiterung der abstrakten Syntax : Speicherzustände s Sta = Val Für die Auswertung eines Ausdrucks benötigen wir eine Wertumgebung und einen Speicherzustand (Anfangszustand). Wenn die Auswertung terminiert, liefert sie seinen Wert und zusätzlich einen Speicherzustand (Endzustand). t Ty =... | t ref | unit e Exp =... | ref e | !e | e1:=e2 DS Sta x VE x Exp x Val x Sta S,V e v,S für (S,V,e,v,S) DS

Programmierung 1 - Repetitorium 13.8 Semantik von F mit Referenzen Nur diese Regeln greifen auf die Zustände zu. Mit Referenzen lassen sich rekursive Prozeduren simulieren. val fak = let val r = ref (fn x => x) fun f x = if x<2 then 1 else x*!r(x-1) in r:=f; f end S,V e v,S r=min( - Dom S) S=S+{rv} S,V ref e r,S S,V e r,S v=S(r) S,V !e v,S S,V e1 r,S S,V e2 v,S r Dom S S=S+{rv} S,V e1:=e2 ( ),S