TW-CAD
    Что такое TestWard
    Технология
    Заказать тест
    Регистрация
    FAQ
    Статьи
  Проектирование
    Информация
    Вирт. лаборатория
  Учебный процесс
    1-й курс
      Лекции
      Ликбез
      Сессия
    5-й курс
      Литература
      Практикум
      Сессия
    Консультации
  Информация
    Как с нами связатся
    О нас

 

 

 

Структурное программирование

Построение программы из простых и составных операторов

С появлением ПК в начале 70 годов была осознана необходимость разработки массовых технологий программирования. Структурное программирование - это один из ответов на потребности практики. Согласно этому подходу программа пишут так, что ее можно прочитать неотрывно, как письмо. Исключается необходимость перескакивать с одного места в другое место программы при помощи операторов goto. Структурированная программа не только легче читается, но и легче воспринимается другими, легче отлаживается и сопровождается. Впервые технология была опробована в Паскале, а затем стандарты Ф-77, Ф-90 и Ф-95 ввели в язык Фортран адекватные средства программирования. В ряду других подходов можно назвать объектно-ориентированное (управляемое данными) программирование и визуальное программирование, основанное на использовании планшета для создания форм, ориентированных на пользователя и сопутствующих программных модулей, дополняемых программистом.

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

Блок-схемы  алгоритмов и программ

Алгоритм - это последовательность действий, приводящая к результату. Действия сопоставляются исполняемым операторам программы. Блок-схема программы помогает расставить исполняемые операторы в соответствии с алгоритмом.  Блок-схема строится из ограниченного набора блоков, указанных в таблице, а также линий, соединяющих их в порядке выполнения. Блок-схема - это способ рассуждения об алгоритме на человеческом языке. Запись алгоритма в виде программы - это формальное компьютерное описание алгоритма. Способов обсуждения может быть много, но графические образы существенно облегчают восприятие сложных структур человеком. Техника рисования упрощается при использовании компьютерных средств, в частности, пакета MS VISIO или SMART DRAW 5. Эти пакеты позволяют рисовать  схемы из готовых блоков, в-частности он позволяет рисовать блок-схемы. Блоки легко масштабируются, дополняются надписями, соединяются линиями. При перемещении блоков линии переезжают вслед за блоками.

БЛОКИ

ПОЯСНЕНИЯ

начало и конец ПЕ

на каждую ПЕ - своя блок-схема

соединительные линии для блоков

влево и вверх - со стрелкками

линии также соответствуют операторам

exit
cycle
goto m

эти простые операторы, они имеют
один вход и один выход 


структурный if как блок

 

if, имея внутри разветвления, все равно как блок имееет один вход и один выход

Переключатель структурный - это обобщение структурного if на случай любого количества блоков (в таблице не показан)
как блок имееет один вход и один выход

 

 

 

условный if - это частный случай   структурного if, в котором блок "нет" пуст

Логический if- это частный случай   условного if, в котором вместо блока - простой оператор

 

 


условный if как блок
GIFJPG/do12.gif (1599 bytes)
цикл как блок
имееет один вход и один выход

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


пара блоков как новый блок
следование блоков:

соединить блоки последовательно - конец одного с началом следующего

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

Сначала рисуют не подробную блок-схему,

          начало

         конец

а потом ее детализируют.

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

начало

конец

Важно отметить, 

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

По готовой блок-схеме легко писать программу.

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

Имеются программы рисования придумываемых блок-схем, например VISIO.

Имеются также программы печати блок-схем по готовым программам.

Программу строят из составных операторов (также СО называют конструкциями) и простых операторов, руководствуясь следующим

  • ПЕ пишут последовательно внутри одного текста или в разных текстах, объединяя их в один проект
  • в ПЕ вкладывают другие операторы, сначала неисполняемые, а затем исполняемые операторы
  • последовательно пишут любые операторы
  • простые исполняемые операторы вкладывают в ПЕ или блоки
  • блок - это начинка составного исполняемого оператора
  • составной исполняемый оператор содержит один, два, либо несколько блоков
  • границы блока - это ключевые строки   - таковы традиции Фортрана, например
    IF () then
      .. .. блок ДА
    else
      .. ..
    блок НЕТ
    end IF
  • составные исполняемые операторы вкладывают в качестве блоков без ограничений на глубину

 

БЛОК

__простой __

следование

 

__простой __

__простой __

__простой __

