Выделение памяти под матрицу

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Выделение памяти под матрицу

Сообщение majhar » 14.07.2008 21:11:58

Как правильно выделить память под двумерный массив? Вариант с динамическими массивами и функцией SetLength() неплох, но хотелось бы узнать как это сделать используя указатели. Так сказать "в стиле си" ))
majhar
незнакомец
 
Сообщения: 4
Зарегистрирован: 14.07.2008 20:52:31

Re: Выделение памяти под матрицу

Сообщение Vadim » 15.07.2008 05:11:02

majhar
Динамический массив и SetLength() это и есть тот самый указатель. Только не в стиле Си. Ведь мы же с Вами (как и все разработчики на FreePascal) цивилизованные люди, не так ли? Поэтому пользоваться методами каменного века не будем. :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Выделение памяти под матрицу

Сообщение majhar » 15.07.2008 11:53:05

Мммда... Что-то я ступил. :oops: Ведь адресная арифметика в 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
незнакомец
 
Сообщения: 4
Зарегистрирован: 14.07.2008 20:52:31

Re: Выделение памяти под матрицу

Сообщение Vadim » 15.07.2008 13:18:51

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
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Выделение памяти под матрицу

Сообщение majhar » 15.07.2008 13:58:19

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
незнакомец
 
Сообщения: 4
Зарегистрирован: 14.07.2008 20:52:31

Re: Выделение памяти под матрицу

Сообщение Vadim » 15.07.2008 16:58:36

majhar писал(а):Как это???

Ну, как ни странно, а именно вот так. :) Я только там в объявлении неправильно матрицу написал. Надо вот так:
Код: Выделить всё
DynArray: array of array of Integer;

Для меня самого было божественным откровением узнать в своё время, что размер динамическому массиву можно задавать не только в одном измерении, но и в двух. Хотя в хелпе об этом не было ни слова написано. Экие они там тихони, право слово. :)
majhar писал(а):Это спорный вопрос. Мне, например, работа функции fpc_dynarray_setlength из rtl, гораздо менее понятна.

Скорее не спорный, а вопрос привычки. :) Но если исходить из того, с чем Вы полностью согласны, то вникать в реализацию каждой функции RTL нет никакой необходимости до тех пор, пока эта функция делает то, что нам нужно. И нас примирять с этой функцией должно то обстоятельство, что предназначена она для внутреннего применения в модуле system. Разве что Вы захотите довести скорость работы с динамическими массивами до уровня первой космической. :)
Правда на сегодняшний день и динамические массивы уже вчерашний день. :) Классы, которые созданы по типу хранения данных наподобие массива (например TStringList или TList), обеспечивают неизмеримо большее удобство в применении, чем динамический массив. Ведь динамический массив ограничен функционально тем, что это всего лишь коробочка для хранения данных, с неизвестным начальным объёмом. Кроме хранения он ничего более не умеет.
А вот классу можно придать нужный функционал, например он может не только хранить матрицу, но и производить её транспортирование или инвертирование, если речь идёт о логическом содержимом. И уже в пользовательской программе не нужно ломать голову, как нам транспортировать матрицу, мы её просто транспортируем и всё... :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Выделение памяти под матрицу

Сообщение Рождённый_в_СССР » 27.08.2008 17:42:40

Vadim писал(а):Правда на сегодняшний день и динамические массивы уже вчерашний день. Классы, которые созданы по типу хранения данных наподобие массива (например TStringList или TList), обеспечивают неизмеримо большее удобство в применении, чем динамический массив. Ведь динамический массив ограничен функционально тем, что это всего лишь коробочка для хранения данных, с неизвестным начальным объёмом. Кроме хранения он ничего более не умеет.А вот классу можно придать нужный функционал, например он может не только хранить матрицу, но и производить её транспортирование или инвертирование, если речь идёт о логическом содержимом. И уже в пользовательской программе не нужно ломать голову, как нам транспортировать матрицу, мы её просто транспортируем и всё...

Если я не прав - поправьте
но когда вы придаёте 'нужный функционал' мы не просто пишем одну строчку, а описываем всю функцию что она должна делать, аналогично я могу описать в том же модуле где создается описывается динамический массив функцию траспонирования, отличия будет только в том, что объявленно не точно внутри отной конструкции. Вызовы
Matrix.Transparate; и Transparate(Matrix);
Помойму ничем кординальным не отличаются ) впрочем как сомнительны любые другие превосходства ООП над структурным. Всё дело на любителя, кому как думается, а ООП имхо для больших организаторов, кому хочется красивыми и громкими объявлениями его скромного кода позаниматься.
Аватара пользователя
Рождённый_в_СССР
новенький
 
Сообщения: 65
Зарегистрирован: 08.08.2007 01:03:26
Откуда: Саратов


Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Рейтинг@Mail.ru