nei*_*rds 1 delphi pascal pointers
我正在尝试在 Delphi 中创建一个链表实现,但无法创建节点,因为我需要检查头指针是否为空。我现在使用的代码如下所示:
procedure LinkedList.addNode(newNode: Node);
var lastNode: Node;
begin
if pHead = nil then
pHead := @newNode
else
lastNode := peekLastNode(pHead^);
lastNode.pNext := @newNode;
end;
Run Code Online (Sandbox Code Playgroud)
程序在添加一个元素后就冻结了,所以 nil 部分是无限期的问题。
这是整个程序:
program LinkedListImplementation;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
Node = record
data: string;
pNext: ^Node;
end;
type
LinkedList = class
pHead: ^Node;
function peekLastNode (currentNode: Node) : Node;
function listToString(currentNode: Node) : String;
procedure addNode (newNode: Node);
end;
//the initial parameter for this function is LinkedList.pHead^
function LinkedList.peekLastNode (currentNode: Node) : Node;
begin
if currentNode.pNext = nil then
result := currentNode
else
result := peekLastNode(currentNode.pNext^);
end;
//produces string in form 'abc -> def -> ghi' from linked list
function LinkedList.listToString(currentNode: Node) : String;
begin
if currentNode.pNext = nil then
result := currentNode.data
else
result := currentNode.data + ' -> ' + listToString(currentNode.pNext^)
end;
//this uses helper method 'peekLastNode'
procedure LinkedList.addNode(newNode: Node);
var lastNode: Node;
begin
if pHead = nil then
pHead := @newNode
else
lastNode := peekLastNode(pHead^);
lastNode.pNext := @newNode;
end;
var
Strings: LinkedList;
String1: Node;
String2: Node;
begin
try
String1.data := 'abc';
String2.data := 'def';
Strings.Create();
Strings.addNode(String1);
Strings.addNode(String2);
WriteLn(Strings.listToString(Strings.pHead^));
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
在addNode(), 如果pHead是nil那么你将它设置为指向一个局部变量,如果不是nil那么你设置lastNode.pNext为指向另一个局部变量。这些局部变量在addNode()退出时超出范围,从而离开pHead/pNext悬空,以便下次尝试使用它们时它们指向无效内存。
将Node实例添加到列表时需要使用堆分配,并且需要传递^Node指针而不是Node直接传递实例。
此外,addNode()有一个逻辑错误,因为它lastNode.pNext无条件地设置是否pHead是nil。如果PHEAD是nil那么lastNode没有分配任何东西。该else块缺少有关begin..end其操作的语句。
此外,您甚至没有LinkedList正确构建对象。 Strings.Create();需要Strings := LinkedList.Create();改为。
话虽如此,请尝试更像这样的事情:
program LinkedListImplementation;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
PNode = ^Node;
Node = record
data: string;
pNext: PNode;
end;
type
LinkedList = class
private
pHead: PNode;
public
destructor Destroy; override;
function peekLastNode(currentNode: PNode = nil): PNode;
function listToString(currentNode: PNode = nil): String;
function addNode(const data: String): PNode;
procedure clear;
end;
destructor LinkedList.Destroy;
begin
clear;
end;
//the initial parameter for this function is LinkedList.pHead
function LinkedList.peekLastNode(currentNode: PNode) : PNode;
begin
if currentNode = nil then currentNode := pHead;
if (currentNode = nil) or (currentNode.pNext = nil) then
Result := currentNode
else
Result := peekLastNode(currentNode.pNext);
end;
{ Alternatively:
function LinkedList.peekLastNode(currentNode: PNode): PNode;
begin
if currentNode = nil then currentNode := pHead;
Result := currentNode;
if Result <> nil then
begin
while Result.pNext <> nil do
Result := Result.pNext;
end;
end;
}
//produces string in form 'abc -> def -> ghi' from linked list
function LinkedList.listToString(currentNode: PNode): String;
begin
if currentNode = nil then currentNode := pHead;
if currentNode = nil then
Result := ''
else if currentNode.pNext = nil then
Result := currentNode.data
else
Result := currentNode.data + ' -> ' + listToString(currentNode.pNext);
end;
{ Alternatively:
function LinkedList.listToString(currentNode: PNode): String;
begin
Result := '';
if currentNode = nil then currentNode := pHead;
if currentNode <> nil then
begin
Result := currentNode.data;
while currentNode.pNext <> nil do
begin
currentNode := currentNode.pNext;
Result := Result + ' -> ' + currentNode.data;
end;
end;
end;
}
//this uses helper method 'peekLastNode'
function LinkedList.addNode(const data: String): PNode;
begin
New(Result);
Result.data := data;
Result.pNext := nil;
if pHead = nil then
pHead := Result
else
peekLastNode(pHead).pNext := Result;
end;
{ Alternatively:
function LinkedList.addNode(const data: String): PNode;
var
currentNode: ^PNode;
begin
currentNode := @pHead;
while currentNode^ <> nil do
currentNode := @((currentNode^).pNext);
New(currentNode^);
(currentNode^).data := data;
(currentNode^).pNext := nil;
Result := currentNode^;
end;
}
procedure LinkedList.clear;
var
currentNode, nextNode: PNode;
begin
currentNode := pHead;
while currentNode <> nil do
begin
nextNode := currentNode.pNext;
Dispose(currentNode);
currentNode := nextNode;
end;
end;
var
Strings: LinkedList;
begin
try
Strings := LinkedList.Create();
try
Strings.addNode('abc');
Strings.addNode('def');
WriteLn(Strings.listToString());
finally
Strings.Free();
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
245 次 |
| 最近记录: |