Delphi数组

 

静态数组的定义方法


//1. 标准方法:
var
  MyArr: array[0..10] of Integer;  //定义静态数组

//2. 可以使用非0下标:
var
  MyArr: array[9..10] of Integer;  //不能提倡,这样不容易与系统函数沟通

//3. 根据预定义类型来声明数组:
type
  TMyArr = array[0..10] of Integer;  //先定义一个数组类型
var
  MyArr: TMyArr;  //再定义静态数组

//4. 在非过程区可以直接赋值:
var
  MyArr: array[0..2] of Integer = (11,22,33);

//5. 多维数组:
var
  MyArr: array[0..2, 0..2] of Integer;
begin
  //使用
  MyArr[1,2] := 100;
end;

//6. 根据子界定义数组:
type
  TRange = 0..10;
var
  MyArr: array[TRange] of Integer;

//7. 根据枚举定义数组:
type
  TEnums = (Enum1,Enum2,Enum3);
var
  MyArr: array[TEnums] of string;
begin
  MyArr[Enum1] := '万一';
  ShowMessage(MyArr[Enum1]);  //万一
end;

//8. 根据其他类型定义数组:
var
  MyArr: array[Byte] of Char;
begin
  MyArr[255] := #65;
  ShowMessage(MyArr[255]);  //A
end;

//应尽量不使用内建类型,可以新建类型:
type
  TNewByte = Byte;
var
  MyArr: array[TNewByte] of Char;
begin
  MyArr[255] := #65;
  ShowMessage(MyArr[255]);  //A
end;

//也可以使用类型别名:
type
  TChar = type Char;
var
  MyArr: array[TChar] of Byte;
begin
  MyArr['C'] := 255;
  ShowMessage(IntToStr(MyArr['C']));  //255
end;

//同时定义类型:
type
  MyRec = record
    s: string;
    r: Real;
    b: Byte;
  end;
var
  Arr1: array[0..100] of MyRec;
  Arr2: array[0..100] of record s: string; r: Real; b: Byte; end;  //可以直接这样定义
  Arr3: packed array[0..100] of MyRec;  //压缩数组定义, 好像没有区别?

 

 
动态数组的使用


//例1:
var
  StrArr: array of String;  //动态数组定义时不与维数
begin
  SetLength(StrArr,6);  //分配6个元素位置: 0-5
  StrArr[0] := '万一';  //动态数组的下界是 0
  ShowMessage(StrArr[0]);  //分配空间后和静态数组一样使用
  StrArr := nil;        //一般没必要手动释放, 动态数组离开作用域会自释放
end;

//例2. 动态数组的引用:
var
  Arr1,Arr2: array of Integer;
  a: array[0..1] of Integer;
begin
  SetLength(Arr1,6);
  Arr1[5] := 100;

  Arr2 := Arr1;  //Arr2 引用了 Arr1
  ShowMessage(IntToStr(Arr2[5]));  //100
  ShowMessage(IntToStr(Length(Arr2)));  //当然 Arr2 维数也会是 6

  ShowMessage(IntToStr(SizeOf(Arr1)));  //4, 其实动态数组是个指针
  ShowMessage(IntToStr(SizeOf(Arr2)));  //4

  Arr2[5] := 99;                   //现在它们指向同一个数组, 改变这个就是改变那个
  ShowMessage(IntToStr(Arr1[5]));  //99

  Arr1 := nil;                     //释放其中一个指针, 数组继续存在
  ShowMessage(IntToStr(Arr2[5]));  //99
end;

//例3. 数组 Copy <1>:
var
  Arr1,Arr2: array of Integer;
begin
  SetLength(Arr1,6);
  Arr1[5] := 100;

  Arr2 := Copy(Arr1);  //数组 Copy
  Arr2[5] := 99;  //改变 Arr2 不再影响 Arr1
  ShowMessage(IntToStr(Arr1[5]-Arr2[5]));  //1

  SetLength(Arr1,7);
  ShowMessage(IntToStr(Length(Arr1)));  //7
  ShowMessage(IntToStr(Length(Arr2)));  //6, 没有一点牵扯了
end;

//例4. 数组 Copy <2>:
var
  Arr1,Arr2: array of Integer;
  i: Integer;
