Y
yancaoshi
Unregistered / Unconfirmed
GUEST, unregistred user!
我的目的是生成树,打算由根节点通过递归方法创建子节点,并且只能从未用过的字段中选择作为节点名称,现在问题出在创建子节点时回溯收集父节点的名称上。最好不要告诉我换一个方法,而希望能帮我分析一下为什么出错:肯定指针没用好。我只是个中途入门者,所以基础方面比较欠缺,在写程序的时候说不定就犯比较低级的错误。
我简化了自己的单元文件,大家直接粘贴一下,Form上添加一个按钮就可以调试了,看上去是死循环——实际上的确是死循环,不要F9运行,单步调试好了,创建了一个子节点后到GetUsedField过程就出错了。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
PNode = ^TNode;
TNode = class
public
UsedField: string;
Parent: PNode
// 指向父亲节点
Childs: array of PNode
//指向各子节点
function GetUsedFields: string
//获取到此节点已经用过的字段
function CreateChild(AField: string
Creator: TNode): PNode;
procedure Test;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
FirstNode: PNode;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
FirstField: string;
FirstChild: PNode;
begin
New(FirstNode); //FirstNode是全局变量
FirstNode^ := TNode.Create;
FirstNode.UsedField := 'A';
FirstNode.Parent := nil;
FirstField := 'B';
FirstChild := FirstNode.CreateChild(FirstField, FirstNode^);
FirstChild.Test;
end;
{ TNode }
function TNode.CreateChild(AField: string
Creator: TNode): PNode;
var
NewNode: PNode;
begin
New(NewNode);
NewNode^ := TNode.Create;
NewNode.UsedField := AField;
NewNode.Parent := @Creator;
SetLength(Creator.Childs, Length(Creator.Childs) + 1);
Creator.Childs[High(Creator.Childs)] := NewNode;
Result := NewNode;
end;
function TNode.GetUsedFields: string;
var
NodeAddr: PNode;
begin
NodeAddr := @Self;
if NodeAddr.Parent = nil then
begin
Result := '';
end
else
begin
Result := NodeAddr.UsedField;
NodeAddr := NodeAddr.Parent
//这里出错,得到的其实不是FirstNode了
while NodeAddr <> nil do
begin
Result := ',' + NodeAddr.UsedField;
NodeAddr := NodeAddr.Parent;
end;
end;
end;
procedure TNode.Test;
var
SelectedField: string;
Used: string;
begin
Used := GetUsedFields;
//省略了一些语句,作用是根据Used得到未用过的字段,赋一个固定字符串也行
SelectedField := 'ft'
//假设赋'ft'
CreateChild(SelectedField, Self).Test;
end;
end.
我简化了自己的单元文件,大家直接粘贴一下,Form上添加一个按钮就可以调试了,看上去是死循环——实际上的确是死循环,不要F9运行,单步调试好了,创建了一个子节点后到GetUsedField过程就出错了。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
PNode = ^TNode;
TNode = class
public
UsedField: string;
Parent: PNode
// 指向父亲节点
Childs: array of PNode
//指向各子节点
function GetUsedFields: string
//获取到此节点已经用过的字段
function CreateChild(AField: string
Creator: TNode): PNode;
procedure Test;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
FirstNode: PNode;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
FirstField: string;
FirstChild: PNode;
begin
New(FirstNode); //FirstNode是全局变量
FirstNode^ := TNode.Create;
FirstNode.UsedField := 'A';
FirstNode.Parent := nil;
FirstField := 'B';
FirstChild := FirstNode.CreateChild(FirstField, FirstNode^);
FirstChild.Test;
end;
{ TNode }
function TNode.CreateChild(AField: string
Creator: TNode): PNode;
var
NewNode: PNode;
begin
New(NewNode);
NewNode^ := TNode.Create;
NewNode.UsedField := AField;
NewNode.Parent := @Creator;
SetLength(Creator.Childs, Length(Creator.Childs) + 1);
Creator.Childs[High(Creator.Childs)] := NewNode;
Result := NewNode;
end;
function TNode.GetUsedFields: string;
var
NodeAddr: PNode;
begin
NodeAddr := @Self;
if NodeAddr.Parent = nil then
begin
Result := '';
end
else
begin
Result := NodeAddr.UsedField;
NodeAddr := NodeAddr.Parent
//这里出错,得到的其实不是FirstNode了
while NodeAddr <> nil do
begin
Result := ',' + NodeAddr.UsedField;
NodeAddr := NodeAddr.Parent;
end;
end;
end;
procedure TNode.Test;
var
SelectedField: string;
Used: string;
begin
Used := GetUsedFields;
//省略了一些语句,作用是根据Used得到未用过的字段,赋一个固定字符串也行
SelectedField := 'ft'
//假设赋'ft'
CreateChild(SelectedField, Self).Test;
end;
end.