модульного программирования.



Работа добавлена на сайт TXTRef.ru: 2019-12-03

Технология модульного программирования. Функции.

Бинарный поиск. Поиск по бинарному дереву.

Бинарный поиск.

Поиск может быть выполнен значительно быстрее, если записи предварительно отсортированы по возрастанию или убыванию ключей. Предположим, что записи отсортированы a1<a2...<aN по возрастанию ключей, тогда сначала вычисляется индекс среднего элемента p=n/2. Если значение не целое, оно может округляться в любую сторону. Затем выполняется сравнение ключа среднего элемента и К, К=ар. Если они равны то поиск завершен успешно и результатом является индекс р некоторого элемента. В противном случае поиск должен быть продолжен в одной из половин таблицы. Если к<ар тогда а1,а2...ар-1 , к>Ар тогда Ар+1, Ар+2....Аn.  Затем указанные шаги повторяются до тех пор пока не встретится запись с ключом К или останется 1 непросмотренный элемент в некоторой половине подмассива. Очевидно это этот единственный элемент будет иметь ключ К или же поиск будет завершен неуспешно, эффективность бинарного поиска: каждый просмотр среднего  элемента массива или подмассива требует 2 сравнения(1ый - "=", 2ой - "<,>"). Поскольку каждый просмотр среднего элемента уменьшает зону поиска в 2 раза, то один непросмотренный элемент останется после выполнения 2log2n сравнений. Отсюда в худшем случае бинар. поиск требует E=2log2n+1 сравнений. Тогда оценка сложности O(log2n). В сравнении с лин. поиском считается, что бинар. поиск становится более эффективным при n>20.

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

2 реализации бинарного поиска: итерационный и рекурсивный.

Поиск по бинарному дереву .

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

Построение дерева производится так: ключ первой записи входной последовательности сопоставляется с корнем дерева. Затем поочередно для записей начиная со второй до последней производится следующие действия: ключ очередной выбранной записи сравнивается с ключом корня. Если он меньше, он сравнивается с ключом левого потомка, если больше то правого и тд. по дереву до достижения листа. Если достигается лист, то образуется новая вершина дерева и ей сопоставляется соответствующая запись. Например пусть вх последовательностью явл.: 8,11,3,9,14,1,10,5,6,12,15,7,13.

Поиск по такому дереву осуществляется аналогично его построению путем просмтора веришн начиная от корня к листьям по тем же самым правилам.

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

К-аргумет поиска

а[1...n] - массив ключей, Р - номер текущей вершины

L[p], R[p] - номера левого (правого) потомка текущей вершины Р

top -номер корня TS - результат поискаTS=0 - неуспешный поиск  или же TS=p - успешный поиск, где р=1,2,3...N.

Трудоемкость алгоритма определяется высотой дерева 0(n) до 0(log2n). Худший с т зрения вычислительных затрат случай возникает тогда, когда при построении дерева записи считываются строго по возрастанию или убыванию ключей. Тогда дерево вырождается в лин. список длиной n. Однако, если записи выбираются  в случайном порядке, то получается полное или почти полное дерево и алгоритм поиска работает подобно бинарному методую В среднем считается что сложность поиска по дереву имеет оценку 0(log2n)

Типовые задачи синхронизации.

В программировании не существует идеальных решений и алгоритмов на все

случаи жизни,  но имеются типовые задачи и варианты их решения.  Мы рассмотрим

несколько типовых задач синхронизации и их решения:

- «Производители-Потребители»

- «Читатели-Писатели»

- «Обедающие философы»

- «Спящий брадобрей» 56

 Задача «Производители-потребители»

Одной из типовых задач,  требующих синхронизации,  является задача producerconsumer  (производитель-потребитель). Пусть два потока обмениваются информацией

через буфер ограниченного размера. Производитель добавляет информацию в буфер, а

потребитель извлекает ее оттуда.

Функциональность потоков производителя и потребителя можно записать

следующим образом.