begin
  SetLength(Arr1,6);
  for i := Low(Arr1) to High(Arr1) do  //给每个元素赋值
    Arr1[i] := i+1;

  Arr2 := Copy(Arr1,1,3);  //只 Copy 第2..4个元素

  ShowMessage(IntToStr(Arr1[1]));  //2, 现在 Arr2[0] 和 Arr1[1] 的值是一样的
  ShowMessage(IntToStr(Arr2[0]));  //2

  ShowMessage(IntToStr(Length(Arr1)));  //6, 维数肯定不一样了
  ShowMessage(IntToStr(Length(Arr2)));  //3
end;

//例5. 动态多维数组:
var
  Arr: array of array of Integer;  //定义多维数组
begin
  SetLength(Arr,5,5);  //分配空间
  Arr[0,3] := 100;     //赋值
  ShowMessage(IntToStr(Arr[0,3]));  //取值
end;

//例6. 另类建立:
var
  Arr: array of Integer;
begin
  Arr := varArrayCreate([0,3],varInteger);
  ShowMessage(IntToStr(Length(Arr)));  //4

  Arr := VarArrayOf([1,2,3,4]);

  ShowMessage(IntToStr(Arr[0]));  //1
  {这是给变体数组使用的,可能会有效率问题}
end;
 

变体数组


var
  Arr: array[0..3] of Variant;
begin
  Arr[0] := 123;
  Arr[1] := 'wy';
  Arr[2] := True;
  Arr[3] := VarArrayOf([1,'wanyi',1.5]);  //变体数组的元素也可以是变体数组

  ShowMessage(Arr[0]);  //123, 不需要转换
  ShowMessage(Arr[1]);  //wy
  ShowMessage(Arr[2]);  //True
  ShowMessage(Arr[3][1]);  //wanyi
end;
 

数组与枚举


type
  TMyEnum = (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday); {定义枚举}
var
  weekArr: array[TMyEnum] of string; {定义数组}
  myEnum: TMyEnum;                   {定义枚举变量}
begin
  {数组赋值}
  weekArr[Monday]    := '星期一';
  weekArr[Tuesday]   := '星期二';
  weekArr[Wednesday] := '星期三';
  weekArr[Thursday]  := '星期四';
  weekArr[Friday]    := '星期五';
  weekArr[Saturday]  := '星期六';
  weekArr[Sunday]    := '星期天';

  {调用数组}
  ShowMessage(weekArr[Sunday]); {星期天}

  {遍历数组}
  for myEnum := Low(weekArr) to High(weekArr) do
  begin
    ShowMessage(weekArr[myEnum]); {将分别显示: 星期一 ... 星期天}
  end;
end;

 

数组与子界


type
  TABC = 'A'..'G';                {定义子界}
var
  abcArr: array[TABC] of Integer; {定义数组}
  abc: TABC;                      {定义子界变量}
begin
  {数组赋值}
  abcArr['A'] := 11;
  abcArr['B'] := 22;
  abcArr['C'] := 33;
  abcArr['D'] := 44;
  abcArr['E'] := 55;
  abcArr['F'] := 66;
  abcArr['G'] := 77;

  {调用数组}
  ShowMessage(IntToStr(abcArr['G'])); {77}

  {遍历数组}
  for abc := Low(abcArr) to High(abcArr) do
  begin
    ShowMessage(IntToStr(abcArr[abc])); {11 22 33 44 55 66 77}
  end;
end;
 

动态数组的释放


//动态数组一般是不需要手动释放的, 如果需要...
var
  arr: array of Integer;
begin
  {设置动态数组维数}
  SetLength(arr,10);

  {释放方法一}
  arr := nil;

  {释放方法二}
  SetLength(arr, 0);

  {释放方法三}
  Finalize(arr);
end;
 

数组竟然可以这样定义


//这是常规思路:
const
  arr: array[0..1] of Char = ('A','B');
begin
  ShowMessage(arr);                   {AB}
  ShowMessage(IntToStr(Length(arr))); {2}
end;

//没想到可以这样:
const
  arr: array[Boolean] of Char = ('A','B');
begin
  ShowMessage(arr);                   {AB}
  ShowMessage(IntToStr(Length(arr))); {2}

  {访问元素}
  ShowMessage(arr[False]);            {A}
  ShowMessage(arr[True]);             {B}

  {也可以这样访问}
  ShowMessage(arr[Low(arr)]);         {A}
  ShowMessage(arr[High(arr)]);        {B}

  {但不能这样访问}
//  ShowMessage(arr[0]);
//  ShowMessage(arr[1]);

  {但可以变通一下}
  ShowMessage(arr[Boolean(0)]);       {A}
  ShowMessage(arr[Boolean(1)]);       {B}
