PChar


Spis treści

          1 Ogólna informacja o typie danych
          2 Zastosowanie
               2.1 Zastosowanie w bibliotekach DLL
               2.2 Zastosowanie do skracania stringów
               2.3 Przykład dla skracania stringów
          3 Przestroga



Ogólna informacja o typie danych


PChar jest typem danych, tzw. wskaźnikowym. To znaczy w samej zmiennej przechowywany jest tylko adres w pamięci wskazujący na tzw. null-terminated string - ciąg znaków (String) zakończony znakiem #0.

Zastosowanie


Zastosowanie w bibliotekach DLL


Typ PChar używany jest do zastępowania zmiennej typu String tam, gdzie nie można przekazywać zmiennych o zmiennej długości (String jest teoretycznie nieograniczony, więc jego długość, a zatem ilość zajmowanej przez niego pamięci jest dynamicznie dostosowywana do potrzeb), czyli na przykład przy przekazywaniu danych pomiędzy różnymi modułami programu. Przez moduł rozumiem tutaj bibliotekę dll czy główny program.

Można też zauważyć, że wszystkie funkcje WinApi są wywoływane również za pomocą zmiennych typu PChar, gdyż również przekazujemy w ten sposób zmienne do biblioteki DLL, której używa nasza aplikacja za pośrednictwem modułów takich jak Windows.pas, ShellApi.pas itp.

Zastosowanie do skracania stringów


Dodatkowo typ PChar można używać do prostszego skracania zmiennej typu string o określoną ilość znaków. Zauważmy, że jest to tylko adres w pamięci, a koniec tej zmiennej nie jest określony przez długość, a przez wystąpienie zarezerwowanego znaku #0. Dzięki temu wystarczy, że przesuniemy taki wskaźnik w prawo, a "obetniemy" pierwszą część naszego ciągu znaków. Jednocześnie nie musimy troszczyć się o odpowiednią zmianę długości, gdyż koniec dalej jest końcem.

Przykład dla skracania stringów


var
  S: String;
  C: Integer;
begin
  Write('Podaj ciąg znaków: ');
  ReadLn(S);
  Write('Podaj całkowitą liczbę znaków, którą chcesz usunąć z ciągu: ');
  ReadLn(I);
  S:=String( PChar(S) + I );
  WriteLn(S);
end;


Można zauważyć tutaj dwie rzeczy:
1) Można by zastosować zamiast tego funkcję Copy albo Delete. Ta pierwsza jednak wymagałaby wykonania kolejnej funkcji Length (chyba, że znamy długość string'a), zaś ta druga działałaby równie skutecznie tylko w tym przypadku, gdy przypisujemy wynik naszego "ucinania" pod tą samą zmienną. Przy zastosowaniu PChar nie ma takiej konieczności. Dodatkowo zastosowanie funkcji Copy jest mniej czytelne szczególnie, gdy ilość znaków do ucięcia nie jest w prostej zmiennej, tylko wyraża się bardziej rozbudowanym wyrażeniem.

2) Zastosowałem tutaj coś, co mogłoby wyglądać jak dodawanie zmiennej typu Integer (liczba całkowita) do ciągu znaków. Musimy jednak pamiętać, że zmienna PChar jako taka jest liczbą, wskazującą tylko na adres w pamięci. Dodając więc liczbę całkowitą do wskaźnika "przesuwamy" jego wskazanie o żądaną liczbę bajtów, a zatem znaków (gdyż w zmiennej string każdy znak zajmuje 1 bajt). Dzięki temu uzyskujemy ciąg znaków rozpoczynający się od (I+1)-go znaku.

Przestroga


Rozważmy taki przykład:

function foo:PChar;
var
  s:string;
begin
  s := 'Ala ma kota';
  result := PChar(s);
end;


Po wywołaniu powyższej funkcji program za alokuje w pamięci miejsce dla zmiennej s, przypisze jej tekst 'Ala ma kota', po czym zrzutuje ją na PChara i przypisze do wyniku. Niebezpieczeństwo jest takie, że po opuszczeniu funkcji zmienna s jest dealokowana, a wynik dalej pokazuje na miejsce w pamięci gdzie ona była. Jeżeli koniecznością jest zwracanie zmiennej typu PChar można zastosować jedną z poniżej podanych metod:

1.
function foo:PChar;
var
  s:string;
begin
  s:='Ala ma kota';
  result:=NewStr(s);
  // NewStr nie powinno być używane. Jest ono używane tylko dla kompatybilności wstecz
end;


2.
function foo:PChar;
var
  s:string;
begin
  s:='Ala ma kota';
  GetMem(result, Length(s));
end;


Należy jednak pamiętać o zwolnieniu tak zaalokowanej pamięci poprzez funkcje: DisposeStr, lub w drugim przypadku przez FreeMem.
Informacje
Ostatnia modyfikacja 06-01-2006 15:55 Ostatni autor Adam Boduch
Ilość wyświetleń 12649 Wersja 8
Komentarz
manfredek dnia 12-04-2009 23:16
i tyle...
Wolverine dnia 22-12-2005 16:07
NewStr powinno nie powinno być używane. Jest ono używane tylko dla kompatybilności wstecz

Dobre :D
Szczawik dnia 22-12-2005 02:21
A ja się czepię:

samej zmiennej przechowywany jest tylko adres w pamięci wskazujący na tzw. null-terminated string


PChar przechowuje adres wskazujący na Char. Nic więcej. To, że są funkcje pozwalające na obsługę null-terminated string pod tym adresem to sprawa funkcji, ale nie typu PChar. Warto byłoby to zaznaczyć.
Adam.Pilorz dnia 21-12-2005 21:23
Hmm... Faktycznie trochę nienajlepsze sformułowanie. Ale nie mogę wymyślić nic, czym by to zastąpić (w sensie jak by to w słowa ująć ładnie). Niech ktoś podpowie :P
Wolverine dnia 21-12-2005 17:50
Typ PChar używany jest do zastępowania zmiennej typu String tam, gdzie nie można przekazywaćzmiennych o zmiennej długości

Jakos mi to nie tages, to tez "zmienna o zmiennej dlugosci", robi realloca i masz wiekszy/mniejszy ciag, napisalbym raczej cos w stylu, ze to jest taki jakby uniwersalny format przekazywania lancuchow, no bo delphi ma jakas swoja koncepcje na stringi, stl znowu jakas inna itp.
Adam.Pilorz dnia 21-12-2005 17:38
Jak ktoś ma pomysł, co można dodać, to zapraszam do wprowadzania twórczych modyfikacji :]

Katalog
Copyright © 2000-2006 by Coyote Group 0.9.3-pre3
Czas generowania strony: 0.0780 sek. (zapytań SQL: 9)