.RU
Карта сайта

Основные понятия традиционного программирования - Содержание предисловие 2 веб-страницы 3 введение 6 1архитектура ЭВМ 17

Основные понятия традиционного программирования


В этом разделе мы рассмотрим некоторые понятия императивных и объектно-ориентированных языков программирования. Мы будем обращаться к таким языкам программирования, как Ada, С, C++, С#, FORTRAN, Java и Pascal. FORTRAN, Pascal и С относятся к императивным языкам третьего поколения. C++ является объектно-ориентированным языком, разработанным как расширение языка С. Языки Java и С# — это тоже объектно-ориентированные языки, созданные на основе языка C++. (Язык Java был создан компанией Sun Microsystems, a C# является продуктом компании Microsoft.) Ada первоначально создавался как императивный язык третьего поколения, обладающий свойствами объектно-ориентированных языков. Однако его новейшая версия более всего соответствует парадигме объектно-ориентированных языков.

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

Хотя мы и включили объектно-ориентированные языки, такие как C++, Java и С#, в список рассматриваемых языков, в этом разделе мы чаще будем обращаться к императивным языкам, поскольку многие компоненты программы, написанной на объектно-ориентированном языке (например, процедуры, описывающие, как объект должен реагировать на внешний стимул), в сущности, являются небольшими императивными программами. Отличительные характеристики объектно-ориентированных языков программирования мы рассмотрим в разделе 5.5.

Культуры языков программирования


Как и в случае с естественными языками, люди, использующие разные языки программирования, приобретают различия, делающие их представителями разных культур, и часто спорят о преимуществах использования того или иного языка. Иногда эти различия очень заметны, например, когда речь идет о разных парадигмах программирования. В других случаях различия незначительны. Например, несмотря на то что в этой книге приводятся два понятия, «процедура» и «функция» (раздел 5.3), программист, работающий с языком С, всегда говорит о функции, потому что процедура в языке С является функцией, которая не возвращает никакого значения. Еще похожий пример. Программист, работающий с языком C++, процедуру объекта называет функцией-членом, хотя существует общий термин «метод». Это различие является результатом того, что язык C++ представляет собой расширение языка С. Другое различие заключается в том, что зарезервированные слова в языках Pascal и Ada выделяются жирным шрифтом. Этот прием не используется программистами в языках С, C++, FORTRAN и Java1.

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

Операторы, которые содержат рассматриваемые языки, можно разделить на три группы: операторы описания, исполняемые операторы и комментарии. Операторы описания (declarative statements) определяют терминологию, которая будет использоваться в программе, например задают имена, используемые в дальнейшем для ссылок на элементы данных. Исполняемые операторы (imperative statements) описывают шаги алгоритма, лежащего в основе программы. Комментарии (comments) упрощают чтение текста программы, объясняя ее свойства на естественном языке. Программа, написанная на императивном языке, или элемент такой программы (например, процедура) обычно начинается с описания данных, которые будут использоваться в программе. За операторами описания следуют исполняемые операторы, описывающие алгоритм, который будет выполняться (рис. 5.4). Комментарии можно поместить в любое место программы для объяснения выполняемых ею действий. Сначала рассмотрим понятия, связанные операторами описания.

Переменные и типы данных


В разделе 5.1 говорилось о том, что языки программирования высокого уровня позволяют обращаться к ячейкам памяти предпочтительно через описательные имена, а не через числовые адреса. Такие имена называются переменными (variable), тем самым подчеркивается тот факт, что при изменении значения, хранящегося в ячейке памяти, изменяется и значение, присвоенное переменной. В рассматриваемых нами языках все переменные, которые будут использоваться в программе, должны быть предварительно определены с помощью операторов описания. В этих же операторах необходимо описать типы данных, которые будут храниться в ячейках, связанных с переменными.

Понятие тип данных (data type) включает в себя и способ кодировки данных, и операции, которые можно выполнять над этими данными. Например, к типу данных integer (целые числа) относятся числовые данные, состоящие из целых чисел, которые хранятся в двоичном дополнительном коде. Над целыми числами можно выполнять обычные арифметические операции и операции сравнения. К типу данных real, или вещественные числа (в некоторых языках он называется float), относятся числовые данные, которые содержат действительные числа, представленные в формате с плавающей запятой. Над данными типа real можно выполнять те же операции, что и над целыми числами. Однако обратите внимание на то, что при сложении двух целых чисел и при сложении двух вещественных чисел выполняются разные действия.

