Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Н.П.Фефелов ИНФОРМАТИКА Учебник.docx
Скачиваний:
14
Добавлен:
03.11.2018
Размер:
1.23 Mб
Скачать

Основы программирования

5. Основы программирования

5.1 Понятие алгоритма  Для достижения поставленной цели (решения задачи) необходимо предпринимать действия, которые должны привести к успеху (получению решения). Алгоритмами являются способы решения, описанные с помощью предписаний, которые удовлетворяют определенным требованиям.  Алгоритм — это способ с точным (т.е. выраженным в точно определенном языке) конечным описанием применения эффективных (т.е. практически выполнимых) элементарных шагов. Название алгоритм (algorithm) происходит от имени хорезмского математика IX века Аль-Хорезми. Его полное имя - Абу Джафар ибн Мусы аль-Хорезми.  Алгоритм должен обладать следующими свойствами:  - быть дискретным (состоять из последовательности шагов). Число шагов должно быть конечным (выполнение алгоритма всегда заканчивается);  - быть  определенным,  результаты   работы  алгоритма должны быть одинаковыми независимо от пользователя и применяемых технических средств;  - быть детерминированным - при повторных выполнениях одного алгоритма и входных данных должны получаться одинаковые результаты;  - быть эффективным, алгоритм более эффективен, если он заканчивается за меньшее число шагов;  - быть массовым, т.е. применяться для решения не только частных задач, но и класса однотипных задач.  Существует много разных возможностей для представления алгоритмов. Независимо от формы их описания, для алгоритмов важно различать следующие аспекты решения поставленной задачи:  - постановку задачи, которая должна быть решена с помощью алгоритма;  - специфический способ (математический метод), каким решается задача;  - разбиение решения на последовательность шагов;  - описание каждого шага в понятном исполнителю алгоритма виде.  Исполнителем алгоритма может быть человек, техническое устройство или ЭВМ. Исполнитель алгоритма может выполнять шаги большей или меньшей сложности. Для формирования алгоритма необходимо учитывать возможности исполнителя и разбивать алгоритм на элементарные шаги, которые может выполнить исполнитель. Возможности технического устройства определяют действия, выполняемые в одном шаге. Eсли исполнителем является ЭВМ, то шаги алгоритма доводятся до отдельных команд ЭВМ. Например, первые ЭВМ не имели команд умножения и деления, поэтому эти операции приходилось расписывать через алгоритмы сложения и вычитания.  Существует множество способов описания алгоритмов: естественный (словесный); графический (схемы алгоритмов, граф-схемы); средствами алгоритмического языка или командами ЭВМ.  Для человека наиболее понятен естественный способ, ЭВМ выполняет алгоритмы, написанные на алгоритмическом языке. Запись алгоритма на алгоритмическом языке должен сделать человек-пользователь (он должен знать этот язык). Поэтому алгоритмический язык является универсальным средством записи алгоритмов, понятным составителю алгоритма и ЭВМ.  Для примера рассмотрим естественное описание алгоритма задачи «Волк, коза и капуста». Крестьянину необходимо перевести на другой берег реки волка, козу и капусту. В его распоряжении есть лодка, в которую помещается, кроме крестьянина, один из названных объектов. Нельзя оставлять на одном берегу волка и козу или козу и капусту.  Алгоритм состоит из семи шагов:  1) перевезти козу;  2) вернуться;  3) перевезти волка,  4) вернуться с козой на старый берег;  5) перевезти капусту;  6) вернуться;  7) перевезти козу.  Если в лодке крестьянина можно разместить два объекта, то задача решается за три шага:  1) перевезти волка и капусту;  2) вернуться;  3) перевезти козу.  Крестьянин, имеющий большую лодку, может посадить в нее всех сразу и решить задачу за один шаг. Таким образом, в зависимости от возможностей исполнителя один и тот же алгоритм может реализовываться различным числом шагов, при этом, чем меньше шагов, тем больше сложность одного шага.  В описаниях алгоритмов некоторые шаги выполняются лишь при определенных условиях или выполнение некоторых шагов производится неоднократно. Часто поставленная задача  решается с помощью решения той же самой задачи, но с несколько измененными данными, т.е. рекурсивно. Классические элементы, которые встречаются в описаниях алгоритмов, это:  последовательное выполнение элементарных шагов;  разветвления по условиям;  повторения (циклы) и рекурсия.  Похожие концепции имеют место и в командах ЭВМ, способной выполнить алгоритм, шагами которого являются команды. Для выполнения алгоритмов, записанных на алгоритмическом языке, требуется преобразование шагов алгоритма в машинные команды ЭВМ. Такое преобразование делается на ЭВМ специальной программой — транслятором. Описание алгоритма командами ЭВМ или средствами алгоритмического языка называют программой.  В математической теории формальных алгоритмов показывается, что любой алгоритм может быть сведен к шагам, связанным с заменой символов алфавита в словах, изображающих данные (замена слов). Такие шаги представляют собой самые элементарные шаги, на которые можно разбить алгоритм. Это доказано русским математиком А. Марковым и английским математиком А. Тьюрингом, который создал алгоритмическую модель — машину Тьюринга.

