Программирование на Lazarus

Основы кода

Показывать лекцию целиком

Цель лекции

Знакомство с типами данных. Применение переменных, констант, комментариев.

Типы данных

Наверное, вы понимаете, что умение пользоваться компонентами - это еще не программирование? Разработка пользовательского интерфейса - настройка формы, размещение на ней компонентов, организация меню, придание всему этому привлекательного вида и удобства использования - всё это, скорее, дизайн. Программирование - это знание языка, умение писать исходный код. Этим мы сегодня и займемся.

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

В Паскале существует всего несколько стандартных типов, с которыми может работать программист:

  • Целые числа (числа без запятой: 5; -12; 0)
  • Вещественные числа (числа с запятой: 5,3; -3,14; 0,0)
  • Символы (отдельные буквы или другие символы: "Б", "z", "", "/")
  • Строки (группы символов: "Это строка", "This is a text")
  • Логический тип (может принимать значение либо Ложь - False, либо Истина - True)
  • Lazarus основан на Object Pascal, который имеет множество дополнительных типов данных. Например, тип Дата-Время, коллекции строк, файлы, записи, классы и так далее. Со многими типами мы будем знакомиться в течении курса, в порядке возрастания сложности материала.

    Элементы программы

    Программа на языке Object Pascal может содержать следующие стандартные элементы:

  • Служебные (зарезервированные) слова
  • Идентификаторы
  • Типы
  • Переменные
  • Константы
  • Комментарии
  • Метки
  • Подпрограммы
  • Служебные (зарезервированные) слова - это такие слова, которые являются частью языка и применяются для обозначения различных инструкций или элементов программы. Примеры служебных слов: as, class, if, for, var, array, unit, interface, uses.

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

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

    Правило. Для идентификаторов разрешено использовать только символы латинского алфавита, цифры и знак подчеркивания. Причем первым символом идентификатора не может быть цифра. Строчные и заглавные символы не различаются, то есть myvar, MyVar и MYVAR - это один и тот же идентификатор.

    Примеры правильных идентификаторов:

  • MyVar
  • _perem
  • a2
  • MinimalnayaZarplata
  • Примеры неправильных идентификаторов:

  • Зарплата (не латинские символы)
  • 2a (первый символ - цифра)
  • My perem (в идентификаторе неразрешенный символ - пробел)
  • Типы - это специальные конструкции языка, указывающие компилятору, сколько памяти нужно зарезервировать для объявляемого элемента, например, переменной, массива, константы. Типами могут быть стандартные типы Паскаля, расширенные типы Объектного Паскаля или типы данных, объявленные пользователем. Мы будем знакомиться с разными типами данных на протяжении всего курса.

    Примеры типов: integer (целое число), real (число с запятой), string (строка) и т.п.

    Переменные

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

    Все данные, с которыми работает программа, располагаются в ОЗУ (Оперативное Запоминающее Устройство, Оперативная память) компьютера. Когда пользователь загружает программу, то в оперативную память считываются все инструкции программы и данные, которые в ней используются. Данные располагаются в памяти по различным адресам, которые фактически, представляют собой цифры. Так, первый байт памяти располагается под номером 1, второй под номером два и т.д. Однако не все данные занимают только один байт, есть и двухбайтовые, и четырехбайтовые данные, и даже больше. Именно поэтому так важно указывать тип данных - компилятор должен знать, сколько байт в памяти будет занимать ваш элемент, сколько места ему нужно выделить. Допустим, нам нужен некий элемент данных в 2 байта, и компьютер поместит его в ОЗУ по адресу, например, 1000000. Значит, когда потребуется узнать содержимое этого элемента, компьютер должен обратиться к ячейке памяти под номером 1000000, и считать оттуда два байта.

    В процессе работы программы эти данные могут меняться. Поэтому нам нужен некий контейнер, ящик определенного размера, где мы будем хранить данные. Эти данные будут меняться, а адрес ящика в памяти останется неизменным, пока работает наша программа. Такой ящик и называется переменной - элементом, чьи данные могут меняться. Итак,

    Переменная - это ячейка оперативной памяти, которая занимает соответствующее её типу количество байт. Данные в этой ячейке могут меняться, а адрес размещения в ОЗУ остается неизменным, пока работает программа.

    Чтобы программист не мучался с адресацией этих ячеек, в Паскале переменным присваивается имя - идентификатор. Когда мы объявляем переменную с определенным именем, компьютер запоминает это имя и ассоциирует его с реальным адресом в памяти, и количеством занимаемых переменной байт. А когда мы считываем данные переменной MyPerem, то компьютер сам находит нужный участок памяти и считывает оттуда нужное количество байт.

    Переменные объявляются в разделе var (англ. variable - переменная). Объявление имеет следующий синтаксис (конструкцию):

    var
       Имя_перем_1: Тип_1;
       Имя_перем_2: Тип_2;
       …
       Имя_перем_n: Тип_n;
        

    То есть, в объявлении мы указываем имя создаваемой переменной, затем символ "двоеточие", а затем тип данных этой переменной. Если же нам нужно объявить несколько переменных одного типа, то мы можем перечислить их в одном операторе через запятую:

    var
       перем_1, перем_2,… перем_n: Тип;
        

    Объявление переменных в разных строках - это не правило языка, всё описание можно уместить и на одной строке:

    var перем_1: Тип_1; перем_2: Тип_2;
        

    Но такой код будет сложно читать, он труден для восприятия. Поэтому предыдущие примеры все же предпочтительней, когда каждый оператор описывается на своей строке, программа становится более "читабельной".

    Совет. Давайте переменным и другим элементам и конструкциям, которые вы описываете, осмысленные имена, а не просто непонятные наборы символов!

    Например, если мы хотим хранить в переменной минимальную заработную плату, то разумно назвать такую переменную MinZarPlat, для переменной с вашим именем - MyName или MoeImya - зависит от вашей фантазии, лишь бы вам самим было понятно, для чего вы вообще создавали эту переменную. Ведь это только поначалу вы будете помнить, что за переменные вы используете. А если вы откроете свой проект через год? Или его откроет ваш друг или коллега? Что хранится в переменной a? Для чего создана переменная d3? Такие непонятные идентификаторы затрудняют восприятие программы и категорически не рекомендуются к использованию.

    Исключение могут составить переменные, которые обычно создаются в качестве счетчиков для циклов, например, или для каких-то коэффициентов. Такие переменные традиционно называют i, k, l (или др. символами английского языка).

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

    C:\Education\02-02\

    Загрузите файл проекта Hello.lpi - это приведет к загрузке Lazarus и открытию в нем данного проекта. На переднем плане должен оказаться Редактор кода (если это не так, нажмите <F12>, чтобы переключиться с формы на код). Вы можете сразу заметить, что одна переменная у нас уже объявлена:

    (рис 4.1) Переменная fMain

    Вот ведь любопытно: у нас есть форма fMain, да еще и переменная с таким же именем! Дело в том, что компилятор FPC рассматривает нашу форму, как переменную. Обращение к этой переменной - это обращение к самой форме.

    Теперь опустим курсор до обработки события нажатия на кнопку Button1 и немного изменим код этого события:

    (рис 4.2) Новый код события OnClick кнопки Button1

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

    procedure TfMain.Button1Click(Sender: TObject);
    var
      MyName: String;
    begin
      MyName:= 'Привет, ' + Edit1.Text + '!';
      ShowMessage(MyName);
      MyName:= 'Рады вас видеть, ' + Edit1.Text + '!';
      ShowMessage(MyName);
    end;
        

    Как видите, здесь мы использовали переменную MyName с типом String (строка). Мы дважды присваивали ей разные значения, а затем считывали их, чтобы вывести в сообщении. Где именно нужно объявлять переменные, мы поговорим в лекции №8 (Подпрограммы), там же обсудим такое важное понятие, как область видимости переменной. Пока лишь учтите, что при использовании событий, переменные нужно объявлять до служебного слова begin, а использовать саму переменную нужно после этого служебного слова.

    Оператор присваивания значения

    На примере вышеприведенного кода мы могли заметить, что значения переменным присваиваются с помощью оператора присваивания

    :=
        

    То есть, двоеточие и знак "равно", следующий сразу за ним, без пробелов. Присвоение происходит справа-налево: вначале вычисляется значение, указанное ПОСЛЕ этого оператора, затем оно присваивается переменной, указанной ДО оператора присваивания. Например:

    var
       i: integer;  //объявили переменную с типом integer - целое число
    begin
       i:= 3;  //присвоили этой переменной значение 3
        

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

    var
       i: integer;
    begin
       i:= 3;
       i:= 2 * 5 + 36 * i;  //сложное выражение
        

    Тут мы объявили целочисленную переменную i. Этой переменной мы присвоили значение 3. Потом мы присвоили новое значение, которое сначала высчитывается компьютером из сложного выражения, а затем только присваивается переменной. Какое же значение теперь в i? Давайте считать. Из уроков математики мы знаем, что сначала вычисляются такие операторы, как умножение и деление, а только потом - сложение и вычитание. То есть, сначала высчитывается 2 * 5 = 10 (для компьютера знак "*" - это умножение, если кто-то не знает). Затем вычисляется 36 * i, а i - это 3, мы делали это присваивание строчкой выше. Так что получаем 36 * 3 = 108. Затем складываем эти значения: 10 + 108 = 118. Именно столько и попадет, в конце концов, в переменную i.

    Здесь у кого-то может возникнуть вопрос: а почему автор советовал давать переменным осмысленные имена, а сам назначил простое имя i? Вопрос справедливый, отвечу так. Это - не реальная программа со множеством подпрограмм и переменных, это простой пример с одной переменной, и мы в любом случае, не запутаемся. Кроме того, переменная была назначена не для какой-то конкретной цели, а лишь для демонстрации присваивания ей значения. Поэтому и имя у переменной простое. В более сложных примерах и в лабораторных работах я постараюсь придерживаться своих же рекомендаций.

    Если вы заметили, то в нашей программе мы также присваивали переменной не просто значение, а составное выражение:

    MyName:= 'Привет, ' + Edit1.Text + '!';
        

    Здесь мы строку "Привет, " соединяли с тем, что хранилось в поле ввода Edit1, добавляли восклицательный знак, а результат уже присваивали переменной MyName. Обратите внимание, что после слов "Привет" мы вписали не просто запятую, а запятую с последующим пробелом. Если бы мы не указали этот пробел, то в результате текст сливался бы, а это не очень красиво:

    Привет,Дмитрий!
        

    Константы

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

    В математике константа (лат. constanta - постоянная, неизменная) - некоторая величина, не изменяющая своё значение в рамках рассматриваемого процесса. В программировании константа имеет то же значение. Причем константы бывают двух типов: простые неименованные) и именованные.

    Простая константа представляет собой готовое значение, например,

    i:= 3; //здесь 3 - это числовая константа
    s:= 'строка'; // 'строка' - строковая константа
        

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

    Именованная константа - несколько более сложное понятие. Фактически, это такая же ячейка оперативной памяти, как и переменная, но значения в этой ячейке не могут меняться. Применение таких констант полезно в двух случаях:

  • Когда не хочется запоминать реального значения, или когда оно довольно длинное. Например, число ПИ равно 3,141 592 653 589 793 238 462 643 383 279 502 88. Хочется вам запоминать такое значение? Не проще ли определить константу pi и записать в нее это число? Тогда в дальнейшем, вместо указания этого числа мы будем указывать константу pi. Компилятор сам подставит нужное значение вместо имени этой константы.
  • Когда какое-то значение используется в программе без изменений, но со временем оно может стать другим. Например, минимальная зарплата (МРОТ - Минимальный Размер Оплаты Труда) на 2013 год принята в размере 5205 руб. Наша программа, к примеру, вычисляет зарплату сотрудников, для этого МРОТ может умножаться на различные коэффициенты, например, коэффициент выслуги лет. Поскольку такое вычисление будет многократным - для каждого сотрудника отдельно, да еще с различными условиями (отпуск, больничный, премия и т.п.), то разумно объявить константу mrot со значением 5205, и в дальнейшем использовать ее вместо реального значения. Почему такой подход удобен? Во-первых, наша программа может попасть в другой регион, а там может оказаться свой размер МРОТ. Например, в Ленинградской области принят МРОТ в размере 6800 руб., а в г. Москве и вовсе 12200 руб. Во-вторых, на 2014 год размер МРОТ наверняка увеличится, а значит, его значение изменится. В обоих этих случаях достаточно будет изменить значение константы в начале модуля, и во всех местах кода, где эта константа применяется, автоматически будет использовано новое значение. Нам не придется кропотливо выискивать по всему коду, где же мы использовали при расчетах размер МРОТ, чтобы вписать туда новое значение.
  • Итак, правило:

    Константа - область оперативной памяти, значение в которой остается неизменным, пока программа работает.

    Стоит отметить, что когда программа завершает свою работу, все ячейки, выделенные под переменные и под константы, очищаются. Вернее, перестают учитываться операционной системой. То есть, если другая программа захочет их использовать, Windows это разрешит. Но до тех пор, пока эта программа не запишет в ячейки уже свои значения, там будет "мусор" - набор непонятных данных. Вот почему очень важно не только объявлять переменные (константы), но и присваивать им начальные значения.

    Константы объявляются в разделе const (англ. constants - постоянные, константы), причем этот раздел должен располагаться до раздела var. Объявление константы и присвоение ей значения в отличие от переменных, происходит одновременно:

    const
      mrot = 5205;
        

    Здесь мы создали раздел констант, в котором объявили константу mrot, и сразу же присвоили ей значение 5205. Как видите, вместо оператора присваивания ":=", как это было у переменных, здесь используется простой знак "равно", а тип константы не указывается. Компилятор сам, в зависимости от указанного значения, присваивает константе наиболее подходящий тип.

    Вернемся к нашему примеру, и снова доработаем код события нажатия на кнопку:

    procedure TfMain.Button1Click(Sender: TObject);
    const
      priv = 'Привет, ';
    var
      MyName: String;
    begin
      MyName:= priv + Edit1.Text + '!';
      ShowMessage(MyName);
      MyName:= 'Рады вас видеть, ' + Edit1.Text + '!';
      ShowMessage(MyName);
    end;
        

    В этом примере мы объявили константу priv и присвоили ей текст - начало приветствия. Причем раздел const мы поместили до раздела var. В строке

    MyName:= priv + Edit1.Text + '!';
        

    компилятор вместо "priv" подставит значение "Привет, " и мы получим прежний текст приветствия.

    Комментарии

    Когда кода очень много, программист легко может в нем запутаться. Чтобы этого не произошло, в Паскале предусмотрены комментарии.

    Комментарий - это пояснительный текст, который добавляется программистом к исходному коду и игнорируется компилятором.

    То есть, программист сам себе оставляет комментарии> - заметки, указывающие, что происходит в данном участке кода, для чего создан данный элемент, что будет происходить дальше и т.п. При сборке программы компилятор FPC игнорирует весь этот текст и не включает его в программу. Комментарий остается лишь в исходных кодах.

    Комментарии улучшают восприятие кода программистом, а если проект разрабатывается не одним программистом, а группой, тут без комментариев и вовсе не обойтись. Говорят, в компании Microsoft, когда принимают на работу нового программиста, смотрят на стиль его кода. И если там комментариев меньше, чем 1/3 от всей программы, ему отказывают в вакансии. Это и понятно - если кто-то другой будет подключать ваш модуль к общей программе, без комментариев ему будет трудно разобраться, что у вас к чему. Даже если вы сами вернетесь к вашей программе через какое-то время, без комментариев вам будет трудно вспомнить, где и что у вас хранится, иной раз проще написать такую программу заново. Поэтому использование комментариев обязательно для каждого программиста, уважающего свое собственное время, и время коллег.

    Комментарии бывают однострочными и многострочными.

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

    i:= 3;  //присвоили этой переменной значение 3
        

    Здесь текст после "//" - однострочный комментарий. Мы могли бы расположить его и на отдельной строке:

    //присваиваем переменной новое значение:
    i:= 10;
        

    Имейте в виду, что если вы используете какой-то оператор после однострочного комментария на той же строке, для FPC это будет считаться продолжением комментария, и оператор не будет выполнен:

    //присваиваем переменной новое значение:   i:= 10;
        

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

    //*************************************************
    …какой-то код
    //*************************************************
    Или так:
    //------------ НАЧАЛО БЛОКА КОДА -----------------------------
    …какой-то код
    //------------ КОНЕЦ БЛОКА КОДА -------------------------------
        

    В общем, для улучшения читабельности программы, после "//" вы можете использовать собственные разделители.

    Многострочный комментарий. Когда комментарий содержит много пояснительного текста, его делают многострочным. Для этого его помещают в фигурные скобки "{…}". Всё, что находится внутри таких скобок, считается комментарием:

    {Пример комментария}
    
    {Пример длинного
     многострочного комментария}
    
    {
    Пример длинного
    многострочного комментария
    }
        

    Также в Паскале вместо фигурных скобок для многострочного комментария можно применять символы комментариев языка С: "(*…*)":

    (*
    Пример многострочного комментария
    в стиле С/С++
    *)
        

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

    Совет: комментарии - это хорошо, однако не переусердствуйте и не давайте совсем уж очевидных комментариев.

    Выше я приводил такие очевидные комментарии, но там это было необходимо, чтобы пояснить новую тему:

    var
       i: integer;  //объявили переменную с типом integer - целое число
    begin
       i:= 3;  //присвоили этой переменной значение 3
        

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

    Вернуться к учебному плану