Не могу понять, как работает вызов из программы скомпилированного модуля для работы с двусвязным списком. Взял для разбора темы пример готового модуля и программы для его тестирования. Модуль скомпилировал. Куда он должен быть помещен? При запуске программы тестирования появляется ошибка, что не задана ссылка на объект. И программа не на модуль ссылается, а на его исходник. Что не так?
Прилагайте всегда исходники. Код или в данном случае лучше файлами (в папке выделяете и в окно ответа перетягиваете). Совершенно не понятно что не так.
А куда она должна ссылаться и как?
Не могу исходники добавить, пишет: нельзя новичкам добавлять файлы. Только рисунок разрешил добавить. А скомпилированный модуль куда нужно поместить?
Interface
{uses maintype;}
Type
Telem = integer;
TList = ^TElement;
TElement = Record
Data : Telem;
Next, Prev : TList;
End;
{процедура инициализирует список и добавляетпервый элемент}
Procedure InitListAndAddFirst(X : Telem; var L:Tlist );
{добавление в НЕПУСТОЙ список -ПОСЛЕ элемента на который указывает L}
Procedure AddAfter(X : Telem; Var L : TList);
{переход кконцу списка}
Procedure GotoLast(var l:tlist);
{к началу}
Procedure GotoFirst(var l:tlist);
{печать}
Procedure ListPrint(l:Tlist);
{уничтожение}
Procedure ListDestroy(var l:tlist);
IMPLEMENTATION
Procedure InitListAndAddFirst(X : Telem; var L:Tlist );
begin
New(L);
L:=Nil;
//L:=New(TList);
L^.Next:=Nil;
L^.Prev:=Nil;
L^.Data:=X; {создаем первый элемент}
end;
Procedure AddAfter(X : Telem; Var L : TList); {добавление в НЕПУСТОЙ список}
Var P : TList;
Begin
if l<>nil then
begin
New(P);
//P:=New(TList); {создаем элемент}
P^.Data:=X;
If (L^.Next = Nil) Then {надо добавить элемент в конец списка}
Begin
L^.Next:=P;
P^.Prev:=L;
P^.Next:=Nil;
End Else
Begin {надо вставить элемент между двумя}
P^.Next:=L^.Next;
L^.Next^.Prev:=P;
P^.Prev:=L;
L^.Next:=P;
End;
end else writeln('Error!');
End;
Procedure GotoLast(var l:tlist);
begin
While L^.next <> Nil Do L:=L^.Next
end;
Procedure GotoFirst(var l:tlist);
begin
While L^.Prev<>NIL Do L:=L^.Prev
end;
Procedure ListPrint(l:Tlist);
begin
While L^.prev <> Nil Do L:=L^.prev;
While L <> Nil Do
begin
write(L^.data, ' ');
L:=L^.next
end
end;
Procedure ListDestroy(var l:tlist);
var
p:Tlist;
begin
While L^.Next <> Nil Do L:=L^.Next;
While L <> Nil Do
Begin
P:=L;
L:=L^.Prev;
Dispose(P);
End;
end;
end.
uses crt, dlist;
var
L:tlist;
begin
writeln('Программа,тестирующая модуль DList для работы с двусвязными списками');
writeln('Добавляем первый элемент,список инициализируется автоматически...');
InitListAndAddFirst(1,L);
writeln('Теперь добавим элемент 2 после того,на который указывал L... (AddAfter)');
AddAfter(2,l);
writeln(' ... и перейдем к концу списка, чтобы добавлять после последнего...(GotoLast)');
GotoLast(l);
AddAfter(3,l); GotoLast(l); {... }
AddAfter(4,l); GotoLast(l); { ... }
AddAfter(5,l); GotoLast(l); { ...}
writeln('Полученный список (после добавления в конец) (listprint)');
ListPrint(L);
writeln('... вставим после 4 элемент 6');
writeln('Для этого идем в начало списка(GotoFirst) и ищем элемент 4 ... ');
gotoFirst(l); {в начало}
while (l^.data<>4)and (l^.next<>nil) do l:=l^.next; {ищем}
writeln;
writeln('Нашли, добавляем... ');
addafter(6,l);
writeln('...вот, что у нас получилось (ListPrint) :');
ListPrint(L);
writeln('Уничтожаем список, очищая память. (ListDestroy)');
ListDestroy(L);
end.
Ну тогда вставьте кодом, как то так:
Код Program9:
```
uses dlist;
begin
end.
```
Будет выглядеть так:
Код Program9:
uses dlist;
begin
end.
И так же с модулем. Знак ` находится в англ. раскладке за ё.
Первая строка модуля пропала что-то Unit DList;
Модуль DList:
Interface
{uses maintype;}
Type
Telem = integer;
TList = ^TElement;
TElement = Record
Data : Telem;
Next, Prev : TList;
End;
{процедура инициализирует список и добавляетпервый элемент}
Procedure InitListAndAddFirst(X : Telem; var L:Tlist );
{добавление в НЕПУСТОЙ список -ПОСЛЕ элемента на который указывает L}
Procedure AddAfter(X : Telem; Var L : TList);
{переход кконцу списка}
Procedure GotoLast(var l:tlist);
{к началу}
Procedure GotoFirst(var l:tlist);
{печать}
Procedure ListPrint(l:Tlist);
{уничтожение}
Procedure ListDestroy(var l:tlist);
IMPLEMENTATION
Procedure InitListAndAddFirst(X : Telem; var L:Tlist );
begin
New(L);
L:=Nil;
//L:=New(TList);
L^.Next:=Nil;
L^.Prev:=Nil;
L^.Data:=X; {создаем первый элемент}
end;
Procedure AddAfter(X : Telem; Var L : TList); {добавление в НЕПУСТОЙ список}
Var P : TList;
Begin
if l<>nil then
begin
New(P);
//P:=New(TList); {создаем элемент}
P^.Data:=X;
If (L^.Next = Nil) Then {надо добавить элемент в конец списка}
Begin
L^.Next:=P;
P^.Prev:=L;
P^.Next:=Nil;
End Else
Begin {надо вставить элемент между двумя}
P^.Next:=L^.Next;
L^.Next^.Prev:=P;
P^.Prev:=L;
L^.Next:=P;
End;
end else writeln('Error!');
End;
Procedure GotoLast(var l:tlist);
begin
While L^.next <> Nil Do L:=L^.Next
end;
Procedure GotoFirst(var l:tlist);
begin
While L^.Prev<>NIL Do L:=L^.Prev
end;
Procedure ListPrint(l:Tlist);
begin
While L^.prev <> Nil Do L:=L^.prev;
While L <> Nil Do
begin
write(L^.data, ' ');
L:=L^.next
end
end;
Procedure ListDestroy(var l:tlist);
var
p:Tlist;
begin
While L^.Next <> Nil Do L:=L^.Next;
While L <> Nil Do
Begin
P:=L;
L:=L^.Prev;
Dispose(P);
End;
end;
end.```
Ну смотрите:
Ошибка времени выполнения: System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
Стек:
в DList.DList.InitListAndAddFirst(Int32 X, TElement*& L) в C:\PABCWork.NET\dlist.pas:строка 33
в Program1.Program.$Main() в C:\PABCWork.NET\Program1.pas:строка 7
в Program1.Program.Main()
Читаем снизу вверх:
в Program1.Program.$Main() в C:\PABCWork.NET\Program1.pas:строка 7
То есть ошибка была когда программа дошла до 7 строчки в основной программе (у меня она Program 1 а не 9, но не суть) и при её выполнении случилась ошибка. Дальше:
в DList.DList.InitListAndAddFirst(Int32 X, TElement*& L) в C:\PABCWork.NET\dlist.pas:строка 33
Значит что более подробно - ошибка произошла при выполнении процедуры InitListAndAddFirst
, на строчке 33. На этом стек ошибки заканчивается значит эта та строчка что вызвала ошибку. Смотрим в эту процедуру:
procedure InitListAndAddFirst(X: Telem; var L: Tlist );
begin
New(L);
L := nil;
//L:=New(TList);
L^.Next := nil;
L^.Prev := nil;
L^.Data := X; {создаем первый элемент}
end;
В эту процедуру передаётся 1
и пустой указатель (со строчки 7 основной программы), тот указатель создаётся, обнуляется и после этого на строчке L^.Next := nil
вызывается System.NullReferenceException
потому что L
ни на что не ссылается.
И знаки ``` надо ставить на отдельную строчку, то есть:
```Unit DList;
Сотрёт эту строчку, и ещё:
end.```
Тут ``` вообще не сработало, потому что кроме него на строчки ещё end.
.
А как нужно?
Как правильно в модуле должно быть?
Вы про ``` или про вашу программу?
про программу
Ну надо же чтоб указатель на что то ссылался, инициализировать его, после чего не уничтожив через L := nil
. А вообще я бы рекомендовал для начала больше разобраться в теории. И указатели в паскале очень ограничены, лучше используйте классы или пишите на одном из C
языков.
Спасибо.