5.2 Программа в машинных кодах  Возьмем переменные XY, С, Epsи запишем словесное описание алгоритма:  1. Назначить Y =0.5 * X.  2. Вычислить V= 0.5 * (X/Y-Y).  3. Прибавить к старому значению YY + V.  4. Взять абсолютное значение С = ABS(V).  5. Если С > Eps,  то 5.1 переход на шаг 2.  6. Конец.  Для сравнения дадим этот алгоритм на языке Паскаль  Eps:= 1.0E-6; Y :=0.5 * X; REPEAT V := 0.5 * (X/Y - Y); Y := Y + V UNTIL ABS(V) <= Eps;  Составим теперь программу в машинных кодах условной трехадресной ЭВМ, работающей в десятичной системе счисления с длиной слова 11 десятичных разрядов. В команде (см. рис 3.13) на код операции отводятся два разряда (100 команд), на адрес одного операнда - три разряда (адресация ОП из 1000 ячеек).  Число в ЭВМ представляется в формате с фиксированной точкой, децимальная тока предполагается левее старшего разряда, т.е. число содержит только дробную часть. Старший разряд числа - знаковый.  Упрощенная система команд нашей ЭВМ приведена в таблице 5.1.  Составление программы в машинных кодах следует начать с распределения ячеек ОП для данных. Их можно располагать произвольно. Мы расположим данные с адреса 100, как показано в таблице 5.2. Пояснение кодов в ячейках 107 - 111 будет дано позже.  Назначим адрес начала программы равным 200 (выбирается произвольно), и, зная адреса данных, теперь можно кодировать команды. Промежуточные результаты помещаются в рабочую ячейку по адресу 105. Вид программы, записанный на бланке для кодирования, приведен в таблице 5.3.  В таблице команда разбита на четыре составных части для удобства записи и чтения. Реально каждая команда представляет собой одно 11-разрядное число. Так, первая команда будет числом 05100103101.  Арифметические команды выбирают операнды по первому и второму адресам, результат направляется по третьему адресу. Команда определения абсолютного значения использует только первый и третий адрес, а команда условного перехода делает переход по второму адресу, если результат предыдущей команды отрицательный, в противном случае выполняется следующая команда.  Примечание: * — команда используется в программе вычислений с массивом вместо предыдущей.  Теперь составим программу вычисления Y = sqrt(X) для массива из 10 чисел. Ранее составленную программу следует теперь повторить циклически 10 раз, причем каждый раз с очередным элементом массива и записью результатов в выходной массив. Разместим массив аргументов в ячейках 121-ИЗО, а массив результатов - в ячейках 131-5-140. Программу цикла сделаем отдельной. В ней надо переслать элемент входного массива по адресу 100, затем передать управление программе вычислений по адресу 200, после окончания вычислений вернуться на следующую после перехода команду, а результат вычисления записать из ячейки 101 в выходной массив.  Команда пересылки аргумента из массива должна при повторении вычислений изменять первый адрес от 121 до 130, т.е.  30   121 000 100     для первого элемента массива;  30   130 000 100     для последнего элемента массива. Аналогично для пересылки значения корня должен изменяться третий адрес:  30   101 000 131     для первого результата;  30   101 000 140     для последнего результата. В командах необходима переадресация. Ее можно сделать, если воспринимать команду как число и прибавлять к ней константу единицы первого или второго адреса, т.е. числа 00001000000 и  00000000001. Вот здесь и проявляется основной принцип фон Неймана (см. 3.2) - команды должны кодироваться в числовом виде и размещаться в одной памяти с данными!  Наконец, необходимо после вычислений проверять условие выхода из цикла. Для этого можно опять воспользоваться кодом команды пересылки и сравнивать ее текущее значение с кодом команды пересылки последнего числа-30130000100.  Любой   циклический алгоритм должен содержать четыре  части:  начальная установка;  тело цикла;  изменение;  проверка окончания.  Начальная установка должна быть первой в цикле, остальные части могут располагаться в любом порядке. Наиболее удобно расположить их так: изменение, тело цикла, проверка окончания. При первом выполнении цикла следует обойти команды изменения. Программа вычисления квадратного корня для массива чисел написана с адреса 220 и приведена в таблице 5.4.  Таблица 5.4 - Вычисление квадратного корня для массива чисел  Обратите внимание, что ячейки с адресами 225 и 227 можно не заполнять, поскольку команды 220 и 221 формируют их, а команды 223 и 224 производят в них переадресацию. В программе вычисления (Таблица 5.3) по адресу 208 необходимо записать команду безусловного перехода на адрес 227 вместо команды Стоп.  Попробуйте проследить выполнение команд циклической программы и убедиться в ее возможностях.

5.3 Символические коды. Ассемблер  Составление программ для ЭВМ первого поколения делалось исключительно на машинном языке, т.е. в командах ЭВМ. Команды представляются двоичными числами, программист должен был составлять команды из числовых значений кодов операций и адресов операндов. Кодирование программы командами ЭВМ является кропотливой работой, требующей большого внимания, но достаточно формальной. Для примера попробуйте, не глядя в таблицу программы вычисления квадратного корня, составить ее самостоятельно и сосчитайте количество сделанных ошибок.  Если в программе необходимо добавить или зачеркнуть команду, адресация других команд меняется и приходится менять адреса в командах перехода. Это еще более усложняет программирование в машинных кодах.  Для уменьшения количества ошибок программисты предварительно записывали программу в формате команд, но использовали символьные обозначения для кодов операций и переменных.  Воспользуемся обозначениями из таблиц 5.1 и 5.2 и запишем программу вычисления квадратного корня с адреса K+l:  Программа записана в содержательных обозначениях, но адреса сохранены. Можно и адреса обозначить метками. Получим полностью символически написанную программу, по каждая строка программы будет представлять одну команду. Такая программа будет представлять собой уже текст, напоминающий математическую запись:  Логика программы, записанной в символическом виде, прослеживается яснее. Символьное обозначение адресов переходов не привязывается к конкретным адресам. Можно проверить алгоритм, внести в него любые изменения, это не приведет к изменениям в других строках программы. После проверки алгоритма, записанного таким образом, можно приступить к кодированию машинных команд, пользуясь таблицами кодов и распределения памяти. Такая технология более производительна и дает меньше ошибок при составлении программ.  Если теперь в символическую программу добавить директивы для определения данных и управления построением машинной программы, мы получим запись программы на машинно-ориентироваппом языке.  Машинно-ориентированный язык с сохранением формата команды (одна строка текста программы представляет одну команду) получил название языка символического кодирования, или ассемблера. ЭВМ понимает только команды, записанные с помощью двоичных чисел. Поскольку в программе существует однозначное соответствие между числовыми и символическими значениями составных частей команды, то преобразование про-  граммы, написанной на языке ассемблера, может выполнить специальная программа-переводчик. Такая программа получила созвучное название:ассемблер.  Программирование на ассемблере требует знания особенностей конкретной ЭВМ: системы команд, форматов представления данных и т.п. и доступно квалифицированным программистам, но приводит к созданию наиболее коротких и быстрых программ. На ассемблере пишутся программы для управления вычислительным процессом — операционной системы. Современные архитектуры ЭВМ имеют сложную систему адресации, развитую систему команд, поэтому составление программы непосредственно в числовых кодах сейчас практически невозможно. Ассемблер - единственное средство программирования с использованием команд ЭВМ.  Недостаток машинно-ориентированных языков состоит в жесткой привязке к системе команд конкретной ЭВМ. Ее невозможно выполнять на ЭВМ с другой системой команд, другой архитектуры.

