На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила ЧаВО (FAQ) разделов Паскаля
В этом разделе разрешено создавать только темы, в которых описано РЕШЕНИЕ какой-либо общей проблемы, или описание какого-либо аспекта языка Паскаль.
Обсуждение уже созданных тем разрешено, но только конструктивное, например указание на ошибку или уточнение имеющегося текста.

Стоит почитать Структуры данных
Модераторы: volvo877, Romtek
  
> Record , Тип запись, как он устроен.
    Тип-запись. Описание:
    ExpandedWrap disabled
      type some_record=record
        field1:type1;
        ......
        fieldN:typeN;
      end;
    Технически, запись - объединение переменных разных типов, объединенных одним смыслом (например, точка в пространстве, город, человек), в одной переменной, под одним именем.
    Для того, чтобы разобраться, что же за тип такой record давайте представим себе такую задачу:

    Допустим нам нужно создать себе программку - блокнотик, в котором были бы записаны краткие описания всех наших друзей (не больше 100 человек). Их имена, телефоны, адреса, краткое описание. На данный момент мы не знаем что такое record и будем решать эту задачу без него.

    Что будем делать ?
    Ну очевидно, что если у нас есть друзья, и их не больше ста, то будут массивы. Это ясно. Как мы будем хранить в памяти наших друзей ? Самый простой способ:
    Массив из 100 элементов с строками - именами друзей. Массив из 100 элементов с строками - адресами друзей. Массив из 100 элементов с цифрой - телефоном, и массив из 100 элементов с строками - кратким описанием друга.
    Вот например:
    ExpandedWrap disabled
      var
       FriendName=array[1..100] of string;
       FriendPhone=array[1..100] of longint;
       FriendAddress=array[1..100] of string;
       FriendInfo=array[1..100] of string;

    Всё это нормально. Но далеко не удобно. Посмотрите на код - в нём целых 4 одинаковых повторения - 4 одинаковых массива, с одним размером. И вот тут мы подходим к пониманию типа - record. Давайте я напишу такой пример, и мы его разберём:
    ExpandedWrap disabled
      type
       FriendType=record
         Name:String;
         Phone:Longint;
         Address:String;
         Info:String;
       end;
      var
       Friends:array [1..100] of FreindType;

    В этом примере я создал новый тип - record, и назвал его FriendType. А потом объявил массив из 100 таких элементов, под названием Friends. Мой новый тип является как бы набором всех свойств друга в одном целом. И если я объявляю какую либо переменную такого типа, то она преобетает все свойства, описанные в этом типе. В моём примере переменная Friends[1] будет иметь свойства - Name, Phone, Address, Info. Для доступа к ним нужно указать имя переменной, и через точку называние свойства. Например:
    ExpandedWrap disabled
      Friends[1].Name, или Friends[1].Phone и т.д.


    Поля в записи располагаются последовательно в отведенной под переменную области памяти, в порядке их описания в типе. С этим связаны сложности при чтении и записи в файл, если описания типов в разных программах не совпадают по последовательности полей или различаются по описанным типам (например, длиной строки).
    Размер записи есть сумма размеров всех ее компонентов.
    Обращение к записи может быть цельным, если нужно переписать ее всю, целиком она может быть использована лишь в операторе присваивания. Обычно обращаются лишь к определенным полям, в этом случае запись выглядит как a_record.field1, где a_record - переменная типа запись, а field1 - точная запись имени поля в определении типа. Результат является выражением типа поля, т.е. типа type1. Точка между именем переменной и именем поля обязательна. Поля записи можно передавать в процедуры как параметры-переменные.
    Для упрощения записи длительных преобразований с использованием одной переменной типа запись в Турбо-Паскале есть оператор WITH (в стандартном Паскале его нет) со следующим синтаксисом:
    ExpandedWrap disabled
      WITH var1{,var2,...,varN} DO (оператор);
    Внутри оператора под WITH можно использовать имена полей как самостоятельные переменные. Например:
    ExpandedWrap disabled
      type
        recordtype=record
          x:integer;
          y:real;
          s:string[6];
        end;
      var verylongvariablename:recordtype;
      ...
      with verylongvariablename do begin
        x:=trunc(pow(y,4.5))mod 4097;
        str(x,s);
      end;
    Вроде бы намного проще? НО: На этом операторе особенно часто "валят" студентов преподаватели, так что аккуратнее с ним!
    Если в программе есть переменная с именем, совпадающим с именем поля записи, то внутри оператора WITH она становится недоступной. Пример:
    ExpandedWrap disabled
      type r=record
        a,b:word;
        x:real;
      end;
      var x:word;
          t:r;
      begin
        t.x:=1;
        x:=2;
        with t do writeln(x);
      end.
    Программа выведет значение 1 (компилятор ВР7.0).
    При вложении операторов WITH и совпадении полей записей в их параметрах приоритет имеет внутренняя переменная. Если указываются несколько переменных в одном операторе WITH, то при конфликте имен при обращении к спорному полю нужно указать исходную переменную (несмотря на WITH).
    Паскаль (начиная с Турбо 6.0, может раньше) позволяет делать в типе запись вариантную часть. Пишется это так:
    ExpandedWrap disabled
      type some_record=record
        field1:type1;
        ......
        fieldN:typeN;
        case (тип или объявление переменной) of
          value1:(объявления переменных);
          value2:(...);
          ..............
          valueN:(....);
      end;
    При этом все объявления в одном варианте располагаются последовательно в памяти, а разные варианты - в одной, с общего смещения!!! Таким образом, тип-запись можно использовать для "полуявного" преобразования типов, например можно рассматривать тип real как 6 самостоятельных байт. Размер вариантной части есть наибольший размер объявлений внутри вариантов. Если в конструкции case стоит объявление переменной, то она считается объявленной в основной части записи, ее значение никак не влияет на работу вариантной части. Значения valueX могут быть любого типа. В книге В. Фаронова приводится такая конструкция:
    ExpandedWrap disabled
      type rec2=record
        c:longint;
        case x:byte of
          1: (d:word);
          2: (e: record
                    case boolean of
                      3:(f:rec1); {я опустил этот тип}
                      3:(g:single);
                      '3':(c:word)
               end)
      end;
    end стоит в записи только как признак конца описания типа, ставить его после окончания вариантной части не надо.
    Вывод достаточно прост: Record - тип с большими и гибкими возможностями, в то же время достаточно защищен от ошибок программиста. Поэтому он является основным типом в серьезных проектах, но до тех пор, пока не появились объекты. О них речь позже.
    Сообщение отредактировано: Romtek -
      Эххх ну люблю я наглядность, что тут поделать :)
      А запись в записи (или, по научному - вложенная запись)
      К примеру заменим Phone на AllPhones: Phones;
      ExpandedWrap disabled
        type
         Phones = record
           Home,
           Work,
           Mobile: String[10];
         end;
         
         FriendType = record
           Name,
           Address,
           Info: String[30];
           AllPhones: Phones;
         end;
         
        var
         Friends:array [1..100] of FriendType;
         
        begin
         {Заполняем запись № 1}
          with Friends[1] do
          begin
            Name := 'Вася';
            Address := 'Речная';
            AllPhones.Home := '012-21552';
          end;
        end.
      Сообщение отредактировано: romtek -
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0487 ]   [ 16 queries used ]   [ Generated: 25.04.24, 13:49 GMT ]