|
Вопрос # 4 753/ вопрос закрыт / |
|
Доброго времени суток, уважаемые эксперты!
Совсем недавно начал работать с динамическими массивами.
Пытаюсь в цикле вставлять данные в динамический массив (изменяя, при необходимости, его размерность).
Однако, при попытке изменить размерность массива, получаю ошибку ("Runtime error 216 at ...").
Что я делаю не так?
Код прилагаю.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
Приложение: Переключить в обычный режим- unit Unit1;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs;
-
- type
- TForm1 = class(TForm)
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
- t_Point = ^t_LIST;
- t_LIST = record
- TYPE_POINT : byte;
- case byte of
- 0:(
-
-
-
-
-
-
-
-
- );
- 1: (
- STR:string[54];
- )
- end; //t_LIST
-
- t_MASS = array of t_Point;
-
- t_REC = record
-
-
-
- MASS : t_MASS; //
- end;
-
-
- var
- Form1: TForm1;
- MASSTAT : t_REC;
- PL : t_Point;
- implementation
-
- {$R *.dfm}
-
- function GetPoint(TYPE_POINT : integer):t_POINT;
- var P : t_Point; var size : integer;
- begin
- try
- size := SizeOf(t_LIST);
- new(P);
- FillChar(p^,size,0);
- p.TYPE_POINT := TYPE_POINT;
- p.CH1 := char(SizeOf(p.STR)-1);
- except
- size := size;
- end;
- GetPoint := p;
- end; // GetPoint
-
- procedure FreePoint(var P : t_POINT);
- begin
- if P = nil then exit;
- case p.TYPE_POINT of
- 0: ;
- 1: ;
- else
-
- end;// case
- Dispose(P);
- P := nil;
- end; // FreePoint
-
- 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,REC.NUMB_MAX);
- except
- REC.NUMB_MAX := REC.NUMB_MAX;
- end;
-
- REC.TYPE_REC := TYPE_POINT;
- end; //AddRecPoint
-
- procedure FreeRecPoint(var REC : t_REC);
- var I : integer;
- begin
- for i := 0 to REC.NUMB_MAX -1 do
- if REC.MASS[i] <> nil then
- begin
- FreePoint(REC.MASS[i]);
- end;
- SetLength(REC.MASS,0);
- REC.IMAX := -1;
- REC.NUMB_MAX := 0;
- end;// procedure FreeRecPoint(var REC : t_REC);
-
-
-
- function AddPoint(var REC : t_REC; P : t_Point; var N : integer) : boolean;
- begin
-
-
- if N <= REC.IMAX then
- move(REC.MASS[N+1],REC.MASS[N+2],SizeOf(t_Point)*(REC.IMAX-N+1));
- inc(REC.IMAX);
- N := N+1;
- REC.MASS[N] := GetPoint(P.TYPE_POINT);
- REC.MASS[N]^ := P^;
- Result := true;
- end;// AddPoint(REC : t_REC; P : t_Point) : boolean;
-
-
- procedure TForm1.FormCreate(Sender: TObject);
- var i,L : integer; B : boolean;
- begin
- FreeRecPoint(MASSTAT);
- PL := GetPoint(0);
- for I := 1 to 10 do
- begin
- FillChar(PL^,SizeOf(PL^),0);
- PL.CH1 := char(SizeOf(PL.STR));
- PL.NAMESTR := IntToStr(I);
- L := -1;
- B := AddPoint(MASSTAT,PL,L);
-
- end;
-
- end;
-
- end.
-
 |
Вопрос задал: vsorokin (статус: Посетитель)
Вопрос отправлен: 21 ноября 2010, 16:47
Состояние вопроса: закрыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 17; последнее сообщение — 22 ноября 2010, 21:15; участников в обсуждении: 5.
|
6ruse (статус: 1-ый класс), 22 ноября 2010, 06:35 [#1]:
Доброго времени суток! Вы немного не правильно изменяете размерность массива. Нужно так
SetLength(массив, length(массив)+length(на сколько увеличиваем));
что то вроде этого.
|
|
min@y™ (статус: Доктор наук), 22 ноября 2010, 08:53 [#2]:
Цитата (vsorokin):
Что я делаю не так?
Ты используешь дин. массив не в той задаче.
Здесь нужен список указателей TObjectList.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
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™ (статус: Доктор наук), 22 ноября 2010, 10:09 [#4]:
Цитата (vsorokin):
Не вполне понятно, зачем мне нужен список указателей TObjectList ? Как его использовать? Ведь я всего-навсего хочу использовать изменяемый во время выполнения динамический массив ссылок.
Именно так. Для этих целей и служит TObjectList.
Переделай свой record в класс. Тогда у тебя будет возможность ОЧЕНЬ СИЛЬНО упростить и сократить твой код. Первоочередная задача — решиться похерить то, что ты уже написал. Я понимаю, что это трудно, но себя нужно преодолеть, и тогда всё получится, поверь мне!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
vsorokin (статус: Посетитель), 22 ноября 2010, 11:59 [#5]:
Уважаемый эксперт min@y™:
Наверняка, все можно переписать правильно с т.з. классического ООП.
Я привел здесь небольшой фрагмент программы. У меня возникла проблема, связанная с изменением длины динамического массива. Раньше я такие массивы не использовал.
Хотелось бы понять, в чем моя ошибка именно при применении динамического массива? В частности, функции SetLength.
P.S. Буду также признателен, если Вы покажете, как можно в моем случае использовать TObjectList.
|
|
min@y™ (статус: Доктор наук), 22 ноября 2010, 13:27 [#6]:
Цитата:
Буду также признателен, если Вы покажете, как можно в моем случае использовать TObjectList.
Если ты готов отказаться от дин. массивов - напишу тебе примерчик. Я уверен, что в данном случае тебе нужно выкинуть дин. массивы.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
vsorokin (статус: Посетитель), 22 ноября 2010, 13:50 [#7]:
min@y™: Готов отказаться от дин. массивов!
Однако, в конечном счете, мне нужно получить массив ссылок на t_Point = ^t_LIST. Этот массив использую для сортировки и быстрого поиска нужной информации. (В предыдущей версии программы я успешно использовал статический массив).
Однако, появилась необходимость иметь возможность быстро изменять его (массива) размер в процессе выполнения программы. Поэтому, и попробовал с минимальными изменениями в программе перейти от статического к динамическому массиву.
И вдруг - облом.
|
|
Вадим К (статус: Академик), 22 ноября 2010, 13:53 [#8]:
Можно конечно переписать код, тут действительно нужно переписать, так как код сильно сдобренный указателями.
Но может все таки на этих костылях построить что то чуточку рабочее, а потом аккуратно уже переписывать на правильное и работающее.
первое, что хотелось уточнить - ошибка возникает при первой же попытке выставить размер или во время работы?
второе - какая версия делфи.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
vsorokin (статус: Посетитель), 22 ноября 2010, 13:59 [#9]:
Вадим К:
У меня Дельфи 7.
Ошибка возникает во время работы при вторичном (третьем и т.д.) обращении к SetLength (процедура AddRecPoint).
|
|
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 (статус: Студент), 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 (статус: Посетитель), 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 (статус: Студент), 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™ (статус: Доктор наук), 22 ноября 2010, 21:15 [#17]:
Цитата (DNK):
А разве у динамического массива элементы друг за другом расположены в памяти?
Бинго!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
24 декабря 2012, 09:39: Вопрос закрыт (решение принял DNK): Доколе?! Чем не причина?
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|