Помощь - Поиск - Пользователи - Календарь
Полная версия: Динамическая матрица
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
kent
Захотел использовать динамическую матрицу в задаче, но что то не получается... Попытался сначала сделать ввод вывод, но вводишь к примеру M = 3, N = 3...

Вводишь
1 2 3
1 2 3
1 2 3

Выводит
1 1 1
1 1 2
1 2 3

Вот код:

uses crt;
var M,N : Integer;
type
    MyType = Integer;
type
    MyMatrix = array [1..1,1..1] of MyType;
    TMatrix = ^MyMatrix;

{-----------------------------------------------}
Procedure ReadMatrix(var mx : TMatrix);
var i,j : Integer;
begin
     for i := 1 to M do
        for j := 1 to N do begin
           Write('Element [',i,',',j,']:');
           ReadLn(mx^[i,j]);
        end;
end;
{-----------------------------------------------}

{-----------------------------------------------}
Procedure WriteMatrix(var mx : TMatrix);
var i,j : Integer;
begin
     for i := 1 to M do
        for j := 1 to N do begin
           Write(mx^[i,j]:3);
           if j = N then WriteLn;
        end;
end;
{-----------------------------------------------}

var a : TMatrix;
    Size : Word;

begin
     {$R-}
     Clrscr;
     Write('Input M:');
     ReadLn(M);
     Write('Input N:');
     ReadLn(N);
     Size := M * N * SizeOf(MyType);
     GetMem(a,Size);
     WriteLn('Input Matrix:');
     ReadMatrix(a);
     WriteLn;
     WriteLn('Source Matrix:');
     WriteMatrix(a);
     FreeMem(a,Size);
     Readkey;
end.



Подскажите что не так...
volvo
Цитата(kent @ 30.07.05 20:16)
Подскажите что не так...

smile.gif Подсказываю:
GetMem(a,Size);

Если бы все было так просто... Вообще-то описания типов должны быть такими:
type
  MyType = Integer;
  PVector = ^TVector;
  TVector = Array[1 .. maxInt div sizeof(MyType)] Of MyType;

  PMatrix = ^TMatrix;
  TMatrix = Array[1 .. MaxInt div sizeof(PVector)] Of PVector;


Ну, и выделение/освобождение памяти, соотвественно:
  ReadLn(M);
  GetMem(a, M*SizeOf(PVector));
  ReadLn(N);
  For i := 1 To M Do
    GetMem(a^[i], N*SizeOf(MyType));


Кстати, в процедуре распечатки матрицы у тебя лишний If - зачем?
Вот так не лучше? ;)
Procedure WriteMatrix(mx : PMatrix);
var i, j : Integer;
begin
  for i := 1 to M do begin
    for j := 1 to N do
      Write(mx^[i]^[j]:3);
    WriteLn;
  end;
end;
kent
Попробовал сделать так, выводит правильно, но вместо того чтобы ждать нажатия клавиши (Readkey), выдает Runtime - error 204... blink.gif
И ещё вопрос, что означает?

MaxInt div sizeof(Type)


Не совсем врубаюсь... Может проще как-нибудь можно?
volvo
Цитата(kent @ 30.07.05 21:57)
выводит правильно, но вместо того чтобы ждать нажатия клавиши (Readkey), выдает Runtime - error 204... blink.gif

Значит, что-то неправильно делаешь (эта ошибка возникает при неправильной работе с указателями через GetMem/FreeMem)...
Вот так должно происходить освобождение:
  For i := 1 To M Do
    FreeMem(a^[i], N*SizeOf(MyType));
  FreeMem(a, M*SizeOf(PVector));

Цитата(kent @ 30.07.05 21:57)
И ещё вопрос, что означает?
MaxInt div sizeof(Type)

Может проще как-нибудь можно?

Вообще-то я пропустил, там должно быть вот так:
TVector = Array[1 .. 2 * maxInt div sizeof(MyType)] Of MyType;
:p2:
Это означает, что максимальное число элементов массива рассчитывается исходя из следующих соображений: максимальный размер массива в Турбо-Паскале = 64Кбайта, что соответствует 2*maxInt. Но столько элементов в массив поместится только, если размер каждого = 1 байту. У тебя размер каждого элемента = SizeOf(MyType), вот и дели макс. возможный размер на размер каждого элемента, чтобы получить макс. число элементов в массиве... При таком способе у тебя НИКОГДА не произойдет выхода за пределы массива...

Можно, в принципе, оставить как было у тебя:
type
  ...
  TVector = Array[1 .. 1] Of MyType;
  ...
  TMatrix = Array[1 .. 1] Of PVector;

, но тогда тебе придется отключать контроль выхода за пределы массива ({$R-}), что не очень хорошо, ведь контроль отключается ДЛЯ ВСЕЙ программы...
kent
Сейчас все ОК, никаких ошибок... smile.gif


Цитата
Значит, что-то неправильно делаешь (эта ошибка возникает при неправильной работе с указателями через GetMem/FreeMem)...

Немного не так у меня было...
Вместо:
  For i := 1 To M Do
    FreeMem(a^[i], N*SizeOf(MyType));
  FreeMem(a, M*SizeOf(PVector));

Стояло:

FreeMem(a, M*SizeOf(PVector));
For i := 1 To M Do
    FreeMem(a^[i], N*SizeOf(MyType));



А насчет размерности масива, буду наерное использовать твой вариант, дальше сложные задачки идут и без дополнительных массивов наверное не обойтись, так что ({$R-}) мне будет только мешать...

Спасибо тебе большое, что так подробно всё объяснил... :thanks:
Жалко тут рейтинга нет с меня два ++... smile.gif
volvo
Цитата(kent @ 30.07.05 22:46)
Стояло:

FreeMem(a, M*SizeOf(PVector));
For i := 1 To M Do
    FreeMem(a^[i], N*SizeOf(MyType));


Я так и думал... Это очень распространенная ошибка: дело в том, что вообще-то память должна освобождаться в порядке, противоположном ее выделению. То есть, если выделялось так:
GetMem(x1, ...);
GetMem(x2, ...);
...

То освобождаться должно так:
...
FreeMem(x2, ...);
FreeMem(x1, ...);

Это же желательно взять за правило в случае работы с New/Dispose...
А я кроме этого (по возможности) придерживаюсь такого же порядка при работе с файлами, то есть то, что открывается последним, закрывается первым. :yes:
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.