Pascal: Занятие № 13. Записи в Паскале

На занятии будет рассмотрена работа со сложными типами данных в Паскале — записями, будут разбираться конкретные решенные примеры задач

Записи в Паскале

Записи в Паскале – структурированный комбинированный тип данных. Запись состоит из определенного числа компонент, называемых полями, которые могут быть разного типа.

Описание записи в Паскале

Общий вид описания типа record в Паскаль:

1
2
3
4
5
var <имя_записи> = record
     <имя_поля1>:<тип_поля1>;
     <имя_поля2>:<тип_поля2>;
     ...
end;

Но лучше создавать пользовательский тип записи и использовать переменную данного типа:

1
2
3
4
5
6
type <имя_записи> = record
     <имя_поля1>:<тип_поля1>;
     <имя_поля2>:<тип_поля2>;
     ...
end;
var <имя_переменной>: <имя_записи>;

Рассмотрим примеры объявления и создания записи в Паскале.

Пример: создать запись для работы с датами. Запись должна быть с тремя полями, соответствующими месяцу, дню и году.
1
2
3
4
5
6
type mydate = record
    month: 1..12;
    day: 1..31;
    year: integer
end;
var d:  mydate;

В примере переменная mydate — запись, состоящая из трех полей: month, day и year. Каждое поле содержит соответственно данные: целое число в пределах от 1 до 12 — номер месяца (интервальный тип), целое число от 1 до 31 — число месяца (интервальный тип), целое число — год.

Обращение к полям записи

Пример: Для записи из предыдущего примера задать конкретное значение и вывести его на экран в удобочитаемом виде.
1
2
3
4
5
6
7
8
9
10
11
12
type mydate = record
    month: 1..12;
    day: 1..31;
    year: integer
end;
var d:  mydate;
begin
  d.day:=1;
  d.month:=12;
  readln(d.year);
  writeln(d.day,'/',d.month,'/',d.year);
end.
record 1. Создать анкетные данные о студенте(type anketa):
запись с полями: Ф.И.О. (fio — строковый тип), дата рождения (birth — строковый тип), курс (kurs — значения 1..5). Создать переменную student созданного типа. Выводить значения полей на экран.

Записи в виде двумерной таблицы

Часто записи используются в виде двумерной таблицы, каждый столбец которой имеет свой тип.
Таким образом, если описана двумерная таблица, то ее начальные значения задаются как вектор, каждый компонент которого является записью.

Рассмотрим пример использования записи-таблицы:

Пусть дана таблица хранения дней рождения разных людей:

1 2 3
Day 2 14 14
Month 1 2 12
Year 1985 1987 1989

Задать данные таблицы в виде записи. Объявить массив дней рождения и вывести дату первого дня рождения.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type zap1= record
                day:1..31;
                month: 1..12;
                year: 1900..2100;
 
          end;
var  birthdays:array[1..100] of zap1;
begin
            birthdays[1].day:=2;
            birthdays[2].day:=14;
            birthdays[3].day:=14;
            birthdays[1].month:=1;
            birthdays[2].month:=2;
            birthdays[3].month:=12;
            birthdays[1].year:=1985;
            birthdays[2].year:=1987;
            birthdays[3].year:=1989;
            writeln(birthdays[1].day);
end.
record 2. Для предыдущего задания (record 1) задать таблицу значений с данными о нескольких студентах, и, использовав массив, вывести все данные о студентах в удобочитаемом виде.

Использование конструкции with при работе с записями

При работе с записями есть возможность избавиться от постоянного префикса в виде обращения к названию переменной. Сравним два примера:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    type zap1= record
                    day:1..31;
                    month: 1..12;
                    year: 1900..2100;
     
              end;
    var  my_birthday: zap1;
    begin
      my_birthday.day:=17;
      my_birthday.month:=4;
      my_birthday.year:=1993;
    ...
    end.
  2. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    type zap1= record
                    day:1..31;
                    month: 1..12;
                    year: 1900..2100;
     
              end;
    var  my_birthday: zap1;
    begin
    with my_birthday do
    begin
        day:= 17;
        month:= 3;
        year:= 2004;
    end;
    ...
    end.

Во втором примере значительно проще обращаться к полям записи, избавившись от префикса, благодаря with

record 3. Создать запись toy с информацией об имеющихся в продаже игрушках (название товара (name), цена товара (price) и возрастной диапазон (age), для которого игрушка предназначена). Заполнить несколько товаров. Вывести данные на экран. Использовать массив и конструкцию with.

Внимание: Ключевое слово with при работе с массивами:

with <название массива>[1] do
begin
    <поле1>:=...;
    <поле2>:=...;
    ...
end;

Записи при работе с файлами

Пример: Пусть требуется создать файл из записей, данные которых вводятся с клавиатуры.
Структура записи файла следующая:
— фамилия;
— телефон.
Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
type
    t_subscriber = record
      surname: string[20];
      tel: LongInt;
    end;
 
