arrays - delphi 在使用函数和数组时出错
问题描述
当我通过函数填充数组时会发生此错误。该函数使用存储在文本文件中的所有详细信息填充数组。该代码可以填充数组,但是当我尝试在函数中使用它时它不起作用。
type
DynamicArray = array of string;
Function fillarr(ArrParm: DynamicArray; FileName: String): DynamicArray;
Var
tf: TextFile;
sWord: String;
i: Integer;
begin
i := 0;
SetLength(ArrParm, 1);
AssignFile(tf, FileName);
Reset(tf);
while not eof(tf) do
begin
Readln(tf, sWord);
ArrParm[i] := sWord;
Inc(i);
SetLength(ArrParm, i + 1);
end;
SetLength(ArrParm, i - 1);
Result := ArrParm;
end;
procedure TForm4.FormShow(Sender: TObject);
Var
arrPictures: DynamicArray;
begin
FillArr(arrPictures, 'NameOfTheTextFile.txt');
ShowMessage(arrPictures[1]); // Error occurs here
解决方案
您必须了解动态数组是引用类型,但引用是按值传递的。
在TForm4.FormShow
中,您有一个动态数组变量arrPictures
。即使这是一个局部变量,它也会被初始化,因为它是一个动态数组,它是一种托管类型。具体来说,它的开头是nil
(一个零长度的动态数组)。因此,第二个元素arrPictures[1]
在此方法开始时不存在。
您尝试通过调用来填充数组FillArr
。但是,当您传递arrPictures
给此方法时,引用是按值传递的,因此FillArr
获得了指向动态数组堆对象的指针的副本。
现在,该SetLength
过程重新分配了动态数组堆对象,因此指向它的指针必须改变。换句话说,ArrParm
变量的值发生变化,指向一个新的动态数组堆对象。最初的,它TForm4.FormShow
是有意识的,保持不变。(但在这种情况下它根本不存在,因为数组nil
的长度为零。)
因此,当fillarr
返回时,arrPictures
仍然是nil
,并且arrPictures[1]
仍然不存在。所以你得到一个 AV 试图阅读它。
解决办法是把数组参数做成var
参数,这样动态数组变量是通过引用传递的。这样,当FillArr
更改指针的值时,此更改将对 in 中的变量可见TForm4.FormShow
:
function fillarr(var ArrParm: DynamicArray; FileName: string): DynamicArray;
(fillarr
是一个函数,它实际上返回了新数组。但是当你在 中调用这个函数时TForm4.FormShow
,你会丢弃结果值,所以你不会因为它是一个函数而获得任何收益。但这意味着不同的解决方案是不丢弃结果值。但是您可以完全删除参数。您不需要或不希望例程有两种方法返回相同的值。要么让它成为一个带var
orout
参数的过程,要么让它成为一个不带参数的函数.)
除了这个问题,代码还有其他问题。例如,试着想想你是如何阅读文件的。你能用更少的SetLength
电话做到这一点吗?
(但在实际应用程序中,根本不应该使用传统的 Pascal I/O,并且应该“从不”一次增加一个动态数组或字符串的大小。)
推荐阅读
- javascript - jquery 在 html 脚本标签中不起作用
- php - PHP中文件上传If语句的测试错误
- r - 求解具有 12 个变量的约束方程
- android - 将构建类型(“debug”/“release”)传递给 ndk-build
- r - 使用 difftime + 减法运算符时出现错误“必须提供原点”在不同的分钟内不起作用
- javascript - React 博客网站的管理仪表板
- typescript - Admin Sdk 自定义声明返回 null
- matlab - 直接在函数输出处分解单元格
- python-3.x - MinMaxScaler 和变换后的 ValueError
- javascript - 虽然命令不适用于延迟 javascript