您如何检查对象Pascal / Delphi中的记录指针是否没有值?

问题描述 投票:0回答:1

我试图在Delphi中创建一个链表实现,但是无法创建节点,因为我需要检查头指针是否为空。我现在正在使用的代码如下所示:

procedure LinkedList.addNode(newNode: Node);
var lastNode: Node;
begin
if pHead = nil then
  pHead := @newNode
else
   lastNode := peekLastNode(pHead^);
   lastNode.pNext := @newNode;
end;

仅添加一个元素,程序就会冻结,因此,无数部分是无限期的问题。

这里是整个程序:

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.
pointers delphi pascal
1个回答
0
投票

addNode()中,如果pHeadnil,则将其设置为指向局部变量,如果不是nil,则将其设置为lastNode.pNext指向另一个局部变量。当addNode()退出时,这些局部变量将超出范围,从而使pHead / pNext悬空,因此它们将在您下次尝试使用它们时指向无效的内存。

[将Node实例添加到列表时,需要使用堆分配,并且需要传递^Node指针,而不是直接传递Node实例。

[此外,addNode()具有逻辑错误,因为它无条件设置lastNode.pNext是否为pHeadnil。如果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;
var
  newNode, lastNode: PNode;
begin
  New(newNode);
  newNode.data := data;
  newNode.pNext := nil;
  if pHead = nil then
    pHead := newNode
  else begin
    lastNode := peekLastNode(pHead);
    lastNode.pNext := newNode;
  end;
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;
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.
© www.soinside.com 2019 - 2024. All rights reserved.