我发现这个在线代码在程序中有一个过程。
我不明白为什么作者会选择这样写。
我所注意到的是执行的递归函数。

为什么他没有像我看过的大多数代码那样分离过程。

他的实施:

procedure XML2Form(tree : TJvPagelistTreeView; XMLDoc : TXMLDocument);
var
  iNode : IXMLNode;

  procedure ProcessNode(
    Node : IXMLNode; 
    tn   : TTreeNode);
  var
    cNode : IXMLNode;
  begin
    if Node = nil then Exit;
    with Node do
    begin
      tn := tree.Items.AddChild(tn,Attributes['text']);
      tn.ImageIndex := Integer(Attributes['imageIndex']);
      tn.StateIndex := Integer(Attributes['stateIndex']);
    end;

    cNode := Node.ChildNodes.First;
    while cNode <> nil do
    begin
      ProcessNode(cNode,tn);
      cNode := cNode.NextSibling;
    end;
  end; (*ProcessNode*) 
begin
  tree.Items.Clear;
  XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
  XMLDoc.Active := True;

  iNode := XMLDoc.DocumentElement.ChildNodes.First;

  while iNode <> nil do
  begin
    ProcessNode(iNode,nil);
    iNode := iNode.NextSibling;
  end;
  XMLDoc.Active := False;
end; (* XML2Form *)


procedure Form2XML(tree: TJVPagelistTreeView);
var
  tn : TTreeNode;
  XMLDoc : TXMLDocument;
  iNode : IXMLNode;

  procedure ProcesstreeItem(
    tn    : TTreeNode;
    iNode : IXMLNode);
  var
    cNode : IXMLNode;
  begin
    if (tn = nil) then Exit;
    cNode := iNode.AddChild('item');
    cNode.Attributes['text'] := tn.Text;
    cNode.Attributes['imageIndex'] := tn.ImageIndex;
    cNode.Attributes['stateIndex'] := tn.StateIndex;
    cNode.Attributes['selectedindex'] := tn.Selectedindex;

    //child nodes
    tn := tn.getFirstChild;
    while tn <> nil do
    begin
      ProcesstreeItem(tn,cNode);
      tn := tn.getNextSibling;
    end;
  end; (*ProcesstreeItem*)
begin
  XMLDoc := TXMLDocument.Create(nil);
  XMLDoc.Active := True;
  iNode := XMLDoc.AddChild('tree2xml');
  iNode.Attributes['app'] := ParamStr(0);

  tn := tree.TopItem;
  while tn <> nil do
  begin
    ProcesstreeItem (tn,iNode);

    tn := tn.getNextSibling;
  end;

  XMLDoc.SavetoFile(ChangeFileExt(ParamStr(0),'.XML'));
  XMLDoc := nil;
end; (* Form2XML *)

或修改实施:

procedure ProcessNode(Node : IXMLNode; tn : TTreeNode);
var
  cNode : IXMLNode;
begin
  if Node = nil then Exit;
  with Node do
  begin
    tn := tree.Items.AddChild(tn,Attributes['text']);
    tn.ImageIndex := Integer(Attributes['imageIndex']);
    tn.StateIndex := Integer(Attributes['stateIndex']);
  end;

  cNode := Node.ChildNodes.First;
  while cNode <> nil do
  begin
    ProcessNode(cNode,tn);
    cNode := cNode.NextSibling;
  end;
end; (*ProcessNode*)

procedure ProcesstreeItem(tn : TTreeNode; iNode : IXMLNode);
var
  cNode : IXMLNode;
begin
  if (tn = nil) then Exit;
  cNode := iNode.AddChild('item');
  cNode.Attributes['text'] := tn.Text;
  cNode.Attributes['imageIndex'] := tn.ImageIndex;
  cNode.Attributes['stateIndex'] := tn.StateIndex;
  cNode.Attributes['selectedindex'] := tn.Selectedindex;

  //child nodes
  tn := tn.getFirstChild;
  while tn <> nil do
  begin
    ProcesstreeItem(tn,cNode);
    tn := tn.getNextSibling;
  end;