Предположим, что мы хотим использовать переменную WeightLimit в нашей программе для обращения к ячейке памяти, содержащей числовое значение, представленное в двоичном дополнительном коде. В языках С, C++, Java и С# мы бы воспользовались выражением

int WeightLimit:

которое означает: «Имя WeightLimit будет использоваться дальше в программе по отношению к ячейке памяти, содержащей значение, представленное в двоичном дополнительном коде». В одном выражении можно объявить тип нескольких переменных. Например, выражение

int Height. Width;

объявляет обе переменные, Height и Width, как переменные типа integer. Кроме того, многие языки позволяют при описании переменной задавать ее первоначальное значение1. Таким образом, выражение

int WeightLimit = 100;

не только объявляет переменную WeightLimit переменной типа integer, но гакже присваивает ей начальное значение 100.

Другими распространенными типами данных являются character (символьный тип) и Boolean (логический тип). К символьному типу данных character относятся данные, состоящие из символов, хранящихся в кодировке ASCII или Unicode. Над такими данными можно выполнять операцию сравнения, то есть определять, находится ли один символ перед другим в алфавитном порядке, проверку, является ли цепочка символов подцепочкой другой, а также операцию конкатенации, то есть то есть добавления одной цепочки символов в конец другой.

К логическому типу данных Bool ean относятся элементы данных, которые могут принимать только два значения — true (истина) или false (ложь). К таким переменным можно применять операцию запроса, является текущее значение переменной истиной или ложью. Например, если переменная EndOfList является переменной логического типа, то можно использовать такое выражение

if (EndOfList) then (...) else (...).

К другим типам данных, которые еще пока не являются примитивами в языках программирования, относятся изображения, аудио-, видео- и гипертекст. Однако такие типы, как GIF, JPEG и HTML, могут в ближайшем будущем стать такими же обычными, как integer и real. Язык Java, который содержит инструменты для работы со многими такими типами данных, является шагом в этом направлении.

Пример того, как можно описать одни и те же переменные в разных языках программирования, представлен в табл. 5.1. (Переменные Length и Width являются переменными вещественного типа, переменные Price, Tax и Total — целочисленные переменные, а переменная Symbol является переменной символьного типа.) Обратите внимание на то, что языки больше различаются по форме, чем по содержанию. В разделе 5.4 мы рассмотрим, как транслирующая программа использует сведения, собранные из таких декларативных выражений, чтобы преобразовать программу, написанную на языке высокого уровня, в машинные команды. А пока обратите внимание на то, что такую информацию можно использовать для поиска ошибок. Например, выражение, которое требует сложения двух переменных символьного типа, по всей видимости, содержит ошибку.

Таблица 5.1. Описание переменных в разных языках программирования

Описание переменных в языке Pascal var

Lehgth, Width: real; Price, Tax, Total: integer; ____________________________________________Symbol:____________char;___________________

Описание переменных в языках С, C++, С# float Length, Width; и Java int Price. Tax, Total: ____________________________________________char Symbol;______________________________

Описание переменных в языке FORTRAN REAL Length, Width

IMTEGER Price. Tax. Total __________________________________________________CHARACTER Symbol_______________________________

Структуры данных


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

Наиболее распространенной структурой данных является однородный массив (homogeneous array). Однородный массив представляет собой набор значений одного типа, например одномерный список, двумерную таблицу или таблицу с большим количеством измерений. В большинстве языков программирования для того, чтобы описать массив, нужно задать количество измерений, а также число элементов в каждом измерении. Например, структура, описанная выражением в языке С int Scores [2] [9];

означает: «Переменная Scores будет использоваться в программе для обозначения двумерного массива целых чисел, состоящего из двух строк и девяти столбцов» (рис. 5.5). То же самое выражение на языке FORTRAN будет выглядеть следующим образом:

INTEGER Scores (2.9).

