Java in 12 Stunden∗ 0 Was ist Java und warum verwenden wir Java? 0.1 Eigenschaften von Java Java ist eine einfache“, objektorientierte, robuste und plattformunabhängige Pro” grammiersprache. Eine graphische Ausgabe ist mittels der AWT (Abstract Window Toolkit) möglich, für einfache Zwecke verwenden wir im Rahmen des Praktikums auch das Programm GNUPlot. Java besitzt keine Zeiger-Arithmetik und aufgrund des Garbage Collectors (automatische Speicherbereinigung) ist es -gerade für Programmieranfänger- einfacher als C oder C++, die eine ähnliche Symtax besitzen. 0.2 Nachteil von Java Jede Programmiersprache hat seine Vor- und Nachteile. Java läßt leider im Gegensatz zu C++ das Überladen von Operatoren wie +, −, ∗, <, =, == etc. nicht zu. Denkt man etwa an die Implementierung von komplexen Zahlen, so führt dies zu Konstruktionen wie z.add(w) statt z = z+w. 0.3 Warum wollen wir Java einsetzen? Da Java nicht speziell auf mathematische Fragestellungen spezialisiert ist, liegt im Gegensatz zu Programmen wie Mathematica, Maple etc. keine Black-Box vor. Dafür steigt selbstverständlich der Aufwand, den man betreiben muß, um eine gegebene Aufgabe zu implementieren. Allerdings erhöht sich hierdurch auch der Lernaufwand. 0.4 Mehr über Java Im Netz findet man eine Vielzahl an Informationen zum Thema Java, eine gute Quelle ist unter anderem das Buch (und e-book) Java ist auch eine Insel“. Durch die ” Verwendung von Eclipse anstatt eines einfachen Editors kann man den Arbeitsaufwand (zumindest nach einer gewissen Arbeitungszeit) erheblich vereinfachen. Weitere Informationen findet man beispielsweise auch auf unserer Homepage: http://www-computerlabor.math.uni-kiel.de/stochastik ∗ Dieses Mini-Skript ist aus der Einführung in die Programmiersprache Java im Rahmen eines Programmierpraktikums im Sommersemester 2005 am mathematischen Seminar der ChristianAlbrechts-Universität entstanden. Es werden nur die grundlegensten Konzepte vorgestellt. 1 1 Learning by doing: HelloWorld und objektorientierte Programmierung Das nachfolgende Java-Programm gibt Hello world!“ auf den Bildschirm aus und ” zeigt den allgemeinen Aufbau von Java-Programmen: class HelloWorld { public static void main(String args[]){ System.out.println("Hello world!"); // Kommentar } } Aufgabe: Tippen Sie obigen Quelltext ab und speichern Sie diesen in einer Datei namens HelloWorld.java ab. Führen Sie anschließend dieses Programm aus. ❢ Hinweis: • Achten Sie stets auf Groß- und Kleinschreibung! • Es ist wichtig, daß der Name der Klasse (hier: HelloWorld) mit dem Dateinamen (+Endung: .java, hier also HelloWorld.java) übereinstimmt! Zum Übersetzen (Kompilieren, engl.: to compile) und anschließenden Ausführen des Java-Programmes HelloWorld geben Sie in einem Terminal die nachfolgenden Befehle ein: javac HelloWorld.java java HelloWorld Achten Sie auch hier wieder auf Groß- und Kleinschreibung! ❢ Hinweis: Kommentieren Sie Ihre Programme ausführlich und sinnvoll! Kommentare können anstatt mit // (gilt bis zum Zeilenende) auch wie folgt eingeführt werden: /* Kommentar über mehrere Zeilen */ ❢ Tip: Häufig ist es sinnvoll, einzelne Code-Fragmente auszukommentieren, um die Fehlersuche zu vereinfachen. Alternativ können Sie natürlich auch einen Debugger hierzu verwenden. Im obigen Programm wird eine Klasse mit dem Namen HelloWorld deklariert. Wir gehen nun kurz allgemein auf die objektorientierte Programmierung ein: 1.1 Objektorientierte Programmierung: Methoden und Datenkapselung Einfach gesagt ist eine Klasse ein Verbund aus Daten und Funktionen (sogenannten Methoden), die auf diese Daten wirken können. Indem man einen Zugriff auf diese Daten nur mittels dieser Methoden zuläßt, kommt es zur Datenkapselung (Schlüsselwörter: public, protected, private). 2 (Abstrakte) Beispiele: 1.) Ein Punkt im 2 besteht aus zwei reellen Zahlen x, y. Operationen sind beispielsweise die Addition sowie die Skalarmultipliktion, aber auch der Betrag eines Punktes und die Berechnung des zugehörigen Winkels. 2.) Denkt man an eine Datenbank, so besteht diese aus einer Reihe von Datensätzen (die jeweils eine identische Struktur besitzen) und einer Reihe von Operationen (etwa dem Suchen nach einem Datensatz oder dem Sortieren). class Point { private double x,y; // x und y-Komponenten des Punktes public Point(double a, double b) { x = a; // alternativ: this.x = a; y = b; } public double betrag() { return Math.sqrt(x*x+y*y); } public void print() { System.out.println("(" + x + ", " + y + ")"); } public static void main(String args[]) { Point p = new Point(2,3); // Erzeuge einen Punkt p (= (2,3)) p.print(); System.out.println("Betrag = " + p.betrag() ); } } Aufgabe: Tippen Sie das Programm Point ab und speichern Sie dieses in einer Datei namens Point.java. Führen Sie dieses aus. Die Methode Point hat den selben Namen wie die Klasse und wird als Konstruktor bezeichnet. Der Konstruktor hat formal keinen Rückgabewert und wird u.a. zur Initiierung der zugehörigen Datenelemente verwendet. ❢ Das Schlüsselwort void wird für den Konstruktor nicht verwendet! Man beachte, daß erst in der Zeile Point p = new Point(2,3); eine Instanz der Klasse Point erzeugt wird, d.h. es wird Speicher für die Datenelemente (hier: x, y) reserviert. Man sagt auch, daß p ein Objekt der Klasse Point ist. Da x und y private Datenelemente sind, ist ein direkter Zugriff außerhalb der Klasse Point, beispielsweise p.x = 42; in main, nicht möglich. Versuchen Sie es ruhig mal. 3 Aufgabe: Erweitern Sie das Programm Point durch eine Methode namens Abstand, die den (euklidischen) Abstand zweier Punkte zurückliefert, d.h.implementieren Sie public double Abstand(double x 1, double x 2). Wie sieht es alternativ mit public double Abstand(Point p) aus? Die Methode main ist der Einstiegspunkt in das Programm. Auch wenn es mehrere Instanzen (Objekte) vom Typ Point gibt, so darf es nur eine Instanz dieser Methode geben (andernfalls gäbe es mehrere potentielle Einstiegspunkte). Dies geschieht mit dem Schlüsselwort static. Entsprechendes gilt auch für die Datenelemente: Aufgabe: Modifizieren Sie obiges Programm wie folgt: Ersetzen Sie die Zeile private double x,y; durch private static double x; private double y; Und main beinhalte ausschließlich den folgenden Code: Point p1 = new Point(2,3); Point p2 = new Point(4,5); p1.print(); p2.print(); Überlegen Sie sich vorher, was ausgegeben wird! In Java gibt es nur Methoden, also ausschließlich Funktionen, die sich in einer Klasse befinden. Denkt man etwa an Funktionen wie sin, cos etc., so haben diese Methoden stets das Attribut static. ❢ Beachten Sie, daß Klassen nur Datenelemente und Methoden, aber keine Anweisungen enthalten dürfen! public class GehtSoNicht { int i; i=5; // FUNKTIONIERT NICHT! } Hier wurde offensichtlich versucht, daß Datenelement i standardmäßig auf den Wert 5 zu setzen. Dafür verwendet man jedoch einen Konstruktor: public class SoGehtEs { int i; public SoGehtEs() { i = 5; } } 4 1.2 Objektorientierte Programmierung: Vererbung Eine Klasse kann zwei Beziehungen zu anderen Klassen haben: Eine hab ich“- und ” eine bin ich“-Beziehung. So enthält etwa die Klasse Point die beiden Komponenten ” x und y (double ist ein primitiver Datentyp und keine Klasse im eigentlichen Sinn). Andererseits ist ein Hund etwa ein Tier, ein Student ist eine Person etc. Fallen Ihnen weitere Beispiele ein? Es folgt ein einfaches (wenn auch unvollständiges) Beispiel für eine Vererbung in Java: public class Person { private double groesse; private double gewicht; // Grösse // Gewicht public Person(double Neuegroesse, double NeuesGewicht) { groesse = NeueGroesse; gewicht = NeuesGewicht; } public double getGewicht() { // gibt das Gewicht zurück return gewicht; } ... } public class Student extends Person { private int MatrikelNummer; public Student(double NeueGroesse, double NeuesGewicht, int NeueMatrikelNummer) { super(NeueGroesse, NeuesGewicht); // Konstruktor von Person MatrikelNummer = NeueMatrikelNummer; } public int getMatrikelnummer() { return MatrikelNummer; } .... // eine neue Methode! } Notation: Person ist eine Superklasse und Student ist eine Unterklasse (von Person). In diesem Beispiel wurde die Klasse Person noch um ein weiteres Datenelement (die Matrikelnummer) und eine Methode (getMatrikelnummer) erweitert. Innerhalb von Person kann auf die Datenelemente und Methoden, denen das Attribut public oder protected vorangestellt ist, zugegriffen werden. Im obigen Beispiel ist daher der Zugriff auf groesse und gewicht innerhalb von Student nicht möglich, wohl aber auf die Methode getGewicht. Natürlich kann 5 man in der Klasse Person nicht auf die Methode getMatrikelnummer zugreifen. Implementiert man in der Unterklasse eine Methode und gibt es in der Superklasse eine Methode mit gleichem Namen, so spricht man vom Überschreiben. Mittels dem Schlüsselwort super kann man auf die entsprechende Methode in der Superklasse zugreifen. Allgemeiner ist auch super.methodenname(parameter1,parameter2,...) möglich. Es können auch mehrere Methoden mit dem gleichen Namen existieren. Man spricht dann vom Überladen. Allerdings müssen die Parameter dieser Methoden verschieden sein, da ansonsten bei einem Aufruf nicht klar ist, welche Methode nun verwendet werden soll. Frage: Wir wollen obiges Beispiel verallgemeinern. Was fällt Ihnen dazu ein? Genau, man könnte (je nach Anwendung) auch noch Angestellte, Beamte etc. hinzunehmen, allerdings auch Tiere und Gegenstände. An der Spitze dieser Hierachie sitzt dann eine Superklasse, die wir möglicherweise niemals direkt verwenden wollen - sie ist zu abstrakt. Mit dem Schlüsselwort abstract erreicht man, daß man diese Klasse nicht direkt verwenden kann, sondern erst ableiten muß, bevor man eine Instanz erzeugen kann. Alle Klassen in Java haben eine Superklasse namens Object! Aufgabe: 1.) Finden Sie heraus, welche Methoden die Klasse Object besitzt! 2.) Erweitern Sie die Klasse Point (durch Ableiten) zu einer Klasse PointV2 (Point, Version 2), die die Methode GetArg beinhalten soll: • GetArg berechnet den Winkel (und gibt diesen auf dem Bildschirm aus) zwischen der x-Achse und der Geraden, die durch den Punkt (x, y) und den Ursprung geht. Möglicherweise müssen Sie einige Anpassungen an der Klasse Point vornehmen. Welche sind am sinnvollsten? ❢ Hinweis: Verwenden Sie für jede Klasse eine eigene Datei (mit dem gleichen Namen wie dem der Klasse)! Kurz gesagt: Ein gutes Design zahlt sich aus! 2 Primitive Datentypen und Kontrollstrukturen 2.1 Primitive Datentypen Es gibt eine Reihe von Datentypen, auf die in keiner Programmiersprache verzichtet werden kann. In Java sind dies byte, short, int, long, char, float, double, boolean 6 Hier sind im wesentlichen int (Integer) bzw. long (Integer mit größerem Wertebereich), double (Gleitkommazahlen, höhere Genauigkeit als float) und möglicherweise boolean (ein boolscher Ausdruck) von Interesse. Natürlich sind die üblichen Operationen wie +,-,* und / für Variablen vom Typ int, long und double möglich. Manchmal ist folgendes praktisch a += b; a++; // // // // // entspricht der Zuweisung a = a + b; Entsprechendes gilt für *=, -= und /= entspricht der Zuweisung a = a + 1; Es ist auch ++a; möglich (entsprechend a--) (was könnte der Unterschied sein?) Java ist eine objektorientierte Programmiersprache, aber int, long, double etc. sind keine Klassen. Entsprechend gibt es auch die Klassen Byte, Integer, Char, Boolean die entsprechend ein primitives Datenelement kapseln“. Die Klasse Integer stellt ” unter anderen die nachfolgenden Methoden bereit: // Konstruktoren: public Integer(int i) public Integer(String str) // andere Methoden: public double doubleValue() // Beispiel (z.B. in main): // Integer value = new Integer("1234"); // gibt den Wert des aufrufenden Objekts // als double-Wert zurück public int intValue() public String toString() // Gibt den Wert in einer Zeichenkette // (String) zurück Entsprechende Methoden gibt es auch für die Klassen Double, Long und Float. Aufgabe: Schreiben Sie ein Java-Programm, bestehend aus den nachfolgenden Klassen: Koerper, Kreis, Quader, Wuerfel (Ein Körper ist dabei als (meßbare) Teilmenge von 3 zu verstehen.) 1.) Welche Beziehungen liegen vor? 2.) Implementieren Sie die nachfolgenden Methoden: getVolumen, getDurchmesser, getOberflaeche, 7 die entsprechend das Volumen, den Durchmesser und die Oberfläche berechnen und zurückliefern. Natürlich passen Sie main entsprechend an, um obige Klassen zu testen! Hinweis: Das Volumen einer Kugel ist bestimmt durch durch 4πr 2 , r > 0 Radius. 4 3 · πr 3 , die Oberfläche Lösungshinweise: Natürlich ist ein Wuerfel ein Quader und sowohl Kreise, Quader, als auch Würfel sind Körper. Die zu implementierenden Methoden sind die Gemeinsamkeiten dieser Klassen, die jedoch unterschiedlich zu implementieren sind. Wir implementieren die Klasse Koerper als abstrakte Klasse, dadurch kann kein Objekt der Klasse Koerper erzeugt werden. Natürlich gibt es auch andere Lösungsmöglichkeiten, insbesondere dann, wenn Koerper nicht als abstrakte Klasse implementiert werden soll: // Datei: Koerper.java public abstract class Koerper { // Datenelemente: // Man könnte noch Datenelemente hinzufügen, aber // bei dieser Implementierung benötigen wir keine! // // // // (abstrakte) Methoden: Eine abstrakte Methode wir mit dem Schlüsselwort abstract deklariert und besitzt keine definierte Implementierung. (Statt "{ Anweisungen; ... }" gibt es nur ein ";" public abstract double getDurchmesser();// Gibt den Durchmesser zurück public abstract double getOberflaeche(); // Bestimmt die Oberfläche public abstract double getVolumen(); // Gibt die Höhe zurück } // Datei: Kreis.java public class Kreis extends Koerper { // Datenelemente: private double r; // Radius // Konstruktor(en): public Kreis(double Radius) { r = Radius; // "Genauer": this.r = Radius; } // Methoden: // die abstrakten Methoden aus Koerper müssen(!) implementiert werden! public double getDurchmesser() { return 2*r; // Der Durchmesser ist der doppelte Radius } public double getOberflaeche() { return 4* Math.PI * r*r; } 8 public double getVolumen() { // Vorsicht: 4/3 ist eine Integerzahl, also "1" ! return (4.0 / 3.0) * Math.PI * r*r*r; } } // Datei: Quader.java public class Quader extends Koerper { // Datenelemente: private double a; // die drei Kantenl"angen private double b; private double c; // Konstruktor(en): public Koerper(double x, double y, double z) { a = x; b = y; c = z; } // Methoden: public double getDurchmesser() { return Math.sqrt(a*a + b*b + c*c); } public double getOberflaeche() { return (2*a*b + 2*a*c + 2* b*c); } public double getVolumen() { return a*b*c; } } // Datei: Wuerfel.java public class Wuerfel extends Quader { // Datenelemente: // keine // Konstruktor public Wuerfel(double a) { super(a, a, a); // Den Konstruktor von Quader aufrufen } // Methoden: public static void main(String args[]) { Wuerfel w = new Wuerfel(3); // Beispiel Koerper k = new Quader(1,2,3); // Geht auch! System.out.println("Beispiel Wuerfel: "+ w.getVolumen()); System.out.println("Beispiel Quader "+ k.getDurchmesser()); } } 9 2.2 Kontrollstrukturen Natürlich macht es im allgemeinen wenig Sinn, den Quelltext eines (Java-) Programmes einfach zeilenweise auszuführen: 2.2.1 Die if-Anweisung if( Bedingung1 ) { // Anweisungen... } else if( Bedingung2 ) { // andere Anweisungen... } ... else { // falls keine der obigen Bedinungen erfüllt sind // Anweisungen } Sowohl die else if als auch die else Anweisung ist optional, aber ohne ein if kann natürlich kein else verwendet werden. ❢ Wichtiger Hinweis: In Java ist = ein Zuweisungsoperator, d.h. if( a=b ) ist stets erfüllt - zumindest wenn a und b zuvor eingeführt worden sind! Gemeint ist hier jedoch sicherlich der Vergleich von a und b: if(a == b) ... { // "==" statt "=" !!! Dieser Fehler dürfte vom Compiler zwar erkannt werden (allerdings wohl nur als Warning“ und nicht als Error“), es ist jedoch ein sehr häufig gemachter ” ” Fehler. a!=b entspricht entsprechend der Aussage (wahr oder falsch), ob a und b verschieden sind. ❢ Hinweis: Strukturieren Sie Ihre Programme indem Sie den Quelltext entsprechend formatieren! Sie verlieren den Überblick, wenn Sie alle Zeilen ohne Abstand (bzw. Einrückung) direkt untereinander schreiben. Für Java ist dies kein Problem, aber Sie verlieren SEHR leicht die Übersicht! 10 2.2.2 Die for-Schleife Die for-Schleife entspricht der Umsetzung von n P xi : i=0 for(int i = 0; i <= n; i++) { // Anweisungen ... } // ab hier ist i wieder unbekannt Allgemein hat die for-Schleife die Form for( Initialisierung; Fortsetzungsbedingung; Aktualisierung) { Anweisungen... } Im obigen Beispiel wird die Laufvariable i erst zu dem Zeitpunkt eingeführt, zu dem man sie auch benötigt. Natürlich können Sie i auch schon vorher einführen, zumindest bei for-Schleifen ist dies jedoch in den meist Fällen unangebracht. Beispiel: Fügen Sie die folgenden Anweisungen in main ein, übersetzen Sie Ihr Programm und führen Sie es wie folgt aus java programmname Ich bin ein Parameter (dabei steht programmname für den Namen ihres Java-Programmes): for(int i=0; i < args.length; i++) { System.out.println(i + "-ter Parameter: " + args[i]); } Dies ist auch gleich ein Beispiel für ein Feld (Array), wobei man bedenke, daß in einem solchen Fall die Zählung stets bei 0 beginnt! 2.2.3 Die while-Schleife Solange eine Bedingung nicht erfüllt ist, wird der nachfolgende Block ausgeführt: while( Bedingung ) { Anweisungsblock } Die while-Schleife überprüft die Bedingung zu Beginn der Schleife, ist die Bedingung zu Beginn nicht erfüllt, wird die Schleife gar nicht ausgeführt. Eine for-Schleife ist im Grunde eine while-Schleife, wie das nachfolgende Beispiel zeigt: int i; i = 0; while( i < 10) { System.out.println(i); i++; // entspricht: i = i +1; } 11 2.2.4 Die do-Schleife Die while-Schleife überprüft die Bedingung bereits vor dem ersten Schleifendurchlauf. Bei der do-Schleifen findet eine Überprüfung erst nach dem Schleifendurchlauf statt. Damit wird der Anweisungsblock innerhalb einer do-Schleife mindestens einmal ausgeführt! do { Anweisungsblock } while ( Bedingung ); 2.2.5 Felder (Arrays) Wie stellt man in Java ein Element aus dem n dar? Natürlich führt man dazu n double-Variablen ein. Möchte man diese durchindizieren, so verwendet man Felder (Arrays): int vektor[]; double matrix[][]; // Ein Array von int-Werten // 2D-Array von double-Werten Man beachte, daß noch kein Speicher für vektor und matrix reserviert wurde (ja, wieviele Elemente sollen vektor und matrix eigentlich haben?). Dies geschieht erst mit vektor = new int[10]; matrix = new double[10][20]; Zugriff erfolgt dann mittels vektor[i] bzw. matrix[i][j]. Ein anderes Beispiel ist int liste[] ={1,2,3,5}; In diesem Fall wird bereits Speicher für liste reserviert. ❢ Hinweis: • Die Zählung beginnt stets bei 0, also vektor[0],...,vektor[9]! • Liegt kein primitiver Datentyp vor, sondern Klassen, so ist Vorsicht geboten: Point punkte[] = new Point[5]; reserviert nicht etwa Speicher für 5 Instanzen vom Typ Point, sondern es wird nur Speicher für 5 Verweise (Referenzen) auf mögliche Instanzen vom Typ Point reserviert. Also: Point punkte[]; // Zugriff auf punkte[0] ist nicht möglich punkte = new Point[5]; // Zugriff auf punkte[i] ist möglich, aber punkt[i] zeigt // noch auf keine Instanz vom Typ Point for(int i = 0; i<5; i++) { punkte[i] = new Point(2,3); } 12 3 Verschiedenes 3.1 Noch einmal Point Betrachte Point a = new Point(1,2); Point b = new Point(1,2); Wir wollen testen, ob die a und b den selben Punkt repräsentieren. Der naive Ansatz if(a==b) führt jedoch nicht zum gewünschten Ergebnis! a und b sind Verweise (Referenzen), d.h. a und b verweisen auf eine bestimmte Speicheradresse, die jedoch verschieden sind. Damit ist a==b false. Point erbt jedoch von der Superklasse Object die Methode equals. Aus diesem Grund betrachten wir stattdessen if(a.equals(b)). Leider erhalten wir auch dieses Mal nicht das Gewünschte. Überschreibt man die Methode equals (in Point) geeignet, so kommt man jedoch zum Ziel. 3.2 Die Ein- und Ausgabe Bislang haben wir zwar die Ausgabe auf dem Bildschirm mittels System.out.println verwendet, allerdings ist die Eingabe (oder die Ausgabe in eine Datei) sicherlich ebenso nützlich. Was aber passiert, wenn eine Integer-Zahl eingelesen weden soll und der Anwender auch Buchstaben getippt hat? Java wirft in diesem Fall eine Ausnahme, eine Exception. Eine Exception tritt auch auf, wenn man beispielsweise versucht durch 0 zu teilen. try { // Anweisungsblock, häufig auch nur 1,2 Anweisungen, // die eine Exception werfen können } catch (Ausnahmetyp1 a) { // Ausnahmebehandlung } catch (Ausnahmetyp2 b) { // Ausnahmebehandlung } ... finally { // Code, der vor Beendigung des try-Blocks ausgeführt werden muss } Für die Ausgabe in eine Datei und das Lesen von der Tastatur stellen wir den Teilnehmern eine Klasse namens InputOutput bereit. Schauen Sie sich den Quelltext einfach mal an und versuchen Sie ihn zu verstehen! // Eingabe ber die Tastatur: InputOutput.Key.getInt() // liefert ein Integer-Wert 13 InputOutput.Key.getDouble() // liefert ein Double-Wert // Dateioperationen (schreiben): InputOutput.WriteFile.setFilename(String NewFilename) // Setzt einen Dateinamen InputOutput.WriteFile.ResetFile() // löscht die Datei InputOutput.WriteFile.writeDouble(double value) // schreibt einen Double-Wert InputOutput.WriteFile.writeInteger(int value) // schreibt einen Int-Wert writeChar(char value) // schreibt ein char-Wert writeLineFeed() // fügt einen Zeilenvorschub ein Betrachten Sie beispielsweise die nachfolgende Anwendung: ... double wert = 3.6615; InputOutput.WriteFile.SetFilename("Test.txt"); InputOutput.WriteFile.WriteDouble(wert); InputOutput.WriteFile.WriteChar(’ ’); // Leerzeichen einfügen InputOutput.WriteFile.WriteInteger(42); 3.3 Zufallszahlen Binden Sie zunächst ein weiteres Java-Package ein mittels: import java.util.*; (außerhalb der Klasse in einer der ersten Zeilen der Datei!). Dann liefert Math.random() eine auf [0, 1] gleichverteilte Pseudo-Zufallszahl. 3.4 GNUPlot Natürlich ist mit Java auch eine grafische Ausgabe möglich. Wir verwenden jedoch (zunächst?) das Programm GNUPlot. Rufen Sie dieses wie folgt auf: gnuplot 14 Wenn Sie jetzt beispielsweise plot sin eingeben, erhalten Sie eine einfache Darstellung vom Sinus. Wir verwenden GNUPlot zur Darstellung von Daten. Diese müssen stets im folgenden Format (hier: zwei-dimensional) vorliegen: x_0 y_0 x_1 y_1 x_2 y_2 ... Den Inhalt einer Datei test.txt können Sie mittels plot “test.txt“ oder plot “test.txt“ with points von GNUPlot darstellen lassen. 15