Как с помощью указателей в TurboPascal'e сделать такую матрицу, у которой ни кол-во строк, ни кол-во столбцов неизвестно (кажадая строка может иметь свой какой-то размер)
Здравствуйте, Ozone, Вы писали:
O>Есть такая задачка:
O>Как с помощью указателей в TurboPascal'e сделать такую матрицу, у которой ни кол-во строк, ни кол-во столбцов неизвестно (кажадая строка может иметь свой какой-то размер)
O>Помогите кто чем может.
Матрица она на то и матрица.
Копай в сторону указателей.
Здравствуйте, Ozone, Вы писали:
O>Да так, но это я уже понял. O>Как мне теперь правильно выделять память и заполнять ее (матрицу).
Как насчет GetMem/FreeMem?
... << RSDN@Home 1.1 beta 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Ozone, Вы писали:
O>>Да так, но это я уже понял. O>>Как мне теперь правильно выделять память и заполнять ее (матрицу). S>Как насчет GetMem/FreeMem?
Это все конечно здорово
Все эти процедуры я конечно знаю, просто я не могу сообразить как ее (матрицу) создать.
rCOLS:=random(100);
{ ??? под что выделить память ??? }for i:=1 to rCOLS do begin
rROWS:=random(100);
{ ??? под что выделить память ??? }for j:=1 to rROWS do begin{??? чему присваивать ???} := random(50);
end;
end;
{И как это все потом вывести на экран?}
Здравствуйте, Ozone, Вы писали:
O>Все эти процедуры я конечно знаю, просто я не могу сообразить как ее (матрицу) создать.
Ну как под что? Ты же задекларировал переменную M типа PPInt?
ну вот под нее и выделяешь:
var
M: PPInt;
Col: PInt
begin
rCOLS:=random(100);
GetMem(M, sizeof(PInt)*rCOLS);
for i:=0 to rCOLS-1 do begin
rROWS:=random(100);
Col:= PInt(Integer(M)+i*sizeof(PInt));
GetMem(Col, rROWS*sizeof(Integer));
for j:=0 to rROWS-1 do begin
PInt(Integer(Col)+j*sizeof(Integer))^ := random(50);
end;
end;
{И как это все потом вывести на экран?}
... << RSDN@Home 1.1 beta 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S>var
S> M: PPInt;
S> Col: PInt
S>begin
S>rCOLS:=random(100);
S>GetMem(M, sizeof(PInt)*rCOLS);
S>for i:=0 to rCOLS-1 do begin
S> rROWS:=random(100);
S> Col:= PInt(Integer(M)+i*sizeof(PInt));
S> GetMem(Col, rROWS*sizeof(Integer));
S> for j:=0 to rROWS-1 do begin
<B>{В этом месте программа вылетает из DOS}</B>
S> PInt(Integer(Col)+j*sizeof(Integer))^ := random(50);
S> end;
S>end;
S>
Здравствуйте, Ozone, Вы писали:
O>Да так, но это я уже понял. O>Как мне теперь правильно выделять память и заполнять ее (матрицу).
Дык всё не просто, в Турбо то Паскале. Там ДОС правит, а значит есть куча ограничений.
Придётся или object свой написать для инкапсуляции действий с такой матрицей, или бороться через записи.
Анализируем.
Для Дельфи мы бы написали
var
Matrix: array of array of Integer;
begin
SetLength(Matrix, N); // Задаём количество строк
...
// по строкам
SetLength(Matrix[i], M); // Задяём количество элементов в i-той строке
...
Вуалля. Теперь хотим то же, но по 3 рубля.
Пусть тип элементов матрицы будет Integer. Никто не мешает его потом изменить на нужный или record.
Объявляем данные
type
PMatrixData = ^TMatrixData;
TMatrixData = array[1..16384] of Integer;
Объявляем строку матрицы
type
PMatrixRow = ^TMatrixRow;
TMatrixRow = record
Count: Integer; // количество элементов
Data: PMatrixData; // сами данныеend;
Объявляем колонки матрицы
type
PMatrixRowList = ^TMatrixRowList;
TMatrixRowList = array [1..16384] of PMatrixRow;
И саму матрицу
type
TMatrix = record
Count: Integer; // количество строк в матрице
Row: PMatrixRowList; // список строкend;
Магика 16384 заключается в ограничении на размер блока в 64К и тем, что MaxInteger div SizeOf(Integer) = 16384 (32768 div 2 = 16384). Т.е. надо вложиться в непрерывный блок. Иначе придётся делать связанные списки, а это производительность.
Теперь смотрим, для чего всё затея была.
var
Matrix: TMatrix;
Item: Integer;
begin
with Matrix do
begin
Count := N;
GetMem(Row, Count * SizeOf(PMatrixRow));
end;
// по строкам
GetMem(Matrix.Row^[i], SizeOf(TMatrixRow));
with Matrix.Row^[i] do
begin
Count := M;
GetMem(Data, Count * SizeOf(Integer));
end;
// обращение
Item := Matrix.Row^[i].Data^[j];
Matrix.Row^[i].Data^[j] := Item;
Контроль индексов остаётся на совести программиста.
Конечно, я могу ошибиться в синтаксисе, давно BP не пользую, но идея-то понятна. И обернуть это дело в object труда не представляет, зато сколько потом пользы...
Здравствуйте, akasoft, Вы писали:
A>Здравствуйте, Ozone, Вы писали:
O>>Да так, но это я уже понял. O>>Как мне теперь правильно выделять память и заполнять ее (матрицу).
A>Дык всё не просто, в Турбо то Паскале. Там ДОС правит, а значит есть куча ограничений.
A>Контроль индексов остаётся на совести программиста.
A>Конечно, я могу ошибиться в синтаксисе, давно BP не пользую, но идея-то понятна. И обернуть это дело в object труда не представляет, зато сколько потом пользы...
Маленькие хитрости старого доброго ДОСа:
var
matr: array [1..1,1..1] of integer;
begin
GetMem(@matr,versize*horsize*sizeof(integer));
{$R-}
{адресуем как хотим. Память есть}
matr[10,20]:=111;
...
Здравствуйте, Ozone, Вы писали:
O>Есть такая задачка:
O>Как с помощью указателей в TurboPascal'e сделать такую матрицу, у которой ни кол-во строк, ни кол-во столбцов неизвестно (кажадая строка может иметь свой какой-то размер)
O>Помогите кто чем может.
Можно описать массивы:
type
TIntArray = array [0..0] of Integer;
PIntArray = ^TIntArray;
TMatrixArray = array [0..0] of PIntArray;
PMatrixArray = ^TMatrixArray;
Снимаешь range checking при компиляции.
Далее:
var
Matrix : PMatrixArray;
i : Integer;
begin
GetMem(Matrix, sizeof(PIntArray) * ROW_COUNT);
for i:= 0 to ROW_COUNT do
GetMem(Matrix^[i], sizeof(Integer) * COL_COUNTI);
// далее обращение к элементам Matrix^[i]^[j]end;
Если это все таки Delphi старших версий — то реализация н6а динамических массивах более универсальна.