Home Computer Pascal Kurs Site Map counter

Jetzt lerne ich Pascal... Teil 9

Objekte in Aktion

Nachdem ich mich Teil 7 schon über Objekte ausgelassen habe, nun ein Beispiel. Das Problem bei Objekten ist, das man für den Nutzen schon etwas mehr Code schreiben muss, und Bei Turbo Pascal es nur ein eingeschränktes Objektmodell gibt (es gibt Objekte, aber keine Klassen). So richtig nützlich werden Objekte erst in Delphi, mit erheblich besseren programmtechnischen Eigenschaften.

Trotzdem hier ein Stringobjekt, das eine Art komfortabler String sein soll. Es gibt ja eine Reihe von String Routinen. Doch einige fehlen, so z.B. einen String ab einer bestimmten Position zu durchsuchen oder in Kleinbuchstaben umzuwandeln. Gleichzeitig ist die Val Prozedur ein echter Witz weil es eigentlich eine Funktion und keine Prozedur sein sollte. Daneben sind die Stringfunktionen nicht sehr sicher, z.B. wenn ich angebe Delete('Hallo',2,10); dann wird ein 'H' daraus - vielleicht will ich aber das in diesem Fall von falscher Längenangabe gar nicht gelöscht wird. Es sollte also mehr auf Eingabefehler reagiert werden.

Kurzum Strings eignen sich gut zum Bauen eines String-Objektes. Ich habe hier nicht ganz sauber Programmiert, da ich der Wert (val) als public deklariert habe um die gebräuchlichen Operatoren (=,+:=) weiterhin benutzen zu können. Ziel war, es das man das Stringobjekt ähnlich Strings benutzen kann, aber mit mehr Sicherheit und komfortablen Routinen:

unit Strobj;

interface
const
Maxlen 80;

type
Tstringobject object
public
Val : string[Maxlen];
procedure Eq(const Dest : string);
function Length : Byte;
function Pos(const Suchmuster : string): Byte;
function Instr(const Suchmuster : string; Start : Byte): Byte;
function Rightpos(const Suchstr : string): Integer;
procedure Add(const Dest : string);
procedure Delete(const Start,Anzahl : Byte);
procedure Deleteto(const Start,Ende : Byte);
function Substr(const Start,Ende : Byte): string;
function Copy(const Start,Anzahl : Byte): string;
procedure Insert(const Dest: string; Start : Byte);
procedure Replace(const Ersatz : string; const Position : Integer);
function Doubleval : Extended;
function Intval : LongInt;
function Delspace : string;
function TrimRight : string;
function Trim : string;
function Lowcase : string;
function UpCase : string;
constructor Create;
end;

implementation

constructor
Tstringobject.Create;

begin
Val:='';
end;


procedure Tstringobject.Eq(const Dest : string);

begin
if
System.Length(Dest)<=Maxlen
then Val:=Dest;
end;

function Tstringobject.Length : Byte;

begin
Length:=System.Length(Val);
end;

function Tstringobject.Pos(const Suchmuster : string): Byte;

begin
Pos:=System.Pos(Suchmuster,Val);
end;

function Tstringobject.Instr(const Suchmuster : string; Start : Byte): Byte;

begin
if
Start<Length
then Instr:=System.Pos(Suchmuster,System.Copy(Val,Start,Maxlen))+Start-1
else Instr:=0;
end;

procedure Tstringobject.Add(const Dest : string);

begin
Val:=Val+Dest;
end;

procedure Tstringobject.Delete(const Start,Anzahl : Byte);

begin
if
(Start<=Length) and (Start+Anzahl<=Length)
then System.Delete(Val,Start,Anzahl);
end;

procedure Tstringobject.Deleteto(const Start,Ende : Byte);

begin
if
(Start<=Length) and (Ende<=Length) and (Ende>Start)
then System.Delete(Val,Start,Ende-Start);
end;

procedure Tstringobject.Insert(const Dest: string; Start : Byte);

