Universität Ulm,
Fakultät für Mathematik und Wirtschaftswissenschaften,
SAI,
WS 1998/99,
Allgemeine Informatik I
Lösung zu Blatt 10 --- Allgemeine Informatik I (WS 1998/99)
12. Kantige Kurven
(*
Allgemeine Informatik I / Programmieren I WS 1998/1999
Musterloesung fuer das Blatt 10, Aufgabe 12
Andreas Borchert, 11. Januar 1998
*)
MODULE FPlot;
FROM Arguments IMPORT InitArgs, GetFlag, AllArgs, FetchString, Usage,
FetchCard;
FROM Functions IMPORT Function, ParseFunction, SetFuncParam,
EvalFunction, errpos;
FROM InOut IMPORT Write, WriteString, WriteLn;
FROM SysExit IMPORT Exit;
IMPORT StdFuncs;
VAR
(* Kommandozeilenparameter *)
function: Function; (* zu plottende Funktion *)
varname: ARRAY [0..7] OF CHAR; (* Variablenname, normalerweise "x" *)
xmin, xmax: REAL; (* Darzustellender Bereich auf der X-Achse *)
xdelta: REAL; (* Abstaende zwischen den Punkten auf der X-Achse *)
height, width: CARDINAL;
PROCEDURE ProcessArgs;
VAR
flag: CHAR; (* einzelne Option auf der Kommandozeile *)
PROCEDURE FetchFunction(VAR function: Function);
(* Uebernahme eines von Functions(3) unterstuetzten Ausdrucks
aus der Kommandozeile; analog zu FetchCard etc. brechen
wir sofort ab, wenn die Angabe nicht in Ordnung ist
*)
VAR
fstring: ARRAY [0..127] OF CHAR;
index: CARDINAL;
BEGIN
FetchString(fstring);
IF ~ParseFunction(fstring, function) THEN
WriteString("Fehler in dem Ausdruck:"); WriteLn;
WriteString(fstring); WriteLn;
FOR index := 1 TO errpos DO
Write(" ");
END;
WriteString("^--- Fehlerposition"); WriteLn;
Exit(1);
END;
END FetchFunction;
PROCEDURE FetchReal(VAR real: REAL);
(* statt nur die Eingabe reeller Zahlen zuzulassen,
sind wir hier grosszuegig und erlauben beliebige
Ausdruecke von Functions. Dies erlaubt die Spezifikation
von Konstanten wie ``pi'' oder ``e'
*)
VAR
expression: Function;
BEGIN
FetchFunction(expression);
real := EvalFunction(expression);
END FetchReal;
BEGIN (* ProcessArgs *)
(* Voreinstellungen *)
xdelta := 0.1;
xmin := -1.0; xmax := 1.0;
varname := "x";
height := 23;
width := 80;
(* Abarbeiten der Parameter *)
InitArgs("[-d xdelta] [-h hoehe] [-v varname] [-w weite] [-x min max] function");
WHILE GetFlag(flag) DO
CASE flag OF
| "d": FetchReal(xdelta); width := 0;
| "h": FetchCard(height);
| "v": FetchString(varname);
| "w": FetchCard(width);
| "x": FetchReal(xmin); FetchReal(xmax);
ELSE
Usage;
END;
END;
FetchFunction(function); AllArgs;
END ProcessArgs;
CONST
plotch = "X";
space = " ";
CONST
plotbufsize = 8192;
VAR
(* Statusvariablen des Plotters *)
plotbuf: ARRAY [0..plotbufsize-1] OF REAL;
plotindex: [0..plotbufsize];
minvalue, maxvalue: REAL;
PROCEDURE InitPlotter;
BEGIN
plotindex := 0; minvalue := 0.0; maxvalue := 0.0;
END InitPlotter;
PROCEDURE Plot(x, y: REAL);
(* Diese Version von Plot ignoriert x und geht stattdessen davon
aus, dass die Abstaende zwischen den x-Werten gleichmaessig sind
*)
BEGIN
IF plotindex <= HIGH(plotbuf) THEN
plotbuf[plotindex] := y;
(* Minimum und Maximum aktualisieren, wobei wir Singularitaeten
herausnehmen
*)
IF (y > MIN(REAL)) & (y < minvalue) THEN
minvalue := y;
ELSIF (y < MAX(REAL)) & (y > maxvalue) THEN
maxvalue := y;
END;
INC(plotindex);
END;
END Plot;
PROCEDURE FlushPlotter;
(* Graphische Ausgabe der gesammelten Werte *)
VAR
ydelta: REAL;
column: [0..plotbufsize-1];
line: CARDINAL;
value: REAL;
BEGIN
ydelta := (maxvalue - minvalue) / FLOAT(height);
FOR line := height-1 TO 0 BY -1 DO
value := minvalue + FLOAT(line) * ydelta;
FOR column := 0 TO plotindex-1 DO
IF plotbuf[column] >= value THEN
Write(plotch);
ELSE
Write(space);
END;
END;
WriteLn;
END;
END FlushPlotter;
PROCEDURE FPlot;
(* Das Intervall zwischen xmin und xmax wird entsprechend
der Spezifikation von width oder xdelta aequidistant
unterteilt und fuer alle Zwischenpunkte x wird die
angegebene Funktion bewertet und (x,f(x)) an Plot uebergeben
*)
VAR
x, y: REAL; (* x, f(x) *)
n, (* Zwischenpunktindex 0..m *)
m: CARDINAL; (* Anzahl der Teilintervalle *)
BEGIN
IF width # 0 THEN
xdelta := (xmax - xmin) / FLOAT(width - 1);
END;
m := TRUNC((xmax - xmin) / xdelta);
FOR n := 0 TO m DO
x := xmin + FLOAT(n) * xdelta;
SetFuncParam(function, varname, x);
Plot(x, EvalFunction(function));
END;
END FPlot;
BEGIN
ProcessArgs;
InitPlotter;
FPlot;
FlushPlotter;
END FPlot.
Andreas Borchert, 20. Januar 1999