вложение в блок

  • в неисполняемых СО, например, при описании производных типов  допускается не вложение, а ссылки на ранее сделанные определения

 

Классификация операторов управления ходом вычислений

Операторы управления ходом вычислений позволяют изменить естественный ход вычислений

  • участок программы на выбор
  • участок программы неоднократно
  • досрочный выход из конструкции

Классификация производится в зависимомости

  • от типа управляющего выражения (строки таблицы)
  • числа подчиненных блоков (столбцы таблицы)
  • местоположение блока показано .. ..

Тип выражения

ЧИСЛО подчиненных БЛОКОВ

0-без блоков

1 блок

2 и более блоков

без
выражения

Безусловный
переход
goto m

exit  cycle return stop

do ! бесконечный цикл
.. ..
enddo

логическое
выражение
(условие)

logical L

Логический if
if ( L ) простой

если L=.true. то выполнить простой
оператор 

Условный
if ( L ) then
.. ..
end if
Структурный 
if ( L ) then
.. ..
else
.. ..
end if
итеративный цикл
do while(L)
. ..
end do
Векторный условный
where (
vectorL)
.. ..
Векторное присваивание
endwhere
Векторный структурный
where (vectorL)
.. ..
Векторное присваивание
elsewhere
.. ..
Векторное присваивание
end where

арифметическое
выражение
real R

арифметическое
выражение
integer
I

Переключатель
вычисляемый
goto ( ..m ), I

Арифметический if
if(RI) m<,m=,m>

Цикл по параметру RI
do RI=RIн,RIк,RIш
.. ..
end do

RI- вещественная или целая переменная

Переключатель структурный
select case( IC )
case ( ..constIC )
.. ..
.....
.....
casedefault
(..constIC)
   .. ..
end select

с любым числом блоков


символьная переменная - строка из одного символа
character C

IC - целая или  символьная переменная

Нерекомендуемые операторы - это опасные в применении операторы с метками, характерные для программ до новой эры структурного программирования

  • Безусловный переход   по метке    goto m
  • Переключатель вычисляемый   с метками   goto ( ..m ), I
  • Арифметический оператор с метками       if( RI) m<,m=,m>
  • дополнительный возврат из подпрограммы на метку  return m

DO - Оператор цикла

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

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

В заголовке цикла присутствует слово do - по-русски "делать". В Фортране-90 представлены три вида циклов:
-  цикл по параметру или цикл с заранее известным числом повторений
-  итеративный цикл
-  бесконечный цикл

Таблица. Сравнение трех видов циклов

Цикл

С заранее известным числом повторений Итеративный Бесконечный

Форма записи

DO i= iн , iк , is
.. ..
ENDDO

DO WHILE(условие)
.. ..
ENDDO
DO
.. ..
ENDDO
Число повторений

n = max( 0, int[ ( iк - iн + is ) / is ] )
int - целая часть, max-максимум

заранее не известно

Потенциально
бесконечное

Нормальн. выход

через n раз

когда перестанет выполняться условие

Никогда

Обозначение цикла на блок-схеме

Цикл с заранее известным числом повторений

Отличительная особенность этого вида циклов - наличие параметра цикла и ключевая фраза i = iн , iк , is , содержащая триплет, т.е. тройку чисел. Триплет задает способ изменения параметра цикла по закону арифметической прогрессии, где

  • i -параметр цикла, переменная
  • каждое из чисел триплета  iн , iк , is - это константа, переменная или арифметическое выражение, при этом
    - начальное значение параметра цикла,
    - конечное значение параметра цикла,
    is - шаг изменения параметра цикла

Например, цикл  do step=2,11,3   заставляет изменяться параметр step по следующему закону 2,5,8,11

Допускаются варианты написания цикла

DO  i = iн , iк , is ! Обычная форма без имени
   .. ..
ENDDO
  ! удобна при копировании

имя: DO  i = iн , iк , is ! Полная форма DO с именем цикла
   .. ..
ENDDO
имя    !   имя в начале и в конце

DO   i = iн , iк   ! Сокращенная форма без указания шага is
   .. ..
ENDDO
    !
подразумевается is=1

DO   m, i = iн , iк, is    ! устаревшая форма с меткой
   .. ..
m
ENDDO   ! с меткой у последнего оператора
или устаревшая форма с меткой и пустышкой в конце цикла - так писали раньше, например, в старых учебниках
do m, i= iн , iк , is ! устаревшая форма
   .. ..