Producer:

 while(true) {

   PrepareData(); // Подготовить данные

   Put(Data);     // Поместить данные в циклический буфер

 }

Consumer:

 while(true) {

   Get(&Data);    // Считать данные из циклического буфера

   UseData();     // Использовать данные

 }

Сразу необходимо отметить,  что если буфер пуст,  то потребитель должен ждать,

пока в нем появятся данные,  а если буфер полон,  то производитель должен ждать

появления свободного элемента.  В данном случае реализация производителя и

потребителя будет иметь следующий вид.

Producer:

 while(true) {

   PrepareData();          // Подготовить данные

   while( ! Put(Data) )    // Разместить данные57

     ;

 }

Consumer:

 while(true) {

   while( ! Get(&Data) )   // Считать данные

     ;

   UseData();              // Использовать данные

 }

Задача  «Производители-Потребители»  заключается в обеспечении согласованного

доступа нескольких потоков к разделяемому циклическому буферу.  Корректное

решение должно удовлетворять следующим условиям:

- потоки выполняются параллельно;

- одновременно в критической секции, связанной с каждым критическим ресурсом,

должно находиться не более одного потока;

- потоки должны завершить работу в течение конечного времени;

- потоки должны корректно использовать операции с циклическим буфером.

Предположим, что решение задачи использует реализацию циклического буфера, в

которой Start указывает на ячейку, в которую будет положен следующий элемент, End

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

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

между производителями и потребителями: например, производитель изменяет значение

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

своей критической секции  (т.е.  принимал решение о возможности изъять очередной

элемент или изымал элемент), то изменение значения переменной Start производителем

не может привести к принятию неверного решения потребителем или ошибке при

изъятии элемента.  В случае нескольких потоков,  для потоков-производителей

критическим ресурсом будет переменная Start, для потоков-потребителей – переменная

End.

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

критическим данным, во-вторых, оповещение потребителей, ожидающих поступления

данных, и производителей, ожидающих появления незаполненных записей в буфере.

Решение задачи "Производитель-Потребитель", использующее семафоры

Semaphore Access = 1;//управляет доступом к разделяемым данным58

Semaphore Empty = n;  // количество пустых записей

Semaphore Full  = 0;  // количество заполненных записей

Producer(){

  P(Empty);  // ждем появления свободной записи

  P(Access);  // получаем доступ к указателям

  <записываем значение в запись>

  V(Access); // завершили работу с указателями

  V(Full);  // сигнализируем о появлении заполненной записи

}

Consumer(){

  P(Full);  // ждем появления заполненной записи

  P(Access); // получаем доступ к указателям

  <извлекаем данные из записи>

  V(Access); // завершили работу с указателями

  V(Empty); // сигнализируем о появлении свободной записи

  <используем данные из записи>

}

Двоичный семафор Access используется для организации согласованного доступа к

критическим данным, счетные семафоры Full и Empty используются для сигнализации

ожидающим потокам о наступлении ожидаемого события (появлении заполненной или

пустой записи соответственно).

Решение задачи "Производитель-Потребитель", использующие мониторы

Monitor Bounded_buffer {

  buffer Resources[N];

  condition not_full, not_empty;

  Produce(resource x) {

     while( array “resources” is full )

        wait(not_full);

     <записываем значение “x” в запись массива “Resources”>

     signal(not_empty);

  }

  Consume(resource *x) {

     while( array “resources” is empty )

        wait(not_empty); 59

     *x = <считываем значение из массива “Resources”>

     signal(not_full);

  }

}

В данном решении для сигнализации используются условные переменные,  а

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

внутри монитора.

Задача «Читатели-Писатели»

Вторая типовая задача – проблема читателей и писателей (Readers-Writers problem).

Предположим, у нас есть хранилище данных, с которым работают несколько потоков.

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

Функциональность потоков читателя и писателя можно записать следующим

образом.

Writer:

 while(true) {

   PrepareData();  // Подготовить данные

   Write(Data);    // Записать данные

 }

Reader:

 while(true) {

   Read(&Data);    // Прочитать данные

   UseData();      // Использовать данные

 } 60

