Песни о Паскале — страница 76 из 112

var Champ : TChamp; { массив команд }


{ Процедура пузырьковой сортировки не изменилась! }

procedure BubbleSort(var arg: TChamp);

...

end;

var i: integer;


begin       {--- Главная программа ---}

{ Вводим названия команд, набранные очки и прочие данные }

for i:=1 to CSize do begin

      Write('Название команды: '); Readln(Champ[i].mName);

      Write('Набранные очки: '); Readln(Champ[i].mAces);

      Write('Выигрышей: ');       Readln(Champ[i].mWins);

end;

{ сортируем }

BubbleSort(Champ);

{ Выводим результаты }

Writeln('Итоги чемпионата:');

Writeln('Место Команда       Очки Выигрышей');

for i:=1 to CSize do begin

      Write(i:3,' ':3, Champ[i].mName,

      Champ[i].mAces:(20-Length(Champ[i].mName) ));

      Writeln(Champ[i].mWins:8);

end;

Readln;

end.


Напоследок отвечу на один вероятный вопрос. Поля записи объявлены мною в некотором порядке, существенно ли это? Ничуть! Поля могут объявляться в любой последовательности, – это не влияет на их обработку.

Итоги

• Для соединения разнородных, но связанных общим смыслом данных используют записи.

• Запись заключается в пару ключевых слов RECORD-END, между которыми перечисляются имена и типы полей, входящих в запись.

• На основе записей могут быть построены как одиночные переменные, так и массивы.

• Доступ к полям записей выполняется через имя переменной и имя поля, разделяемые точкой.

А слабо?

А) Дополните программу «P_50_2» с тем, чтобы обработать все поля записи.

Б) Предложите структуру записи для полицейской базы данных. Какие данные следует, по вашему мнению, включить в неё?

В) Напишите программу для полицейской базы данных с применением записей. Обеспечьте ввод данных из файла, поиск по номеру и распечатку полей найденной записи.

Г) В текстовом файле тремя колонками представлены сведения о школьниках: фамилия, рост и вес. Ваша программа должна преобразовать его в три других файла, где эти же сведения отсортированы соответственно: 1) по фамилиям, 2) по росту и 3) по весу учеников.

Д) Домино. В этой игре используют 28 костяшек, каждая из которых содержит пару чисел от 0 до 6. Например: 0:0, 1:5, 6:6. Представьте костяшку записью, а игральный набор – массивом этих записей. Заполните массив костяшек и распечатайте его. «Смешайте» костяшки случайным образом и вновь распечатайте массив. Для удобства направьте распечатку в текстовый файл.

Е) Карты. Колода содержит 36 карт четырех мастей: трефы и пики – черные, а бубны и червы – красные. Относительная сила карты определяется числом от 6 до 14. Представьте карту записью, содержащей её масть, цвет и силу. Представьте колоду массивом записей, сформируйте полную колоду и распечатайте в текстовый файл. «Перетасуйте» колоду и вновь распечатайте в файл. При распечатке силу карт от 11 до 14 напечатайте их названиями: валет, дама, король, туз.

Глава 51Указатели в море памяти



Птице в небе хорошо, а рыбе – в реке. Программы «живут» в оперативной памяти, – дайте им почуять себя там, как рыба в воде, и они обретут беспредельную мощь! Следующие главы продвинут нас к этой цели.

Погружение в оперативную память

Оперативная память содержит миллионы байтовых ячеек, – вы знаете об этом. Каждой ячейке назначен уникальный номер, иначе говоря – адрес. Уникальный – это значит, что все адреса разные, – так нумеруют дома на улицах и квартиры в домах. Первой ячейке памяти присвоен адрес 0, второй – 1 и так далее. Подобно тому, как почтальон находит дом по номеру, процессор обращается к данным по адресам ячеек, где они хранятся.

