Na FreeHostingu Endora běžà desĂtky tisĂc webĹŻ. PĹ™idejte se ještÄ› dnes!
VytvoĹ™it web zdarmaNa FreeHostingu Endora běžà desĂtky tisĂc webĹŻ. PĹ™idejte se ještÄ› dnes!
VytvoĹ™it web zdarmavar s:string; t:string[30];Proměnná s je vnitřně polem [0..255] a proměnná t polem [0..30]
{$V+} type s30 = string[30]; procedure pracuj(var s:s30); begin end; var s:string; t:string[30]; v:string[40]; begin pracuj(s); {ne} pracuj(t); {ano} pracuj(v); {ne} end.Chování překladače závisí na nastavení kompilačních direktiv. Jestliže máme zapnuté přísné hlídání řetězců(neboli {$V+}), tak nám pascal povolí jen
Pracuj(t);var p:pchar; begin p:='Ahoj svete'; writeln(p); end.Jak to, že jsme nemuseli použít proceduru GetMem a alokovat paměť? Inu, protože při přiřazování konstant se pcharový buffer vytvoří v zásobníku. Jestliže ale chceme přiřadit proměnnou, tak si musíme poradit sami.
var p:pchar; c:char; begin p:='Ahoj svete'; c:=p[1];Vidíte? Vidíte to? Ačkoliv nikde nedeklaruju žádné pole, tak sem píšu index pozice. A potom - nikam nepíšu stříšku! Ti co pascal dobře znají si teď možná klepou na čelo a říkají si: "Ten Laaca je ale lemro, to ví přece každý!" Možná, ale je na to potřeba důkladně upozornit, protože se jedná o dosti výraznou inkonzistenci jazyka pascal.
var s:string; p:pchar; c:char; i:integer;| TP | FP1 | FP2 | |
| p:=s; | ne | ne | ne |
| s:=p; | ne | ano* | ano* |
| c:=p[0]; | ano | ano | ano |
| writeln(p); | ano | ano | ano |
| l:=length(p); | ne | ne | ano** |
Procedure Vypis(s:string); var p:char; begin s:=s+#0; p:=@s; inc(p); writeln(p); end;Vše je myslím jasné.
Function StrPcopy(cil:pchar; zdroj:string):pchar - zkopíruje string do pcharu. Je ale na programátorovi, aby si předpřipravil dostatečně velký buffer.StrPas(p:pchar):string - zkopíruje pchar do stringu. Tedy to, co FP dělá sám od sebe.unit pcharobj; interface type PPchar = ^TPChar; TPChar = object p:pchar; {buffer znaku} d:longint; {delka retezce} _dd:longint; {delka alokovaneho bufferu (interni promenna)} Constructor Init; Function VratZnak(n:longint):char; Procedure VlozP(s:pchar;poz:longint); {jako Insert} Procedure VlozS(s:string;poz:longint); { to same } Function Delka:longint; {jako Length} Procedure Vyjmi(poz,l:longint); {j. Delete } Function Dej(poz,l:longint):string; {j. Copy } Destructor Done; end; implementation const TPCHAR_GRANULARITA = 16; {Klicovy prvek objektu. Aby se po pridani kazdeho znaku nemusela prealokovavat pamet, tak se alokuje vzdy minimalne 16 bajtu a dalsi se pridava az podle potreby granularita by mela byt nasobek 16, protoze DOS ma interne prave 16 bajtovou granularitu pameti. Tedy prikaz "GetMem(p,1)" alokuje ve skutecnosti 16 bajtu} {$IFDEF FPC} {$IFDEF VER2} Function PcharDelka(p:pchar):longint; begin PcharDelka:=length(p); end; {$ELSE} Function PcharDelka(p:pchar):longint;assembler; asm xor eax,eax mov esi,p @znova: cmp byte [esi],0 je @konec inc esi inc eax jmp @znova @konec: end; {$ENDIF} {$ELSE} Function PcharDelka(p:pchar):longint;assembler; asm push ds {registry BP,SP,SS,DS,CS musi byt na konci stejne jako na zacatku} xor ax,ax xor dx,dx lds si,p @znova: cmp byte [ds:si],0 je @konec inc si inc ax jmp @znova @konec: pop ds {obnova} end; {$ENDIF} Procedure Realokace(var p:pchar;n1,n2:longint); var q:pointer; w:word; begin {$IFDEF FPC} ReAllocMem(p,n2); {$ELSE} GetMem(q,n2); if n2>n1 then w:=n1 else w:=n2; Move(p^,q^,w); FreeMem(p,n1); p:=q; {$ENDIF} end; Constructor TPChar.Init; begin d:=1; _dd:=TPCHAR_GRANULARITA; GetMem(p,_dd); p[0]:=0; end; Function TPChar.VratZnak(n:longint):char; begin VratZnak:=p[n-1]; end; Function TPChar.Delka:longint; begin Delka:=PcharDelka(p); end; Function TPChar.Dej(poz,l:longint):string; var s:string; begin s[0]:=char(l); move(p[poz-1],s[1],l); Dej:=s; end; Procedure TPChar.VlozP(s:pchar;poz:longint); var t1,t2,np:Pchar; o_dd,n:longint; begin dec(poz); {pozici budu cislovat od 1, tak jako u typu string} n:=PcharDelka(s); if n=0 then Exit; {diskutabilni. snad je to OK} if d+n>_dd then {bude treba provest realokaci pameti} begin inc(d,n); o_dd:=_dd; _dd:=(d div TPCHAR_GRANULARITA+1)*TPCHAR_GRANULARITA; GetMem(np,_dd); {pripravim novy buffer} t1:=np; t2:=p; inc(t1,poz); inc(t2,poz); Move(p^,np^,poz); Move(s^,t1^,n); inc(t1,n); poz:=d-n-poz-1; Move(t2^,t1^,poz); inc(t1,poz); t1^:=#0; {pri kopirovani 0 bajtovych bloku se nezkopiruje zarazka, tak ji doplnim rucne} FreeMem(p,o_dd); p:=np; end else begin {realokace pameti nebude treba} t1:=p; t2:=p; inc(t1,poz); inc(t2,poz+n); Move(t1^,t2^,d-poz); {posun textu vpravo od vlozeneho} Move(s^,t1^,n); {a vlozeni S} inc(d,n); end; end; Procedure TPChar.VlozS(s:string;poz:longint); var t:Pchar; begin s:=s+#0; t:=@s; inc(t); VlozP(t,poz); end; Procedure TPChar.Vyjmi(poz,l:longint); var t1,t2:Pchar; np:longint; begin dec(poz); t1:=p;inc(t1,poz); t2:=p;inc(t2,poz+l); Move(t2^,t1^,d-poz-1); dec(d,l); np:=(d div TPCHAR_GRANULARITA+1)*TPCHAR_GRANULARITA; if np<>_dd then Realokace(p,_dd,np); {P uz ale muze ukazovat jinam (obsah P se muze zmenit)} _dd:=np; end; Destructor TPChar.Done; begin FreeMem(p,_dd); _dd:=0; d:=0; end; end.
uses PCharObj; var s,t:string; p:TPChar; begin s:='Ahoj svete, podivej na moji automatickou realokaci pameti!'; p.init; p.VlozS(s,1); writeln(p.p); writeln(p.dej(1,4)); writeln('Delka zpravy: ',s.d,' znaku.'); readln; p.done; end.