Главная страница
Навигация по странице:

  • 4.4 Разработка программы 79

  • 4.4 Разработка программы 81

  • 4.5 Стиль программирования 83

  • 4.5 Стиль программирования 85

  • 4.6 Тестирование и отладка 87

  • программирование тусур. Программирование учебное пособие. Учебное пособие Томск Эль Контент


    Скачать 0.93 Mb.
    НазваниеУчебное пособие Томск Эль Контент
    Анкорпрограммирование тусур
    Дата17.08.2022
    Размер0.93 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование учебное пособие.pdf
    ТипУчебное пособие
    #647947
    страница8 из 16
    1   ...   4   5   6   7   8   9   10   11   ...   16
    Глава 4. Технология программирования
    begin
    {проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i)
    then writeln(i,
    ' — не удовлетворяет гипотезе
    Гольдбаха
    ');
    i:=i+2
    end;
    end.
    • Вариант 3. Чтобы проверить взаимодействие «заглушки» с основной про- граммой, присваиваем функции gold постоянно ложное значение.
    var i,m: integer;
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    begin
    {заглушка}
    gold:=false
    end;
    begin writeln(
    'Введите натуральное m'); readln(m);
    i:=2;
    while i{проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i)
    then writeln(i,
    ' — не удовлетворяет гипотезе
    Гольдбаха ');
    i:=i+2
    end;
    end.
    • Вариант 4. Только число 4 представляется в виде суммы двух четных про- стых чисел (4 = 2 + 2). Все большие четные числа, если удовлетворяют ги- потезе Гольдбаха, то представляются только в виде суммы двух нечетных простых чисел. Поэтому уточняем функцию gold: ищем простые числа только среди нечетных чисел и первое проверяемое четное число полагаем равным 6.
    var i,m: integer;

    4.4 Разработка программы
    79
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    var j: integer;
    begin gold:=false;
    for j:=3 to n
    3 do
    if j и n
    j — простые числа then gold:=true
    end;
    begin writeln(
    'Введите натуральное m>=6'); readln(m);
    i:=
    6;
    while i{проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i)
    then writeln(i,
    ' — не удовлетворяет гипотезе
    Гольдбаха ');
    i:=i+2
    end;
    end.
    В таком виде программу даже нельзя откомпилировать: в функции gold в условном операторе отсутствует логическое выражение.
    • Вариант 5. Определяем функцию prime в виде «заглушки».
    var i,m: integer;
    function prime(n:integer):boolean;
    {n — простое число <=> значение функции — истина}
    begin prime:=true end;
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    var j: integer;
    begin gold:=false;
    for j:=3 to n-3 do if prime(j) and prime(n
    −j) then begin writeln(n,
    '=', j, '+', n
    −j);
    gold:=true end end;
    begin

    80
    Глава 4. Технология программирования
    writeln(
    'Введите натуральное m>=6'); readln(m);
    i:=6;
    while i{проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i)
    then writeln(i,
    ' — не удовлетворяет гипотезе
    Гольдбаха ');
    i:=i+2
    end;
    end.
    • Вариант 6. «Заглушку» в функции prime заменяем полноценным кодом.
    var i,m: integer;
    function prime(n:integer):boolean;
    {n — простое число <=> значение функции — истина}
    var k: integer;
    begin prime:=true;
    for k:=2 to n
    1 do
    if n mod k=0 then prime:=false
    end;
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    var j: integer;
    begin gold:=false;
    for j:=3 to n
    −3 do if prime(j) and prime(n
    −j) then begin writeln(n,
    '=', j, '+', n
    −j);
    gold:=true end end;
    begin writeln(
    'Введите натуральное m>=6'); readln(m);
    i:=6;
    while i{проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i)

    4.4 Разработка программы
    81
    then writeln(i,
    ' — не удовлетворяет гипотезе
    Гольдбаха ');
    i:=i+2
    end;
    end.
    Уже создана работоспособная программа, решающая проблему Гольдбаха.
    Но это программа не эффективна. Следующие версии программы посте- пенно увеличивают ее эффективность.
    • Вариант 7. Оптимизируем функцию prime. Достаточно проверять наличие делителей только среди чисел, не превышающих половины n.
    function prime(n:integer):boolean;
    {n — простое число <=> значение функции — истина}
    var k: integer;
    begin prime:=true;
    for k:=2 to n div 2 do if n mod k=0 then prime:=false end;
    • Вариант 8. Оптимизируем функцию prime в большей степени. Оказыва- ется, что достаточно проверять наличие делителей только среди чисел, не превышающих корня квадратного из n (действительно, если n = ab, то одно из чисел a или b не больше n
    1
    /2
    ).
    function prime(n:integer):boolean;
    {n — простое число <=> значение функции — истина}
    var k: integer;
    begin prime:=true;
    for k:=2 to trunc(sqrt(n)) do if n mod k=0 then prime:=false end;
    • Вариант 9. Еще раз оптимизируем функцию prime: прекращаем переби- рать потенциальные делители n, как только найдем делитель.
    function prime(n:integer):boolean;
    {n — простое число <=> значение функции — истина}
    var k: integer; p: boolean;
    begin
    p:=true; k:=2;
    while p and (k<= trunc(sqrt(n))) do
    if n mod k=0 then p:=false else k:=k+1;
    prime:=p
    end;

    82
    Глава 4. Технология программирования
    • Вариант 10. Оптимизируем функцию gold — прекращаем выполнять цикл,
    как только обнаружим, что число удовлетворяет гипотезе Гольдбаха.
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    var j: integer; g:boolean;
    begin
    g:=false; j:=3;
    while (j<=n div 2) and not g do if prime(j) and prime(n
    −j) then begin writeln(n,
    '=', j, '+', n-j); g:=true end
    else j:=j+2;
    gold:=g
    end;
    • Вариант 11. Пишем окончательную версию функции prime: учитываем,
    что n — нечетное число. Заметим, что в этой версии функция prime будет правильно работать только для нечетных чисел, а в предыдущих версиях такого ограничения не было.
    function prime(n:integer):boolean;
    {n — простое нечетное число <=> значение функции — истина}
    var k: integer; p: boolean;
    begin p:=true; k:=
    3;
    while p and (k<= trunc(sqrt(n))) do if n mod k=0 then p:=false else k:=k+
    2;
    prime:=p end;
    • Вариант 12. Окончательная версия программы: оптимизируем главную про- грамму; убираем печать из функции gold и вставляем печать в главную программу.
    function prime(n:integer):boolean;
    {n — простое нечетное число <=> значение функции — истина}
    var k: integer; p: boolean;
    begin p:=true; k:=3;
    while p and (k<= trunc(sqrt(n))) do if n mod k=0 then p:=false else k:=k+2;
    prime:=p

    4.5 Стиль программирования
    83
    end;
    function gold(n:integer):boolean;
    {n удовлетворяет гипотезе Гольдбаха <=> значение функции — истина}
    var j: integer; g:boolean;
    begin g:=false; j:=3;
    while (j<=n div 2) and not g do if prime(j) and prime(n
    −j) then g:=true else j:=j+2;
    gold:=g end;
    var m,i,h :integer;
    begin writeln(
    'Введите натуральное m>=6'); readln(m);
    h:=0; i:=6;
    while (i{проверяем гипотезу Гольдбаха для четного числа i}
    if not gold(i) then h:=i else i:=i+2;
    end;
    if h=0 then writeln(
    'Гипотеза Гольбаха верна для всех
    чисел <
    ',m)
    else writeln(
    'Гипотеза Гольдбаха не выполнена
    для
    ',h)
    end.
    4.5 Стиль программирования
    В процессе разработки каждая программа не один раз подвергается исправле- ниям, и при этом человеку каждый раз приходится читать ее, разбираться в струк- туре, искать места, в которых могут возникнуть затруднения. Поэтому чем легче они написаны, тем проще в них разобраться.
    Начинающие программисты часто считают, что им нет необходимости специ- ально заботиться о внятности программы: ведь они сами ее придумали и все в ней знают, зачем тратить время на какое-то оформление? Увы, это заблуждение, хотя и очень распространенное.
    Как бы хорошо программист ни понимал свою программу, есть предел, после которого невозможно удержать все детали. Если работа ведется с продолжительны- ми перерывами, вспомнить подробности бывает не так-то просто. Довольно частая жизненная ситуация — программу начинает один человек, а доделывает другой.

    84
    Глава 4. Технология программирования
    Опытные программисты всегда уделяют внимание тому, как выглядит их про- грамма. Получится красивой — ее будет легко читать, понимать и исправлять, а зна- чит, у нее больше шансов оказаться правильной и полезной.
    Правила оформления программы обычно называют стилем программирования.
    Одни и те же действия почти всегда можно выполнить по-разному. У каждого программиста есть свои привычки и пристрастия, которые и образуют его стиль.
    Со временем у него обязательно вырабатывается свой неповторимый почерк, свой способ использования инструментов, по которому его нетрудно опознать, как по подписи на бумаге.
    Стиль программирования может быть хорошим и плохим. Хороший стиль про- граммирования способствует повышению надежности программ (надежная про- грамма — программа, не содержащая ошибок).
    Вот несколько рекомендаций, которые позволяют понять, что такое хороший стиль.
    • Кто ясно мыслит, тот ясно излагает!
    Прежде чем писать программу, надо четко уяснить, какая поставлена задача и как ее решить. Если в мыслях нет ясности — не помогут никакие приемы и ухищ- рения.
    • Не забывайте о комментариях!
    Все языки программирования позволяют включать в программу комментарии —
    пояснительный текст, который нужен только для человека. Компьютер не читает комментарии, он просто не замечает их. Комментарии — важнейший элемент стиля,
    это очень мощный инструмент, позволяющий сделать программу действительно понятной.
    У программы должно быть предисловие — большой вступительный коммента- рий, который может занимать несколько страниц текста. Он включает следующие разделы:
    • имя автора программы (творчество не должно быть анонимным!);
    • название программы и ее назначение;
    • по возможности подробное описание решаемой задачи;
    • описание исходных данных и требуемых результатов задачи;
    • описание основной идеи решения;
    • ссылки на литературу и другие источники, связанные с задачей и ее решением;
    • дата написания первоначальной версии программы и история последующих изменений.
    Каждое описание переменных, констант должно сопровождаться комментари- ем, поясняющим их содержательную суть.
    Для каждой подпрограммы требуется давать небольшой вступительный ком- ментарий — для чего предназначена данная конкретная подпрограмма.
    Программы порой основаны на довольно сложных алгоритмах, понять которые по тексту не так-то легко. В этом случае хорошие комментарии, поясняющие смысл алгоритма в целом, могут оказаться очень полезными.

    4.5 Стиль программирования
    85
    • Не доверять комментариям (этот совет предназначен не для тех, кто пишет,
    а для тех, кто будет читать программу).
    Примеры плохих комментариев: «счетчик», «дополнительная переменная»,
    «вещественное число», «строка». Примеры хороших комментариев: «количество найденных совпадений», «самое большое число в списке».
    Вот типичный фрагмент программы:
    k:=k+1; {увеличим k на 1}
    Комментарий абсолютно ничего не прибавляет к тексту программы: читатель и так видит, что k увеличивается на 1 (а если не видит, то здесь ему не поможет даже самый подробный комментарий). Желательно описать, почему происходит это увеличение. Например, «нашли очередное совпадение» или «переходим к сле- дующему элементу».
    Необходимо помнить, что компьютер всегда делает то, что написано в програм- ме, а не в комментариях. Хороший комментарий рассказывает о замысле програм- миста, а анализ самой программы — о реализации задуманного.
    Но с другой стороны, подробный комментарий в иных случаях помогает заме- тить, что выполняются не те действия, о которых было заявлено.
    • Понимание переменных — ключ к пониманию программы.
    Любая программа обрабатывает какую-то информацию, представленную в виде переменных. Поэтому необходимо в первую очередь понять смысл переменных,
    которые в ней используются.
    Надо тщательно выбирать имена переменных. Следует избегать однобуквенных имен и конструкций типа «буква и цифра» — в них легко запутаться. Надо давать близкие имена родственным данным, но нельзя давать похожими именами данные,
    которые ничего общего не имеют. Как назовешь корабль, так он и поплывет!
    Используйте осмысленные имена. Плохо: x, xx, xxx, x1, yx и т. д.
    Избегайте похожих имен (X1, XI и Xl — три разных окончания: цифра один,
    буквы «ай» и «эль»; X0 и XO).
    Если в идентификаторах используете цифры, помещайте их в конце.
    Никогда не используйте в качестве определяемых идентификаторов стандарт- ные идентификаторы.
    Не создавайте лишние промежуточные переменные.
    • Разделяй и властвуй!
    Разбивайте программу на подпрограммы. Объем подпрограммы должен быть таким, чтобы её было несложно охватить как единое целое, понять сразу всю логику её работы. Обычно подпрограмма без описаний и комментариев должна целиком помещаться на экране. Если экрана не хватает, есть смысл подумать о дальнейшем разбиении.
    • Текст должен быть удобен для чтения.
    Для компьютера чаще всего неважно, как ваша программа разбита на строки и где в ней поставлены пробелы. Компилятор должен отделить лексемы друг от друга, а остальное ему безразлично.
    Человек же, наоборот, обращает особое внимание на то, как оформлен текст,
    ведь от этого зависит его восприятие.
    • Надо «выделять» алгоритмическую структуру.

    86
    Глава 4. Технология программирования
    Опытные программисты всегда пишут программу «лесенкой». Каждый раз, ко- гда в ней используется алгоритмическая структура (цикл, ветвление), текст сдви- гается вправо. Такая запись позволяет сразу увидеть, где начинается и где закан- чивается конструкция, какие операторы входят в неё, а какие — нет.
    • Смещение означает подчинение.
    Данное правило — пояснительное расширение предыдущего.
    Вообще, всегда, когда надо показать, что один фрагмент подчинен другому,
    подчиненный фрагмент записывается со смещением вправо. Тем самым поясняют,
    что это не самостоятельное действие, а часть предыдущего.
    • Не надо экономить на пробелах.
    Они облегчают чтение и понимание программы. Если в одной строке запи- сывается несколько операторов, необходимо поставить пробелы между ними. Во многих случаях желательно использовать пробелы при знаках действий.
    • Надо избегать волшебных чисел.
    Числа в программе не стоит использовать в явном виде. Когда в тексте про- граммы встречается такое число (что-нибудь вроде 179), читателю часто бывает совершенно непонятно, что оно означает и откуда взялось.
    Тяжело приходится программистам, когда возникает необходимость изменить такое число. Надо сделать кропотливую и не очень приятную работу — не пропу- стить все вхождения данного числа и не делать замену там, где данное число имеет другой логический смысл (например, число 100 может означать в одном месте ко- личество элементов массива, а в другом месте — температуру кипения воды).
    • Используйте описание констант.
    Конечно, такие числа, как 0 или 1, не стоит делать константами — это только усложнит программу.
    • Шаг за шагом.
    Известно, что проще всего разобраться в линейной программе, в которой все действия выполняются последовательно, одно за другим, как записаны.
    Это не означает, что надо избегать циклов и ветвлений — без них невозможно построить не один сложный алгоритм. Но лучше, чтобы конструкции были корот- кими, тогда каждая из них может рассматриваться как отдельное действие в общей линейной последовательности.
    • Без goto.
    Оператор goto делает программу чуть-чуть короче, нарушая последователь- ность выполнения. Однако в участках, куда совершается переход, может таиться опасность. Именно там чаще всего происходят ошибки. Причина очевидна: в одно и то же место программы можно попасть из разных мест с различной предыстори- ей. Уследить за соблюдением всех необходимых условий становится очень трудно,
    отсюда и сложности.
    • Не надо прерывать циклы.
    Еще один способ нарушения последовательного выполнения — досрочное вы- полнение цикла. В языке Паскаль для этого есть специальная процедура break.
    Цикл — самая сложная для понимания алгоритмическая структура. Обычно предполагается, что заголовок цикла полностью описывает условие его продол-

    4.6 Тестирование и отладка
    87
    жения и завершения. Досрочное прекращение нарушает это правило, поэтому им лучше не пользоваться.
    • Блок должен заканчиваться естественно.
    Не надо вставлять в середину блока (программы или подпрограммы) операто- ры, ведущие к выходу из блока (exit) или прекращению работы (halt). Заверше- ние должно быть естественным — подпрограмма обязана вернуть управление в точ- ку вызова. Единственное исключение из этого правила — обнаружение фатальной ошибки, которая делает дальнейшую работу программы бессмысленной.
    • Использование логических величин.
    Начинающие программисты часто не понимают сути логических величин и со- здают громоздкие выражения там, где можно написать коротко и ясно.
    Например, вместо if a = true then . . . следует писать if a then . . . .
    Логическая величина — это условие, не нуждающееся ни в каком дополнительном сравнении.
    Еще пример: выражение if a = true then a := false else a := true преобразуем в a := not a.
    • Изучите и активно используйте возможности языка.
    В результате программы становятся короче и исключаются определенные ошибки.
    Избегайте трюков, например использование параметров цикла после окончания цикла for (неизвестно, какое значение имеет параметр цикла после его окончания).
    • Не гонитесь за микроэффективностью.
    Настоящая эффективность программы достигается за счет изменения алгоритма.
    Игнорируете все предложения по повышению эффективности, пока программа не будет правильной.
    Не жертвуйте легкостью чтения ради эффективности.
    Добивайтесь эффективности на основе измерений, а не догадок.
    4.6 Тестирование и отладка
    4.6.1 Тестирование
    Тестирование — процесс выполнения программы с намерением найти ошибки.
    Если ваша цель показать отсутствие ошибок, вы их найдете не слишком много.
    Если же ваша цель — показать наличие ошибок, вы найдете значительную их часть.
    Два крайних подхода к стратегии тестирования:
    программа = «черный ящик», идеальная стратегия — проверить всевозмож- ные комбинации значений на входе и выходе;
    главное — логика программы, идеальная стратегия — проверить каждый путь, каждую ветвь алгоритма.
    Искусство тестирования заключается в искусстве отбора тестов с максимальной отдачей.

    88
    1   ...   4   5   6   7   8   9   10   11   ...   16


    написать администратору сайта