5.4 Слова и абстрактные языки  Любая конечная последовательность символов в абстрактном алфавите X, рассматриваемая как единое целое, называется словом (см. 2.1). Словом может считаться целая фраза, страница или книга, поскольку знаки препинания и пробел входят в алфавит. Не требуется осмысленности слов. Слово служит для наименования (обозначения) понятий, предметов, лиц, действий, состояний, признаков, связей и т.д.  Для того чтобы из всего множества слов выделить правильные в некотором смысле слова, над исходным алфавитом X строится так называемыйформальный язык. Язык - набор представлений, соглашений и правил, используемых для выражения информации. В языке определяются синтаксис и семантика. Синтаксис языка - грамматические правила образования конструкций языка из его алфавита. Семантика характеризует значение словосочетаний, слов и частей слов. Она определяет сущ-  ность кодов, команд и сообщений. Толкование (определение) значений слов определяется в семантическом словаре.  Естественным языком называют систему звуковых, словарных и грамматических средств, которая служит средством человеческого общения, мышления. Искусственным (формальным) языком является набор символов, кодов и правил их комбинирования, которые предназначены для обмена информацией между техническими устройствами, а также между человеком и техническими устройствами.  Среди формальных языков следует выделить алгоритмические языки и языки программирования. Эти языки представляют особые удобства для наглядного описания процедурных шагов процесса обработки и передачи данных при решении широкого круга задач. Разработано и создается большое число различных языков программирования.  Для любого языка формулируется (формальная) грамматика. Она представляет собой конечную совокупность формальных правил, с помощью которых порождаются все слова данного языка (т.е. правильные слова) и только такие слова. В современной информатике разработана теория формальных грамматик, которая позволяет сформулировать правила языка способом, понятным устройствам обработки данных. Некоторые простые способы описания грамматик (метаязык Вэкуса-Наура и синтаксические диаграммы) будут рассмотрены при знакомстве с алгоритмическими языками.

5.5 Алгоритмические языки и языки программирования  Для описания алгоритмов и перерабатываемой ими информации (данных) используются алгоритмические языки. Большинство алгоритмических языков предназначено для записи алгоритмов человеком, поэтому алфавиталгоритмического языка всегда основан на алфавите естественного языка (в большинстве случаев английского). Кроме букв, цифр, знаков препинания, используются символы математических операций и скобки. Слова языка формируются произвольно и используются  обычно как имена объектов алгоритма или представляют данные (например, числа). Особый смысл в алгоритмическом языке имеют ключевые слова. Они составлены из нескольких символов, но для алгоритма считаются одним символом (иероглифом). Ключевые слова образуют вторичный алфавиталгоритмического языка. Например, BEGIN и END служат операторными скобками, AND, OR и NOT обозначают логические операции и т.д.  В каждом алгоритмическом языке устанавливаются типы данных, которые могут обрабатываться алгоритмами. Разновидность данных определяется назначением алгоритмического языка, но большинство современных языков включает числовые данные (целые и с плавающей точкой), логические исимвольные данные, а также более сложные типы - агрегаты данных(массивы, записи, множества, структуры). Тип данных указывается ключевым словом. Составитель алгоритма может на основе базовых типов данных определять новые типы (для агрегатов) и назначать им оригинальные имена. Для каждого алгоритма составляется описание объектов данных с указанием их типа (для констант и переменных). Все переменные обозначаются в алгоритме уникальным именем. Переменные кодируют адреса в памяти, откуда следует взять данные или куда записать результат.  Далее в алгоритмическом языке определяется набор операций над данными каждого типа. Обычно это арифметические операции для числовых данных,операции сравнения и логические операции, операции над символами и строками.  Действия с данными записываются в алгоритмическом языке с помощью выражений. Выражение -- это фраза, которая может содержать константы, имена переменных, имена функций, знаки операций и скобки, например  (EXP(tau/alpha) + EXP(tau/alpha))/2 + 3.1459* (х + 0.12).  Здесь 2, 3.1459, 0.12 - числовые константы; tau, alpha, x -имена переменных; EXP - указатель функции.  Порядок выполнения операций в выражении определяется установленным в языке приоритетом операций, скобки включаются в выражение, когда следует определить другую после-  довательность операций. В выражение разрешается включать данные разных типов, при его вычислении могут происходить преобразования типов данных, а тип результата определяется установленными в языке соглашениями.  Действия, необходимые для выполнения алгоритма, осуществляется в алгоритмическом языке инструкциями - операторами. Оператор представляет собой законченную фразу и выражает один шаг алгоритма. Алгоритм на алгоритмическом языке - это последовательность операторов. Операторы разделяются знаком препинания (обычно точкой с запятой). Шаги алгоритма выполняются в порядке записи от первого до последнего оператора. Алгоритм считается закончившим свою работу, если выполнен последний оператор.  Огромное количество алгоритмов, применяемых в науке и технике, можно записать ограниченным числом типов операторов. Это следующие типы операторов:  присваивания (назначения);  условный и выбора;  цикла;  перехода;  вызова подпрограммы (перехода с возвратом);  пустой;  составной.  Все алгоритмические языки допускают вложенность операторов. Телом оператора цикла может быть условный оператор, внутри которого можно разместить оператор выбора. В одной ветви оператора выбора может снова быть другой оператор цикла. Вложенность операторов обеспечивается составным оператором, который позволяет представить последовательность операторов как один. Все эти средства обеспечивают компактную запись алгоритмов на алгоритмическом языке.  Для описания данных и их типов в алгоритмическом языке используются фразы декларации переменных, по форме напоминающие операторы языка. Но они не являются шагами алгоритма, поэтому не могут считаться операторами.  Правила правильной записи операторов и деклараций описания переменных определяются формальной грамматикой ал-  горитмичсского языка. Этой грамматикой руководствуется программа перевода алгоритма, записанного на алгоритмическом языке, в машинный код — компилятор.

