[求助]误入了歧途?关于链表和指针 ( 积分: 100 )

  • 主题发起人 主题发起人 yancaoshi
  • 开始时间 开始时间
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.
 
楼主还真是简化了,TSubentry呢

说实在的,确实很乱,感觉没必要非这么做,先贴代码吧
 
对象其实就是指针,所有PNode的地方都用TNode。
NodeAddr := @Self
=> NodeAddr := Self;
 
lichengbin来了我就没分了,溜先[:D]
 
lichenbin和chenbin有什么联系和区别啊?
 
看清楚了,是lichengbin和chenybin,没啥关系[:D]
^^^^^ ^^^^^
 
他在的帖子我基本不得分,所以要溜[:D]

楼主还是贴那个类的代码吧,我水平低些,需要多看点代码才行
 
后退
顶部