Если несколько потоков одновременно обращаются к разным записям базы

данных, то никаких проблем не возникает. Проблема синхронизации доступа к данным

возникает при обращении нескольких потоков к одной и той записи.  К тому же,

организация согласованного доступа для потоков-читателей и потоков писателей

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

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

записи требует эксклюзивного доступа.

Задача  «Читатели-Писатели»  заключается в обеспечении согласованного доступа

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

удовлетворять следующим условиям:

- потоки выполняются параллельно;

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

другими потоками;

- во время выполнения потоком операции чтения,  другие потоки также могут

выполнять операцию чтения;

- потоки должны завершить работу в течение конечного времени.

Решение задачи "Писатели-Читатели", использующее семафоры

Semaphore RC = 1; //управляет доступом к переменной ReadCount

Semaphore Access = 1; //управляет доступом к данным

int ReadCount = 0; //количество "активных"(читающих) читателей

Writer(){

  P(Access);      // захватываем доступ к критическим данным

  <выполняем операцию записи>

  V(Access);      // освобождаем доступ к критическим данным

}

Reader(){

  P(RC);//получаем эксклюзивный доступ к переменной ReadCount

  ReadСount++;    // увеличиваем число активных читателей

  if( ReadСount == 1 )

     P(Access);   // захватываем доступ к кр ритическим данным

  V(RC);// освобождаем доступ к переменной ReadCount

  <выполняем операцию чтения>

  P(RC);//получаем эксклюзивный доступ к переменной ReadCount 61

  ReadСount--;    // уменьшаем число активных читателей

  if( ReadСount == 0 )

     V(Access);   // освобождаем доступ к критическим данным

  V(RC);// освобождаем доступ к переменной ReadCount

}

Для защиты разделяемых критических данных используется двоичный семафор

Access. Функция писателя просто получает доступ к критическим данным  (уменьшая

семафор Access) и использует их.

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

данным нескольких читателей,  поэтому она использует дополнительную переменную

ReadCount –  количество читателей,  выполняющих операцию чтения в настоящий

момент.  Данная переменная также требует защиты для корректного использования

несколькими читателями  (для этого введен двоичный семафор RC),  но ее

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

первому читателю  (остальные будут заблокированы при попытке уменьшить семафор

RC), а освобождение данных оставить последнему читателю, завершившему операцию

чтения.  Обратим внимание,  что вследствие подобного подхода функция читателя

содержит 3  критических секции:  одну,  связанную с чтением критических данных,  и

две,  связанных с изменением переменной ReadCount  и организации процесса входа и

выхода из первой критической секции.

Отметим также,  что если потоки-читатели постоянно входят в критическую

секцию,  возможно голодание (starvation)  потоков-писателей.  (Голодание –  ситуация,

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

неограниченного периода времени). Для решения этой проблемы можно использовать

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

в критическую секцию при наличии ожидающих писателей  (мы не будем приводить

данное решение).

6.3.  Задача «Обедающие философы»

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

использоваться потоками,  причем для решения конкретной задачи потоку требуется

использовать несколько ресурсов одновременно.  В этом случае мы имеем задачу

обеспечения согласованного доступа к некоторому подмножеству имеющихся

ресурсов.  Задача об обедающих философах представляет частную постановку такой62

задачи,  имеющую ограничениями относительно общего случая,  но допускающая

расширения своего решения.

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

образом.  На круглом столе расставлены тарелки,  по одной на каждого философа.  В

центре стола – большое блюдо спагетти, а на столе лежат пять вилок — каждая между

двумя соседними тарелками. Каждый философ находится только в двух состояниях —

либо он размышляет, либо ест спагетти. Начать думать после еды философу ничто не

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

что любой философ,  прежде чем начать есть,  должен положить из общего блюда

спагетти себе в тарелку. Для этого он одновременно должен держать в левой и правой

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

начать есть.  Закончив еду,  философ кладет вилки слева и справа от своей тарелки и

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