end;

//同理, 这样也可以:
const
  arr: array[Byte] of Integer = (
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,
    30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,
    56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,
    82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,
    106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
    146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,
    166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,
    186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
    206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,
    226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
    246,247,248,249,250,251,252,253,254,255,256);
begin
  ShowMessage(IntToStr(arr[Low(arr)]));  {1}
  ShowMessage(IntToStr(arr[High(arr)])); {256}
  ShowMessage(IntToStr(Length(arr)));    {256}
end;

//给这种用法来一个必要性的实例:
const
  BoolStr: array[Boolean] of string = ('False', 'True');
var
  b: Boolean;
begin
  b := True;
  ShowMessage(BoolStr[b]); {True}
  b := not b;
  ShowMessage(BoolStr[b]); {False}
end;

#4楼  2008-09-10 18:43 蓝色光芒 [未注册用户]

我来提醒大家 
数组定义时,如果唯数是以枚举开始的话,编译指令是从Low()..High() 
所以带有负数值的枚举用来定义数组常量会出错. 
如: 
Type 
TErrorCode = (ecNOERROR = 0, 
ecDisConnect = -1, 
ecOtherError = -2); 
Const 
ErrorLabels : array [TErrorCode] of String =( 
'无错误' , '断开连接' , '其他错误'); 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
Caption := ErrorLabels[ecOtherError]; 
end; 

Caption得到的是:无错误,那是因为Low(TErrorCode)=ecOtherError 
High(TErrorCode)就是ecNOERROR 

开放数组参数


//给一个整型开放数组求和的函数
function MyFun(const arr: array of Integer): Integer;
var
  i: Integer;
begin
  Result := 0;
  for i in arr do Result := Result + i;
end;

{测试1:}
procedure TForm1.Button1Click(Sender: TObject);
var
  num: Integer;
begin
  num := MyFun([1,2,3]);
  ShowMessage(IntToStr(num)); {6}
end;

{测试2:}
procedure TForm1.Button2Click(Sender: TObject);
var
  iArr: array of Integer;
  i,x: Integer;
begin
  SetLength(iArr, 10);

  for i := Low(iArr) to High(iArr) do
  begin
    iArr[i] := i + 1;
  end;

  x := MyFun(iArr);
  ShowMessage(IntToStr(x)); {55}
end;

关于 array of const

之前应该参考一下: 关于开放数组参数



 


//这是在 System 单元定义的一组标识数据类型的常量:
vtInteger    = 0;
vtBoolean    = 1;
vtChar       = 2;
vtExtended   = 3;
vtString     = 4;
vtPointer    = 5;
vtPChar      = 6;
vtObject     = 7;
vtClass      = 8;
vtWideChar   = 9;
vtPWideChar  = 10;
vtAnsiString = 11;
vtCurrency   = 12;
vtVariant    = 13;
vtInterface  = 14;
vtWideString = 15;
vtInt64      = 16;

//这是定义在 System 单元关于数据类型的一个结构:
TVarRec = record
  case Byte of
    vtInteger:    (VInteger: Integer; VType: Byte);
    vtBoolean:    (VBoolean: Boolean);
    vtChar:       (VChar: Char);
    vtExtended:   (VExtended: PExtended);
    vtString:     (VString: PShortString);
    vtPointer:    (VPointer: Pointer);
    vtPChar:      (VPChar: PChar);
    vtObject:     (VObject: TObject);
    vtClass:      (VClass: TClass);
    vtWideChar:   (VWideChar: WideChar);
    vtPWideChar:  (VPWideChar: PWideChar);
    vtAnsiString: (VAnsiString: Pointer);
    vtCurrency:   (VCurrency: PCurrency);
    vtVariant:    (VVariant: PVariant);
    vtInterface:  (VInterface: Pointer);
    vtWideString: (VWideString: Pointer);
    vtInt64:      (VInt64: PInt64);
end;

作为参数的开放数组, 有时数组的成员类型是不确定的, 此时应该使用 array of const 定义; 详细举例:



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{把不同数据类型返回字符串的函数}
function Fun1(arr: array of const): string;
var
  i: Integer;
