记录结构的问题, 怎样找出记录的名字?(100分)

  • 主题发起人 主题发起人 sileo
  • 开始时间 开始时间
S

sileo

Unregistered / Unconfirmed
GUEST, unregistred user!
请看下面的注释部分. 谢谢!
unit Unit1;

interface

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

type
Pfld = ^fld;
fld = Record
S1: string;
S2: string;
F1: double;
F2: double;
I1: Integer;
I2: Integer;
D1: TDateTime;
D2: TDateTime;
//...
end;

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

var
Form1: TForm1;

Tfld : pfld;

function Set_FLds( fldName:string
fldValue: variant ):string;

implementation

{$R *.DFM}

function Set_FLds( fldName:string
fldValue: variant ):string;
begin
New(Tfld);

//以下方法太笨了, 有没有好的办法?
//能不能自动找记录的名称, 并赋值?
//

if fldName = 'S1' then
begin
Tfld.S1 := fldValue;
exit;
end;
if fldName = 'S2' then
begin
Tfld.S2 := fldValue;
exit;
end;
if fldName = 'F1' then
begin
Tfld.F1 := fldValue;
exit;
end;
if fldName = 'F2' then
begin
Tfld^.F2 := fldValue;
exit;
end;
//....
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Set_Flds( 'S1','0000123');
showmessage(Tfld^.S1);
end;

end.
 
分不够吗?
 
你开什么玩笑,[:)]
在记录中使用case就可以了,如果还不清楚,你可以查找Delphi的源代码,有这样使用的
例子,比如说,Variant本身就是.它是这样用TVarData(xxx)
case ......
 
xiangya兄:
不是很明白,能否说详细些? 谢谢!!
 
加多一百大洋!!
 
发表一下个人看法
首先需要明白你的结构定义是否合理,是否每个该类型的变量都需要结构中定义的这么多
变量,如果不是的话,应该考虑使用 variant 变量,如果variant变量不能满足的话,
再考虑使用变体纪录。
在过程中赋值可以如上面老大所说的应用case语句判断变量类型,否则那么
多if 谁受得了?!

 
下面的方法应该不算太笨吧...

var
SL:TStringList;
procedure Init;
begin
SL:=TStringList.Create
//记得用完了Free哟~
SL.Add('S1');
SL.Add('S2');
SL.Add('F1');
SL.Add('F2');
SL.Add('I1');
SL.Add('I2');
SL.Add('D1');
SL.Add('D2');
end;
function Set_FLds( fldName:string
fldValue: variant ):string;
begin
New(Tfld);
case SL.IndexOf(fldName) of
0: Tfld.S1:=fldValue;
1: Tfld.S2:=fldValue;
2: Tfld.F1:=fldValue;
//...
end;
end;
 
改进版:

type
Pfld=^fld;
PVariant=^Variant;
fld=Record
S1:PVariant;
S2:PVariant;
F1:PVariant;
F2:PVariant;
end;
var
Tfld : fld;
SL:TStringList;
procedure Init;
var
PV:PVariant;
begin
with Tfld do //稍稍有些麻烦——你可以用类嘛,结构体很麻烦的
begin
New(PV)
S1:=PV;
New(PV)
S2:=PV;
New(PV)
F1:=PV;
New(PV)
F2:=PV;
end;
SL:=TStringList.Create
//记得用完了Free哟~
SL.Clear;
SL.Add('S1');
SL.Add('S2');
SL.Add('F1');
SL.Add('F2');
end;
function Set_FLds( fldName:string
fldValue: variant ):string;
var
addr:Integer;
begin
addr:=Integer(@Tfld.S1)+SL.IndexOf(fldName)*SizeOf(PVariant)
//一步到位
PVariant(Pointer(addr)^)^:=fldValue
//这一行让我调了好半天 :(
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Tfld.S2^:='Hello!';
Set_FLds('S1','24');
Set_FLds('F1',2.34);
Caption:=String(Tfld.S1^)+'..'+String(Tfld.S2^)+'..'+String(Tfld.F1^);
end;

begin
Init;
end.

OK?
 
你的方法并不笨,简洁,易读,别老想找巧妙的办法
这方法最直接了
 
Creation-zy 的方法可行,但还是麻烦了些,可能还会慢,要建立StringList.
有更好的办法吗?
 