begin
if
(Start<=Length) and (System.Length(Dest)+Start<=Maxlen)
then System.Insert(Dest,Val,Start);
end;

function Tstringobject.Doubleval : Extended;

var Temp : Extended;
Code : Integer;

begin
System.Val(Val,Temp,Code);
if Code0 then Doubleval:=Temp else Doubleval:=-1.0;
end;

function Tstringobject.Intval : LongInt;

var Temp : LongInt;
Code : Integer;

begin
System.Val(Val,Temp,Code);
if Code0 then Intval:=Temp else Intval:=-1;
end;

procedure Tstringobject.Replace(const Ersatz : string; const Position : Integer);

var I : Integer;

begin
if
(Position>0) and (System.Length(Ersatz)+Position<=Length)
then
begin
for
I:=1 to System.Length(Ersatz) do
Val[I+Position-1]:=Ersatz[I];
end;
end;

function Tstringobject.Delspace : string;

var I: Integer;
Strng : string[Maxlen];

begin
Strng:=Val;
I:=System.Pos(' ',Strng);
while I>0 do
begin
System.Delete(Strng,I,1);
I:=System.Pos(' ',Strng);
end;
Delspace:=Strng;
end;


function Tstringobject.TrimRight : string;

var I : Integer;
Strng : string[Maxlen];

begin
Strng:=Val;
I:=Length;
while (I>0) and (Strng[I]=' ') do
begin
System.Delete(Strng,I,1);
Dec(I);
end;
TrimRight:=Strng;
end;

function Tstringobject.Trim : string;

var I : Integer;
Strng : string[Maxlen];

begin
Strng:=Val;
while (System.Length(Strng)>0) and (Strng[1]=' ')
do System.Delete(Strng,I,1);
Trim:=Strng;
end;

function Tstringobject.Rightpos(const Suchstr : string): Integer;

var I,Len : Integer;
Flag : Boolean;

begin
Len:=System.Length(Suchstr);
if Length<Len then begin Rightpos:=-1; Exit; end;
I:=Length-Len;
repeat
Flag:=System.Copy(Val,I+1,Len)=Suchstr;
Dec(I);
until Flag or (I0);
if Flag then Rightpos:=I+1 else Rightpos:=0;
end;

function Tstringobject.Lowcase : string;

var Strng : string[Maxlen];
I : Integer;

begin
Strng:='';
for I:=1 to Length do
if
Val[I] in ['A'..'Z'] then Strng:=Strng+Chr(Ord(Val[I])+32)
else Strng:=Strng+Val[I];
Lowcase:=Strng;
end;

function Tstringobject.UpCase : string;

var Strng : string[Maxlen];
I : Integer;

begin
Strng:='';
for I:=1 to Length do
if
Val[I] in ['a'..'z'] then Strng:=Strng+Chr(Ord(Val[I])-32)
else Strng:=Strng+Val[I];
UpCase:=Strng;
end;

function Tstringobject.Substr(const Start,Ende : Byte): string;

begin
Substr:=System.Copy(Val,Start,Ende-Start);
end;

function Tstringobject.Copy(const Start,Anzahl : Byte): string;

begin
Copy:=System.Copy(Val,Start,Anzahl);
end;

end.
Hier nun ein kleines Testprogramm: Sichtbar wird, das Delspace und Lowcase nur den konvertierten String zurückgeben, aber das Original nicht verändern. Deutlich wird auch das man im Text oftmals kürzer schreiben kann: Anstatt

Writeln(Lowcase(astr))

bei einem normalen String schreibt man

Writeln(Astr.lowcase)

Wobei hier auch deutlich ist: Die Ausgabe in Kleinbuchstaben ist eine Funktion des String Objektes "astr" und nicht der Aufruf einer Funktion die etwas mit einem String macht. Es ist klarer. Noch besser und mehr im Sinne der objektorientierten Programmierung wäre es wenn das Feld val private wäre und man noch Methoden für:= und = sowie Wertrückgabe implementieren würde. Auch würde man alles als Funktionen realisieren und Rückgabewerte mit Fehlercodes verwenden. Doch dann wird's zum einen kompliziert und zum anderen wäre es dann auch angesagt gleich ein fortgeschrittenes Objektmodell zu nehmen wie in Free Pascal oder Delphi wo man dann eine Exception auslöst auf die dann das Hauptprogramm reagiert.