begin
  Result := '';
  for i := Low(arr) to High(arr) do
  begin
    case arr[i].VType of
      vtInteger   : Result := Result + IntToStr(arr[i].VInteger)            + ' ';
      vtBoolean   : Result := Result + BoolToStr(arr[i].VBoolean, True)     + ' ';
      vtChar      : Result := Result + arr[i].VChar                         + ' ';
      vtExtended  : Result := Result + FloatToStr(arr[i].VExtended^)        + ' ';
      vtString    : Result := Result + PShortString(arr[i].VString)^        + ' ';
      vtPointer   : Result := Result + IntToStr(Integer(arr[i].VPointer))   + ' ';
      vtPChar     : Result := Result + arr[i].VPChar                        + ' ';
      vtObject    : Result := Result + arr[i].VObject.ClassName             + ' ';
      vtClass     : Result := Result + arr[i].VClass.ClassName              + ' ';
      vtWideChar  : Result := Result + arr[i].VWideChar                     + ' ';
      vtPWideChar : Result := Result + arr[i].VPWideChar                    + ' ';
      vtAnsiString: Result := Result + PAnsiChar(arr[i].VAnsiString)^       + ' ';
      vtCurrency  : Result := Result + CurrToStr(arr[i].VCurrency^)         + ' ';
      vtVariant   : Result := Result + string(arr[i].VVariant^)             + ' ';
      vtInterface : Result := Result + IntToStr(Integer(arr[i].VInterface)) + ' ';
      vtWideString: Result := Result + PWideChar(arr[i].VWideString)        + ' ';
      vtInt64     : Result := Result + IntToStr(arr[i].VInt64^)             + ' ';
    end;
  end;
end;

{简化上一个函数}
function Fun2(const arr: array of const): string;
var
  i: Integer;
const
  n = #32;
begin
  Result := '';
  for i := Low(arr) to High(arr) do with arr[i] do
  begin
    case VType of
      0 : Result := Result + IntToStr(VInteger)            + n;
      1 : Result := Result + BoolToStr(VBoolean, True)     + n;
      2 : Result := Result + VChar                         + n;
      3 : Result := Result + FloatToStr(VExtended^)        + n;
      4 : Result := Result + PShortString(VString)^        + n;
      5 : Result := Result + IntToStr(Integer(VPointer))   + n;
      6 : Result := Result + VPChar                        + n;
      7 : Result := Result + VObject.ClassName             + n;
      8 : Result := Result + VClass.ClassName              + n;
      9 : Result := Result + VWideChar                     + n;
      10: Result := Result + VPWideChar                    + n;
      11: Result := Result + PAnsiChar(VAnsiString)^       + n;
      12: Result := Result + CurrToStr(VCurrency^)         + n;
      13: Result := Result + string(VVariant^)             + n;
      14: Result := Result + IntToStr(Integer(VInterface)) + n;
      15: Result := Result + PWideChar(VWideString)        + n;
      16: Result := Result + IntToStr(VInt64^)             + n;
    end;
  end;
end;

{获取类型名的函数}
function Fun3(const arr: array of const): string;
var
  i: Integer;
const
  n = sLineBreak;
begin
  Result := '';
  for i := Low(arr) to High(arr) do with arr[i] do
  begin
    case VType of
      0 : Result := Result + 'Integer'   + n;
      1 : Result := Result + 'Boolean'   + n;
      2 : Result := Result + 'Char'      + n;
      3 : Result := Result + 'Extended'  + n;
      4 : Result := Result + 'String'    + n;
      5 : Result := Result + 'Pointer'   + n;
      6 : Result := Result + 'PChar'     + n;
      7 : Result := Result + 'Object'    + n;
      8 : Result := Result + 'Class'     + n;
      9 : Result := Result + 'WideChar'  + n;
      10: Result := Result + 'PWideChar' + n;
      11: Result := Result + 'AnsiString'+ n;
      12: Result := Result + 'Currency'  + n;
      13: Result := Result + 'Variant'   + n;
      14: Result := Result + 'Interface' + n;
      15: Result := Result + 'WideString'+ n;
      16: Result := Result + 'Int64'     + n;
    end;
  end;
end;

{测试}
procedure TForm1.Button1Click(Sender: TObject);
var
  a: Integer;
  b: Boolean;
  c: Char;
  d: Extended;
  e: ShortString;
  f: Pointer;
  g: PChar;
  h: TButton;
  i: TClass;
  j: WideChar;
  k: PWideChar;
  l: AnsiString;
  m: Currency;
  n: Variant;
  o: IInterface;
  p: WideString;
  q: Int64;
