home *** CD-ROM | disk | FTP | other *** search
- (* ----------------------------------------------------------------------- *)
- (* DYNSTR.PAS *)
- (* dynamische Stringverwaltung in Pascal *)
- (* Bibliothek fuer Turbo-Pacal und MS-DOS Version 1.0 *)
- (* (C) 1987 Walter Christ & PASCAL INT. *)
- (* ----------------------------------------------------------------------- *)
- Type (* Typedeklaration dynamischer String *)
- DynString = RECORD
- anz : integer;
- case integer of
- 1 : (st : ^char);
- 2 : (adr,seg : integer;)
- end;
- CharPointer = RECORD case integer of (* Typdeklaration Char-Zeiger *)
- 1 : (st : ^char);
- 2 : (adr,seg : integer;)
- end;
- MaxPascalString = string[255]; (* Groesster Pascalstring *)
- var
- RTE : boolean; (* RunTimeError - Flag *)
- (* ----------------------------------------------------------------------- *)
- (* Laufzeitfehler der Library - es ist nicht mehr genuegend Speicher vor- *)
- (* vorhanden: *)
- PROCEDURE RunTimeError;
- BEGIN
- RTE := TRUE; (* Error Flag setzen *)
- (* Hier koennen programmspezifische Fehlerbehandlungen eingefuegt werden *)
- END;
- (* ----------------------------------------------------------------------- *)
- (* einem dynamischen String einen Wert zuweisen. 'pastring' kann ein be- *)
- (* liebiger Pascalstring sein: *)
- procedure DefDynString (var dst : dynstring; pastring : maxpascalstring );
- var helppointer, merker : charpointer; i : integer;
- BEGIN
- if (dst.anz > 0) THEN FreeMem(dst.st,dst.anz); (* alten Inhalt loeschen *)
- (* neuen Speicherplatz holen *)
- if ((MaxAvail-1) < Length(pastring)/16) THEN
- BEGIN RunTimeError; dst.anz := 0; END
- ELSE
- BEGIN
- GetMem(dst.st,Length(pastring));
- merker.st := dst.st; (* Pointer ausrichten *)
- helppointer.st := Addr(pastring[1]);
- for i := 1 to ord(pastring[0]) do begin (* Inhalt kopieren *)
- merker.st^ := helppointer.st^;
- merker.adr := succ(merker.adr);
- helppointer.adr := succ(helppointer.adr);
- END;
- dst.anz := ord(pastring[0]); (* Laenge setzen *)
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Dynamische String aneinanderreihen. 'dst2' wird an 'dst' angehaengt *)
- procedure ConcatDynString (var dst : dynstring; dst2 : dynstring );
- var helppointer, merker, merker2 : charpointer; i : integer;
- BEGIN
- merker.st := dst.st; (* alten Bereich merken *)
- helppointer.st := dst.st; (* neuen Bereich anfordern: *)
- if ((MaxAvail-1) < (dst.anz+dst2.anz)/16 ) THEN RunTimeError
- ELSE BEGIN
- GetMem(dst.st,dst.anz + dst2.anz);
- merker2.st := dst.st; (* neuen Bereich merken *)
- for i := 1 to dst.anz do begin (* 'dst' in neuen Bereich kopieren *)
- merker2.st^ := merker.st^;
- merker2.adr := succ(merker2.adr);
- merker.adr := succ(merker.adr);
- END;
- merker.st := dst2.st;
- for i := 1 to dst2.anz do BEGIN (* 'dst2' in neuen Bereich kopieren *)
- merker2.st^ := merker.st^;
- merker2.adr := succ(merker2.adr);
- merker.adr := succ(merker.adr);
- END;
- if (dst.anz > 0) THEN FreeMem(helppointer.st,dst.anz);
- dst.anz := dst.anz + dst2.anz;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* dynamischer String auf Bildschirm ausgeben: *)
- PROCEDURE PrintDynString (dst : dynstring);
- var st : charpointer; i : integer;
- BEGIN
- st.st := dst.st;
- for i := 1 to dst.anz do BEGIN
- (* Hier laesst sich leicht ein System-Aufruf implementieren *)
- write(st.st^);
- st.adr := succ(st.adr);
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* dynamischer String auf Bildschirm ausgeben, danach in neue Zeile gehen: *)
- PROCEDURE PrintLnDynString (dst : dynstring);
- BEGIN printdynstring(dst); writeln; END;
- (* ----------------------------------------------------------------------- *)
- (* Insert-Funktion fuer dynamische Strings. 'Obj' und 'Target'-String *)
- (* muessen beide dynamische String sein: *)
- PROCEDURE InsertDynString (Obj :dynstring; var Target : dynstring ;
- Pos : integer);
- var helppointer, merker, merker2, merker3 : charpointer; i : integer;
- BEGIN (* Gueltigkeitsbereich ueberpruefen: *)
- if (Pos > Target.anz) THEN Pos := Target.anz + 1;
- if ( Pos < 1 ) THEN Pos := 1;
- merker.st := target.st; (* alten Bereich merken *)
- helppointer.st := target.st; (* neuen Bereich anfordern: *)
- if (MaxAvail-1 < (obj.anz + Target.anz)/16) THEN RunTimeError
- ELSE BEGIN
- GetMem(target.st,obj.anz + Target.anz);
- merker2.st := target.st; (* neuen Bereich merken *)
- for i := 1 to Pos-1 do BEGIN (* 'target' in neuen Bereich kopieren *)
- merker2.st^ := merker.st^;
- merker2.adr := succ(merker2.adr);
- merker.adr := succ(merker.adr);
- END;
- merker3.st := obj.st; (* 'obj' in neuen Bereich kopieren *)
- for i := 1 to obj.anz do BEGIN
- merker2.st^ := merker3.st^;
- merker2.adr := succ(merker2.adr);
- merker3.adr := succ(merker3.adr);
- END;
- for i := pos to Target.anz do BEGIN (* Target 2. Teil kopieren *)
- merker2.st^ := merker.st^;
- merker2.adr := succ(merker2.adr);
- merker.adr := succ(merker.adr);
- END;
- if (target.anz > 0) THEN FreeMem(helppointer.st,target.anz);
- target.anz := target.anz + obj.anz;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Delete-Prozedur fuer dynamische Strings: *)
- PROCEDURE DeleteDynString (var St :dynstring; Pos :integer; Num :integer);
- var merker, merker2, helppointer : charpointer; i : integer;
- BEGIN
- if (Pos+Num <= st.anz ) THEN BEGIN
- helppointer.st := st.st;
- merker.st := st.st;
- if (MaxAvail -1 < (st.anz-num)/16) THEN RunTimeError
- ELSE BEGIN
- GetMem(st.st,st.anz-num);
- merker2.st := st.st;
- for i := 1 to Pos do BEGIN (* String Teil1 kopieren *)
- merker2.st^ := merker.st^;
- merker.adr := succ(merker.adr);
- merker2.adr := succ(merker2.adr);
- END;
- merker.adr := helppointer.adr + num + pos;
- for i := Pos + num to st.anz do BEGIN (* String Teil2 kopieren *)
- merker2.st^ := merker.st^;
- merker.adr := succ(merker.adr);
- merker2.adr := succ(merker2.adr);
- END; (* Speicherplatz von geloeschten Zeichen freigeben: *)
- FreeMem(helppointer.st,st.anz);
- st.anz := st.anz - num;
- END;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Copy-Funktion fuer dynamische Strings *)
- PROCEDURE CopyDynString (var dst,src : dynstring; pos,num : integer);
- var merker, merker2, helppointer : charpointer; i : integer;
- BEGIN
- if (pos + num <= src.anz ) THEN BEGIN
- helppointer.st := dst.st; (* neuen Speicherplatz holen: *)
- if (Maxavail-1 < num/16) THEN RunTimeError
- ELSE BEGIN
- GetMem(dst.st,num); (* Pointer ausrichten: *)
- merker.st := dst.st;
- merker2.st := src.st;
- merker2.adr := merker2.adr + pos;
- for i := 1 to num do BEGIN (* Inhalt kopieren *)
- merker.st^ := merker2.st^;
- merker.adr := succ(merker.adr);
- merker2.adr := succ(merker2.adr);
- END; (* alten Inhalt loeschen: *)
- if dst.anz > 0 THEN FreeMem(helppointer.st,dst.anz);
- dst.anz := num; (* Laenge setzen *)
- END;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* einen dynamischen String loeschen *)
- PROCEDURE ClearDynString (var str : dynstring);
- BEGIN
- if str.anz > 0 THEN BEGIN (* Speicher freigeben: *)
- FreeMem(str.st,str.anz); str.anz := 0;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* einen dynamischen String initialisieren *)
- PROCEDURE InitDynString (var str : dynstring);
- BEGIN str.anz := 0; END;
- (* ----------------------------------------------------------------------- *)
- (* der Inhalt von 'dst' wird nach 'src' kopiert *)
- PROCEDURE AssignDynString (var dst : dynstring; src : dynstring);
- var merker, merker2 : charpointer; i : integer;
- BEGIN
- if dst.anz > 0 THEN FreeMem(dst.st,dst.anz); (* alten Speicher freigeben *)
- if Maxavail-1 < src.anz/16 THEN (* Speicher anfordern *)
- BEGIN RunTimeError; dst.anz := 0; END
- ELSE BEGIN
- Getmem(dst.st,src.anz);
- merker.st := src.st; (* Pointer ausrichten *)
- merker2.st := dst.st;
- for i := 1 to src.anz do begin (* kopieren *)
- merker2.st^ := merker.st^;
- merker2.adr := succ(merker2.adr);
- merker.adr := succ(merker.adr);
- END;
- dst.anz := src.anz;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* diese Funktion liefert die Laenge eines dynamischen Strings *)
- FUNCTION LenDynString (str : dynstring ) : integer;
- BEGIN Lendynstring := str.anz; END;
- (* ----------------------------------------------------------------------- *)
- (* diese Funktion liefert ein Zeichen aus einem dynamischen String *)
- FUNCTION DynChar (str : dynstring; pos : integer) : char;
- var merker : charpointer;
- BEGIN (* Pointer ausrichten: *)
- merker.st := str.st; merker.adr := merker.adr+pos; DynChar := merker.st^;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Mit dieser Funktion kann man ein Zeichen innerhalb eines dyn. Strings *)
- (* ueberschreiben *)
- PROCEDURE AssignChar (var str : dynstring; pos : integer; ch : char);
- var merker : charpointer;
- BEGIN (* Pointer ausrichten: *)
- merker.st := str.st; merker.adr := merker.adr+pos; merker.st^ := ch;
- END;
- (* ----------------------------------------------------------------------- *)
- (* lexikalischer Vergleich dyn. Strings *)
- (* Ergebniswerte: 1 stra > strb, 0 stra = strb, -1 stra < strb *)
- FUNCTION CmpDynString (stra,strb : dynstring) : integer;
- VAR merker, merker2 : charpointer; i, ex : integer;
- BEGIN
- i := 1; merker.st := stra.st; merker2.st := strb.st; ex := -2;
- while (i <= stra.anz) and (ex = -2) do BEGIN
- if i > strb.anz THEN ex := 1 (* stra groesser strb *)
- ELSE if merker.st^ = merker2.st^ THEN
- BEGIN (* naechstes Zeichen positionieren: *)
- merker.adr := succ(merker.adr); merker2.adr := succ(merker2.adr);
- i := succ(i);
- END
- ELSE
- BEGIN
- if merker.st^ < merker2.st^ THEN ex := -1 (* stra kleiner strb *)
- ELSE ex := 1; (* stra groesser strb *)
- END;
- END;
- if ex = -2 THEN
- if stra.anz = strb.anz THEN ex := 0 (* beide gleich *)
- ELSE ex := -1; (* stra kleiner strb *)
- CmpDynString := ex;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Convertierung dynamischer nach Pascal String *)
- PROCEDURE ConvDynString (stra : dynstring; var pascalstr : maxpascalstring);
- Var i, anz : integer; merker : charpointer;
- BEGIN
- merker.st := stra.st; (* Pointer ausrichten *)
- anz := stra.anz; (* Inhalt kopieren *)
- if anz > 255 THEN anz := 255;
- for i := 1 to anz do begin (* kopieren *)
- pascalstr[i] := merker.st^;
- merker.adr := succ(merker.adr);
- END;
- pascalstr[0] := chr(anz); (* Laenge setzen *)
- END;
- (* ----------------------------------------------------------------------- *)
- (* Testprogramm fuer dynamische Strings *)
- var
- a,b,c,d,e : dynstring;
- i : integer;
- p : maxpascalstring;
- BEGIN
- InitDynString(a); InitDynstring(b); InitDynstring(c);
- InitDynstring(d); InitDynString(e);
- DefDynString(a,'Dies ist ein Programm fuer');
- DefDynString(b,'dynamische Strings');
- DefDynString(c,'Test-');
- InsertDynString(c,a,14); ConcatDynString(d,a);
- ConcatDynString(d,b); DefDynString(c,' ');
- InsertDynString(c,d,32); PrintlnDynString(d);
- AssignDynString(e,d); PrintlnDynString(e);
- DeleteDynString(e,18,9); PrintlnDynString(e);
- AssignChar(e,17,' '); PrintlnDynString(e);
- writeln('d groesser e ?',CmpDynString(d,e));
- DefDynString(d,'Aha');
- writeln('d groesser e ?',CmpDynString(d,e));
- AssignDynString(e,d);
- writeln('d groesser e ?',CmpDynString(d,e));
- p := 'Pascalstring'; DefDynSTring(d,p);
- ConvDynString(d,p); writeln(p);
- DefDynString(e,'*');
- for i := 1 to 10 do BEGIN
- ConCatDynString(e,e); PrintDynString(e);
- writeln('==>',Lendynstring(e));
- END;
- CopyDynString(d,e,1000,3); PrintDynString(d);
- writeln('vorhandener Speicherplatz :',MaxAvail);
- ClearDynString(e);
- writeln('vorhandener Speicherplatz :',MaxAvail);
- END.