В качестве совместно используемых ресурсов в данном случае выступают вилки, а

ограничение состоит в том,  что каждая вилка используется только двумя сидящими

рядом с ней философами.

Функциональность потоков-философов можно записать следующим образом.

Philosopher:

 while(true) {

   think();      // Размышляем

   take_forks(); // Берем 2 вилки

   eat();        // Обедаем

   put_forks(i); // Кладем на стол обе вилки

 } 63

Задача  «Обедающие философы»  заключается в обеспечении согласованного

доступа нескольких потоков к разделяемым ресурсам.  Корректное решение должно

удовлетворять следующим условиям:

- потоки выполняются параллельно;

- во время использования  «вилок»  потоком данные  «вилки»  не должны

использоваться его соседями;

- потоки должны завершить работу в течение конечного времени.

Решение задачи  "Обедающие философы",  использующее семафоры

(предполагается количество философов, равное 5)

#define LEFT     (i+4)%5

#define RIGHT    (i+1)%5

#define THINKING 0    // Состояния философов

#define HUNGRY   1

#define EATING   2

int State[5];       //Массив состояний философов

Semaphore Access=1; //Управление доступом к критическим данным

Semaphore S[5]={0,0,0,0,0};//Для ожидания освобождения ресурсов

void Philosopher( int i ){  // i – номер философа от 0 до 4

 while( true ){

   think();       // Размышляем

   take_forks(i); // Берем 2 вилки или блокируемся

   eat();         // Обедаем

   put_forks(i);  // Кладем на стол обе вилки

 }

}

void take_forks( int i){

 P(Access); // Захватываем доступ к критическим данным

 State[i] = HUNGRY; // Изменяем свое состояние

 test(i);   // Пытаемся взять две вилки

 V(Access); // Освобождаем доступ к критическим данным

 P(S[i]);   // Блокируемся, если не удалось взять вилки

} 64

void put_forks( int i){

 P(Access);   // Захватываем доступ к критическим данным

 State[i] = THINKING; // Изменяем свое состояние

 test(LEFT);  // Пытаемся накормить соседа слева

 test(RIGHT); // Пытаемся накормить соседа справа

 V(Access);   // Освобождаем доступ к критическим данным

}

void test( int i ){

if(state[i]==HUNGRY&&state[LEFT]!=EATING&&state[RIGHT]!=EATING){

  State[i] = EATING;  // Изменяем состояние

  V(S[i]);            // Разрешаем перейти к еде

}

}

Семафор Access  используется для защиты массива состояний философов State[5].

Семафоры S[5]  используются для оповещения философа о возможности взять две

вилки и начать обед. Отметим,  что момент начала обеда определяется не философом,

желающим обедать, а философом, завершившим обедать.

Можно предположить следующие типичные недостатки,  присущие различным

решениям задачи об обедающих философах:

- если все философы проголодались, взяли левую вилку и не желают ее отдавать, то

они все будут ожидать правые вилки в течение бесконечного времени;  предложенное

решение не допускает возникновения подобной ситуации;

- если имеется голодный философ,  то его непосредственные соседи могут по

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

времени хотя бы одна из необходимых ему вилок занята –  в результате возможно

голодание отдельного философа;  предложенное решение допускает возможность

такого голодания.

Имеется простое расширение предложенного решения на случай,  когда каждый

поток может использовать произвольное множество ресурсов.  Для этого,  во-первых,

необходимо добавить массив признаков занятости ресурсов и описания множеств

ресурсов,  затребованных каждым потоком,  во-вторых,  при освобождении ресурсов

поток должен просматривать все потоки,  ожидающие освобождения ресурсов,  и в65

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

резервировать за ними ресурсы и разрешать им продолжить выполнение.

Подобное решение будет лишено первого недостатка  (по причине того,  что все

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

возвращают), но будет подвержено второму, как и оригинальное решение.

Структура процессора

Принцип фон Неймана

  1.  Двоичное кодирование
  2.  Принцип программного управления

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

  1.  Принцип адресности.

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

  1.  Принцип однородности памяти