m
continue ! помечали последний оператор в области действия цикла

Правила применения цикла с заранее известным числом повторений

  • Оператор DO сам принудительно изменяет i по закону арифметической прогрессии: программисту внутри цикла изменять i запрещается

  • Число повторений цикла рассчитывается заранее до цикла по формуле 
    n = max( 0, int[( iк-iн+is)/is]  )
    причем  n всегда целое, n зависит от iн , iк , is
    max(x,y)-большее из двух чисел, причем в нашем применении max(0,y),  y= int[( iк-iн+is)/is] 

    max(0,y)=y при y>0, 

    max(0,y)=0 при y<0,

    max(0,y)=0 при y=0

    int[x/y]-целая часть частного, иногда, ее, как на рисунке, обозначают   ] x/y [
    n вычисляется до цикла - см. подробную блок-схему цикла

      Примеры на расчет числа повторений цикла от простого к сложному

      do i=3,9,2           n= (9-3+2)/2 =  8/2  = 4

      do i = 0.3,0.9,0.2           n= (0.9-0.3+0.2) / 0.2 =  0.8 / 0.2 = 4

      do i=9,3,-2          n= [3-9+(-2)] / (-2) =  -8/(-2)   = 4

      do i=3,10,2         n=int( (10-3+2)/2 )=int( 9./2. )=int( 4.5 )=4

      do i=9,3,2            n=max(0, (3-9+2) /2 )=max(0, (-4) /2  ) = max(0, -2 ) = 0

      do i=10,3,2    n=max(0, int[ (3-10+2)/2] )=max(0, int[(-7)/2]) =max(0, int[ -3.5] )=max(0, -3 )=0

  • Параметр цикла - это переменная предпочтительнее целого типа integer ,

    чтобы параметр изменялся точно в интервале [ iн , iк ]

    чтобы число повторений цикла рассчитывалось точно,

    при этом последнее значение i внутри цикла i=+(n-1)is=

    при выходе из цикла i=iк+is

  • Величины iн , iк , is , как и i, могут быть не только целого типа integer, но и типа real или double precision. Следует понимать, что в этом случае

    параметр i изменяется не точно, а приближенно

    хуже того, ошибка по формуле  i=i+is постепенно накапливается и становится тем заметнее, чем больше число повторений

    ввиду накопления ошибок "последнее значение i=+(n-1)is "  может уйти за интервал  [ iн , iк ], вываливаясь за цикл

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

  • Величины iн , iк , is в отличие от i могут быть не только переменными, но и константами или арифметическими выражениями. Изменять переменные iн , iк , is внутри цикла можно, но на n это не повлияет, так как n вычисляется до цикла
  • Шаг изменения i -это is, не равный 0, причем is>0 - для возрастающего i , is<0 - для убывающего i; ну а когда пишут, опустив шаг i = iн,iк подразумевается is=1. При нормальном выходе из цикла  i достигает значение i=iк+is, продвинутое за конечное значение на шаг
      Do .. .. enddo
       
    следующий
    оператор выполнится при i=iк+is
  • Досрочный выход из цикла - это оператор exit, передающий управление на оператор, следующий за enddo.
  • do i = iн , iк , is
       .. ..
       if( e )   EXIT   ! досрочный ВЫХОД из ЦИКЛА
       .. XXX..
    enddo
    оператор, следующий за циклом
    . На этотоператор попадают

    при досрочном выходе из цикла достигнутое  i сохраняется

    при нормальном завершении цикла i=iк+is 

    Именованная полная форма do разрешает осуществлять досрочный выход по EXIT my с любой глубины на оператор следующий за   ENDDO my
    my: DO
              .. ..
              do
                 .. ..   
                if( e) EXIT my     ! выход с любой глубины
               .. XXX..
              enddo
           .. XXXXXX  ..
        ENDDO my
     
    на оператор, следующий за циклом  my

    Досрочный выход на метку m за циклом производит и goto m, но его лучше не применять!

  • Следующий проход цикла CYCLE
  • do
          .. ..
          if(
    условие  )   cycle ! к следующему проходу цикла
           ..____ ..
    пропускаются при выполнении cycle
    enddo
    Именованная полная форма do разрешает использовать CYCLE my на любой глубине
    my: DO
        .. ..
       do
            .. ..
             if( e) CYCLE
    my ! с любой глубины
          ..___. .
       enddo  !   ..___ ..
        ..___..
    ENDDO
    my ! Следующий проход цикла my

  • В конструкции ( ..v , i= iн , iк , is ) или ( ..e , i= iн , iк , is ), называемой неявным do; вместо do .. .. enddo область действия цикла ограничена скобками, а под ..v подразумевается список переменных или ..e - выражений, перечисленных через запятую и зависящих от i . Неявный do используется как элемент списка ввода-вывода в операторах read / write , а также в списках инициализации оператора data и в конструкторе массива. Проиллюстрируем применение неявного Do на примере - вывода таблицы из 100 значений замечательного предела 
  • real x
    write(2,11 ) &
                (    x,      sin(x)/x,     x = 1,0.01,-0.01 )
    11 format"('|    x     | sin(x)/x |'/ &
             ('|',e10.3, '|', e10.3,'|')  )"

