Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 753

/ вопрос закрыт /

Доброго времени суток, уважаемые эксперты!

Совсем недавно начал работать с динамическими массивами.
Пытаюсь в цикле вставлять данные в динамический массив (изменяя, при необходимости, его размерность).
Однако, при попытке изменить размерность массива, получаю ошибку ("Runtime error 216 at ...").
Что я делаю не так?
Код прилагаю.

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

Приложение:
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. procedure FormCreate(Sender: TObject);
  12. private
  13. { Private declarations }
  14. public
  15. { Public declarations }
  16. end;
  17.  
  18. t_Point = ^t_LIST;
  19. t_LIST = record
  20. TYPE_POINT : byte;
  21. case byte of
  22. 0:(
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31. );
  32. 1: (
  33. STR:string[54];
  34. )
  35. end; //t_LIST
  36.  
  37. t_MASS = array of t_Point;
  38.  
  39. t_REC = record
  40.  
  41.  
  42.  
  43. MASS : t_MASS; //
  44. end;
  45.  
  46.  
  47. var
  48. Form1: TForm1;
  49. MASSTAT : t_REC;
  50. PL : t_Point;
  51. implementation
  52.  
  53. {$R *.dfm}
  54.  
  55. function GetPoint(TYPE_POINT : integer):t_POINT;
  56. var P : t_Point; var size : integer;
  57. begin
  58. try
  59. size := SizeOf(t_LIST);
  60. new(P);
  61. FillChar(p^,size,0);
  62. p.TYPE_POINT := TYPE_POINT;
  63. p.CH1 := char(SizeOf(p.STR)-1);
  64. except
  65. size := size;
  66. end;
  67. GetPoint := p;
  68. end; // GetPoint
  69.  
  70. procedure FreePoint(var P : t_POINT);
  71. begin
  72. if P = nil then exit;
  73. case p.TYPE_POINT of
  74. 0: ;
  75. 1: ;
  76. else
  77.  
  78. end;// case
  79. Dispose(P);
  80. P := nil;
  81. end; // FreePoint
  82.  
  83. procedure AddRecPoint(var REC : t_REC; TYPE_POINT,NUMB:integer);
  84. var I:integer;
  85. begin
  86. REC.NUMB_MAX := REC.NUMB_MAX+ NUMB;
  87. try
  88. SetLength(REC.MASS,REC.NUMB_MAX);
  89. except
  90. REC.NUMB_MAX := REC.NUMB_MAX;
  91. end;
  92.  
  93. REC.TYPE_REC := TYPE_POINT;
  94. end; //AddRecPoint
  95.  
  96. procedure FreeRecPoint(var REC : t_REC);
  97. var I : integer;
  98. begin
  99. for i := 0 to REC.NUMB_MAX -1 do
  100. if REC.MASS[i] <> nil then
  101. begin
  102. FreePoint(REC.MASS[i]);
  103. end;
  104. SetLength(REC.MASS,0);
  105. REC.IMAX := -1;
  106. REC.NUMB_MAX := 0;
  107. end;// procedure FreeRecPoint(var REC : t_REC);
  108.  
  109.  
  110.  
  111. function AddPoint(var REC : t_REC; P : t_Point; var N : integer) : boolean;
  112. begin
  113.  
  114.  
  115. if N <= REC.IMAX then
  116. move(REC.MASS[N+1],REC.MASS[N+2],SizeOf(t_Point)*(REC.IMAX-N+1));
  117. inc(REC.IMAX);
  118. N := N+1;
  119. REC.MASS[N] := GetPoint(P.TYPE_POINT);
  120. REC.MASS[N]^ := P^;
  121. Result := true;
  122. end;// AddPoint(REC : t_REC; P : t_Point) : boolean;
  123.  
  124.  
  125. procedure TForm1.FormCreate(Sender: TObject);
  126. var i,L : integer; B : boolean;
  127. begin
  128. FreeRecPoint(MASSTAT);
  129. PL := GetPoint(0);
  130. for I := 1 to 10 do
  131. begin
  132. FillChar(PL^,SizeOf(PL^),0);
  133. PL.CH1 := char(SizeOf(PL.STR));
  134. PL.NAMESTR := IntToStr(I);
  135. L := -1;
  136. B := AddPoint(MASSTAT,PL,L);
  137.  
  138. end;
  139.  
  140. end;
  141.  
  142. end.
  143.  