end; (*ProcesstreeItem*)

procedure XML2Form(tree : TJvPagelistTreeView; XMLDoc : TXMLDocument);
var
  iNode : IXMLNode;
begin
  tree.Items.Clear;
  XMLDoc.FileName := ChangeFileExt(ParamStr(0),nil);
    iNode := iNode.NextSibling;
  end;
  XMLDoc.Active := False;
end;

procedure Form2XML(tree: TJVPagelistTreeView);
var
  tn : TTreeNode;
  XMLDoc : TXMLDocument;
  iNode : IXMLNode;
begin
  XMLDoc := TXMLDocument.Create(nil);
  XMLDoc.Active := True;
  iNode := XMLDoc.AddChild('tree2xml');
  iNode.Attributes['app'] := ParamStr(0);

  tn := tree.TopItem;
  while tn <> nil do
  begin
    ProcesstreeItem (tn,'.XML'));
  XMLDoc := nil;
end; (* Form2XML *)

解决方法

这样的嵌套过程在这个XML相关代码中是有意义的。要处理所有节点,需要一个递归调用ProcessNode。你必须注意,有时,内部函数需要访问比一些参数更多的数据。

潜在的实现可能是:

>使用“平”程序,如在您的实现中;
>使用“嵌套”过程,如原来的实现;
>创建一个专用的类(或记录方法),它将保持私有对于该单元的实现部分。

当然,第三个选项听起来更可维护。它将允许清除过程的分离,并允许使用本地方法的变量。使用记录(或旧版本的Delphi对象)将允许处理对象分配在主过程的堆栈上,因此您不需要编写Obj:= TInterType.Create;试试..终于Obj.Free。但是如果你使用一个对象,请注意一些新版本的Delphi has compilation issue – 你应该更好地使用方法记录。

“平面”过程风格是IMHO不比“嵌套”过程更好,更糟糕的是,由于需要向内部调用添加附加参数,或使用一些全局变量。顺便说一下,每次调用都有很多变量会增加堆栈空间,并降低速度。

“嵌套”风格实际上是面向对象的。当调用内部函数时,编译器将寄存器中的调用者堆栈基础传递给嵌套函数(就像对象的附加自参数)。所以内部函数能够访问所有调用者栈变量,就像在私有对象中声明的一样(第三个解决方案)。

Delphi IDE和内部调试器很好地处理嵌套过程。对于一些小的代码(也就是说,在同一个屏幕高度上可以读取的内容),IMHO可能是有意义的。那么,当你需要更多的流程时,具有方法和显式变量的专用记录/对象将更加可维护。但是“平”选项是IMHO不被编码。

我只是written a blog article about these implementation patterns,它将提供QuickSort实现的一些源代码,它将尽可能使用尽可能少的堆栈空间,并且将避免调用过程中的嵌套过程,并改用专用私有对象。

在所有情况下,不要害怕创建一些内部对象/类来实现算法。 Delphi的最新版本甚至允许类定义中的私有类型 – 但是有时候,使内部对象对于单元的实现部分完全是私有的,即使不显示为单元的接口部分的私有成员,我感觉更为舒适。

类不仅用于在单元之外发布过程:OOP也适用于实现模式。您的代码将更加易于维护,在大多数情况下,自身参数将被用于一次性引用所有相关数据,因此您的代码也可能更快更轻!