Рекомендации:

  • в подстроках Фортрана-77, а затем и в операторе Select case стало модно использовать диапазоныи. В секциях массива пошли дальше и стали использовать триплеты, по смыслу такие же, как в циклах. Отличие в знаке препинания: вместо запятой-двоеточие. Секции массивов, основанные на использовании триплетов, - конструкция более емкая, чем неявный do, например, сравни списки read и write при вводе-выводе первой половины массива  из 100 элементов
    real A(1:100)
  • read(1,*) A                       !   ввести весь массив
    read(1,*) (A(i),i=1,100)  !  можно в более общем виде
    write(1,*) (A(i),i=1,50)  ! вывести только первую половину массива
    write(2,*) A(1:50)          ! вывести только первую половину массива

    write(2,*) A(1:100:2) ! вывести половину элементов с нечетными номерами
    write(2,*) A(1:99:2)   ! вывести половину элементов с нечетными номерами
    write(2,*) A(2:100:2) ! вывести половину элементов с четными номерами

  • при большой глубине вложения блоков  и человек плохо воспринимает программу, и диагностика затруднена. Заботясь о читаемости программы, пользуйтесь именами циклов, отступами и комментариями, облегчающими восприятие, как в примере:
    BIG:Do A= 1,10      ! BIG-БОЛЬШОЙ ЦИКЛ по A
                 small:do x=0.7 , 3.5, 0.35    ! small-малый цикл по x
                                 write(3,*) x,  a*x +7.2
                           end do small  !  конец small
            End Do BIG ! КОНЕЦ BIG
  • внимание - в случае ошибок в закрытии блоков компилятор иногда путает IF и DO в неименованных конструкциях

В  С и Паскале имеются аналогичные виды циклов, правда, с некоторыми отличиями

  • в цикле с заранее известным числом повторений в С можно иметь несколько параллельно изменяющихся параметров, каждый параметр изменяется по-своему
  • в цикле с заранее известным числом повторений в Паскале допускается только целочисленный параметр, изменяющийся с шагом 1 или -1
  • в Паскале и в С используется ключевое слово FOR вместо DO
  • правописание оператора цикла в каждом языке свое
  • в Паскале и в С вместо фортрановского DO WHILE с предусловием имеется две разновидности итеративного цикла с предусловием и постусловием

Примеры на вычисление координат точек четверушки окружности во втором квадранте

Даются все более удачные решения одной и той же задачи с радиусом  r=4.5, различающиеся выбором угловой меры и типа параметра цикла, с последующим сравнением полученных таблиц. Названия решений DR, RR, RI.. состоят из двух букв, причем

  • первая буква указывает на то в чем задается угол и шаг r-радианы D-градусы
  • вторая буква указывает на то какого типа   параметра цикла R-вешественый, I-целый

