如何简化下面的代码 ( 积分: 55 )

  • 主题发起人 主题发起人 catcatdogdog
  • 开始时间 开始时间
C

catcatdogdog

Unregistered / Unconfirmed
GUEST, unregistred user!
const
Array0: Array[0..2] of String = ('aaa', 'bbb', 'ppp');
Array1: Array[0..5] of String = ('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll');
Array2: Array[0..3] of String = ('aer', 'rty', 'uuu', 'ooo');
......
var
ID: Integer;
i: Integer;

...
case ID of
0:
for i := 0 to Length(Array0) - 1 do
ShowMessage(Array0);
1:
for i := 0 to Length(Array1) - 1 do
ShowMessage(Array1);
2:
for i := 0 to Length(Array2) - 1 do
ShowMessage(Array2);
end;
意思是说,数组常量Array0..ArrayN的名称是和ID对应的,对不同的ID,取不同的数组常量进行相关操作。
有没有一种方法,只用写一个通用的语句,就能实现上述case中的操作,也就是
for i := 0 to Length(Array[red]ID[/red]) - 1 do ...
的效果?
我想过用一个指针数组存储各数组常量地址,如果各数组常量长度相同,倒可以用下面的方法
type
TStrArray = Array[0..2] of String;
const
PArray: Array[0..N] of Pointer

...
for i := 0 to Length(TStrArray(PArray[ID])) - 1 do ...
但现在长度不同,也就不能这样用了。不知有没有其它方法?
 
const
Array0: Array[0..2] of String = ('aaa', 'bbb', 'ppp');
Array1: Array[0..5] of String = ('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll');
Array2: Array[0..3] of String = ('aer', 'rty', 'uuu', 'ooo');
......
var
ID: Integer;
i: Integer;

...
case ID of
0:
for i := 0 to Length(Array0) - 1 do
ShowMessage(Array0);
1:
for i := 0 to Length(Array1) - 1 do
ShowMessage(Array1);
2:
for i := 0 to Length(Array2) - 1 do
ShowMessage(Array2);
end;
意思是说,数组常量Array0..ArrayN的名称是和ID对应的,对不同的ID,取不同的数组常量进行相关操作。
有没有一种方法,只用写一个通用的语句,就能实现上述case中的操作,也就是
for i := 0 to Length(Array[red]ID[/red]) - 1 do ...
的效果?
我想过用一个指针数组存储各数组常量地址,如果各数组常量长度相同,倒可以用下面的方法
type
TStrArray = Array[0..2] of String;
const
PArray: Array[0..N] of Pointer

...
for i := 0 to Length(TStrArray(PArray[ID])) - 1 do ...
但现在长度不同,也就不能这样用了。不知有没有其它方法?
 
const
caStr: array [0..2, 0..5] of string = (('aaa', 'bbb', 'ppp', '', '', ''),
('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll'),
('aer', 'rty', 'uuu', 'ooo', '', ''));
 
to anewed:
这样的话就得不到每个数组的[red]实际[/red]长度了啊。
 
好象是不行呀!我在做动态生成控件的时候也遇上过类似的问题,好象没解决!
 
如果是控件的话,倒可以用
function FindComponent(const AName: string): TComponent;
其实也是存在一个数组中,名称好得到,
关键是控件类型(类似于此处的常量类型)不能自动得到啊。
 
