0

可変数の引数を受け入れる関数を作成することができます。

function f(const x: array of const): String;

そしてそれをこのように使用します:

f([1,3,4, "hello"]);

引数を「変更可能」として定義することもできます。

function g(var x: Byte): String;

var B: Byte;
g(B);

しかし、どのタイプの引数でもいくつでも取り、それらのすべての値を変更できる関数を定義することは可能ですか?ポインターを使用してこれを実行できることはわかっていますが、渡されたパラメーターのタイプがわからないため、ポインターをいじるのは非常に安全ではありません。


1つの型だけでなく、1つの変数だけでなく、さまざまな型の変数の変数を返すことができる関数を作成したいだけです。また、関数を使用するために無数の行を記述したくありません。関数呼び出しなどの前にSetLength()を使用するのではなく、関数自体にする必要があります。これが私がこれまでに作った最高のものです:

type TVarArr = Array of Variant;
     PVarArr = ^TVarArr;
Procedure f(a: PVarArr);
var
 i:Integer;
begin
  SetLength(A^, 4);
  a^[0] := 46;
end;

ar: TVarArr;
begin
f(@ar);
caption := IntToStr(ar[0]);
4

2 に答える 2

2

Tom は Delphi のバージョンが十分に高くないため、この回答を使用することはできませんが、D2010 以降のユーザーなら誰でも、拡張 rtti の TValue をこのタイプの課題で有効に活用できます。

以下は、次の方法を示す小さなコンソール アプリです。

  • 開いている配列パラメーターから TValue の動的配列を作成します。
  • TValue の動的配列を新しい動的配列にコピーし、途中で個々の値を変更します。
  • TValues の動的配列内のアイテムを「その場で」変更します。

楽しみ。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Rtti,
  System.SysUtils,
  System.TypInfo;

const
  StringKinds: set of TTypeKind = [tkChar, tkString, tkWChar, tkLString, tkWString, tkUString];

type
  TValueArray = array of TValue;

function ValueArrayFromConstArray(const aSource: array of TValue): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    Result[idx] := aSource[idx];
end;

function ReturnNewArray(const aSource: TValueArray): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    if aSource[idx].Kind in StringKinds then
      Result[idx] := 'Dest' + aSource[idx].ToString
    else
      if aSource[idx].Kind in [tkInteger] then
        Result[idx] := 10 + aSource[idx].AsInteger
      else
        Result[idx] := aSource[idx];
end;

procedure ModifyArrayValues(var aArray: TValueArray);
var
  idx: Integer;
begin
  for idx := Low(aArray) to High(aArray) do
    if aArray[idx].Kind in StringKinds then
      aArray[idx] := 'Dest' + aArray[idx].ToString
    else
      if aArray[idx].Kind in [tkInteger] then
        aArray[idx] := 10 + aArray[idx].AsInteger
      else
        ;//aArray[idx] := aArray[idx];
end;

var
  Source: TValueArray;
  Destination: TValueArray;
  Item: TValue;
  idx: Integer;
begin
  Source := ValueArrayFromConstArray(['Some', 42, TObject]);
  Destination := ReturnNewArray(Source);
  idx := 0;
  WriteLn('', #9, 'Old', #9, 'New');
  WriteLn('-', #9, '----', #9, '----');
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString, #9, Destination[idx].ToString);
    Inc(idx);
  end;
  WriteLn;
  WriteLn;
  WriteLn('', #9, 'Modified');
  WriteLn('-', #9, '----');
  Source := ValueArrayFromConstArray(['first', 50, TValue.From<TFloatValue>(fvCurrency)]);
  ModifyArrayValues(Source);
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString);
  end;
  ReadLn;
end.
于 2012-11-07T21:11:34.957 に答える
1
Procedure All(var a:Array of Variant);
var
 i:Integer;
begin
  for I := Low(a) to High(a) do
      begin

        if VarType(a[i])=258  then
          a[i] := a[i] + ' modified';

      end;
end;

Procedure AllConst( a:Array of Variant);
var
 i:Integer;
begin
  for I := Low(a) to High(a) do
      begin
        Showmessage(a[i]);
      end;
end;


procedure TForm3.Button1Click(Sender: TObject);
var
 a:Array of Variant;
begin
  AllConst([1,2,'Test']);
  SetLength(a,3);
  a[0] := 3.141;
  a[1] := 'Test';
  a[2] := 27;
  all(a);
  Showmessage(a[1]);
end;
于 2012-11-07T12:59:02.150 に答える