!
Сообщение от: Anton
Это заключительный материал автора, тема будет дополнена, если выйдет продолжение
Глава 10. Диаграммы потоков и диаграммы Насси-Шнейдермана (Chapin)
В этом уроке автор отходит от непосредственного программирования и рассказывает о графическом инструменте — диаграммах потоков (блок-схемах), которые помогают проектировать программы. Особое внимание уделяется диаграммам Насси-Шнейдермана, которые способствуют структурному программированию.
Привет, друзья! Мы продолжаем наш учебник по программированию, но сегодня не будем разбирать код или конкретную инструкцию. Сменим ритм и поговорим об одном полезном инструменте — диаграммах потоков. Иногда их ошибочно называют organigramas, я и сам грешил этим словом, но правильно — diagramas de flujo. Далее для краткости буду говорить просто «диаграммы».
Зачем нужна диаграмма потока? Это графический способ показать шаги, необходимые для решения задачи. Задача может выглядеть по-разному, и диаграмма должна учитывать все возможные варианты. Для сложной задачи диаграмма может быть довольно объёмной, хотя обычно она проще.
Существует много видов диаграмм. Сначала мельком взглянем на классический тип (он лежит у меня на столе вверх ногами). Это самый традиционный вид, но мне он не нравится, потому что позволяет писать плохой код — с пресловутым GOTO. Я не против GOTO из снобизма, а потому что он порождает запутанный «спагетти-код»: переходы туда-сюда, и потом невозможно понять, откуда пришли и куда вернёмся. Структурированная программа гораздо легче для понимания.
Классические блок-схемы позволяют программировать и хорошо, и плохо — как ты их построишь. А вот другие диаграммы, которые мы сейчас рассмотрим, заставляют программировать структурно, потому что в них нет поддержки инструкции GOTO.
Давайте посмотрим на классическую блок-схему (на столе). Все диаграммы имеют как минимум одно начало и один конец, хотя иногда может быть несколько конечных точек. Начало и конец обозначаются овалом со словами «Inicio» и «Fin». Ромбоид означает ввод/вывод данных: здесь, например, запрашивается DNI (испанский идентификационный номер) как строка (поэтому с символом $). Обычно в диаграммах не привязываются к конкретному языку, но я позволил себе такую вольность. Ромбы — это вопросы, точки принятия решений с ответами «да» и «нет». Здесь мы спрашиваем, пуст ли DNI: если пользователь ничего не ввёл и нажал Enter, это сигнал к выходу. Если не пуст, продолжаем. Прямоугольники — это процессы, операции в памяти: присваивание, преобразование и т.д. Мы преобразуем строковый DNI в числовой, потому что дальше нужны вычисления. Потом вычисляем остаток от деления DNI на 23 (модуль). В зависимости от остатка (от 0 до 22) назначаем букву. Затем объединяем DNI и букву в переменную NIF, выводим результат. И вот здесь появляется тот самый GOTO: он ведёт обратно для повторения цикла, пока не введут пустой DNI. Я уже объяснил, почему GOTO нежелателен.
Теперь перейдём к другим диаграммам — диаграммам Насси-Шнейдермана (сокращённо NS), также известным как диаграммы Чапина (Chapin). Я встречал написание «ЧапИн» с ударением на «и», но не уверен. Главное — не произносить «Шопен», а то мы начнём делать диаграммы для фортепианных партий. Шучу. Эти диаграммы основаны на теории структурного программирования. Суть теории: любую программу, какой бы длинной и сложной она ни была, можно построить из трёх простых структур:
- Последовательные процессы — блок, внутри которого может быть одна или много инструкций.
- Циклы — для повторения: REPEAT, WHILE, FOR.
- Условные конструкции — принятие решений: простая IF (с ветвями «да» и «нет») и множественный выбор (SWITCH, CASE, SELECT и т.п.).
В диаграммах Чапина нет соединительных линий и переходов — только вложенные прямоугольники. Поэтому они не позволяют писать неструктурно: они вынуждают программировать правильно.
Рассмотрим элементы диаграмм Чапина:
- Процесс: прямоугольник с текстом.
- Условие: прямоугольник, разделённый на две части (для IF), или на несколько секций для SWITCH. В SWITCH можно также добавить ветку default.
- Циклы: REPEAT обозначается как прямоугольник с буквой «L»-образной скобкой слева; WHILE — аналогично, но скобка может быть слева или справа; FOR — тоже.
Теперь пример реальной диаграммы Чапина — программа ведения файла. Начинаем с инициализации (всегда должна быть). Затем открываем файл. Дальше идёт большой цикл REPEAT...UNTIL, который повторяется, пока не будет нажата клавиша Escape. Внутри цикла: рисуем панель управления, принимаем нажатие клавиши, затем проверяем, Escape ли это. Если да — закрываем файл и выходим. Если нет — идём в множественный выбор (SWITCH), где обрабатываются различные клавиши: F7 (добавить), Enter (редактировать), F9 (удалить), клавиши курсора (перемещение по записям), F10 (отчёты) и т.д. После каждой операции клавишу сбрасываем в пустую строку (чтобы цикл не завершился), и возвращаемся к началу цикла.
Важный момент: если из подпрограммы (например, редактирования) выйти по Escape, то мы должны вернуться в главное меню, а не завершить программу. Поэтому внутри подпрограмм клавиша очищается, и только на уровне панели управления Escape приводит к выходу.
Теперь на чистом листе я покажу, как комбинировать элементы. Внутрь цикла REPEAT можно вкладывать процессы, условия, другие циклы. Главное — сохранять структуру вложенности. Если процесс слишком большой, его можно вынести на отдельный лист и разработать отдельно.
Давайте построим диаграмму для задачи вычисления контрольной буквы испанского DNI. Сначала процесс инициализации. Затем цикл REPEAT...UNTIL, который продолжается, пока не введён пустой DNI или не нажата Escape. Внутри цикла: выводим приглашение, запрашиваем DNI (строкой). Если строка пустая — выходим из цикла (Break). Иначе преобразуем DNI в число, вычисляем остаток от деления на 23. Далее — множественный выбор (SWITCH) по остатку: для каждого значения от 0 до 22 присваиваем соответствующую букву (официальная таблица). После SWITCH объединяем DNI и букву в NIF, выводим результат, делаем паузу. Если во время паузы нажата Escape — выходим из цикла, иначе повторяем.
Теперь напишем программу на YaBasic, следуя этой диаграмме. Слева на экране — диаграмма, справа — код. Я не буду писать код прямо сейчас (это заняло бы много времени), но объясню соответствие.
В начале программы идут описания подпрограмм (процедур). Наша первая подпрограмма — Inicializa, она пустая, но оставлена для будущих дополнений. Затем начинается основной код с REPEAT. Внутри вызывается DibujaMensajeEnPantalla — эта подпрограмма очищает экран и выводит сообщение. Затем PideDni — запрашивает DNI через INPUT. Далее проверка: если DNI пустой (=""), выполняется BREAK — выход из цикла. Если нет — преобразуем DNI в число: dni = Val(dni$). Вычисляем остаток: resto = Mod(dni, 23). Затем идёт SWITCH resto с 23 ветками CASE, каждая присваивает переменной letra$ нужную букву. После END SWITCH формируем nif$ = dni$ + letra$, выводим его. Затем вызываем Pausa — она печатает подсказку и ждёт нажатия клавиши; нажатая клавиша сохраняется в tecla$. Если tecla$ = "escape", цикл завершается, иначе продолжается.
Код подпрограммы Pausa использует INKEY$ для ожидания клавиши. Подпрограмма Despedida выводит прощальное сообщение.
Я признаю, что реализация SWITCH на 23 ветки не самая элегантная — можно было бы обойтись одной строкой с функцией MID$, но мы её ещё не изучали. Поэтому пока так.
Диаграммы Чапина очень помогают при проектировании, особенно больших программ: всегда можно разбить сложный процесс на несколько более простых, вынося их на отдельные листы. Это дисциплинирует.
На этом всё. В следующем видео продолжим изучение функций работы со строками.
До встречи!