Вся информация (команды и данные) находится в одной и той же памяти и внешне неразличима. Идентификацией содержимого ячейки занимается программа.

Подобная архитектура еще называется прингстонской.

Гарвардская архитектура

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

Структура:

 

Базовая структура ПК

Центральный процессор

ЦП осуществляет общее управление и выполнение всех команд.

Основные этапы выполнения команд:

  1.  выборка команды и определение адреса следующей команды
  2.  дешифрация команды
  3.  формирование адресов операндов
  4.  выборка операндов
  5.  выполнение операции и формирование флагов
  6.  запись результата

По отношению к внешним компонентам процессор выполняет только 2 функции: считывание (read, r, rd) и запись (write, w, wr).

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

Процессор реагирует на все внешние воздействия.

Память

Оперативная память (основная; ОП)

  1.  постоянная. Используется для хранения постоянных коэффициентов и стандартных программ. (только чтение)
  2.  полупостоянная (ППЗУ). Используется для хранения часто используемых данных и программ. Чаще применяется в специализированных машинах и на этапах отладки.     
  3.  АЗУ используется для записи и считывания.

Контроллеры

Все внешние устройства (внешняя память, устройство ввода-вывода) подключаются к процессору через контроллеры.

Контроллер для шины представлен только регистрами или портами ввода-вывода. Через них передается адрес, данные и управление (на уровне процессора, т.е. прочитать или записать).

Контроллер формирует для внешнего устройства все УС.

Шины

  1.  Адресная шина.

Является однонаправленной. Ширина шины (разрядность) задает максимально адресуемое адресное пространство от 0 до 2n-1.

  1.  Шина данных.

Является двунаправленной. Чаще всего ширина совпадает с длиной слова (8; 16; 32; 64)

  1.  Шина управления.

Каждый провод шины управления однонаправленный. По этой шине передаются УС и принимаются ОС.

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

Совокупность трех шин называется системной шиной.

Тактовый генератор формирует последовательность импульсов, которая задает тактовую частоту микропроцессора. Время выполнения операций задается в машинных тактах (напр., сложение с фиксированной точкой выполняется за 3-4 машинных такта)

Процессор

В состав процессора входит арифметико-логическое устройство, устройство управления, регистровая память.

АЛУ

В простейшем виде, АЛУ – комбинационная схема, выполняющая элементарные действия, плюс несколько регистров для хранения исходных данных и результатов. Более сложные АЛУ содержат блоки аппаратной реализации типовых функций.

Схема управления

Схема управления формирует все управляющие сигналы, необходимые для работы  АЛУ и контроллеров внешних устройств.

Локальная (регистровая) память

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

В состав локальной памяти входят:

1)   регистры общего назначения (РОН). Они могут быть универсальными или

           специализированными. В процессорах фирмы INTEL  используется смешанный принцип (по   

           умолчанию они специализированные, но могут быть использованы как универсальные). Это   

           самая быстродействующая память.

  1.  стековая память. Это специализированная память со специфической процедурой записи и чтения. Запись осуществляется в вершину стека с перезаписью всего ранее записанного. Считывание производится тоже только из вершины стека. Такая структура памяти удобна при выполнении подпрограмм и прерываний, когда в вершину стека записывается адрес возврата из подпрограммы.
  2.  cache-память. По быстродействию она хуже регистровой  Часто в гарвардской архитектуре кэш делится на кэш данных и кэш команд. Во многих процессорах имеется возможность наращивания кэш внешними микросхемами. Предназначена для временного хранения текущих массивов данных и команд.

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

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

Виды проекций

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

• центральные (перспективные);

• параллельные (аксонометрические).

Если центр проекции находится на конечном расстоянии от проекционной плоскости, то проекция − центральная . Если же центр проекции удален на бесконечность, то проекция − параллельная .

 

Центральная проекция

Параллельная проекция

Полная классификация

Параллельные проекции делятся на два типа:

1) ортогональные (направление проецирования является нормалью к проекционной плоскости);