После описания массива к нему можно обращаться по заданному имени. А к отдельным элементам массива можно обращаться с помощью целых чисел, которые называются индексами (indices). Они определяют строку и ряд, в котором находится элемент массива. Однако диапазон индексов меняется от языка к языку. Например, в языке С (и его производных C++, Java и С#) индексы начинаются с 0. То есть элемент, находящийся во второй строке и четвертом столбце массива Scores, можно обозначить с помощью выражения Scores [1] [3], а элемент, расположенный в первой строке и первом столбце, будет обозначаться как Scores [0] [0]. Напротив, в языке FORTRAN индексы начинаются с 1, поэтому элемент, расположенный во второй строке и четвертом столбце, будет обозначаться как Scores (2,4) (см. рис. 5.5).

Некоторые языки программирования предоставляют программисту свободу в выборе интервала индексов для однородного массива. Например, выражение Scores: array [3..4. 12..20] of integer:

Таблица 5.1. Описание переменных в

разных языках программирования

Описание переменных в языке Pascal

var

Lehgth, Width: Price, Tax, Total Symbol:

real; : integer; char;

Описание переменных в языках С, C++, С# и Java

float Length, Width; int Price. Tax, Total: char Symbol:

Описание переменных в языке FORTRAN

REAL Length, INTEGER Price. CHARACTER Symbol

Width Tax. Total


в языке Pascal описывает такой же двумерный массив целых чисел Scores, как и приведенный выше, за исключением того, что строки здесь определены значениями 3 и 4, а столбцы пронумерованы от 12 до 20. Поэтому элемент, расположенный во втором ряду и четвертом столбце, будет обозначаться выражением Scores [4,15].

В отличие от однородного массива, в котором элементы данных относятся к одному типу, неоднородный массив (heterogeneous array) может содержать данные разных типов. Например, совокупность данных о сотруднике компании может состоять из элемента символьного типа Name, элемента целочисленного типа Аде и элемента вещественного типа Ski 11 Rating. В языках Pascal и С (рис. 5.6) такой тип массива называется соответственно записью (record) и структурой (structure).

Описание неоднородного массива в Pascal

var

Employee: record

Name: packed array [1..8] of char; Age: integer; SkillRating: real end

Описание неоднородного массива в С

struct

{ char Name [8];

int Age:

float SkillRating; } Employee:


К компоненту неоднородного массива обычно обращаются по имени массива, после которого ставится точка и затем указывается имя этого компонента. Например, к компоненту Age массива Employee (см. рис. 5.6) можно обратиться с помощью выражения Employee.Age.

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

Константы и литералы


Иногда в программе используются фиксированные, заранее заданные значения. Например, программа, управляющая воздушным движением определенного аэропорта, может содержать различные ссылки на положение этого аэропорта относительно уровня моря. В процессе написания программы это значение, скажем, 645 футов, можно каждый раз записывать числом. Такая явная запись значения называется литералом (literal). В результате использования литералов получаются такие выражения, как

EffectiveAlt <- Altimeter - 645

где EffectiveAlt и Altimeter — переменные, а 645 — литерал.

Однако использование литералов не очень удобно, поскольку иногда трудно понять значение выражения, в которое они включены. Как, например, можно узнать из предыдущего выражения, что означает число 645? Кроме того, использование литералов может усложнить изменение программы, если оно потребуется. Если с этой программой работать в другом аэропорту, то все ссылки на положение аэропорта относительно уровня моря нужно изменить. Если используется литерал 645, то нужно просмотреть всю программу и изменить каждое выражение, в котором он встречается. Трудности могут возникнуть в том случае, когда литерал 645 используется также для обозначения какого-либо другого свойства. Как тогда узнать, какое из них нужно поменять?

Для того чтобы избежать этих трудностей, в языках программирования существует возможность присваивать постоянным значениям описательные имена. Такие имена называются константами (constant). Например, описательный оператор языка Ada

AirportAlt constant Integer := 645:

присваивает имени Ai rportAl t фиксированное значение 645 целочисленного типа. То же самое выражение можно записать на Java:

final int AirportAlt = 645;

а на C++ и С# оно будет иметь следующий вид:

const AirportAlt = 645.

После такого выражения имя AirportAlt можно использовать вместо литерала 645. Используя эту константу в нашем псевдокоде, выражение

EffectiveAlt <- Alireter - 645

можно переписать как

EffectiveAlt <- Alimeter - AirportAlt.

Нетрудно заметить, что последнее выражение лучше отражает смысл утверждения. Кроме того, если программу, содержащую такие константы, использовать в другом аэропорту, который находится на высоте 267 футов над уровнем моря, то все, что нужно сделать, это изменить параметры одного оператора описания.

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


Как только определены переменные и константы, которые будут использоваться в программе, программист может приступать непосредственно к процессу описания алгоритма, который осуществляется с помощью исполняемых операторов. Основными исполняемыми операторами являются операторы присваивания (assignment statement), в результате выполнения которых переменной присваивается некоторое значение (или, более точно, значение сохраняется в ячейке памяти, связанной с этой переменной). Синтаксические структуры с такими операторами обычно состоят из переменной, за которой следуют символ операции присваивания, и выражение, обозначающее значение, которое нужно присвоить. Эта структура означает, что выражение нужно вычислить, а результат сохранить как значение данной переменной. Например, утверждение

Z = X + Y:

в языках С, C++, С# и Java означает, что сумму X и Y нужно присвоить переменной Z. В языках Ada и Pascal это утверждение будет иметь вид:

Z := X + Y;

Обратите внимание на то, что эти выражения отличаются только оператором присваивания: в языках С, C++ и Java это просто знак равенства, а в языках Ada и Pascal — двоеточие и знак равенства. Возможно, самое наглядное обозначение для оператора присваивания используется в языке APL (A Programming Language), который был создан Кеннетом Иверсеном (Kenneth E. Iverson) в 1962 году. Для записи операции присваивания в этом языке применяется стрелка. Таким образом, приведенное выше выражение в APL (как и в нашем псевдокоде) можно записать так: Z <- X + Y.

Основное качество операторов присваивания состоит в том, что в правую часть высказывания можно поместить любое выражение. Например, алгебраическое выражение с арифметическими операциями сложения, вычитания, умножения и деления, которые обычно обозначаются символами +, -, * и / соответственно. Однако эти выражения по-разному интерпретируются в языках программирования. Например, результатом выражения 2*4 + 6/2 будет 14, если вычислять его справа налево, или 7, если вычислять его слева направо. Эта неоднозначность обычно разрешается с помощью введения приоритетов (старшинства) операторов (operator precedence). Согласно традиционным правилам алгебры операции умножения и деления имеют приоритет над операциями сложения и вычитания.

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

2 х (4 + 6)/2

равно 10.

Выражения оператора присваивания могут содержать не только алгебраические операции. Например, если переменные Fi rst и Last представляют собой цепочки символов, то после выполнения следующей команды, записанной на языке FORTRAN: Both = First // Last

переменной Both будет присвоен результат конкатенации этих двух цепочек. То есть если переменные First и Last равны abra и cadabra соответственно, то переменная Both будет равна цепочке abracadabra.

Многие языки программирования позволяют использовать один символ для обозначения нескольких операций. В таких случаях значение символа определяется типом операндов. Например, символ «+» обычно обозначает операцию сложения, когда его операндами являются числа. Но в языке Java этот символ также обозначает конкатенацию, когда его операндами являются цепочки символов. Такое использование символов операций называется перегрузкой операций (overloading).

Управляющие операторы


Управляющими операторами (control statement) называются исполняемые операторы, меняющие последовательность выполнения инструкций программы. Из всех операторов, использующихся в языках программирования, операторы управления вызвали больше всего споров. Основным предметом дискуссий является самый простой оператор управления goto. Он позволяет изменить порядок выполнения программы и перейти к выполнению программы, начиная с определенного места, которое обозначено именем или числом. Следовательно, этот оператор является не чем иным, как непосредственным применением команды перехода машинного языка. Наличие такого оператора в языке высокого уровня позволяет программистам писать такие бессистемные программы1:

goto 40 20 Применить процедуру Evade

goto 70 40 if (KryptoniteLevel < LethalDose) then goto 60

goto 20

60 Применить процедуру RescueDamsel 70 ...

тогда как все эти действия можно записать с помощью одной структуры:

if (KryptoniteLevel < LethalDose)

then (применить процедуру RescueDamsel) else (применить процедуру Evade)

Для того чтобы избежать таких сложностей, современные языки программирования содержат такие операторы управления, которые позволяют записывать ветвящиеся структуры с помощью одного выражения. Некоторые общепринятые ветвящиеся структуры и соответствующие им в разных языках программирования операторы управления изображены на рис. 5.7. Обратите внимание на го, что с первыми двумя структурами мы уже встречались в главе 4. В нашем псевдокоде они представлены операторами if-then-else и while. Третью структуру, которая называется выбором, можно рассматривать как расширение структуры i f-then-el se. Различие между ними состоит в том, что оператор if-then-else позволяет выбирать из двух вариантов, а оператор case — из нескольких.


Другой распространенной структурой является оператор цикла for (рис. 5.8), подобный оператору while нашего псевдокода. Различие между ними заключается в том, что инициализация, модификация и проверка условия завершения цикла объединены в одном операторе. Такой оператор удобно использовать, когда тело цикла нужно выполнить определенное количество раз — один раз для каждого значения переменной-счетчика в заданном интервале. В частности, оператор, изображенный на рис. 5.8, предписывает, чтобы тело цикла было выполнено несколько раз: когда значение переменной Count равно 1, затем когда ее значение равно 2 и последний раз, когда ее значение равно 3.


Из приведенных примеров можно сделать вывод, что ветвящиеся структуры с незначительными вариациями присутствуют и в императивных, и в объектно-ориентированных языках программирования. В теоретической вычислительной технике существует предположение, что решение любой задачи, имеющей алгоритмическое решение, можно записать с помощью ограниченного количества структур. Мы обсудим это утверждение в главе 11. А пока следует заметить, что изучение языка программирования — это не бесконечное изучение различных операторов управления. На самом деле большинство структур управления, используемых в современных языках программирования, являются разновидностью структур, описанных в этой главе.

Выбор того, какие структуры включить в язык программирования, дело вкуса. Перед создателем языка стоит цель разработать язык, который не только позволяет записывать алгоритмы в удобном для чтения виде, но также помогает программисту в этом. Эта цель достигается с помощью ограничения использования тех элементов, которые исторически привели к неаккуратному программированию, и введения хорошо продуманных элементов. В результате мы имеем структурное программирование (structured programming), которое объединяет в себе методы написания программ и правильное использование операторов управления. Цель состоит в том, чтобы создать программу, легкую для понимания и выполняющую поставленные перед ней задачи.

Комментарии


Опыт показывает, что когда человек пытается понять программу большого размера, не столь важно, насколько хорошо продуман язык программирования и как используются его свойства, сколь полезна или даже обязательна дополнительная информация, представленная на нормальном человеческом языке. Поэтому в языках программирования предусмотрена возможность размещения в программе поясняющих комментариев (comments). Транслятор игнорирует комментарии, поэтому их присутствие или отсутствие никак не отражается на программе с точки зрения машины. Версия программы на машинном языке, порождаемая транслятором, остается неизменной, с комментариями или без них. Но информация, которую они содержат, является важной для человека. Без нее невозможно было бы понять большие и сложные программы.

VISUAL BASIC

Visual Basic является объектно-ориентированным языком программирования. Он был разработан компанией Microsoft как инструмент, с помощью которого пользователи операционной системы Microsoft Windows могли бы разрабатывать свой собственный графический пользовательский интерфейс. На самом деле Visual Basic — это больше, чем просто язык программирования. Он представляет собой полный пакет для разработки программного обеспечения, который позволяет программисту создавать пользовательский интерфейс из определенных компонентов (таких как кнопки, флажки, текстовые поля, полосы прокрутки и т. д.) и переделывать эти компоненты согласно своим потребностям, описывая, как они должны реагировать на определенные события. Например, в случае с кнопкой программист может описать, что должно происходить, если щелкнуть на ней мышью. Этот метод создания программного обеспечения из заранее определенных компонентов является современной тенденцией в разработке программного обеспечения.

Благодаря популярности операционной системы Windows и удобству использования пакета Visual Basic, язык Visual Basic стал сегодня одним из самых распространенных языков программирования. С другой стороны, из-за того что Visual Basic совместим только с программными средствами компании Microsoft, он не признается языком программирования общего назначения.

Существует два основных способа отделения комментариев от текста программы. Один из них — заключить комментарий в специальные скобки. Другой способ — обозначить начало комментария, который может занимать оставшуюся часть строки справа от знака. В языках C++, С# и Java возможны оба способа записи комментариев. В них комментарий можно поместить между знаками /* и */ или начать его с //. Таким образом, в C++, С# и Java допустимы обе записи:

/* Это комментарий. */

или

// Это комментарий.

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

ApproachAngle - SlipAngle - HyperSpacelncine:

добавляют комментарий «Вычесть HyperSpacelncine из SlipAngle и присвоить значение переменной ApproachAngle». Такие комментарии не делают программу более понятной, а только удлиняют ее. Запомните, что цель комментария — пояснить программу, а не повторить ее. В данном примере лучше объяснить, почему вычисляется значение переменной ApproachAngl e (если это не ясно из программы). Например, комментарий: «Переменная ApproachAngle используется позже для вычисления значения переменной ForceFiel dJetti sonVel ocity», намного полезнее, чем предыдущий.

Кроме того, комментарии, помещенные между операторами программы, иногда затрудняют чтение и понимание программы. Лучше всего помещать комментарии, касающиеся одного блока программы, в одном месте, например в его начале. Так создается некоторый участок программы, который содержит описание цели и общие характеристики блока программы где пользователь может найти необходимые объяснения. Если использовать такой прием для всех блоков программы, тогда программа приобретает единообразие: каждый блок состоит из пояснительных комментариев, за которыми следует формальное представление этого блока. Подобное единообразие значительно облегчает чтение программы.
2014-07-19 18:44
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • Контрольная работа
  • © sanaalar.ru
    Образовательные документы для студентов.