怎样将一个数组全部置为空值? (100分)

  • 主题发起人 主题发起人 delphi 首富
  • 开始时间 开始时间
要是大富翁里面每一个帖子都能向这样得到讨论,那它就像我心目中的大富翁了。



 
特别感谢:beyondair, chuguozhen
Fillchar这个函数容易引起异常,我试过了。

看到大家讨论NUll值与空值的区别,我谈一下自己的看法:
据我所知,delphi里有两个值NUll,nil,它们的作用体现在对数据库字段的赋值上。
Table有一个函数 AppendRecord([nil, null, 0]), 第一个nil表示保留原有值,null表示
将第二个字段置为空值,在很多需要写全的函数里,nil起到了占位的作用。
我不懂Unassigned这种值,如果理解没错,nil=Unassigned

看过这么多的发言,我只能说我的“笨办法”就是我的答案了,无奈
 
再等一天就结贴
 
苯办法挺好的,在c里用memset
其实有没有必要置为零?用的时候自然会赋值,用一个count变量控制一下就可以了
 
nil是指针类型的!null是个值!unassigned和assigned是相反的功能!unassigned常常起释放变量的作用!相当与vb中的nothing
 
看多了实在忍不住,我也要说:
题目是要设成 空 或 NUIL ,前贴已经讨论这两者的含义,我同意。
但各位富翁兄弟有几点很明确是错误的:
1.setlength(value, 0);
setlength(value, 20);
设置后内值未知!
2.FillChar(Value[0],Length(Value)*SizeOf(Variant),0);
肯定越界!!!
3."variant数组不就是指针数组吗"——您说的?
4.“一个二维数组当然是线形存放的,即地址连续的,那么你只要把这一段连续的地址空间
全部清零不就等于数组清零了?”
variant 数组一定是线性存放的吗?!!!
5.笨办法:
for i:= 0 to 19 do
value := varnull;
这是将 variant 置 NUIL 的标准的做法!!!
6.variant 数组过大时,用标准做法比锁定后置值慢 20 倍。
仅此而已。
 
to [blue]delphi 首富[/blue]
兄弟的笨方法还真是笨得可以[:D]
开始看到这个问题觉得很奇怪,因为数组是生存期自动管理的数据类型,一般不需要手工释
放,如果确实需要将数组占用的资源释放(将数组全部置空值),用下面这条语句就可以了
Value:=nil;
SetLengtl(value,20);
即使用循环也不要把循环写死,这样写就比较好了
for i:=Low(value) to High(value) do
value:=NULL

很显然,第一种方法效率要高的多:)
 
小雨哥是总结,Kirste的Valur:=nil是好解,但对本题不是正解决,由于题是空值,所以笨办法不笨,
真好。
结束吧
 
copyMemory()
试试吧
 
几点疑问,请教
setlength(value, 0)
setlength(value, 20);设置后内值未知?
FillChar 肯定越界?,Variant类型赋不同类型的值后,所占空间不同么?
动态数组不是连续存放?
Valur:=nil ,Value的空间还在么?清空数组等于释放空间?
 
没错,beyondair 说的 setlength(value, 0)
setlength(value, 20)
可以设置
value 的大小,但内部是 null 还是 empty 呢 ? 所以我说未知。
fatalexception 说的 FillChar 我想他是忽略了 variant 这个特定的类型。
Length(Value)*SizeOf(Variant) 这句怎么看也顺眼,但试着调试时看看它的值。
variant 初始的时候的值是多少? 它是 varempet ,是一个 ole 类型的内存值,甚至
不在应用程序内存空间,MS 定义的内存管理把 ole 的值送入 2g-3g 空间。所赋值不同,
内存占用当然不同,更要命的是 variant 它是什么 ? Length(Value)*SizeOf(Variant)
这个值是多少 ? 没有 lock 前,Delphi 也不知道。只知道 varempet = $0000 。这个
可以查 system.pas 。动态数组连续存放的说法没错,但有个前提,在 Delphi 中,编译
器必须知道数组头和数据必须是对齐,加了 pack 都不行,而 variant 恰恰不是单一数据
类型,一个 variant 可以为一个简单数据类型,VarArrayOf 一下它又可以是一个数组类型,
(setlength 这个在大多时候可以分配内存,但在 variant 类型里尽量用 VarArrayOf )。
value:=nil 实际上是销毁了这个 value ,没有空间也没有内容了,它也不被程序认可了。
你知道,我也说不清,但针对 variant Delphi 确实特意给了它特别的处理代码,甚至编
译器都没有对它再优化。一切代码的处理直接可以查 system.pas 。
 
DFW确实是一个可以使人增长知识的地方,我加入该论坛也只有1个月多的时间,但是学到了很多知识,本贴我就学到了好多知识。真是应该感谢很多人。
本贴的问题讨论了这么长时间,后续又产生了一些新问题,甚至我们都忘了题目,问题是:“怎样将一个数组全部置为空值?”然后补充说明为:
=================================================
我需要这样一个函数:
var: value:?array?of?variant
函数名(value, null, 开始下标, 个数)
比如我要置一个长度20的数组为空:
函数(value, null, 0, 20);

笨办法:
for i:= 0 to 19 do
value := null
=================================================
刚才,我看了Delphi的帮助文件,以下既是帮助文件的全部内容和例子:

Unassigned function

See also Delphi example C++ example
--------------------------------------------------------
Returns an "empty" variant.

Unit

Variants

Category

Variant support routines

Delphi syntax:

function Unassigned: Variant;

C++ syntax:

extern PACKAGE Variant __fastcall Unassigned();

Description

A variant variable can be "empty", meaning it has not yet been assigned to. The Unassigned function returns an empty variant, which can be assigned to a variant variable to restore the variable to its initial state.