5.6 Описание грамматики алгоритмического языка  В информатике разработано несколько способов задания грамматик, порождающих формальные языки. Наиболее простыми средствами описания грамматики являются металингвистические формулы Бэкуса-Маура и синтаксические диаграммы.  Метаязык Бэкуса-Наура. Для описания синтаксиса используются Бэкусовские нормальные формы (БНФ), предложенные Дж. Бэкусом (IBM) и П. Науром (Дания). Язык описывается металингвистическими формулами. Они совпадают по форме с оператором присваивания, т.е. слева ставится определяемое понятие, затем знак ::= (читается «это есть», «равно по определению»), а в правой части помещается выражение, определяющее понятие левой части.  Роль постоянных величин в формулах играют символы алфавита, а рольпеременных, значениями которых являются определенные последовательности основных символов, - некоторые понятия языка, встречающиеся в левых частях других формул.  Каждое понягис обозначается одним или несколькими словами обычного (не формального) языка (например, число, выражение, оператор). Каждое понятие заключается в угловые скобки и называется металингвистической переменной.  Если металингвистические переменные следуют друг за другом, то их значения сцепляются (конкатенируются), что соответствует логической операции И. Если они разделяются знаком |, то возможен выбор любого варианта (логическая операция ИЛИ).  Каждая металингвистическая формула задаст правило порождения допустимых значений соответствующих метапере-менных.  Разберем понятие целого числа без знака в БНФ.  <целое без знака> ::= <цифра> | <целое без знака><цифра>, <цифра>::=()| 1|2|3|4|5|6|7|8|9.  Здесь <целое без знака> и <цифра> - метапеременные, а С/9 - символы цифр из алфавита языка.  Формула показывает, что правильное целое число будет представлять собой или одну цифру, или непрерывную последовательность цифр и только цифр. Например, 3; 3644; 0006500 -правильные целые числа, а число +76,2 уже не будет целым числом без знака, поскольку в него включены символы знака плюс, и запятая (хотя это тоже число, но не целое и со знаком).  Замечательным в металингвистических формулах является рекурсивное (т.е. через само себя) определение части понятий. Например, метапеременная <целое без знака > содержится в обеих частях метаформулы. Это дает возможность составлять числа из любого числа цифр.  Определим еще одно более сложное понятие алгоритмического языка -составной оператор.  <составной оператор> ::= <начало><конец составного>.  <начало> ::= BEGIN,  <конец составного> ::= <оператор> END |  <оператор> ; <конец составного>.  Здесь постоянные - BEGIN и END (ключевые слова языка); переменные - <начало>, <конец составного, <оператор>.  Распишем рекурсивную формулу явно:  <конец составного> ::= <оператор> END, 1  <конец составного> ::= <оператор> ; <конец составного>.   2  Подставляем значение <конец составного> из 2 и получаем:  <конец составного> ::= <оператор> ; <оператор>;<конец составного>,  <конец составного> ::= <оператор>; <оператор>; <оператор> ;  <конец составного>; и так далее.  112  Для завершения подставим <конец составного> из 1:  <конец составного> ::= <оператор> ; <оператор> ; <опера-тор>;  <оператор> END.  Таким образом, в нашем случае составной оператор определяется как  <составной оператор> :: = BEGIN <оператор> ; <оператор> ;  <оператор>; <оператор> END.  БНФ для понятия составной оператор является формальным представлением словесного определения составного оператора. Составной оператор есть последовательность операторов, разделенных точкой с запятой и помещенных в операторные скобки BEGIN и END. Обратите внимание, что после последнего оператора точка с запятой не ставится.  Свойство рекурсивности БНФ позволяет компактно описывать сложные конструкции алгоритмического языка. Алгоритмический язык Алгол был полностью определен в БНФ.  Синтаксические диаграммы предложены автором языка Паскаль Никлаусом Виртом. Это фактически металингвистические формулы в графическом изображении. Переменные в синтаксических диаграммах изображаются прямоугольниками, постоянные - кружками. Линии, соединяющие графические символы, показывают последовательность вхождения переменных и постоянных в определяемое диаграммой понятие.  Рассмотрим синтаксическую диаграмму понятия «имя переменной»{идентификатор) в языке Паскаль. В ней две переменные: буква и цифра.Вход в диаграмму делается в понятие буква, а затем может быть циклический возврат на вход понятия буква или цифра. Выход может быть после любого повторения цикла выбора буквы или цифры, в том числе нулевого цикла. Следовательно, идентификатор может состоять либо из одной буквы, либо быть последовательностью любого числа букв и цифр, но первой в последовательности должна быть буква.  I  113  идентификатор  --------7-*  Буква  Цифра  буква  цифра  Переменные буква и цифра определяются через постоянные (символы алфавита языка). Буква - это любой из символов латинского алфавита, а цифрой служит любая из десятичных цифр.  Другой пример синтаксической диаграммы - определение понятия число. В языке Паскаль допускаются целые числа и с дробной частью. Последние могут записываться как в форме с фиксированной точкой, так и в формате с плавающей точкой.  число  целое без знака  цифра  Минимально число может представлять собой последовательность цифр - 57323, это целое число. Если в числе есть точка и дробная часть, то это число с фиксированной точкой, например -12.684. Запись 54Е-4 - будет представлять число с плавающей точкой. Попробуйте определить, будут ли числами следующие последовательности символов: +364. и -.169.  Попробуйте самостоятельно проследить другие пути на синтаксической диаграмме и определить возможные формы записи правильных чисел.  Формальная грамматика — это математическая система, определяющая вид языка. Одновременно она является устройством, которое придает предложениям языка полезную структуру.  В грамматике, определяющей язык L, используются два конечных непересекающихся множества: множество терминальных символов и множество нетерминальных символов N. Из терминальных символов образуются слова определяемого языка. Нетерминальные символы служат для порождения новых слов языка по некоторым правилам.  Сердцевину формальной грамматики составляет конечное множество Р правил образования, которое описывает процесс порождения фраз языка. Формальная грамматика G определяется четверкой G = (N,P,S), где S выделенный символ из N, называемый начальным (исходным) символом, с которого начинаются все правила языка.  Существует множество вариантов описания грамматик, использующих различные принципы: машины Тьюринга; грамматики Хомского; лямбда-исчисление; системы Поста.  5.7 Системы программирования  Составление программ для ЭВМ первого поколения делалось исключительно на машинном языке, т.е. в командах ЭВМ. Пример такой программы приведен в 5.1. Программист должен был составлять команды из числовых значений кодов операций  и адресов операндов. Составление программ в машинных кодах было трудной кропотливой и малотворческой работой.  Первым этапом автоматизации программирования было внедрение машинно-ориентированных языков символического кодирования - ассемблеров. Эти языки позволили облегчить самый формальный этап составления программы - кодирование, что привело к существенному увеличению производительности труда программистов.  На следующем уровне развития языков находятся процедурно-ориентированные языки. В отличие от машинно-ориентированных языков, синтаксис и семантика этих языков не зависят от состава команд конкретной ЭВМ и ее архитектуры. Запись программы на процедурно-ориентированном языке достаточно близка к общепринятой математической записи, компактна и удобна для восприятия. Привязку составленной программы к конкретной архитектуре ЭВМ осуществляет транслятор (программа-переводчик).  После ввода в ОН текста программы на языке программирования, осуществляется ее трансляция. Каждый оператор программы заменяется последовательностью команд ЭВМ. В результате создается программа, состоящая из машинных команд.  Процесс перевода программы и процесс ее исполнения могут реализовываться двумя способами. Первый способ, называемый компиляцией,состоит в том, что сначала вся программа переводится в машинный код, а потом выполняется. Программу в машинных кодах можно сохранить на внешнем устройстве (ВУ), а затем выполнять ее сколько угодно раз путем простого переписывания ее из ВУ в ОП. Программа перевода - компилятор - для выполнения программы не нужна.  Второй способ — интерпретация - предполагает, что отдельные операторы (или другие части исходной программы) сразу после перевода в машинный код выполняются, после чего та же процедура совершается над следующим оператором и т.д. При интерпретации во время выполнения рабочей программы интерпретатор находится в ОП, и занимает дополнительный объем памяти. Кроме того, процесс решения задачи замедляет-  ся, так как между отдельными этапами выполнения рабочей программы управление передается интерпретатору.  Интерпретатор работает медленнее, чем компилятор. Однако при отладке новых программ удобнее работать с интерпретатором, так как он позволяет после исправления ошибки продолжить выполнение программы. Компилятор, обрабатывая всю программу, может обнаружить все ошибки программы и выдать о них сообщения. Но после исправления ошибок компиляцию программы следует начать снова.  Реальные программы представляют собой сложные программные комплексы, в разработке которых принимает участие большое число программистов и даже организаций. Коллективная технология программирования предполагает модульную структуру программы, когда программа составляется из отдельных законченных частей - модулей. Модуль - это обособленная часть программы или подпрограмма. Модули разрабатываются независимо различными исполнителями с учетом стандартных соглашений (имеют единый интерфейс)и пишутся на алгоритмическом языке, что дает возможность собирать из модулей сложные программы. Такая форма программы называется исходный модуль. Библиотеки стандартных подпрограмм в исходном виде позволяют пользоваться ранее созданными модулями.  Модульная структура программы не позволяет записывать программы модулей в абсолютных адресах. Каждый модуль компилируется отдельно и планируется с нулевого адреса. Получается промежуточная форма программы - объектный модуль. Это уже программа в машинных кодах, но не связанная с другими частями. Удобнее хранить заранее подготовленные модули в объектном виде в библиотеках объектных модулей, при этом экономится время, затрачиваемое на повторную компиляцию.  Для получения готовой для исполнения программы ее следует собрать (скомпоновать) из отдельных объектных модулей. Эта операция проводится обслуживающей программой, называемой компоновщиком или редактором связей. Компоновщик соединяет все объектные модули в одну программу -загрузочный модуль. Загрузочный модуль может строиться в оперативной памяти и после компоновки сразу выполняться. Если про-  грамма будет выполняться неоднократно, лучше сохранить загрузочный модуль в файле на внешнем устройстве. При необходимости выполнить программу ее размещают в оперативной памяти с помощью программы-загрузчика. Обычно программы связывания и загрузки позволяют создатьперемещаемый загрузочный модуль, т.е. программу, которая может выполняться в любом месте оперативной памяти. Настройка адресов программы по месту в оперативной памяти производится перед выполнением загрузчиком.  Язык программирования, транслятор, программы связывания и загрузки и другие обслуживающие программы, а также текстовый редактор и программа отладки составляют систему программирования. В настоящее время система программирования собирается в пакет программ - интегрированную инструментальную оболочку (ИИО), которая позволяет проводить все операции по редактированию, обработке, отладке и выполнению программы в среде оболочки. Системы программирования Турбо Паскаль, Турбо Си фирмы Borland International являются примерами таких систем программирования.  Последовательность обработки и выполнения программы в инструментальной оболочке приведена на рисунке 5.3. Она состоит из пяти этапов: редактирование текста программы, компиляции, компоновки, выполнения и отладки программы.  С помощью текстового редактора вводится и исправляется текст программы, он сохраняется в файле. В текст могут быть включены ссылки на готовые исходные модули, хранящиеся в библиотеках исходных модулей или других файлах. Вставка текстов библиотечных исходных модулей производится специальной программой - макропроцессором. Часто макропроцессор встраивается в компилятор. Полная программа в исходном виде, обработанная макропроцессором сохраняется на внешнем устройстве, она может быть записана также в текстовый файл.  Компиляция программы — второй этап обработки, результатом которого является создание одного или нескольких объектных модулей, сохраняемых на диске. Компилятор проводит синтаксический и лексический анализ текста программы. При обнаружении ошибки выдается сообщение с указанием места  в тексте программы. В Турбо-системах программирования обработка ведется до первой ошибки, после чего вызывается текстовый редактор, а указатель текста показывает на неправильную конструкцию программы. После исправления можно вызвать компилятор повторно.  Если объектные модули составлены правильно, система программирования вызывает компоновщик для сборки загрузочного модуля. В своей работе компоновщик добавляет в загрузочную программу объектные модули из библиотек. Готовый загрузочный модуль либо остается в оперативной памяти, либо записывается в файл для дальнейшего выполнения в зависимости от режима работы, выбранного пользователем.  Теперь можно выполнить программу. Если она дает неправильные результаты (ошибка алгоритма), можно воспользоваться услугами отладчика и выполнить ее в режиме отладки. В этом режиме можно посмотреть значение любой переменной и установить ее новое значение, указать отладчику, за какими переменными надо наблюдать при отладке программы. Отладчик позволяет установить контрольные точки остановки программы для анализа контролируемых переменных. При необходимости можно сделать рестарт программы, не закончив ее выполнение. Работа в режиме отладки позволяет обнаружить ошибки алгоритма, а затем вернуться в текстовый редактор для исправления ошибок.  Системы программирования в среде интегрированной инструментальной оболочки имеют множество различных режимов работы и сервисных функций, выбор которых делается через меню. Обработка и отладка сложной программы — обычно длительный и сложный процесс. Никогда нельзя быть уверенным в том, что в программе исправлены все ошибки.

