Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Проектирование программ и программирование на C++. Структурное программирование

.pdf
Скачиваний:
3
Добавлен:
12.11.2023
Размер:
3.86 Mб
Скачать

Отличия макроса от функции:

1.Определение функции присутствует в программе в одном эк­ земпляре, коды, формируемые макросом, вставляются в программу столько раз, сколько используется макрос. В этом отношении макро­ сы похожи на inline-функции, но подстановка для макроса выполня­ ется всегда.

2.Функция определена для данных того типа, который указан

вспецификации и возвращает значения только одного конкретного типа. Макрос пригоден для обработки параметров любого типа. Тип полученного значения зависит от типов параметров и самих выраже­ ний. В примерах 1 и 2 в качестве параметров могут использоваться любые целочисленные или вещественные типы.

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

#define max(a,b) (a<b?b:a)

#define t(e) e*3

#define PRN(c) cout<<"\n"«#c«" равно ,,;cout«c;

#define E x*x #include<iostream.h> void main()

{

int x=2;

PRN(max(++x,++x);

PRN(t(x));

PRN(t(x+x));

PRN(t(x+x)/3);

PRN(E);

}

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

Примеры подстановок параметров макроса:

P R N (m ax(+ + х ,+ + х );

P R N (t (х ));

P R N ( t (х + х ) );

P R N ( t (х + х )/ 3 ) ;

P RN(E) ;

1- я подстановка

cout<<"\n"<<"m ax (++х, ++х) " « " равно " ;c o u t< < m ax(+ + х ,+ + х );

2- я подстановка

c o u t< < //\ n //<<//max (+ + х,+ + х) "<<" равно

"; cou t< < (++х<++х?++х:++х) ; / / т.е. х увели­ чится на 3 (=5)

1- я подстановка

c o u t « " \ n " « " t (х) " « " равно " ; c o u t « t (х)

2-

я подстановка

 

c o u t< < " \n " < < " t( х ) " < < " равно

 

c o u t « x * 3 ; //х = 5 , результат 15

1-

я подстановка

 

c o u t< < " \n " < < " t (х+х) ” « "

равно " ; c o u t «

t (х+х)

 

2-

я подстановка

 

c o u t< < /'\n " < < //t (х+х) ” « "

равно

 

cou t< < (х+х) *3; //х = 5 , результат 30

1-

я подстановка

 

c o u t< < " \n " < < " t (х+х) " << " равно //; c o u t «

t (х + х )/3

 

2-

я подстановка

 

c o u t< < " \n //<<//t (х + х )" « "

равно

 

co u t< < (х+х) * 3 /3 ; / / результат (5+5)-3/3=10

1-

я подстановка

 

c o u t< < " \n //<<"E,/<<#/ равно ";cout<<E ;

2-

я подстановка

 

c o u t < < //\ n /,< < /#E'/< < /'р а в н о "; c o u t < < x * x ; / / результат 25

Результаты:

т а х ( + + х , + + х ) равно 5

t

(х ) равно 15

t

(х+х) равно 20

t( х + х ) / 3 равно 10

Еравно 25.

21. ТЕХНОЛОГИЯ СОЗДАНИЯ ПРОГРАММ 21.1. Проектирование программы

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

Этапы создания программы:

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

-описание исходных данных и результатов;

-описание задачи, реализуемой программой;

-способ обращения к программе;

-описание возможных аварийных ситуаций и ошибок пользователя.

2.Разработка внутренних структур данных. Большинство ал­ горитмов зависит от способа организации данных (статические или динамические, массивы, списки или деревья и т.п.).

3.Проектирование программы, которое заключается в опреде­ лении общей структуры и способов взаимодействия модулей. На дан­ ном этапе может применяться технология нисходящего проектирова­ ния, при котором задачу разбивают на подзадачи меньшей сложно­ сти. На этом этапе очень важной является спецификация интерфей­ сов, т.е. способов взаимодействия подзадач. Для каждой подзадачи составляется внешняя спецификация, аналогичная п. 1. На этом же этапе решаются вопросы разбиения программы на модули, взаимо­ действие этих модулей должно быть минимальным. На более низкий уровень проектирования переходят только после окончания проекти­ рования верхнего уровня. Алгоритмы для модулей записывают

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

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

5. Нисходящее тестирование. Проектирование и программиро­ вание сопровождаются тестированием. Цель процесса тестирования - определение наличия ошибки, нахождение места ошибки, ее причи­ ны и соответствующие изменения программы - исправление. Тест - это набор исходных данных, для которых заранее известен результат. Тест, выявивший ошибку, считается успешным. Процесс исправле­ ния ошибок в программе называется отладкой, исправляются ошиб­ ки, обнаруженные при тестировании. Отладка программы заканчива­ ется, когда достаточное количество тестов выполнилось неуспешно, т.е. программа на них выдала правильные результаты.

Цель тестирования - показать, что программа работает правиль­ но и удовлетворяет всем проектным спецификациям. Чем больше ошибок обнаружено на начальных стадиях тестирования, тем меньше их остается в программе. Чем меньше ошибок осталось в программе, тем сложнее искать каждую из этих ошибок.

Идея нисходящего тестирования заключается в том, что к тести­ рованию программы надо приступать еще до того, как завершено ее проектирование. Только после того как проверен и отлажен один уровень программы, можно приступать к программированию и тес­ тированию следующего уровня.

Для исчерпывающего тестирования рекомендуется проверить:

-каждую ветвь алгоритма;

-граничные условия;

-ошибочные исходные данные.

21.2.Кодирование и документирование программы

Главная цель, к которой нужно стремиться при написании программы, - это получение легко читаемой программы простой структуры. Для этого написание программы рекомендуется начинать

сзаписи на естественном языке или в виде блок-схем ее укрупненно­ го алгоритма (что и как должна делать программа). Алгоритм надо записать как последовательность законченных действий. Каждое за­ конченное действие оформляется в виде функции. Каждая функция должна решать одну задачу. Тело функции не должно быть длинным (30-50 строк), так как сложно разбираться в длинной программе, ко­ торая содержит длинные функции. Если некоторые действия повто­ ряются более одного раза, их тоже рекомендуется оформить как функцию. Короткие функции лучше оформить как подставляемые функции (inline).

Имена переменных выбираются таким образом, чтобы можно было понять, что делает эта переменная, например, сумму обознача­

ют Sum, Summa или S, массив - A r r a y или Агг и т.п. Для счетчи­ ков коротких циклов лучше использовать однобуквенные имена, на­ пример i или j . Чем больше область видимости переменной, тем более длинное у нее имя. Не рекомендуется использовать имена, на­ чинающиеся с символа подчеркивания, имена типов, идентификато­ ры, совпадающие с именами стандартной библиотеки C++.

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

Глобальные переменные лучше не использовать. Если использо­ вание глобальной переменной необходимо, то лучше сделать ее статиче­ ской, тогда область ее видимости будет ограничена одним файлом.

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

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

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

Нельзя возвращать из функции ссылку на локальную пере­ менную, так как эта переменная будет автоматически уничтожаться при выходе из функции. Также не рекомендуется возвращать ссылку на динамическую локальную переменную, созданную с помощью

операции new или функции malloc ()

Если в программе используются числа, например размеры массивов, то для них лучше использовать символические имена - константы или перечисления. Это делает программу более понятной, кроме того, в такую программу легче будет вносить изменения, так как достаточно будет изменить константу в одном месте.

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

венство нулю,

так как это не имеет смысла. Например, условие

if (ok!=0)

лучше записать как if (ok)

Более короткую ветвь

оператора if рекомендуют помещать сверху, иначе управляющая структура может не поместиться на экране.

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

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

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

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

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

//--------------------------------------------------------------

• Вложенные блоки должны иметь отступы в 3-4 символа, при­ чем блоки одного уровня вложенности должны быть выровнены по вертикали. Закрывающая фигурная скобка должна находиться под открывающей.

СПИСОК ЛИТЕРАТУРЫ

1.Буч Г. Объектно ориентированный анализ и проектирование

спримерами приложений на C++. - М ; СПб.: Бином, 2001. - 560 с.

2.Лаптев В.В., Морозов А.В., Бокова А.В. C++. Объектноориентированное программирование. Задачи и упражнения. - СПб.: Питер, 2007. -2 8 8 с.

3.Ноткин А.М. Технология объектно ориентированного про­ граммирования на языке C++. - Пермь: Изд-во Перм. гос. техн. ун-та, 2007.- 172 с.

4.Павловская Т.А., Щупак Ю.А. C++. Объектно ориентиро­ ванное программирование: практикум. - СПб.: Питер, 2008. - 265 с.

5.Павловская Т.А. C/C++. Программирование на языке высоко­ го уровня. - СПб.: Питер, 2009. - 461 с.

6.Пышкин Е.В. Основные концепции и механизмы ООП. - СПб.: БХВ-Петербург, 2005. - 640 с.

7.Хорев П.Б. Технологии ООП. - М.: Академия, 2008.-448 с.

Учебное издание

Викентьева Ольга Леонидовна, Гусин Александр Николаевич, Полякова Ольга Андреевна

ПРОЕКТИРОВАНИЕ ПРОГРАММ И ПРОГРАММИРОВАНИЕ НА C++

Часть I СТРУКТУРНОЕ ПРОГРАММИРОВАНИЕ

Учебное пособие

Корректор В. В. Мальцева

Подписано в печать 31.01.2012. Формат 60x90/16. Уел. печ. л. 8,75. Тираж 25 экз. Заказ 11/2012.

Издательство Пермского национального исследовательского

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

Адрес: 614990, г. Пермь, Комсомольский пр., 29, к. 113. Тел. (342)219-80-33.

Соседние файлы в папке книги