Выделение памяти под матрицу
Модератор: Модераторы
Выделение памяти под матрицу
Как правильно выделить память под двумерный массив? Вариант с динамическими массивами и функцией SetLength() неплох, но хотелось бы узнать как это сделать используя указатели. Так сказать "в стиле си" ))
majhar
Динамический массив и SetLength() это и есть тот самый указатель. Только не в стиле Си. Ведь мы же с Вами (как и все разработчики на FreePascal) цивилизованные люди, не так ли? Поэтому пользоваться методами каменного века не будем.
Динамический массив и SetLength() это и есть тот самый указатель. Только не в стиле Си. Ведь мы же с Вами (как и все разработчики на FreePascal) цивилизованные люди, не так ли? Поэтому пользоваться методами каменного века не будем.
Мммда... Что-то я ступил.
Ведь адресная арифметика в fpc нормально работает.
Насколько я понял, вот такое возможно:
Но динамический массив будет, видимо, идеологически более верным ))
Насколько я понял, вот такое возможно:
Код: Выделить всё
const W = 10;
H = 5;
type PInt = ^integer;
var p : ^PInt;
newp : pointer;
i, j : integer;
begin
getmem(newp, H*sizeof(PInt));
p := newp;
for i := 0 to H-1 do
begin
getmem(newp, W*sizeof(integer));
(p+i)^ := newp;
end;
for i := 0 to H-1 do
for j := 0 to W-1 do ((p+i)^+j)^ := i*W + j ;
for i := 0 to H-1 do
for j := 0 to W-1 do write( ((p+i)^+j)^, ' ');
end.Но динамический массив будет, видимо, идеологически более верным ))
majhar писал(а):type PInt = ^integer;
var p : ^PInt;
...
У Вас тут получается "указатель на указатель на целочисленный тип". Не слишком ли сложная конструкция?
Мало того, она ещё и сложноинициализируема и сложна для понимания происходящих там процессов. И данные оттуда сложно доставать...
Вот давайте теперь сравним с динамическим массивом:
Код: Выделить всё
Const
COL = 5;
ROW = 10;
Var
DynArray: array of Integer;
i, j: Integer;
va-bank: integer;
Begin
...
//Выделяем память под массив
SetLength(DynArray, COL, ROW);
//Заполняем данными
Randomize;
For i:=0 To COL-1 Do
For j:=0 To ROW-1 Do
DynArray[i, j]:=Random(100);
//Берём данные из первой попавшийся ячейки
va-bank:=DynArray[Random(COL), Random(ROW)];
//... и превращаем программу в Лас-Вегас казино :)
If va-bank=99 Then
WriteLn('Вы выиграли 1 000 000 долларов!!!')
Else
WriteLn('Ну всё, пипец! Ты проиграл даже штаны...');
End;
По-моему так более понятно, чем с указателями, Вы не находите?
Так что дело тут отнюдь не в идеологии. Нас вообще не должны заботить технические подробности выделения памяти. А с указателями основной процент затрат времени при написании программы уйдёт именно на эту нудную и совершенно неинтересную работу - выделение и освобождение памяти. Мало того, можно выдрать себе последнии волосы из головы, пытаясь найти ошибку связанную с неправильной работой с указателями. При работе же с динамическими массивами вся (или почти вся
Vadim писал(а):Код: Выделить всё
Var
DynArray: array of Integer;
i, j: Integer;
va-bank: integer;
Begin
...
//Выделяем память под массив
SetLength(DynArray, COL, ROW);
Как это???
Может быть SetLength(DynArray, COL*ROW)? но это уже не матрица.
Vadim писал(а):У Вас тут получается "указатель на указатель на целочисленный тип". Не слишком ли сложная конструкция?
Мало того, она ещё и сложноинициализируема и сложна для понимания происходящих там процессов. И данные оттуда сложно доставать...
Это спорный вопрос. Мне, например, работа функции fpc_dynarray_setlength из rtl, гораздо менее понятна.
Но с этим я полностью соглсен:
Особенно если речь только о прикладных программах.Vadim писал(а):Нас вообще не должны заботить технические подробности выделения памяти. А с указателями основной процент затрат времени при написании программы уйдёт именно на эту нудную и совершенно неинтересную работу - выделение и освобождение памяти. Мало того, можно выдрать себе последнии волосы из головы, пытаясь найти ошибку связанную с неправильной работой с указателями.
А возможность полноценной работы с указателями подтверждает универсальность языка и компилятора fpc, пригодность его для решения любых задач. Что очень меня радует.
majhar писал(а):Как это???
Ну, как ни странно, а именно вот так.
Код: Выделить всё
DynArray: array of array of Integer;Для меня самого было божественным откровением узнать в своё время, что размер динамическому массиву можно задавать не только в одном измерении, но и в двух. Хотя в хелпе об этом не было ни слова написано. Экие они там тихони, право слово.
majhar писал(а):Это спорный вопрос. Мне, например, работа функции fpc_dynarray_setlength из rtl, гораздо менее понятна.
Скорее не спорный, а вопрос привычки.
Правда на сегодняшний день и динамические массивы уже вчерашний день.
А вот классу можно придать нужный функционал, например он может не только хранить матрицу, но и производить её транспортирование или инвертирование, если речь идёт о логическом содержимом. И уже в пользовательской программе не нужно ломать голову, как нам транспортировать матрицу, мы её просто транспортируем и всё...
- Рождённый_в_СССР
- новенький
- Сообщения: 65
- Зарегистрирован: 08.08.2007 01:03:26
- Откуда: Саратов
Vadim писал(а):Правда на сегодняшний день и динамические массивы уже вчерашний день. Классы, которые созданы по типу хранения данных наподобие массива (например TStringList или TList), обеспечивают неизмеримо большее удобство в применении, чем динамический массив. Ведь динамический массив ограничен функционально тем, что это всего лишь коробочка для хранения данных, с неизвестным начальным объёмом. Кроме хранения он ничего более не умеет.А вот классу можно придать нужный функционал, например он может не только хранить матрицу, но и производить её транспортирование или инвертирование, если речь идёт о логическом содержимом. И уже в пользовательской программе не нужно ломать голову, как нам транспортировать матрицу, мы её просто транспортируем и всё...
Если я не прав - поправьте
но когда вы придаёте 'нужный функционал' мы не просто пишем одну строчку, а описываем всю функцию что она должна делать, аналогично я могу описать в том же модуле где создается описывается динамический массив функцию траспонирования, отличия будет только в том, что объявленно не точно внутри отной конструкции. Вызовы
Matrix.Transparate; и Transparate(Matrix);
Помойму ничем кординальным не отличаются ) впрочем как сомнительны любые другие превосходства ООП над структурным. Всё дело на любителя, кому как думается, а ООП имхо для больших организаторов, кому хочется красивыми и громкими объявлениями его скромного кода позаниматься.