我觉得怎么这么别扭,难道你每次set一次你就 New(Tfld) 一次?
 
我现在改用类.
但我还是象用记录结构一样, 找不到类记录的名字(象宏替换一样就好办了).
Tfld = class
S1: string;
S2: string;
F1: double;
//...
public
procedure Set_FLds( fldName:string
fldValue: variant );
end;

procedure Tfld.Set_FLds( fldName:string
fldValue: variant );
begin
if fldName = 'S1' then
begin
S1 := fldValue;
exit;
end;
if fldName = 'S2' then
begin
S2 := fldValue;
exit;
end;
//....
//象这样就很烦, 能否用.诸如能用indexname(fldName) := fldValue.
// 那就一句搞定了.
end;

 
各位: help me!!
 
方案1:
unit Unit2;
interface
uses
Classes, Sysutils;
type
Tfld=class
S1: string;
S2: string;
F1: double;
public
procedure Set_FLds(fldName:string;fldValue:variant);
class procedure InitSL
//初始化索引表,用类方法实现
class procedure FreeSL
//释放索引表
end;
implementation
var
fldSL:TStringList=nil;
class procedure Tfld.FreeSL;
begin
FreeAndNil(fldSL);
end;
class procedure Tfld.InitSL;
begin
if fldSL=nil then
fldSL:=TStringList.Create;
fldSL.Clear;
with fldSL do
begin
Add('S1');
Add('S2');
Add('F1');
end;
end;
procedure Tfld.Set_FLds( fldName:string
fldValue: variant );
begin
if fldSL<>nil then
case fldSL.IndexOf(fldName) of
0: S1:=fldValue;
1: S2:=fldValue;
2: F1:=fldValue;
end;
end;
end.


方案2:
unit Unit2;

interface

uses
Classes, Sysutils;

type
PVariant=^Variant;
Tfld=class
S1: PVariant;
S2: PVariant;
F1: PVariant;
public
procedure Set_FLds(fldName:string;fldValue:variant);
class procedure InitSL;
class procedure FreeSL;
constructor Create;
destructor Destroy
override;
end;

implementation

var
fldSL:TStringList=nil;
constructor Tfld.Create;
var
PV:PVariant;
begin //分配空间
New(PV)
S1:=PV;
New(PV)
S2:=PV;
New(PV)
F1:=PV;
end;
destructor Tfld.Destroy;
begin //释放空间
Dispose(S1);
Dispose(S2);
Dispose(F1);
inherited;
end;
class procedure Tfld.FreeSL;
begin
FreeAndNil(fldSL);
end;
class procedure Tfld.InitSL;
begin
if fldSL=nil then
fldSL:=TStringList.Create;
fldSL.Clear;
with fldSL do
begin
Add('S1');
Add('S2');
Add('F1');
end;
end;
procedure Tfld.Set_FLds( fldName:string
fldValue: variant );
var
addr:Integer;
begin
if fldSL<>nil then
begin
addr:=Integer(@S1)+fldSL.IndexOf(fldName)*SizeOf(PVariant);
PVariant(Pointer(addr)^)^:=fldValue;
end;
end;
end.
 
谢谢creation-zy,
能有更好的办法吗?
 
TO:creation-zy
type
PVariant=^Variant;
Tfld=class
S1: PVariant;
S2: PVariant;
F1: PVariant;
public
procedure Set_FLds(fldName:string;fldValue:variant);
class procedure InitSL;
class procedure FreeSL;
constructor Create;
destructor Destroy
override;
end;
中的
class procedure InitSL;
class procedure FreeSL;
为什么用类方法?
不用类方法是不是也一样?
若不一样请说明!TKS!
 
类方法——就是类中不需要类的实例(指对象)就可以执行的方法,这些方法不需要类的实例信息,
但和该类的联系又十分紧密(比如Object Pascal中的ClassName——类名,它不需要对象)。在上面的
例子中,InitSL和FreeSL均没有读写类的实例中的任何内容,又和类紧密相关,因此采用类方法实现。
 
to:creation-zy

我调试了方案2,发觉就ss.Set_FLds('S1',10)可以!
将'S1'换成'S2','F1'就不行!不知是何故?
你调试过了吗?
 
后退
顶部