如何使过程更改变量参数的值?

时间:2015-04-20 18:59:33

标签: delphi delphi-2010

我尝试创建一个简单的过程,从输入的字符串中删除空格:

procedure RemoveSpaces(StringParameter : String);
var
   SpacePosition: Integer;
begin
   SpacePosition := Pos(' ',StringParameter);
   while SpacePos <> 0 do
   begin
      Delete(StringParameter,SpacePos,1);
      SpacePosition := Pos(' ',StringParameter);
   end;
end;

但在测试以下代码中的过程后:

var
   Input : String;
begin
   Readln(Input);
   RemoveSpaces(Input);
   Writeln(Input);
   Readln;
end.

很明显,输入变量只是从程序中反过来,好像它从未改变过一样。

我认为这可能仅限于我可以用我尚未实现的过程做什么但后来我记得我之前已经创建了一个带有StringList参数的过程,并按字母顺序对StringList中的字符串进行排序将更改保存到StringList变量参数:

var
   myStringList : TStringList;

implementation

procedure StringListSort(StringList : TStringList);
begin
   //Sort StringList
end;

procedure TFormName.ButtonNameClick(Sender: TObject);
begin
   StringListSort(myStringList);
end; 

欢迎解决我的问题。

1 个答案:

答案 0 :(得分:12)

procedure RemoveSpaces(StringParameter: string);

您正在传递字符串参数按值。在语义上 1 ,副本由您传递的参数组成,并且对该副本进行任何修改。来电者没有观察到修改。

您需要通过参考传递参数。当您通过引用传递时,该过程对原始变量进行操作,而不是副本。

在Pascal和Delphi中,you pass by reference by using the var keyword。变化

procedure RemoveSpaces(StringParameter: string);

procedure RemoveSpaces(var StringParameter: string);

您观察到TStringList参数似乎有不同行为的原因是TStringList是一个引用类型的类。这意味着给定List: TStringList然后List是对象的引用。有关值和引用类型之间区别的更多讨论,请参阅我的答案:Why should we use classes rather than records, or vice versa?

documentation可以就此事说:

  

类类型的变量实际上是引用对象的指针。因此,多个变量可以引用同一个对象。与其他指针一样,类类型变量可以保存值nil。但是,您不必显式取消引用类型变量来访问它指向的对象。例如,SomeObject.Size := 100将值100分配给Size引用的对象的SomeObject属性;你不会把它写成SomeObject^.Size := 100

这里的文档更明确地说明类类型变量实际上只是指针。

您可以使用RTL函数StringReplace

更有效,更简单地实施您的程序
procedure RemoveSpaces(var StringParameter: string);
begin
  StringParameter := StringReplace(StringParameter, ' ', '', [rfReplaceAll]);
end;

我还要评论一个函数可能是更好的选择。这使您可以灵活地传递除变量之外的其他内容,例如文字或常量。而且您还可以更轻松地编写和链接函数。

所以这将是

function SpacesRemoved(const str: string): string;
begin
  Result := StringReplace(str, ' ', '', [rfReplaceAll]);
end;

然后不必写:

RemoveSpaces(Input);
Writeln(Input);

你可以写

Writeln(SpacesRemoved(Input));

1 我在语义上说,因为string是一个引用类型,虽然是一个特殊的类型。区别在于,如果多个变量引用相同的字符串对象,则在进行修改时,将字符串复制到新对象,并为修改变量赋予唯一引用。这称为写时复制,其作用是使string数据类型的行为类似于值类型。