русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

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


Дата добавления: 2014-02-04; просмотров: 1610; Нарушение авторских прав


Записи

 

Запись(record) – наиболее общий сложный тип данных. Переменная типа "запись" объединяет данные разного типа. В этом принципиальное отличие записи от массива - все элементы массива имеют один и тот же тип. Необходимость в таком типе данных вытекает из многих программистских задач. Скажем, нам нужно спроектировать базу данных для хранения информации о сотрудниках фирмы. Для каждого сотрудника надо запомнить его фамилию (текстовая строка), год рождения (целое число), семейное положение (два варианта: женат/замужем – холост/не замужем). Хранение всех этих данных в отдельных переменных типа STRING, WORD и BOOLEAN соответственно – прямой путь к путанице. Гораздо удобнее, когда все данные на одного сотрудника хранятся в одной переменной. Вот тут-то нам и понадобятся записи. Кстати, само название "запись" происходит оттого, что чаще всего переменные такого типа записываются в файлы данных.

Рассмотрим на примере тип данных "запись":

 

TYPE TDate = RECORD
day: 1..31;
month:1..12;
year:1900..2100;
END;

 

Представленный здесь тип данных Tdate предназначен для хранения календарных дат. Запись состоит из полей. Каждое поле имеет свое уникальное имя (day, month, year) и для каждого поля указывается его собственный тип данных. Для полей, в которых хранятся номера дней в месяце и месяцев в году, правильным будет применение типов-диапазонов, что позволит сразу выявлять ошибочные даты типа 32.13.2002.

А в этом примере создается структура данных для хранения координат точки:

 

TYPE TPoint = RECORD
x:REAL;
y: REAL;
END;

 

Как видно, поля могут иметь и одинаковый тип – запись остается записью.

Тот факт, что каждое поле имеет сове уникальное имя, приводит к невозможности перебора полей записи в цикле. В отличие от массива, по полям записи нельзя пройтись в цикле – нужно знать имя каждого поля. Для обращения к полю по имени название поля отделяется от имени переменной-записи точкой:



 

TYPE TA=RECORD

x:REAL;

y:BYTE;

END;
VAR A:TA;

A.x:=10.0;
A.y:=5;

 

Полем записи, в свою очередь, может быть другая запись! Возможен следующий вариант:

 

TYPE TA1=RECORD

a:REAL;

b:BYTE;

END;

TA2=RECORD

c:TA1;

d:WORD;

END;
VAR x:TA2;

Label1.Caption:=x.c.a;

 

У вложенных записейдля обращения к нужному полю может потребоваться несколько точек.

Еще более сложная структура – записи с вариантами. Внутри записи с вариантами создается несколько наборов полей и специальное поле-селектор. Значение селектора определяет, какой набор полей доступен в настоящий момент.

Как известно, координаты точек на плоскости можно выражать в привычной декартовой системе координат (Х и Y), а можно – в полярной (Рис. 3.1). В полярной системе положение точки задается длиной и углом поворота отрезка, соединяющего эту точку с началом координат.

Рис. 6.1. Полярная система координат.

Создадим структуру данных, которая сможет хранить координаты точек как в декартовой, так и в полярной системах:

 

TYPE TCoord=(Cartesian, polar);
TCrd=RECORD
CASE kind:TCoord OF
Cartesian: x,y: REAL;
polar: r, phi: REAL;
END
END;

 

Для различения систем координат вводится перечислимый тип данных Tcoord, содержащий два значения: Cartesian для декартовых координат и polar – для полярных. Поле-селектор kind показывает, что, если в kind записано значение Cartesian, то в записи окажутся доступными поля x,y, а если polar – то поля r, phi.

Попробуем вычислить расстояние между двумя точками, причем координаты каждой из точек могут быть заданы как в полярной, так и декартовой системе. Вспомнив геометрию и формулы преобразования координат, получим следующий код:

 