var
    subscriber: t_subscriber;
    f: file of t_subscriber;
    i: Integer;
 
begin
  Assign(f,'notebook.dat');
  Rewrite(f);
  for i:=1 to 5 do begin
    with subscriber do begin
      Write('Surname: ');
      ReadLn(surname);
      Write('Phone: ');
      ReadLn(tel);
    end;
    Write(f, subscriber);
  end;
  Close(f);
end.
record 4. Выполнить предыдущее задание с игрушками (запись toy), записывать данные в файл, а затем считывать их из файла и выводить на экран.

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

// Запись в файл:
write(f, toys[1]);
// Считывание из файла:
read(f,toys_1[1]);

Рассмотрим пример последовательного доступа к типизированному файлу с использованием записей:

Пример: В анкету подписчиков сначала записать данные (фамилия, телефон), а затем считать эти данные. Если номер телефона указан без двойки впереди, то добавить к нему двойку: если номер 236244475 — ничего с ним не делать, если же номер 36233357, то необходимо получить номер 236233357. Исправленную информацию выводить на экран.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
type
    t_subscriber = record
      surname: string[20];
      tel: integer;
    end;
 
var
    subscriber: t_subscriber;
    f: file of t_subscriber;
    s: string;
 
begin
  Assign(f,'z:\pascal.dat');
  rewrite(f);
  subscriber.surname:='ivanov';
  subscriber.tel:=36233357;
  write(f,subscriber);
  subscriber.surname:='petrov';
  subscriber.tel:=236244475;
  write(f,subscriber);
  close(f);
  Reset(f);
  while not Eof(f) do begin
    Read(f, subscriber);
    with subscriber do begin
      Str(tel,s);
      if Copy(s,1,3) = '362' then
        tel := tel+2000000;
    end;
    Seek(f,FilePos(f)-1); // возврат указателя назад
    Write(f,subscriber);
    Writeln(subscriber.surname, ' ',subscriber.tel);
  end;
  Close(f);
end.

Множества в Паскале

Множества в Паскале — это некоторое собрание элементов, одно и того же базового типа.

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

Размер множества в Turbo Pascal всегда ограничен некоторым предельно допустимым количеством элементов. Во множествах допускаются только такие элементы, порядковые значения которых не выходят за границы 0..255. В Turbo Pascal в целочисленных множествах могут присутствовать только числа от 0 до 255.
Отрицательные элементы множеств в Turbo Pascal не допускаются. Поэтому базовыми типами не могут быть типы shortint, integer, longint.

Таким образом, если необходимо множество целочисленных объектов, то базовый тип для Turbo Pascal должен быть объявлен как диапазон типа byte. Для множеств, содержащих символы, базовым типом должен быть тип char .

Пример: Создать множество дней недели, базовым типом которого является перечисляемый тип из названий дней недели.
1
2
3
4
5
type week_days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
var work_days: set of week_days;
begin
  work_days:=[Mon, Wed, Thu];
end.

Из примера видно, что множества (тип set) задаются путем перечисления значений, разделенных запятыми и заключенных в квадратные скобки.

Синтаксис:
name_set:=[expr1, expr2, … exprn];

Важно! Множества нельзя выводить на экран и считывать оператором read
Пример: Создать множество, базовым типом которого является символьный тип char. Объявить две переменные данного множества
1
2
3
type letters = set of char;
var ch1,ch2:letters;
...

Переменные ch1 и ch2 из примера также не могут быть выведены на экран и их значения не могут быть запрошены при помощи оператора read.

Возникает логичный вопрос: как же тогда работать с множествами в Паскале?

Чтобы ответить на данный вопрос, сначала рассмотрим операции, выполняемые над множествами.

Действия над множествами

