Array Of Const

0

Siemka.
Ostatnio trochę poczytałem i znalazłem takie coś, jak Array Of Const (Free Pascal).
Wiem, jak to zadeklarować i jak zrobić, aby działało, lecz mam jedno pytanie:
Aby takie coś użyć muszę wywołać z kodu procedurę (np): Wyswietl(['Tekst', 25]);
I tak się zastanawiam, czy nie można by się pozbyć tych kwadratowych nawiasów ([ oraz ]) tak, aby było to tak: Wyswietl(Tekst, 25).
Szukałem, lecz nie znalazłem odpowiedzi, liczę na to, że tutaj dostanę jakąś podpowiedź (chyba, że tak się nie da).

0

Jeżeli Tekst to string to musi być w apostrofach.

1

Odpowiedź brzmi: tak powinno być. To nie jest to samo co parametry ... w językach typu C, mimo że można tego w ten sposób użyć (np. zasymulować printf()).

array of const ma taką przewagę, że funkcja wie ile parametrów otrzymała, i zna ich typy. a ponieważ parametry są zgrupowane w tak naprawdę jeden i to nazwany, przekazanie ich gdzieś dalej jest banalne.

Istnieje coś takiego jak varargs, ale służy do importowania funkcji napisanych w C z zewnętrznych bibliotek. wtedy nie trzeba nawiasów:

function printf(fmt:pchar):longint; varargs; cdecl; external 'msvcrt.dll';

const nl = #13#10; // nowa linia

begin
  printf('ala ma %d %s'+nl, 2, 'koty');
end.

Powyższe można zapisać też z array of const

function printf(fmt:pchar; args:array of const):longint; cdecl; external 'msvcrt.dll';

const nl = #13#10;

begin
  printf('ala ma %d %s'+nl, [2, 'koty']);
end.

Ale funkcje pisane w pascalu muszą używać array of const, a nie varargs.
Poprzednie zdanie jest kłamstwem. Można się bardzo uprzeć:

{$mode objfpc}

procedure wyswietl_inty(ile:integer); cdecl; varargs; external;

procedure wyswietl_inty_args(ile:longint; inty:array of const); cdecl; [alias:'_wyswietl_inty'];
var pargs:plongint;
    i:integer;
begin
  pargs:=@(plongint(@ile)[1]);
  for i:=0 to ile-1 do
    write(pargs[i],' ');
  writeln;
end;

begin
  wyswietl_inty(3, 1,2,3);
end.

ale:
• nie musi to być przenośne między architekturami (przykład działa dla win 32-bit)
• funkcja nie wie ile i jakie parametry otrzymała, więc trzeba to podać w inny sposób (tu: parametr ile i założenie, że będą tylko inty)
• nie ma żadnej kontroli nad tym, czy prawidłowe parametry przekazujemy (można zrobić wyswietl_inty(1, 'dupa') i dostaniemy śmieci)

Z tych powodów funkcje ze zmienną liczbą parametrów w C/C++ nadają się tylko do zastosowań typu printf, gdzie zawsze przekazywany jest string z „formatem” określający ile i jakie parametry są przekazywane.

Za to we Free Pascalu i Delphi przy wykorzystaniu konstrukcji array of const wiemy ile i jakich typów są to parametry — niewielkim kosztem tych dodatkowych nawiasów.

0

dodam tylko, że dowolna ilość, dowolnego typu parametrów w procedurach write i writeln jest wbudowana i nie da się tego przypiąć do własnych procedur/metod (poza sztuczką, którą pokazał Azarien).

0
Azarien napisał(a)

array of const ma taką przewagę, że funkcja wie ile parametrów otrzymała, i zna ich typy. a ponieważ parametry są zgrupowane w tak naprawdę jeden i to nazwany, przekazanie ich gdzieś dalej jest banalne.

Poza tym przypadkiem gdy chcesz przekazać dalej całą tablicę... ;-)

0

kiedyś napisałem funkcję sprintf, używało się jej tak: write(cośtam, ileśtam, ....., sprintf(b));
początek funkcji wyglądał tak:
function sprintf(var b:string):string;
begin
sprintf:='';
......

to co write miało wyświetlić trafiało do przekazywanego przez zmienną stringa.
robiłem sztuczki z chyba textbuf(output), są tam wskaźniki do cyklicznego bufora, można wydłubać co siedzi w buforze po czym go opróżnić.

0

Poza tym przypadkiem gdy chcesz przekazać dalej całą tablicę...

no jak to?

procedure foo(args:array of const);
begin
 ...
end;

procedure bar(args:array of const);
begin
  foo(args);
end;

to co write miało wyświetlić trafiało do przekazywanego przez zmienną stringa.
nowsze wersje Free Pascala mają procedurę writestr:

var s:string;
...
writestr(s,'ala ma ',2,' koty');

robiłem sztuczki z chyba textbuf(output)

bardziej wspieranym sposobem byłoby zdefiniowanie własnej procedury zamiast assign (np. AssignString) która by kojarzyła stringa ze zmienna typu text (text jest rekordem normalnie zawierającym wskaźniki na funkcje I/O do pliku). potem byś korzystał z write/writeln:

var s:string; // string do którego będzie szedł tekst
var st:text;
...
assignstring(st,@s); // zamiast assign, pomijamy co ta funkcja zawiera...
write(st,'ala ma ',2,'koty'); // to idzie do stringa s
close(st);

ale ponieważ mamy writestr, to nie jest to już potrzebne.

0
Azarien napisał(a)

Poza tym przypadkiem gdy chcesz przekazać dalej całą tablicę...

no jak to?

procedure foo(args:array of const);
begin
 ...
end;

procedure bar(args:array of const);
begin
  foo(args);
end;

To było wieki temu kiedy z tym walczyłem, ale chodziło mi wtedy chyba bardziej o budowanie takiej tablicy, żeby przekazać dalej.
Np. w takim celu, żeby w bar() odczytać pierwszy element "args" i w zależności od niego przekazać do foo() albo stałą albo końcowe k elementów z "args".

0
vpiotr napisał(a)

Ale może znasz sposób jak to zrobić - w funkcji bar przesłać "args" do "foo" z jednym parametrem dodatkowym - wewnątrz "args" (było potrzebne do jakiejś tam pochodnej writeln)

{$mode objfpc}

procedure print_args(args:array of const);
var i:integer;
begin
  for i:=low(args) to high(args) do
  case args[i].vtype of
    vtinteger    : writeln('integer : ',args[i].vinteger);
    vtansistring : writeln('string  : "',ansistring(args[i].vansistring),'"');
  end;
end;


procedure insert_int(args:array of const; value:integer; idx:integer);
var len,i:integer;
    args_arr:array of tvarrec;
begin
  len:=length(args);
  setlength(args_arr,len+1);

  for i:=0 to idx-1 do
    args_arr[i]:=args[i];

  args_arr[idx].vtype:=vtinteger;
  args_arr[idx].vinteger:=value;

  for i:=idx to len-1 do
    args_arr[i+1]:=args[i];

  print_args(args_arr);
end;


begin
  insert_int([1,2,'ala ma kota'], 99, 2);
end.
---------- New Program ----------
integer : 1
integer : 2
integer : 99
string  : "ala ma kota"

Output completed (0 sec consumed) - Normal Termination

1 użytkowników online, w tym zalogowanych: 0, gości: 1