delphi – 程序中的程序?的更多相关文章

  1. ios – Xcode只看到一些嵌套类的类似扩展,这些扩展是用不同的文件编写的

    解决方法我遇到过类似的问题,似乎编译器正在尝试处理扩展嵌套类的文件,在嵌套类定义之前.因此,您有此错误说该Space没有成员SomeClass.我发现的解决方案是转到目标设置,打开BuildPhases.在“编译源”部分中,您应该将用于定义嵌套类的文件放在扩展它的文件上.这个解决方案似乎甚至可以很好地与您的观察结果一致,当您重新创建文件时,它有时会编译,因为当您重新创建文件时,它在编译源中的位置会发生变化.

  2. ios – 嵌套递归函数

    我试图做一个嵌套递归函数,但是当我编译时,编译器崩溃.这是我的代码:编译器记录arehere解决方法有趣的…它似乎也许在尝试在定义之前捕获到内部的引用时,它是bailing?以下修复它为我们:当然没有嵌套,我们根本没有任何问题,例如以下工作完全如预期:我会说:报告!

  3. ios – 在swift中将捕获列表正确放置在嵌套闭包中

    在Swift中为哪些嵌套闭包定义捕获的引用?如果[weakself]被捕获在只有内部最后面的闭包,GCD将保留ExampleDataSource,直到块完成执行,这就解释了为什么调试看起来像这样:同样的事情会发生,如果没有捕获列表被包括,我们从来没有可选地解开自己,尽管编译器,确实试图警告你!

  4. ios – 无效的软件包 – 嵌套软件包没有在CFBundleSupportedPlatforms Info.plist键中列出的正确平台

    我上传了一个应用程序到iOSAppStoretestflight.iOSAppStore收到以下电子邮件:InvalidBundle–Anestedbundledoesn’thavetherightplatformslistedinCFBundleSupportedplatformsInfo.plistkey.Oncetheseissueshavebeencorrected,youcanthenr

  5. ios – 如何在使用嵌套上下文时自动设置Core Data关系

    解决方法想到的第一个想法是,虽然姓名的人际关系是不可选的,但你并没有说Person的姓名关系也是不可选的.创建一个没有名字的人,可以用您的代码处理,然后在实际需要时创建名称吗?当然不用打扰自定义awakeFromInsert…

  6. ios – 我在哪里可以找到用于创建IPad应用程序的Delphi资源?

    我之前一直在使用Delphi并且一直都是Windows家伙.我的妻子为我的生日买了一台新的iPad,我昨晚第一次使用它.哇!…

  7. 如何从命令行部署OSX或IOS Delphi项目?

    我正在使用像这样的脚本构建我的Delphi应用程序现在我想添加一个选项将应用程序部署到OSX系统修改这样的脚本,那么可以从命令行部署OSX或IOSDelphi项目吗?

  8. cocoa-touch – Interface Builder:如何选择嵌套元素?

    在界面构建器中是否有一种方法可以看到我的元素树,以便我可以选择它们.在实际视图中选择内容非常困难,特别是当我有很多元素和嵌套视图等时.谢谢解决方法尝试按住shift并右键单击元素.它应该显示该元素下的视图层次结构的菜单.实际上,等一下,在层次结构中显示出这个元素之上的元素.你想要做的是使用Nib窗口,选择’Window’然后设置它的列视图,这样你就可以更轻松地导航.

  9. 寒城攻略:Listo 教你 25 天学会 Swift 语言 - 21 Nested Types

    //***********************************************************************************************//1.nestedTypes(类型嵌套)//________________________________________________________________________________

  10. Swift基础语法: 22 - Swift的函数类型, 嵌套函数

    前面我们讲解了函数里面的形参,现在让我们继续来看看函数的类型,以及嵌套函数,让我们一起来看看:1.使用函数类型在Swift中的函数声明和在OC中没什么区别,只有语法上的差异,但在Swift中有一项比较有趣的就是,声明变量或者常量的时候也是可以指定返回值的,比如:当然,常量也是可以如此的,这里就不多做解释了,想知道的朋友可以自己回去试试.2.作为形参类型的函数类型还有更好玩的就是,我们可以在声明新的

