В языке Паскаль типом-множеством называется множество всевозможных сочетаний объектов исходного множества. Число элементов исходного множества не может быть больше 256, а порядковые номера элементов (т.е. значение функции Ord) должны находиться в пределах от 0 до 255. Для задания типа-множества следует использовать зарезервированные слова set of , а затем указать элементы этого множества, как правило, в виде перечисления или диапазона.
Введя тип-множество, можно задать переменные или типизированные константы этого типа-множества. При задании значений константе-множеству ее элементы перечисляются через запятую (допустимо указывать диапазоны) и помещаются в квадратные скобки.
Множеству можно в программе присвоить то или иное значение. Обычно значение задается с помощью конструктора множества. Конструктор задает множество элементов с помощью перечисления в квадратных скобках выражений, значения которых дают элементы этого множества. Допустимо использовать диапазоны элементов.
Например, следующие конструкции являются конструкторами множеств:
[Plus,Minus]
[1..K mod 12, 15]
[Chr(0) .. Chr(31), 'A', 'B']
В каждое множество включается и так называемое пустое множество [ ], не содержащее никаких элементов.
Конструктор множества можно использовать и непосредственно в операциях над множествами.
Для множеств определены следующие операции:
+ – объединение множеств;
– – разность множеств;
* – пересечение множеств;
= – проверка эквивалентности двух множеств;
<> – проверка неэквивалентности двух множеств;
<= – проверка, является ли левое множество подмножеством правого множества;
>= – проверка, является ли правое множество подмножеством левого множества;
in – проверка, входит ли элемент, указанный слева, в множество, указанное справа.
Результатом операции объединения, разности или пересечения является соответствующее множество, остальные операции дают результат логического типа.
Выберите с учителем задачи для самостоятельного решения из ниже предложенного списка.
1. Дана непустая последовательность символов. Требуется построить и напечатать множество, элементами которого являются встречающиеся в последовательности цифры от 1 до 3 и от 17 до 100.
2. Дана непустая последовательность символов. Требуется построить и напечатать множество, элементами которого являются встречающиеся в последовательности знаки препинания.
3. Дана непустая последовательность символов. Требуется построить и напечатать множество, элементами которого являются встречающиеся в последовательности буквы от D до I.
4. TYPE natur=1..maxint;
Описать функцию digist(n), подсчитывающую количество различных (значащих) цифр в десятичной записи натурального числа n.
5. TYPE natur=1..maxint;
Описать процедуру print(n), печатающую в возрастающем порядке все цифры не входящие в десятичную запись натурального числа n.
6. Дана непустая последовательность слов из строчных русских букв; между соседними словами - запятая, за последним словом - точка. Напечатать в алфавитном порядке все гласные буквы, которые входят в каждое слово.
(Примечание: гласные буквы - а, е, и, о, у, ы, э, ю, я;
согласные - все остальные буквы, кроме й, ъ, ь)
7. Дана непустая последовательность слов из строчных русских букв; между соседними словами - запятая, за последним словом - точка. Напечатать в алфавитном порядке все согласные буквы которые не входят ни в одно слово.
(Примечание: гласные буквы - а, е, и, о, у, ы, э, ю, я; согласные - все остальные буквы, кроме й, ъ, ь)
8. Дана непустая последовательность слов из строчных русских букв; между соседними словами - запятая, за последним словом - точка. Напечатать в алфавитном порядке все согласные буквы которые не входят ни в одно слово.
(Примечание: гласные буквы - а, е, и, о, у, ы, э, ю, я; согласные - все остальные буквы, кроме й, ъ, ь)
9. Описать множество гласных и согласных букв русского языка, определить количество гласных и согласных букв в предложении, введенном с клавиатуры.
10. Опишите множество М(1..50). Сделайте его пустым. Вводя целые числа с клавиатуры, заполните множество 10 элементами.
11. Опишите множество Pr(1..20) и поместите в него все простые числа в диапазоне от а до b.
12. Составьте программу вычисления суммы мест, на которых в слове Х стоят гласные буквы.
13. Подсчитайте число разных букв в слове.
14. Опишите множества Rus и Lat, содержашие русские и латинские буквы. В цикле вводите русские и латинские буквы и выводите соответствующее сообщение. Выход из цикла – какая-либо клавиша, не являющаяся алфавитно-цифровой.
15. Дан двумерный массив. Найти и напечатать число, которое встречается в каждой строке. Если такого числа нет - напечатайте сообщение.
16. Задан целочисленный массив. Подсчитать число различных значений в массиве.
17. Даны две таблицы по 10 элементов в каждой. Найдите наименьшее среди тех чисел первой таблицы, которые не входят во вторую таблицу (считая, что хотя бы одно такое число есть).
Задание. Приготовьте файлы и листинги решенных задач по этой теме.
Будьте готовы ответить на следующие вопросы:
1. Что такое множество? Каким элементам должны удовлетворять все элементы множества? Преимущества использования типа множество?
2. Что такое базовый тип множества? Как он задается?
3. Какое множество называется пустым, как оно обозначается?
4. Как задается описание множественного типа?
5. Какие операции допустимы над множествами? Каков тип результатов выражений с применением операций над множествами?
6. Какие множества считаются равными, неравными? Имеет ли значение для сравниваемых множеств порядок следования элементов?
7. Для чего применяются операции ">=", "<="? В чем их отличие?
8. Для чего применяется операция in? Особенности ее применения.
9. Что называется объединением множеств?
10. Что называется разностью множеств?
Запись
Занятие 1. Комбинированный тип данных. Запись. Описание записи. Доступ к полям записи. Оператор With. Примеры решения задач
Довольно часто вполне оправданным является представление некоторых элементов в качестве составных частей другой, более крупной логической единицы. представляется естественным сгруппировать информацию о номере дома, названии улицы и городе в единое целое и назвать адресом, а объединенную информацию о дне, месяце и годе рождения – датой. В языке Паскаль для представления совокупности разнородных данных служит комбинированный тип запись.
Запись и массив схожи в том, что обе эти структуры составлены из ряда отдельных компонент. В то же время, если компоненты массива должны быть одного типа, записи могут содержать компоненты разных типов.
Приведем пример описания переменной, имеющей структуру записи:
Var
Address : Record
HouseNumber : Integer;
StreetName : String[20];
CityName : String[20];
PeopleName : String;
End;
Отметим, что поля StreetName и CityName имеют одинаковый тип: String[20]. Поскольку в описании эти поля могут располагаться в любом порядке, то можно сократить описание записи с полями одинакового типа. Сокращенное описание записи Address выглядит следующим образом:
Var
Address : Record
HouseNumber : Integer;
StreetName, CityName : String[20];
PeopleName : String;
End;
Каждая компонента записи называется полем. В переменной записи Address поле с именем HouseNumber само является переменной типа Integer, поле StreetName – двадцатисимвольной строкой и т.д.
Для того чтобы обратиться к некоторому полю записи, следует написать имя переменной и имя поля. Эти два идентификатора должны разделяться точкой.
Оператор, который присваивает полю HouseNumber значение 45, выглядит так:
Address.HouseNumber := 45;
Таким же образом присваиваются значения другим полям записи Address :
Address.StreetName := 'Профсоюзная';
Address.CityName := 'Сургут';
Address.PeopleName := 'Петрова Алла Ивановна';
Каждое поле записи Address можно рассматривать как обычную переменную, которую можно напечатать или использовать в расчетах. Вместе с тем запись может использоваться как единое целое. В этом случае надо ввести тип записи.
Предположим, имеется следующее описание:
Type
Date = Record
Day : 1..31;
Month : (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
Year : Integer;
End;
Var
HisBirth, MyBirth : Date;
После приведенного описания переменные HisBirth и MyBirth имеют тип записи Date. Помимо действий над отдельными полями записей HisBirth и MyBirth можно выполнять операции над всей записью. Следующий оператор присваивания устанавливает равенство значений записей HisBirth и MyBirth :
HisBirth := MyBirth;
Это присваивание эквивалентно следующей последовательности операторов:
HisBirth.Day := MyBirth.Day;
HisBirth.Month := MyBirth.Month;
HisBirth.Year := MyBirth.Year;
Для переменных одного типа можно проверить выполнение отношения равенства или неравенства ("=", "<>"). После выполнения приведенных выше присваиваний следующее булево выражение будет иметь значение True:
HisBirth = MyBirth;
Рассмотрите пример описания процедуры, которая получает запись в качестве параметра–значения и печатает дату в сокращенной стандартной форме, используя формат (MM-DD-YYYY).
Procedure WriteDate(OneDate : Date);
Begin
Write(Ord(OneDate.Month)+1);
Write('-');
Write(OneDate.Day:2);
Write('-');
Write(OneDate.Year:4);
End;
Так как на тип компонент массива не накладывается ограничений, то можно использовать массив, компонентами которого являются записи. Посмотрите описание такого массива:
Var
Birthdays : Array [1..Persons] of Date;
Чтобы обратиться к некоторому полю определенной записи массива, следует определить имя массива, индекс интересующей записи и имя необходимого поля.
Например, следующий оператор печатает содержимое поля Year записи Birthdays[3]:
Write(Birthdays[3].Year);
Примечание. Поля записи в свою очередь тоже могут быть массивами, множествами, записями.
Задание. Рассмотрите следующие описания:
Type
Date = Record
Day : 1..31;
Month :1..12;
Year : 1..9999
End;
Reminder = Record
Message : Array [1..5] of String;
Event : Date
End;
Var
Today : Date;
Memos : Array [1..100] of Reminder;
Calendar : Array [1..365] of Date;
Запишите в тетрадь, какой тип, если он определен, у следующих идентификаторов?
а) Today.Year
б) Memos [2]
в) Memos [4].Month
г) Calendar [200]
д) Memos [16].Message[2]
е) Memos [16].Message[1],[2]
ж) Calendar[1].Date
з) Memos [10].Event
Задание. Составьте программу, организующую ввод наиболее полной информации о людях и вывод интересующей информации на экран.
Приведем описание массива, компоненты которого являются записями:
Var
Payroll : array [1..Workers] of
record
FirstName, LastName : string;
Residence : record
HouseNumber : real;
StreetName, CityName : string;
StateName : Array [1..2] char;
ZipCode : integer;
end;
Phone : record
AreaCode, Exchenge : 1..999;
Line : 1..9999;
rnd;
PayScale : 'A' ..'G';
end;
Отметим, что два поля Residence и Phone являются записями. Как выполнить обращение к полям этих записей? Как распечатать условный шифр рабочего № 7? Поскольку это поле располагается во вложенной записи, то следует указать как имя самой записи, так и имя записи, в которую данная запись входит.
write (Payroll[7].Residence.ZipCode);
Аналогично приведенное присваивание корректирует шифр рабочего № 23:
Payroll[23].Phone.AreaCode :=804;
Оператор if, представленный ниже, выполняет проверку инициала рабочего № 58:
if Payroll[58].LastName[1] in ['T'..'Z'] Then ...
Соблюдение всех правил перечисления индексов и имен полей при составлении ссылок является довольно утомительным занятием, часто приводящим к ошибкам. В некоторых программах, содержащих большое количество обращений к одному и тому же полю, такое положение приводит к однообразному повторению. Чтобы облегчить выполнение многократных ссылок для описанных структур вводится оператор With (в переводе с английского – предлог "с").
Общая форма записи:
with <имя переменной> do <оператор>
В рамках оператора, определяемого внутри оператора With, к полям определяемой переменной можно обращаться просто по имени. Например,
with Payroll[7].Residence do
ZipCode := 2345;
for i := 1 to Workers do
with Payroll[i] do
if PayScale < 'G'
then
PayScale := Succ(PayScale);
Оператор with позволяет более компактно представлять часто используемые переменные. Посмотрите это на примере фрагмента программы, печатающего адрес рабочего № 14:
with Payroll[14].Residence do
begin
writeln(HouseNumber,' ',StreetName);
writeln(CityName,',',StateName,',',ZipCode);
end;
В рамках составного оператора, следующего за with, каждое обращение к имени поля автоматически связывается с записью Payroll[14].Residence. Печать адресов всех рабочих выполняется при помощи следующего оператора цикла:
for i := 1 to Workers do
with Payroll[i].Residence do
begin
writeln(HouseNumber,' ',StreetName);
writeln(CityName,',',StateName,',',ZipCode);
end;
Операторы with могут быть вложенными. Приведенные ниже три оператора эквивалентны друг другу:
1. Payroll[i].Residence.HouseNumber := 50;
2. with Payroll[i].Residence do
HouseNumber := 50;
3. with Payroll[i] do
with Residence do
HouseNumber := 50;
Однако недопустимым является использование вложенных операторов With, в которых указываются поля одного типа, поскольку возникает неоднозначность конструкции. По этой причине приведенное использование вложенных операторов With является неверным:
with Payroll[5] do
with Payroll[17]do
PayScale :='A';
Следует очень внимательно подходить к использованию вложенных операторов With, применение которых не только может привести к ошибкам, но также к потере наглядности структуры программы. Хотя оператор With является стандартным средством сокращения, его полезность должна еще проявиться. Конечной целью всякого хорошего программиста является написание не только короткой, но и понятной программы.
Рассмотрите решение задачи.
Задача. В массиве хранятся данные об учениках класса: школа, фамилия, класс. Вывести список учеников, которые учатся в восьмом классе.
Program LipovsevM;
Uses
Crt;
Type
Uchenik=record
Shkola : integer;
Fam : string[15];
Klass : integer;
end;
Var
I,n,a,j : integer;
Massiv : array[1..100] of Uchenik;
Рrocedure Poisk;
Begin
for i:=1 to n do
if massiv[i].klass=8
then
with massiv[i] do
writeln(Shkola:4,' ',Fam:15,' ',klass);
End;
Begin
ClrScr;
writeln('Введите число учеников ');
write('->');
read(n);
for i:=1 to n do
begin
writeln('Введите через пробел номер школы и фамилию ученика ');