5.8 Парадигмы и технологии программирования  Парадигма в науке — это исходная концептуальная модель постановки проблем и методов их решений, способов исследований проблем.  Важным признаком классификации языков программирования является использование в них одной из парадигм программирования. В настоящее время все программы строятся на основе процедурной (императивной), функциональной (аппли-кативной), логической (реляционной) и объектно-ориентированной парадигм.  Программа на процедурном языке программирования состоит из последовательности инструкций (операторов), задающих шаги (процедуру) решения задачи. Программы не только определяют, что нужно сделать, но какэто сделать. Основное действие определяется оператором присваивания, он изменяет содержимое областей памяти. Концепция памяти как хранилища значений, содержимое которого может обновляться операторами программы, является фундаментальным в императивном (процедурном) программировании.  Работа программы сводится к последовательному выполнению операторов с целью преобразования значений исходных данных в результаты. С точки зрения программиста, имеются программа и память, причем программа последовательно обновляет память.  Процедурные языки характеризуются высокой эффективностью реализации на традиционных архитектурах ЭВМ, но в них отсутствует строгая математическая основа. Кроме того, необходимо описывать переменные (явно распределять память программы).

Модульная и структурная технология программирования.Совершенствование языков процедурного программирования и технологии привело к модульному программированию, когда программа проектируется состоящей из относительно независимых частей - модулей, в которых используется единый принцип передачи данных между модулями - интерфейс(см. 5.7). Обычно модули представляют собой подпрограммы.  Голландский математик Эдсгер Дейкстра - научный сотрудник фирмы Барроуз (Burroughs), один из наиболее авторитетных в мире теоретиков программирования в 1968 г. (в 38 лет) показал, что большинство программ неоправданно сложны из-за отсутствия в них четкой структуры. Виновником служит опера-  тор GOTO (безусловный переход). Для ЭВМ проблем не возникает. Но восприятие такой программы человеком очень затруднено. Вместо GOTO Э. Дейкстра предложил использовать четыре типа управляющих структур:последовательность, альтернативу (условный оператор), повторение (цикл) ивызов подпрограммы. Эти управляющие структуры позволяют обходиться без меток и операторов безусловного и условного переходов и получатьструктурированную программу.  Указанные управляющие структуры допускают вложенность (см. 5.5). В управляющие операторы можно включать вызовы подпрограмм, оформленных как модули, так что структурное программирование всегда используетмодульный принцип. Замена частей алгоритма обращениями к модулям делает основную программу более компактной и, главное, легко обозримой.  Алгоритм модуля может содержать обращения к другим модулям, реализующим часть этого алгоритма. Этим обеспечивается принципнисходящего проектирования программ, или принцип сверху вниз. По этому принципу алгоритм программы сначала разбивается на этапы, затем каждый этап может делиться на более мелкие этапы второго уровня и т.д. Затем каждый этап проектируется как отдельный модуль. Нисходящее проектирование программ считается наиболее продуктивным, поскольку реализует общий принцип системного подхода. Легко распределить разработку программы по отдельным исполнителям и осуществлять общее руководство.  В основе технологии объектно-ориентированного программированиялежит понятие объекта, а суть его выражается формулой: «объект = данные + процедуры». Каждый объект интегрирует в себе некоторую структуру данных и доступные только ему процедуры обработки этих данных, называемыхметодами. Объединение данных и методов в одном объекте называетсяинкапсуляцией.  Для описания объектов служат классы. Класс определяет свойства и методы объекта, принадлежащего этому классу. Любой объект можно определить как экземпляр класса.  Объектно-ориентированное программирование заключается в выборе имеющихся или создании новых объектов и организации взаимодействия между ними. При создании новых объектов свойства объектов могут добавляться или наследоваться от объектов-предков. В процессе работы с объектами допускается полиморфизм - возможность использования методов с одинаковыми именами для обработки данных разных типов.  Технология объектно-ориентированного программирования впервые была реализована в языке Smalltalk, первоначально предназначенном для реализации функций машинной графики. К наиболее современным объектно-ориентированным языкам программирования относятся C++ и Java.  В последнее время многие объектно-ориентированные программы реализуются в системах визуального программирования. Отличительной особенностью таких систем является мощная среда разработки программ из готовых «строительных блоков», позволяющая создать интерфейсную часть программы в диалоговом режиме практически без кодирования программных операций. К числу объектно-ориентированных систем визуального программирования относятся: Visual Basic, Delphi, C++ Builder и Visual C++.  Сущность функционального (аппликативного) программированияопределена А.П. Ершовым как «... способ составления программ, в котором единственным способом расчленения программы на части является введение имени для функции, а единственным правилом композиции - оператор суперпозиции функции. Никаких ячеек памяти, ни операторов присваивания, ни циклов, ни, тем более, блок-схем, ни передачи управления». В аппликативном программировании указывается только что, но не как сделать.  Роль основной конструкции в функциональных языках играет выражение. К выражениям относятся скалярные константы, структурированные объекты, функции. Функции трактуются как однозначное отображение аргументов на значение результата.  Аппликативный язык программирования включает следующие элементы:  - классы   констант,   которыми   могут   манипулировать функции;  - набор базовых функций, описания которых вставлены в язык;  - правила построения новых функций из базовых;  - правила формирования выражений на основе вызова функций.  Программа на функциональном языке представляет собой совокупность описаний функций и выражения, которые необходимо вычислить. Выражение вычисляется посредством редукции, то есть серии упрощений, до тех пор, пока это возможно по следующим правилам: вызовы базовых функций заменяются их значениями; вызовы небазовых функций заменяются их телами, в которых параметры замещены аргументами.  В функциональном программировании отсутствуют операторы присваивания, вследствие чего переменные обозначают не области памяти, а объекты программы, что полностью соответствует понятию переменной в математике. В принципе, можно составлять программы и вообще без переменных. Кроме того, нет существенного различия между константами и функциями, то есть между программами и данными. В результате этого функция может быть значением вызова другой функции и может быть элементом структурированного объекта. Число аргументов при вызове функции не обязательно должно совпадать с числом параметров, указанных при ее описании. Перечисленные свойства характеризуют аппликативные языки как языки программирования очень высокого уровня.  Первым языком функционального программирования был ЛИСП (LISP - LISt Processing - обработка списков). В нем функции и данные представляются списками. Язык предназначен в основном для обработки символьной информации.  Для примера напишем выражение для определения корней квадратного уравнения:  на условном языке функционального программирования.  Выражение для Х1:ДЕЛ(СУМ(ВЫЧ(0)В),ККВ(ВЫЧ(УМН(В,В),УМН(4,УМН(А,С))))),УМН(2,А)).  Выражение для Х2: ДЕЛ(ВЫЧ(ВЫЧ(0,В),ККВ(ВЫЧ(УМН(В,В),УМН(4,УМН(А,С))))),УМН(2,А)).  Здесь используются базовые функции СУМ(х,у), ВЫЧ(х,у), УМН(х,у), ДЕЛ(х,у) и извлечения квадратного корня - ККВ(х).  Центральным понятием в логическом (реляционном) программированииявляется отношение. Программа представляет собой совокупность определения отношений между объектами. В логическом программировании нужно только специфицировать факты, на которых основывается алгоритм, а не определять последовательность шагов, которые следует выполнить. Это свидетельствует о декларативности языка логического программирования, выражаемой высказыванием: «алгоритм = логика + управление».  Логическое программирование открыл язык Пролог (PROLOG - PROgramming LOGic - программирование в терминах логики). Языки логического программирования характеризуются высоким уровнем, строгой ориентацией на символьные выражения, возможностью инверсных вычислений, т.е. переменные в процедурах не делятся на входные и выходные.  К сожалению, парадигмы функционального и логического программирования очень неэффективно реализуются на фон-неймоновской архитектуре ЭВМ, предназначенных для процедурного программирования. Японский проект ЭВМ пятого поколения, опубликованный в 1980 г., предполагает главной операцией этих ЭВМ логический вывод.  Логические программы, в принципе, имеют невысокое быстродействие, так как выводы делаются методом проб и ошибок, поиском с возвратами к предыдущим шагам.

