Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по информатики.doc
Скачиваний:
44
Добавлен:
13.11.2018
Размер:
1.53 Mб
Скачать

12.2. Программирование задачи

Технология программирования задач различается для операторных и функциональных языков программирования. Ограничимся рассмотрением вопроса для операторных языков. Тогда этот этап разбивается на два последовательных шага – разработку алгоритма и отладку программы.

12.2.1. Разработка алгоритма

Алгоритм – это точное предписание, определяющее вычислительный процесс, ведущий от исходных данных к искомому результату.

Алгоритм обладает следующими свойствами (они следуют из определения):

  1. определенность (детерминированность) – каждая команда (или предписание) понятна исполнителю (человеку или компьютеру) и исключает неоднозначность исполнения;

  2. результативность – реализация вычислительного процесса, предусмотренного алгоритмом, должна через определенное число шагов привести к результату или сообщению о невозможности его получения;

  3. массовость – если алгоритм разработан для решения определенной задачи, он должен быть применим для решения задач этого типа при всех допустимых значениях исходных данных;

  4. дискретность – пошаговый характер процесса получения результата, состоящий в последовательном выполнении конечного числа заданных алгоритмом действий.

Различают следующие простейшие виды алгоритмов:

  1. линейный, когда предписания алгоритма выполняются в той последовательности, в которой они представлены в алгоритме;

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

  3. циклический, когда предписания алгоритма выполняются многократно. В зависимости от характера повторений различают циклические алгоритмы с заданным и незаданным числом повторений (в этом случае такие алгоритмы называют итерационными).

12.2.1.1. Способы описания алгоритма

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

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

Структурно-стилизованный способ - это формализованное представление предписаний, задаваемых путем использования ограниченного набора типовых синтаксических конструкций. Данный способ представления алгоритма требует подготовки и специальных несложных знаний. Примером его может служить нотация Бэкуса – Наура, которая часто используется для описания структуры формализованных языков, например, языков программирования, в частности, Турбо-Паскаля. В этой нотации типовыми синтаксическими конструкциями являются продукции вида:

А::=В,

где А – определяемое продукцией понятие,

В – понятие или группа понятий, которые служат для раскрытия структуры понятия А;

знак «::=» имеет смысл «есть по определению».

Пример 12.3. Определим структуру понятия «оператор ввода» для Турбо-Паскаля. В соответствии с правилами этого языка, оператор ввода содержит название оператора (read) и операнд, показывающий, значения каких переменных вводятся; заканчивается оператор точкой с запятой. Таким образом, в состав оператора ввода входят две строковые постоянные величины – “read” и “;” и одна строковая переменная величина – операнд, который может включать произвольный по числу и составу набор имен переменных.

Для различения строковых постоянных и переменных условимся переменные заключать в угловые скобки, например, <операнд>, а постоянные – в кавычки, например, “read”. Тогда, очевидно, и само понятие «оператор ввода» является переменной величиной.

Запишем определения переменных с помощью упомянутой нотации:

<оператор ввода> ::= “read” <операнд> “;” . (12.1)

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

<операнд> ::= “(“ <список имен переменных> “)” , (12.2)

<список имен переменных> ::= <имя> [“,” <список имен переменных>] . (12.3)

Здесь квадратные скобки означают возможное отсутствие их содержимого в структуре определяемого понятия. Действительно, в конкретном операторе ввода может вводиться только одна переменная, тогда список вырождается в одно имя. Отметим также, что понятие списка имен переменных определено рекурсивно через себя же. Это часто используется при определении формальных структур.

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

Язык графических символов предполагает соотнесение каждому типу действий геометрической фигуры, представленной в виде блочного символа. Действия (блоки) соединяются линиями потока. Совокупность таких связанных блоков называется блок-схемой. Составление блок-схем регламентируется ГОСТ 19.003-80 и ГОСТ 19.002-80. Основными блоками, используемыми в блок-схемах, являются следующие:

Блок Название Характеристика

процесс Для обозначения одного или нескольких действий,

(обработка) изменяющих значение, форму представления или

размещения данных.

решение Выбор направления выполнения алгоритма

в зависимости от некоторых переменных условий.

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

модификация Для организации циклических конструкций. Внутри записывается параметр цикла и закон его изменения. В блок-схеме этот блок помещается всегда в начале цикла. Имеет фиксированные входы и выходы.

предопределенный Предполагает использование ранее созданных и

процесс отдельно описанных алгоритмов или программ.

ввод-вывод Преобразование данных в форму, пригодную для обработки (ввод) или отображения результатов обработки (вывод).

пуск-останов Определяет начало и конец алгоритма. Содержит, соответственно, буквы Н или К.

внутристраничный Указывает на связь между прерванными линиями

соединитель потока, соединяющими блоки на одной странице.

Внутри пишется номер блока, которому или из которого передается управление.

межстраничный Указывает на связь между прерванными линиями

соединитель потока, соединяющими блоки на разных страницах.

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

комментарий Сопровождает блок, если в нем не поместились

нужные данные.

магнитный диск Показывает место хранения данных.

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

Блоки: процесс, решение, модификация, предопределенный процесс, ввод-вывод, останов имеют единый вход (т.е. входящую линию потока), который располагается вверху блока.

Например, для блока «процесс»:

Блоки: процесс, предопределенный процесс, ввод-вывод, пуск имеют единый выход (т.е. выходящую линию потока), который располагается внизу блока. Например, для блока «процесс»:

