Основы
алгоритмического программирования (типы данных, операторы, функции, процедуры и
т.д.).
Рассмотрение начнем
с первой составляющей − данных. Одно из главных свойств алгоритма
состоит в том, что он по определенным правилам преобразует исходные (входные)
данные в выходные (чаще говорят − в результат). При этом в процессе
выполнения алгоритма может потребоваться создать некоторые рабочие
(промежуточные) данные, которые будут необходимы только в ходе обработки, а
после ее завершения потеряют свое значение. Кроме того, для некоторых
алгоритмов аргумент может одновременно являться и результатом (например,
увеличить массив вдвое), что приводит к существованию еще одной разновидности
данных. Специального термина для них в учебной литературе нет, поэтому
приведенное на рисунке название несколько условно.
Перечисленные выше
категории названы видами величин. Вид величины показывает ее информационную
роль в алгоритме.
Величина −
это элемент данных.
Кроме вида,
величина имеет имя. Для человека имя переменной − это ее
обозначение в программе. Формально выбор имени не имеет значения. Удачное имя переменной,
соответствующее ее сути, способно облегчить понимание программы.
Для компьютера
имя − это место в памяти. Каждой переменной отводится определенное место,
и в машинной программе, которая получается после трансляции текста на исходном
языке, имена заменяются на обращения к соответствующему адресу.
Постоянные
величины, значения которых не меняются в процессе выполнения программы,
называются константами. Константы в программе могут быть представлены
либо непосредственно своим значением (числом, строкой), либо именем. Для
некоторых констант в языке Pascal определены стандартные имена: FALSE, TRUE,
MAXINT.
Величины, значения
которых могут изменяться в процессе выполнения программы, называются переменными.
Переменные в программе могут быть представлены только именем. В ЭВМ каждой
величине отводится определенная область памяти, где хранится ее значение.
Помимо вида и
имени, каждая величина в алгоритме имеет свой тип. Тип величины
определяет множество значений, которые может принимать величина и множество операций,
в которых она может участвовать. Для компьютера тип − это способ
интерпретации содержимого памяти. В современных компьютерах для представления
информации используется двоичное кодирование. При этом для кодирования
различной информации используются разные принципы, но полученный в итоге
двоичный код сам по себе не содержит никаких признаков, которые позволили бы
определить его природу и отличить, например, числа от текста. Указывая в
программе тип переменной, мы сообщаем компьютеру, как следует преобразовывать
информацию в соответствующем месте памяти.
Величина в
программе может иметь какое-либо значение. Для человека значение −
это информационное содержание, а для компьютера − это код в памяти.
Все имеющиеся типы
принято делить на группы. Типы, принадлежащие одной группе, имеют определенное
сходство. Прежде всего, выделяют простые и структурные типы.
Простые типы, в свою очередь подразделяют на порядковые и вещественные
типы.
Порядковые типы
называются так потому, что их допустимые значения представляют собой множество,
состоящее из конечного числа элементов. В этом множестве есть первый и
последний элементы. Кроме того, каждый элемент порядкового типа имеет
предшествующий ему и следующий за ним элементы. Так, например, у целого
значения 12 есть предшественник (значение 11) и преемник (значение 13).
Очевидным исключением являются первый (у него нет предшественника) и последний
(нет преемника) элементы.
К порядковым типам
относятся целый (целые числа со знаком и без: ShortInt, Integer,
LongInt, Byte, Word), логический (Boolean − могут принимать только
два значения: True (истина) и False (ложь)) и символьный типы данных
(Char − любой символ, каждому символу алфавита соответствует
индивидуальный числовой код от 0 до 255).
В отличие от
порядковых, вещественные типы представляют вещественные (действительные) числа
(числа, имеющие как целую, так и дробную части), а множество вещественных чисел
даже из ограниченного диапазона пронумеровать невозможно. Строго говоря,
следует учитывать то обстоятельство, что компьютер может оперировать лишь с
конечным набором чисел. Это связано с его конечной разрядностью (то есть
количеством двоичных разрядов, отводимых под хранение данных). Но для
вещественных чисел количество их допустимых значений весьма велико, поэтому не имеет
смысла относить их к группе порядковых типов.
К структурным типам
данных относятся массив (Array), множество (Set), файл (File) и запись(Record).
Отдельную группу
составляет строковый тип данных (в Pascal это String), представляющий собой
строку символов длиной не более 255 символов.
Кроме того, во
многих языках программирования имеется ограниченный тип данных, представляющий
собой интервал значений порядкового типа, называемого базовым типом (например
var a: 1..25, ch: 'a'..'z'). Переменная ограниченного типа сохраняет
все свойства базового типа.
Мы рассмотрели так
называемые стандартные типы данных. В языке Pascal реализована возможность
определения собственного типа данных − пользовательские типы данных,
которые объявляются в разделе описания типов, который открывается словом Type.
Понятие типа есть
практически во всех языках программирования. При этом можно выделить два
принципиально разных подхода: статические и динамические типы.
В языках со
статическими типами тип указывается при описании переменной, он связан с ее
именем. Если, например, переменная описана как целая, то в дальнейшем ей нельзя
присвоить вещественное или символьное значение. К языкам со статическими типами
относятся Паскаль, Си, Бейсик, КуМир.
В языках с
динамическими типами тип связывается не с именем, а со значением переменной. В
этом случае любой переменной можно присвоить значение любого типа, но текущее
значение ограничивает множество допустимых операций. Динамические типы
используются в таких языках, как Лого, Перл и др.
Для обработки
данных используются различные алгоритмы. Любой алгоритм состоит из
последовательности команд, которые по-другому называются предписаниями, или
чаше всего операторами. Термин "оператор" был введен в
качестве отличительного от "машинной команды" для того, чтобы
подчеркнуть сходство предписаний языков программирования с математическим
понятием оператора, т.е. способа отображения одного состояния памяти (или ее
участка) в другое.
Набор операторов в
различных языках программирования, как ни странно, относительно невелик и
примерно одинаков. Основу любого алгоритмического языка составляет оператор
присваивания (:= в языке Pascal). Именно он позволяет изменять значения данных
программы и тем самым получать результат решения задачи. Как метко сказано
"удивительно, что в обычных языках программирования есть только один
оператор, который фактически что-то делает, — оператор присваивания. Все
другие операторы, такие, как условные операторы и вызовы процедур, существуют
только для того, чтобы управлять последовательностью выполнения операторов
присваивания".
Чтобы получить
простейшую законченную линейную программу, к операторам присваивания надо
добавить какие-то средства ввода-вывода значений переменных. Ввод и вывод
информации для конкретных языков отличаются наиболее сильно (в Pascal это
Writeln и Readln).
Для организации
разветвляющихся и циклических участков алгоритма в языках программирования
предусмотрены операторы, которые обычно называются управляющими. К ним
относятся имеющиеся в любом алгоритмическом языке условный оператор,
конструкция выбора и несколько разновидностей циклов. Помимо этого стандартного
обязательного набора, могут существовать и другие операторы. В частности,
отметим оператор безусловного перехода Goto, который хотя и есть практически в любом
языке, но фактически является "запрещенным": дело в том, что его
применение существенно усложняет чтение программы, тогда как перечисленные выше
стандартные конструкции вполне позволяют без него обойтись.
Остается
рассмотреть еще одну важную конструкцию языков программирования — процедуру
и ее некоторую специфическую разновидность — функцию. Помимо
термина "процедура" в языках программирования используются
эквивалентные термины "подпрограмма", "метод" (в
объектно-ориентированных языках программирования), "вспомогательный
алгоритм" (в алгоритмических языках).
Процедура − это самостоятельный участок программы,
оформленный по определенным правилам, который можно неоднократно вызывать из
любых частей программы. Главным критерием для использования процедуры служит
необходимость выполнить одни и те же действия в разных местах программы.
Программа с процедурами гораздо короче и нагляднее. Благодаря полной
автономности алгоритма процедуры от основной программы, возникает существенно
меньше ошибок, связанных с использованием одинаковых имен переменных: локальные
переменные, описанные внутри процедуры, никак не влияют на переменные основной
программы даже при совпадении имен. Процедуру легче использовать (безо всяких
исправлений!) впоследствии при решении аналогичных задач. Современное
программирование базируется именно на процедурном стиле
(объектно-ориентированный подход вообще невозможен без процедур!), поэтому
лучше привыкать к нему прямо "со школьной скамьи". Кроме того,
анализ, проводимый при выделении процедуры из текста основной программы, очень
важен для более глубокого понимания алгоритма.
Примечание. Хочется
обязательно подчеркнуть, что ради "прозрачности" программы и
возможности последующего использования ее частей квалифицированные программисты
часто оформляют в виде подпрограммы даже те самостоятельные блоки, которые
встречаются всего один раз.
Процедура
вызывается по имени, при этом ей передаются необходимые фактические параметры
(но можно и не передавать никаких параметров). Из процедуры можно вызывать другие
процедуры, можно организовать такой алгоритм, при котором процедура вызывает
сама себя (так называемый рекурсивный алгоритм). После завершения выполнения
процедуры осуществляется возврат в то место программы, из которого произошел
вызов (на следующий после обращения к процедуре оператор). Для решения этой
проблемы в компьютере предусмотрен специальный механизм перехода с возвратом −
в специальной области памяти запоминается адрес следующей команды.
Функция представляет собой частный случай процедуры и
используется тогда, когда результатом является единственная величина. Например,
функциями являются периметр или площадь геометрической фигуры, путь, проходимый
телом по определенному закону за заданное время, количество вещества,
образующееся в ходе реакции соединения, и т.д.
Характерная
особенность функции состоит в том, что она не является, строго говоря,
самостоятельным оператором. Это существенно отличает ее от процедуры, которая
записывается в программе наравне со стандартными операторами. Вследствие
сказанного выше, функция обычно входит в правую часть выражения оператора
присваивания. При этом логика ее работы очень напоминает логику математических
функций типа sin x или Ln x: результат вычислений подставляется в
выражение для дальнейших действий.
Рассмотрим использование функции на простом примере.
Пусть требуется вычислить значение у по формуле f(1)+f(5) , где f(x)=
x2 + 2. Процесс решения сформулированной задачи будет
происходить на ЭВМ следующим образом
При первом вызове функции в качестве значения ее
аргумента будет передано число 1, которое и будет подставлено вместо х.
Функция произведет несложные вычисления и в качестве результата f вернет
значение 3. Затем эти действия повторятся для х = 5 , и ответ 27 также
будет возвращен в формулу для дальнейших вычислений. Остается сложить оба
значения f и поместить сумму в переменную у
Интересно проследить за особенностями процедур и
функций в различных языках программирования. Так в языке Basic подпрограмма не
выделялась в автономную структуру и была частью общей программы. В Pascal
появилась четкая локализация процедур и функций, причем функция является
частным случаем процедуры. Для C характерна обратная картина: там все
конструкции, являются функциями, а когда их результат не нужен, объявляют
функцию не имеющей результата при помощи специального слова void
(пустой)
|