vsorokin Вопрос закрыт (ответы не принимаются, мини-форум закрыт)

Вопрос задал: vsorokin (статус: Посетитель)
Вопрос отправлен: 21 ноября 2010, 16:47
Состояние вопроса: закрыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 17; последнее сообщение — 22 ноября 2010, 21:15; участников в обсуждении: 5.
6ruse

6ruse (статус: 1-ый класс), 22 ноября 2010, 06:35 [#1]:

Доброго времени суток! Вы немного не правильно изменяете размерность массива. Нужно так
SetLength(массив, length(массив)+length(на сколько увеличиваем));
что то вроде этого.
min@y™

min@y™ (статус: Доктор наук), 22 ноября 2010, 08:53 [#2]:

Цитата (vsorokin):

Что я делаю не так?

Ты используешь дин. массив не в той задаче.
Здесь нужен список указателей TObjectList.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 09:41 [#3]:

6ruse:
procedure AddRecPoint(var REC : t_REC; TYPE_POINT,NUMB:integer);
 var I:integer;
begin
 // REC.NUMB_MAX := REC.NUMB_MAX+ NUMB;
  try
   SetLength(REC.MASS,Length(REC.MASS) + NUMB);
  except
    REC.NUMB_MAX := REC.NUMB_MAX;
  end;
  REC.NUMB_MAX := Length(REC.MASS);
  REC.TYPE_REC := TYPE_POINT;
end; //AddRecPoint
дает такой же результат (ошибку при повторном вызове SetLength(REC.MASS,Length(REC.MASS) + NUMB))

min@y™:

Не вполне понятно, зачем мне нужен список указателей TObjectList ? Как его использовать?
Ведь я всего-навсего хочу использовать изменяемый во время выполнения динамический массив ссылок.
min@y™

min@y™ (статус: Доктор наук), 22 ноября 2010, 10:09 [#4]:

Цитата (vsorokin):

Не вполне понятно, зачем мне нужен список указателей TObjectList ? Как его использовать? Ведь я всего-навсего хочу использовать изменяемый во время выполнения динамический массив ссылок.

Именно так. Для этих целей и служит TObjectList.
Переделай свой record в класс. Тогда у тебя будет возможность ОЧЕНЬ СИЛЬНО упростить и сократить твой код. Первоочередная задача — решиться похерить то, что ты уже написал. Я понимаю, что это трудно, но себя нужно преодолеть, и тогда всё получится, поверь мне!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 11:59 [#5]:

Уважаемый эксперт min@y™:
Наверняка, все можно переписать правильно с т.з. классического ООП.
Я привел здесь небольшой фрагмент программы. У меня возникла проблема, связанная с изменением длины динамического массива. Раньше я такие массивы не использовал.
Хотелось бы понять, в чем моя ошибка именно при применении динамического массива? В частности, функции SetLength.

P.S. Буду также признателен, если Вы покажете, как можно в моем случае использовать TObjectList. :)
min@y™

min@y™ (статус: Доктор наук), 22 ноября 2010, 13:27 [#6]:

Цитата:


Буду также признателен, если Вы покажете, как можно в моем случае использовать TObjectList. :)

Если ты готов отказаться от дин. массивов - напишу тебе примерчик. Я уверен, что в данном случае тебе нужно выкинуть дин. массивы.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 13:50 [#7]:

min@y™: Готов отказаться от дин. массивов!

Однако, в конечном счете, мне нужно получить массив ссылок на t_Point = ^t_LIST. Этот массив использую для сортировки и быстрого поиска нужной информации. (В предыдущей версии программы я успешно использовал статический массив).
Однако, появилась необходимость иметь возможность быстро изменять его (массива) размер в процессе выполнения программы. Поэтому, и попробовал с минимальными изменениями в программе перейти от статического к динамическому массиву.
И вдруг - облом. :(
Вадим К

Вадим К (статус: Академик), 22 ноября 2010, 13:53 [#8]:

Можно конечно переписать код, тут действительно нужно переписать, так как код сильно сдобренный указателями.

Но может все таки на этих костылях построить что то чуточку рабочее, а потом аккуратно уже переписывать на правильное и работающее.

первое, что хотелось уточнить - ошибка возникает при первой же попытке выставить размер или во время работы?
второе - какая версия делфи.
Галочка "подтверждения прочтения" - вселенское зло.
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 13:59 [#9]:

Вадим К:
У меня Дельфи 7.
Ошибка возникает во время работы при вторичном (третьем и т.д.) обращении к SetLength (процедура AddRecPoint).
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 16:12 [#10]:

М.б, все дело в строке:
if N <= REC.IMAX then
     move(REC.MASS[N+1],REC.MASS[N+2],SizeOf(t_Point)*(REC.IMAX-N+1));
(function AddPoint)?
Если закомментировать, то ошибка пропадает.
Самое любопытное, что со статичным массивом это прекрасно работало !
Вадим К

Вадим К (статус: Академик), 22 ноября 2010, 16:34 [#11]:

я думал об этой строке. Не перетираете ли Вы данные? Может быть у Вас обычный расстрел памяти?
выведите себе размер REC.IMAX-N+1 и посмотрите на него. может он "не такой как ожидается"? Выводить значения можно хоть в запасное memo.
Галочка "подтверждения прочтения" - вселенское зло.
DNK

DNK (статус: Студент), 22 ноября 2010, 16:50 [#12]:

Улыбнуло! Строка 90.
REC.NUMB_MAX := REC.NUMB_MAX;
"Digital Networked Knight"
Вадим К

Вадим К (статус: Академик), 22 ноября 2010, 17:06 [#13]:

там на самом деле должно быть
REC.NUMB_MAX := REC.NUMB_MAX - NUMB;
если по логике:)
Галочка "подтверждения прочтения" - вселенское зло.
vsorokin

vsorokin (статус: Посетитель), 22 ноября 2010, 17:24 [#14]:

DNK:
В строке 90 я просто делал точку останова. :)

Изменил в function AddPoint
строку
if (REC.NUMB_MAX = 0) or (REC.NUMB_MAX = (REC.IMAX+1)) then
на
if (REC.NUMB_MAX = 0) or (REC.NUMB_MAX <= (REC.IMAX+2)) then

и все понеслось!
Хотя, я так и не понял до конца, каким образом в

move(REC.MASS[N+1],REC.MASS[N+2],SizeOf(t_Point)*(REC.IMAX-N+1))

я затирал память?

Всем большое спасибо!
Вадим К

Вадим К (статус: Академик), 22 ноября 2010, 18:00 [#15]:

нужно конечно проверить, но мне кажется, что был выход на один элемент за конец массива.
Скорее всего статический массив начинался с 1, а динмаический - с нуля.
Галочка "подтверждения прочтения" - вселенское зло.
DNK

DNK (статус: Студент), 22 ноября 2010, 21:02 [#16]:

Цитата:

move(REC.MASS[N+1],REC.MASS[N+2],SizeOf(t_Point)*(REC.IMAX-N+1))


А разве у динамического массива элементы друг за другом расположены в памяти?
"Digital Networked Knight"
min@y™

min@y™ (статус: Доктор наук), 22 ноября 2010, 21:15 [#17]:

Цитата (DNK):

А разве у динамического массива элементы друг за другом расположены в памяти?

Бинго!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

24 декабря 2012, 09:39: Вопрос закрыт (решение принял DNK): Доколе?! Чем не причина?

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:41
Выполнено за 0.03 сек.