Řetězce

Zatím jsme používali řetězce jen na komentování výsledků v příkazech Writeln. Řetězce, tedy pole znaků, mohou ale sloužit k lecčemu a některé z úloh formulovaných zcela přirozeně pro řetězce jsou, nahlíženo okem informatiků, docela složité. Jako rekreaci doporučuji si prohlédnout třeba nějakou literaturu k hledání nejdelšího společného podřetězce dvou řetězců, úlohu, která může být docela užtečná třeba u analýzy DNA. Právě pro rozsáhlost problému budeme řetězce studovat jen velmi utilitárně a vyhneme se mnoha detailům a problémům.

Řetězcové konstanty

Již víme vše o znacích a řetězce jsou speciální pole znaků. Protože by bylo nepříjemné psát něco jako
('A','h','o','j',' ','l','i','d','i','!')
lze v Pascalu zapisovat řetězcové konstanty takto 'Ahoj lidi!'.

Writeln('''Apostrof uvnitr retezce  ('') se pise jako dva ('''')''');

Vypíše: 'Apostrof uvnitr retezce (') se pise jako dva ('')'

Typ String

Naneštěstí přes všechnu snahu o pravidelnost v Pacsalu se ukázalo, že užitečné věci jsou nepravidelné. Příkladem jsou třeba řetězce. Jde o složitý problém. Již jsme viděli, že kvůli spolupráci s OS mají speciální význam pole znaků se spodní mezí intervalu indexů 0. Z historických důvodů je jazyce Object Pascal připraveno několik variant řetězcových typů. Povíme jen něco málo o typu string.

var s,t : string;
    i,j : integer;

begin
  s := 'ABCD1234'; {Přiřazení konstanty do řetězce}
  t := s;            {Přiřazení hodnoty  s do t}
  Writeln(t);        {Vypíše 'ABCD1234'}

  t := copy(s,2,3);  {Přiřazení výsledku funkce do proměnné, kus počínaje druhým dlouhý tři}
  t[1] := 'B';
  Writeln(t);        {Vypíše 'BCD'}

  Delete(s,1,4);     {Vypustí 'ABCD'}
  Writeln(s);        {Vypíše '1234'}

  t := '..'+s;     {Složení řetězce z kousků}
  Writeln(t);        {Vypíše '..1234'}

  Insert('xx',t,2);
  Writeln(t);        {Vypíše '.xx.1234'}

  Writeln('Retezec '''+t+''' ma delku ',Length(t)); {délka řetězce ve znacích}
  Writeln('Podretezec ''23'' se nachazi na indexu ',
           Pos('23',t),  {nalezení polohy podřetězce jinak 0}
           ' retezce '+t);

  Setlength(t,20);
  t[20]:='6';
  Writeln(t);        {Vypíše '.xx.1234           6' ale ty mezery nejsou mezery, jak uvidíme:}
  for i:=1 to length(t) do
         Write('#',ord(t[i]));
                     {Vypíše '#46#120#120#46#49#50#51#52#0#0#0#0#0#0#0#0#0#0#0#54'); }

  str(Pi:20:10,s);  {Nacpi Pi do retezce}
  Writeln(#10#10#10#10+s); {čtyři novéřádky a Pi}
  val(copy(s,11,10),i,j);  {převeď řetězec na číslo}
  Writeln(i);     {Vypíše 1415926536}
  Readln;
end.

Ještě máme po ruce další spoustu procedur a funkcí např. UpperCase

Velmi důležitá je někdy funkce

procedure Val(S; var V; var Code: Integer)

která umí do celočíselné nebo reálné proměnné V dosadit hodnotu zapsanou v řetězci. Code je 0 pokud nenastanou problémy, jinak je to index problematického znaku v řetězci.
Interně je typ string podobný poli znaků s otevřeným koncem, první znak řetězce (pokud má délku >0) se ale nachází na indexu 1. Proto SetLength(Retezec,Delka) znamena výjimečně, že použití Retezec[Delka] je OK.

Proceduru SetLength(Retezec,Delka) použijeme především tehdy, pokud chceme pomocí indexů pracovat s jednotlivými znaky řetězce (buď vědomě za jeho aktuální délkou, nebo ji jednoduše nezáme). V rámci přiřazovacího příkazu a při volání systémových funkcí pracujících s řetězci tuto funkci folat smozřejmě nemusíme.

Ve výjimečných případech se může hodit vědět, že řetězec s neproměnnou délkou se deklaruje jako

type tJmenaReckychPismen = string [10]; //zadne neni delsi

Jde ale o přežitek z minulosti, třeba jen tím, že v hranatých závorkách smíme uvést jen číslo do 255.