begin
  a := 1;
  b := True;
  c := 'a';
  d := 2;
  e := 'S';
  f := Pointer(3);
  g := 'P';
  h := TButton(Sender);
  i := TForm;
  j := #19975;
  k := '一';
  l := 'A';
  m := 4;
  n := 5;
  //o;
  p := '万一';
  q := 7;

  ShowMessage(Fun1([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
  ShowMessage(Fun2([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
  {结果如下:}
  {1 True a 2 S 3 P TButton TForm 万 一 A 4 5 0 万一 7 }

  ShowMessage(Fun3([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
  {结果如下:
    Integer
    Boolean
    Char
    Extended
    String
    Pointer
    PChar
    Object
    Class
    WideChar
    PWideChar
    AnsiString
    Currency
    Variant
    Interface
    WideString
    Int64
  }
end;

{我试试没有在 TVarRec 中的类型是怎么归类的}
procedure TForm1.Button2Click(Sender: TObject);
var
  a: Byte;
  b: Word;
  c: Cardinal;
  d: Double;
  e: Real;
  f: TStrings;
begin
  ShowMessage(Fun3([a,b,c,d,e,f]));
  {结果如下:
    Integer
    Integer
    Integer
    Extended
    Extended
    Object
  }
end;

end.

从这个例子中还能得到的启示是(根据网友的提示, 下面可能理解错了!):



//不超过 4 字节的简单类型, 在内存中只有一个存放处.
Integer;
Boolean;
Char;
WideChar;

//超过 4 字节的类型(包括字符串), 在内存中有两个存放处: 一个是指针位置; 一个是数据位置.
Int64;         //俺在D7中内存就一个数据位置

Extended;
Currency;
Variant;
ShortString;
AnsiString;
WideString;

//指针: 只有 4 字节大小.
Pointer;
PChar(PAnsiChar);
PWideChar;

//对象: 复杂了...
Object
Class;
IInterface;

 

判断一个数组的长度用 Length 还是 SizeOf ?

最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适!

如果是一维数组、且元素大小是一个字节, 这样用看不出错误, 譬如:



var
  arr1: array[0..9] of Char;
  arr2: array[0..9] of Byte;
begin
  ShowMessageFmt('%d,%d,%d,%d',[Length(arr1), SizeOf(arr1),
                                Length(arr2), SizeOf(arr2)]);
  {显示结果: 10,10,10,10}
end;

但如果数组元素多于一个字节、或是多维数组的情况下, 就不行了, 举例:



const
  arr1: array[0..9] of Integer = (1,2,3,4,5,6,7,8,9,10);
  arr2: array[0..1, 0..3] of Integer = ((1,2,3,4), (5,6,7,8));
var
  arr3: array[Boolean] of Integer;
  arr4: array[Byte] of Integer;
begin
  ShowMessage(IntToStr(Length(arr1)));    {10}
  ShowMessage(IntToStr(SizeOf(arr1)));    {40}

  ShowMessage(IntToStr(Length(arr2)));    {2}
  ShowMessage(IntToStr(Length(arr2[0]))); {4}
  ShowMessage(IntToStr(Length(arr2[1]))); {4}
  ShowMessage(IntToStr(SizeOf(arr2)));    {32}

  ShowMessage(IntToStr(Length(arr3)));    {2}
  ShowMessage(IntToStr(SizeOf(arr3)));    {8}

  ShowMessage(IntToStr(Length(arr4)));    {256}
  ShowMessage(IntToStr(SizeOf(arr4)));    {1024}
end;

我们倒是可以利用这个原理, 迅速知道多维数组的元素总数:



const
  arr: array[0..1, 0..2, 0..3] of Integer =
    (((1,1,1,1), (2,2,2,2), (3,3,3,3)), ((4,4,4,4), (5,5,5,5), (6,6,6,6)));
begin
  ShowMessage(IntToStr(SizeOf(arr) div SizeOf(Integer))); {24}
end;
 

如何把字符串覆给数组



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{把字符串给静态(字符)数组}
procedure TForm1.Button1Click(Sender: TObject);
const
  str = '万一的 Delphi 博客';
var
  StaticArr: array[0..255] of Char;
begin
  {直接赋值即可}
  StaticArr := str;

  {显示}
  ShowMessage(StaticArr); {万一的 Delphi 博客}
end;

{把字符串给动态(字符)数组}
procedure TForm1.Button2Click(Sender: TObject);
const
  str = '万一的 Delphi 博客';
var
  DynamicArr: array of Char;
  i: Integer;
begin
  {设置动态数组大小}
  SetLength(DynamicArr, Length(str));

  {把字符串赋给动态数组}
  for i := 0 to Length(DynamicArr) - 1 do
    DynamicArr[i] := str[i+1];

  {显示动态数组中的字符}
  ShowMessage(PChar(@DynamicArr[0])); {万一的 Delphi 博客}
end;

{数组元素可不一定都是字符}
procedure TForm1.Button3Click(Sender: TObject);
const
  str = '万一的 Delphi 博客';
var
  DynamicArr: array of string;
begin
  SetLength(DynamicArr, 1);
  DynamicArr[0] := str;
  ShowMessage(DynamicArr[0]); {万一的 Delphi 博客}
end;

end.
 

多维动态数组与多维动态数组指针



本例效果图:



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Align := alLeft;
end;

{多维动态数组}
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: array of array of array of Integer; {定义一个三维动态数组}
  i,j,k,ic,jc,kc: Integer;
begin
  {设置数组}
  SetLength(Arr, 2,3,4);

  {获取各维的维数}
  ic := Length(Arr);
  jc := Length(Arr[0]);
  kc := Length(Arr[0][0]);

  {赋值}
  for i := 0 to ic - 1 do
    for j := 0 to jc - 1 do
      for k := 0 to kc - 1 do
        Arr[i][j][k] := Random(100);

  {取值}
  Memo1.Clear;
  for i := 0 to ic - 1 do
    for j := 0 to jc - 1 do
      for k := 0 to kc - 1 do
        Memo1.Lines.Add(Format('Arr[%d][%d][%d] = %d', [i, j, k, Arr[i][j][k]]));
end;

{多维动态数组指针}
procedure TForm1.Button2Click(Sender: TObject);
Type
  TMyArr = array of array of array of Integer; {定义一个三维动态数组类型}
var
  PArr: ^TMyArr; {动态数组指针变量}
  i,j,k,ic,jc,kc: Integer;
begin
  {用作维数的变量}
  ic := 2;
  jc := 3;
  kc := 4;

  {分配内存; 按说动态数组还需要 8 个管理字节, 我不知道 Delphi 是怎么协调的}
  GetMem(PArr, ic * jc * kc * SizeOf(Integer));

  {设置数组}
  SetLength(PArr^, ic,jc,kc);

  {赋值}
  for i := 0 to ic - 1 do
    for j := 0 to jc - 1 do
      for k := 0 to kc - 1 do
        PArr^[i][j][k] := Random(100);

  {取值}
  Memo1.Clear;
  for i := 0 to ic - 1 do
    for j := 0 to jc - 1 do
      for k := 0 to kc - 1 do
        Memo1.Lines.Add(Format('Arr[%d][%d][%d] = %d', [i, j, k, PArr^[i][j][k]]));

  {自己分配的内存要负责释放}
  FreeMem(PArr);
end;

end.

数组类型与数组指针的巧妙利用



本例通过存取结构, 慢慢引入了数组类型与指针的一些使用方法; 其中六个小例子的测试内容和结果都是一样的.



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type {先定义结构和结构指针}
  PMyRec = ^TMyRec;
  TMyRec = record
    F1: Char;
    F2: Word;
  end;

{用静态数组储存或读写结构很方便}
procedure TForm1.Button1Click(Sender: TObject);
var
  ArrRec: array[0..2] of TMyRec;
  i: Integer;
begin
  {写入}
  for i := 0 to 2 do
  begin
    ArrRec[i].F1 := Chr(i+65);
    ArrRec[i].F2 := (i+1) * 10;
  end;

  {读取}
  for i := 0 to Length(ArrRec) - 1 do
    ShowMessageFmt('%s, %d', [ArrRec[i].F1, ArrRec[i].F2]);
end;

{这个只是定义了一块内存, 没用数组的概念, 有点麻烦}
procedure TForm1.Button2Click(Sender: TObject);
var
  buf: PMyRec;
begin
  GetMem(buf, SizeOf(TMyRec) * 3); {申请内存}

  {写入}
  buf^.F1 := 'A';
  buf^.F2  := 10;
  Inc(buf);       {到下一个}
  buf^.F1 := 'B';
  buf^.F2  := 20;
  Inc(buf);
  buf^.F1 := 'C';
  buf^.F2  := 30;

  Dec(buf, 2);    {回到开始}

  {读取}
  ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]);
  Inc(buf);       {到下一个}
  ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]);
  Inc(buf);
  ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]);

  Dec(buf, 2);    {回到开始}
  FreeMem(buf);   {释放内存}
end;

{可以给结构定义一个数组类型}
procedure TForm1.Button3Click(Sender: TObject);
type
  TArr = array of TMyRec;
var
  buf: PMyRec;
  i: Integer;
begin
  GetMem(buf, SizeOf(TMyRec) * 3);

  for i := 0 to 2 do
  begin
    TArr(buf)[i].F1 := Chr(i+65);
    TArr(buf)[i].F2 := (i+1) * 10;
  end;

  for i := 0 to 2 do
    ShowMessageFmt('%s, %d', [TArr(buf)[i].F1, TArr(buf)[i].F2]);

  FreeMem(buf);
end;

{直接用动态数组也行}
procedure TForm1.Button4Click(Sender: TObject);
var
  Arr: array of TMyRec;
  i: Integer;
begin
  SetLength(Arr, 3);
  for i := 0 to 2 do
  begin
    Arr[i].F1 := Chr(i+65);
    Arr[i].F2 := (i+1) * 10;
  end;

  for i := 0 to 2 do
    ShowMessageFmt('%s, %d', [Arr[i].F1, Arr[i].F2]);
end;

{使用一个元素的数组指针, 这是很常用的}
procedure TForm1.Button5Click(Sender: TObject);
type
  PArr = ^TArr;
  TArr = array[0..0] of TMyRec;
var
  buf: PArr;
  i: Integer;
begin
  GetMem(buf, SizeOf(TMyRec) * 3);

  for i := 0 to 2 do
  begin
    buf^[i].F1 := Chr(i+65);
    buf^[i].F2 := (i+1) * 10;
  end;

  {用这种方法不能像下面这样读写, 也就是 [] 中不能是超过 0 的常数, 但可以用变量}
  {这也容易理解, 因为常量会直接编译到代码中, 在没有分配内存以前, 编译器不知道数组会更大}
  {要解决这个问题需要用下一个方法}
//  buf[0].F1 := 'A';
//  buf[0].F2 := 10;
//  buf[1].F1 := 'B';
//  buf[1].F2 := 20;
//  buf[2].F1 := 'C';
//  buf[2].F2 := 30;

  for i := 0 to 2 do
    ShowMessageFmt('%s, %d', [buf[i].F1, buf[i].F2]);

  FreeMem(buf);
end;

{使用一个超大的数组指针, Delphi 的 TList 类就是这么干的}
procedure TForm1.Button6Click(Sender: TObject);
type
  PArr = ^TArr;
  TArr = array[0..100000] of TMyRec; {不要担心内存暴涨, 使用时我们只用其指针}
var
  buf: PArr;
  i: Integer;
begin
  GetMem(buf, SizeOf(TMyRec) * 3);

  for i := 0 to 2 do
  begin
    buf^[i].F1 := Chr(i+65);
    buf^[i].F2 := (i+1) * 10;
  end;

  {和上例不同的是, 下面的代码也可以}
//  buf[0].F1 := 'A';
//  buf[0].F2 := 10;
//  buf[1].F1 := 'B';
//  buf[1].F2 := 20;
//  buf[2].F1 := 'C';
//  buf[2].F2 := 30;

  for i := 0 to 2 do
    ShowMessageFmt('%s, %d', [buf[i].F1, buf[i].F2]);

  FreeMem(buf);
end;

end.

复制动态数组


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TArr = array of Int64; {先把需要的动态数组数组定义成一个类型, 因为下面需要类型转换}
var
  arr1,arr2: TArr;       {两个等待测试的数组变量}
  p: Pointer;            {该指针用于中转数组中的数据}

{先给第一个数组赋测试值}
procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 1000 - 1 do
  begin
    SetLength(arr1, Length(arr1)+1);
    arr1[High(arr1)] := i * 2;
  end;
  {抽查显示}
  ShowMessage(IntToStr(arr1[9])); {18}
end;

{复制到第二个数组}
procedure TForm1.Button1Click(Sender: TObject);
var
  size: Cardinal;
begin
  size := Length(arr1) * SizeOf(arr1[0]); {源数组大小}
  GetMem(p, size);                        {根据源数组大小分配内存}
  CopyMemory(p, arr1, size);              {复制}
  arr2 := TArr(p);                        {转换}
  {抽查显示}
  ShowMessage(IntToStr(arr2[9]));         {18}
end;

end.

假定数组元素是个结构, 再测试一次:



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TRec = record
    str: string;
    int: Integer;
  end;

  TArr = array of TRec;

var
  arr1,arr2: TArr;
  p: Pointer;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 1000 - 1 do
  begin
    SetLength(arr1, Length(arr1)+1);
    arr1[High(arr1)].str := IntToStr(i);
    arr1[High(arr1)].int := i * 2;
  end;
  ShowMessageFmt('%s,%d',[arr1[9].str, arr1[9].int]); {9,18}
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  size: Cardinal;
begin
  size := Length(arr1) * SizeOf(arr1[0]);
  GetMem(p, size);
  CopyMemory(p, arr1, size);
  arr2 := TArr(p);
  ShowMessageFmt('%s,%d',[arr2[9].str, arr2[9].int]); {9,18}
end;

end.

 

时间: 2024-11-02 02:43:49

Delphi数组的相关文章

Delphi数组初始化

Delphi下如何对数组进行初始化? 答: 1.Delphi提供对常量数组的简单初始化方法如下: const arrByte: Array[0..2] of byte =(112,32,55); 2.如果想对变量数组进行初始化,可以先声明常量数组,然后,对变量数组进行赋值即可: procedure AssignArr; var   arrMyByte: Array[0..2] of byte; begin     //方法一     Move(arrByte, arrMyByte, SizeOf

Delphi数组复制

const    AA : arrary[0..4] of byte =(0,1,2,3,4) var   BB : arrary[0..4] of byte; begin   BB := AA ;   {这样是错误的}   Move(AA,BB,sizeof(BB));  {正确的} end;

Delphi中数组赋值

曾经想过, Delphi 要能这样给数组赋值就好了: arr := [...]; VarArrayOf 可不是新东西, 不过之前还没习惯用它. var bs: TBytes; //  bs: TArray<Byte>begin//  SetLength(bs, 3); bs := VarArrayOf([11, 22, 33]); ShowMessage(IntToStr(bs[2])); //33end; var strArr: TArray<string> begin//  S

C# 调用DELPHI 结构体指针数组出现的乱码

问题描述 delphi:TAirc=recordID:array[0..64]ofChar;MC:array[0..128]ofChar;LMAC:Single;XMAC:Single;WTNOL:Single;WTMAX:Single;WTMIN:Single;stdFWD:Single;stdAFT:Single;stdLFT:Single;stdRIT:Single;end;PAirc=^TArrAirc;functionGetAirc(varS:PAirc;aPath:PChar):In

降噪-Delphi 2007中如何将数组中的值以音频形式播放出来

问题描述 Delphi 2007中如何将数组中的值以音频形式播放出来 我的程序中首先将两个wav文件分别读入两个数组,然后进行了降噪算法,最后输出为e,e是一个元素个数为二百多万的real型动态数组,我现在想将其以声音形式播放出来,请问需要怎样做?waveout可以实现吗? 多谢各位大神 解决方案 使用Beep函数,它可以自定义频率和时间http://www.feiesoft.com/api/Beep.html

delphi创建的动态库中二维数组作为形参

问题描述 使用delphi创建的动态库,动态库中的函数使用二维数组作为形参,二维数组怎么定义呢?放在哪里定义啊?在application中,我会用的.typeArrayType=array[0..2]ofInteger;functionTForm1.udefun(varhehe:arrayofMyArray):integer;beginend;调用udefun函数时,定义varhehe:arrayofMyArray;就可以了.但动态库中,ArrayType=array[0..2]ofIntege

Delphi中把Integer数组保存到文件并读取

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Se

在Delphi中巧改窗体文件实现控件数组

delphi 开发的应用中,每一个窗体都有一个对应的窗体文件(.dfm),用来记录该窗体的属性以及窗体上所有控件的属性,以便在窗体关闭后能准确地重新生成窗体.几乎所有的DELPHI参考书都没有提到过该文件的具体情况,偶尔提到,也都泛泛而谈,因为窗体文件是二进制文件,只有在DELPHI提供的编辑环境中才能看到它的本来面目,对其进行操作可能会出现不可预知的错误:而且在大多数情况下,确实没有修改的必要.而本文谈到的和窗体文件密切相关. 要利用窗体文件,首先必须了解该类型文件的结构.窗体文件的结构很简单

Delphi中记录数组存出到文件和从文件导入

Type TRecord = Record Name: String[10]; address: String[50]; End; TRecordFile = File Of TRecord; Var Form1: TForm1; aRecordFile: TRecordFile; aRecordFileName: String = 'c:\PersonS.dat'; Implementation{$R *.dfm} Function RecordsSaveToFile(aFileName: S