Запись алгоритмов с помощью диаграмм Несси - Шнейдермана (структограмм ) Язык Си является достаточно развитым для того, чтобы вообще обойтись без каких-либо особых способов записи алгоритмов. Однако для тех, кто только начинает программировать, может понадобится более наглядное средство иллюстрации алгоритмов. Раньше для таких целей широко использовались так называемые блок-схемы. Однако их применение очень легко может привести к появлению программ с неоправданно сложной структурой, в которой трудно разобраться. Для описания логики работы программ вместо блок-схем можно использовать диаграммы Несси - Шнейдермана, которые отличаются тем, что пригодны для описания только структуированных программ (состоящих из базовых логических структур). Рассмотрим базовые логические структуры и их представление в виде структограмм. Процесс - один или несколько операторов, выполнение которых происходит последовательно. Изображается в виде прямоугольника, управление в который передается сверху, а выходит из него снизу: Проверка условия - управление передается в один из нижних процессов: Цикл - пока. Процесс повторяется несколько раз пока истинно условие. 9.4. Некоторые приемы программирования Рассмотрим некоторые типовые приемы программирования и использования рассмотренных выше операторов. Для подсчета различных объектов, получающихся в процессе работы программы используют счетчики, которые представляют собой переменные целого типа, меняющие свои значения в процессе выполнения счета. Использование счетчика покажем на примере программы, которая подсчитывает количество отрицательных значений функции sin( x ) для x меняющегося от xn до xk с шагом h. Вначале запишем алгоритм с помощью диаграммы Несси-Шнейдермана. Теперь можно рассмотреть программу на языке Си : #include <math.h> #include <stdio.h> /* использование счетчика */ void main( void ) { double xn, xk, h, x; int Count; /* счетчик */ printf( "Введите xn, xk, h \n" ); scanf( "%lf%lf%lf", &xn, &xk, &h ); x = xn; Count = 0; /* инициализация счетчика */ while( x <= xk ) { if( sin(x) < 0 ) Count++; /* выполнение счета */ x += h; } printf( "Число отрицательных синусов = %d\n", Count); } Довольно часто в программах приходится вычислять суммы и произведения. При нахождении суммы надо выделить переменную для ее хранения, обнулить ее, затем циклически добавлять к ней очередное значение. Найдем сумму отрицательных значений функции sin(x) для x меняющегося от xn до xk с шагом h. Следующая программа решает эту задачу: #include <math.h> #include <stdio.h> /* нахождение суммы отрицательных значений синуса */ void main( void ) { double xn, xk, h, x, sum; printf( "Введите xn, xk, h \n" ); scanf( "%lf%lf%lf", &xn, &xk, &h ); x = xn; sum = 0; /* обнуление суммы */ while( x <= xk ) { if( sin(x)<0 ) sum += sin(x); /* вычисление суммы */ x += h; } printf( "Сумма = %lf\n", sum); } Для повышения эффективности программы можно описать еще одну переменную, например sinus и изменить оператор вычисления суммы: if( ( sinus = sin(x) ) < 0 ) sum += sinus; В этом случае экономится время за счет однократного вычисления синуса. Для вычисления произведения необходимо выделить переменную для его хранения, занести в эту переменную единицу и в цикле домножать ее на очередное значение. Во многих сложных алгоритмах требуется запоминать факты наступления различных событий, связанных с процессом выполнения программы. Для этих целей используются флаги, которые представляют собой переменные целого типа, принимающие определенные значения в зависимости от этих событий. Простейший пример использования флагов иллюстрирует фрагмент программы, моделирующий работу оператора if с помощью оператора while. Иными словами, показывается, что при реализации программ можно вообще обойтись без оператора if. Действительно, рассмотрим следующий оператор if: if( a > b ) k = sin(x); else k = x * x; Очевидно, такие же действия будет выполнять группа операторов, использующая флаг и приведенная ниже: fl = 1; /* флаг */ while ( a > b && fl ) { k = sin(x); fl = 0; } while ( fl ) { k = x * x; fl = 0; } В данном случае флаг сигнализирует о выборе одной из альтернатив оператора if. Следующая программа устанавливает факт наличия отрицательных значений sin(x) для x меняющегося от xn до xk c шагом h : #include <math.h> #include <stdio.h> /* использование флагов */ void main( void ) { double xn, xk, h, x; int minus; /* флаг */ printf( "Введите xn, xk, h \n" ); scanf( "%lf%lf%lf", &xn, &xk, &h ); x = xn; minus = 0; /* предполагается, что нет не одного отрицательного значения */ while( x <= xk ) { if( sin(x) < 0 ) minus = 1; x += h; } if( minus ) printf( "Имеются отрицательные значения\n" ); else printf( "Все синусы положительные\n" ); } В данной программе флаг устанавливается в 1, как только появляется отрицательный синус. Оператор прерывания цикла Предыдущая программа имеет существенный недостаток: перебираются все значения синуса, хотя цикл можно остановить, когда появится первое отрицательное значение. Этот недостаток можно исправить, как показано в следующем фрагменте: x = xn; minus = 0; while( x < xk && !minus ) { ... } В языке Си есть специальный оператор для прерывания цикла. Это оператор "break;". Выполнение его в программе немедленно прерывает цикл, в котором он находится и управление передается на следующий за циклом оператор. Используя оператор break, цикл предыдущей программы можно переписать в виде: x = xn; minus = 0; while( x < xn ) { if( sin(x) < 0 ) { minus = 1; break; } x += h; } |