Если адресовать полученную таблицу для aGRAPHER, то первым действием должно быть open(2,file='okr2.dat')   - открыть файл с расширением *.dat   Решения варьируются в зависимости от применения явного и неявного цикла и форматного вывода

  • (Rr) самое плохое  решение с "потерей" последней точки pi или "лишней" точкой после pi
    угол в радианах,  шаг 0.1 - не кратен pi, цикл DO - явный 
    program rr
    real :: r=4.5, x,pi
    integer i
    open(1,file='okr2.txt')
    pi=2.*asin(1.); i=0    ;
    write(1,*) 'n=',int((pi-pi/2+0.1)/0.1) 
    ! n=int[(pi-pi/2+0.1)/0.1]=int[(1.57+0.1)/0.1]=int[1.67*10]=int[16.7]=16,
    write(1,*)    "     i    al      x      y"
    do ral=pi/2,pi,0.1
      i=i+1; x = r*cos(ral); y = r*sin(ral) ; write(1,*) i,ral, x,y
    enddo
    end
    при этом получим значения
    n= 16
    i    al          x            y
    1) 1.570796 -1.967013E-07 4.500000
    ... ...
    16) 3.070796 -4.488727 3.183210E-0 --> недолёт
    еще одну 17-ю точку на оси абсцисс можно "добавить", искусственно продвинув
    ral на полшага и писать DO так     
    do ral  =  pi/2,  pi+0.05,  0.1    всего лишь, чтобы добавить строку  
    17)  x= -4.498081     y=-1.313939E-01 --> перелёт, а не точно  x=4.5; y=0.
  • (Rr) решение с явным DO, угол в радианах, шаг  в долях pi
    real
    :: r-4.5,  x,y,pi;  real ral 
    ! угол в радианах
    pi=2.*asin(1.)
    do ral=pi/2,pi,pi/30
      x=r*cos(ral);  y=r*sin(ral);  write(2,*) x,y
    enddo
    !    n=(pi-pi/2+pi/30)/(pi/30)=16
    i       al                   x                      y
    1) 1.570796 -1.967013E-07 4.500000
    .. ..
    16) 3.141592 -4.500000 4.971016E-06 - значения не круглые, но близкие
  •  
  • (Dr) угол вещественный в градусах
    write
    размещен внутри
    явного do
    real :: r=4.5 , dalf,x,y;  real  dalf    !  угол в градусах
    do dalf=90,180,2 
       !  угол в градусах с шагом 2 градуса
        x=r*cosd(dalf);    y=r*sind(dalf) ;
      write(2,*) x,y
    enddo
      ! -  количество точек n=(180-90+2)/2=46 и все значения "кругленькие"
  • (Dr) угол вещественный в градусах, вывод форматный
    решение с неявным do, размещенным внутри write
    real  r/4.5/ , dalf    !  угол в градусах с шагом 2 градуса
    write(2,17) (r*cosD(dalf),r*sinD(dalf), dalf=90.,180.,2.)
    17    format(   f8.3,         f8.3)
    решение отличается лишь заменой явного цикла на неявный и более аккуратным оформлением результатов
        .000   4.500
      ...
      -4.500    .000
     
      do  размещен внутри   write
  • (Ri) решение с  с целым параметром цикла i=0,15 который легко пересчитывается в ral - угол в радианах по формуле ral= pi/2 +i* pi/30
    integer i; real r/4.5/,x, y, pi ;   real  ral  ! угол в радианах
    pi=2.*asin(1.)

    do i=0,15
    ral=pi/2 + i*pi/30; x=r*cos(ral); y=r*sin(ral) ;

    write(2,"(f8.3,f8.3)"
    ) x,y
    enddo 
    ! число точек n=(15-0+1)/1 = 16 , а значения
    1) x=.000   y=4.500
      ....
    16) x=
    -4.500  y=0.000 - приемлемые   x,y
  • Если сравнивать решения, делая шаг все мельче, то именно последний вариант (RI) наиболее защищен от ошибок, так как целое  i изменяется в цикле точно. Во всех других вариантах ошибка по углу к концу интервала  накапливается, тем больше чем мельче шаг. Возможна еще одна реализация ( DI ) также с циклом по целому параметру ialf, который переводится в вещественный аргумент при помощи функции real(ialf)  
  • ( Di ) лучшее решение без накопления ошибок с неявным DO, угол и шаг целые, в градусах, вывод форматный
    real r/4.5/; integer ialf    !  угол в градусах с шагом 2 градуса
    write(2,"(f8.3,f8.3)") (r*cosD(real(ialf)),r*sinD(real(ialf)),ialf=90,180,2) 
    do
      размещен внутри write

Примечания к примерам:

  • в Ф-90 функции sinD(degree) и cosd(degree) есть в числе стандартных , degree - угол в градусах
  • в Ф-77 функцию sinD(degree) можно определить  так
    real pi, degree
    parameter ( pi=3.1415298)sinD(degree)=sin(degree*pi/180)  !   аналогично и косинус, degree - угол в градусах
Hosted by uCoz
.

 

 Web-design Звягин В.Ф. со товарищи: Аминев Р.Ш..
197101, Россия, Санкт-Петербург, ул.Саблинская, 14
ИТМО
Hosted by uCoz