Главная Учебники - Разные Лекции (разные) - часть 34
|
А.А. Богуславский, С.М. Соколов Основы программирования на языкеСи++ Часть 1. Введение в программирование
на языке Си++
(длястудентовфизико-математическихфакультетов педагогических институтов) Коломна, 2002 2 ББК 32.97я73
Рекомендовано кизданию УДК 681.142.2(075.8) редакционно-издательскимсоветом Б 73 Коломенскогогосударственного педагогического института Богуславский А.А., СоколовС.М. Б73 ОсновыпрограммированиянаязыкеСи++: Длястудентовфизико- математических факультетовпедагогическихинститутов. –Коломна: КГПИ, 2002. – 490 с. Пособие предназначенодляобучениястудентов, обладающих навыкамиполь- зовательской работынаперсональномкомпьютере, основнымпонятиямиметодам современного практическогопрограммирования. Предметомизучениякурсаявляется объектно-ориентированноепрограммированиенаязыкеСи++ всредесовременных 32-хразрядныхоперационныхсистемсемейства Windows. Программакурсаразбита на 4 части: (1) ВведениевпрограммированиенаязыкеСи++; (2) Основыпрограмми- рования трехмернойграфики; (3) Объектно-ориентированное программированиена языке Си++ и (4) Программированиедля Microsoft Windows сиспользованием Visual C++ ибиблиотекиклассов MFC. После изучениякурсастудентполучаетдостаточнополноепредставлениео содержании современногообъектно-ориентированногопрограммирования, обуст- ройстве современныхоперационныхсистем Win32 иособытийно-управляемомпро- граммировании. Напрактическихзанятияхвырабатываютсянавыкипрограммирова- ния наСи++ винтегрированной средеразработки Microsoft Visual C++ 5.0. Рецензенты: И.П. Гиривенко–к.т.н., доцент, зав. кафедройинформатикиивычислительнойтех- ники Рязанскогогосударственногопедагогическогоуниверситета им. С.А. Есенина. А.А. Шамов–к.х.н., доценткафедрытеоретическойфизикиКоломенскогогосу- дарственного педагогическогоинститута. 3 СОДЕРЖАНИЕ
КРАТКОЕ ОПИСАНИЕ УЧЕБНОГО КУРСА "ОСНОВЫ ПРОГРАММИРОВАНИЯ
НА ЯЗЫКЕ СИ++" ..........................................................................................................................5
ЛЕКЦИЯ 1. ОСНОВЫ СИ++.........................................................................................................7
1. НЕСКОЛЬКО ЗАМЕЧАНИЙОНАЗНАЧЕНИИПРОГРАММИРОВАНИЯ................................................7 2. ПРОИСХОЖДЕНИЕ ЯЗЫКАСИ++...................................................................................................9 3. СТАНДАРТ ANSI СИ++ ................................................................................................................9 4. СРЕДА РАЗРАБОТКИMICROSOFT DEVELOPER STUDIO VISUAL С++...........................................10 5. ПРИМЕР ПРОГРАММЫНАСИ++ .................................................................................................10 6. ВЫПОЛНЕНИЕ ВВОДА/ВЫВОДА ДАННЫХИПРИСВАИВАНИЕЗНАЧЕНИЙ....................................12 7. УПРАВЛЕНИЕ ПОРЯДКОМВЫПОЛНЕНИЯКОМАНДСПОМОЩЬЮОПЕРАТОРА IF ........................13 8. ОФОРМЛЕНИЕ ИСХОДНОГОТЕКСТА...........................................................................................15 9. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................15 10. УПРАЖНЕНИЯ ...........................................................................................................................15 ЛЕКЦИЯ 2. ПЕРЕМЕННЫЕ, ТИПЫ ДАННЫХ И ВЫРАЖЕНИЯ....................................18
1. ИДЕНТИФИКАТОРЫ ....................................................................................................................18 2. ТИПЫ ДАННЫХ...........................................................................................................................18 3. ВЫВОД ВЕЩЕСТВЕННЫХЧИСЕЛНАЭКРАН................................................................................22 4. ОПИСАНИЯ, КОНСТАНТЫ ИПЕРЕЧИСЛЕНИЯ..............................................................................24 5. ПРИСВАИВАНИЕ ИВЫРАЖЕНИЯ.................................................................................................26 6. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................28 7. УПРАЖНЕНИЯ .............................................................................................................................28 8. ПРИЛОЖЕНИЯ .............................................................................................................................29 ЛЕКЦИЯ 3. ФУНКЦИИ И ПРОЦЕДУРНАЯ АБСТРАКЦИЯ .............................................31
1. НАЗНАЧЕНИЕ ПОДПРОГРАММ.....................................................................................................31 2. ОПРЕДЕЛЕНИЕ НОВЫХФУНКЦИЙ...............................................................................................31 3. СПОСОБЫ ПЕРЕДАЧИПАРАМЕТРОВВНУТРЬФУНКЦИЙ..............................................................33 4. ПОЛИМОРФИЗМ ИПЕРЕГРУЗКАФУНКЦИЙ..................................................................................35 5. ПРОЦЕДУРНАЯ АБСТРАКЦИЯИ"ХОРОШИЙ" СТИЛЬ ПРОГРАММИРОВАНИЯ...............................36 6. МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ...........................................................................................36 7. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................38 8. УПРАЖНЕНИЯ .............................................................................................................................39 ЛЕКЦИЯ 4. ТЕКСТОВЫЕ ФАЙЛЫ И ПОТОКИ ВВОДА/ВЫВОДА ................................41
1. НАЗНАЧЕНИЕ ФАЙЛОВ................................................................................................................41 2. ПОТОКИ ВВОДА/ВЫВОДА ...........................................................................................................41 3. ПРОВЕРКА ОШИБОКВЫПОЛНЕНИЯФАЙЛОВЫХОПЕРАЦИЙ.......................................................43 4. СИМВОЛЬНЫЙ ВВОД/ВЫВОД ......................................................................................................44 5. ПРОВЕРКА ДОСТИЖЕНИЯКОНЦАФАЙЛАПРИОПЕРАЦИЯХВВОДА............................................45 6. ПЕРЕДАЧА ПОТОКОВ ФУНКЦИЯМВКАЧЕСТВЕПАРАМЕТРОВ.....................................................47 7. ОПЕРАТОРЫ ВВОДА/ВЫВОДА ">>" И "<<" .................................................................................48 8. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................50 9. УПРАЖНЕНИЯ .............................................................................................................................50 ЛЕКЦИЯ 5. ОПЕРАТОРЫ ВЕТВЛЕНИЯ И ЦИКЛЫ ...........................................................52
1. ЛОГИЧЕСКИЕ ЗНАЧЕНИЯ, ВЫРАЖЕНИЯ ИФУНКЦИИ...................................................................52 2. ЦИКЛЫ "FOR", "WHILE" И "DO...WHILE" .....................................................................................53 3. МНОЖЕСТВЕННОЕ ВЕТВЛЕНИЕИОПЕРАТОР"SWITCH" ..............................................................55 4. БЛОКИ ИОБЛАСТЬВИДИМОСТИПЕРЕМЕННЫХ..........................................................................56 4 5. ЗАМЕЧАНИЕ ОВЛОЖЕННЫХЦИКЛАХ.........................................................................................59 6. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................59 7. УПРАЖНЕНИЯ .............................................................................................................................60 ЛЕКЦИЯ 6. МАССИВЫ И СИМВОЛЬНЫЕ СТРОКИ.........................................................63
1. НАЗНАЧЕНИЕ МАССИВОВ...........................................................................................................63 2. ПЕРЕДАЧА МАССИВОВВКАЧЕСТВЕПАРАМЕТРОВФУНКЦИЙ....................................................66 3. СОРТИРОВКА МАССИВОВ...........................................................................................................68 4. ДВУМЕРНЫЕ МАССИВЫ..............................................................................................................69 5. СИМВОЛЬНЫЕ СТРОКИ...............................................................................................................70 6. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................73 7. УПРАЖНЕНИЯ .............................................................................................................................73 ЛЕКЦИЯ 7. УКАЗАТЕЛИ............................................................................................................75
1. НАЗНАЧЕНИЕ УКАЗАТЕЛЕЙ........................................................................................................75 2. ПЕРЕМЕННЫЕ ТИПА"МАССИВ". АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИСУКАЗАТЕЛЯМИ....................79 3. ДИНАМИЧЕСКИЕ МАССИВЫ.......................................................................................................81 4. АВТОМАТИЧЕСКИЕ ИДИНАМИЧЕСКИЕПЕРЕМЕННЫЕ................................................................82 5. СВЯЗНЫЕ СПИСКИ......................................................................................................................82 6. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................86 7. УПРАЖНЕНИЯ .............................................................................................................................87 ЛЕКЦИЯ 8. РЕКУРСИЯ...............................................................................................................89
1. ПОНЯТИЕ РЕКУРСИИ...................................................................................................................89 2. ПРОСТОЙ ПРИМЕРРЕКУРСИИ.....................................................................................................89 3. КАК ВЫПОЛНЯЕТСЯРЕКУРСИВНЫЙВЫЗОВ................................................................................90 4. ЕЩЕ ТРИПРИМЕРАРЕКУРСИИ....................................................................................................92 5. РЕКУРСИЯ ИЦИКЛЫ....................................................................................................................93 6. РЕКУРСИЯ ВСТРУКТУРАХДАННЫХ............................................................................................94 7. РЕКУРСИВНАЯ РЕАЛИЗАЦИЯАЛГОРИТМАБЫСТРОЙСОРТИРОВКИ.............................................94 8. СВОДКА РЕЗУЛЬТАТОВ...............................................................................................................97 9. УПРАЖНЕНИЯ .............................................................................................................................97 ЛЕКЦИЯ 9. СОСТАВНЫЕ ТИПЫ ДАННЫХ.......................................................................100
1. НАЗНАЧЕНИЕ СОСТАВНЫХТИПОВДАННЫХ............................................................................100 2. ОПИСАНИЕ ИИНИЦИАЛИЗАЦИЯСТРУКТУР..............................................................................100 3. ДОСТУП ККОМПОНЕНТАМСТРУКТУРЫЧЕРЕЗУКАЗАТЕЛЬ......................................................103 4. МАССИВЫ ИСТРУКТУРЫ..........................................................................................................104 5. ПЕРЕГРУЗКА ОПЕРАТОРОВ........................................................................................................105 6. ПРИМЕНЕНИЕ СТРУКТУРДЛЯРЕАЛИЗАЦИИСТЕКА ..................................................................107 7. СВОДКА РЕЗУЛЬТАТОВ.............................................................................................................111 8. УПРАЖНЕНИЯ ...........................................................................................................................112 ПРИЛОЖЕНИЕ. КРАТКОЕ РУКОВОДСТВО ПО СРЕДЕ РАЗРАБОТКИ DEVELOPER
STUDIO VISUAL C++..................................................................................................................113
1. СОЗДАНИЕ НОВОГОПРОЕКТА...................................................................................................113 2. ДОБАВЛЕНИЕ ВПРОЕКТНОВОГОИСХОДНОГОФАЙЛА.............................................................114 3. СБОРКА ПРОЕКТА.....................................................................................................................115 4. ЗАПУСК НОВОГОПРИЛОЖЕНИЯ................................................................................................116 ЛИТЕРАТУРА.............................................................................................................................117
5 Краткое описание учебного курса "Основы программиро-
вания на языке Си++"
Развитие современныхтехнологийпрограммированияпредполагаетвладение программистом широкимнаборомпрактическихнавыков, средикоторыходнимииз основных можносчитатьзнаниеязыкапрограммирования, средыразработкиисис- темных технологийбазовойоперационнойсистемы. Рассматриваемыйучебный курс предназначен дляначальнойподготовкипрограммиста, владеющегоязыкомпро- граммирования Си++ применительнокразработкепрограммвОСсемейства Win32. При анализедоступныхвИнтернетзарубежныхкурсов, связанныхсобучени- ем практическомупрограммированиюврамкахподготовкипоспециальностям Computer Science, оказаласьзаметнаследующаятенденция: существуюткурсыпоизуче- нию языкаСи++, курсыпоизучениюобъектно-ориентированногопрограммирования на базе, чащевсего, Java иреже, Си++, ипрактическистандартныйкурс "Операцион- ные системы", посвященныйструктуре Unix-совместимыхоперационныхсистем. Ха- рактерной особенностьюзарубежныхуниверситетскихкурсовявляетсяотсутствие разделов, посвященныхизучениюпрактическогопрограммированиявсредекоммер- ческих ОСмассовогораспространения, впервуюочередь, ОС Windows. Сдругой стороны, изучениепрограммированиядляэтихОСпредлагаетсярядом коммерческих учебных организаций, носрокиобученияпорядка 3-5 днейпредполагаютобучение уже грамотногоспециалиста, имеющегонавыкипрограммированиявкакой-либодру- гой ОСилинадругомязыкепрограммирования. В сегодняшнихроссийскихусловиях, неотрицаянеобходимостифундамен- тальной подготовкиспециалистовповычислительнойтехникевобластитеорииалго- ритмов иустройствавычислительныхипрограммныхсистем, можноотметитьполез- ность изучения технологийпрактическогопрограммирования–использованиясред разработки ибиблиотекпрограммированиядляОСмассовогораспространения. Этим обусловлена направленностьрассматриваемогокурса–начальнаяподготовкапро- граммистов наСи++ длясредыОС Windows. Сложность обученияпрактическомупрограммированию, нанашвзгляд, за- ключается втрудностисочетанияобученияабстрактнымпонятиямпрограммирова- ния (таким, какструктурыданных, понятие алгоритма, основныекомпонентыалго- ритмического языка, методологияпроектированияпрограммногообеспечения), с изучением технологийисредпрограммированиянабазекакой-либоконкретнойОС. Эти практическиетехнологиипребываютвпостоянномразвитии, поэтомуможет быть сложновыделитькакие-либоконкретныесредстваразработкивкачествепред- мета изучения. Несмотря наширокоераспространениесредбыстройразработкиПрО (напри- мер, Visual Basic, Inprise Builder и Inprise Delphi), выборихвкачествеучебнойсреды представляется нецелесообразным, т.к. вэтихсредахкажущаясяпростотаразработки ПрО касаетсятолькоформированиякаркасаприложенияизнабораготовыхкомпо- нент, аустройствоэтихкомпонентилиизменениеструктурыкаркасатребуетсерьез- ных знанийнетолькопоструктуребазовойОС, ноипосистемнойархитектуресреды программирования. Программа данногокурсапредназначенадляобучениялиц, имеющих навыки пользовательской работынаперсональномкомпьютере, основнымпонятиямимето- дам современногопрактическогопрограммирования. Предметомизучениякурсаяв- ляется объектно-ориентированноепрограммирование наязыкеСи++ всредесовре- менных 32-хразрядныхоперационныхсистемсемейства Windows. Программакурса 6 разбита на 4 части: 1) ВведениевпрограммированиенаязыкеСи++ (9 лекций) 2) Основыпрограммированиятрехмернойграфики (8 лекций) 3) Объектно-ориентированноепрограммированиенаязыкеСи++ (9 лекций) 4) Программированиедля Microsoft Windows сиспользованием Visual C++ и библиотеки классов MFC (9 лекций) На каждоелекционное занятиедолжнобытьпредусмотреноминимумодно практическое (2 академическихчаса) иеще, всреднем, 4 часасамостоятельныхзаня- тий. Т.о., наизучениекурсаотводится 72 лекционныхчаса, 72 практических (т.о., 144 аудиторных часа) и 144 часасамостоятельныхзанятий. Методические материалыдлякурсасформированынаосновепримерно 10-ти зарубежных изданий, частьизкоторыхпереведенанарусскийязык. В первойчастикурсарассматриваютсяпроцедурныеосновы языка Си++. Они включают всебяоформлениетекстапрограмм, правилазаписивыраженийнаСи++, рассмотрение простыхтиповданныхиалгоритмическихконструкцийусловныхопе- раторов, циклов_______идр. Вконцеэтойчастикурсаподробнорассматриваютсясоставные типы данных. Приэтомделаютсязамечанияодостоинствахинедостаткахэтихтипов данных, чтовпоследствииупрощаетвведениепонятийобъектно-ориентированного программирования. Вторая частькурсапосвященаприменениюязыкаСи++ дляпрограммирования задач вконкретнойпредметнойобласти–трехмернойкомпьютернойграфики. Вка- честве базовойграфическойбиблиотекивыбранабиблиотека OpenGL, являющаяся открытым стандартомвданнойобласти. Изучениеэтойбиблиотекидемонстрирует методику освоенияготовогоинструментария, сформированноговрезультатеприме- нения методовструктурногопроектированиявконкретнойпредметнойобласти. По- нятия, относящиесякмашиннойграфике, понятиекаркасаприложенияиобработки событий иллюстрируютсяпростымипримерамиивдальнейшемиспользуютсяпри изучении программированиявсреде Windows. Третья частькурсаизучаетсяпослеусвоениястудентамипроцедурногопро- граммирования. Основныевопросыобъектно-ориентированногопрограммирования на Си++ излагаются напримерепрограммированияконсольныхприложений Win32. Рассматриваются элементарныеприемыобъектно-ориентированногопроектирования –проектированиенаосновераспределенияобязанностей, метод CRC-карточек. В четвертойчастикурсаизучаетсяархитектураоперационныхсистемсемейст- ва Windows иметодыпрограммированиядляэтихОС. Примернотретьэтойчастипо- священа рассмотрениюосновныхкомпонентоперационныхсистем Windows 9x/NT, знакомству сбазовыми сервисамиоперационныхсистемипрограммированиюдля этих ОСнаязыкеСи++ науровне Win32 API. Воставшейсячастирассматриваются приемы программированиядляОС Windows набазебиблиотекиклассов MFC. Эта библиотека классовявляетсяпромышленнымстандартом, упрощающимразработку программ ииспользование Win32 API. Подробноописываетсякаркасприложения MFC, основныеклассыэтойбиблиотеки, приемыиспользованияэтихклассоввсоб- ственных программах, архитектура однодокументныхприложений "документ/вид". После изучениякурсастудентполучаетдостаточнополноепредставлениео содержании современногообъектно-ориентированногопрограммирования, обуст- ройстве современныхоперационныхсистем Win32 иособытийно-управляемомпро- граммировании. Напрактическихзанятияхвырабатываютсянавыкипрограммирова- ния наСи++ винтегрированнойсредеразработки Microsoft Visual C++ 5.0. 7 ЛЕКЦИЯ 1. Основы Си++
1. Несколько замечаний о назначении программирования
Программирование –этотехническаятворческаядеятельность, целькоторой заключается врешенииважныхдлячеловеказадачиливыполненииопределенных действий спомощьюкомпьютера. Нарис. 1 представленаидеализированнаясхема решения типичнойзадачипрограммирования. Подробное описание задачи илинеобходимых действий КОМПЬЮТЕР Решение задачиили выполнение действий Рис. 1.
Схема решениязадачиспомощьюкомпьютера. В рамкахтакойсхемынеобходимымикомпонентамикомпьютераявляются центральный процессор, устройстваввода/выводаипамять (рис. 2). Рис. 2.
Основные компонентыкомпьютера. Конечно, вдействительностиделообстоитнетакпросто, какпоказанона рис. 1. Например, "подробноеописание (спецификация) задачи" наестественномязы- ке длякомпьютеранегодится (внастоящеевремя). Болеетого, длярешениязадачина компьютере недостаточнополногоописаниязадачи, необходимотакжеснабдить компьютер информациейотом, какименноследуетрешатьзадачу–т.е. составитьал- горитм. Дляописанияалгоритмоврешениязадачилиалгоритмоввыполнениякаких- либо действий (например, управлениероботом-манипулятором) спомощьюкомпью- тера применяютсяязыкипрограммирования. На рис. 3 показанаболееподробнаясхемарешениязадачиспомощьюкомпью- тера, вкоторойучтенанеобходимостьиспользованияязыкапрограммирования. Ил- люстрация этойсхемынаконкретномпримереприведенавтаблице 1. Существует большоеколичестворазличныхязыковпрограммированияимного способов ихклассификации. Например, "языкамивысокогоуровня" считаютсяте языки, синтаксискоторыхсравнительно близоккестественномуязыку, втовремякак синтаксис "низкоуровневых" языковсодержитмноготехническихподробностей, свя- занных сустройствомкомпьютераипроцессора. 8 Рис. 3.
Схема решениязадачинакомпьютересиспользованиемязыкапрограммирования. Таблица 1.
Основные этапырешениязадачипопроверкечисланапростоту. Спецификация задачи
Требуется определить, являетсялиданноечислопростым. Алгоритм
Ввести x
Для каждого целого числа z из диапазоне от 1 до x
Если остаток от деления x на z равен 0, то
вывести сообщение "число не простое" и закончить работу
Если такого числа z не найдено, то
вывести сообщение "число простое" и закончить работу
Описание алгоритма на
языке высокого уровня
#include <iostream.h> int main() { int x; cout << "Введите число:\n"; cin >> x; for (int z=2; z<x; z++) if (x % z == 0) { cout << "Это не простое число.\n"; return 0; } cout << "Это простое число.\n"; return 0; } Объектный код (внут-
ренний код конкретного
компьютера)
Двоичные командыпроцессора (частично) Исполняемый файл для
конкретного компьютера
Двоичные командыпроцессора (полностью) "Императивные" или "процедурные" языкипозволяютпрограммистуописать, в какой последовательностикомпьютербудетвыполнятьотдельныешагиалгоритмаи, таким образом, решатьзадачуивыдаватьнаэкранрезультат. "Декларативные" языки предназначены большедляописаниясамойзадачиижелаемогорезультата, анедей- ствий компьютера. "Объектно-ориентированныеязыки" рассчитанынаприменениеособогопод- хода кописаниюзадач, согласнокоторомувзадачевыделяютсянекоторые "объекты" с характернымдляних "поведением" ивзаимодействующиемеждусобой. Одиниз 9 первых объектно-ориентированныхязыков–Смоллток, онпредназначенисключи- тельно дляобъектно-ориентированногопрограммирования. Вотличиеотнего, язык Си++ обладаеткакобъектно-ориентированнымивозможностями, такисредствами традиционного процедурногопрограммирования. Радикальные приверженцыразличныхязыковистилей программирования иногда делаютэкстравагантныезаявления, выделяющиесемействоязыковилиодин язык какисключительныйиидеальноподходящийдлялюбыхзадач. Например, до- вольно распространеномнение, чтообъектно-ориентированныйподходнаиболее близок кспособурешениязадаччеловеком. Поэтомуповодувысовременемсможе- те составитьсобственноемнение, т.к. абсолютноистинного, очевидно, нет. 2. Происхождение языка Си++
Язык Си++ былразработанвначале 1980-хгг. БьерномСтрауструпомизком- пании AT&T Bell Laboratories. Си++ основаннаязыкеСи. Двасимвола "++" вназва- нии –этоиграслов, символами "++" вязыкеСиобозначаетсяоперацияинкремента (увеличениезначенияпеременнойна 1). Т.о., Си++ был задуманкакязыкСисрас- ширенными возможностями. БольшаячастьязыкаСивошлавСи++ какподмножест- во, поэтомумногиепрограммынаСиможноскомпилировать (т.е. превратитьвнабор низкоуровневых команд, которыекомпьютерможетнепосредственновыполнять) с помощью компилятораСи++. При классификацииязыковпрограммированияязыкСивызываетнекоторые трудности. Посравнениюсассемблером, этовысокоуровневыйязык. ОднакоСисо- держит многонизкоуровневых средствдлянепосредственныхоперацийспамятью компьютера. ПоэтомуязыкСиотличноподходитдлянаписанияэффективных "сис- темных" программ. НопрограммыдругихтиповнаСимогутоказатьсядовольно сложными дляпонимания, иестьрядошибок, которымпрограммынаСиособенно подвержены. Дополнительныеобъектно-ориентированныевозможностиСи++ были добавлены вСи, вчастности, дляустраненияэтихнедостатков. 3. Стандарт ANSI Си++
Национальный ИнститутСтандартизацииСША (American National Standards Institution, ANSI) разработал "официальные" стандартыдлямногихязыковпрограм- мирования, втомчиследляСииСи++. Этистандартысталиобщепринятымииони имеют оченьбольшоезначение. Программу, целикомнаписанную на ANSI Си++, га- рантированно можнозапуститьналюбомкомпьютере, длякоторогоимеетсякомпи- лятор ANSI Си++. Другимисловами, стандартгарантируетпереносимостьпрограмм на языке ANSI Си++. В действительностибольшинствоверсийСи++ представляютсобойстандарт- ный ANSI Си++, дополненныйнекоторымимашинно-зависимымивозможностями. Эти специфическиесредствапредназначеныдляоблегчениявзаимодействияпро- грамм сконкретнымиоперационнымисистемами. Вообще, впрограммах, которые должны бытьпереносимыми, подобнымиспецифическимивозможностямиследует пользоваться какможнореже. ВтакихслучаяхчастипрограммынаСи++, вкоторых используются не-ANSI компонентыязыка, целесообразноособымобразомпомечать, так, чтобыихлегкоможнобылоотделитьотосновнойчастипрограммыимодифи- цировать длядругихкомпьютеровиоперационныхсистем. 10 4. Среда разработки Microsoft Developer Studio Visual С++
Известно, чтолучшийспособизученияязыкапрограммированиязаключаетсяв том, чтобыписатьнанемпрограммыипроверять, какониработаютнакомпьютере. Для этогонеобходимынесколькопрограмм: •Текстовый редактор, спомощьюкоторогоможнонабиратьиредактировать исходный текстпрограммнаСи++. •Компилятор. Этапрограммавыполняетпреобразованиеисходноготекстав машинные команды, которыекомпьютерможетнепосредственновыпол- нять. •Компоновщик, которыйсобираетотдельныескомпилированныечастипро- граммы вединоецелоеи, принеобходимости, добавляеткнимкомпоненты из готовыхбиблиотек. Врезультатекомпоновкиполучаетсяготоваякза- пуску программа–исполняемыйфайл. •Отладчик, спомощьюкотороголегчеискатьошибкивпрограмме. Ошибки могут обнаружитьсякакприкомпиляции, такивовремяработыпрограм- мы. В данномкурсеизученияСи++ практическиеупражненияпредполагаетсявы- полнять всредеразработкипрограммMicrosoft Developer Studio Visual C++
для IBM-совместимыхПКподуправлениемWindows 95/NT
. Вэтомпакетеинтегрирова- ны редактор, компилятор, компоновщикиотладчик. Всевместеониобразуютединую удобную средупрограммирования. КраткоеописаниеработысосредойVisual C++
приведено вПриложении
. 5. Пример программы на Си++
Ниже приведенисходныйтекстпростойпрограммынаСи++. // В языке Си++ с двойной косой черты начинаются комментарии // (например, как эта строка). Компилятор игнорирует комментарии, // начиная от первой черты и до конца строки. /* Второй способ записи комментариев – после косой черты со звездочкой. После текста комментария надо поставить звездочку, а затем – косую черту. Комментарии, записанные подобным образом, могут занимать больше одной строки. */ /* В программе ОБЯЗАТЕЛЬНО должно быть достаточное количество комментариев! */ /* Эта программа запрашивает у пользователя текущий год, возраст пользователя и еще один год. Затем программа вычисляет возраст пользователя, который будет у него во втором введенном году.*/ #include <iostream.h> int main() { int year_now, age_now, another_year, another_age; cout << "Введите текущий год и нажмите ENTER.\n"; cin >> year_now; cout << "Введите свой возраст (в годах).\n"; cin >> age_now; 11 cout << "Введите год, для которого вы хотите узнать свой возраст.\n"; cin >> another_year; another_age = another_year - (year_now - age_now); if (another_age >= 0) { cout << "В " << another_year << " году вам будет "; cout << another_age << "\n"; } else { cout << "В " << another_year << " вы еще не родились!\n"; } return 0; } Программа 5.1.
Некоторые свойствапрограммы 5.1 являютсяобычнымидлябольшинствапро- грамм наСи++. Программаначинается (послекомментариев) соператора #include <iostream.h> Этот операторназывается "директивойinclude". Докомпилятораисходный текст обрабатываетсяпрепроцессором
–специальнойпрограммой, котораямодифи- цирует текстпрограммыпоспециальнымкомандам–директивам. Директивыпре- процессора начинаютсяссимвола "#". Директиваinclude предназначена длявклю- чения висходныйтекстсодержимогодругогофайла. Например, впрограмму 5.1 включается файлiostream.h, содержащийописанияфункцийстандартнойбиблиоте- ки ввода/выводадляработысклавиатуройиэкраном. (Стандартныебиблиотекиязы- ка Си++ будутрассматриватьсяпозже). Алгоритм, записанныйвпрограмме 5.1, оченьпростой. Поэтомуструктуру программы легкопредставитьввидеспискапоследовательновыполняемыхкоманд (операторов). Схематичнопрограмму, содержащуюсяпоследирективы#include, можно представитьввиде: int main() { Первый оператор
; ... ... Последний оператор
; return 0; } Подобная структураявляетсяобщейдлявсехпрограммнаСи++. Каждыйопе- ратор втелепрограммызавершаетсяточкойсзапятой. Вхорошоразработанной большой программебольшинствооператоровявляютсяобращениями (вызовами) к подпрограммам, которыезаписываютсяпосле функцииmain() или вотдельных файлах. Каждаяподпрограмма (функция) имеетструктуру, подобнуюфункции main(). Нофункцияmain() в каждойпрограмметолькоодна. Именноснееначина- ется выполнениепрограммы. (Подробнеефункциибудутрассматриватьсядалее.) В концефункцииmain() записана строка: 12 return 0; Эта строказначит "вернутьоперационнойсистемевкачествесигналаобус- пешном завершениипрограммызначение 0". Операторвозвратаreturn применяется не толькопризавершениипрограммы, ноипризавершенииотдельныхподпрограмм. В любомслучаеэтотоператорвозвращаетопределенноезначениенаболеевысокий уровень управления. В программе-примереиспользуются четырепеременные
: year_now, age_now, another_year и another_age Переменные впрограммированииотличаютсяотматематическихпеременных. Они используютсякаксимволические имена "фрагментовоперативнойпамятиком- пьютера". Привыполнениипрограммывразличныемоментывременипеременные могут хранитьразличныезначения. Впрограмме 5.1 первоеупоминаниечетырехпе- ременных содержитсявстрокесоператоромописанияпеременных: int year_now, age_now, another_year, another_age; Этот операторуведомляеткомпилятор, что дляхранениячетырехпеременных типа "целоечисло" (integer –int) требуетсявыделитьнеобходимоеколичествопамя- ти. Этаобластьпамятибудетзарезервированавтечениевыполненияоставшейсячас- ти программы. Переменныевсегдадолжныбытьописаныдопервогоиспользования. В программированиихорошимстилемсчитаетсяописаниевсехпеременных, исполь- зуемых вподпрограмме, вначалеэтойподпрограммы. ВСи++ естьнесколькораз- личных типовпеременных, ионибудутобсуждатьсянемногопозже. 6. Выполнение ввода/вывода данных и присваивание значений
После компиляции
программы ееможнозапустить на выполнение
. Результат выполнения наэкранебудетвыглядетьпримернотак: Введите текущий год и нажмите ENTER. 2000
Введите свой возраст (в годах). 21
Введите год, для которого вы хотите узнать свой возраст. 2017
В 2017 году вам будет 38 Первая, третья, пятаяиседьмаястрокивыдаютсянаэкранпрограммойспо- мощью следующегооператора: cout << Выражение1
<< Выражение2
<< ... << ВыражениеN
; Этот операторвыводитнаэкрансообщение: Выражение
1 Выражение
2 ... Выражение
N Последовательность операторов cout << Выражение
1; cout << Выражение
2; ... ... cout << Выражение
N; 13 приводит каналогичномурезультату. Еслимеждувыражениямитребуетсявставить пробелы илиновыестроки, тоихнужноуказатьявно, спомощьюсимволов" " и "\n" соответственно. Числа, показанныевышевпримеревыдачинаэкранполужирным
шрифтом, бы- ли напечатаныпользователем. Впоказанномпримере оператор cin >> year_now; приводит ктому, чтопеременнойyear_now присваивается
значение 2000
. Этопроис- ходит послетого, какпользовательнапечатает "2000
" инажметклавишуEnter
. В программе естьещеместа, гдепеременнымприсваиваютсязначения, втом числе оператор присваивания: another_age = another_year - (year_now - age_now); Операция "=" означает "присвоитьпеременной, стоящейслеваотзнакаравен- ства, значение, указанноесправа". ПроверканаравенствовСи++ обозначается двой- ным символом: "==". 7. Управление порядком выполнения команд с помощью оператора if
В несколькихпоследнихстрокахпрограммы (достроки "return 0") записано: if (another_age >= 0) { cout << "В " << another_year << " году вам будет "; cout << another_age << "\n"; } else { cout << "В " << another_year << " вы еще не родились!\n"; } Оператор ветвления (условныйоператор) "if...else..." выглядитпримерно одинаково вовсехпроцедурныхязыкахпрограммирования. ВСи++ онназывается просто оператором if
, иегообщаяструктуратакова: if ( условие ) { Оператор
1; ... ... Оператор
N; } else { Оператор
N+1; ... ... Оператор
N+M; } Часть "else (иначе)" воператореif необязательна. Болеетого, еслипосле "if ( условие )" стоиттолькоодиноператор, томожноопуститьфигурныескобкии записать оператортак: 14 if ( условие ) Оператор
1; В программахусловныеоператорычастовстречаютсягруппами, например: ... ... if (total_test_score < 50) cout << "Вы не прошли тест. Выучите материал как следует.\n"; else if (total_test_score < 65) cout << "Вы прошли тест со средним результатом.\n"; else if (total_test_score < 80) cout << "Вы хорошо выполнили тест.\n"; else if (total_test_score < 95) cout << "Вы показали отличный результат.\n"; else { cout << "Вы сдали тест нечестно!\n"; total_test_score = 0; } ... ... Приведенный фрагментпрограммыможетпоказатьсядовольносложным. Тем не менее, онсоответствуетправиламСи++. Этолегкопонять, еслиобратитьсяксин- таксической диаграммеоператораif (рис. 4). В овальныхиликруговыхрамкахнасинтаксическихдиаграммахуказываются элементы языка, которыебуквальнотакивоспроизводятсявисходномтекстепро- грамм. Впрямоугольныхрамкахприведеныэлементы, требующиедальнейшегооп- ределения, возможно, спомощьюдругихсинтаксическихдиаграмм. Набортакихдиа- грамм служитформальнымописаниемсинтаксисаязыкапрограммирования. Обратите внимание, чтонарис. 4 отсутствуетсимвол ";" иразделители "{}". Эти элементыязыкавключенывопределение (исинтаксическуюдиаграмму) для обобщенного понятия "операторязыкаСи++". Рис. 4.
Синтаксическая диаграммаоператораif. При обработкеприведенногофрагментапрограммыкомпиляторСи++ трактует весь текст, выделенныйнижеполужирнымшрифтом, какодиноператорпослеперво- го словаelse. ... ... if (total_test_score < 50) cout << "Вы не прошли тест. Выучите материал как следует.\n"; else if (total_test_score < 65)
cout << "Вы прошли тест со средним результатом.\n";
else if (total_test_score < 80)
cout << "Вы хорошо выполнили тест.\n";
15 else if (total_test_score < 95)
cout << "Вы показали отличный результат.\n";
else
{
cout << "Вы сдали тест нечестно!\n";
total_test_score = 0;
}
... ... 8. Оформление исходного текста
Между текстомпрограммы, приведеннымвп.5 итекстом, которыйпоказан ниже, длякомпилятораСи++ нетникакихразличий. #include <iostream.h> int main() { int year_now, age_now, another_year, another_age; cout << "Введите текущий год и нажмите ENTER.\n"; cin >> year_now; cout << "Введите свой возраст (в годах).\n"; cin >> age_now; cout << "Введите год, для которого вы хотите узнать свой возраст.\n"; cin >> another_year; another_age = another_year - (year_now - age_now); if (another_age >= 0) { cout << "В " << another_year << " году вам будет "; cout << another_age << "\n"; } else { cout << "В " << another_year << " вы еще не родились!\n"; } return 0; } Отсутствие комментариев
, пробелов
, пустых строк
и отступов
делают эту программу практическинепригоднойдлячтениячеловеком. Длявыработкихорошего стиля программирования, конечно, требуется знатьнетолькоправилаоформления текста программы, ноихследуетсоблюдатьссамогоначала. Приоформлениисобст- венных программбудьтепоследовательныиделайтетак, чтобыотступыипробелы отражали логическуюструктурувашихпрограмм. Для переменныхследуетвыбиратьосмысленныеимена: имена "year_now", "age_now", "another_year" и "another__age" лучше, чем "y_n", "a_n", "a_y" и "a_a" инамноголучше, чем "w", "x", "y" и "z". Этоособенноважно, есливбудущем ваши программымогутпотребоватьизмененияспомощьюдругихпрограммистов. 9. Сводка результатов
В даннойлекциикраткоинеформальнобылирассмотренынескольковажных вопросов: переменныеитипыданных, вводивывод, оператор присваиванияиуслов- ный оператор ("операторif"). Болеестрогоиподробноэтивопросыбудутрассмот- рены впоследующихлекциях. 10. Упражнения
Для выполненияэтихупражненийтребуетсянекоторыйопытработысПКпод управлением операционнойсистемыWindows 95/NT
. Упражнение 1 Изучите краткоеруководствопоVisual C++
в Приложении
. Создайтепроектс именем "AgeCalculator". СоздайтеисходныйфайлсименемAgeCalculator.cpp 16 и наберитевнемисходныйтекстпрограммы 5.1. Сохранитефайлнадискеидобавьте его впроект. Соберитепроектизапуститепрограммунавыполнение. Возможно, вывстретитесьсоследующимипроблемами: 1) В окне программы вместо русских букв выводятся какие-то странные символы.
Эта проблемаобъясняетсяразличиемтаблицкодировокWindows
и DOS
. В этих таблицах русские буквырасположенывразныхместах. Консольныепрограммыприработеисполь- зуют кодировкуDOS
, атекстовыйредакторVisual C++
–кодировкуWindows
. Поэтому вам придетсядобавитьпреобразованиестроксрусскимибуквамиизкодировкиWindows
в кодировкуDOS
. Для этоговключитевпрограмму, послефайлаiostream.h, файлwindows.h с описа- нием функцийоперационнойсистемыWindows
: #include <windows.h> Перед функциейmain() создайте новуюфункциюсименем rus_str(), котораябудетвы- полнять необходимоепреобразованиеспомощьюспециальнойфункцииWindows
: char* rus_str( char* str ) { CharToOem( str, str ); return str; } Во всехстрокахпрограммы, гденаэкранвыдаютсясимвольныестрокисрусскимибук- вами, укажитепреобразованиеэтихстрокспомощьюновойфункции, например: cout << rus_str( "Введите текущий год и нажмите ENTER.\n" ); 2) После завершения работы окно программы закрывается и не удается увидеть ре-
зультаты.
Для исправленияэтогонедостаткапрощевсегопредусмотретьвконцепрограммыввод произвольного символа. Покапользовательненажметкакую-нибудьсимвольнуюклави- шу ипотомEnter
, окнопрограммыбудетоставатьсянаэкране. Дляэтогопотребуетсяза- вести символьнуюпеременную (строкусописаниемэтойпеременнойрасположитепосле строки сописаниемцелочисленныхпеременных): char wait_char; Перед строкойсоператоромвозврата "return 0" добавьтеоператордлявводасимвола с клавиатуры: cin >> wait_char; Сравните результатыработысвоейпрограммыспримеромизлекции. Поэкс- периментируйте надулучшениемилиизменениемформатавыводанаэкран. Упражнение 2 Модифицируйте программу 5.1, чтобыприпревышениипеременной "another_age" значения150
на экранвыводилосьсообщение: Извините, но вы вряд ли доживете до [year]
года! Проверьте работусвоейпрограммыдлянесколькихразныхлет. Упражнение 3 Измените программуизупр.2 так, чтобывнейучитывалисьигоды, имесяцы. На экранпрограммадолжнавыводитьследующиесообщения: Введите текущий год и нажмите ENTER. 2000
Введите текущий месяц (число от 1 до 12). 10
17 Введите свой возраст (в годах). 25
Введите месяц своего рождения (число от 1 до 12). 5
Введите год, для которого вы хотите узнать свой возраст. 2006
Введите месяц этого года. 6
Ваш возраст в 6/2006: 31 год и 1 месяц. Программа должнавыдаватькорректныесообщениядляединственногоимно- жественного числалетимесяцев, т.е. должнавыводитьнаэкран "25 лет и 1 ме- сяц", но "24 года и 2 месяца". Подсказка:
В программе вам потребуются дополнительные переменные. Обязатель-
но добавьте их имена в оператор описания переменных. При вычислениях могут при-
годиться некоторые стандартные операции Си++:
Символ Операция Пример Значение
+
Сложение 3 + 5 8 -
Вычитание 43 - 25 18 *
Умножение 4 * 7 28 /
Деление 9/2 4 %
Остаток приделе- нии нацело 20 % 6 2 (Обратите внимание, что в приведенной таблице операция деления "/" применялась к
двум целым числам, поэтому результат – тоже целое число.)
Кроме арифметических операций, для проверки условий в операторе
if
вам могут
потребоваться некоторые логические операции.
Символ Операция Пример Значение
<
меньше, чем 3 < 5 TRUE (истина) <=
меньше илиравно 43 <= 25 FALSE (ложь) >
больше, чем 4 > 7 FALSE >=
больше илиравно 9 >= 2 TRUE ==
равно 20 == 6 FALSE !=
не равно 20 != 6 TRUE &&
Логическое И 5 > 2 && 6 > 10 FALSE ||
Логическое ИЛИ 5 > 2 || 6 > 10 TRUE 18 ЛЕКЦИЯ 2. Переменные, типы данных и выражения
1. Идентификаторы
В исходномтекстепрограммнаСи++ используетсядовольномногоанглий- ских словиихсокращений. Всеслова (идентификаторы), встречающиесявпрограм- мах, можноразделитьнатрикатегории: 1) Служебные слова языка.
Например, этословаif, int и else. Назначение этих словпредопределеноиегонельзя изменить. Нижеприведенболее полный списокслужебныхслов: asm continue float new signed try auto default for operator sizeof typedef break delete friend private static union case do goto protected struct unsigned catch double if public switch virtual char else inline register template void class enum int return this volatile const extern long short throw while По назначениюэтисловаможноразбитьнаотдельныегруппы (прил. 8.1). 2) Библиотечные идентификаторы.
Назначение этихсловзависитотсреды программирования. Вслучаесерьезнойнеобходимостипрограммистможет изменить ихсмысл. Примерытакихслов: cin, cout и sqrt (имяфункции извлечения квадратногокорня). 3) Идентификаторы, введенные программистом.
Эти слова "создаются" программистом –например, именапеременных (такие, какyear_now и another_ age в программе 1.5.1). Идентификатором не можетбытьпроизвольнаяпоследовательностьсимволов. По правиламСи++, идентификаторначинаетсясбуквыилисимволаподчеркивания ("_") исостоиттолькоизанглийскихбукв, цифрисимволовподчеркивания. 2. Типы данных
2.1 Целые числа Правила Си++ требуют, чтобывпрограммеувсехпеременныхбылзадантип данных. Типданныхint встречался намуженеоднократно. Переменныеэтоготипа применяются дляхраненияцелыхчисел (integer). Описаниепеременной, какимею- щей типint, сообщаеткомпилятору, чтоондолженсвязатьсидентификатором (именем) переменнойколичествопамяти, достаточноедляхраненияцелогочиславо время выполненияпрограммы. Границы диапазонацелыхчисел, которыеможнохранитьвпеременныхтипа int, зависятотконкретногокомпьютера. ВСи++ естьещедвацелочисленныхтипа– short int и long int. Онипредставляют, соответственно, болееузкийиболее широкий диапазонцелыхчисел, чемтипint. Добавлениеклюбомуизэтихтипов префикса unsigned означает, чтовпеременной будутхранитсятольконеотрица- тельные числа. Например, описание: unsigned short int year_now, age_now, another_year, another_age; 19 резервирует памятьдляхранениячетырехотносительнонебольшихнеотрицательных чисел. Приведем несколькополезныхправил, касающихсязаписицелочисленных значений висходномтекстепрограмм. 1) Нельзяпользоватьсядесятичнойточкой. Значения 26 и 26.0 одинаковы, но "26.0" неявляетсязначениемтипа "int". 2) Нельзяпользоватьсязапятымивкачестверазделителейтысяч. Например, число 23,897 следуетзаписывать как "23897". 3) Целыезначениянедолжныначинатьсяснезначащегонуля. Онприменяется для обозначенияустаревшихвосьмеричныхчисел, такчтокомпиляторбу- дет рассматриватьзначение "011" какчисло 9 ввосьмеричнойформе. 2.2 Вещественные числа Для хранениявещественныхчиселприменяютсятипыданныхfloat и double. Смысл знаков "+" и "-" длявещественныхтиповсовпадаетсцелыми. По- следние незначащиенулисправаотдесятичнойточкиигнорируются. Поэтомувари- анты записи "+523.5", "523.5" и "523.500" представляютодноитожезначение. В Си++ такжедопускаетсязаписьвформатес плавающей запятой
(вэкспоненциальном формате) ввидемантиссы
и порядка
. Например, 523.5 можнозаписатьввиде "5.235e+02" (т.е. 5.235*10*10), а -0.0034 ввиде "-3.4e-03". В большинствеслучаевиспользуетсятипdouble, онобеспечиваетболеевысо- кую точность, чемfloat. Максимальнуюточностьинаибольшийдиапазончисел достигается спомощьютипаlong double, ноонтребуетбольшепамяти (в Visual C++
10 байтначисло), чем double (8 байт). 2.3 Преобразование типов в выражениях При выполнениивычисленийиногдабываетнужногарантировать, чтоопреде- ленное значениебудетрассматриватьсякаквещественноечисло, дажееслинасамом деле это целое. Чащевсегоэтонужноприделенииварифметическихвыражениях. Применительно кдвумзначениямтипаint операция деления "/" означаетделение нацело, например, 7/2 равно 3. Вданномслучае, еслинеобходимополучитьрезультат 3.5, томожнопростодобавитьдесятичнуюточкувзаписиодногоилиобоихчисел: "7.0/2", "7/2.0" или "7.0/2.0". Ноеслиивчислителе, ивзнаменателестоятперемен- ные, анеконстанты, тоуказанныйспособнеподходит. Вместонегоможноприме- нить явноепреобразованиетипа. Например, значение "7" преобразуетсявзначение типа double с помощьювыражения "double(7)". Поэтомуввыражении answer = double(numerator) / denominator операция "/" всегдабудетрассматриватьсякомпиляторомкаквещественноеделение, даже если "numerator" и "denumerator" являютсяцелымичислами. Дляявногопреоб- разования типовможнопользоватьсяидругимиименамитиповданных. Например, "int(14.35)" приведеткполучениюцелогочисла14. 20 2.4 Символьный тип Для хранениясимвольныхданныхвСи++ предназначентип "char". Перемен- ная типа "char" рассчитананахранениетолькоодногосимвола (например, буквы или пробела). Впамятикомпьютерасимволыхранятсяввидецелыхчисел. Соответ- ствие междусимволамииихкодамиопределяетсятаблицейкодировки, котораязави- сит откомпьютераиоперационнойсистемы. Почтивовсехтаблицахкодировкиесть прописные истрочныебуквыанглийскогоалфавита, цифры0,...,9, инекоторые специальные символы, например, #, ., !, +, - и др. Самойраспространеннойтаблицей кодировки, скореевсего, является таблицасимволов ASCII. В текстепрограммсимвольныеконстантытипа "char" надозаключатьводи- ночные кавычки, иначекомпиляторпойметихнеправильноиэтоможетпривестик ошибке компиляции, или, чтоещехуже, кошибкамвременивыполнения. Например, "'A'" являетсясимвольнойконстантой, но "A" будетрассматриватьсякомпиляторомв качестве именипеременной. Аналогично, "'9'" являетсясимволом, а "9" –целочис- ленной _______константой. Т.к. впамятикомпьютерасимволыхранятсяввидецелыхчисел, тотип "char" на самомделеявляетсяподмножествомтипа "int". НаСи++ разрешаетсяиспользо- вать символыварифметическихвыражениях. Например, налюбомкомпьютерес таблицей ASCII следующеевыражениедастистинноезначение (TRUE, или1): '9'-'0' == 57-48 == 9 В таблице ASCII кодомсимвола '9' являетсядесятичноечисло 57 (вшестнадца- теричной записи 0x39), а ASCII–код символа '0' равендесятичномучислу 48 (шестна- дцатеричное значение 0x30). Приведенноевыражениеможнопереписатьввиде: 57-48 == 0x39-0x30 == 9 Кодами ASCII удобнеепользоватьсявшестнадцатеричнойформе. Призаписи шестнадцатеричных чиселвСи++ применяетсядвухсимвольныйпрефикс "0x". Переменные типа "char" существенноотличаютсяот "int" привыполнении ввода данныхсклавиатурыивыводанаэкран. Рассмотримследующуюпрограмму. #include <iostream.h> int main() { int number; char character; cout << "Напечатайте символ и нажмите Enter:\n"; cin >> character; number = character; cout << "Вы ввели символ '" << character; cout << "'.\n"; cout << "В памяти компьютера он хранится в виде числа "; cout << number << ".\n"; return 0; } Программа 2.1.
Программа 2.1 выдаетнаэкранследующиесообщения: 21 Напечатайте символ и нажмите Enter: 9
Вы ввели символ '9'. В памяти компьютера он хранится в виде числа 57. Программу 2.1 можноизменитьтак, чтобыонапечаталавсютаблицусимволов ASCII. Дляэтогопридетсяприменить "операторциклаfor". "Циклfor" является примером оператора цикла
–этиоператорыбудутрассмотреныподробноводнойиз следующих лекций. Операторfor имеет следующийсинтаксис: for (инициализация
; условие_повторения
; изменение_значений
) { Оператор
1; ... ... Оператор
N; } Цикл for выполняется вследующемпорядке: (1) Сначалавыполняетсяопера- тор инициализации
. (2) Выполняетсяпроверка, являетсялиусловие_повторения
истин- ным. Еслиусловиеложно, тооператор for завершается. Еслиусловиеистинно, то последовательно выполняютсяоператорытелациклаОператор
1...Оператор
N, изатем выполняется операторизменение_значений
. Послеэтогопроисходитпереходнанача- ло шага (2). Чтобы кодсимволавывестинаэкранвшестнадцатеричнойформе, надоснача- ла послатьнаэкранслужебный символ-манипулятор. Программадляпечатифраг- мента таблицы ASCII (от 32-госимвола (пробел) до 126-го (символ '~')), будетвыгля- деть так: #include <iostream.h> int main() { int number; char character; for (number = 32; number <= 126; number = number + 1 ) { character = number; cout << "Символ '" << character; cout << "' имеет код "; cout << dec << number << " (дес.) или "; cout << hex << number << " (шестнд.).\n"; } return 0; } Программа 2.2.
Программа 2.2 напечатаетнаэкране: Символ ' ' имеет код 32 (дес.) или 20 (шестнд.). Символ '!' имеет код 33 (дес.) или 21 (шестнд.). ... ... Символ '}' имеет код 125 (дес.) или 7D (шестнд.). Символ '~' имеет код 126 (дес.) или 7E (шестнд.). 22 2.5 Символьные строки В большинстверассмотренныхпримеровпрограммдлявыводанаэкранчасто используются символьныестроки. ВСи++ символьныестрокизаключаютсявдвой- ные кавычки. Поэтомувпрограммахчастовстречаются операторывыводавроде: cout << "' имеет код "; На самомделевСи++ строковыйтип ("string") неявляетсястандартнымти- пом данных, таким, как, например, "int", "float" или "char". Строкихранятсявпамя- ти ввидесимвольныхмассивов, поэтомустрокибудутрассматриватьсяпозднее, при изучении массивов. 2.6 Типы данных, определяемые пользователем Вопрос отипахданных, определяемыхпользователем, будетобсуждатьсяна- много болееподробновпоследующихлекциях. Будетпоказано, какпрограммист может определитьсобственныйтипданных, необходимыйдлярешенияконкретной задачи. Средстваопределенияновыхтиповданных–однаизнаиболеемощныхвоз- можностей Си++, которыепозволяютхранитьиобрабатыватьвпрограммахнаСи++ сложные структурыданных. 3. Вывод вещественных чисел на экран
При выводенаэкранчисленныхзначенийтипа "float", "double" или "long double" возможноуказаниеточностипредставленияданныхнаэкранеизаданиене- которых дополнительныхпараметровотображения, например, отображениезначений в форматесфиксированнойилиплавающейточкой. В программе 3.1 вещественноечислоотображаетсявформатесфиксированной точкой идвумядесятичнымизнакамипослезапятой. Идентификатор "sqrt" является именем библиотечнойфункцииизвлеченияквадратногокорня. Описаниебиблиотеки математических функций содержитсявзаголовочномфайле "math.h". #include <iostream.h> #include <math.h> int main() { float number; cout << "Введите вещественное число.\n"; cin >> number; cout << "Корень из "; cout.setf(ios::fixed); // СТРОКА 12 cout.precision(2); cout << number; cout << " примерно равен " << sqrt( number ) << ".\n"; return 0; } Программа 3.1.
Программа 3.1 напечатаетнаэкране: 23 Введите вещественное число. 200
Корень из 200.00 примерно равен 14.14. Если СТРОКУ 12 заменитьна "cout.setf(ios::scientific);", товидрезульта- та изменится: Введите вещественное число. 200
Корень из 2.00e+02 примерно равен 1.41e+01. В выходныеданныеможновключитьпараметрытабуляции. Дляэтогопредна- значена функцияшириныполя, например, "cout.width(20)". Оназадаетширинусле- дующего выводимогонаэкранзначенияравной, какминимум, 20 символам (при меньшей ширинеавтоматическибудутдобавленыпробелы). Этавозможностьосо- бенно полезнадляпечатитаблиц. В компилятореVisual C++
при указаниишириныполяпоумолчаниюпредпо- лагается, чтозначениявыравниваютсяпоправойгранице. Чтобызадатьвыравнива- ние полевойграницеполя, потребуетсяиспользоватьещенесколькоманипуляторов ввода-вывода. Этоспециальныефункциииоператоры, содержащиесявбиблиотеке ввода/выводаСи++. Ониописанывзаголовочномфайлеiomanip.h. Для заданиявы- равнивания полевойграниценадоустановитьспециальныйфлажок (переключатель) с помощьюфункцииsetiosflags: #include <iostream.h> #include <iomanip.h> #include <math.h> int main() { int number; cout << setiosflags( ios::left ); cout.width(20); cout << "Число" << "Квадратный корень\n\n"; cout.setf( ios::fixed ); cout.precision(2); for ( number = 1 ; number <= 10 ; number = number + 1 ) { cout.width(20); cout << number << sqrt(number) << "\n"; } return 0; } Программа 3.2.
Программа 3.2 выдастнаэкранследующиесообщения: Число Квадратный корень 1 1.00 2 1.41 3 1.73 4 2.00 5 2.24 6 2.45 24 7 2.65 8 2.83 9 3.00 10 3.16 (ПРИМЕЧАНИЕ
: вовсехпримерахидентификатор "cout" являетсяименемперемен- ной-объектакласса "stream" (поток). Функции "setf(...)", "precision(...)" и "width(...)" являютсяфункциями-членами класса "stream". Понятия "объект", "класс", "функция-член" идр. будутподробнорассматриватьсявкурсеобъектно- ориентированного программирования.) 4. Описания, константы и перечисления
Как выужезнаете, впрограммахнаСи++ переменныеобязательнодолжны быть описаныдопервогоиспользования, например, так: float number; После оператораописаниядомоментавыполненияпервогооператорапри- сваивания значениепеременной "number" будетнеопределенным, т.е. этапеременная может иметьслучайноезначение. ВСи++ можно (ижелательно) инициализировать переменные конкретнымизначенияминепосредственноприописаниипеременных. Например, возможенследующийоператорописаниясинициализацией: float PI = 3.1416; Если значениепеременнойвпрограмменикогданеизменяется, тоеецелесооб- разно защититьотслучайногоизмененияспомощьюслужебногослова "const" –т.е., превратить вконстанту. 4.1 Тип "Перечисление" Для описаниянаборасвязанныхпосмыслуконстанттипа "int" вСи++ есть оператор перечисления. Например, описаниевида enum { MON, TUES, WED, THURS, FRI, SAT, SUN }; эквивалентно описанию 7 констант-кодовднейнедели: const int MON = 0; const int TUES = 1; const int WED = 2; const int THURS = 3; const int FRI = 4; const int SAT = 5; const int SUN = 6; По умолчаниючленамперечисления "enum" присваиваютсязначения 0, 1, 2, и т.д.. Принеобходимостичленыперечисленияможноинициализироватьдругимизна- чениями. Неинициализированнымявночленамбудутприсвоенызначенияпопоряд- ку, начинаяотпредыдущегопроинициализированногочлена: enum { MON = 1, TUES, WED, THURS, FRI, SAT = -1, SUN }; В приведенномпримере "FRI" имеетзначение 5, а "SUN" –значение 0. 25 4.2 Расположение описаний констант и переменных в исходном тексте В исходномтекстеописанияконстантчащевсегоразмещаютсявзаголовке программы передфункцией "main". Послених, ужевтелефункции "main", размеща- ются описанияпеременных. Дляиллюстрацииэтогопорядканижеприведенфраг- мент программы, котораярисуетнаэкранеокружностьзаданногорадиусаивычисля- ет еедлину (набиратьэтотпримерненадо, посколькуонприведеннеполностью.) #include <iostream.h> const float PI = 3.1416; const float SCREEN_WIDTH = 317.24; int drawCircle(float diameter); /* Это "прототип функции" */ int main() { float radius = 0; cout << "Введите радиус окружности.\n"; cin >> radius; drawCircle(radius*2); cout.setf(ios::fixed); cout.precision(2); cout << "Длина окружности радиуса " << radius; cout << " примерно равна " << 2*PI*radius << ".\n"; return 0; } int drawCircle(float diameter) { float radius = 0; if (diameter > SCREEN_WIDTH) radius = SCREEN_WIDTH/2.0; else radius = diameter/2.0; ... ... } После определенияфункции "main()" вэтойпрограммесодержитсяопределе- ние функциирисованияокружности "drawCircle(...)". Деталиреализацииэтой функции сейчаснесущественны (будемсчитать, чтофункцияdrawCircle(...)" реа- лизована корректноиеюможнопользоватьсятакже, как, например, функцией "sqrt(...)"). Обратитевнимание, что, хотяпеременная "radius" используетсявобеих функциях "main()" и "drawCircle(...)", этонеоднаитажепеременная, адверазных
. Если быпеременная "radius" былаописанадофункции "main", товтакомслу- чае онабылабыглобальной переменной
(общедоступной). Тогда, предполагая, что внутри функции "drawCircle(...)" описанияпеременнойуженет, если "drawCircle(...)" присвоит глобальнойпеременнойзначение "SCREEN_WIDTH/2.0", тоэто значение чутьпозжефункция "main()" используетдлявычислениядлины окружности и получитсяневерныйрезультат. В приведеннойпрограммеглобальнойпеременнойнет, аестьдвелокальных
переменных "radius". Например, перваяпеременная "radius" являетсялокальной
пе- 26 ременной функции "main()", или, говорят, чтофункция "main()" являетсяобластью
видимости
этой переменной. Константы общегоназначения, такие, как "PI" и "SCREEN_WIDTH", принятоопи- сывать глобально
, чтобыонибылидоступнывнутрилюбойфункции. Для контролядействийпрограммывприведенномфрагментепредусмотрено повторное отображениеданных, введенныхпользователем. Другимисловами, задан- ное пользователемзначение "radius" ещеразпечатаетсянаэкранепередотображени- ем длиныокружности. 5. Присваивание и выражения
5.1 Краткая форма записи операторов присваивания В программахчастовстречаютсяоператорыприсваивания, вкоторыхсправа стоит выражение, модифицирующеетекущеезначениепеременной, например: number = number + 1; Переменным частоприсваиваютсязначения, вычисленныенаосновеихстарых значений. ПоэтомувСи++ былавведена краткаяформазаписидляподобныхопера- торов присваивания. Любуюизопераций "+" (сложение), "-" (вычитание), "*" (умно- жение), "/" (деление) и "%" (остатокотделениянацело) можноуказатьвкачестве префикса оператораприсваивания ("=") (cм. следующуютаблицу). Пример:
number += 1; total -= discount; bonus *= 2; time /= rush_factor; change %= 100; amount *= count1 + count2; Эквивалентное выражение:
number = number + 1; total = total - discount; bonus = bonus * 2; time = time / rush_factor; change = change % 100; amount = amount * (count1 + count2); Первый примердопускаетещеболеекраткуюзаписьспомощью оператораин- кремента "++": number++; Оператор "++" существуетивпрефикснойформе: ++number; Постфиксная ипрефикснаяформазаписиимеютважноеразличие, котороене- обходимо помнить. ПрефиксныйоператорприменяетсяДО
вычисления остальной части выражения, апостфиксный–ПОСЛЕ
. Например, посолевыполненияоперато- ров x = 4; y = x++; переменная "x" получитзначение 5, а "y" –значение 4. Вслучаеоператоров x = 4; y = ++x; обе переменныеполучатзначение 5. Этообъясняетсятем, что "++x" выполняетсядо того, какзначение "x" будетиспользовановвыражении, а "x++" –после. ВСи++ су- ществует аналогичныйоператордекремента "--", уменьшающийзначениеперемен- ной на 1, иунеготожеестьпрефикснаяипостфикснаяформа. 27 Вообще, выражениесоператоромприсваиванияимеетзначение, равноезначе- нию левойчастипослевыполненияприсваивания. Нижеприведеновыражение, соот- ветствующее правиламСи++, котороеможноиспользоватьдляпроверкиусловия: (y = ++x) == 5 Это выражениеозначаетследующее: "послеприсвоенияпеременнойy инкре- ментированного значенияx проверить, неравнолизначениеy числу 5". 5.2 Логические выражения и операторы Интуитивно логическиевыражениянаподобие "2<7", "1.2!=3.7" и "6>=9" вос- принимаются человекомкакутверждения, которыемогутбыть "истинными (true)" или "ложными (false)" (операция "!=" означает "неравно"). Допускаетсяобъеди- нение несколькихподобныхвыраженийвболеесложноевыражениеспомощью ло- гических операций "&&" ("И"), "||" ("ИЛИ") и "!" ("НЕ") (см. таблицу). Выражение:
(6 <= 6) && (5 < 3) (6 <= 6) || (5 < 3) (5 != 6) (5 < 3) && (6 <= 6) || (5 != 6) (5 < 3) && ((6 <= 6) || (5 != 6)) !((5 < 3) && ((6 <= 6) || (5 != 6))) Истинно или ложно:
false true true true false true В таблицевчетвертомпримеревыражениеистинно, посколькуприоритетопе- рации "&&" выше, чему "||". Приоритет (порядоквыполнения) различныхопераций Си++ можноузнатьвучебникеилируководствепоязыкуСи++, атакжевсправочной системе Visual C++
(темаOperator Precedence
). Еслиувасвозникаютсомненияотно- сительно приоритетаопераций, применяйтекруглыескобки(). Применениеэтих скобок облегчаетчтениепрограмм. Составные логическиевыраженияобычноприменяютсявкачествеусловийв операторах if и вциклахfor. Например: ... ... if ( total_test_score >= 50 && total_test_score < 65 ) cout << "Вы прошли тест со средним результатом.\n"; ... ... У логических выраженийвСи++ естьещеодноважноесвойство. ВСи++ ис- тинное значение ("true") представляетсяввидецелогочисла 1 (большинство ком- пиляторов любоеположительноечислосчитаютистиннымзначением), аложное значение ("false") ввидезначения 0. Этоможетпривестикошибкам. Например, легко напечатать "=" вместо "==". Поэтомуфрагмент ... ... if ( number_of_people = 1 ) cout << "Есть только один человек.\n"; ... ... всегда будетпечататьсообщение "Естьтолькоодинчеловек", дажееслидооператора if переменная "number_of_people" былабольше 1. 28 6. Сводка результатов
В даннойлекциидовольноподробнорассматривалисьпеременныеязыкаСи++. У переменныхвсегдаестьопределенныйтипданных. Переменныеприменяютсядля временного илипостоянногохранениязначенийразныхтипов. Значенияпеременным можно присваиватьразличнымиспособами. Ввыраженияхдлявычисленияновых значений переменныхможно использоватьразличныеарифметическиеилогические операции. 7. Упражнения
Упражнение 1 Для преобразованиятемпературыизшкалыЦельсиявабсолютнуюшкалутем- ператур (шкалуКельвина) надо добавить ктемпературепоЦельсиюзначение 273.15. В шкалуФаренгейтатемпературапоЦельсиюпреобразуетсяt
= 1.8t
o + 32 f
. Напишите программупреобразованиязначенийтемпературы, котораябудет печатать наэкранеследующуютаблицу: Цельсий Фаренгейт Абсолютная температура 0 32.00 273.15 20 68.00 293.15 40 104.00 313.15 ... ... ... ... ... ... 300 572.00 573.15 Упражнение 2 Измените программуизупражнения 1 так, чтобыоназапрашивалаупользова- теля минимальную имаксимальнуютемпературупоЦельсию, которыедолжныбыть в первойипоследнейстрокахтаблицы. Программатакжедолжназапроситьшагиз- менения температуры (наэтозначениедолжныотличатьсятемпературывсоседних строках таблицы, вупражнении 1 шагбылравен 20-тиградусам). Перед таблицейпрограммадолжнавывестинесколькострокспояснениемсво- их действий, атакжеповторитьвыводнаэкранвведенныхпользователемданных. Упражнение 3 Напишите программу, котораясчитываетсклавиатурысимвол (ch) изатемвы- водит одноизследующихсообщений (вместо ch долженвыводитьсявведенныйсим- вол, авместо ... –соответствующаяпрописнаяилистрочнаябуква): а) еслисимвол ch является 2ьстрочнойбуквой–сообщение "Букве ch соответст- вует прописнаябуква ...", б) если ch являетсяпрописнойбуквой–сообщение "Букве ch соответствует строчная буква ...", в) если ch неявляетсябуквой–сообщение "Символ ch неявляетсябуквой". Для составлениянеобходимыхусловийобратитеськрасширеннойтаблице символов ASCII (см. п.8.3). Упражнение 4 Напишите программудлявозведенияпроизвольногочислаx в положительную степень n с помощьюциклаfor. (Естьлиспособыповышенияэффективностивашей программы?) 29 8. Приложения
8.1 Служебные слова Си++ По назначениюслужебныесловаязыкаСи++ можноразделитьнанесколько групп. Нижеперечисленыэтигруппыиотносящиесякнимслова. Полужирным
шрифтом выделеныслова, назначениекоторыхвыузнаетевданномвводномкурсе. •Типы данных (определяюттипыданных, которыеможнохранитьвпамяти компьютера). char short int long
(целые числа) enum
(тип "перечисление") double float
(вещественные числа) void
struct
union typedef
(типы, определяемые пользователем) •Модификаторы типовданных (позволяютзадатьнекоторыесвойствахране- ния данныхвпамяти). signed unsigned
volatile register const static extern
auto •Управление порядкомвыполненияоператоров. if else
(ветвление с двумя вариантами) switch case default
(множественное ветвление) for while do
(циклы) break continue
return
(возврат из функции) goto (безусловный переход) •Динамическое распределениепамяти. new delete
•Объектно-ориентированноепрограммирование (этисловабудутподробно рассматриваться вотдельномкурсеобъектно-ориентированногопрограм- мирования ипроектирования). class private protected public virtual this friend template operator •Обработка исключений (особыймеханизмобработкиошибоквобъектно- ориентированных программах). try throw catch •Разное. sizeof
inline asm 30 8.2 Таблица символов ASCII 8.3 Расширенная таблица символов ASCII для кодовой страницы DOS-866 31 ЛЕКЦИЯ 3. Функции и процедурная абстракция
1. Назначение подпрограмм
Естественный иинтуитивнопонятныйподходкрешениюбольшихсложных задач состоитвтом, чтобыразбитьбольшуюзадачунанаборменьших, которыемож- но решитьболееилименеенезависимоизатемскомбинироватьполученныерешения для полученияполногорешения. Натакомподходеоснованаметодологияструктур- ного программирования, котороегосподствоваловразработкепрограммногообеспе- чения допоявления объектно-ориентированногоподхода. При структурномпрограммированиибольшаяпрограммаразделяетсянанабор более илименеенезависимыхподпрограмм
. ВСи++ подпрограммыназываются функциями
(вПаскалеинекоторыхдругих языкахпрограммированияестьдватипа подпрограмм – "процедуры" и "функции"). Подпрограммы уженеоднократновстречалисьвпредыдущихлекциях. Напри- мер, впрограмме 2.3.2 дляпостроениятаблицыквадратныхкорнейбылприменен следующий циклfor: ... #include<math.h> ... ... for ( number=1 ; number<=10 ; number=number+1 ) { cout.width(20); cout << number << sqrt(number) << "\n"; } ... Функция "sqrt(...)" –этоподпрограмма, описаниекоторойхранитсявзаголо- вочном файле "math.h", ареализация–вбиблиотечномфайле "math.lib". Привызове функции "sqrt(...)" ейпередаетсячисловойпараметр "number", функцияприменяет алгоритм вычисленияквадратногокорняизэтогочисла, изатемвозвращаетвычис- ленное значениеобратновместовызова. Дляпримененияэтойфункциипрограмми- сту совсемнеобязательнознать, какойименноалгоритмреализованвнутринее. Глав- ное, чтобыфункциягарантированновозвращалаверныйрезультат. Былобыдовольно нелепо включатьвявномвидеалгоритмизвлеченияквадратногокорня (и, возможно, делать этонеоднократно) вглавнуюфункциюпрограммы "main". В даннойлекцииописывается, какпрограммистможетопределятьсвоисобст- венные функции. Сначалапредполагается, чтоэтифункцииразмещаютсяводном файле сфункцией "main". Вконцелекциипоказывается, какраспределятьфункции программы понесколькимфайлам. 2. Определение новых функций
Простым примеромопределенияииспользованияновойфункцииявляется программа 2.1 (внейпользовательскаяфункцияназывается "area(...)"). Этапро- грамма вычисляетплощадьпрямоугольниказаданнойдлиныиширины. #include<iostream.h> int area(int length, int width); /* Описание функции */ 32 // ГЛАВНАЯ ФУНКЦИЯ: int main() { int this_length, this_width; cout << "Введите длину: "; /* <--- строка 10 */ cin >> this_length; cout << "Введите ширину: "; cin >> this_width; cout << "\n"; /* <--- строка 14 */ cout << "Площадь прямоугольника с размерами "; cout << this_length << "x" << this_width; cout << " равна " << area(this_length, this_width) << "\n"; return 0; } // КОНЕЦ ГЛАВНОЙ ФУНКЦИИ // ФУНКЦИЯ ВЫЧИСЛЕНИЯ ПЛОЩАДИ: int area(int length, int width) /* Начало определения функции */ { int number; number = length * width; return number; } /* Конец определения функции */ // КОНЕЦ ФУНКЦИИ Программа 2.1.
Программа 2.1, конечно, допускаетзаписьвболеесжатойформе, новданном виде онаслужитхорошейиллюстрациейнекоторыхсвойствфункцийСи++: •Структура определения (реализации) функцииподобнаструктурефункции "main()" –втелефункцииестьописаниялокальныхпеременныхииспол- няемые операторы. •У функциимогутбытьпараметры, которыеуказываютсявспискевнутри круглых скобокпослеименифункции. Укаждогопараметразадаетсятип. •Если вызовфункциивстречаетсяранееееопределения, товначалепро- граммы должносодержатьсяописаниефункции (прототип). Прототип функции описываетеепараметрыитипвозвращаемогозначения. Обычно прототипы функцийразмещаютсяпослеописанияглобальныхконстант. Внутри функцииможетбытьнесколькооператороввозврата "return". Функ- ция завершаетсяпослевыполнениялюбогооператора "return". Например: double absolute_value(double number) { if (number >= 0) return number; else return -number; } 33 3. Способы передачи параметров внутрь функций
Во всехрассмотренныхдосихпорпримерахпараметры функцийпередавались по значению
. Привызовеизфункции "main()" вызываемойфункциипередаютсяко-
пии
указанных переменных. Например, впрограмме 2.1 функции "area(...)" переда- ются текущиезначенияпеременных "this_length" и "this_width". Затемфункция "area(...)" сохраняетпереданныезначениявсобственныхлокальныхпеременных, и именно этипеременныеучаствуютвпоследующихвычисленияхвнутрифункции. 3.1 Передача параметров по значению Функции, принимающиепараметрыпо значению
, "безопасны" втомсмысле, что онинемогутслучайноизменитьпеременныевызывающейфункции (т.е. уфунк- ций нетскрытыхпобочных эффектов
). Большинствофункцийпроектируютсяименно таким образом. Программа 3.1 поясняет, почемуважногарантировать "сохранность" перемен- ных вызывающейфункции. Этапрограммадолжнавыводитьнаэкранфакториали корень изчисла, введенногопользователем: Введите положительное число: 4
Факториал 4! равен 24, а квадратный корень из 4 равен 2. Для извлеченияквадратногокорняприменяетсябиблиотечнаяфункция "sqrt(...)". Библиотечнойфункциидлявычисленияфакториаланет, поэтомупри- дется написатьсобственнуюфункцию (вычисляющуюдлялюбогоположительного целого числаn значение n!=(1*2*3*...*n)). #include<iostream.h> #include<math.h> int factorial(int number); // ГЛАВНАЯ ФУНКЦИЯ: int main() { int whole_number; cout << "Введите положительное число:\n"; cin >> whole_number; cout << "Факториал " << whole_number << "! равен "; cout << factorial(whole_number); cout << ", а квадратный корень из " << whole_number; cout << " равен " << sqrt(whole_number) << ".\n"; return 0; } // КОНЕЦ ГЛАВНОЙ ФУНКЦИИ // ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ ФАКТОРИАЛА: int factorial(int number) { int product = 1; for ( ; number > 0 ; number--) product *= number; 34 return product; } // КОНЕЦ ФУНКЦИИ Программа 3.1.
Если быфункция "factorial(...)" изменялапеременнуювызывающей функции, топрограмма 3.1 выдавалабыследующийответ (формальноправильный, но посмыслузадачинекорректный): Введите положительное число: 4
Факториал 4! равен 24, а квадратный корень из 0 равен 0. 3.2 Передача параметров по ссылке Все-такииногдабываетнеобходимо, чтобыфункцияизменилазначениепере- данного ейпараметра. Рассмотримпрограмму 2.1. С 10-йпо 14-юстрокувнейвы- полняется запросразмеров прямоугольника, азатемвычисляетсяегоплощадь. При структурномпрограммированиинезависимыепосмыслучастипрограммы принято оформлятьввидеотдельныхфункций. Дляполученияданныхотпользова- теля создадимфункцию "get_dimensions". Вданномслучаенеобходимо, чтобыэта функция изменялазначенияпеременных "this_length" и "this_width" (переданныхей в качествепараметров) –помещалавнихзначения, введенныепользователемскла- виатуры. Изменениепараметровфункциивозможноприпередачепараметровпо
ссылке
. Утакихпараметроввзаголовкефункциипослеименитипауказываетсясим- вол "&". #include<iostream.h> int area( int length, int width ); void get_dimensions( int& length, int& width ); // ГЛАВНАЯ ФУНКЦИЯ: int main() { int this_length, this_width; get_dimensions( this_length, this_width ); cout << "Площадь прямоугольника с размерами "; cout << this_length << "x" << this_width; cout << " равна " << area( this_length, this_width ) << "\n"; return 0; } // КОНЕЦ ГЛАВНОЙ ФУНКЦИИ // ФУНКЦИЯ ВВОДА РАЗМЕРОВ ПРЯМОУГОЛЬНИКА: void get_dimensions( int& length, int& width ) { cout << "Введите длину: "; cin >> length; cout << "Введите ширину: "; cin >> width; cout << "\n"; 35 } // КОНЕЦ ФУНКЦИИ // ФУНКЦИЯ ВЫЧИСЛЕНИЯ ПЛОЩАДИ: int area( int length, int width ) { return length*width; } // КОНЕЦ ФУНКЦИИ Программа 3.2.
Функция _______"get_dimensions" изменяетзначенияпараметров "this_length" и "this_width", ноневозвращаетникакогозначения (т.е. неявляется "функцией" вма- тематическом смысле). Этотфактотражаетсяивпрототипе, ивопределениифунк- ции –вкачествевозвращаемогозначенияуказантип "void" ("пустой" тип). 4. Полиморфизм и перегрузка функций
Одним изхарактерныхсвойствобъектно-ориентированногоязыка, втомчисле и Си++, являетсяполиморфизм
–использованиеодногоименидлявыполненияраз- личных действийнадразличнымиобъектами. Применительнокфункциямэтоназы- вается перегрузкой
. ДляосновныхоперацийСи++ перегрузкаужевстроенавязык: например, усложениясуществуеттолькоодноимя, "+", ноегоможноприменятьдля сложения какцелых, такивещественныхзначений. Этаидеярасширяетсянаобра- ботку операций, определенныхпользователем, т.е., функций. Перегруженные функцииимеютодинаковыеимена, норазныеспискипарамет- ров ивозвращаемыезначения (см. программу 4.1). #include<iostream.h> int average( int first_number, int second_number, int third_number ); int average( int first_number, int second_number ); // ГЛАВНАЯ ФУНКЦИЯ: int main() { int number_A = 5, number_B = 3, number_C = 10; cout << "Целочисленное среднее чисел " << number_A << " и "; cout << number_B << " равно "; cout << average(number_A, number_B) << ".\n\n"; cout << "Целочисленное среднее чисел " << number_A << ", "; cout << number_B << " и " << number_C << " равно "; cout << average(number_A, number_B, number_C) << ".\n"; return 0; } // КОНЕЦ ГЛАВНОЙ ФУНКЦИИ // ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 3-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number, int third_number ) 36 { return ((first_number + second_number + third_number)/3); } // КОНЕЦ ФУНКЦИИ // ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 2-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number ) { return ((first_number + second_number)/2); } // КОНЕЦ ФУНКЦИИ Программа 4.1.
Программа 4.1. выводитнаэкрансообщения: Целочисленное среднее чисел 5 и 3 равно 4. Целочисленное среднее чисел 5, 3 и 10 равно 6. 5. Процедурная абстракция и "хороший" стиль программирования
Функции помогаютприменятьдляразработкипрограммструктурныйметод проектирования "сверху вниз
". Приэтомрешаемаязадачаделитсянаподзадачи (иза- тем напод-подзадачиит.д.). Длярешениякаждойподзадачипрограммистреализует отдельную функцию, приэтомемуненужнознатьдеталиреализацииостальных функций. Чтобы функциеймогвоспользоватьсядругойпрограммист, онадолжнаиметь осмысленное имяикомментарийсописаниемназначенияфункции, еепараметров и возможных возвращаемыхзначений. Опытные программистынаначальныхэтапахразработкичастоприменяют пустые функции (заглушки
), которыесодержаттолькооператорвозвратазначениясо- ответствующего типа. Этифункцийоблегчаютотладкуглавнойфункцииилипросто функции болеевысокогоуровня. Выделение врешаемойзадачефункций методом "сверхувниз" частоназывает- ся функциональной
или процедурной абстракцией
. Припроектированиинезависимых друг отдругафункцийширокоприменяетсяпередачапараметровпозначениюило- кальные переменные внутрифункций. Послереализациипрограммистможетрас- сматривать подобныефункциикак "черныеящики". Дляихиспользованиязнатьде- тали реализациинеобязательно. 6. Модульное программирование
Помимо метода "сверхувниз", вторымважнымметодомструктурногопроек- тирования являетсяметодмодульногопрограммирования. Онпредполагаетразделе- ние текстапрограммынанесколькофайлов, вкаждомизкоторыхсосредоточеныне- зависимые частипрограммы (сгруппированныепосмыслуфункции). В программахнаСи++ частоприменяютсябиблиотечныефункции (например, "sqrt(...)"). Дляиспользованиябольшинства функций, втомчислеибиблиотечных, необходимы двафайла (вскобкахпримерыданыдля "sqrt(...)"): •Заголовочный файл
("math.h") спрототипомфункции ("sqrt(...)" имногих других математическихфункций). Поэтомувпрограммах, вызывающих 37 "sqrt(...)", естьстрока "#include <math.h>", анеявноеобъявлениеэтой функции. •Файл реализации
(дляпользовательскихфункцийэтофайлысисходным текстом наСи++, абиблиотечныефункцииобычнохранятсявскомпилиро- ванном видевспециальныхбиблиотечных файлах, например, "libcmtd.lib"). Файлыреализациипользовательскихфункций (обычнос расширением ".cpp") содержатопределенияэтихфункций. Разделение исходноготекстаназаголовочныефайлыифайлыреализациипо- казано впрограмме 6.1, котораявыполняеттежедействия, чтоипрограмма 4.1. Те- перь программасостоитизтрехфайлов: главногофайла, заголовочногофайласопи- саниями двухфункцийрасчетасреднегозначения, исоответствующегофайлареали- зации. В главномфайлесодержитсяследующийтекст: #include <iostream.h> #include "averages.h" int main() { int number_A = 5, number_B = 3, number_C = 10; cout << "Целочисленное среднее чисел " << number_A << " и "; cout << number_B << " равно "; cout << average(number_A, number_B) << ".\n\n"; cout << "Целочисленное среднее чисел " << number_A << ", "; cout << number_B << " и " << number_C << " равно "; cout << average(number_A, number_B, number_C) << ".\n"; return 0; } Главный файл программы 6.1.
Обратите внимание, чтоимяфайластандартнойбиблиотеки "iostream.h" вди- рективе препроцессора "include" заключеновугловыескобки ("<>"). Файлысимена- ми вугловыхскобкахпрепроцессорищетвбиблиотечныхкаталогах, указанныхвна- стройках компилятора. Именапользовательскихзаголовочныхфайловобычноза- ключаются вдвойныекавычки, ипрепроцессорищетихвтекущемкаталогепро- граммы. Далее приведеносодержимоефайла "averages.h". Внем естьидентификатор препроцессора "AVERAGES_H" ислужебныесловапрепроцессора "ifndef" ("еслинеоп- ределено"), "define" ("определить") и "endif" ("конецдирективыif"). Идентифика- тор "AVERAGES_H" являетсяглобальным символическимименемзаголовочногофайла. Первые двестрокифайласлужатзащитойотповторнойобработкитекстазаголовоч- ного файлапрепроцессором, наслучай, есливисходномтекстепрограммыстрока "#include "averages.h"" встречаетсянесколькораз. В заголовочныхфайлах, кромепрототиповфункций, часторазмещаютсяопи- сания глобальных константипользовательскихтипов. Подробнееобэтомговоритсяв курсе объектно-ориентированногопрограммирования. #ifndef AVERAGES_H # define AVERAGES_H 38 // (Определения констант и пользовательских типов) // ПРОТОТИП ФУНКЦИИ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 3-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number, int third_number ); // ПРОТОТИП ФУНКЦИИ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 2-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number ); #endif Заголовочный файл averages.h.
Ниже показаносодержимоефайла "averages.cpp" сисходнымтекстомполь- зовательских функций: #include <iostream.h> #include "averages.h" // ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 3-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number, int third_number ) { return ((first_number + second_number + third_number)/3); } // ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ ЦЕЛОЧИСЛЕННОГО СРЕДНЕГО // ЗНАЧЕНИЯ 2-Х ЦЕЛЫХ ЧИСЕЛ: int average( int first_number, int second_number ) { return ((first_number + second_number)/2); } Файл реализации averages.cpp.
Программа
6.1
демонстрирует основное достоинство модульного подхода
:
при
изменении деталей реализации в файле
"
averages.cpp
"
не обязательно вносить из
-
менения в файл
"
averages.h
"
или в главный файл программы
.
7. Сводка результатов
В данной лекции описано
,
как в Си
++
можно создавать новые функции
.
Есть
два способа передачи параметров внутрь функции
:
по значению и по ссылке
.
Функ
-
ции облегчают применение процедурной абстракции при разработке программ мето
-
дом
"
сверху вниз
".
При модульном подходе описание и реализация функций разме
-
щаются в отдельных файлах
,
в таком случае для вызова функции необходимо вклю
-
чать в текст программы заголовочный файл
.
39
8. Упражнения
Упражнение 1
В программе из упражнения
2
лекции
2 (
файл
ex2_2.cpp)
| |||||