Pascal过程传递变量数组

时间:2016-07-18 13:36:56

标签: pascal

当我尝试将变量数组从过程传递到主程序时,过程中的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.

3 个答案:

答案 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函数使其成为防弹。

但我也可以看到,有时以自己的方式编制索引可能有用/重要。