Их три:

  • объединение (+);
  • пересечение (*);
  • и разность (-).
  • Объединение двух множеств A и B (A + B) – это новое множество, состоящее из элементов, принадлежащих множеству A или B либо тому и другому одновременно
    множества в Паскале

    Пример:

    1
    2
    3
    4
    5
    6
    7
    
    var ch1,ch2, ch3: set of char;
    begin
       ch1:=['a', 'b', 'd'];
       ch2:=['m', 'd', 'e'];
       ch3:=ch1 + ch2 + ['k', 'n'];
    {Результат: ch3 = ['a', 'b', 'd', 'm', 'e', 'k', 'n']}
    end.

    Пересечение двух множеств A и B (A * B) – это множество, состоящее из элементов, одновременно принадлежащих множествам A и B.
    множества в Паскале: пересечение

    Пример:

    1
    2
    3
    4
    5
    6
    7
    
    var ch1, ch2, ch3: set of char;
    begin
       ch1:=['a', 'b', 'd'];
       ch2:=['m', 'd', 'e'];
       ch3:=ch1 * ch2;
    {Результат: ch3 = ['d'] }
    end.

    Разность двух множеств A и B (A – B) – это новое множество, состоящее из элементов множества A, не вошедших в множество B.
    множества в Паскале: разность

    Пример:

    1
    2
    3
    4
    5
    6
    
    var ch1, ch2, ch3: set of char;
    begin
    ch1 := ['a', 'e', 't']; 
    ch2 := ch1 – ['e']; { ['a', 't'] } 
    ch3 := ['m', 'n', 't'] – ch2; { ['m', 'n'] }
    end.

    Множества и операция IN в Паскале

    Операция in необходима для поиска определенного элемента в величине типа set, т.е. в множестве.

    Так, если x есть элемент множества a, то (x in a) дает true

    Пример: создать перечисляемый тип из дней недели и множество из рабочих дней недели (базовым типом которого является перечисляемый тип дней недели). Определить, является ли понедельник рабочим днем.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    type
       week_days=(Mon, Tue, Wed, Thu, Fri);
    var 
       work_days: set of week_days;
    begin
    work_days:=[Mon, Wed];
    if Mon in work_days then
        writeln ('понедельник - рабочий день')
    else
        writeln ('понедельник - не рабочий день')
    end.
    Пример: Тот же пример решить с использованием типа byte в качестве базового типа.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    var
      work_days,days_off: set of byte;
    begin
    work_days:=[1, 2];
    days_off:=[6, 7];
    if 1 in work_days then
        writeln ('понедельник - рабочий день')
    else
        writeln ('понедельник - не рабочий день');
    if 6 in days_off then
        writeln ('суббота - выходной день')
    else
        writeln ('суббота - не выходной день');
    end.
    Пример: Необходимо вывести предложение «На ветке … ворон» с правильным окончанием в зависимости от введенного количества ворон:

  • 1 — на ветке 1 ворона
  • 2 — на ветке 2 вороны
  • 10 — на ветке 10 ворон
  • Показать решение

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    var
       voron, vorona, voroni: set of byte;
       number:integer;
    begin
    voron:=[5,6,7,8,9,10];
    vorona:=[1];
    voroni:=[2,3,4];
    writeln ('введите количество ворон');
    readln(number);
     
    if number in voron then
        writeln ('на ветке ', number,' ворон');
    if number in vorona then
        writeln ('на ветке ', number,' ворона');
    if number in voroni then
        writeln ('на ветке ', number,' вороны')
    end.
    set 1.Говоря о количестве лет на русском языке, после числа используют слова «год», «года» и «лет». Например, 1 год, но 10 лет или 3 года.

    Требуется написать программу, которая в зависимости от числа добавляет правильное окончание.

    Пояснение:
    Последняя (или единственная) цифра равна 1 — слово «год» .
    Оканчивается на 2, 3, 4 — «года».
    Остальные — слово «лет».
    Числа 11, 12, 13, 14 (или имеющие такой остаток от деления на 100) — «лет».

    Пример: Дана строка. Сохранить в ней только первые вхождения символов, удалив все остальные (т.е. оставить все уникальные символы, чтобы не повторялись).
    Показать решение

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    var m : set of char;
        s : string; i : byte;
    begin
        write('строка: ');
        readln(s);
        m :=[];
        i := 1;
        while i <= length(s) do
        if s[i] in m then delete(s, i, 1)
                        else begin m:=m+[s[i]]; i := i + 1 end;
        writeln(s)
    end.
    set 2. Запросить у пользователя ввести строку. Проверить ее на наличие недопустимых символов. В качестве первого символа можно использовать только буквы и знак подчеркивания. Остальные символы могут быть буквами, цифрами и знаком подчеркивания. Использовать заданное начало программы. (так, строка равная '_sdfs234' вернет значение true, тогда как строка равная '_sdfs`234' вернет false)

    Начало программы:

    type t_chs = set of Char;
    const
      lett: t_chs = ['a'..'z','A'..'Z','_'];
      num: t_chs = ['0'..'9'];
    var
      str: string;
      i: byte;
      flag: boolean;

    Описание переменных:
    str — проверяемая строка;
    flag — переменная-флаг для хранения информации о том, корректна ли строка.
    Тип и константы:
    t_chs — множество всех возможных символов;
    lett — множество, содержащее английские буквы и знак подчеркивания;
    num — множество, содержащее цифры.

    6 комментариев для “Pascal: Занятие № 13. Записи в Паскале”

    1. {Для любого количества ворон:}
      var
      vorona, voroni: set of byte;
      number: integer;
      x: string;

      begin
      vorona := [1];
      voroni := [2, 3, 4];
      x := »;
      writeln(‘введите количество ворон’);
      readln(number);
      if (number mod 100 14) then
      if number mod 10 in vorona then
      x := ‘а’
      else if number mod 10 in voroni then
      x := ‘ы’;
      writeln(‘на ветке ‘, number, ‘ ворон’ + x)
      end.

    2. Объясните, пожалуйста. Вот вывод в файл имеет структуру (f,a)
      А как написать, чтобы в один файл записывалось на одну строку несколько данных?
      Спасибо за ответ

    Обсуждение закрыто.