CASE a.kind OF
Cartesian: CASE b.kind OF
Cartesian: d:=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
Polar: d:=sqrt(sqr(a.x-b.r*cos(b.phi)+

sqr(a.y-b.r*sin(b.phi));
END;
Polar: CASE b.kind OF
Cartesian: d:=sqrt(sqr(a.r*cos(a.phi)- b.x)+sqr(a.r*sin(.phi)-b.y));
Polar: d:=sqrt(a.r+sqr(b.r)-2*a.r*cos(a.phi-b.phi))
END;

 

В записях с вариантами часть полей может существовать всегда, независимо от значения поля-селектора. Например, мы создаем структуру данных для хранения информации о студенте или сотруднике университета. Очевидно, и студент, и профессор имеют имя и возраст. В то же время для студента важен номер его учебной группы, а для профессора – номер кафедры, на которой он работает. Записывается это так:

 

TYPE Tposition=(student, professor);
Tperson=RECORD
name: STRING;
age: BYTE;
CASE position:Tposition OF
student: group:STRING;
professor: departmentNo: BYTE;
END
END;

 

Поля name, age, position есть всегда. Поле group есть, если position=student. Поле DepartmentNo есть, если position=professor.

Для повышения эффективности работы с записямив Паскале (в отличие от большинства других языков, в частности, от языка С) предусмотрен очень удобный оператор WITH. Смысл действия оператора WITH заключается в том, чтобы не писать много раз имя переменной-записи при обращении к ее полям. Например, мы хотим занести дату в переменную рассмотренного выше типа Tdate. Придется написать следующее:

 

a.Date:=28;
a.Month:=2;
a.Year:=2002;

 

Такая программа не только громоздка, но и медлительна: в каждой строчке для обращения к переменной а ее адрес вычисляется заново. Вот как надо было написать этот фрагмент:

 

WITH a DO
BEGIN
Date:=28;
Month:=2;
Year:=2002
END;

 

Между BEGIN и END действует соглашение: все упоминаемые поля считаются полямипеременной a, указанной в операторе WITH. Адрес переменной a теперь вычисляется только один раз, что ускоряет работу программы.

Записи целиком нельзя ввести с клавиатуры или вывести на экран. Приходится делать это по полям:

 

VAR d:Tdate;

WITH d DO
BEGIN
day:=StrToInt(Edit1.Text);

month:=StrToInt(Edit1.Text);

year:=StrToInt(Edit1.Text)

END;

 

Гораздо чаще приходится сохранять записи в файл. Если создать файл данных, состоящий из записей, то их в него можно будет записывать целиком, а не по полям:

 

TYPE Ta=RECORD…

VAR a:TA; f:FILE OF Ta;

AssignFile(f,’abc.dbf’);
Rewrite(f);
Write(f,a)

 

 

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

Все работающие на компьютере программы должны как можно быстрее вычислять адреса отдельных элементов переменных, относящихся к сложным типам данных (скажем, элементов массива или полей записи). В массиве адрес j-го элемента будет равен

 

j=i0+j´s, ( 3.1)

где i0 – адрес первого элемента массива, s - число слов памяти, занимаемых одним элементом.

 

Для упрощения вычислений желательно устранить медленную операцию умножения. Поэтому оптимальный случай - s=1 или s=int(s).

Для достижения указанного оптимального варианта применяют выравнивание данных(padding). При выравнивании s округляют до ближайшего большего целого (обозначается ). Предположим, что размер слова на нашем компьютере равен двум байтам, а размер, занимаемый одним элементом массива - пять байт или 2,5 слова. Выравнивание приведет к тому, что под каждый элемент будет выделено 3 слова, а "полслова" останутся незанятыми (Рис. 3.2).

 

Рис. 6.2. Выравнивание данных.

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

Коэффициент использования памяти u равен

 

( 3.2)

В идеале u=1 (вся память используется).

Итак, выравнивать данные или нет? Нужно рассмотреть следующие соображения:

1. Выравнивание требует лишней памяти
2. Отсутствие выравнивания требует организации доступа к части слова
3. Доступ к части слова приводит к заметному увеличению объема программы.

 



<== предыдущая лекция | следующая лекция ==>
Индуктивные функции | Создание пользовательских функций. Передача аргументов


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 1.852 сек.