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

标签 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; 

欢迎任何解决我的问题的方法。

最佳答案

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: TStringListList 是对该对象的引用。有关值类型和引用类型之间区别的更多讨论,请参阅我的回答:Why should we use classes rather than records, or vice versa?

documentation对于此事有这样的说法:

A variable of a class type is actually a pointer that references an object. Hence more than one variable can refer to the same object. Like other pointers, class-type variables can hold the value nil. But you don't have to explicitly dereference a class-type variable to access the object it points to. For example, SomeObject.Size := 100 assigns the value 100 to the Size property of the object referenced by SomeObject; you would not write this as 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 数据类型的行为类似于值类型。

关于delphi - 如何使过程更改变量参数的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29756198/

相关文章:

Delphi 2010 或 2007 用于升级 Delphi 3 项目?

delphi - 如何为 RAD Studio 的工具组件创建选项卡式 View

xml - 如何在文本中添加/插入 xml 节点

delphi - 显示 "empty"TDateTimePicker

Delphi - 绘制文本,使其在重新绘制其下方的图像后不会消失

delphi - TDictionary 通过 DataSnap 崩溃,FComparer 为零

delphi - Delphi 2010 的编译器版本是什么?

delphi - 什么是TExternalThread? "Cannot terminate externally created thread"终止基于线程的计时器时

Delphi TList<T> 泛型

c++ - 在 Delphi 中明确表达所有权