找了个笨办法解决:
type
TStrArray = Array of String;
const
Array0: Array[0..2] of String = ('aaa', 'bbb', 'ppp');
Array1: Array[0..5] of String = ('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll');
Array2: Array[0..3] of String = ('aer', 'rty', 'uuu', 'ooo');
另外定义一堆数组变量:
var
Arr0, Arr1, Arr2: TStrArray;
ArrP: Array of Pointer;
begin
SetLength(Arr0, Length(Array0);
Move(Array0[0], Arr0[0], SizeOf(Array0));
SetLength...
ArrP[0] := @Arr0;
ArrP[1] := @Arr1;
...

for i := 0 to Length(TStrArray(ArrP[ID]^)) - 1 do
ShowMessage(TStrArray(ArrP[ID]^));
end;
这样操作部分是一次解决了,但前面又多了赋值部分,Sigh!
 
Length函数是用来得到字符串长度的。
简化代码可以这个样子:

var
ID: Integer;
i: Integer;
ta: array of String;
...
case ID of
0: ta := Array0;
1: ta := Array1;
2: ta := Array2;
else
end;
for i := Low(ta) to High(ta) do
ShowMessage(ta);
 
to 暗月:
静态数组不能直接赋给动态数组吧,会报错:
Incompatible types: 'Array' and 'dynamic array'
 
实在不行,用指针不就可以了?
 
用Tstringlist数组应该可以解决这个问题。

 
type
PTStrArray =^TStrArray;
TStrArray = Array of String;

const
Array0: Array[0..2] of String = ('aaa', 'bbb', 'ppp');
Array1: Array[0..5] of String = ('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll');
Array2: Array[0..3] of String = ('aer', 'rty', 'uuu', 'ooo');
var
p:PTStrArray;
ID: Integer;
i: Integer;
begin
ID:=strtoint(edit1.text);
// New(p);
case ID of
0: p := @Array0;
1: p := @Array1;
2: p := @Array2;
else
end;
for i := Low(p^) to High(p^) do
ShowMessage(p^);
// FreeMem(p);
end;
为什么我这样子写报错啊?指针该怎么用?
 
catcatdogdog的“笨”方法好象是唯一的方法,但TStrArray(ArrP[ID]^)的用法不对,因为数组本身就是指针:)
赋值可以放在TForm1.FormCreate里,已运行通过的示例如下:
unit Unit1;

interface

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

type
TStrArray = Array of String;

TForm1 = class(TForm)
RzButton1: TButton;
RzEdit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Array0: Array[0..2] of String;
Array1: Array[0..5] of String;
Array2: Array[0..3] of String;
ID: Integer;
i: Integer;
ArrayLength: integer;
ArrayStart: pointer;
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
ID := strtoint(Edit1.Text);
case ID of
0:
begin
ArrayStart := @Array0;
ArrayLength := Length(Array0);
end;
1:
begin
ArrayStart := @Array1;
ArrayLength := Length(Array1);
end;
2:
begin
ArrayStart := @Array2;
ArrayLength := Length(Array2);
end;
end;
for i := 0 to ArrayLength - 1 do
ShowMessage(TStrArray(ArrayStart));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Array0[0] := 'aaa';
Array0[1] := 'bbb';
Array0[2] := 'ppp';

Array1[0] := 'qqq';
Array1[1] := 'eew';
Array1[2] := 'ddd';
Array1[3] := 'nnn';
Array1[4] := 'ete';
Array1[5] := 'lll';

Array2[0] := 'aer';
Array2[1] := 'rty';
Array2[2] := 'uuu';
Array2[3] := 'ooo';
end;

end.
 
谢谢大家的关注,做几点说明:

TStrArray(ArrP[ID]^) 是没问题的
ArrP 是一个指针数组
ArrP[ID] 是指向一个字符串数组的指针
ArrP[ID]^ 是这个指针指向的地址
TStrArray(ArrP[0]^) 是把这个地址的内容作为 TStrArray 类型来用
这种方法在 ListView 的 data 属性中常用到

至于给动态数组一次性赋值
SetLength(Arr0, Length(Array0);
Move(Array0[0], Arr0[0], SizeOf(Array0));
是我目前见过的最快的方法
在大富翁以前的帖子中也有过讨论

to wrl_001:
是不是应该把 p 定义成 pointer类型?
在你的 case 赋值语句中左右两边类型好像不一样了
 
最终解决方案:
const
Array0: Array[0..2] of String = ('aaa', 'bbb', 'ppp');
Array1: Array[0..5] of String = ('qqq', 'eew', 'ddd', 'nnn', 'ete', 'lll');
Array2: Array[0..3] of String = ('aer', 'rty', 'uuu', 'ooo');
ArrayP: Array[0..2] of Pointer = (@Array0, @Array1, @Array2);
ArrayL: Array[0..2] of Integer = (3, 6, 4);

procedure DisplayMessage(ID: Integer);
var
ps: ^String;
i: Integer;
begin
ps := ArrayP[ID];
for i := 0 to ArrayL[ID] - 1 do
begin
ShowMessage(ps^);
Inc(ps);
end;
end;
先前思维局限在字符串数组这个整体上了
其实可以针对每个数组元素来考虑
这样就不必管数组是Array[0..2]还是Array[0..5]
因为每个数组里面的每个Array[N]都是String
就用一个^String就可以了
 

Similar threads

I
回复
0
查看
683
import
I
I
回复
0
查看
582
import
I
I
回复
0
查看
303
import
I
后退
顶部