uses Strobj;

var Astr : Tstringobject;

begin
Astr.Val:='Hallo Welt';
Astr.DeleteTo(1,20);
{Raten Sie mal was nun in Val steht?}
WriteLn(Astr.Delspace);
WriteLn(Astr.Lowcase);
WriteLn(Astr.Rightpos('Welt'));
WriteLn(Astr.Val);
Astr.Val:='566';
WriteLn(Astr.Doubleval);
WriteLn(Astr.Intval);
end.

Neben der besseren Lesbarkeit und der Zusammengehörigkeit von Daten und Methoden gibt es noch zwei weitere Dinge die bei Objekten vorteilhaft sind. Zum einen ist es die Sicherheit. Sie sehen dies bei den Methoden Insert, Delete und Replace. Hier wird der String nur verändert wenn die Indexangaben gültig sind. Das ist eine zusätzliche Fehlerprüfung, die eine Methode bietet.

Das zweite ist das Verstecken von Implementierungsdetails. Hier wird ein generischer String verwendet. Vielleicht wechseln sie aber mal intern auf den Typ PChar um dynamisch den Speicherplatz anzufordern und nicht immer 256 Bytes, egal wie lang der String ist. Dann können alle Routinen intern mit diesem Format intern arbeiten, die Aufrufschnittstelle bleibt jedoch unverändert.

Dazu ein Beispiel aus der Praxis. Ich habe ein eigenes Mailprogramm geschrieben, bei dem ein Objekt eine Mailnachricht ist mit verschiedenen Feldern wie To:, From: bcc: subject: etc. Für das Absenderfeld war ursprünglich nur ein String vorgesehen. Bis ich bemerkte, das zahlreiche Benutzer die BCC und CC Felder für weitere Adressaten nicht nutzten sondern alle Adressaten in das Absenderfeld packten und durch Kommas trennten. Nun habe ich das Absenderfeld durch eine Stringliste ersetzt die bei schreibenden Zugriff (immer noch mit einem String) die Mailadressen in einzelne Strings trennt und beim Lesen wieder zusammensetzt. Von außen ist diese Änderung nicht zu erkennen.


Zum Thema Computer ist auch von mir ein Buch erschienen. "Computergeschichte(n)" beinhaltet, das was der Titel aussagt: einzelne Episoden aus der Frühzeit des PC. Es sind Episoden aus den Lebensäufen von Ed Roberts, Bill Gates, Steve Jobs, Stephen Wozniak, Gary Kildall, Adam Osborne, Jack Tramiel und Chuck Peddle und wie sie den PC schufen.

Das Buch wird abgerundet durch eine kurze Erklärung der Computertechnik vor dem PC, sowie einer Zusammenfassung was danach geschah, als die Claims abgesteckt waren. Ich habe versucht ein Buch zu schreiben, dass sie dahingehend von anderen Büchern abhebt, dass es nicht nur Geschichte erzählt sondern auch erklärt warum bestimmte Produkte erfolgreich waren, also auf die Technik eingeht.

Die 2014 erschienene zweite Auflage wurde aktualisiert und leicht erweitert. Die umfangreichste Änderung ist ein 60 Seiten starkes Kapitel über Seymour Cray und die von ihm entworfenen Supercomputer. Bedingt durch Preissenkungen bei Neuauflagen ist es mit 19,90 Euro trotz gestiegenem Umfang um 5 Euro billiger als die erste Auflage. Es ist auch als e-Book für 10,99 Euro erschienen.

Mehr über das Buch auf dieser eigenen Seite.

Sitemap Kontakt Neues Hier werben Bücher vom Autor Buchempfehlungen Top 99