I . Приёмы построения алгоритмов



Для создания работающей программы разработчик должен пройти три основных этапа:

проектирование – построение алгоритма решения поставленной задачи;

кодирование – перевод алгоритма на язык программирования;

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

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

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

метод последовательной детализации;

Сборочный метод.

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

Метод последовательной детализации можно разбить на три этапа:

1. Строится основной алгоритм решения общей задачи, т.е. исходная задача разбивается на логически завершённые подзадачи.

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

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

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

 

Понятие функции

2.1. Определение функции

 

В любом языке программирования алгоритм решения подзадачи можно описать в виде отдельной подпрограммы. В языке С++ каждая подпрограмма называется функцией – это конструкция языка программирования, связанная с решением конкретной части поставленной задачи.Функция – это самостоятельная единица программы. В языке С++ функции разделяются на библиотечные (описаны в головных файлах stdio.h, math.h, dos.h, string.h и др.) и пользовательские (разработаны самим программистом). В языке С++ всегда есть хотя бы одна функция – главная функция main().

Определение функции состоит из описания заголовка и тела функции. После заголовка функции точка с запятой не ставится. Общий вид функции:

 


<тип_возвращаемого_результата><имя_функции>(<список_формальных_параметров>)

{

        <тело_функции>

}

<тип_возвращаемого_результата> – тип результата работы функции, может быть целочисленным, вещественным, символьным или указателем на любой допустимый тип. Результат работы функции возвращается с помощью оператора return и записывается сразу после этого оператора в виде переменной или выражения, допустимого в языке С++. Если результат возвращается с помощью выражения, то это выражение записывается после оператора return в круглых скобках. Если в заголовке функции тип возвращаемого результата не указан, то по умолчанию это тип int. Функцию, которая возвращает результат с помощью оператора return, можно использовать в выражениях. Если функция не возвращает никакого результата (например, с помощью функции производится вывод на печать элементов массива), то типом возвращаемого результата будет тип void и в теле функции не должен присутствовать оператор return. В описании метода последовательной детализации результат работы функции называется выходным параметром.

<имя_функции> – идентификатор (применительно к методу последовательной детализации – это уникальное имя некоторого вспомогательного алгоритма), при помощи которого функцию можно вызвать для выполнения. Надо стараться задавать такие имена пользовательским функциям, которые не совпадали бы с ключевыми словами языка С++.

<список_формальных_параметров> определяет типы  и имена формальных параметров. В <список_формальных_параметров> параметры разделяются запятыми. С точки зрения построения алгоритмов методом последовательной детализации, формальные параметры – это входные данные, от которых функционально зависит решение конкретной подзадачи. Таким образом, формальные параметры – это переменные, которые позволяют произвести обмен между вызываемой (решает подзадачу) и вызывающей функциями. <список_формальных_параметров> может отсутствовать. В этом случае в заголовке функции после ее имени пишутся «пустые» скобки.

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

 

Область видимости переменных

Каждая переменная, используемая в теле функции, должна быть объявлена в теле функции, в списке формальных параметров или вне функции. Переменные, используемые в функциях:

глобальные (внешние): объявленные в программе либо как внешние (т.е. до заголовка главной функции main() с ключевым словом extern), либо как статические внешние;

локальные (внутренние): объявленные, доступные и используемые только в теле функции;

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

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

int x;          // глобальное x (по отношению к функции func())

void func()

{

int x;   // первое локальное x “прячет” глобальное x

x = 1;  // присвоить первому локальному x значение 1

{

     int x;  // прячет первое локальное x

     x = 2; // присвоить второму локальному x значение 2

}

x = 3;   // присвоить первому локальному x значение 3

}

int* p = &x; // взять адрес глобального x (по отношению к функции

                  // func())

Скрытие имен неизбежно при написании больших программ. В этом случае легко не заметить, что имя скрыто и некоторые ошибки, возникающие из-за этого, очень трудно обнаружить. Следовательно, от скрытия имен нужно уходить при написании программ. Использование для глобальных переменных часто употребляемых имен вроде i или x как раз и приводит к ошибкам, вроде переобъявления переменной.

При объявлении переменная создается, когда встречается её описание, и уничтожается, когда её имя выходит из области видимости. Переменные с глобальными именами создаются и инициализируются только один раз и “живут” до завершения программы. Объекты, объявленные с ключевым словом static, ведут себя именно таким образом:

void func()

{

int b = 1;       // инициализируется при каждом вызове func()

static int c = 1; // инициализируется только один раз

printf("a = %i\n", a++);

printf("b = %i\n", b++);

printf("c = %i\n", c++);

}

 

extern int a = 1;

int main()

{

while (a<4)

func();

return 1;

}

 

Функция func() вызывается в цикле while и производит вывод на экран следующее:

a = 1 b = 1 c = 1

a = 2 b = 1 c = 2

a = 3 b = 1 c = 3

Явно неинициализированная статическая (static) переменная неявно инициализируется нулем.

 

Параметры функции

 

Параметры функции определяются списком формальных параметров. Область видимости формальных параметров – те­ло функции. Имена формальных параметров используются в операторах тела функции. Формальными параметрами могут быть только идентификаторы.

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

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

1) количества формальных и фактических параметров;

2) последовательности формальных и соответствующих им фактических пара­метров (первому формальному параметру соответствует первый фактический, второму – второй и т. д.);

3) типов формальных и соответствующих им фактических параметров.

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

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

<имя_типа_параметра> <идентификатор_параметра>

Здесь <имя_типа_параметра> – имя допустимого типа значений, стандартного или определенного пользователем; <идентификатор_параметра> – имя формального параметра.

Отсутствие имени типа параметра в списке формальных параметров является синтаксической ошибкой.

 

Описание функции

 

Пример описания функции:

int func(int a, char *str, float b[])

{

    …//операторы тела функции

}

Строка int func(int a, char *str, float b[]) – это заголовок функции; функция возвращает целочисленный результат, func – это имя функции, a, str, float b[] – формальные параметры функции (a – целочисленная переменная, str – указатель на тип char, т.е. строка, b – имя одномерного массива значений типа float).

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

 

Организация вызова функции

 

Форма вызова функции:

<имя_функции>(<список_фактических_параметров>);

Если при описании функции список формальных параметров отсутствовал, то при вызове функции <список_фактических_параметров> так же должен отсутствовать. При вызове функции ей передается управление. Опишем организацию вызова функции.

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

При вызове функции стек заполняется следующим образом:

1. В стек помещается адрес вызова функции.

2. В стек копируются значения переданных в функцию фактических

параметров.

3. Выполняются операторы тела функции.

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

5. Из стека забирается адрес точки вызова функции, и по этому адресу происходит возврат в вызывающую функцию.

Затем выполняются операторы вызывающей функции, следующие за строкой вызова функции.

 


Дата добавления: 2019-11-25; просмотров: 194; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!