5.9 Развитие языков программирования  На ЭВМ первого поколения программирование велось непосредственно в машинных кодах (см. 5.2). Программа представляла собой набор машинных команд в двоичном или восьмеричном формате, который определялся архитектурой конкретной ЭВМ. Но уже в первом поколении стали применяться автокоды с использованием символьных имен (см. 5.3).  Первый такой язык программирования видимо был создан К. Цузе. Он решил, что нужна система числовых и символьных обозначений, построенная на основе логики, по существу, система исчисления шагов решения задачи, и на этой основе создал систему программирования Планкалкюль(планирующее исчисление). Работы К. Цузе в силу известных причин (см. 4) не получили широкой известности. Только в 1972 году работа К. Цузе была издана целиком. «Видимо, все могло бы обернуться совсем иначе, и мы живем не в лучшем из миров», - заметил один из ученых, критикуя возникшие позже языки, в создании которых не были использованы идеи К. Цузе.  Первую компилирующую программу создала Грейс Хоппер, морской офицер, доктор математики, программист на американской ВМ Марк-1.  Первые универсальные языки программирования. Настоящий машинно-независимый алгоритмический язык Фортран (FORTRAN - FORmular TRANslator) был создан в 1956 г. в фирме IBM под руководством Дж. Бэкуса. Основными понятиями языка стали: оператор присваивания (N=10), запись выражений в виде алгебраических формул, введение массивов и индексных переменных, оператор цикла DO. В 1958 г. создан улучшенный вариант Фортран-2. Он позволял делать программу модульной и объединять в одну программу модули на Фортране и ассемблере.  В 1962 г. появился Фортран-4, в него была включена обработка текстовых данных. В 1966 г. создан стандарт Фортран-4, а в 1977 г. еще один стандарт Фортран-77. Фортран и по сей день остается популярным средством программирования среди научных работников. Были созданы быстрые и оптимизированные  компиляторы, в него включены возможности обработки графической информации и выработан новый стандарт Фортран-95. Особую ценность представляют обширные библиотеки Фортран-программ, наработанные за 40 лет несколькими поколениями программистов из различных проблемных областей. Недостатком Фортрана является его пренебрежение принципами структурного программирования (в 1956 г. о них не знали) и невозможность обрабатывать структуры данных (записи).  Для деловых применений (обработки данных) Фортран годился плохо. В 1959 г. министерство обороны США создало конференцию по языкам программирования - КОДАСИЛ (CODASYL - Conference on Data System Languages). Была образована группа, которая в 1960 г. объявила о создании нового языка КОБОЛ (COBOL - Common Business Oriented Languages). В 1962 г. была создана улучшенная версия.  Синтаксис Кобола напоминает фразы на английском или национальном языке. Бизнесмен легко прочитает программу. Впервые введено понятие структуры — коллекция разнородных данных (записи в Паскале). Язык приспособлен для выполнения однородных операций над большими массивами данных. Программа на КОБОЛе состоит из трех секций: описаний, данных, операторов.  Еще до появления КОБОЛа наметилась попытка разработать третий универсальный язык АЛГОЛ (ALGOL -ALGOrithmic Language), который, подобно Фортрану, был языком, преимущественно для решения численных задач. В 1958 г. в Цюрихе собрались восемь наиболее авторитетных разработчиков алгоритмических языков. Были Дж. Бэкус - Фортран, Джозеф Уэгстен - Кобол. Они анонсировали Алгол-58.  В Алголе основные понятия Фортрана были собраны в более логичную изящную структуру. Дж. Бэкус и П. Наур разработали строгую и точную систему определения каждой конструкции языка в виде БНФ (см. 5.6). БНФ оказала большое влияние на разработку других языков программирования.  В 1960 г. в Париже был объявлена новая версия.- Алгол-60. Он обладал четко выраженным синтаксисом для операторов структурного программирования, в том числе возможностью  рекурсивного обращения к подпрограммам. Блочная структура программы позволяла вводить внутренние динамические блоки, содержащие локальные переменные, т.е. использовать одну область памяти неоднократно.  Европейские страны сразу приняли Алгол. Он позволил им обрести независимость от американцев. Широко распространен Алгол был в Англии, ФРГ, СССР, Китае.  В СССР было создано несколько систем программирования на Алголе. Лучшей из них была Альфа-система автоматизации программирования, разработанная под руководством А.П. Ершова в Новосибирском Академгородке. Она содержала расширенный Алгол, возможность записи операторов на русском языке и была реализована на ЭВМ М20 и БЭСМ-6. Дальнейшее развитие Алгол получил в стандарте Алгол-68, но он не нашел широкого применения из-за смены поколения ЭВМ.  В США Алгол так и не одолел Фортран. Однако с появлением ЭВМ 3-го поколения и системы IBM/360 в 1964 г. стали необходимы языки, в равной степени удовлетворяющие потребностям вычислений и обработке данных. Был создан комитет, результатом деятельности которого явился новый язык программирования PL/1 - Programming Language One.  Язык объединил возможности трех языков: Фортрана, Алгола и Кобола. Из Алгола были взяты четкий синтаксис, БНФ, блочная структура, внутренние подпрограммы. Из Фортрана -принцип умолчания, форматированный ввод-вывод (сильно усовершенствованный), внешние подпрограммы. Из Кобола — структуры, как агрегаты данных, записеориентированный ввод-вывод. Были включены новые возможности - управляемая и базированная память, обработка исключительных ситуаций, параллельная обработка.  Язык получился громоздкий, сильно ориентированный на систему IBM/360, но хороший для коллективного производства программ. Во времена ЕС ЭВМ это был наиболее универсальный язык.  Языки высокого уровня позволили больше времени уделять решению задач (алгоритму), не отвлекаясь на кодирование. Языки для диалогового режима работы ЭВМ. Сотрудники математического факультета Дартмутского колледжа Томас Курц и Джон Кемени решили обучить азам программирования всех студентов независимо от специальности. Нужен язык для легкого усвоения студентами. По синтаксису он должен быть близок к Фортрану, но отличаться простотой.  Такой язык был создан в 1964 г. Он был сконструирован на диалоговое взаимодействие с ЭВМ и получил название Бейсик (BASIC - Beginning All-purpose Simbolic Code). Важно, что он легко реализовался на микрокомпьютерах в виде интерпретаторов, а позднее и компиляторов (QBASIC). Современные версии языка Бейсик позволяют решать задачи на профессиональном уровне. Последние версии Бейсика позволяют использовать оба вида трансляции: компиляцию и интерпретацию. При разработке программы используется интерпретатор, а законченная программа компилируется в загрузочный модуль. Язык не структурирован и обладает всеми недостатками Фортрана в части использования оператора GOTO. В 1975 году авторы провели ревизию языка и анонсировали истинный Бейсик (True Basic) без оператора GOTO, но он не нашел широкого применения.  В это же время Никлаус Вирт, профессор математики федерального технического университета Швейцарии (до этого работал в Станфордском университете США), создал простой язык Паскаль (Pascal). Название было взято в честь Б. Паскаля, создавшего первый механический вычислитель (см. 4).  Паскаль основан на Алголе-60 и строго структурирован. Все переменные требуют описания. Язык оказался удачным и был принят в 1970 г. на волне структурного программирования как средство обучения программированию специалистов по информатике. В дальнейшем он был приспособлен к микропроцессорам и в нею были внесены существенные добавления.  Недостаток Паскаля — невозможность модульного построения программы сдерживал его применение для производства сложных программ. В 1981 г. Вирт разработал язык модульных программ — Модула-2.  В это же время француз Филипп Кан в 1984 г. организовал в США фирму Borland International, в которой создана система  программирования Турбо Паскаль. Модульная конструкция программы решена здесь другим путем - введением специальных объектов: модулей (Units). В Турбо Паскале расширены типы данных, введены средства графики.  Другой удачный язык программирования был создан в фирме Bell в 1972 г. Денисом Ритчи, Кеном Томпсоном и Дж. Керниганом (Bell Laboratories, США). Он получил название Си (С, третий), поскольку его прототипом был созданный в Англии язык В.  Язык Си достаточно полно отражает возможности современных компьютеров, позволяя писать эффективные программы, не прибегая к Ассемблеру. Язык предназначался для системных применений, но хорошо используется и для прикладных программ. На нем написаны программы операционной системы UNIX. За более чем 30 лет своего существования язык оброс многими встроенными функциями для управления вычислительным процессом. Фирма Borland International разработала для С систему программирования Турбо С.  Военное ведомство США в 1975 г. решило навести порядок в использовании языков программирования в военных программах и создало комитет HOLWG (High Order Languages Working Group - рабочая группа по языку высокого уровня). Комитет выработал требования к универсальному языку. В 1979 г. такой язык был создан во французской фирме «Син Хоннуэлл Буль» (филиал Хоннуэлл Корпорейшн, США) под руководством Жана Ихбна. Этот язык получил название Ада в честь Огасты Ады Лавлейс, соратницы Ч. Бэббиджа.  Ада - язык структурного программирования, но большой и сложный. Программа состоит из модулей, которые могут писаться различными пользователями. Модульная схема позволяет создавать надежные, легкочитаемые и удобные в сопровождении программы. Кроме того, предусмотрено параллельное выполнение модулей с синхронизацией в местах стыковки в многопроцессорных вычислительных системах.  Ада в 1980 г. вплотную обеспечила гарантированную мобильность: программу, написанную для одного компьютера, почти наверняка можно перекомпилировать и правильно вы-  полнить на другой машине. Это делает Аду важным программным средством при разработке больших проектов.  Ада используется при разработке программ для компьютерных систем, встроенных в вооружение. Эти программы работают в реальном масштабе времени, на них накладываются жесткие требования на быстродействие. Язык Ада был принят на вооружение МО США, в том числе и НАТО.

