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

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

Используя язык высокого уровня (такой как Фортран) программисты могли писать программы до несколько тысяч строк длиной. Однако язык программирования, легко понимаемый в коротких программах, когда дело касается больших программ, становится нечитабельным (и неуправляемым). Избавление от таких неструктурированных программ пришло после создания в 1960 году языков структурного программирования. К ним относятся языки Алгол, Паскаль и С.

Структурное программирование подразумевает точно обозначенные управляющие структуры, программные блоки, отсутствие инструкций GOTO, автономные подпрограммы, в которых поддерживается рекурсия и локальные переменные. Главным в структурном программировании является возможность разбиения программы на составляющие ее элементы. Используя структурное программирование, средний программист может создавать и поддерживать программы свыше 50 000 строк длиной.

Структурное программирование тесно связано такими понятиями как «нисходящее проектирование» и «модульное программирование».

Метод нисходящего проектирования предполагает последовательное разложение функции обработки данных на простые функциональные элементы («сверху-вниз»).

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

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

1) определяются цели автоматизации предметной области и их иерархия;

2) устанавливается состав приложений (задач обработки), обеспечивающих реализацию поставленных целей;

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

4) определяются необходимые для решения задач функции обработки данных;

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

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

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

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

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

· линейной (следование);

· нелинейной (развилка);

· циклической (цикл, или повторение).

Эта теорема была сформулирована в 1966 г. Боймом и Якопини (Corrado Bohm, Guiseppe Jacopini). Главная идея теоремы – преобразовать каждую часть программы в одну из трех основных структур или их комбинацию так, чтобы неструктурированная часть программы уменьшилась. После достаточного числа таких преобразований оставшаяся неструктурированной часть либо исчезнет, либо становится ненужной. В теореме доказывается, что в результате получится программа, эквивалентная исходной и использующая лишь упоминавшиеся основные структуры.

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

В алгоритмическом языке С (С++) для реализации структурного кодирования используются следующие операторы:

· составной-оператор;

· оператор-выражение;

· оператор-выбора;

· оператор-с-меткой;

· оператор-перехода;

· оператор-итерации;

· asm-оператор;

· объявление (только в С++).

Структура «следование» (рис. 5.1, а) реализуется составным оператором, оператором-выражение, asm-оператором и др.

Составной оператор, или блок, представляет собой список (возможно, пустой) операторов, заключенных в фигурные скобки {…}. Синтаксически блок рассматривается как единый оператор, но он влияет на контекст идентификаторов, объявленных в нем. Блоки могут иметь любую глубину вложенности.

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

<выражение>;

Компилятор языка C++ выполняет операторы-выражения, вычисляя выражения. Все побочные эффекты от этого вычисления завершаются до начала выполнения следующего оператора. Большинство операторов-выражений представляют собой операторы присваивания или вызовы функций (например, printf(), scanf()). Особым случаем является пустой оператор, состоящий из одной точки с запятой (;). Пустой оператор не выполняет никаких действий. Однако он полезен в тех случаях, когда синтаксис C++ ожидает наличия некоторого оператора, но по программе он не требуется (например, бесконечный цикл for).

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

Структура «развилка» (рис. 5.1, б, в) реализуется операторами выбора. Операторы выбора, или операторы управления потоком, выполняют выбор одной из альтернативных ветвей программы, проверяя для этого определенные значения. Существует два типа операторов выбора: if...else и switch.

Базовый оператор if (рис. 5.1, б) имеет следующий формат:

if(условное_выражение)оператор_если_"истина"<else>оператор_если_"ложь";


Язык C++ в отличие от, например, языка Паскаль не имеет специального булевого типа данных. В условных проверках роль такого типа может играть целочисленная переменная или указатель на тип. Условное_выражение должно быть записано в круглых скобках. Это выражение вычисляется. Если оно является нулевым (или пустым в случае типа указателя), мы говорим, что условное_выражение ложно (false ); в противном случае оно истинно (true).

Если предложение else отсутствует, а условное_выражение дает значение "истина", то выполняется оператор_если_"истина"; в противном случае он игнорируется.

Если задано предложение <else> оператор_если_"ложь", а условное_выражение дает значение "истина", то выполняется оператор_если_"истина"; в противном случае выполняется оператор_если"ложь".

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

if (!ptr)... или if (ptr = = 0)....

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

Например, запись:

if (x == 1)

if (y == 1) puts("x=1 и y=1");

else puts("x!= 1");

дает неверное решение, так как else, независимо от стиля записи, сопоставляется не с первым, а со вторым if. Поэтому правильная запись последней строчки должна быть такой:

else puts("x=1 и y!=1");

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

if (x = = 1)

{

if (y = = 1) puts("x = и y=1");

}

else puts("x!= 1"); // правильное решение

Оператор switch (см. рис. 5.1, в) использует следующий базовый формат:

switch (переключающее_выражение) case_оператор;

Он позволяет передавать управление одному из нескольких операторов с меткой case в зависимости от значения переключающего_выражения. Любой оператор в case_операторе (включая пустой оператор) может быть помечен одной (или более) меткой варианта:

case константное_выражение_i: case_оператор_i;

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

Допускается иметь в одном операторе switch повторяющиеся константы case.

Оператор может иметь также не более одной метки default:

default: оператор_умолчания;

После вычисления переключающего_выражения выполняется сопоставление результата с одним из константных_выражений_i. Если найдено соответствие, то управление передается case_оператору_i с меткой, для которой найдено соответствие. Если соответствия не найдено и имеется метка default, то управление передается оператору_умолчания. Если соответствие не найдено, а метка default отсутствует, то никакие операторы не выполняются. Для того чтобы остановить выполнение группы операторов для конкретного варианта, следует использовать оператор break.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  




Подборка статей по вашей теме: