Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
09.04.2015
Размер:
232.96 Кб
Скачать

4.2.Основные структуры, пошаговая детализация

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

  • Содержит единственный вход,

  • Содержит единственный выход,

  • Не содержит бесполезных (недостижимых) фрагментов,

  • Не содержит бесконечных циклов.

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

Все основные структуры были рассмотрены нами ранее, а все примеры рассмотренных нами алгоритмов и программ были структурными. Как следствие их структурности – отсутствие в них оператораgoto. В нашем курсе мы даже не затрагивали этот оператор, хотя он и имеется в Си. Для беглого ознакомления с ним рассмотрим пример программы, в которой используется операторgoto:

# include <stdio.h>

# include <conio.h>

Void main ()

{

int k;

float e,e1;

clrscr();

e =1.0;

k=0;

M: e=e/2;

e1=e + 1.0;

k = k+1;

if (e1 > 1.0) goto M;

printf("k = %d\n", k);

printf("Машинный нуль = %e \n", e);

getch();

}

В этой программе вычисляется машинный нуль: такое значение e, при котором значениеe + 1 не будет отличаться от1. Операторif (e1 > 1.0) goto M; обеспечивает безусловный переход к оператору с меткойM ( к операторуM: e=e/2;), если истинно выражениеe1 > 1.0. Переменнаяk определяет количество итераций для достижения машинного нуля.

При выполнении этой программы на нашем компьютере (с установленной версией Borland3.1C++) получили следующий результат:

к = 24 Машинный нуль = 5.960464e-08

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

# include <stdio.h>

# include <conio.h>

Void main ()

{

int k;

float e,e1;

clrscr();

e =1.0;

k=0;

do

{

k = k+1;

e = e/2;

e1=e + 1.0;

}

while (e1 > 1.0);

printf("k = %d\n", k);

printf("Машинный нуль = %e \n", e);

getch();

}

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

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

Содержательная постановка задачи.

Измерения степени загрязнения воздуха производятся каждую минуту в течение 24 – часового периода около дымовых труб завода. Мера загрязнения – число частиц, деленное на миллион ( КМ ). Обычно эта величина находится в диапазоне от 10 000 до 90000 тысяч. Модуль обработки информации должен делать следующее:

  1. Вычислить среднюю величину загрязнения для каждого часа из всего 24-часового периода.

  2. Зафиксировать число нарушений за час. Нарушением считается такая ситуация, когда в течение 5 минут подряд величина загрязнения превосходит 100 000 КМ. Таким образом, если эта величина превосходит 100 000 КМ в течение десяти минут, то фиксируется 2 нарушения. Таким образом, максимальное число нарушений в час равно 12. Нарушение может оказаться на границе часов. В этом случае его относят к тому часу, во время которого оно заканчивается.

  3. Напечатать отчет, в следующем виде: час среднее значение число загрязнения, КМ нарушений 1 50 000 1 2 70 000 1 3 80 000 2 4 65 000 12 5 75 000 4 6 50 000 3 … ……... . … ……... . … ……... . 24 50 000 0

Математическая постановка задачи.

Дано: массив загрязнений:MZ(i,j),

где MZ(i,j) – величина загрязнения в течениеi– го часаj– ой минуты,

i= 1,…24;j= 1,…60

Определить:

Среднее значение загрязнения для каждого i- го часаSZ(i):(1)

Все множество значений индексов jдля каждой строкиiразделим на K(i) групп. Каждая такая группаL(i,k)определится по правилам:L(i,k) = {J1(i,k),J1(i,k)+1, …J2(i,k)},

где к=1,2,3…..K(i), и справедливы следующие утверждения для любогоi:

  • для любого j  L(i,k) MZ(i,j) >100 000

  • MZ(i, J1(k) –1)<100 000

  • MZ(i, J2(k) +1)<100 000

Определим число нарушений для к – той группы i– строкиPnr(i,k) по формуле:

Pnr(i,k) =entier ( / 5 ), i=1,…24,k= 1,2,…K(i) гдеentier ( x) – функция , вычисляющая целую часть отx.

Тогдачисло нарушений для каждого часаNr(i)определится по формуле:Nr(i) = ,i= 1,2,..24

Ознакомившись с математической постановкой можно заметить, что среднее число загрязнений для каждого часа SZ(i) вычисляется просто. Но, что касается числа нарушений для каждого часаNr(i), то для его вычисления нарисовать сразу алгоритм довольно трудно, хотя имеются для этого все формулы. А кроме того, вовсе не обязательно пытаться напрямую реализовать эти формулы. Часто алгоритмически формулы реализуются не так, как написаны формулы, а реализуется их внутренняя логика.

Попробуем разработать алгоритм модуля, используя метод пошаговой детализации, используя при этом АЯРН (см. юниту 1).

И

Модуль СМОГ

Подготовить Обработать данные за 24 часа Завершить Конец СМОГ

так, на первой стадии детализации решение нашей задачи представим в следующем виде:

На второй стадии детализации получим:

Модуль СМОГ

Получить адрес массива MZНапечатать заголовки Цикл поiна 24 раза Подготовиться к обработке текущего часа

Обработать данные часа Напечатать результаты часа

Конец цикла на 24 раза Завершить Конец СМОГ

На третьей стадии детализации получим:

Модуль СМОГ

Получить адрес массива MZНапечатать заголовки Цикл на 24 раза Подготовиться к обработке текущего часа

Подготовить

Цикл по jна 60 раз обработать данные текущей минуты Конец цикла на 60 раз

Завершить Напечатать результаты часа

Конец цикла на 24 раза Завершить Конец СМОГ

На четвертой стадии детализации получим, введя новую переменную Sumдля накопления в соответствии с формулой (1):

Модуль СМОГ

Получить адрес массива MZНапечатать заголовки Цикл поiна 24 раза Подготовиться к обработке текущего часа

Sum= 0;

Цикл по jна 60 раз НакопитьSumПроверить на нарушение Конец цикла на 60 раз

Sum=Sum/60 Напечатать результаты часа

Конец цикла на 24 раза Завершить Конец СМОГ

Введем вспомогательную переменную Infдля подсчета превышений текущего часа. КогдаInfстанет равным 5, то это и будет указывать на очередное нарушение. Так как ввели новый элемент, то нужно задать себе ряд вопросов. Нужно ли устанавливать его начальное значение? Ясно, что при обнаружении превышения необходимо увеличить его значение на 1. Если это первое превышение, то нужно быть уверенным, что текущее значениеInfравно нулю. Когда же нужно обнулятьInf? Очевидно, это нужно сделать в начале модуля и после того, как наберется 5 превышений подряд.

Введем также переменную Pnrt– для подсчета количества пяти превышений подряд в текущем часе, обнуление которой, очевидно, нужно выполнить перед началом цикла на 60 повторений.

В результате на пятой стадии детализации получим:

Модуль СМОГ

Получить адрес массива MZНапечатать заголовкиInf= 0; Цикл поiна 24 раза

Sum= 0;

Pnrt= 0;

Цикл по jна 60 разSum=Sum+MZ(i,j) ЕслиMZ(i,j) >100 000

то обработать превышение

иначе Inf= 0;

Конец если

Конец цикла на 60 раз

Sum=Sum/60 Напечатать результаты часа

Конец цикла на 24 раза Завершить Конец СМОГ

Детализируем действие «обработать превышение»:

Inf = Inf +1;

Если Inf =5

то Pnrt=Pnrt+1

Inf= 0;

Конец если

В результате на шестой стадии детализации получим:

Модуль СМОГ

Получить адрес массива MZНапечатать заголовкиInf= 0; Цикл поiна 24 раза Читать данные текущего часа

Sum= 0;

Pnrt= 0;

Цикл по jна 60 разSum=Sum+MZ(i,j) ЕслиMZ(i,j) >100 000

то Inf = Inf +1;

Если Inf=5

то Pnrt=Pnrt+1

Inf= 0;

Конец если

иначе Inf= 0;

Конец если

Конец цикла на 60 раз

Sum=Sum/60 Напечатать результаты часа

Конец цикла на 24 раза Завершить Конец СМОГ

Практически алгоритм решения задачи готов. Обратите внимание, что введя вспомогательные переменные Sum,InfиPnrt, мы обошлись без массивов, которые вроде бы должны были иметь место, исходя из математической постановки задачи. Поскольку в содержательной постановке не указано, что обработанная информация о каждом часе должна хранится (она просто выдается на печать), то это позволило нам не хранить «лишнюю информацию», а это повышает эффективность нашего модуля.

А теперь приступим к программированию модуля на Си. Ниже представлен текст программы модуля (функции) вместе с отладочным вариантом функции main:

//Отладка модуля СМОГ

# include <stdio.h>

# include <conio.h>

# define N1 3

# define N2 12

Соседние файлы в папке attachments_05-09-2012_18-55-54