gpt4 book ai didi

delphi - 为什么这两个 Delphi 代码块的行为不同?

转载 作者:行者123 更新时间:2023-12-03 15:51:24 25 4
gpt4 key购买 nike

第一个代码块中注释的两个部分看似相同,但产生不同的结果(由于其他地方的问题)。我不明白它们有何不同。我唯一改变的是注释掉第一部分(for 循环)或第二部分(赋值行)并获得不同的结果。

var
Amount: Integer;
I: Integer;

begin
Amount := 3;

// This produces undesired results (**the for loop**)
for I := 0 to Amount-1 do
CharDataBool[I] := CharToArray(CharDataText[I]);

// This works as expected (**the assignment lines**)
CharDataBool[0] := CharToArray(CharDataText[0]);
CharDataBool[1] := CharToArray(CharDataText[1]);
CharDataBool[2] := CharToArray(CharDataText[2]);

下面的代码的做法有问题,并且在某种程度上是问题的根源,但我的问题是关于上面的代码。仅当 CharToArray 函数未分配 false 时,上述问题才会出现,如下所示:

function CharToArray(Source: TCharDetails): TCharArray;
var
X, Y: Integer;
begin
SetLength(Result, Source.Width, 10);

for Y := 0 to 9 do
for X := 0 to Source.Width-1 do
if Source.S[Y*Source.Width+X] = 'x' then
Result[X,Y] := true
else Result[X,Y] := false; // Adding this solves the problem

end;

没有进入“留下未知的值是非常糟糕的”,我只是想理解为什么问题出现在代码的第一部分中(for循环)而不是(分配行)?这三个赋值行与 for 循环有何不同?

下面可以复制到默认VCL项目中的Unit1

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;

type
TCharArray = array of array of boolean;

TCharDetails = record
S: String;
Width: Integer;
end;

var
CharDataText: array of TCharDetails;
CharDataBool: array of TCharArray;

var
Form1: TForm1;

procedure Init;



implementation

{$R *.dfm}

function CharToArray(Source: TCharDetails): TCharArray;
var
X, Y: Integer;
begin
SetLength(Result, Source.Width, 10);

for Y := 0 to 9 do
for X := 0 to Source.Width-1 do
if Source.S[Y*Source.Width+X] = 'x' then
Result[X,Y] := true;

end;

procedure Init;
var
Amount: Integer;
I: Integer;

X,Y: Integer;
S1, S2: String;

begin
Amount := 2;

SetLength(CharDataText, Amount);
SetLength(CharDataBool, Amount);

ChardataText[0].Width := 10;
ChardataText[0].S :=
// 1234567890
' ' + // 0
' x ' + // 1
' xx ' + // 2
' x ' + // 3
' x ' + // 4
' x ' + // 5
' x ' + // 6
' x ' + // 7
' x ' + // 8
' xxx ';

ChardataText[1].Width := 10;
ChardataText[1].S :=
// 1234567890
'x ' + // 0
' xxxx ' + // 1
' x x ' + // 2
' x ' + // 3
' x ' + // 4
' x ' + // 5
' x ' + // 6
' x ' + // 7
' x ' + // 8
' xxxxxx x';


for I := 0 to Amount-1 do
CharDataBool[I] := CharToArray(CharDataText[I]);
S1 := '';
for Y := 0 to 9 do
for X := 0 to 9 do
S1 := S1 + CharDataBool[1,X,Y].ToString;

CharDataBool[0] := CharToArray(CharDataText[0]);
CharDataBool[1] := CharToArray(CharDataText[1]);
S2 := '';
for Y := 0 to 9 do
for X := 0 to 9 do
S2 := S2 + CharDataBool[1,X,Y].ToString;

// S1 != S2 ??
ShowMessage(S1 + #13 + S2);


end;

initialization

Init;

end.

最佳答案

函数返回值是托管类型。不保证 Result 在进入函数时重新初始化。

在循环示例中,编译器优化了迭代之间的隐式本地 Result 重新初始化。这意味着数组以前的内容仍然存在,必须清除。

作为一般规则,始终在输入时初始化=清除托管函数结果。

在本例中,首先调用函数中的 SetLength(Result,0,0);

<小时/>

参见Do I need to setLength a dynamic array on initialization?举个例子。

关于delphi - 为什么这两个 Delphi 代码块的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54847184/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com