Konwersja String na PAnsiChar lub PChar

dos

Nie wiem czy ten temat był już tu poruszany ale ja szukałem i nic nie znalazłem (jeszcze parę dni temu sam nie wiedziałem jak to zrobić). No więc typ PAnsiChar jest wykorzystywany przez np. procedurke ShellExecute w moduliku ShellApi i jak próbujemy uruchomić plik w formacie String (to taka przenośnia, chyba każdy ją rozumie ;-) ) no to pojawia się błąd kompilatora. Aby to przekonwertować, trzeba trochę pokombinować. Ale, i tutaj cytat wróżki chrzestnej ze Shreka 2:

Wy-star-czy:
:-) (jakby co to piszę z pamięci, jakieś drobrne błędy mogą się zdarzyć!)

zmienna_PAnsiChar_lub_PChar := PChar(zmienna_string);

a jeżeli ktoś lubi kombinować to proszę bardzo:

function StrToPAnsiChar(aStr: String): PAnsiChar;
var buf: array[0..1000] of Char;
    I: Integer;
begin
  for I := 0 to 1000 do 
    buf[I] := #0; { musi być zerowanie bufora, patrz info na dole }
  for I := 0 to Length(aStr) do
    begin
      buf[I] := aStr[I + 1];
      StrToPAnsiChar := buf;
    end;
end;

I co? Działa? Tak. W jaki sposób? Przeanalizujmy to...
Otóż najpierw robimy pętle for od 0 do długości zmiannej dane - 1. Tego chyba nie muszę omawiać. Jak wiecie, zmienna_string[i] jest kompatybilne ze zmienną Char. No więc do tablicy charów przypisujemy pokolei każdy znak łańcucha string, a następnie tą tablicę Char przypisujemy do typu TAnsiChar. I co? Nie ma błędu! Dlaczego? Bo TAnsiChar jest taką tabelą Charów tylko że jest to typ przekonwertowany z WinApi (C, czy tam C++). Pewnie jakby było PAnsiString to by było kompatybilne ze Stringiem... Widzicie jaki prosty sposób!

PS. Kod i sposób ściągnięty z neta, a właściwie to z forum Eksperta, ale opis jest mój własny!!!

Uwaga !!
begin
for i:=0 to 1000 do buf[i]:=#0;

Wszystko ładnie tylko że w przypadku kilkukrotnego wywołania procedury w buf zostaje zapamiętana stara wartość i procedurka robi psikusy. Dopiszcie to po begin i jest wtedy OK. Trzeba zerować bufor.
Pozdrawiam SQ2HCE Mariusz

16 komentarzy

ekm... a dlaczego nie...?

[code]
ac: ansichar;
pc: pansichar;
s: string;

s := ac
pc := @AC[1];

[/code]

Witam

Mam problem. Potrzebuje rozłożyć ciąg np: 'ala ma kota' na dynamiczna tablice char.
W efekcie chciałbym uzyskać tablicę w której każda komórka będzie zawierać poszczególne litery ciągu 'ala ma kota'

Z Góry dzięki.

Ja też się przyczepię: Konwersja String na PAnsiChar lub PChar. Otóż z tego, co wiem, na razie PChar = PAnsiChar (bo Char = AnsiChar). Być może w przyszłych wersjach Char będzie aliasem na typ WideChar, ale póki co Delphi aż tak nie ubóstwia znaków wielobajtowych.

dodam że ten NULL na końcu jest bardzo istotny. Bo np: jeśli chcecie zrobić coś takiego:

lpFileName : PChar;
s : String;

s:='COM1';
lpFileName:=PChar(s);

to niestety ale portu COM nie otworzycie...

Jakoś nie pasi mi ten gotowiec.. więcej żartów niż treści, formatowanie by się jakieś przydało...

length(dane)

, a nie length(dane)-1

 

przeanalizowałem ten kod i to var buf: array[0..lenght(dane)+20] of char; napewno nie może działać... No bo w końcu to dane robi się w trakcie działania programu, a buf przy Create... Wygłupiłem się... Ale nie będę więcej, przygotowuje potężny artykuł

No i napisałem że może nie działać... No i że nie sprawdzałem... Dopiszę do artykułu tego PChara.

var buf: array[0..lenght(dane)+20] of char;

:D łał swietny jestes :D a teraz napisz z tym jakis program

po co w ogole kombinujesz, tak jak napisal Deti PAnsiChar(string) i masz...

function StrToPAnsiChar(dane:string):PAnsiChar;
var buf: array[0..999999] of char;
i : integer;
begin
for i:=0 to lenght(dane)-1 do
begin
buf[i]:=dane[i+1];
StrToPAnsiChar:=buf;
end;
end;

Może być? Albo jeszcze lepiej:

function StrToPAnsiChar(dane:string):PAnsiChar;
var buf: array[0..lenght(dane)+20] of char; //to 20 to dla bezpeczeństwa :-) Nie wiem czy tak można bo nie sprawdzałem, z pamięci pisze
i : integer;
begin
for i:=0 to lenght(dane)-1 do
begin
buf[i]:=dane[i+1];
StrToPAnsiChar:=buf;
end;
end;

a co jesli dane beda mialy wiecej niz 1000 znakow? :)

Ale według mojego sposobu można łatwiej operować na pojedyńczyń znakach łańcucha... :-)

PAnsiChar jest wskaźnikiem na łańcuch, a wystarczy:

PCHAR(string) .. i już mamy zamienione. :)

Sorry, rzeczywiście. Niepotrzebna jest funkcja PAnsiCharToStr. Zaraz to wykasuje.

function PAnsiCharToStr(dane:PAnsiChar):string;
begin
PAnsiCharToStr:=PAnsiChar(dane);
end;

Przeczytaj sam co napisales :D podajesz w parametrze PAnsiChar, rzutujesz to na PAnsiChar i przypisujesz do stringa ...

a string to P(ansi)Chara - P(ansi)Char(jakis_string), jest jeszcze funkcja StrPas, ale jest ona tylko ze wzgledow "kompatybilnosci wstecznej"

Bo TAnsiChar jest taką tabelą Charów tylko że jest to typ przekonwertowany z WinApi (C, czy tam C++).

coz, taka roznica, ze string w 1 bajcie ma zapisana jego dlugosc (aby wiadomo bylo dokad czytac) a PChar na koncu ma bajt o wartosci NULL, czyli 0, lub #0 (jak kto woli :)) Oba sa tablicami charow (bajtow)

A, to wszystko juz gdzies bylo (w faq)

Przyda wam się? Jak tak to piszcie!!! Jestem ciekaw...