Доброго времени суток ув. форумчане! Обращаюсь к вам со своей проблемой, для начала опишу текущую картину.
Имеется следующий класс :
type
point = class
id : integer;
X : real;
Y : real;
Z : real;
function Point (x : real; y : real; id_get : integer) : integer;
end;
function point.Point (x : real; y : real; id_get : integer) : integer;
var id : Integer;
begin
id := - 1;
X := x;
Y := y;
if ( id_get <> -1 ) then id_get := id;
end;
init_points : array of integer;
xPos, yPos, zPos : integer;
tab : array of point;
procedure TForm1.GiveValues();
var i : integer;
begin
for i:= Low(init_points) to High(init_points)
do
if ( ( i mod 3 ) = 0 ) then
begin
xPos := init_points[i];
yPos := init_points[i + 1];
zPos := init_points[i + 2] - 150;
AddPoint();
end;
end;
procedure TForm1.AddPoint();
var deletion : boolean;
dx, dy, dist : real;
i, y : integer;
p : point;
new_point : point;
begin
deletion := FALSE;
if ( ( zPos > 0 ) or ( xPos < 0 ) ) then Exit;
if ( Length(tab) > 0 ) then
begin
for i := Low(tab) to High(tab) do
begin
p := tab[i];
dx := p.X - xPos;
dy := p.Y - yPos;
dist := sqrt (dx * dx + dy * dy);
if (dist < 4) then
begin
deletion := TRUE;
for y := i to High(tab) - 1 do tab[y] := tab[y + 1]; //смещаем на элемент вниз
SetLength(tab, High(tab) - 1); //уменьшаем размер так как убрали 1 элемент
end;
end;
end;
if ( deletion = FALSE ) then
begin
new_point.Point(xPos, yPos, -1);
new_point.Z := zPos + 150; // !!!! Вот тут программа вылетает !!!!
SetLength(tab, High(tab) + 1);
tab[Length(tab)] := new_point; // добавляем в конец новый элемент
end;
end;
Для начала: Point у тебя - класс, и его перед использованием надо что? Правильно, создать. У тебя в коде создания экземпляра класса нет. Как-то вот так:
if ( deletion = FALSE ) thenНу, или сделать Point.Point конструктором (не понимаю я этой С++-ной привычки называть конструктор точно так же, как и сам класс. Я больше привык к Create-у) и вызывать соответствующим образом (как принято в Дельфи, а не так, как в Турбо Паскале)
begin
new_point := Point.Create; // Да, да. Point.Point - обычная функция, а нужен конструктор
new_point.Point(xPos, yPos, -1);
new_point.Z := zPos + 150; // !!!! Вот тут программа вылетает !!!!
SetLength(tab, High(tab) + 1);
tab[Length(tab)] := new_point; // добавляем в конец новый элемент
end;
Спасибо за ответ Владимир, идея понятна, есть несколько вытекающих вопросов :
1 - Destroy надо делать каждый раз после того как я уже использовал это значение?
2 - Нет идей почему теперь может писать invalid pointer operation ссылаясь на end в конце функции GiveValues?
for i := Low(tab) to High(tab) do
Я переписал указанные места (destroy пока не делал, потому что основная задача сначала скомпилить то, что есть). Теперь компилятор указывает ту же ошибку только в строке dx := p.X - xPos; Вероятно где-то что-то опять я проворонил.
procedure TForm1.AddPoint();
var deletion : boolean;
dx, dy, dist : real;
i, y : integer;
p : point;
new_point : point;
begin
deletion := FALSE;
if ( ( zPos > 0 ) or ( xPos < 0 ) ) then Exit;
if ( Length(tab) > 0 ) then
begin
i := 1;
while ( i <> Length(tab) ) do
begin
ShowMessage(inttostr(Length(tab)));
p := Point.Create; //добавил и тут конструктор
p := tab[i];
dx := p.X - xPos;
dy := p.Y - yPos;
dist := sqrt (dx * dx + dy * dy);
if (dist < 4) then
begin
deletion := TRUE;
for y := i to High(tab) - 1 do tab[y] := tab[y + 1];
SetLength(tab, High(tab) - 1);
end;
i := i + 1;
end;
end;
if ( deletion = FALSE ) then
begin
new_point := Point.Create;
new_point.Point(xPos, yPos, -1);
new_point.Z := zPos + 150;
SetLength(tab, Length(tab) + 1);
tab[Length(tab)] := new_point;
end;
end;
procedure TForm1.GiveValues();
var i : integer;
begin
i := 0;
while ( i < Length(init_points) )
do
begin
xPos := init_points[i];
yPos := init_points[i + 1];
zPos := init_points[i + 2] - 150;
AddPoint();
i := i + 3;
end;
end;
i := 0;
while ( i < Length(init_points) ) // <--- Ну, будет i = Length(init_points) - 1
do
begin
xPos := init_points[i];
yPos := init_points[i + 1];
zPos := init_points[i + 2] - 150; // Тут - попытка обратиться к "запредельному элементу"
AddPoint();
i := i + 3;
end;
Cпасибо за ответ, Владимир. Массив считывает из файла значения, которых 256. Делаю я это так:
procedure TForm1.DataFromFile (); //pick ups data from file
var num, size, i : Integer;
begin
AssignFile(Points_file, 'Points.txt');
Reset(Points_file);
size := 256;
i := 0;
SetLength(init_points, size);
SetLength(tab, 0);
while not Eof(Points_file) do
begin
Read(Points_file, num);
init_points[i] := num;
i := i + 1;
end;
CloseFile(Points_file);
end;
Стоп, стоп... Сразу не посмотрел вот сюда:
i := 1;
while ( i <> Length(tab) ) do
begin
for i := Low(tab) to High(tab) do. Массивы индексируются с 0, а не с 1. Надо делать:
i := 0;
while ( i < Length(tab) ) do
begin
SetLength(tab, Length(tab) + 1);
tab[Length(tab)] := new_point;
Спасибо Владимир, я смог скомпилировать код - основная моя проблема была в том, что я по массиву не с 0 шёл.
У меня остался последний вопрос по моему коду - в моём первом посте описана функция Point. В этой функции каждрому экземпляру класса point должно быть присвоено значение X и Y, которое передаётся через параметр этой функции через x и y. Но когда в моём случае создаётся экзсемпляр new_point, и после вызова функции new_point.Point(параметры) значения new_point.X и new_point.Y равны 0 (по крайней мере я так заметил) - я сделал вывод что каким-то образом эти значения не передаются вне функции. Если я не ошибаюсь, то в паскале для таких случае перед параметром функции требовалось написать var, мне очень интересно что для этого надо сделать на Delphi.
Так что чему в функции присваивается? Одинаковые имена полей класса и параметров - зло. Хотя бы перед именем поля поставь Self, чтобы было понятнее, что происходит...
> не понимаю я этой С++-ной привычки называть конструктор точно так же, как и сам класс
Она, кстати, не всегда выполняется.
Вообще это неудобно.
> Кстати, замени там цикл на while
Не надо заменять его на while, потому что там останется тот же дурацкий алгоритм за квадрат.
Я хочу чтобы внутри функции Point формировались значения для new_point.X и new_point.Y. Для этого я делаю там присваивание X := x, Y := y, но значения не присваиваются и равны 0 (внутри функции они верные), вне функции new_point.X и new_point.Y - 0.
Я ж написал:
function point.Point (x : real; y : real; Var id_get : integer) : integer;(Паскаль, как и все языки его группы, не делает разницы между X и x, это для него одна и та же переменная. И то, что ты делаешь - это присвоение параметру самого себя. Смысла - никакого, поле класса вообще не затрагивается).
begin
{Self.}id := - 1;
self.X := x;
self.Y := y;
if ( id_get <> -1 ) then id_get := {Self.}id;
Point := { чему равен результат функции??? }
end;
> а корректно работающий (в отличие от For-а, я написал почему) алгоритм за квадрат...
Хорошая отмаза.
Спасибо огромное за помощь, ввиду некоторых жизненных обстоятельств мне пришлось вернуться к Delphi - из-за того, что давно там не работал - оттуда и все вытекающие ошибки, на которые вы указали.