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

К машинно-зависимым языкам программирования также относятся машинно-ориентированные языки, основные конструктивные средства которых также позволяют учитывать особенности архитектуры и принципов работы определенной ЭВМ или ряда ЭВМ, т.е. обладают теми же возможностями и требованиями к программистам, что и машинные языки, но в отличие от последних требуют предварительной трансляции на машинный язык программ, составленных с их помощью.
К данному виду языков программирования относятся: автокоды, языки символического кодирования и ассемблеры. В отличие от программирования на машинных языках программирование на машинно-ориентированных языках (ассемблерах) характерно и для современных ПК. Это объясняется тем, что в языке ассемблера допускается использование средств, присущих языкам высокого уровня.
Использование языка ассемблера, как правило, ограничивается областью системного программирования, т.е. программированием микропроцессоров, разработкой операционных систем или их компонентов, разработкой драйверов - программ обмена информацией между центральными и периферийными устройствами, программ увязки взаимодействия отдельных компонентов прикладных программ и т.д.
Тот факт, что языки данного класса учитывают специфику организации и принципов работы конкретных ЭВМ и допускают при программировании указание конкретных режимов работы физических средств ЭВМ, распределение памяти, явное определение внешних устройств и т.п., относит их к языкам "низкого уровня", или языкам уровня 1:1 (т.е. к языкам, для которых одному оператору входного языка программирования соответствует один оператор машинного языка).
Машинно-независимые языки (или языки высокого уровня) не требуют от пользователя полного знания специфики ЭВМ, на которой реализуется программа решения задачи. Инструментальные средства этих языков программирования позволяют записывать программу в виде, допускающем ее реализацию на ЭВМ с различными типами машинных операций, привязка к которым целиком возлагается на соответствующий транслятор.
Решение задачи на этих языках описывается в наглядном, достаточно легко воспринимаемом виде. Для них характерны:
возможность написания выражений, символическая идентификация переменных, вызов функций по именам и т.п. Благодаря этому производительность программиста при составлении исходных программ на языках высокого уровня примерно в 10- 15 раз выше, чем на языке ассемблера. Однако получаемые в результате трансляции машинные программы, как правило, в 2 - 5 раз объемнее по сравнению с такой же программой, но написанной на ассемблере, и работают в 2 - 5 раз медленнее.
Быстрый рост производительности ЭВМ, с одной стороны, и хроническая нехватка программистских кадров, с другой стороны, послужили причиной бурного развития и применения высокоуровневых языков программирования.
Обособленное, промежуточное положение между машинно-независимыми и машинно-зависимыми языками занимает язык Си, создание которого явилось результатом попытки объединения достоинств, присущих языкам обоих классов:
· в плане максимального использования возможностей конкретной вычислительной архитектуры (что присуще языкам низкого уровня), благодаря чему программы на языке Си компактны и работают эффективно;
· в плане максимального использования мощных выразительных возможностей современных языков высокого уровня.
Результат такого компромисса обусловил достаточно сложный синтаксис языка Си.
Язык Си и его модификации в настоящее время используются главным образом для создания системных и прикладных программных продуктов, в которых решающее значение отводится факторам быстродействия и минимизации объемов памяти. На языке Си написано ядро операционной системы Unix, вследствие чего ее легко можно было изменять и модернизировать (а это упрощает процесс ее переноса с одной вычислительной системы на другую, при этом 95% исходного программного текста операционной системы остается неизмененным).
Машинно-независимые языки классифицируются на процедурно-ориентированные и проблемно-ориентированные.
Процедурно-ориентированные (универсальные) языки эффективны для описания алгоритмов решения широкого класса задач. Из языков этого класса наиболее известны: Фортран, Кобол, ПЛ/1, Бейсик, Паскаль, Ада.
Проблемно-ориентированные языки предназначены для описания процессов обработки информации в более узкой, специфической области. Наиболее известными языками этой группы являются: РПГ, Лисп, АПЛ, GPSS.
В последнее время отмечается бурный рост объектно-ориентированных языков программирования, т.е. языков, ориентированных на разработку программных приложений для широкого круга разнообразных по сфере приложения задач, имеющих общность в реализуемых компонентах (например, при взаимодействии с базами данных, работе в условиях функционирования корпоративных сетей организаций или взаимодействии с глобальной сетью Интернет). Объектно-ориентированный подход в программировании позволяет применять одни и те же (типовые) архитектурные и концептуальные решения для быстрого создания эффективных программных приложений.
Основное достоинство алгоритмических языков высокого уровня - возможность описания программ решения задач в форме, максимально удобной для восприятия человеком. Но так как каждое семейство ЭВМ имеет свой собственный, специфический внутренний (машинный) язык и может выполнять лишь те команды, которые записаны на этом языке, то для перевода исходных программ на машинный язык используются специальные программы-трансляторы.
Работа всех трансляторов строится по одному из двух принципов: интерпретация или компиляция.
Интерпретация подразумевает пооператорную трансляцию и последующее выполнение оттранслированного оператора исходной программы. В связи с этим можно отметить два недостатка метода интерпретации: во-первых, интерпретирующая программа должна находиться в памяти ЭВМ в течение всего процесса выполнения исходной программы, т.е. занимать определенный объем памяти; во-вторых, процесс трансляции одного и того же оператора повторяется столько раз, сколько раз должна исполняться эта команда в программе, что резко снижает производительность работы программы.
Несмотря на указанные недостатки, трансляторы-интерпретаторы получили достаточное распространение, так как они поддерживают диалоговый режим, что особенно удобно при разработке и отладке исходных программ. Кроме того, интерпретаторы легче разрабатывать, и они обходятся дешевле, чем компиляторы с того же языка.
В случае многократного решения задачи, когда быстродействие работы вычислительной системы имеет существенное значение, целесообразно использовать другой принцип - компиляцию.
При компиляции процессы трансляции и выполнения разделены во времени: сначала исходная программа полностью переводится на машинный язык (после чего наличие транслятора в оперативной памяти становится ненужным), а затем оттранслированная программа может многократно исполняться. Следовательно, для одной и той же программы трансляция методом компиляции обеспечивает более высокую производительность вычислительной системы при сокращении требуемой оперативной памяти.
Большая сложность в разработке компилятора по сравнению с интерпретатором с того же самого языка объясняется тем, что компиляция программы включает два действия: анализ, т.е. определение правильности записи исходной программы в соответствии с правилами построения языковых конструкций входного языка, и синтез - генерирование эквивалентной программы в машинных кодах. Трансляция методом компиляции требует неоднократного "просмотра" транслируемой программы, т.е. трансляторы-компиляторы являются многопроходными: при первом проходе они проверяют корректность синтаксиса языковых конструкций отдельных операторов независимо друг от друга, при последующем проходе - корректность синтаксических взаимосвязей между операторами и т.д.
Полученная в результате трансляции методом компиляции программа называется объектным модулем, который представляет собой эквивалентную программу в машинных кодах, но не "привязанную" к конкретным адресам оперативной памяти. Поэтому перед исполнением объектный модуль должен быть обработан специальной программой операционной системы (редактором связей) и преобразован в загрузочный модуль, т.е. программный модуль с относительными адресами.
Загрузочный модуль может иметь простую, оверлейную или динамическую структуру.
Модуль простой структуры состоит из единственного загрузочного модуля, сформированного редактором связей. Этот модуль перед исполнением целиком загружается в оперативную память и включает все необходимые для его работы команды. Модули простой структуры наиболее эффективны с точки зрения производительности, так как в ходе исполнения требуют минимального вмешательства управляющей программы ОС.
Если программа функционально достаточно сложна или велика по размерам, то она реализуется в виде модулей (сегментов) оверлейной структуры (структуры "с перекрытием"). Загрузочный модуль оверлейной структуры состоит из оверлейных сегментов и содержит информацию, используемую оверлейным супервизором для загрузки отдельных сегментов в основную память. При этом разные сегменты такой программы могут повторно использовать одну и ту же область оперативной памяти. Оверлейная организация модулей менее эффективна с точки зрения времени их исполнения, так как требует большего вмешательства управляющей программы ОС.
При выполнении модулей простой и оверлейной структуры управляющая программа ОС не осуществляет вызов других загрузочных модулей, и в этом они уступают динамической организации модулей. При выполнении загрузочных модулей динамической структуры могут появляться запросы на другие загрузочные модули, и управляющая программа ОС может начать загрузку этих модулей в оперативную память еще до завершения исполнения предыдущего модуля. Благодаря этому вызываемые программные модули могут исполняться как последовательно, так и параллельно, что повышает быстродействие программы.
Наряду с рассмотренными выше трансляторами-интерпретаторами и трансляторами-компиляторами на практике используются также трансляторы интерпретаторы-компиляторы, которые объединяют в себе достоинства обоих принципов трансляции: на этапе разработки и отладки программ транслятор работает в режиме интерпретатора, а после завершения процесса отладки исходная программа повторно транслируется в объектный модуль (т.е. уже методом компиляции). Это позволяет значительно упростить и ускорить процесс составления и отладки программ, а за счет последующего получения объектного модуля обеспечить более эффективное исполнение программы.
Учитывая, что эффективность программ, получаемых с помощью высокоуровневых языков программирования, может значительно уступать аналогичным программам, составленным на языках низкого уровня, в ряде случаев используются оптимизирующие трансляторы (оптимайзеры), которые после завершения компиляции осуществляют оптимизацию объектного модуля.
Например, хороший компилятор способен распознать небрежность программиста и исключить из цикла “статические” вычисления. Под “статическими” вычислениями понимается выполнение в цикле определенной операции, результат которой не зависит от итераций цикла. Распознав такую конструкцию, компилятор выводит ее за рамки цикла. Этот тип оптимизации называется перемещением выражений.
Другим более сложным видом оптимизации является устранение неиспользуемого кода. Компилятор находит операторы, которые не выполняются ни при каких условиях, и не включает их в исполняемый код.
В общем случае в зависимости от выигрыша в производительности и временных затрат все виды оптимизации можно разделить на несколько уровней. Первый и второй уровни оптимизации, как правило, повышают быстродействие на 10 - 15% при минимальных затратах. Третий уровень оптимизации позволяет увеличить производительность еще на 5%, однако это обойдется значительно дороже.
Таким образом, выбор типа алгоритмического языка (см. рис. 7.3) зависит от многих факторов: назначения, удобства написания исходных программ, эффективности получаемых объектных программ и т.п. Для ПК ведущее место в настоящее время занимают языки высокого уровня, например различные версии языков: Бейсик, Паскаль, Фортран, Кобол, АПЛ, Ада, Си и т.д.
Среди них доминирующая роль отводится процедурно-ориентированным языкам, называемым также универсальными (хотя некоторые из них, например Фортран, Кобол, Бейсик и т.п., и разрабатывались с ориентацией на конкретную сферу применения).
Абсолютное большинство языков программирования в настоящее время составляют процедурные языки, с помощью которых программист определяет последовательность реализации событий в объектной программе путем последовательной записи предложений в исходной программе. Иными словами, программирование на этих языках подразумевает необходимость описания не только того, что необходимо получить в результате решения задачи, но и того, как это необходимо осуществить.
Одним из главных направлений совершенствования языков программирования для задач экономического управления было стремление к разработке таких языков, в которых до минимума сводилась (а в идеале вообще отсутствовала) проблема как. Естественно, что такие языки не могут быть процедурными.
Первую попытку создания такого языка предпринял Ломбарди, предложивший и реализовавший в 1963 г. для частного класса задач, связанных с обработкой файлов в сфере управления, язык General business-oriented language baseed on decision expression. В этой же области свои языки предложили фирмы ICL (язык NICOL) и IBM (язык РПГ), в которых многое связанное с процедурой работы программы носит скорее неявный, чем явный характер. Учитывая, что значительная часть логики программы реализуется автоматически, время создания программ с помощью таких языков и число отладочных проверок значительно сократились.
Таким образом, наряду с универсальными процедурно-ориентированными языками стали создаваться проблемно-ориентированные языки программирования, предназначенные для описания процессов обработки информации в какой-либо узкой (специфической) области, в которых решение задачи в большей степени сосредоточивалось на проблеме, что необходимо получить в результате, а проблема, как это необходимо сделать, в большей или меньшей степени снималась с программиста. Среди этих языков наиболее известными являются: РПГ – язык для генерации отчетов, Лисп - язык для обработки списков, GPSS – язык для моделирования, АПЛ - язык для статистической обработки массивов.
Актуальности решения проблемы разработки языков программирования, базирующихся на принципах что без как, способствовал международный конгресс IFIP (International Federation of Information Processing-Международная федерация по обработке информации), прошедший в Стокгольме в 1976 г. под лозунгом "В 1980 г. программирование без программистов ". В рамках реализации этой идеи были созданы непроцедурные языки, приближающиеся по своему синтаксису к естественному языку и ориентированные на пользователей - специалистов управления, не являющихся программистами.
Наиболее известными из языков этого типа являются:
· Smalltalking - малый разговорный;
· QBE (Query By Example-программирование на примере);
· Форт, который находит применение при решении сложных задач имитационного моделирования, в системах искусственного интеллекта в графических системах и т.п.
Основной особенностью языка Форт является его открытость, которая позволяет на основе имеющихся определений строить новые функции. При этом программист может вводить новые операции, типы данных или определения. Возможность поддержки средствами Форт многозадачного режима работы придают ему свойства операционной системы.
Особое место среди языков программирования занимают функциональные языки, в частности Пролог (PROLOG - PROgramming in LOGic - логическое программирование), предложенный А.Калмероэ в 1978 г., являющийся языком логического программирования, относящимся к языкам пятого поколения. Главное назначение языка - разработка интеллектуальных программ и систем. Пролог - это язык программирования, созданный специально для работы с базами знаний, основанными на фактах и правилах (одного из элементов систем искусственного интеллекта). В языке реализован механизм возврата для выполнения обратной цепочки рассуждений, при котором предполагается, что некоторые выводы или заключения истинны, а затем эти предположения проверяются в базе знаний, содержащей факты и правила логического вывода. Если предположение не подтверждается, выполняется возврат и выдвигается новое предположение.
Языковые средства СУБД предназначены в первую очередь для разработки прикладных программ решения задач экономического управления, информация для которых хранится и поддерживается с помощью баз данных. Синтаксис языка программирования в среде СУБД мало чем отличается от синтаксиса высокоуровневых языков программирования, в связи с чем указанные программно-инструментальные средства ориентированы в основном на профессиональных программистов, хотя наличие развитых средств подсказки и помощи (в виде примеров, демонстрирующих использование отдельных языковых конструкций) значительно облегчает работу достаточно широкого круга пользователей.
Sequel (Structured English QUEry Language) и его усовершенствованный вариант SQL - языки манипулирования данными, основанные на исчислении отношений. Используются в реляционных СУБД в качестве языка запросов к базам данных и языка программирования задач обработки данных.
С развитием компьютерных сетей, увеличением вычислительной мощности компьютеров и их ресурсов возникла потребность в интерпретирующем языке, позволяющем получать многоплатформенную вычислительную среду путем преобразования с его помощью программ, написанных на других языках программирования (при незначительном снижении их производительности). Наиболее близко к реализации подобного языка подошла технология языка Java (а точнее ее часть - байт-код). Именно его разработка и использование составляют принципиальное отличие, которое выделяет язык Java среди других языков программирования высокого уровня. Объектно-ориентированный язык Java (разработанный на базе языка Си++) предназначен для создания надежных, переносимых, распределенных сетевых программных приложений, работающих в различных многооконных системах в условиях архитектуры клиент-сервер, а также для администраторов сети, использующих Java-приложения для улучшения интерактивных качеств Web-серверов.
Другим объектно-ориентированным языком программирования является язык Delphi. Созданный на базе языка Паскаль специалистами фирмы Borland язык Delphi, обладая мощностью и гибкостью языков Си и Си++, превосходит их по удобству и простоте интерфейса при разработке приложений, обеспечивающих взаимодействие с базами данных и поддержку различного рода работ в рамках корпоративных сетей и сети Интернет.
В последние годы резко расширилась практика программирования в среде электронных таблиц. В основе реализации программирования задач с помощью электронных таблиц (ЭТ) лежит идея компьютеризации работы пользователей с "пустографкой" как специфической формой представления документа, с которым обычно приходится иметь дело специалистам управления. Разработчики электронных таблиц (впоследствии названных табличными процессорами) воплотили эту идею путем предоставления пользователям возможности записи в любую клетку электронной таблицы цифровой, символьной (текстовой) информации либо формулы, обеспечивающей получение искомого результата по различным исходным данным.
Пользователь ЭТ получил удобное инструментальное средство, позволяющее: вводить исходные данные, необходимые для решения задач; указывать формулы получения результатных данных; оформлять решение задачи в виде привычных для него табличных документов. При этом способ описания расчетных формул почти ничем не отличается от принятых правил их представления в математике (за исключением требования линейной структуры записи). Порядок реализации арифметических действий в формулах совпадает с принятым приоритетом выполнения операций в математике, а для изменения такого порядка используется система круглых скобок.
Единственным наследием, доставшимся пользователям ЭТ от программирования на высокоуровневых языках, осталось правило построения логических выражений, реализуемое по стандартной для языков программирования схеме построения условных операторов: IF - THEN - ELSE (если условие соблюдается, то выполняется действие, иначе осуществляется действие-2).
Быстрому и широкому распространению ЭТ как инструментальному средству решения экономических задач, помимо простоты и удобства подготовки решения с их помощью задач, способствовали также:
· наличие большого числа встроенных функций (математических, статистических, финансовых и т.п.);
· возможность "проигрывания" различных вариантов решения задач и выбора лучшего из них (за счет быстрого автоматического пересчета конечных результатов при любом изменении исходных данных);
· поддержка ЭТ средствами графической интерпретации, наглядное представление результатной информации.
Кроме того, работа с современными электронными таблицами может быть автоматизирована благодаря использованию командных языков, макросов и т.п.
Стили программирования
Одним из важнейших признаков классификации языков программирования является принадлежность их к одному из стилей, основными из которых являются следующие: процедурный, функциональный, логический и объектно-ориентированный.
Процедурное программирование
Процедурное (императивное) программирование является отражением архитектуры традиционных ЭВМ, которая была предложена фон Нейманом в 40-х годах. Теоретической моделью процедурного программирования служит алгоритмическая система под названием «машина Тьюринга».
Программа на процедурном языке программирования состоит из последовательности операторов (инструкций), задающих процедуру решения задачи. Основным является оператор присваивания, служащий для изменения содержимого областей памяти. Концепция памяти как хранилища значений, содержимое которого может обновляться операторами программы, является фундаментальной в императивном программировании.
Выполнение программы сводится к последовательному выполнению операторов с целью преобразования исходного состояния памяти, то есть значений исходных данных, в заключительное, то есть в результаты. Таким образом, с точки зрения программиста имеются программа и память, причем первая последовательно обновляет содержимое последней.
Процедурные языки характеризуются следующими особенностями:
· необходимостью явного управления памятью, в частности, описанием переменных;
· малой пригодностью для символьных вычислений;
· отсутствием строгой математической основы;
· высокой эффективностью реализации на традиционных ЭВМ.
Одним из важнейших классификационных признаков процедурного языка является его уровень. Уровень языка программирования определяется семантической (смысловой) емкостью его конструкций и степенью его ориентации на программиста. Язык программирования частично ликвидирует разрыв между методами решения различного рода задач человеком и вычислительной машиной. Чем более язык ориентирован на человека, тем выше его уровень. Дадим краткую характеристику реализованным на ПЭВМ языкам программирования в порядке возрастания их уровня.
Двоичный язык является непосредственно машинным языком. В настоящее время такие языки программистами практически не применяются.
Язык Ассемблера — это язык, предназначенный для представления в удобочитаемой символической форме программ, записанных на машинном языке. Он позволяет программисту пользоваться мнемоническими кодами операций, присваивать удобные имена ячейкам и областям памяти, а также задавать наиболее удобные схемы адресации.
Язык Макроассемблера является расширением языка Ассемблера путем включения в него макросредств. С их помощью в программе можно описывать последовательности инструкций с параметрами — макроопределения. После этого программист может использовать снабженные аргументами макрокоманды, которые в процессе ассемблирования программы автоматически замещаются макрорасширениями. Макрорасширение представляет собой макроопределение с подставленными вместо параметров аргументами.
Другими словами, язык Макроассемблера представляет средства определения и использования новых, более мощных команд как последовательности базовых инструкций, что несколько повышает его уровень.
Языки Ассемблера и Макроассемблера применяются системными программистами-профессионалами с целью использования всех возможностей оборудования ЭВМ и получения эффективной по времени выполнения и по требуемому объему памяти программы. На этих языках обычно разрабатываются относительно небольшие программы, входящие в состав системного программного обеспечения: драйверы, утилиты и другие.
Язык программирования С (Си) первоначально был разработан для реализации операционной системы UNIX в начале 70-х годов. В последующем приобрел высокую популярность среди системных и прикладных программистов. В настоящее время этот язык реализован на большинстве ЭВМ.
В С сочетаются достоинства современных высокоуровневых языков в части управляющих конструкций и структур данных с возможностями доступа к аппаратным средствам ЭВМ на уровне, который обычно ассоциируется с языком низкого уровня типа языка Ассемблера. Язык С имеет синтаксис, обеспечивающий краткость программы, а компиляторы способны генерировать эффективный объектный код.
Одна из наиболее существенных особенностей С состоит в нивелировании различий между выражениями и операторами, что приближает его к функциональным языкам. В частности, выражение может обладать побочным эффектом присваивания, а также может использоваться в качестве оператора. Нет также четкой границы между процедурами и функциями, более того, понятие процедуры не вводится вообще.
Синтаксис языка затрудняет программирование и восприятие составленных программ. Отсутствует и строгая типизация данных, что предоставляет дополнительные возможности программисту, но не способствует написанию надежных программ.
Ваsic(Бэйсик) (Beginners All-purpose Symbolic Instruction Code) — многоцелевой язык символических инструкций для начинающих) представляет собой простой язык программирования, разработанный в 1964 году для использования новичками. Он был разработан как простейший язык для непосредственного общения человека с вычислительной машиной. Поэтому первоначально работа велась в интерактивном режиме с использованием интерпретаторов. В настоящее время для этого языка имеются также и компиляторы.
Согласно концепциям, заложенным в Basic, этот язык в смысле строгости и стройности является антиподом языка Pascal. В частности, в нем широко распространены различные правила умолчания, что считается плохим тоном в большинстве языков программирования подобного типа.
Basic широко распространен на ЭВМ различных типов и очень популярен в среде программистов, особенно начинающих. Существует множество диалектов этого языка, мало совместимых между собой. Basic активно поглощает многие концепции и новинки из других языков. Поэтому он достаточно динамичен, и нельзя однозначно определить его уровень.
Pascal (Паскаль) является одним из наиболее популярных среди прикладных программистов процедурным языком программирования, особенно для ПЭВМ. Разработанный в 1970 году швейцарским специалистом в области вычислительной техники профессором Н. Виртом, язык назван в честь французского математика и по замыслу автора предназначался для обучения программированию. Однако язык получился настолько удачным, что стал одним из основных инструментов прикладных и системных программистов при решении задач вычислительного и информационно-логического характера. В 1979 году был подготовлен проект описания языка — Британский стандарт языка программирования Pascal BS6192, который стал также и международным стандартом ISO 7185.
В языке Pascal реализован ряд концепций, рассматриваемых как основа «дисциплинированного» программирования и заимствованных впоследствии разработчиками многих языков. Одним из существенных признаков языка Pascal является последовательная и достаточно полная реализация концепции структурного программирования. Причем это осуществляется не только путем упорядочивания связей между фрагмента