2) косоугольные (направление проецирования и нормаль к проекционной плоскости не совпадают).

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

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

Двумя важными видами косоугольных проекций являются проекции:

1) Кавалье (cavalier);

2) Кабине (cabinet).

Центральная проекция приводит к визуальному эффекту перспективного укорачивания, когда размер проекции объекта изменяется обратно пропорционально расстоянию от центра проекции до объекта. Центральная проекция любой совокупности параллельных прямых, которые не параллельны проекционной плоскости, будет сходиться в точке схода. Точек схода бесконечно много. Если совокупность прямых параллельна одной из главных координатных осей, то их точка схода называется главной точкой схода. В зависимости от того, сколько координатных осей пересекает проекционную плоскость, различают три вида проекций:

1. Одноточечная

2. Двухточечная (широко применяется в архитектурном, инженерном и промышленном проектировании).

3. Трехточечная центральная (практически не используется).

Модульное программирование

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

Модуль характеризуют:

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

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

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

– слабые информационные связи с другими программными модулями – обмен информацией между модулями должен быть по возможности минимизирован.

Каждый модуль состоит из спецификации и тела. Спецификации определяют правила использования модуля, а тело – способ реализации процесса обработки.

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

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

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

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

– принятие основных решений в алгоритм выносится на максимально «высокий» по иерархии уровень;

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

 

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

– экранные формы ввода и/или редактирования информации базы данных;

– отчеты генератора отчетов;

– макросы;

– стандартные процедуры обработки информации;

– меню, обеспечивающее выбор функции обработки и др.

 

Алгоритмы большой сложности обычно представляются с помощью схем двух видов:

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

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

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

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

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

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

принятие основных решений в алгоритме выносится на максимально "высокий" по иерархии уровень;

для использования одной и той же функции в разных местах алгоритма создается один модуль, который вызывается на выполнение по мере необходимости. В результате дальнейшей детализации алгоритма создается функционально-модульная схема (ФМС) алгоритма приложения, которая является основой для программирования (рис. 18.3).

  

Функционально-модульная структура приложения

Пример:. Некоторые функции могут выполняться с помощью одного и того же программного модуля (например, функции Ф1 и Ф2).

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

Функция Фm реализуется с помощью иерархии связанных модулей.

Модуль n управляет выбором на выполнение подчиненных модулей.

Функция Фx реализуется одним программным модулем.

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

экранные формы ввода и/или редактирования информации базы данных;

отчеты генератора отчетов;

макросы;

стандартные процедуры обработки информации;

меню, обеспечивающее выбор функции обработки и др.

ЗАДАЧА ПО ТОЭ:

Ток I1 равен: I1=E/(R1+R2*R3/R2+R3)

I1=6/(10+40*40+40)= 0,0036 А


ОП

УВв

УУ

АЛУ

УВыв

С

Р

Р

Р

Р

К

А

УС     ОС

ЦП

БП

ТГ

ША

ШД

ШУ

ПЗУ

ОЗУ

ОЗУ

КОНТР

КОНТР

ВнУстр

ВнУстр

Другие работы

товарный знак знак обслуживания и т.


ДОГОВОР КОММЕРЧЕСКОЙ КОНЦЕССИИ Договор по которому одна сторона правообладатель обязуется предоставить другой стороне пользователю за вознагражд...

Подробнее ...

это свойство объекта характеризующею степень ...


Режимные перерывы регламентированы режимом работы предприятия и участка перерывы па обед между сменами нерабочие смены нерабочие дни. Специализа...

Подробнее ...

РЖД много внимания уделяет внешнему виду желе...


Дипломный проект 2 Лист Дата Подпись № докум. Дипломный проект 49 Лист Дата Подпись № докум. Подпись и дата Взам. Подпись и дата Справ.

Подробнее ...

. Згенерувати два великих простих числа p та ...


Схема шифрування Рабіна B шифрує повідомлення M для яке потім дешифрує. Представити повідомлення m як число у проміжку {0 . Надіслати зашифрован...

Подробнее ...