Решение практических задач на Паскале. Выпуск 7
В предыдущем выпуске рассылки был описан способ возведении матрицы в целочисленную степень. Недостаток "того" метода заключался в том, что для изменения ранга матрицы необходимо заново компилировать программу. Это, ессно, неудобно. И я обещал предложить другой способ.
Но способ опишу нестандартный. Это не пресловутый список. Идея простая: отключается проверка принадлежности
диапазону с помощью указания компилятору {$R-}. Объявляется массив минимальной размерности,
например, Благодаря такому определению Паскаль "знает", что ar - это массив, у него есть элементы,
к которым можно обращаться по их индексу. А в результате того, что отключена проверка принадлежности
диапазону, он и не "догадывается", что мы обращаемся к элементам с индексами больше объявленных.
Следовательно, "делай, с ним что хошь". Нужно только разместить этот массив в динамической памяти и "пометить" ее как занятую. Для обычного блока данных программы этого сделать нельзя. Помечать нужно, чтобы нечаянно не переписать данные
Для того, чтобы убедиться в справедливости сказанного об обычной памяти, наберите такой код:
var
k: Integer;
ar: array[1..1, 1..1] of Real;
i: Integer;
BEGIN
WriteLn;
ar[1,1]:=0.5;
WriteLn('Это правильно, как и ввели: ', ar[1,1]:5:1);
i:=2; {!!!} k:=i;
{$R-} {От сех пор не проверять принадлежность диапазону}
ar[1, i]:=0.11; {Константу использовать нельзя! Используем переменную i}
WriteLn('И это правильно? ', ar[1, k]:5:2,' Не так ли?');
WriteLn('Тогда это как понимать? i стала равным ',i);
WriteLn('ВСЕ ПРАВИЛЬНО (в смысле, неправильно)!! Когда писали в элемент ar[1, 2], то'+
#13#10#9'переписали содержимое переменной i!');
WriteLn('В оперативной памяти компьютера она находится за массивом');
END.
Надеюсь, помните: не следует буквально понимать фразу "набирать код". Выделите его (код), нажмите Ctrl+C для того, чтобы скопировать текст в карман Windows (Clipboard). Переведите редактор Паскаля в оконный вид (Alt+ENTER). Создайте новый фа йл. Зайдите в системное меню окна (в самом верхнем левом углу окна, где написано Borland Pascal 7.0). Выберите пункт меню "Изменить - Вставить". Нажмите F2 для сохранения текста программы
В нашем случае для размещения массива в куче следует использовать процедуру GetMem. Есть еще New, но она использует информацию о структуре размещаемого в памяти элемента. В частности, о его длине. А нам нужно захватить памяти больше, чем положено
Однако, реализация сложнее, чем просто вызвать GetMem, а потом обращаться к "запредельным"
элементам массива. На это обычно не обращают внимания, так как используют только отдельные элементы
массива, а НЕ ВСЕ! См., например,
http://closed.narod.ru/k/2/643.html.
Способ решения, предложенный в
пособии по программированию на Паскале показался мне сложным
Паскаль при вычислении адреса элемента массива в оперативной памяти
использует информацию об объявлении массива. По этой причине, когда мы
выходим за пределы массива - этот адрес оказывается неправильным. Например, если использовать определение
Проверить это сможете, если наберете код такой программы:
type
PMatrix = ^TMatrix;
TMatrix = array[1..1, 1..1] of real;
var
p: PMatrix;
i, j: Integer;
size: Integer;
const
range: Integer = 6;
BEGIN
size:= range*2*SizeOf(Real);
GetMem(p, size);
Writeln;
{$R-}
for i:=1 to range do begin
for j:=1 to range do
Write('[',i,',',j,']:', ofs(p^[i,j]):3,' ') ;
WriteLn
end;
FreeMem(p, size);
END.
Вы получите такое:
[1,1]: 0 [1,2]: 6 [1,3]: 12 [1,4]: 18 [1,5]: 24 [1,6]: 30 [2,1]: 6 [2,2]: 12 [2,3]: 18 [2,4]: 24 [2,5]: 30 [2,6]: 36 [3,1]: 12 [3,2]: 18 [3,3]: 24 [3,4]: 30 [3,5]: 36 [3,6]: 42 [4,1]: 18 [4,2]: 24 [4,3]: 30 [4,4]: 36 [4,5]: 42 [4,6]: 48 [5,1]: 24 [5,2]: 30 [5,3]: 36 [5,4]: 42 [5,5]: 48 [5,6]: 54 [6,1]: 30 [6,2]: 36 [6,3]: 42 [6,4]: 48 [6,5]: 54 [6,6]: 60Тут показаны адреса элементов в памяти. Точнее, показаны смещения. Сегмент у них один.
Выпуск что-то получается длинным ... .На этом пока прервусь. Способ решения дам позднее
Скажу только, что при использовании стандартной процедуры move решение получается более понятное, да и описывать матрицу как массив нет никакой необходимости ...
Обращу Ваше внимание на то, что на нашем форуме www.yourpascal.com появилась возможность размещать свои файлы. При создании нового раздела это просто и естественно, а при ответе - нужны выбирать "ответ", а не "быстрый ответ"
Мы приглашаем Вас и Ваших друзей к сотрудничеству. Напишите, какая проблема Вас лично интересует - и мы постараемся помочь Вам. Поделитесь со всеми, если Вам удастся найти красивое решение. Присылайте свои программы, и если они хороши, то опубликуем их с обязательным указанием Вашего авторства.
По всем вопросам можно писать либо в Гостевую книгу нашего сайта на www.turbopascal.tk, либо
мне,
Постараюсь ответить на все вопросы и учесть все разумные предложения
Рассылка поддерживается сайтом www.turbopascal.tk. При перепечатке ссылка на сайт обязательна
Внимание: сессия и экзамены еще не начались - самое время подписаться на нашу рассылку:
|
|