Блок «решение» имеет как минимум два выхода, которые подписываются словами ДА и НЕТ, например,

ДА

НЕТ

Блок «модификация» имеет выходы и входы (кроме входа в блок) со следующими значениями:

  1. связь 1 – возврат к началу цикла. Имеет место, когда параметр цикла не превысил своего максимального значения;

  2. связь 2 – вход в тело цикла;

  3. связь 3 – выход из цикла, когда параметр цикла превысил свое максимальное значение.

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

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

Выход из этого блока допускается только снизу, например:

Сами линии потока должны отвечать следующим требованиям:

  1. должны быть параллельны внешним краям рамки листа;

  2. допускается пересечение линий потока или изгиб под углом 90, например:

  1. для обозначения слияния место слияния обозначается точкой, например:

  1. направление линий потока сверху вниз и слева направо считается основным. В противном случае, направление указывается стрелкой;

  2. расстояние между параллельными линиями потока не менее 3 мм, между остальными символами схемы не менее 5 мм.

Операторный язык – это такой способ кодирования алгоритма, в результате которого получается понятная для компьютера запись алгоритма - программа. Этот способ требует, как минимум, знания правил записи выражений средствами того или иного языка программирования.

Эволюция языков программирования показательна с точки зрения того, как менялась технология кодирования алгоритмов, упрощая труд программистов:

  1. первые языки программирования – это машинные коды – аналог машинных команд. Структура команды включает код операции (как правило, числовой) и список операндов. Программирование требовало от программиста распределение переменных и команд по доступным адресам памяти, для чего необходимо было знать требуемые объемы команд и переменных. Для вычислений также использовался специальный регистр процессора - сумматор. В качестве операндов выступали не переменные, а их адреса. Например, пусть память компьютера, которой располагает программист, содержит адреса от 1 до 100, по каждому из которых доступен байт памяти. Нужно запрограммировать вычисление переменной z по формуле: z = a + b, причем a = 8, b = 10. Пусть имеется набор двухадресных машинных команд, включающий, в частности, команды:

код объем действие

операции

124 3 б сложить операнды, результат – в сумматоре,

125 2 б поместить содержимое сумматора по адресу,

126 3 б поместить константу по адресу.

Программист распределяет переменные (с учетом размера их значений) по адресам:

переменная требуемый объем памяти адрес

a 1 б 1

b 1 б 2

z 1 б 3

Тогда вся программа будет выглядеть следующим образом:

адрес содержимое комментарий

памяти памяти

1 - для переменной a.

2 - для переменной b.

3 - для переменной z.

4 126 8,1 константа 8 помещается по адресу 1, т.е. вычисляется a = 8. После этого действия содержимое памяти по адресу 1 становится равным 8.

7 126 10,2 константа 10 помещается по адресу 2, т.е. вычисляется b = 10. после этого действия содержимое памяти по адресу 2 становится равным 10.

10 124 1,2 содержимое адресов 1 и 2 складывается, т.е. вычисляется a+b. Результат – в сумматоре.

13 125 311 содержимое сумматора размещается по адресу 3, т.е. выполняется присваивание z=a+b. После этого действия содержимое памяти по адресу 3 становится равным 18.

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

  1. автокоды явились развитием машинных кодов, когда числовые коды операций заменились мнемоническими обозначениями, по которым можно восстановить смысл операции, а в адресной части можно было использовать имена переменных, а не их адреса. Например, числовые коды операций 124 и 125 из предыдущего примера заменились мнемоническими кодами, соответственно, ADD (сложить, англ.) и MOVE (поместить, англ.). Тогда предыдущая задача для двухадресного кода запишется так:

команда комментарии

MOVE 8,a константа 8 помещается в переменную а.

MOVE 10,b константа 10 помещается в переменную b.

ADD b,a содержимое переменных a и b складывается.

MOVE z результат помещается в переменную z.

Автокоды современных ЭВМ образуют группу языков, которые называются ассемблерами. И автокоды, и машинные коды являются машинно-зависимыми языками программирования: состав и структура команд полностью соответствует составу и структуре команд ЭВМ.

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

var integer a,b,z;

a:=8; b:=10;

z:=a+b; .

Запись средствами Бэйсика еще проще, так как он не требует предварительного описания переменных и констант:

a=8

b=10

z=a+b .

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

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

  1. при написании программы надо учитывать общие особенности процесса вычислений на ЭВМ, например, бессмысленно сравнивать два вещественных выражения А и В в силу погрешности вычислений (это обсуждалось ранее при описании процесса перевода чисел из одной системы счисления в другую, а также при выполнении сложения с плавающей точкой). В этом случае сравнение «А = В» заменяется проверкой |А - В| << , где 0;

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

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

  4. рекомендуется снабжать текст программы комментариями в количестве 1 комментарий на 2 – 3 строки текста (в среднем);

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

  6. минимальное использование оператора безусловной передачи управления, поскольку он затрудняет отладку и понимание программы;

  7. мнемоничность имен переменных, констант, подпрограмм, меток, поскольку это облегчает ориентацию в программе. Здесь рекомендуется применять так называемую венскую запись, когда то или иное имя определяет семантику описываемого объекта (современные языки программирования позволяют использовать очень длинные имена для переменных, констант и прочих объектов);

  8. свойство гибкости программы определяет простоту ее изменения, расширения, модификации в процессе эксплуатации. Это достигается простотой стиля программирования и применением прогрессивных методов проектирования алгоритмов.