当我尝试将变量数组从过程传递到主程序时,过程中的a[1]
应该等于主程序中的arr[1]
,如下所示:
a[1] = arr[1]
a[2] = arr[2]
a[3] = arr[3]
a[4] = arr[4]
a[5] = arr[5]
但该计划实际上是这样的:
a[1] = ''
a[2] = arr[1]
a[3] = arr[2]
a[4] = arr[3]
a[5] = arr[4]
我不知道代码有什么问题,有人可以指出错误吗?
简单的代码,同样的问题:
var
arr : array[1..5] of string;
i : integer;
procedure test(var a : array of string);
var
i : integer;
begin
a[1] := 'one';
a[2] := 'two';
a[3] := 'three';
a[4] := 'four';
a[5] := 'five';
for i := 1 to 5 do writeln(a[i]);
end;
begin
test(arr);
write('-----');
for i := 1 to 5 do
begin
writeln(arr[i]);
if arr[i] = '' then writeln('NOTHING');
end;
readln
end.
答案 0 :(得分:2)
MartynA给了你一个提示,看看"打开数组参数"在在线帮助中。但是没有必要使用ArrayLoBound
等来做他提出的建议。实际数组的声明可以有任何索引范围。
我会这样做:
program OpenArrayTest;
{$APPTYPE CONSOLE}
var
{ Initialization like this only possible for global variables. }
Arr: array[11..15] of string = ('once', 'doce', 'trece', 'catorce', 'quince');
I: Integer;
procedure ModifyArray(var A: array of string);
var
I: Integer;
begin
for I := Low(A) to High(A) do
A[I] := A[I] + ' <-- ' + IntToStr(I);
end;
procedure ShowArray(const A: array of string);
begin
for I := Low(A) to High(A) do
Writeln(A[I]);
end;
begin
ModifyArray(Arr);
ShowArray(Arr);
Writeln('-----');
ShowArray(['one', 'two', 'three', 'four', 'five', 'six', 'seven']);
Readln;
end.
输出结果为:
once <-- 0
doce <-- 1
trece <-- 2
catorce <-- 3
quince <-- 4
-----
one
two
three
four
five
six
seven
换句话说,使用High()
和Low()
来访问参数中的项目。不要使用任何固定边界,因为数组可以有任何长度。另请注意,您可以使用Length(A)
或Length(Arr)
获取数组中的项目数。您不仅可以传递静态数组,如Arr
,还可以传递动态数组,或使用开放数组构造函数(使用[
和]
),就像我在第二次调用中所做的那样到ShowArray()
。
有关我的文章"Open arrays and array of const"中的开放数组的更多信息。
答案 1 :(得分:1)
根据你的评论判断,你有点混乱。
简而言之,如果将过程的参数声明为“数组”,则数组始终从零开始,无论您作为参数传递给它的数组的结构如何,如
test(arr);
尝试以下代码。你会发现,当它运行时,你会在行上得到一个范围检查错误
a[5] := 'five';
那是因为尽管arr
有五个元素,但它们的编号为0..4,因此没有arr
元素的索引为5。
虽然还有其他方法来声明过程参数,但是如果要将数组作为参数传递给它,则必须确保在编写代码时心理转换数组索引,或者(更好)声明数组你把它作为零基础传递给它,就像我做的那样。
然后,尝试养成改变范围检查的习惯。它会发现你自己可能忽略的错误。
我打算让你重写你的test
程序,以便它作为练习正常工作,因为我“猜测”你所发布的是某种学校或课程 - 工作,你应该真正付出一些努力,找出如何自己纠正你的错误。如果您在阅读本文并尝试显而易见的解决方案后仍然感到困惑,请询问。
顺便说一句,如果你使用的是Delphi,请在在线帮助中查找“打开数组参数”。这解释了使用“数组......”程序参数的限制。
另外顺便说一句,Rudy Velthuis在他的回答中说:“但是没有必要使用ArrayLoBound等来做MartynA提出的建议。”这是事实,没有必要,但他已经错过了我的观点。如果您使用1和5之类的值对数组边界进行硬编码,然后在以后更改它们,则很容易忽略需要更新的其他值,例如在for
循环中。将这些值定义为const
是一个很好的习惯,因为它避免引入不一致,但更重要的是确保你考虑你在做什么。 IME ......
program arrayparam;
const
ArrayLoBound = 0;
ArrayHiBound = 4;
var
arr : array[ArrayLoBound..ArrayHiBound] of string;
i : integer;
{$R+} // Turn range-checking on
procedure test(var a : array of string);
var
i : integer;
begin
a[1] := 'one';
a[2] := 'two';
a[3] := 'three';
a[4] := 'four';
a[5] := 'five';
for i := 1 to 5 do
writeln(a[i]);
end;
begin
test(arr);
writeln('-----');
for i := ArrayLoBound to ArrayHiBound do
begin
writeln(arr[i]);
if arr[i] = '' then
writeln('NOTHING');
end;
readln
end.
答案 2 :(得分:0)
所有好的答案,但只是要完整:提问者可以得到完全要求的结果。
可能是因为使用1到5来访问它们对于提问者的目的很重要。
进行以下更改,它将按原定预期打印出来。
输入
TArr =字符串的数组[1..5];
VAR
arr:TArr;
程序测试(var a:TArr);
我同意默认为基于0的数组更简单,并且使用低/ hi函数使其成为防弹。
但我也可以看到,有时以自己的方式编制索引可能有用/重要。