Решение практических задач на Паскале. Выпуск 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. При перепечатке ссылка на сайт обязательна
Внимание: сессия и экзамены еще не начались - самое время подписаться на нашу рассылку:
|