       Notizen zum Kurs "Objektorientierte Implementierung von Problemen des 
       Operations-Research", WS 1993/94, FH Darmstadt

       
       Literatur zur Programmiersprache Eiffel:
       Bertrand Meyer: Eiffel, the Language, Prentice Hall, 1992 
       [ Das vollstndige Sprachhandbuch, das allerdings in einigen Punkten 
       nicht mehr aktuell ist. ]
       Michael Schweitzer/Lambert Strether: The Eiffel/S Compiler & Runtime
       System, The Eiffel/S Library, Release 1.2, 1992
       [ Handbuch zum aktuellen Compiler ]
       Robert Switzer: Eiffel, an Introduction, Prentice Hall, 1993
       [ Eine sehr gut lesbare Einfhrung in die Sprache Eiffel ]
       
       
       
       TEIL 1  EINFHRUNG
       ==================
       Grundlegende Strukturelemente von  EIFFEL  (wie auch von anderen 
       objektorientierten Systemen) sind  KLASSEN  und sind die Mechanismen  
       VERERBUNG und  DYNAMISCHE BINDUNG . In Teil 1 dieser Notizen werden 
       die ersten beiden Begriffe an Beispielen illustriert.

       In einer Klasse werden die mglichen Ausprgungen eines interes-
       sierenden Begriffs durch charakterisierende Eigenschaften reprsen-
       tiert. Informell gesagt ist eine Eiffel-Klasse die Antwort auf eine
       "gut gezielte" Frage.
       Am Beispiel der Klasse  POINT  soll verdeutlicht werden, was damit 
       gemeint ist.
       In der Ebene gibt es unendlich viele verschiedene Punkte. 
       Was ist es, das einen Punkt von einem andern unterscheidet? Was sind 
       die abstrakten Eigenschaften, die "Punkte" charakterisieren?
       Vom Standpunkt eines technischen Zeichners gesehen, der einen Punkt 
       auf sein Zeichenbrett zu plazieren hat, sind dies die Koordinaten
       des Punktes. Der Zeichner wei, was er zu machen hat, sobald er die 
       beiden Koordinaten kennt.

       Hat man einmal gute charakterisierende Eigenschaften fr den interes-
       sierenden Begriff gefunden, so werden diese in der Eiffel-Klasse ko-
       diert.
       Die Klasse  POINT  enthlt dementsprechend die beiden  FEATURES 

                                 x : REAL
                                 y : REAL

       (diese beiden features sind  ATTRIBUTE . Es gibt andere features in
       Eiffel wie Funktionen, Prozeduren ... , siehe unten).
       Die Punktkoordinaten werden wie angegeben abstrakt deklariert. 
       Die Punkte werden nicht etwa durch konkrete Angaben wie  x:=3, y:=4  
       definiert.
       Die Klasse  POINT  enthlt zwei weitere features, nmlich die  
       PROZEDUREN  set_x  und  set_y , die spter erlutert werden.


       class POINT

       feature

          x : REAL
          y : REAL

       ------------------------

       set_x (arg:REAL) is
   
          do
             x := arg
          end 

       -------------------------

       set_y (arg:REAL) is

          do
             y := arg
          end

       --------------------------
       end  -- class POINT


       Was die charakterisierenden Eigenschaften der Objekte sind, ist im 
       allgemeinen eine Frage des Standpunktes. Ein Maler, der einen Farb-
       tupfer auf die Leinwand zu setzen hat, bentigt neben den Koordinaten 
       noch die Angabe der Farbe, damit er wei, was er zu machen hat. Den 
       Maler interessiert also statt der Klasse  POINT  eher die Klasse  
       TUPFER :


       class TUPFER

       feature

          x : REAL
          y : REAL
          c : COLOUR
              -- ( Zwei Trennstriche --  bedeuten: Rest der Zeile Kommentar)
              -- ( Drei Punkte ... bedeuten: Teile der Klasse fehlen)
          ...

       end  --  class TUPFER


       In der Klasse  TUPFER  sind  x und y  vom TYP REAL, c ist vom Typ  
       COLOUR. Dabei sind  REAL und COLOUR  Namen von Klassen, die im 
       aktuellen  UNIVERSUM  bekannt sein mssen, wenn es beim Kompilieren 
       keine Fehlermeldung geben soll. In der Tat ist  REAL  eine Klasse 
       aus der Basisbcherei von Eiffel.
       COLOUR  ist eine lediglich zur Demonstration eingefgte Phantasie-
       klasse.

       Die bisher vorgestellten Konzepte sind auch in Programmiersprachen 
       wie Pascal (durch die dortigen records) und  C (als structures) 
       realisierbar und gut bekannt. 
       Einen neuen Aspekt beim objektorientierten Programmieren illustriert 
       das folgende Beispiel, bei dem auer zwei Attributen eine Funktion 
       deklariert wird:

       Ein Team soll ein Programm entwickeln, mit dessen Hilfe Optimierungs-
       probleme mit linearen Nebenbedingungen und nichtlinearer Zielfunktion 
       gelst werden knnen.
       Wodurch wird ein solches nichtlineares Optimierungsproblem charakteri-
       siert? Prziser gefragt: Wodurch unterscheidet sich eine Problemauspr-
       gung des Optimierungsproblems von einer anderen Problemausprgung?
       
       Antwort:  Die Problemausprgungen unterscheiden sich durch
       - Format und Inhalt von Restriktionsmatrix und Rechter Seite  und
       - die genaue Gestalt der nichtlinearen Zielfunktion.

       Ein dieser Situation entsprechendes Eiffel-Fragment wre:

       
       deferred class NONLINEAR_PROG

       feature

          A : ARRAY2 [REAL]
          b : ARRAY  [REAL]
       
       ----------------------------------

       obj_function (x: ARRAY): REAL is
          deferred
          end
       ----------------------------------
       ...

       end  -- class NONLINEAR_PROG

       
       Die hier auftauchenden  ARRAY  (Vektor) und  ARRAY2 (Matrix) sind 
       Klassen aus der Basisbcherei von Eiffel.

       Man sieht: Zu den Eigenschaften, die die Ausprgungen einer Klasse 
       charakterisieren, knnen bei Eiffel nicht nur Attribute wie  A  und 
       b , sondern auch komplette Funktionen wie  obj_function gehren!

       Man beachte: Beim Beispiel  POINT  wurden die Koordinaten in der Form  
       x,y : REAL  abstrakt deklariert (und nicht durch konkrete Zahlen defi-
       niert).
       Es ist daher konsequent, in der Klasse  NONLINEAR_PROG  die Zielfunk-
       tion  obj_function  nur abstrakt zu deklarieren als  AUFGESCHOBENE
       (deferred) Funktion. Konkret definiert werden solche aufgeschobenen
       features von "erbenden" Klassen erst dann, wenn es ntig ist (siehe
       unten).


       ----------------------------------------------------------------------


       Angenommen nun, die euklidische Norm von Punkten in der Ebene ist ge-
       sucht.
       Hierzu knnte man eine Klasse schreiben hnlich der obigen Klasse
       POINT  und die fehlende Normfunktion hinzufgen.
       Der objektorientierten Programmierweise entspricht es aber, von der 
       schon existierenden Klasse  POINT  zu "erben" und lediglich die feh-
       lenden Teile in der neuen Klasse zu ergnzen:


       class POINT2

       inherit
          
          POINT
          end

          MATH
          end
       
       feature

       norm : REAL is       --    euklidische Norm
          local
             xx: REAL
             yy: REAL
          do
             xx := x * x
             yy := y * y
             Result := sqrt (xx + yy)
          end

       ---------------------------------------------
       end  -- class POINT2
       
       
       Wie man sieht, kann eine Klasse kann von anderen Klassen auf zweifache
       Weise Gebrauch machen, als  KLIENT  oder als  ERBE . 
       Die Klasse  POINT2  greift auf die Klasse  REAL  als Klient zu
       (z.B. xx: REAL ). Hingegen erbt  POINT2  die Klassen  POINT  und  MATH
       (z.B. inherit POINT end ).
       Durch Beerben (inherit) werden die features der geerbten Klasse ver-
       fgbar gemacht als wren sie eigene features der erbenden Klasse. 
       So benutzt  POINT2  die Attribute  x  und  y  der geerbten Klasse
       POINT  und benutzt auerdem die Wurzelfunktion  sqrt  der geerbten 
       Klasse  MATH . 

       Der oben erwhnte Maler wrde sinnvollerweise auch von der Klasse  
       POINT  erben, anstatt alles vllig neu zu schreiben, also:

       
       class TUPFER    --   Variante

       inherit

          POINT
          end
       
       feature
          
          c : COLOUR
          ...
       
       end  --  class TUPFER


       Eine erbende Klasse kann die Implementation von features der geerbten 
       Klasse ignorieren und fr die eigenen Zwecke neu definieren (Syntax
       hierfr siehe Handbuch unter  redefine ).
       So knnte man die Implementation etwa der Maximumnorm dadurch erledi-
       gen, da man von  POINT2  erbt und lediglich die dort als Euklidische
       Norm definierte Funktion  norm  fr die Maximumnorm neu schreibt.
       
       Noch wichtiger ist diese Mglichkeit der Neudefinition in Fllen, wo 
       man von Klassen erbt, die aufgeschobene features enthalten, welche al-
       so berhaupt noch nicht definiert waren.
       Man betrachte obige Klasse  NONLINEAR_PROG , in der die Definition der
       Zielfunktion  obj_funktion  noch aufgeschoben war.
       Jeder, der eine konkrete nichtlineare Zielfunktion zu optimieren hat,
       kann das dadurch erledigen, da er von  NONLINEAR_PROG  erbt, seine
       spezielle Zielfunktion (neu)definiert und im brigen von der Program-
       mierarbeit des Autors von  NONLINEAR_PROG  profitiert.


       ---------------------------------------------------------------------


       Die Klasse  POINT2  ist noch kein lauffhiges Programm zur Berechnung 
       des euklidischen Abstand eines Punktes vom Nullpunkt. Letzteres lei-
       stet erst die nachfolgende Klasse  DISTANCE , welche Klient von  
       POINT2  ist:

       
       class DISTANCE  -- berechnet den euklidischen Abstand eines 
                       -- Punktes der Ebene vom Nullpunkt
       creation
          make

       feature

          io : BASIC_IO
          p  : POINT2

       --------------------------------
   
       make is

          do
             !!io
             !!p
             io.put_newline
             io.put_string ("Gib x: ")
             io.get_real 
             p.set_x (io.last_real)
                               --  last_real ist die letzte mittels  get_real  
                               --  von der Tastatur eingelesene reelle Zahl

             io.put_string ("Gib y: ")
             io.get_real 
             p.set_y (io.last_real)
             io.put_newline
             
             io.put_string ("Berechne nun Abstand des eingelesenen Punktes %N")
             io.put_string ("vom Nullpunkt. Gib <RETURN> %N%N")
                               --  %N bedeutet: neue Zeile
             
             io.get_newline    --  wartet auf <RETURN>
             io.put_string ("Der Abstand ist ")
             io.put_real (p.norm)
             io.put_newline
          end

       --------------------------------
       
       end  -- class DISTANCE
      

       Zur Erluterung:
       Durch die Deklaration  p : POINT2  ist  DISTANCE  Klient von  POINT2
       und kann mit der blichen Punkt-Schreibweise  p.set_x  oder  p.x  auf
       die (von  POINT  geerbten) features von  POINT2  zugreifen.
       
       Auerdem ist  DISTANCE  Klient der Klasse  BASIC_IO . Diese Klasse
       enthlt einige features zur interaktiven Ein- und Ausgabe von Daten
       wie  get_real  oder  put_newline .
       [ In Eiffel/S 1.2 ist eine Klasse  INTERACT  mitgeliefert, die einiges
       weitere ntzliche zu interaktiven Ein- und Ausgabe enthlt.]
       
       Anstatt die Klasse  BASIC_IO  als Klient zu benutzen, wre es fr
       DISTANCE  ebenso mglich gewesen, die Klasse  BASIC_IO  zu erben und
       direkt auf deren features zuzugreifen.
       Ob man eine Klasse als Klient oder als Erbe benutzen sollte, ist also
       durchaus nicht eindeutig.
       Oft bekommt man Klarheit, wenn man sich fragt, ob ein "Objekt" der
       aktuellen Klasse ein Objekt der benutzten Klasse HAT oder ein Objekt
       der benutzten Klasse  IST .
       (Die Objekte entsprechen den Ausprgungen der Klasse; siehe unten.)
       
       Offensichtlich HAT ein Punkt eine reelle Zahl  x  als erste Koordinate.
       Demzufolge benutzt  POINT  benutzt die Klasse  REAL  als Klient.
       Hingegen kann man nicht sagen, da ein Farbtupfer einen Punkt HAT .
       Ein Farbtupfer  IST  vielmehr ein Punkt mit einer weiteren Eigen-
       schaft (nmlich der Farbe).
       Die Klasse  TUPFER  erbt konsequenterweise die Klasse  POINT .


       Klassen enthalten neben ihren charakterisierenden Attributen und
       Funktionen oft noch weitere Funktionen oder Prozeduren.
       Die Klasse  POINT2  beispielsweise enthlt neben den von  POINT  ge-
       erbten Attributen  x  und  y  die Funktion  norm  zur beliebigen
       Benutzung seitens ihrer Klienten oder Erben.
       Ferner knnte der Autor von  POINT , sofern er seitens der Klienten 
       oder Erben Bedarf dafr vermutet, eine Funktion hinzufgen, die das
       Maximum der Koordinatenbetrge (also die Maximumnorm) berechnet.
       Dies wrde den Benutzern von  POINT  die Mhe ersparen, diese Funktion
       jeder fr sich nochmal zu programmieren.
       Eiffelklassen enthalten in der Regel solche "Serviceleistungen" fr
       ihre Erben und Klienten.
       
       Die Klasse  POINT  enthlt neben den charakterisierenden Attributen
       x  und  y  noch die Prozeduren  set_x  und  set_y .
       Wie die zu benutzen sind, zeigt die Prozedur  make  in  DISTANCE , wo
       durch den Befehl  p.set_x  die x-Koordinate von  p  konkret definiert
       wird.

       Diese Art, den Koordinaten eines Punktes konkrete Werte zuzuweisen,
       macht einen etwas umstndlichen Eindruck, und man knnte sich fragen, 
       ob es nicht mglich ist, der x-Koordinate von  p  den Wert beispiels-
       weise  4  zuzuweisen durch den Befehl  p.x:=4 . 
       In der Tat ist derartiges in Eiffel verboten. 
       Die Entscheidung, ob ein Klient aktiven Zugriff auf ein Attribut einer 
       Klasse haben soll oder nicht, ist das ausschlieliche Privileg des 
       Autors der Klasse.
       Wenn also der Autor von  POINT  den Klienten das Recht einrumen will,
       die Koordinaten des Punktes zu verndern, so ist das nur mglich, in-
       dem er in der Klasse  POINT  die speziellen Prozeduren  set_x  und
       set_y  fr diese Zwecke bereitstellt.
       
       [ Da diese scheinbar umstndliche Methodik die einzig vernnftige
       ist, zeigt das simple Beispiel der Klasse  ARRAY  aus der Basisbche-
       rei. Diese Klasse enthlt das Attribut  size , das Kunden ber die
       Arraylnge informiert. Htte ein Klient aktiven Zugriff auf dieses
       Attribut, so knnte er es aktiv manipulieren und ein anderer Klient
       bekme eine falsche Information ber die Arraylnge. ]


       -------------------------------------------------------------------


       Die nur zur Laufzeit eines Programms existerenden  OBJEKTE  einer
       Klasse entsprechen den Ausprgungen der Klasse; die Objekte sind Daten-
       stze des abstrakten Datentyps, welcher durch die Klasse definiert
       ist.
       Ein Objekt setzt sich aus Feldern zusammen, und jedes Feld entspricht
       einem Attribut der Klasse. - Ein Objekt der Klasse  POINT  (mit den
       zwei Attributen  x  und  y ) setzt sich also zusammen aus zwei Feldern,
       jedes fr eine reelle Zahl.
       
       In klassischen Programmieranstzen hat man Variable eines gewissen
       Typs.
       Im objektorientierten Programmieransatz hat man stattdessen  GRSSEN
       (entities)  eines gewissen Klassentyps.
       Eine Gre nimmt bei Laufzeit des Programms  WERTE  an.
       Die Werte einer Gre sind von den Objekten der zugehrigen Klasse zu
       unterscheiden: Der Wert einer Gre ist normalerweise nicht ein Objekt
       der zugehrigen Klasse, sondern ein Verweis (ein Zeiger) auf ein sol-
       ches Objekt.
       
       Ausnahmen dieser Regel liegen vor bei den  BASIS-Typen
                       BOOLEAN , CHARACTER , INTEGER  und  REAL
       Die Werte von Gren dieser Typen sind Objekte der Klassen selber (und
       nicht Verweise auf die Objekte).

       Verweisgren mssen vor Benutzung  KREIERT  werden.
       Eine Kreierung bewirkt Schaffung eines Objekts der betreffenden Klasse
       mit Vorbesetzungswerten (Default-Werten) fr dessen Felder und Bindung
       der Gre an dieses Objekt.
       Gren von Basistypen mssen nicht kreiert werden.

       Beispiel: 
       In der Klasse  DISTANCE  ist durch  p : POINT2  die Verweisgre  p  
       deklariert. Durch  !!p  wird  p  kreiert, d.h. ein Objekt der Klasse  
       POINT2  mit den beiden Default-Werten  0.0 und 0.0  wird geschaffen, 
       und  p  wird an dieses Objekt gebunden.  
       Anschlieend wird dann ber dieses Objekt verfgt: Zwei Zahlen werden 
       von der Tastatur eingelesen und an die Koordinaten von  p  bergeben.
       

       Bei Laufzeit des Programms existiert zu jedem Zeitpunkt das  AKTUELLE
       Objekt ( CURRENT Object). In Eiffel ist die vorgeprgte Gre
                                    Current
       verfgbar, deren Wert (bei Verweisgren) ein Verweis auf das aktuelle
       Objekt ist.
       In Teil 2 wird an einem Beispiel die Benutzung von  Current  demon-
       striert.


       Die Vorschrift, Verweisgren zu kreieren, erfordert einiges Verstnd-
       nis des Sprachsystems, und man kann sich fragen, ob auf Kreieren nicht
       verzichtet werden knnte.
       In der Tat ist Kreieren die einzig vernnftige Methodik.
       Durch den Kreierungsbefehl werden bei Laufzeit Objekte erzeugt und es
       wird Speicherplatz bereitgestellt. Wrde auf explizites Kreieren ver-
       zichtet, so wre es erforderlich, bei Laufzeit fr alle Gren des
       Programms Objekte zu erzeugen und Speicherplatz bereitzustellen, der
       beim konkreten Programmlauf vielleicht gar nicht bentigt wrde.
       Ferner kann einunddieselbe Verweisgre "im Laufe ihres Lebens" an 
       viele unterschiedliche Objekte gebunden sein. Ein einziges Objekt fr
       eine Gre wrde mglicherweise also gar nicht ausreichen.
       
       Das folgende Beispiel illustriert drastisch die Notwendigkeit, expli-
       zit zu kreieren:
       Angenommen, man hat ein Feld mit Komponenten, die Punkte sind, also

                              p : POINT
                              a : ARRAY [POINT]
       
       Man kann nun in die Komponenten des Feldes mit folgendem Programmfrag-
       ment Werte einlesen:

       ...
       from
          i := 1
       until
          i > n
       loop
          !!p
          io.put_string ("Gib x-Koordinate von Punkt  ")   io.put_int (i)
          io.put_string (":  ")
          io.get_real
          p.set_x (io.last_real)
          io.put_newline
          io.put_string ("Gib y-Koordinate von Punkt  ")   io.put_int (i)
          io.put_string (":  ")
          io.get_real
          p.set_y (io.last_real)
          io.put_newline
          a.put (p,i)
          i := i+1
       end
       ...

       Die Prozedur  put  ist eine Serviceleistung der Basisklasse  ARRAY . 
       Der Befehl  a.put (p,i)  setzt (grob gesagt) den ber Tastatur einge-
       lesenen Punkt  p  an die i-te Stelle des Feldes.
       
       Die Variable  p  ist vom Typ  POINT , also eine Verweisgre.
       Genau genommen ist der Wert von  p  ein Zeiger auf einen Punkt.
       Man mu  p  mittels  !!p  fr jedes neue  i  neu kreieren. 
       Macht man dies nicht oder kreiert man  p  VOR der Schleife, so wre 
       das kein Syntaxfehler, aber es gbe die folgende Katastrophe:
       Im Verlauf der Schleife werden alle Komponenten des Feldes zu Zeigern
       auf einen Punkt, und zwar auf einunddenselben Punkt, da nicht neu
       kreiert wird. Darber hinaus wird dieser Punkt per Tastatur stndig
       gendert, so da am Ende der Schleife alle Komponenten auf den glei-
       chen, nmlich den zuletzt eingelesenen Punkt weisen.
       Kurz: Alle Komponenten des Feldes sind gleich!

       In obigem Programmfragment wird innerhalb der Schleife, also fr jede 
       Komponente neu kreiert. Jede Komponente des Feldes ist Zeiger auf 
       ihren individuellen Punkt, und genauso hatte es sein sollen.

       
       --------------------------------------------------------------------
       
       
       In Eiffel gibt es keine Hauptprogramme. Ein Eiffelprogramm setzt 
       sich zusammen aus einer Kollektion von Klassen, die gegenseitig durch 
       die Vererbungs- oder Klientenrelation in Verbindung stehen. - Bei 
       obigem Beispiel sind es nicht weniger als 20 Klassen, auf die das 
       Programm direkt oder indirekt zugreift.
       Um ein Eiffelprogramm zu starten, ist es ntig, eine dieser Klassen 
       als WURZEL-Klasse zu deklarieren und innerhalb dieser Wurzelklasse 
       eine Prozedur als KREIERUNGS-Prozedur auszuzeichnen. - Im obigen Bei-
       spiel ist  DISTANCE  die Wurzelklasse mit  make  als Kreierungsproze-
       dur.

       Bei Programmstart geschieht folgendes: Ein Objekt der Wurzelklasse 
       wird geschaffen, und die Kreierungsprozedur der Wurzelklasse wird 
       gestartet. 
       Dies ist die "Initialzndung" des Programms, die in der Regel weitere 
       Objektkreierungen und Prozeduraufrufe nach sich zieht.
       
       Die Klassen, aus denen sich ein Eiffelprogramm zusammensetzt, befin-
       den sich oft in unterschiedlichen Unterverzeichnissen (Clustern).
       Im Beispiel werden das aktuelle Cluster und dazu die Cluster  basic  
       und  math  benutzt.
       Diese Einzelheiten werden dem Compiler in Form eines pdl-files 
       (Program Deskription Language) mitgeteilt. Es folgt das  pdl-file  
       fr das Beispiel:

       
       program distance
 
       root
           distance : "make"
 
       cluster

           "./"
           end

           "$EIFFEL_S/library/basic"
               find
                   "comparable"    in "compar.e", 
                   "integer_ref"   in "int_ref.e",
                   "character_ref" in "char_ref.e", 
                   "boolean_ref"   in "bool_ref.e",
                   "file_system"   in "file_sys.e",
                   "system_time"   in "sys_time.e",
                   "character"     in "characte.e",
                   "environment"   in "environ.e",
                   "exception"     in "except.e"
           end

           "$EIFFEL_S/library/math"
           end
    
       end -- program distance
       
       
       Das  pdl-file  enthlt also den Programmnamen, den Namen der Wurzel-
       klasse mit Kreierungsprozedur und dann die Pfade der benutzten Ver-
       zeichnisse (das Symbol  "./"  steht fr das aktuelle Verzeichnis).
       Die  find-Zuordnungen  teilen dem Compiler mit, welche Klassen er in
       welchen Eiffel-Dateien findet.
       In der Version Eiffel/S 1.2 ist es nicht mehr ntig, das pdl-file sel-
       ber zu schreiben. Der Compiler sucht sich die bentigten Eiffel-Datei-
       en selber zusammen.

       Ein komplettes Programm wird kompiliert mit dem Befehl  

                          ecc prog_name  (im Beispiel  ecc distance )
       oder
                          ecc -o prog_name

       Compilation mit Option  -o  (optimieren)  geht schneller, bentigt
       weniger Arbeitsspeicher und sorgt fr kleinere und schnellere ausfhr-
       bare Programme. Andererseits haben mit Optimierungsoption kompilierte
       Programme weniger Mglichkeiten zur Fehlerkontrolle.

       Beim Kompilieren erzeugt Eiffel zunchst einen C-Zwischencode 
       (im MN-Labor Borland-Turbo-C), der dann vom C-Compiler automatisch 
       weiterverarbeitet wird. Bei Fehlermeldungen gibt der Eiffel-Compiler 
       Fehlerbeschreibungen entweder in Klartext oder mit dem Fehlercode aus 
       dem Sprachhandbuch.
       Bei erfolgreicher  Eiffel => C  bersetzung sollten keine Fehlermel-
       dungen des C-Compilers mehr vorkommen.

       Der Eiffel-Compiler legt beim Kompilieren eine Vielzahl von Dateien
       in zwei oder sogar drei Unterverzeichnissen ab. Bei der Programment-
       wicklung kommt es oft vor, da man diese Dateien lschen mchte.
       Dies kann auf bequeme Weise mit dem Programm  eclean  gemacht werden,
       da sich im Verzeichnis  EIFFEL\BIN  befindet.

       Ein kompiliertes Programm wird gestartet mit dem Befehl

                                 prog_name
       
       Ein ausfhrbares Eiffel-Programm hat interne Schalter zur Fehlerkon-
       trolle, die ber ein rcl-file (Runtime Control Language) gesteuert
       werden knnen. Existiert kein rcl-file, so werden default-Werte fr 
       die Schalter benutzt.

       
       ---------------------------------------------------------------------

       
       Es ist ist oft wnschenswert, da Datenstrukturen bei Programmende
       nicht verlorengehen, sondern physisch (auf Festplatte) gespeichert
       werden. Wie Eiffel die Kommumikation mit den DOS-Dateien ermglicht,
       zeigt das folgende Programm.


       class FILEDEMO 

       creation
           make

       feature  { ANY }
   
          a  :  ARRAY2 [INTEGER]
       ------------------------------------------------

       make is
   
          local
             ch : CHARACTER
   
          do 
             from
                io.put_string ("Zuerst obersten Menpunkt whlen %N%N")
             until
                ch = 'q'
             loop
                show_menu
                io.get_char
                ch := io.last_char
                inspect ch
                   when  'e'  then  get_data
                   when  'a'  then  change_data
                   when  's'  then  store_data
                   when  'z'  then  show_data
                   else if ch /= 'q' then
                        io.put_string ("Unbekanntes Zeichen %N") end
                end
             end
   
             rescue
                io.put_string ("Fehler bei der Menreihenfolge %N")
                retry
          end

       ------------------------------------------------

       show_menu is
   
          do
             io.put_string ("e : eingeben von Daten %N")
             io.put_string ("a : ndern von Daten %N")
             io.put_string ("s : sichern der Daten auf Datei %N")
             io.put_string ("z : zeigen der Daten %N")
             io.put_string ("q : quit %N")
          end

       ------------------------------------------------

       show_data is
   
          local
             i,j  :  INTEGER
             int  :  INTEGER

          do
             io.put_string ("Koeffizientenmatrix: %N")
             from
                i := 1
             until
                i > a.size1
             loop
                from
                   j := 1
                until
                   j > a.size2
                loop
                   int := a.item(i,j)
                   io.put_string (fmt.i2s("3", int))
                   j := j+1
                end
                io.put_newline
                i := i+1
             end
             io.get_newline
          end
           
       -------------------------------------------------

       get_data is
   
          local
             ch          : CHARACTER
             i,j         : INTEGER
             zzahl,szahl : INTEGER
             f           : FILE [ARRAY2[INTEGER]]
             h           : INTEGER 
    
          do
             io.put_string ("Neue Daten ?       ->  n %N")
             io.put_string ("Daten von Datei ?  ->  d %N")
             io.get_char
             if io.last_char = 'n' then
                io.put_string ("Gib Zeilenzahl %N")
                io.get_int
                zzahl := io.last_int
                io.put_string ("Gib Spaltenzahl %N")
                io.get_int
                szahl := io.last_int
                !!a.make (zzahl, szahl, 0)
                io.put_string ("Matrix zeilenweise eingeben %N")
     
                from
                   i := 1
                until
                   i > a.size1
                loop
                   from
                      j := 1
                   until
                      j > a.size2
                   loop
                      io.get_int 
                      a.put (io.last_int,i,j)
                      j := j+1
                   end
                   i := i+1
                end
 
             else
                h := fs.access_file ("matrix", "rw", false)
                !!f.connect_to (h)
                a := f.item (1)
                f.disconnect
             end
          end

       --------------------------------------------------

       change_data is
   
          local
             i,j  : INTEGER
   
          do
             io.put_string ("Zeile: %N")
             io.get_int
             i := io.last_int
             io.put_string ("Spalte: %N")
             io.get_int
             j := io.last_int
             io.put_string ("Neue Zahl: %N")
             io.get_int
             a.put (io.last_int,i,j)
          end

       ------------------------------------------------

       store_data is
   
          local   
             f : FILE [ARRAY2[INTEGER]]
             h : INTEGER 
   
          do  
             if not fs.file_exists ("matrix") then
                fs.add_file ("matrix", "rw")
             end

             h := fs.access_file ("matrix", "rw", true)
             !!f.connect_to (h)
             f.put (a, 1)
             f.disconnect
          end

       -----------------------------------------------

       end  --  class FILEDEMO


       Mit diesem Programm knnen (mengesteuert) ganze Zahlen in eine Matrix
       eingelesen werden, knnen die Eintrge gendert werden, kann ferner
       die Matrix auf den Bildschirm gebracht werden und kann schlielich die
       Matrix in einer Datei im aktuellen Laufwerk gespeichert und von dort
       wieder geholt werden.
       Nur der letzte Punkt soll hier erlutert werden:
       
       Man betrachte die Prozedur  store_data .
       Mit dem Befehl
                           h := fs.access_file ("matrix", "rw", true)
       verschafft sich die Gre  fs  (vom Typ  FILE_SYSTEM ) Zugang zur phy- 
       sischen Datei  matrix  im aktuellen Laufwerk.
       [ Existiert die physische Datei nicht, so wird sie vorher erzeugt. ]
       Durch den Befehl
                           !!f.connect_to (h)
       wird die Gre  f  (vom Typ  FILE )  mit dem physischen File verbunden.
       Mit den Befehlen
                           f.put (a, 1)
                           f.disconnect
       wird die Matrix  a  an die erste Position von  f  und damit in die 
       physische Datei  matrix  gespeichert.

       In der Prozedur  get_data  geht mit den Befehlen                     
                           h := fs.access_file ("matrix", "rw", false)
                           !!f.connect_to (h)
                           a := f.item (1)
                           f.disconnect
       offensichtlich alles genau umgekehrt.

       
       Die Parameter  rw  und  true/false bedeuten
       rw    :  Zugriffsrecht auf die Datei zum Lesen (r) und Schreiben (w)
       true  :  Die physische Datei wird vor Zugriff gelscht
       false :  Die physische Datei wird vor Zugriff nicht gelscht


       Randbemerkung:
       Im letzten Programm werden die Verweisgren  io (Input-Output) , fmt
       (Format)  und  fs (File System) benutzt. Diese Gren wurden scheinbar
       an keiner Stelle des Programms kreiert, was den Regeln widersprechen
       wrde.
       In der Tat wurden in die Klasse  ANY  drei Routinen hineingeschrie-
       ben, die diese Gren dort ein fr alle mal kreieren.
       Als Beispiel:
                              io : BASIC_IO is
                                  once
                                     !!result
                                  end

       Alternativ dazu kann man solche stndig bentigten Dinge auch in eine
       dafr eigens vorgesehene Klasse schreiben, welche dann von jedem Pro-
       gramm geerbt wird.
       Bei den in Eiffel/S mitgelieferten Beispielprogrammen ist dies die
       Klasse  INTERACT .
