在链表中插入元素(InsertElement 项目引发异常 class 'External: SIGSEGV' )

Inserting element in a linked list (Project InsertElement raised exception class 'External: SIGSEGV' )

我写了这个程序,它应该从用户输入创建一个整数链表,直到用户插入“0”,打印它,在它的末尾添加一个元素,然后再次打印链表,包括添加的元素。

当我 运行 它时,输入和第一个输出工作正常,但是当涉及到添加新元素时,我收到以下错误消息:

"Project InsertElement raised exception class 'External: SIGSEGV' in file 'InsertElement.lpr' at line 66: OutRefEnd^.next := RefNew;"

很明显,第66行有问题:

OutRefEnd^.next := RefNew;

但我无法弄清楚那个问题是什么,它是否与我的代码有关,或者它是否只是编译器。据我所知,错误代码暗示 'outRefEnd^.next'` 指向一个空地址,但由于我为其分配了值 'RefNew',我不太明白为什么这应该是第一名.

有人可以提示我哪里出错了吗?

这是我的代码:

program InserElement(input, output);
    {Has the user type in integers and forms a linked list out of them,
    then inserts an element at the end of that linked list and prints the
    linked list with the added new element}

    {$mode objfpc}{$H+}

    uses
      {$IFDEF UNIX}{$IFDEF UseCThreads}
      cthreads,
      {$ENDIF}{$ENDIF}
      Classes;

    type
      tRefList = ^tList;
      tList = record
                 info : integer;
                 next : tRefList
                end;
    var
     RefBeginning: tRefList;
     RefEnd : tRefList;
     Pointer : tRefList;
     Number : integer;



       procedure CreateList( var outRefBeginning: tRefList);
       { Creates a linear list through user input }


      begin
       readln(Number);
       while Number <> 0 do
       begin
         new (Pointer);
         Pointer^.info := Number;
         Pointer^.next := outRefBeginning;
         outRefBeginning := Pointer;
         readln (Number)
       end { while-loop }
      end; {CreateList}

    procedure InsertElement(inNumber : integer; var outRefBeginning : tRefList; var outRefEnd : tRefList);
      { Inserts a new element at the end of the list. outRefBeginning points to the first
      element of that list, outRefEnd points to the last element of it. The Value of inNumber is
      assigned to the record component info of the new element}

      var
       RefNew : tRefList;

      begin
      { Create and initialise new element }
      new(RefNew);
      RefNew^.info := inNumber;
      RefNew^.next := nil;
      { Insert element at the end of the linear list }
      if outRefBeginning = nil then
         begin
         outRefBeginning := RefNew;
         outRefEnd := RefNew
         end
         else
             begin
               outRefEnd^.next := RefNew;
               outRefEnd := RefNew;
             end;
      end;{ InsertElement }

      procedure PrintList;
      { Prints all elements of the linked list }

      var
       RefNew : tRefList;

      begin
       RefNew := RefBeginning;
       while RefNew <>  nil do
       begin
         writeln (RefNew^.info);
         RefNew := RefNew^.next
       end;
      end;

    begin
      RefBeginning := nil;
      RefEnd := RefBeginning;
      CreateList(RefBeginning);
      PrintList;
      InsertElement(5,RefBeginning,RefEnd);
      PrintList;
      readln;
    end.

[编辑] 对于任何感兴趣的人,我将在下面粘贴更正后的代码,我根据汤姆的回答中的建议进行了更改。

变化:

  1. 我删除了指针变量,因为不再需要它:

    var
     RefBeginning: tRefList;
     RefEnd : tRefList;
     Number : integer;
    
  2. 我将 procedure CreateList 更改为类似于 procedure InsertElement,因为它不仅在 RefBeginning 中而且在 [= 中保存了新元素的值20=]:

     procedure CreateList(var outRefBeginning: tRefList; var OutRefEnd:  tRefList);
           { Creates a linear list through user input }
          var
           RefNew : tRefList;`
    
      begin
       writeln('Please key in natural numbers. Key in 0 once you are done. ');
       readln(Number);
       while Number <> 0 do
       begin
         new (RefNew);
         RefNew^.info := Number;
         RefNew^.next := nil;
         if outRefBeginning = nil then
          begin
          outRefBeginning := RefNew;
          OutRefEnd := RefNew;
          end
         else
         begin
           outRefEnd^.next := RefNew;
           outRefEnd := RefNew
         end;
         readln (Number)
       end; { while-loop }
      end; {CreateList}   
    

    最后但同样重要的是,这是完整的代码:

    program InserElement(input, output);
        {Has the user type in integers and forms a linked list out of them,
        then inserts an element at the end of that linked list and prints the
        linked list with the added new element}
    
    {$mode objfpc}{$H+}
    
    uses
      {$IFDEF UNIX}{$IFDEF UseCThreads}
      cthreads,
      {$ENDIF}{$ENDIF}
      Classes;
    
    type
      tRefList = ^tList;
      tList = record
                 info : integer;
                 next : tRefList
                end;
    var
     RefBeginning: tRefList;
     RefEnd : tRefList;
     Number : integer;
    
    
    
       procedure CreateList(var outRefBeginning: tRefList; var OutRefEnd: tRefList);
       { Creates a linear list through user input }
      var
       RefNew : tRefList;
    
      begin
       writeln('Please key in natural numbers. Key in 0 once you are done. ');
       readln(Number);
       while Number <> 0 do
       begin
         new (RefNew);
         RefNew^.info := Number;
         RefNew^.next := nil;
         if outRefBeginning = nil then
          begin
          outRefBeginning := RefNew;
          OutRefEnd := RefNew;
          end
         else
         begin
           outRefEnd^.next := RefNew;
           outRefEnd := RefNew
         end;
         readln (Number)
       end; { while-loop }
      end; {CreateList}
    
    procedure InsertElement(inNumber : integer; var outRefBeginning : tRefList; var outRefEnd : tRefList);
      { Inserts a new element at the end of the list. outRefBeginning points to the first
      element of that list, outRefEnd points to the last element of it. The Value of inNumber is
      assigned to the record component info of the new element}
    
      var
       RefNew : tRefList;
    
      begin
      { Create and initialise new element }
      new(RefNew);
      RefNew^.info := inNumber;
      RefNew^.next := nil;
      { Insert element at the end of the linear list }
      if outRefBeginning = nil then
         begin
         outRefBeginning := RefNew;
         outRefEnd := RefNew
         end
         else
             begin
               outRefEnd^.next := RefNew;
               outRefEnd := RefNew;
             end;
      end;{ InsertElement }
    
      procedure PrintList;
      { Prints all elements of the linked list }
    
      var
       RefNew : tRefList;
    
      begin
       RefNew := RefBeginning;
       while RefNew <>  nil do
       begin
         writeln (RefNew^.info);
         RefNew := RefNew^.next
       end;
      end;
    
    begin
      RefBeginning := nil;
      RefEnd := nil;
      CreateList(RefBeginning, RefEnd);
      InsertElement(5,RefBeginning,RefEnd);
      PrintList;
      readln;
    end.
    

您在 procedure CreateList(); 中出错,因为您将新记录添加到开头而不是结尾。 RefEndCreateList() 之后仍然是 nil

当您随后使用 RefEnd = nil 调用 InsertElement(5,RefBeginning,RefEnd); 时,由于参数 outRefEnd 为零,因此在行 outRefEnd^.next := RefNew; 上触发了错误。

您应该更正 CreateList() 程序,使其基本上与 InsertElement 类似,将初始项目链接到 outRefBeginningoutRefEnd 并将后续新项目链接到 outRefEnd.