随机推荐

  1. delphi – 主窗口按进程名称处理

    DelphiXe,Win7x64如何从进程名称(exe文件的完整路径)获取主窗口句柄,或至少一个类或窗口名称(如果该进程只有一个窗口).例:解决方法我同意Petesh的说法,你需要枚举顶级窗口并检查创建它的进程的模块文件名.为了帮助您开始枚举顶级窗口,这是一个delphi实现.首先,当你回调给你时,你需要一些与EnumWindows方法通信的方式.为此声明一条记录,该记录将保存您要查找的模块的文件

  2. 如何在Delphi中纯粹通过RTTI信息(即不使用任何实际对象实例)获取TObjectList的子项类型?

    我正在使用RTTI实现用于流式传输任意Delphi对象的通用代码,并且为了使其工作(更具体地说,为了使加载部分工作),我需要以某种方式获得TObjectList的子项类型<T>不使用任何实际对象实例的字段.要求不使用任何实际对象实例的明显原因是,在从流加载对象的情况下(仅基于要加载的对象的类类型的知识),我将不会有任何实例在加载完成之前完全可用–我宁愿只能访问相关类的纯RTTI数据.我希望能

  3. inno-setup – Inno Setup – 安装程序背景图片

    图像作为安装程序背景如何用inno5.5.9做到这一点?

  4. inno-setup – Inno Setup – 如何添加多个arc文件进行解压缩?

    使用InnoSetup解压缩弧文件.我希望有可能解压缩多个arc文件以从组件选择中安装文件(例如).但仍然显示所有提取的整体进度条.这可能吗?的回答的修改预备是相同的,参考其他答案.在ExtractArc中,为要提取的每个存档调用AddArchive.

  5. delphi – 如何在DataSet的帮助下在TAdvStringGrid中显示数据库中的BLOB图像

    解决方法CreateBlobStream正在创建一个TStream对象,而不是TMemoryStream.由于您不想将JPG写入数据库,因此应使用bmRead而不是bmReadWrite.我不习惯sqlite,但你必须确保使用合适的二进制日期类型.为了确保存储的图像真的是JPG,您应该编写JPG以进行测试,例如:

  6. inno-setup – 在Inno Setup的Code部分下载程序后运行程序

    如何运行我通过Internet下载的应用程序,在代码部分中使用,并等待该应用程序完成运行.我有,使用InnoTools下载程序,下载这两个文件,我想,在第二个完成下载后运行该下载,或jdk-8u111-windows-x64.exe,然后继续安装.解决方法使用其他下载插件,而不是ITD(请参阅下面的原因).例如,InnoDownloadPlugin.当您包含idp.iss时,它定义了一个全局IDP

  7. progress-bar – Inno Setup Run部分的简单进度页面

    我的安装程序非常简单,它基本上是:>欢迎页面>进展页面>最终页面欢迎页面和最终页面是标准页面.在Progress页面,我正在静默安装一堆其他程序.实际的脚本是在[Run]部分中安装每个程序.问题是酒吧达到100%然后停留在那里.我只能更改消息文本.我想要实现的是使用Pascal脚本显示进度,例如:这样我就可以显示更准确的进度条.这就是我所拥有的:问题是,当我构建安装程序时,它不显示欢迎页面.我做错了什么?

  8. delphi – 如何使“显示/隐藏桌面图标”设置生效?

    下面的代码调用SHGetSetSettings函数来隐藏桌面图标但它只是从视图菜单中取消选中“显示桌面图标”.我打电话给SHChangeNotify;更新桌面,但这不起作用?解决方法isa,要刷新桌面,您可以将F5键发送到progman窗口隐藏桌面图标的另一种方法是再次显示

  9. inno-setup – Inno Setup – 避免显示子安装程序的文件名

    我试图使用InnoSetup–Howtohidecertainfilenameswhileinstalling?(FilenameLabel)的想法Theonlysuresolutionistoavoidinstallingthefiles,youdonotwanttoshow,usingthe[Files]section.Installthemusingacodeinstead.UsetheEx

  10. inno-setup – Inno Setup磁力链接下载实施

    我目前正在使用InnoDownloadPlugin为我的安装程序下载文件,这个问题最大的问题是faila正确下载文件.因为连接不良等诸多原因.我想添加一种替代方法来下载文件,因此用户可以选择是否需要常规方式或torrent方式.我知道我可以使用aria2c.exe应用程序(https://aria2.github.io/),有人可以帮我实现它的inno设置代码吗?我需要的是使用torrent(ar

返回
顶部