Языки объектно-ориентированного программирования. Первым объектно-ориентированным языком программирования был SimuIa-67, созданный в Норвегии для решения задач моделирования. Наиболее мощным и развитым языком этого направления является Smalltalk, разработанный в 1972 г. А. Кеем. В нем присутствуют все основные принципы объектно-ориентированного языка, в том числе наследование, полиморфизм и инкапсуляция данных.  Объектно-ориентированная технология вошла и в существующие языки. Сотрудник лаборатории Bell Б. Саустрап в начале 1980-х годов дополнил язык С элементами языков Симула и Алгол-68. К июню 1983 г. появился язык С с классами, а чуть позднее -C++. К 1990 г. была выпущена третья версия языка C++, принятая в качестве стандарта. На его основе выпущена система программирования Borland С, а затем система визуального проектирования программ Borland C++ Builder (1996-1998 гг.).  Не остался без внимания язык Паскаль. Понятие объекта было включено в систему Турбо Паскаль, версия 5.5 (1990 г.). В 1995 г. Borland на базе языка Турбо Паскаль разработала пакет визуального программирования Дельфи (Delphi).  Построение программы сводится в Дельфи к выбору из набора готовых форм, которые вкладываются друг в друга и образуют желаемую программно-архитектурную форму программы. Разработчик работает подобно конструктору-дизайнеру. Основной упор в Дельфи делается на максимальное повторное использование имеющихся программ. Это позволяет строить приложения из уже существующих объектов, а также создавать свои собственные объекты. Чаще всего эта система программирования используется для работы с базами данных.  Широко используется версия Visual Basic, созданная в 1991 г. фирмой Microsoft. Язык встроен в интегрированный пакет Microsoft Office: текстовый процессор Word, табличный процессор Excel, система управления базами данных Access (см. раздел 7).  Языки функционального и логического программирования. Первым языком был ИПЛ (IPL - Information Processing Language) - язык обработки информации. Он создан А. Ньюэллом и его сотрудниками в технологическом институте Карнеги в Питсбурге. Центральной идеей ИПЛ было понятие списка. Список — это последовательность элементов, связанных указателями.  В 1958 г. в Массачусетском технологическом институте Д. Маккарти начал работу над языком высокого уровня, в котором понятие списка сочеталось с системой обозначений, заимствованной из функционального программирования, — лямбда-исчислением. Его ввел в 1931 г. логик А. Черч.  Лямбда-исчисление основано на трех элементах: символы (константы, переменные), скобки и обозначения функций (лямбда-функции). Маккарти назвал свой язык Лисп (Lisp - LISt Processing) — обработка списков.  В своем развитии Лисп имел множество версий. Был создан стандарт языка - Common Lisp, на его основе в 1988 г. появились система программирования Xlisp в среде Windows (Великобритания) и учебный пакет для персональных компьютеров -PC Lisp. Сейчас внедряются более строгие версии функциональных языков: Clean - Нидерланды и Haskell - Великобритания. Лисп используется в системах искусственного интеллекта, пакет AutoCAD, являющийся системой автоматизации проектирования для конструктора, также написан на языке Лисп.  Пролог, созданный в 1970-х годах на основе языка Лисп, для исследования проблем искусственного интеллекта, является языком логического программирования. В этом качестве он был выбран основным языком японского проекта ЭВМ пятого поколения. Основным элементом Пролог-программы является атом, выражающий простые отношения между отдельными объектами. В простейшем случае атом - это константа или переменная. Язык состоит только из описаний и не имеет инструкций. Каждая программа на Прологе состоит из предложений, задающих  последовательность логических выводов, с помощью которых должна быть достигнута поставленная цель - сделан окончательный вывод.  Существует ряд систем программирования на Прологе, из которых наиболее известна система Турбо Пролог (Borland). Выпустив две версии системы, фирма передала права разработки в Данию, где была создана система Visual Prolog. Кроме того, Пролог развивается в Нидерландах как система SWI-Prolog.  На основе Пролога разрабатываются экспертные системы, базы знаний, системы представления знаний.  В настоящее время существует огромное количество языков программирования, по оценкам экспертов - более двух тысяч. Среди них есть универсальные языки и узкоспециализированные.