Прежде, чем «задышать», программа должна перекочевать с диска в оперативную память. Рассказать про это? С включением питания компьютера в дело вступает стартовая программа – загрузчик, прошитый в постоянной памяти материнской платы. Эта программка загружает с диска в оперативную память вашу любимую операционную систему, – ритуал сопровождают загадочный скрип, мигание и попискивание. К тому моменту, когда на экране появляется знакомая картинка, часть памяти занимает операционная система. Дальше все определяют капризы пользователя. Он волен загрузить одну или несколько программ, после чего их размещение в памяти может стать таким, как показано на рис. 115.

Распределением памяти под программы заведует операционная система. По мере запуска тех или иных приложений, система «расселяет» их в свободных областях памяти, а по завершении – «выселяет», освобождая память для других целей. Этот механизм именуется динамическим распределением памяти.

Не применяйте слов, смысла которых не знаете. Что значит «динамический»? «Динамо» – греческое слово и означает силу, мощь. Оттого и полюбилось спортивным клубам, но к нашей теме это толкование не подходит. Сила порождает движение, потому «динамический» стали употреблять в смысле «подвижный», «быстрый». А программисты придали этому слову ещё один оттенок: «изменчивый», «непостоянный», разумея под этим изменчивое размещение в памяти данных и программ, — так будем понимать это слово и мы.



Рис.115 – Распределение оперативной памяти
«Планировка» памяти

Обратимся к правой части рис. 115, где упрощенно показано распределение памяти внутри одной программы. Эта память делится на три части или секции (Section – «отделение»). Одна из них вмещает исполняемый код, то есть процедуры, функции и главную программу. Другая – секция данных – отведена для глобальных переменных, а третья – так называемый стек – для параметров процедур и локальных переменных. Сейчас надо усвоить лишь две простые вещи, а именно:

• все секции программы (как и программа в целом) имеют фиксированные, то есть постоянные размеры, определяемые при компиляции программы;

• все объекты программы – процедуры, функции, переменные – обладают своими «личными» адресами в оперативной памяти; эти адреса определяются при загрузке программы, и потому могут изменяться от одной загрузки к другой.

Рассмотрим пример. Пусть в программе объявлены четыре переменные.


var B : Boolean;       C : char; I : integer;       S : string;


После загрузки программы в оперативную память они «расселятся» в соседних ячейках памяти, начиная с некоторого начального адреса N так, как показано на рис. 116.



Рис.116 – Размещение переменных в оперативной памяти

Первые ячейки этого участка памяти займут однобайтовые переменные булевого и символьного типа. В следующих двух байтах поселится целое число, а далее – в 256 байтах – строковая переменная. Подобная картина наблюдается и при размещении структурных переменных – записей; их поля занимают соседние ячейки. И хотя начальный адрес участка N может изменяться от загрузки к загрузке (его определяет операционная система), относительное размещение переменных в памяти остается тем же.

Указатели, первое знакомство

Отныне мы приступаем к освоению средств языка для работы с памятью. Овладев ими, вы откроете себе новые горизонты!

Начнем с нового для нас типа данных – указателя (по-английски – POINTER). Указатели могут хранить адреса переменных, процедур и функций. Нам интересны, прежде всего, указатели на переменные, рассмотрим пример обращения с таким указателем.


var P : ^integer; { указатель на целое }

      N : integer;       { целое }

begin

      P:= @N;       { указателю назначается адрес переменной N }

      P^:= 125;       { переменной присваивается значение через указатель }

      Writeln(N);       { 125 }

end.


В первой строчке объявлен указатель P. Это сделано специальным значком – стрелка вверх «^», – эта стрелка ставится перед именем типа, с которым будет работать указатель. В данном случае указатель P предназначен для хранения адресов переменных типа INTEGER.

Первый из исполняемых операторов


      P:= @N;


заносит в указатель P адрес переменной N. С этого момента указатель P ссылается на то место в памяти, где «живет» переменная N. Обратите внимание на «почтовую собачку» перед N – это операция взятия адреса. То же самое можно сделать функцией взятия адреса.