delphi 如何计算TVirtualStringTree节点数据字段

eh57zj3b  于 2023-02-04  发布在  其他
关注(0)|答案(2)|浏览(135)

我有一个VirtualStringTree(VST),其中的节点具有以下数据结构:

Type
  PMyNodeData = ^TMyNodeData;
  TMyNodeData = record
    Cost:UnicodeString; 
  end;

没有任何子节点的子节点具有成本值,但任何父节点具有等于0的成本值,并且我正在尝试编写程序,使任何父节点的成本值等于其所有子节点的成本之和。
我试过下一个:

procedure CalculateSum(Node:PVirtualNode);
var
  Data: PMyNodeData;
  ChildNode: PVirtualNode;
  ChildData: PMyNodeData;
  CostSum: Extended;
begin
  Data := VST.GetNodeData(Node);
  CostSum := 0.0;
  ChildNode := VST.GetFirstChild(Node);
  while Assigned(ChildNode) do
  begin
    ChildData := VST.GetNodeData(ChildNode);
    CostSum := CostSum + StrToFloat(ChildData.Cost);
    CalculateSum(ChildNode);
    ChildNode := VST.GetNextSibling(ChildNode);
  end;
  if  VST.HasChildren[Node] and (StrToFloat(Data.Cost) = 0) then
    Data.Cost := FloatToStr(CostSum);

end;

用途:

CalculateSum(vst.RootNode);

但我得到访问违规&总和是不正确的..任何建议。

wfsdck30

wfsdck301#

您正在计算子代的Cost之前访问它。您需要在将其Cost添加到CostSum之前 * 调用CalculateSum(ChildNode),而不是像当前所做的那样在 * 之后 * 调用。
此外,您没有指定PMyDataNode是否始终为nil,或者TMyNodeData.Cost是否包含值为0的节点的空字符串。如果您为StrToFloat()提供空字符串,则StrToFloat()将引发异常。如果可能,请改用StrToFloatDef()TryStrToFloat()
试试这样的方法:

procedure CalculateSum(Node: PVirtualNode);
var
  Data, ChildData: PMyNodeData;
  ChildNode: PVirtualNode;
  Cost, CostSum: Extended;
begin
  if not VST.HasChildren[Node] then Exit;
  Data := VST.GetNodeData(Node);
  if Data = nil then Exit;
  CostSum := 0.0;
  ChildNode := VST.GetFirstChild(Node);
  while Assigned(ChildNode) do
  begin
    ChildData := VST.GetNodeData(ChildNode);
    if ChildData <> nil then
    begin
      CalculateSum(ChildNode);
      if TryStrToFloat(ChildData.Cost, Cost) then
        CostSum := CostSum + Cost;
      // or:
      // CostSum := CostSum + StrToFloatDef(ChildData.Cost, 0.0);
    end;
    ChildNode := VST.GetNextSibling(ChildNode);
  end;
  Data.Cost := FloatToStr(CostSum);
end;

话虽如此,我还是建议将TMyNodeData.Cost存储为Double/Extended而不是UnicodeString,所有这些转换都是不必要的开销。
试试这个:

Type
  PMyNodeData = ^TMyNodeData;
  TMyNodeData = record
    Cost: Extended; 
  end;

...

procedure CalculateSum(Node: PVirtualNode);
var
  Data, ChildData: PMyNodeData;
  ChildNode: PVirtualNode;
  CostSum: Extended;
begin
  if not VST.HasChildren[Node] then Exit;
  Data := VST.GetNodeData(Node);
  if Data = nil then Exit;
  CostSum := 0.0;
  ChildNode := VST.GetFirstChild(Node);
  while Assigned(ChildNode) do
  begin
    ChildData := VST.GetNodeData(ChildNode);
    if ChildData <> nil then
    begin
      CalculateSum(ChildNode);
      CostSum := CostSum + ChildData.Cost;
    end;
    ChildNode := VST.GetNextSibling(ChildNode);
  end;
  Data.Cost := CostSum;
end;
bcs8qyzn

bcs8qyzn2#

我已经解决了这个问题作为下一个:

procedure CalculateSum(Node: PVirtualNode);
var
  Data: PMyNodeData;
  ChildNode: PVirtualNode;
  ChildData: PMyNodeData;
  CostSum: Extended;
begin
  Data := VST.GetNodeData(Node);
  if data<>nil then
  CostSum := Data.Cost else Costsum:=0.0;
  ChildNode := VST.GetFirstChild(Node);
  while Assigned(ChildNode) do
  begin
    ChildData := VST.GetNodeData(ChildNode);
    if ChildData <> nil then
    begin
      CalculateSum(ChildNode);
      CostSum := CostSum + ChildData.Cost;
    end;
    ChildNode := VST.GetNextSibling(ChildNode);
  end;
  if (VST.HasChildren[Node]) and (Data<>nil) then
    Data.Cost := CostSum;

end;

相关问题