Use the VarIsEmpty function to test whether a variant is empty. When used on an empty variant, the VarType standard function returns varEmpty.

If an empty variant is cast to another type (for example, by assigning to a non-variant variable or calling VarAsType) the following conversions occur:

Destination Conversion result

Numeric type Zero
String type Empty string
Boolean False.

Unassigned is useful with variants referencing OLE Automation Objects that you want to keep "alive" until another value is assigned to the variant.
-----------------------------------------------------------------------------------------------------------------------------------------------------
Unassigned example
In the code fragment shown below, the statement that assigns Unassigned to the MSWord variable causes the OLE Automation Object that was created to interface with Word to be released.

var
MSWord: Variant;
begin
...
MSWord := CreateOleObject('Word.Basic');
...
MSWord := Unassigned;
...

end;

下面的内容是来自Delphi的Variants.pas单元文件
function Unassigned: Variant;
begin
_VarClear(TVarData(Result));
end;

procedure _VarClear(var V: TVarData);
begin
// byrefs and those inline data types are easy
if (V.VType and varDeepData) = 0 then
V.VType := varEmpty
else
VarClearDeep(V);
end;
procedure VarClearDeep(var V: TVarData);
var
LHandler: TCustomVariantType;
begin
// quick test for the simple ones
if (V.VType < varInt64) then
VarResultCheck(VariantClear(V))

// clear the pascal string correctly for reference counting
else if V.VType = varString then
begin
V.VType := varEmpty;
String(V.VString) := '';
end

// let CORBA deal with its own type
else if V.VType = varAny then
ClearAnyProc(V)

// custom handle the arrays
else if (V.VType and varArray) <> 0 then
VarArrayClear(V)

// ok, finally is it a custom variant type?
else if FindCustomVariantType(V.VType, LHandler) then
LHandler.Clear(V)

// finally let the OS attempt to deal with it
else
VarResultCheck(VariantClear(V));
end;
小雨哥提到的VarArrayOf的原形,内部机制也是用循环赋值的:
function VarArrayOf(const Values: array of Variant): Variant;
var
I: Integer;
begin
Result := VarArrayCreate([0, High(Values)], varVariant);
for I := 0 to High(Values) do
Result := Values;
end;
还有一些内容,其实大家可以参考Variants单元
因此将长度为20的Variant类型的数组置为空,下面的写法和Delphi的写法没有什么本质区别
for i:= 0 to 19 do
value := Unassigned;
 
to [blue]小雨哥:[/blue]
我本不想再回答这个问题了……
/*value:=nil 实际上是销毁了这个 value ,没有空间也没有内容了,
/*它也不被程序认可了。
是这样的吗?当然,Kirste无意和你争论技术上的问题。
to [blue]chuguozhen:[/blue]
/*setlength(value, 0);的意思是释放Value这个动态数组,
/*setlength(value, 20);的意思是设置动态数组的长度为20,
/*如过验证一下,会发现,执行这个语句后,value的每一个值都是0
既然数组定义的是Variant类型,那么它的值就不一定是0,而是可变值,
SetLenght(value,20);
ShowMessage(value[0]);
ShowMessage(IntToStr(value[0]);
……
我调试不了,您自己调试一下就知道了。
to [blue]delphi 首富:[/blue]
[red]可以肯定一点,你的笨方法不是标准做法![/red]
 
to 小雨哥
/*setlength(value, 0);/*setlength(value, 20);设置所分配的空间所有的字节数为0
因为我前面提到
varEmpty=$0000;//这是值为Empty时的类型码
varNull=$0001;//这是为NULL值时的类型码
所以 以上两句代码执行完,内容一定为 空值 因为类型码为$0000,如果是NULL值,第一字节的值为1

我试过为Variant的值赋不同类型的值,或是空间,或是 NULL,它的大小都是16字节
Length(Value)*SizeOf(Variant)这个值就是数组大小乘上16,你可以试试

另外,在system单元中,可以看看为动态数组的SetLength函数的原码,它封装了FillChar
在分配空间之后,为新的空间(也可能是增加的部分)清零,也就是动态数组的默认值
下面就是原码
// Set the new memory to all zero bits
FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);
所以如果你只想清空,我认为这是最简单的办法了

To Kirste,
令一个动态数组变量等于Nil的意思就是释放空间,等同于 setlength(value, 0);
这一点,可以参见 Delphi5 开发人员指南第40页,它原来的内容被破坏,但不一定全为
零,但对于动态数组变量而言,它已经没有空间了,我想小雨哥说的是这个动态数组变量吧

数组定义的是Variant类型,第一次分配空间默认值就是零,即所谓的"空"。所以清数组为
空等于其对应的内存空间清零
 
确实,setlength(value, 0)即将value这个varient数组释放,我运行,查阅cpu,通过.
同意beyongair.
 
谢谢大家的帮助
总结(我的理解):
对Variant数组赋值是个有用的操作,当用它对数据库的反复添加记录时尤为重要。因为
当你没有为某些元素赋值时,会影响下条记录。

Kirste对某些特定的问题没有正确的了解,比如setlength在delphi的英文帮助里有很明白
的说明,你的说法与之不符。

to beyondair: fillchar()对variant是一个不好的应用,我相信

我基本同意小雨哥的看法,对数组锁定后赋值能教教我吗?

 
多人接受答案了。
 
[A] href:="http://www.sina.com.cn" fglkd[/A]
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
D
回复
0
查看
867
DelphiTeacher的专栏
D
D
回复
0
查看
836
DelphiTeacher的专栏
D
D
回复
0
查看
785
DelphiTeacher的专栏
D
后退
顶部