Автор: Феськов С.В.
Теги: воспитание обучение образование методика преподавания учебных предметов в общеобразовательной школе программирование информатика языки программирования 11 класс 10 класс язык программирования c++
ISBN: 978-5-7057-1674-6
Год: 2009
информатика JlkozhaMJiuhoSaHke на азьисе C++ 10-11 классы
В помощь 558т преподавателю $ информатики ^Гфограммировгшие-^ерженьпрофильного курса информатики. Изучая программирование, учащиеся приобщаются к алгоритмической культуре, познают азы профессии программиста. Настоящее пособие содержит материалы к за- нятиям по изучению наиболее популярного и пер- спективного языка программирования - C++. Круг рассматриваемых в пособии тем ограни- чен описанием структурных возможностей языка и представляет начальный этап обучения, который является принципиально важным для формирования культуры программирования. Предложенный материал целесообразно ис- пользовать для подготовки к занятиям в рамках элективного курса, при организации инди- видуальной работы с учащимися, интересую- щимися программированием. Предназначено учителям информатики стар- шей школы; может быть полезным учащимся V10-11 классов, студентам вузов. «УЧИТЕЛЬ.
С. В. ФЕСЬКОВ ИНФОРМАТИКА 10-11 КЛАССЫ ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ C++ (материалы к занятиям) Волгоград Издательство «Учитель»
УДК 371.3 ББК 74.263.2 Ф44 Феськов С. В. Ф44 Информатика. 10-11 классы. Программирование на язы- ке C++ (материалы к занятиям) / С. В. Феськов. - Волго- град: Учитель, 2009. - 133 с. ISBN 978-5-7057-1674-6 Программирование - стержень профильного курса информатики. Изучая про* граммирование, учащиеся приобщаются к алгоритмической культуре, познают азы профессии программиста. Настоящее пособие содержит материалы к занятиям по изучению наиболее по* пулярного и перспективного языка программирования - C++. Круг рассматривае- мых в пособии тем ограничен описанием структурных возможностей языка и пред- ставляет начальный этап обучения, который является принципиально важным для формирования культуры программирования. Предложенный материал целесообразно использовать для подготовки к заняти- ям в рамках элективного курса, при организации индивидуальной работы с учащи- мися, интересующимися программированием. Предназначено учителям информатики старшей профильной школы; может быть полезным учащимся 10-11 классов, студентам вузов. УДК 371.3 ББК 74.263.2 ISBN 978-5-7057-1674-6 О Феськов С. В., 2007 © Издательство «Учитель», 2007 © Оформление. Издательство «Учитель», 2007 Издание 2009 г.
ВВЕДЕНИЕ Современному человеку требуется не только определенный набор знаний, но и умение самостоятельно приобретать недо- стающие и применять их в жизни. Одним из основных источни- ков информации в современном мире становится компьютер, умение работать с которым является, таким образом, важным условием развития человека и его успешности. В школе изучение информатики переносится в более ранние классы, пересматривается содержание предмета, многие разде- лы расширяются, углубляются, появляются новые. Однако тем- пы развития информатизации общества обгоняют учебные пла- ны, школьную программу. В основной школе на эти темы отво- дится недостаточно времени, нет возможности организовать ин- дивидуальную работу. Для учащихся, углубленно изучающих курс информатики, актуальным является овладение навыками алгоритмического мышления, знание различных языков программирования, уме- ние их сравнивать, сопоставлять, анализировать. Кроме того, они должны уметь применять языки программирования для ре- шения конкретных прикладных задач, выбирать оптимальные способы и программные средства для достижения поставленных целей. Программирование - стержень профильного курса информа- тики. Изучение основ программирования связано с целым рядом умений и навыков (организация деятельности, ее планирование и т. д.), которые носят общеинтеллектуальный характер и фор- мирование которых - одна из основных задач современной школы. Очень велика роль изучения программирования для развития мышления школьников, формирования многих приемов умст- венной деятельности. Изучая программирование, учащиеся при- общаются к алгоритмической культуре, познают азы профессии программиста. 3
Данное пособие предназначено учителям информатики стар- шей профильной школы и содержит материалы к занятиям по изучению одного из наиболее популярных и перспективных языков программирования - C++. Пособие ориентировано на изучение основных, базовых конструкций C++ и обретение пер- вичных навыков алгоритмизации и программирования. В силу своей специфики данный курс ни в коем случае не может пре- тендовать на полноту изложения всех основ этого языка. В по- собии содержится описание лишь его основных структурных возможностей; вопросы объектно-ориентированной разработ- ки/программирования и использования визуальных средств C++ Builder для создания оконных приложений Windows не затраги- ваются. Вместе с тем автор уверен, что работа учащегося над простыми консольными программами с использованием пред- ложенного минимума языковых средств дает незаменимый опыт развития практического алгоритмического мышления и является одним из важнейших этапов обучения дисциплинам программи- рования. Предложенный материал может быть использован для под- готовки к занятиям в рамках элективного курса или при работе со старшеклассниками, интересующимися программированием и желающими изучить основы программирования на данном языке. Организация занятий с использованием предложенного материала предполагает знание учащимися основ информатики в объеме базового уровня школьной программы, а также не- большой опыт работы с персональным компьютером в операци- онной системе Windows. Пособие ориентировано на использование учащимися про- граммного пакета Borland C++ Builder 6.0 и в качестве введения содержит описание полного цикла создания консольного при- ложения с использованием этой системы. В то же время пред- ставленный здесь материал может быть легко адаптирован для 4
использования вместе с другими компиляторами и системами разработки. Пособие организовано в виде набора тем, посвященных от- дельным конструкциям изучаемого языка. В рамках каждой те- мы учитель найдет теоретический материал, который может быть основой лекционного занятия, и лабораторную работу, вы- полняя которую, учащиеся закрепляют теоретические знания на практике. Система задач и заданий для самостоятельной работы учащихся позволит учителю разнообразить занятия и повысить качество знаний старшеклассников по информатике. Кроме то- го, предложенный материал предполагает организацию учебно- го процесса в системе лекционно-семинарских занятий, что по- зволяет максимально приблизить учащихся к обучению в выс- ших учебных заведениях. 5
ПРИМЕРНОЕ РАСПРЕДЕЛЕНИЕ ЗАНЯТИЙ ПО ПРОГРАММИРОВАНИЮ НА ЯЗЫКЕ C++ (рекомендуемое количество часов) № п/п Тема занятия Содержание занятия Кол-во часов, тип занятия 1 C++ Builder и консоль- ные прило- жения Программа, язык программирования. Создание консольного приложения в C++ Builder. Компиляция, компоновка и запуск программы. Общая структура программы на языке C++. Использова- ние библиотек. Объявление и инициа- лизация переменных. Стандартные ти- пы данных 1 (лекция) 2 Операции ввода- вывода. Арифмети- ческие опе- рации Консольный ввод-вывод. Потоковый ввод-вывод. Арифметические операции и математические функции 1 (лекция), 2(практи- ка) 3 Оператор условия if- else Назначение и синтаксис. Сокращенные варианты записи. Вложенные операто- ры условия. Составные логические вы- ражения 1 (лекция), 3 (практи- ка) 4 Оператор цикла for Назначение и синтаксис. Сокращенные варианты записи. Вложенные операто- ры цикла 1 (лекция), 3(практи- ка) 5 Массивы I. Поэлемент- ные опера- ции Одномерные (линейные) массивы. Мно- гомерные массивы. Типизированные константы. Инициализация элементов массива 1 (лекция), 3 (практи- ка) 6 Массивы II. Алгоритмы поиска и сортировки Линейный поиск по условию. Поиск максимального (минимального) элемен- та. Сортировка методами прямого вы- бора и пузырька 1 (лекция), 3 (практи- ка) 7 Функции Определение функции. Вызов функции. Формальные и фактические параметры. Прототипы функций 2 (лекция), 5 (практи- ка) ИТОГО 27 6
Тема 1 C++ BUILDER И КОНСОЛЬНЫЕ ПРИЛОЖЕНИЯ 1. Программа, язык программирования. Компьютерной программой будем называть набор инструк- ций или команд, которые человек (программист) дает компью- теру на выполнение. Среди этих инструкций могут быть как простейшие (например, выполнение арифметической опера- ции), так и более сложные (вывод информации на экран, запись файла на жесткий диск и т. д.). Язык, с помощью которого про- граммист общается с компьютером, называется языком про- граммирования. Для компьютерного процессора «родным» является машин- ный язык, содержащий в качестве команд специальные число- вые коды. В силу понятных трудностей, связанных с написани- ем программ в машинных кодах, в настоящее время разработано множество языков высокого уровня, облегчающих процесс про- граммирования, тестирования, отладки и т. д. Основными пре- имуществами использования этих языков являются простота и логичность их конструкций; широкие возможности управления ходом программы; наличие удобных библиотек и т. д. В рамках настоящего курса мы будем использовать язык C++, получив- ший широкое распространение в прикладном и системном про- граммировании, а также в компьютерном моделировании. Историческая справка Язык C++ развился из С, который, в свою очередь, был со- здан на основе двух предшествующих языков - BCPL и В. Язык BCPL был создан в 1967 году Мартином Ричардом как язык для написания компиляторов и программного обеспечения операци- онных систем. Кен Томпсон предусмотрел много возможно- 7
стей в своем языке В - дубликате BCPL - и использовал В для создания более ранних версий операционной системы UNIX в Bell Laboratories в 1970 году на компьютере DEC PDP-7. И BCPL, и В были «нетипичными» языками - каждый элемент данных занимал одно «слово» в памяти, и бремя обработки эле- мента данных, например, целого или действительного числа, падало на плечи программиста. Язык С был развит из В Денисом Ритчи и первоначально реализован в 1972 году. Он использует многие важные концеп- ции BCPL и В, а также добавляет типы данных и другие свой- ства. Первоначально С приобрел широкую известность как язык разработки операционной системы UNIX. Сегодня факти- чески все новые операционные системы написаны на С или на C++. В течение последних десятилетий С стал доступным для большинства компьютеров. Он независим от аппаратных средств. При тщательной разработке на С можно написать мобильные программы, переносимые на большинство компью- теров. В конце 70-х годов С развился в то, что теперь относят к «традиционному С», «классическому С» или «С Кернигана и Ритчи». Публикация книги Кернигана и Ритчи «Язык програм- мирования С» привлекла широкое внимание к этому языку. Широкое распространение С на различных компьютерах (аппаратных платформах) привело ко многим вариациям языка. Некоторые из них были похожи, но несовместимы друг с дру- гом. Это было серьезной проблемой для разработчиков про- грамм, нуждавшихся в написании совместимых программ. Ста- ло ясно, что необходима стандартная версия С. В 1983 году при Американском Национальном Комитете Стандартов (ANSI) в области вычислительной техники и обработки информации был создан технический комитет X3J11, основной целью которого 8
стало «обеспечить недвусмысленное и машинно-независимое определение языка». В 1989 году стандарт был утвержден. ANSI скооперировался с Международной Организацией Стан- дартов (ISO), чтобы стандартизировать С в мировом мас- штабе; совместный стандарт был опубликован в 1990 году и назван ANSI/ISO 9899:1990. C++ - расширение С - был разработан Бьерном Страуст- рупом в начале 80-х годов в Bell Laboratories. C++ обеспечивает ряд свойств, которые «приводят в порядок» язык С, но, что более важно, он обеспечивает возможность объектно- ориентированного программирования. Это явилось революци- онной идеей в мире программного обеспечения. Объекты - это эффективные повторно используемые компоненты програм- много обеспечения, моделирующие элементы реального мира. Разработчики программного обеспечения обнаруживают, что использование достижений модульного, объектно-ориентиро- ванного проектирования может значительно повысить про- дуктивность групп разработки по сравнению с предшествую- щей популярной технологией программирования, такой как структурное программирование. Объектно-ориентированные программы легче понимать, корректировать и модифициро- вать. C++ - гибридный язык, он предоставляет возможность программировать и в стиле С, и в объектно-ориентированном стиле, и в обоих стилях сразу. С середины 90-х годов C++ ста- новится доминирующим системно-образующим языком. Программа на языке C++ представляет собой дисковый файл с расширением СРР (*.срр). Процесс создания этого файла на- зывают редактированием, он, как правило, выполняется с по- мощью специального редактора кода (code editor). 9
test.exe (исполнимый файл) По завершении редактирования исходный код программы необходимо перевести на машинный язык. Этот процесс назы- вают компиляцией, он производится компилятором языка (com- piler). Результат этой стадии - объектный файл с расширением OBJ (*.obj). Завершает разработку программы фаза компоновки, в ре- зультате которой создается исполнимый файл с расширением EXE (*.ехе), готовый к работе. На схеме выше указаны все ос- новные стадии создания этого файла. Современные системы программирования часто объединяют в себе все компоненты, необходимые для создания исполнимого файла, то есть выполняют одновременно функции редактора ко- да, компилятора, компоновщика, а также некоторые другие - библиотекаря (librarian), отладчика (debugger), профайлера (pro- filer) и т. д. Такие системы называют интегрированными среда- ми разработки (IDE, integrated development environ-ment). Про- граммный пакет Borland C++ Builder является примером такой IDE, которую мы будем использовать в рамках настоящего курса. 10
Далее мы будем предполагать, что читатель работает в опе- рационной системе Windows и обладает на своем компьютере установленной копией Borland C++ Builder версии 6.0. Следует отметить, что отличия данной версии от более ранних (а также более поздней C++ Builder 2007) для нас не являются принципи- альными. 2. Создание консольного приложения в C++ Builder. Найдите на Рабочем столе Windows своего компьютера иконку C++ Builder и запустите программу. Перед вами появит- ся набор окон, изображенных на рисунке (см. рис. ниже). (Здесь и далее возможны незначительные несоответствия тем изобра- жениям, которые вы видите на своем компьютере, в зависимо- сти от настроек системы и от версии C++ Builder.) А. С- Builder 6 Projertl ода а (jkleft АТар| \иы» си>Аиы» h/Dnawn/ ffiConrterii В ОМ ode S)B«dMc«w BadwVMh bdLeftTcAght (ЬБуМмМапи. A^uBtond АПнВ»«ММ25б (Я Anchor» AOoSaoi 'll
В меню программы (в верхней текстовой строке окна) выбе- рите пункт File. В выпавшем подменю выберите New, далее на- жмите Other... Перед вами откроется диалоговое окно New Items, изображенное на рисунке: Для создания консольного приложения выберите в этом окне иконку Console Wizard (выделена на рис.) и нажмите кнопку ОК. Снимите все флажки в появившемся окне Console Wizard за ис- ключением флажка Console Application (см. рис. ниже). В каче- стве языка выберите C++ и снова нажмите ОК. Cpnsole Wizard Source Type-------" Г£ (• C++ I г UseyCL I Г UseCQ< 1 F M^Tfreaded : p Console Application F Specify project source....... Открывшиеся окна и есть среда разработки кон- сольного приложения C++ Builder. Она состоит из нескольких компонентов (см. рис. на с. 13), из кото- рых нами будет использо- ваться только часть. Cancel [ Help | 12
Цифрой 1 на рисунке обозначено окно редактора кода (цен- тральное окно на экране). В этом окне программист набирает исходный код программы. Окно уже содержит некоторый текст - это шаблон для консольной программы на языке C++. Цифрами 2 и 3 (слева) обозначены окна просмотра объектов Object Tree- View и Object Inspector, они не используются при разработке консольных приложений и поэтому в настоящее время не со- держат никакой полезной информации. В верхней части экрана, кроме Главного меню, содержатся Панель быстрых кнопок (цифра 4) и Палитра визуальных компонентов (цифра 5). По- следняя также задействуется только при разработке оконных приложений и нами в рамках этого курса использоваться не бу- дет. Панель быстрых кнопок просто дублирует некоторые ос- новные пункты Главного меню. ' 13
Перейдите в окно редактора и добавьте в код программы не- сколько строк в соответствии с приведенным ниже листингом (эти строки выделены полужирным шрифтом): //-------------- Традиция ---------------- #pragma hdrstop #include <iostream.h> #include <conio.h> #pragma argsused int main(int argc, char* argv[]) { cout « "Hello, world!"; getch(); return 0; } //---------------------------------------- 14
Сохраните текст программы в дисковом файле. Для этого в Главном меню выберите последовательно пункты File | Save As... В появившемся диалоговом окне (показано на с. 14) выбе- рите подкаталог для сохранения программы, войдите в него, введите имя файла, например hello, в соответствующее поле и нажмите кнопку Сохранить. Перед вами появится еще одно диалоговое окно, в котором требуется ввести название проекта. В поле Имя файла еще раз введите hello и снова нажмите кнопку Сохранить. 3. Компиляция, компоновка и запуск программы. После того, как исходный код программы hello набран и за- писан на диск, он должен быть откомпилирован и скомпонован. Фаза компиляции сопровождается проверкой синтаксиса про- граммы, все найденные при этом ошибки сообщаются пользова- телю. Выберите в Главном меню последовательно пункты Project | Compile Unit или, иначе, одновременно нажмите клавиши Alt и F9. Это действие запустит компиляцию, ее ход будет отражаться в открывшемся окне Compiling. По окончании процесса в окне будет, в частности, содержаться информация о количестве про- граммных ошибок Errors и предупреждений Warnings, если та- ковые были зафиксированы компилятором в написанной вами программе. Ошибки Errors означают нарушения синтаксиса языка C++, которые делают невозможной дальнейшую компоновку про- граммы. Все ошибки должны быть вами устранены, для чего можно воспользоваться сообщениями компилятора, в которых указывается номер строки и краткое описание ошибки. Предупреждения Warnings означают подозрительные конст- рукции, которые могут функционировать неправильно - не так, как это задумано программистом. Наличие предупреждений не приводит к останову процессов компиляции и компоновки. 15
Однако к ним также следует относиться очень внимательно, так как в большинстве случаев они суть следствия логических оши- бок в программе, которые трудно поддаются обнаружению. Будем считать, что код набранной вами программы не со- держит ошибок и предупреждений, в противном случае еще раз проверьте его на соответствие листингу, приведенному выше. Выберите Project | Build hello в главном меню. Будет запущен процесс последовательной компиляции и компоновки исполни- мого файла. В отсутствие ошибок компоновки в вашем подката- логе будет создан файл hello.exe. Это - исполнимая программа на языке C++. Остается запустить разработанную программу (Windows- приложение) на выполнение. Чтобы сделать это, достаточно дважды щелкнуть мышью на иконке hello.exe. Для этого, одна- ко, вам сначала потребуется найти и открыть свой подкаталог с помощью, скажем, Проводника (Windows Explorer). Вместе с тем существует более удобный способ запуска про- граммы, использующий возможности самого C++ Builder. Вы- берите меню Run | Run или нажмите клавишу F9. C++ Builder откомпилирует, скомпонует и запустит вашу программу одним действием. На следующей картинке изображено открывшееся окно приложения (показано в негативе): D:\SERG\Ltcturei\PUM\heHfl1.M» МШИНВВ! Hello, world?- '' > ' Н| 16
Так как нами создано консольное приложение, вся про- граммная информация будет выводиться в это окно в виде про- стого текста. Приложение пока не делает ничего более полезно- го, как просто выводит на экран строчку «Hello, world!». На- жмите любую клавишу, при этом программа закончит свою ра- боту, и окно приложения будет закрыто. 4. Общая структура программы на языке C++. Использование библиотек. Приведенный выше листинг показывает структуру програм- мы hello, которая является общей для любой программы на C++, в том числе написанной в C++ Builder. Программа начинается с конструкций #pragma и #include - директив препроцессора. Запись #include <iostream.h> означает включение в код программы заголовочного файла библиотеки iostream.h - стандартной библиотеки потокового ввода/вывода (input/output stream). Аналогичная запись #include <conio.h> включает библиотеку консольного ввода/вывода (console in- put/output). Это делает возможным вывод на экран текстовой строки с помощью оператора cout « из состава библиотеки io- stream.h (см. код программы ниже) и использование функции getch из состава библиотеки conio.h для задержки завершения работы приложения до нажатия любой клавиши. Программная библиотека представляет собой набор функ- ций, облегчающих работу пользователя. Функции задействуют- ся путем их вызова. В таблицах (см. на с. 18) приведены не- которые из функций библиотек stdio.h и conio.h с коротким опи- санием их назначения. Более подробную информацию о часто используемых функциях C/C++ можно найти в Приложении 3 (см. с. 109-125), а также в справочной системе C++ Builder (она доступна через меню Help). 17
Библиотека <stdio.h> функция назначение printf вывод текста на экран scanf ввод с клавиатуры fopen открытие файла fclose закрытие файла gets ввод строки puts вывод строки Библиотека <conio.h> функция назначение getch ожидание нажатия клавиши clrscr очистка окна gotoxy перемещение курсора textcolor выбор цвета текста kbhit проверка нажатия клавиши textmode изменение режима Вернемся к исходному коду программы hello. Вслед за пре- процессорными директивами программа содержит заголовок функции с именем main. Функция с таким именем является обя- зательной в любой программе на C++, так как она служит точ- кой начала программы. Фигурные скобки задают тело функции, которое состоит из набора объявлений, определений и операто- ров. Каждое из них должно завершаться символом точки с запя- той «;». В приведенном выше листинге тело функции main за- вершается оператором return 0, который в данном случае являет- ся оператором успешного завершения программы. Выполнение программы начинается с первого оператора внутри main и продолжается последовательно, шаг за шагом, до тех пор, пока управление не достигнет строки с оператором re- turn. В этот момент программа завершает работу. В листинге hello тело функции содержит всего два оператора - оператор вывода на экран текстовой строки и оператор ожидания нажатой клавиши. Отметим также в листинге строки, начинающиеся двойным символом слэша «//», - это комментарии к программе, то есть текст, который не компилируется и используется для улучшения «читаемости» программы. 18
5. Объявления и инициализация переменных. Стандартные типы данных. Основной задачей большинства компьютерных программ является быстрое выполнение большого количества вычисли- тельных операций. В целях увеличения производительности промежуточные результаты расчетов хранятся в оперативной памяти (RAM), Программы C++ для размещения своих данных в RAM используют переменные. В C++ имеется несколько встроенных (стандартных) типов переменных: целочисленные, вещественные, символьные, стро- ковые, логические (булевы) и др. Тип переменной означает вид информации, которая может храниться в этой переменной. При- водим таблицу наиболее употребительных типов: Специфи- катор Название типа Число байт Диапазон возможных значений int целый 4 Л >^31 Л О31 от -2 до 2 float вещественный 4 от3.4*10'38 до3.4*10+38 double вещественный двойной точности 8 от 1.7*10'308 до 1.7*1О+308 bool логический 1 true и false, всего - 2 char символьный 1 символы ASCII, всего - 256 Перед использованием любая переменная должна быть объявлена, что означает указание ее типа и имени. В качестве имени может использоваться почти любая буквенно-цифровая комбинация. Основные требования к имени: оно должно начи- наться с буквы, должно быть уникальным и не должно повто- рять ключевые языковые конструкции C++. При объявлении переменная также может быть инициализи- рована некоторой величиной jn диапазона допустимых значе- 19
ний. Для этой цели используется операция присваивания «=». Общая форма объявления переменной: тип имя [= начальное_значение]; В квадратных скобках здесь указано необязательное выра- жение. В большинстве случаев неинициализированная перемен- ная не имеет определенного значения (точнее, ее значение не- предсказуемо). Объявление переменной может размещаться почти в любом месте внутри программы. Однако оно всегда должно предшест- вовать первому обращению к этой переменной. Нарушение это- го правила является синтаксической ошибкой, на которую ком- пилятор прореагирует сообщением вида «Error: Undefined sym- bol ...». Рассмотрим несколько примеров объявления и инициализа- ции переменных: int х = 10; // переменная целого типа с именем х, и начальным значением 10 float а, Ь, с; // вещественные переменные а, b и с, их значения не определены char sym = 'а'; // символьная переменная sym, инициализирована значением‘а’ char str [20]; // текстовая строка из 20 символов с именем str Обратите внимание на использование запятой при одновре- менном объявлении нескольких переменных и квадратных ско- бок при указании размера текстовой строки. Создайте новое консольное приложение со следующим ис- ходным кодом: //------------ Расчет роста в дюймах ----------- #pragma hdrstop #include <iostrearn.h> #include <conio.h> 20
#pragma argsused int main(int argc, char* argv[]) { char name[20]; float cm, inch; cout « "Enter your name - "; // введите свое имя cin » name; cout « "Enter your height - ";// введите свой рост в см cin » cm; inch = cm/2.54; cout « "Hello t " « name « "!" «endl ; cout « "Your height is " « inch « " in"; getch() ; return 0; } //------------------------------------------ Запишите набранную программу в свой дисковый каталог под любым именем. Запустите программу на выполнение и про- тестируйте ее работу. Проанализируйте листинг исходного кода и объясните, для каких целей здесь использованы переменные name, cm, inch. Сформулируйте алгоритм работы этой программы. Тема 2 ОПЕРАЦИИ ВВОДА-ВЫВОДА. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ Удобная компьютерная программа - это всегда программа, корректно взаимодействующая с пользователем, даже если пользователем является сам программист. Такая программа за- прашивает все необходимые для ее работы данные, используя операции ввода, и выдает результаты работы с помощью опера- ций вывода. Стандартным устройством ввода в ПК считается '21
клавиатура, устройством вывода - экран монитора (точнее, окно приложения на экране). Совокупность клавиатуры и монитора часто называют консолью. C++ дает пользователю различные возможности для про- граммирования ввода-вывода. Эти возможности реализуются с помощью функций, входящих в состав различных библиотек. Далее мы рассмотрим две из них - консольный и потоковый ввод-вывод. 1. Консольный ввод-вывод. Консольный ввод-вывод организуется с помощью функций библиотек stdio.h и conio.h, что предполагает наличие директив ^include <stdio.h> и/или #include <conio.h> в заголовочной части программы. Функция printf используется для вывода информации на эк- ран. С ее помощью в окне приложения можно распечатать как строку простого текста, так и значения переменных различных типов. Общая форма записи соответствующего оператора: printf (”форматная_строка”[, перем1][, перем2][,...]); Здесь в круглых скобках указаны параметры (или аргумен- ты) функции printf, причем первый из них, форматная строка в двойных кавычках, является обязательным. Остальные парамет- ры, переменные различного типа, указываются по необходимо- сти. Форматная строка может содержать: • обычные текстовые символы, которые выводятся на эк- ран в том же виде, как они записаны в форматной строке; • управляющие символы, в частности символы перевода каретки «\п», табуляции «\t» и некоторые другие (начинаются со знака обратной косой черты «\»); • символы форматного преобразования, которые исполь- зуются для вывода значений переменных (начинаются со зна- ка «%»). 22
Вслед за форматной строкой в функции printf через запятую может быть указан список всех переменных, значения которых выводятся на экран. При этом внутри форматной строки должны быть размещены соответствующие символы форматного преоб- разования. Численное значение переменной будет выведено в ту позицию, в которой указан соответствующий символ. Символы преобразования для стандартных типов данных указаны в сле- дующей таблице: Переменная Тип данных C++ Символ преобразования целое число int %d вещественное число float, double %f текстовый символ char %c текстовая строка char ♦, char [ ] %s К примеру, запись printf (’’Hello!”) означает вывод на эк- ран простой текстовой строки «Hello!». Запись printf (”%d”, х) выводит на экран значение целочисленной переменной х. Слу- чай, когда на экран выводятся сразу две переменные, иллюстри- руется следующим примером: printf("Значение %с!-й переменной равно %х", i, х) ; преобразование целочисленной переменной преобразование вещественной переменной Здесь верхние стрелки указывают позиции внутри формат- ной строки, в которые будут выведены значения переменных i и х. Остальной текст форматной строки будет отображен без из-
менения. К примеру, если переменная i к моменту выполне- ния этого оператора имела значение 5, а переменная х была рав- на 1.5, на экран будет выведено: «Значение 5-й переменной рав- но 1.500000». Важным является соответствие символа форматного преоб- разования (%d, %f и т. д.) действительному типу переменной (int, float, double и т. д.). Несоблюдение этого правила ведет к непредсказуемому результату на экране. Поэтому использован- ная в примере переменная i должна быть объявлена ранее как целочисленная (int), ах- как вещественная (float или double). Функция printf также дает возможности управления выводом с помощью эскейп-последователъностей, начинающихся с сим- вола ESC (обратный слэш «\»). Некоторые из них приведены в таблице: Управляющий символ Название Действие \п If (line feed) перевод строки \t ht (horizontal tab) горизонтальная табуляция \v vt (vertical tab) вертикальная табуляция \а bel (audible bell) звуковой сигнал \b bs(backspace) возврат на шаг (забой) V ‘ (single quote) одинарная кавычка \” “ (double quote) двойная кавычка Консольный ввод может быть организован с помощью функции scanf. Вводимая при этом информация помещается в некоторую переменную. Общая форма записи этого оператора: 8сапГ(“форматная_строка”, &перем1[, &перем2][,...]); Аргументы функции scanf во многом аналогичны соответст- вующим аргументам printf, за исключением того, что в качестве 24
дополнительных параметров scanf принимает не имена перемен- ных, а их адреса. В силу этого перед именем каждой перемен- ной в scanf должен стоять знак операции взятия адреса «&» (ам- персанд). В момент передачи управления функции scanf выполнение программы приостанавливается в ожидании ввода от пользова- теля. Вся вводимая с клавиатуры информация отображается на экране (эхо-вывод). Во время ввода пользователю доступны простейшие возможности редактирования, в частности клавиша забоя Backspace. Выполнение оператора завершается, как только пользователь нажимает клавишу Enter. Введенная информация при этом будет приведена к соответствующему типу и записана в переменную. Функция getch из библиотеки conio.h не имеет параметров и используется для ввода с клавиатуры отдельного символа на- жатой клавиши. В отличие от scanf эта функция не требует на- жатия Enter для подтверждения конца ввода. Оператор заверша- ет работу сразу после того, как нажата любая клавиша. Ваша программа может анализировать возвращаемое этой функцией значение, с тем чтобы немедленно на него реагировать. Мы бу- дем также использовать эту функцию в конце программы, для того чтобы приостановить закрытие окна на время ознакомле- ния с результатами работы. Рассмотрим следующий пример работы с функциями кон- сольного ввода-вывода. Пример 1. Напишите программу, выводящую * на экран символы звездочки «*» в форме ромба, * * как это показано на рисунке справа. * * ★ * Решение. Задача может быть решена не- * * сколькими способами. Далее приводится один из * * вариантов (см. на с. 26). * 25
Консольный вывод #pragma hdrstop #include <stdio.h> // #include <conio.h> // Подключаем библиотеки консольного ввода-вывода #pragma argsused int main(int { printf(" argc, char* *\n"); // argv[]) В программе используем несколько printf (M * *\n"); // последовательных вызовов функции printf (•’ * *\n"); // printf для вывода на экран printf(u* *\n"); H отдельных строк рисунка. printf(” * *\n") ; // Каждую строку заканчиваем printf (•• * *\n") ; // управляющим символом '\п'. printf(" *\n"); // gatch(); // Задержка до нажатия любой клавиши return 0; } // // Завершение программы 2. Потоковый ввод-вывод. Потоковый ввод-вывод организуется с помощью библиотеки iostream.h, что предполагает наличие директивы #include <io- stream.h> в заголовочной части программы. В библиотеке опре- делены два потоковых объекта с именами cin и cout, которые связаны с клавиатурой и экраном компьютера соответственно. Эти объекты используются как источник входящей информации (поток cin) и контейнер исходящей информации (поток cout). Для них определены следующие операции: • извлечение из потока cin (знак операции «»»), • размещение в потоке cout (знак операции ««»). Общая форма записи этих операций: cin » переменная; cout« текстовая строка_или_переменная; 26
Здесь первая строка означает извлечение числового значения из потока cin (то есть ввод с клавиатуры) и его запись в пере- менную. Вторая строка - размещение простой текстовой строки или числового значения переменной в потоке cout (то есть вы- вод на экран). Примеры: cout « index; // cin » х; // cout « "Enter your name";// cin » name; // выводит на экран значение index вводит значение х с клавиатуры выводит текстовую строку вводит переменную name В отличие от соответствующих конструкций консольного ввода-вывода, потоковые операторы нигде не требуют явного указания типа переменных. В приведенных выше примерах in- dex, х, name могут быть переменными любого типа (int, float, char и т. д.), и во всех случаях представленные операторы будут работать корректно. Это происходит за счет автоматического определения типа переменной в потоковых операциях. Про- граммист получает дополнительные удобства в связи с исклю- чением ошибок приведения типов, которые характерны для кон- сольных операций. Начинающим программистам C++ часто ре- комендуется использовать именно потоковые операции как бо- лее надежную (и современную) технику программирования. Поток cout допускает наличие в выводимой текстовой строке управляющих символов или ESC-последовательностей ('\n', '\t', '\b' и др. - см. таблицу выше), действие которых аналогично их действию в операторе printf. Кроме того, вывод в cout может управляться с помощью специальных потоковых манипулято- ров. Например, манипулятор endl (end line) приводит к за- вершению текущей строки и переводу курсора на новую экран- 27
ную строку. Запись cout « endl, таким образом, приводит к то- му же результату, что и конструкция cout« ”\п”. Решение сформулированной выше задачи о выводе на эк- ран фигуры в форме ромба средствами потокового ввода-вывода показано в следующем листинге. Потоковый вывод #pragma hdrstop #include <iostroan.h> // для потокового вывода в cout #include <conio.h> // для использования getch #pragma argsused int main(int argc, char* argv[]) { cout « ” *\n"; cout « " * *\n"; cout « " * *\n”; cout « "* *\n"; cout « " * *\n"; cout « " * *\n"; cout « " *\n"; getch () ; return 0; Откомпилируйте текст этой программы, запустите на вы- полнение и проверьте результат. 3. Арифметические операции и математические функции. Выполнение вычислений составляют основу подавляющего большинства компьютерных программ. Для этой цели C++ ис- пользует множество арифметических операций, каждая из кото- рых имеет свой знак. Далее приведена таблица (см. на с. 29) 28
наиболее употребительных бинарных операций, то есть операций с двумя аргументами, с примерами их записи в программе C++. Название операции Знак в C++ Алгебраическое выражение Запись на C++ сложение + f+7 f+7 вычитание - р-с Р-с умножение ♦ bm b*m деление / х/у х/у остаток от деления % г mod s r% S Круглые скобки в арифметических выражениях C++ исполь- зуются так же, как в алгебре. При определении порядка вычис- лений сложных выражений C++ придерживается стандартных правил старшинства операций: первыми выполняются операции в скобках; затем операции умножения, деления и вычисления остатка; в завершение - операции сложения и вычитания. Пример: алгебра: т^а+*+с -» запись на C++: m = (a+b+c)/5- 5 В последнем выражении скобки необходимы для сохранения правильного порядка операций - сначала суммирование, затем деление. Кроме арифметических операций, C++ дает удобные воз- можности использования математических функций. Большая их часть содержится в библиотеке math.h, и для пользования ими требуется соответствующая директива tfinclude <math.h>. Наи- более употребительные математические функции приведены в таблице (см. нас. 30). '29
Название функции Обозначение Запись в C++ синус sin(x) sin(х) косинус cos(x) cos(х) тангенс tg(x) tan(х) квадратный корень л/х sqrt(х) возведение в степень ху pow(x,y) экспонента ех ехр(х) натуральный логарифм 1пх 1од(х) модуль Iх! tabs (х) арксинус arcsin(x) asin (х) арккосинус arccos(x) acos (х) арктангенс arctg(x) atan(х) Все перечисленные функции принимают в качестве аргу- мента вещественную переменную (или константу) и возвращают вещественный результат. Использовать функции можно путем их вызова, аналогично вызову функций ввода-вывода. Например: в результате выполнения следующего набора операторов переменная у получит значение квадратного корня из 2: float х = 2.0; float у = sqrt(x); В библиотеке math.h также определены некоторые часто ис- пользуемые математические константы, часть из которых при- ведена ниже: Константа Запись в C++ Л М_Р1 е М_Е 1п2 M_LN2 1п10 M_LN10 30
Пример 2. Напишите программу, \ запрашивающую у пользователя длины а у3 сторон треугольника а, Ь, с и выводя- / у щую на экран углы а, р, у. z_-------------\ С Решение. Воспользуемся извест- ной формулой косинусов, которую последовательно применим для нахождения всех углов треугольника. Рассчитанные значе- ния а, р, у переведем из радианов в градусы, помножив их на 1807л. Расчет углов треугольника #pragma hdrstop linclude <iostream.h> #include <conio.h> #include <math.h> // для потокового ввода-вывода // для getch() // для acos(x) и М PI Ipragma argsused int main(int argc, char* { float a, b, c; cout « "input a - "; cin >> a; argv[]) // объявляем переменные а, Ьг с // выводим на экран приглашение // вводим значение а и т. д. cout « "input b - "; cin » b; cout « "input c - "; cin » c; float alpha, betta, gamma; // объявляем переменные alpha = acos((b*b + c*c - a*a)/(2*b*c)); // считаем alpha betta = acos((a*a + c*c - b*b)/(2*a*c)); // считаем betta gamma = acos((a*a + b*b - c*c)/(2*a*b)); // считаем gamma cout « "\n alpha « " « alpha/M_PI*180; // выводим все cout « "\n betta = " « betta/M_PI*180; // углы на экран cout « "\n gamma - " « gamma/M_PI*180; // (в градусах) cout « "\n " « alpha + betta + gamma; // сумма углов=р1? getch(); // задержка return 0; // завершение ) //---------------------------r--------------------- 31
Наберите и откомпилируйте этот код. Сделайте несколько расчетов с различными входными данными. Проверьте правиль- ность результатов в характерных случаях равностороннего, пря- моугольного треугольника и т. д. Убедитесь, что сумма а + Р + + у в рамках вычислительной погрешности всегда равняется л. Типичные ошибки программирования 1. Отсутствует директива tfinclude, подключающая необхо- димую библиотеку ввода-вывода. На этапе компиляции ошибка приводит к сообщениям вида “Error: Undefined symbol cout, cin, printf, scanf’. 2. Отсутствует точка с запятой в конце оператора. Последст- вия этой ошибки могут быть разнообразны, но весьма часто это сообщения вида “Error: Statement missing “Error: Declaration syntax”, “Error: Undefined symbol...”. 3. Использование операции » при работе с потоком вывода cout, и операции « при работе с потоком ввода cin. Сообщение - “Error: operator not implemented ...”. 4. Несоответствие символа форматного преобразования (%d, %f и т. д.) типу переменной (int, float, и т. д.) в операторах кон- сольного ввода-вывода printf и scanf. Ошибка не распознается компилятором, однако приводит к неправильной работе соот- ветствующих функций. 5. Используемая в программе переменная не объявлена. Та- кая ошибка приводит к сообщению “Error: Undefined symbol...” 6. Нарушена парность скобок в записи сложного алгебраиче- ского выражения. 32
Контрольные вопросы 1. Общая форма записи основных операторов консольного ввода-вывода. Назначение их аргументов. Управляющие симво- лы и символы форматного преобразования. Примеры. 2. Стандартные объекты потокового ввода-вывода cin и cout. Общая форма записи основных операций. Потоковые ма- нипуляторы. Примеры. 3. Бинарные арифметические операции. Правила старшин- ства операций. Математические функции и константы. 4. Найдите синтаксические и логические ошибки в приве- денных ниже конструкциях a) int а; Ь; с; double х, в) int к = 3; 3 = к; д) int i = 0; j = 0; int j ; ж) float x e 2; printf("%d", x); и) int ar b; cout » b; cin « a; л) float х, y, z; z - sin(x,y); h) float x = -0.5; float у = |x|; 6) int i; i > 0; r) int a, b, c; float a, b, c; e) double x, у = 1. x = sin(y). у = sin(x). з) float x; scanf("%f", x); k) float х, y, z; z = pow(xy); m) int a = 1; int b = cos(a); o) float x « 1.5; float i = 2*exp(x)); 33
5. Определите, что будет выведено на экран в результате выполнения приведенных ниже листингов. Предполагайте, что переменные n, т, х, у объявлены следующим образом: int n = 1, т = 2; float х = 2.5, у = 5; a) cout « "х » х"; б) cout « "х = " « х; в) cout « X « x; r) cout « x+y « zz!zz; д) printf(' '%d!z ', n+m); e) printf (' '%d%dzz, n, 5); ж) float z = n + m * x; з) cout « "xx\nxx\nxxzz; printf("z = %fz/, z); 6. Запишите оператор или набор операторов, печатающих на экране заданную фигуру: а) б) в) ********* * * * * * * * * * ********* Практические задания 1. Напишите программу, рассчитывающую значение задан- ной функции и выводящую его на экран. Значения аргументов должны вводиться с клавиатуры. a) z(x,y) = б) y(x) = sin5j — 34
В) y(x) = arctd—- Ах+1 Д) z(x,y)=y-^ е) ж) z(x,y) = —^-Iny; 1—е и) у(х) = 1-2е~х 1 + 2е”х I 7^ 3) у(х) = ^1 + у+у; к) z(x, у, k) = C0S(*QC). 2. Напишите программу, запрашивающую у пользователя радиус круга и выводящую на экран диаметр, длину окружности и площадь этого круга. 3. Напишите программу, запрашивающую длину основания и высоту равнобедренного треугольника и вычисляющую длины всех его сторон. 4. Напишите программу, вычисляющую объем и площадь поверхности шара по заданному с клавиатуры значению радиуса. 5. Напишите программу, вычисляющую радиус окружно- сти, вписанной в правильный n-угольник, по известной длине его стороны а. Значения п и а вводятся с клавиатуры. 6. Напишите программу, вычисляющую радиус окружно- сти, описанной вокруг правильного n-угольника, по известной длине его стороны а. Значения п и а вводятся с клавиатуры. '35
7. Даны координаты трех точек на плоскости A(xi,yi), В(хз,У2) и С(хз,уз). Напишите программу, вычисляющую вели- чину угла АВС (в градусах). 8. Напишите программу, вычисляющую период обращения вокруг Земли спутника, находящегося на круговой орбите на расстоянии R (км) от поверхности. 9. Напишите программу, вычисляющую угол преломления луча света, падающего под углом а из воздуха на поверхность вещества с показателем преломления п. 10. На депозит в банке была внесена сумма So (тыс. рублей) на срок R (месяцев). Напишите программу, вычисляющую сум- му вклада S по истечении срока, если процентная ставка по дан- ному виду вклада составляет d % годовых. 11. Напишите программу, вычисляющую сумму бесконеч- ной геометрической прогрессии Ьц Ьг, Ьз, Ьд..., если известны bi и знаменатель прогрессии q. Значения Ь] и q вводятся с клавиатуры. Тема 3 ОПЕРАТОР УСЛОВИЯ IF-ELSE 1. Назначение и синтаксис. Оператор условия if-else служит для выбора направления ра- боты программы в зависимости от условий, сложившихся в дан- ной точке программы на момент ее выполнения. Общая форма записи условного оператора: if(<условие>) { <блок операторов 1>; } else < <блок операторов 2>; 1 36
Если на момент выполнения <условие> истинно, программа передает управление <блоку операторов 1> и далее первому оператору за пределами конструкции if-else. При этом <блок операторов 2> не выполняется. Иначе, если <условие> ложно, выполняется <блок операторов 2>, а <блок операторов 1> про- пускается. Соответствующая блок-схема: Фигурные скобки в синтаксисе оператора if-else использу- ются для выделения в тексте блоков 1 и 2. Старайтесь распола- гать закрывающую скобку под открывающей для улучшения читаемости программного кода. Для этой же цели текст внутри фигурных скобок необходимо смещать вправо на несколько по- зиций. В качестве условия в операторах if-else могут использо- ваться любые логические выражения, принимающие значения «истинно» или «ложно» (true - false). В таблице указаны простейшие операции сравнения целых и вещественных чисел (см. на с. 38). 37
Операция Знак операции Пример записи на C++ больше > А>В меньше < С<2 больше либо равно >= к>=0 меньше либо равно <= i<= 10 равно = х = у не равно |= D!=0 Пример 1. Требуется написать программу, переводящую температуру по шкале Цельсия Тс (°C) в температуру по Кель- вину Тк (К). Значение Тс вводится пользователем с клавиатуры. Решение. Используем известную формулу преобразова- ния -Тк = Тс - То, где То = -273 °C - температура абсолютного нуля. Будем считать введенное Тс некорректным, если оно меньше То. Kelvin vs Celsius ------------ #pragma hdrstop #include <iostream.h> #include <conio.h> // для потокового B/B // для консольного B/B (getch) #pragma argsused int main(int argc, char* argv[]) { float ТО = -273; // объявляем и инициализируем TO // объявляем вещественные Тс и Тк float Тс, Tk; cout«" Vvedite Тс = cin»Tc; if(Tc<T0) { // выводим приглашение // запрашиваем Тс // проверяем условие Тс<Т0 cout«" ) else Tc < TO! // условие истинно, выводим на // экран сообщение об ошибке 38
{ Тк ® Тс-ТО; // условие ложно, рассчитываем cout « ” Тк = " « Тк; // Тк и выводим на экран } getch(); // задержка до нажатия на клавишу return 0; // завершение программы } //----------------------------------------------- Наберите приведенный выше код, откомпилируйте его и за- пустите программу на выполнение. Исследуйте результаты ра- боты при различных значениях Тс. 2. Сокращенные варианты записи. При программировании обыденной является ситуация, когда требуется некоторое действие в ответ на сложившиеся условия (например, если получены неверные исходные данные от пользователя, то выдать сообщение об ошибке и выйти из про- граммы). В таких случаях в программах на C++ может исполь- зоваться сокращенная запись оператора условия с отсутствую- щим блоком else. Общая форма такой записи: if(<условие>) { <блок операторов>; } Здесь в случае истинно- сти условия управление пе- редается блоку операторов в фигурных скобках. В слу- чае ложности условия этот блок пропускается. Соответ- ствующая блок-схема отличается от предыдущей отсутствием одного «плеча». 39
Другой вариант сокращения применяется в случае, когда ка- кой-либо из блоков if или else состоит только из одного опера- тора. В этом случае допускается отсутствие фигурных скобок, ограничивающих этот блок. if(<условие>) оператор 1; else оператор 2; Здесь в качестве операторов 1 и 2 могут быть не только про- стые однострочные арифметические действия или операторы ввода-вывода, но и сложные многострочные конструкции, например другие (вложенные) операторы условия или опера- торы цикла, которые будут рассмотрены ниже. 3. Вложенные операторы условия. Операторы условия могут быть вложенными друг в друга, в со- ответствии с тем программным алгоритмом, который они реали- зуют. Допускается произвольная степень их «вложенности». Если один оператор if-else вложен в другой, то первый опе- ратор входит во второй полностью, а не только какой-либо од- ной своей частью - if или else. Недопустимым является частич- ное перекрывание между собой их отдельных блоков. а) правильная запись б) ошибочная запись if(a<=b) if(a<=b) { { if(х?»0) if(х!«0) cout«"x!=0" ; cout«"x!=0" ; else else { { // начало else х = 1; х = 1; У » 0; У - 0; } } } else else ( { } // конец else а = b; а = Ь; cout<<a; cout<<a; } ) 40
В приведенном примере один из операторов (выделен полу- жирным шрифтом) вложен в другой. Запись б) является оши- бочной в силу того, что блок else внутреннего оператора усло- вия частично пересекается с обоими блоками if и else внешнего оператора. Пример 2. Пользователь вводит с клавиатуры три целых числа а, Ь, с. Необходимо вывести на экран наибольшее из этих чисел. Решение. Один из возможных алгоритмов решения этой задачи показан на следующей блок-схеме: Схема может быть реализована программно с помощью вло- женных операторов if-else. 4'1
//--------Выбор наибольшего из 3 чисел tpragma hdrstop #include <iostream.h> tinclude <conio.h> #pragma argsused int main(int argc, char* argv[]) { float а, Ь, с; // объявляем три переменные cout«"Vvedite cin»a; cout«"Vvedite cin»b; cout«”Vvedite cin»c; a - И Ь - с - вводим значения а, Ь, с if(a>b) и если а > b if(a>c) и и если а > с cout«" max = "«а;// то выводим на экран . а else // иначе, т. е. если а <= с cout«" maj : = "«с;// ' выводим с else // иначе, т. е. если а <= b if(b>c) // и если b > с cout«" max = "«Ь; // то выводим b else и иначе, т. е. если b <= а cout«” max = "«с; // выводим с getch(); // задержка до нажатия любой клавиши return 0; Разберите блок-схему этого алгоритма и его программную реализацию. Модифицируйте алгоритм и программный код для поиска наименьшего из трех чисел. 42
4. Составные логические выражения. Условие в операторе if-else может быть выражено не только в виде простого сравнения двух числовых значений. Напри- мер, весьма распространены двойные условия, которые в мате- матике записываются в виде «а < b < с». Запись означает, что значение b лежит в диапазоне между значениями а и с. В про- грамме такие условия должны быть переформулированы с ис- пользованием простых операций сравнения и логических опера- ций «И», «ИЛИ», «НЕ». Логическая операция Знак в C++ Наименование знака и && двойной амперсанд или II двойная вертикальная черта НЕ ** тильда В частности, выражение «а < b < с» сформулируем как «а меньше Ь, и b меньше с». На C++ это будет записано как (a<b)&&(b<c). В тексте программы соответствующий оператор будет иметь вид: if((а<Ь)&&(Ь<с)) { } Пример 3. На пустой шахматной доске в позиции (n, т) на- ходится белая пешка, в позиции (k, I) - черный слон. Здесь пер- вая координата есть номер столбца шахматной доски, ..вторая - номер строки (обе изменяются в диапазоне от 1 до 8). Оцените текущую ситуацию в соответствии с тремя вариантами: S пешка находится под ударом, S слон находится под ударом, J слон и пешка в «безопасности». -43
Решение. Примем во внимание, что пешка может атако- вать две ближайшие к себе позиции по диагонали вперед, а слон атакует обе свои диагонали полностью. Отсюда могут быть сформулированы условия: • «((к = п+1) ИЛИ (к = п-1)) И (1 = т+1)» - атака пешки на слона, • «(к+1 = п+ш) ИЛИ (к-1 = п-m)» - атака слона на пешку, • иначе фигуры в безопасности. //------------- Шахматная композиция ----------- #pragma heirstop #include ciostream.h> #include <conio.h> int main(int argc, char* argv[]) { int n,m,k,l; cout<<"Koordinaty beloi peshki:"<<endl; cout«" wedite n - cin»n; cout«" vvedite m - cin»m; cout«"Koordinaty chernogo slona: "«endl; cout«" vvedite k - "; cin»k; cout«" vvedite 1 - ”; cin»l; if(((k==n+l)||(k==n-l))&&(l==m+l)) // атакован слон cout«endl«"Atakovan chernyi slon!"; else if((k+l==n+m)||(k-l==n-m)) // атакована пешка cout«endl<<"Atakovana belaya peshka!"; else // нет атаки cout«endl«"Figury v bezopasnosti"; getch(); return 0; } //---------------------------------------------- 44
Откомпилируйте и запустите программу на выполнение. Проверьте результаты ее работы при различных положениях пешки и слона. Типичные ошибки программирования 1. Отсутствуют круглые скобки в записи условия. Эта ошибка распознается на этапе компиляции и сопровождается сообщением - «Error: If statement missing ...». 2. Сразу после круглых скобок с записью условия стоит лишняя точка с запятой. При отсутствии блока else такая ошиб- ка не будет распознана компилятором и будет воспринята как пустой оператор if. Точка с запятой после ключевого слова else также является синтаксической ошибкой. 3. Проверка на равенство двух переменных записана с по- мощью одиночного знака «=» вместо двойного знака «=». Компилятор посчитает такую запись операцией присваивания, что приведет к неправильной работе программы. Сообщения об ошибке в этом случае не выдается, однако появляется преду- преждение: «Warning: Possibly incorrect assignment». 4. Частично перекрываются блоки if и/или else двух вло- женных друг в друга условных операторов. Последствия этой ошибки обычно трудно предсказуемы. Иногда это приводит к сообщению вида «Error: Misplaced else». 5. Неправильная запись составного условия. Возможные варианты ошибок - нарушение парности скобок, ошибки в зна- ках логических операций «И», «ИЛИ», «НЕ». Контрольные вопросы 1; Общая форма записи оператора if-else и назначение его функциональных блоков. Блок-схема и алгоритм работы. ' 45
2. Сокращенные формы оператора if-else. Привести примеры. 3. Вложенные операторы условия. Привести примеры. 4. Составные логические выражения и их использование в операторах if-else. Привести примеры. 5. Найдите синтаксические ошибки в приведенных ниже языковых конструкциях. Учтите, что переменные а, Ь, с объяв- лены как целые (int), а х, у - как вещественные (float). a) if(а > Ь); Ь = 5; else; х » у; в) if(а = Ь) cout«"a ravno b!"; else { cout«"a i b ne ravny"; } д) if (x > 0) { у = 2*sin(x)*exp(-x); a - sqrt(x*x); else } У - 0; ж) if(5 > b > c) cout«"OK!"; 6) if(5 > b) { a = 25*x + y; 5 = b; } else cout«"oshibka!"; r) if(a > b) a > b; else a < b; e) if(x > 0) { у = 2*sin(x)*exp(-x); } a = sqrt(x*x); else у = 0; з) if((5 > b)(b > c)) cout«"OK! б. Определите, что будет выведено на экран в результате выполнения приведенных ниже фрагментов кода. Считайте, что переменные а, Ь, с объявлены как целочисленные (int) и инициа- лизированы значениями 1, 5 и 10 соответственно. 46
a) if(a > b) a = b + 1; else b = a - 1; cout«a«b«c; в) if(a < 0) a = 10; cout <<a«b«c; 6) if(5 > b) { a = b + 1; b - a - 1; } else cout«a«b«c; r) if(a > 0) cout«"Ok!"; else b - a; cout«a«b«c; д) if ( (a < b) I I (b > O) a « b; else b = a; cout<<a<<b«c; ж) if(c>a) if(c>0) printf("$$$"); else printf("###"); printf("000"); e) if((a < b)&&(b > c)) a » b; else b » a; cout«a«b«c; з) if(c>a) if(c>10) printf("==="); else printf ("«<") ; printf ("»>") ; 7. Нарисуйте блок-схемы примеров, приведенных в преды- дущем задании. Практические задания 1. Даны три вещественных числа а, Ь, с. Напишите про- грамму, определяющую, могут ли данные числа являться дли- нами сторон треугольника. Значения а, Ь, с вводятся с клавиатуры. 2. Даны три вещественных числа а, Ь, с. Напишите про- грамму, определяющую, могут ли данные числа являться дли- нами сторон прямоугольного треугольника. Значения а, Ь, с вво- дятся с клавиатуры. 47
3. Даны две окружности радиусами г и R, расстояние между центрами которых D. Напишите программу, определяющую, имеют ли данные окружности общие точки. Значения г, R и D вводятся с клавиатуры. 4. Даны стороны треугольника а, Ь, с. Напишите програм- му, определяющую, является ли треугольник остроугольным. Значения а, Ь, с вводятся с клавиатуры. 5. Напишите программу, определяющую количество веще- ственных корней квадратного уравнения ах2 + Ьх + с = 0. Значе- ния а, Ь, с вводятся с клавиатуры. На экран выводится количест- во корней и их значения. 6. В точке (хо, уо) находится центр круга радиуса R. Напи- шите программу, определяющую, находится ли точка с задан- ными координатами (х, у) внутри или за пределами круга. Ве- щественные числа хо, уо, R, х, у вводятся с клавиатуры. 7. На плоскости проведена прямая у = кх + Ь, где к и b - вещественные константы. Напишите программу, определяющую положение точки с заданными координатами (х, у) относительно прямой. Варианты ответа: 1) точка над прямой, 2) под прямой, 3) на прямой. Вещественные числа к, Ь, х, у вводятся с клавиа- туры. 8. Даны точка на плоскости с координатами (х, у) и квадрат с центром в точке (Хс, ус) и стороной а. Напишите программу, определяющую, находится ли точка внутри или за пределами квадрата. Значения х^, ус, а, х, у вводятся с клавиатуры. 9. Даны треугольник со сторонами а, Ь, с и окружность ра- диуса г. Напишите программу, определяющую, может ли: а) треугольник быть целиком помещен в окружность; б) окруж- 48
ность быть целиком помещена в треугольник. Значения а, Ь, с, г вводятся с клавиатуры. 10. На шахматной доске находятся две заданные фигуры (черная и белая) в позициях (n, ш) и (k, 1), где 1 < n, т, к, 1 < 8. Напишите программу, оценивающую ситуацию и выводящую соответствующие сообщения: J фигура 1 атакует фигуру 2, J фигура 2 атакует фигуру 1, обе фигуры в безопасности. В программе учтите возможность обоюдной атаки. Значения п, т, k, 1 вводятся с клавиатуры. Варианты сочетаний фигур: а) два короля; б) две пешки; в) ладья и пешка; г) король и конь; д) ладья и конь; е) пешка и конь; ж) ферзь и король; з) ферзь и слон; и) два слона. 11. Напишите программу, запрашивающую 3 вещественных числа и выводящую их на экран в упорядоченном виде: а) по возрастанию; б) по убыванию. 12. По надежным данным военной разведки, штаб противни- ка находится на расстоянии R (км) от артиллерийской батареи. Из орудия в сторону цели производится выстрел под углом а к горизонту. Скорость вылета снаряда из ствола - V (м/с), ради- ус зоны поражения разорвавшегося снаряда - S (м). Напишите программу, определяющую, будет ли данным выстрелом пора- жена цель. Трением воздуха пренебречь. Значения R,V, S, а вводятся с клавиатуры. 49
Тема 4 ОПЕРАТОР ЦИКЛА FOR 1. Назначение и синтаксис. В компьютерных программах часто возникает необходи- мость выполнения определенного набора операторов заданное число раз (или, иначе, до тех пор, пока выполнено некоторое условие). Такие алгоритмы реализуются с помощью циклов. Под циклом будем понимать повторяющееся действие (или набор действий), организованное с помощью структуры, управляемой счетчиком. Рассмотрим это на следующем простом примере. Пример 1. Напишите программу, выводящую на экран все целые числа от 0 до 99 включительно. Решение. Используя известные нам функции ввода- вывода, можно предложить по крайней мере два следующих ал- горитма решения задачи: Вариант 1 1. Объявляем целочисленную переменную к и инициализи- руем ее значением 0. 2. Выводим на экран к. 3. Увеличиваем к на единицу. 4. Если к меньше 100, воз- вращаемся к пункту 2. 5. Завершаем программу. Вариант 2 1. Объявляем целочислен- ную переменную к и инициа- лизируем ее значением 0. 2. Если к меньше 100, пере- ходим к следующему пункту, иначе завершаем программу. 3. Выводим на экран к. 4. Увеличиваем к на единицу. 5. Возвращаемся к пункту 2. 50
Блок-схемы этих алгоритмов представлены на рисунке: Цикл с пост-условием Цикл с пред-условием Несмотря на то, что результат работы обоих алгоритмов одинаков, существует различие в их организации. Различие свя- зано с расположением условия продолжения цикла: в первом случае проверка происходит после того, как выполнен очеред- ной шаг; во втором - перед очередным шагом. В соответствии с этим предложенные алгоритмы называются циклом с пост-ус- ловием и циклом с пред-условием соответственно. Переменную к будем называть счетчиком цикла, а повторяющиеся в цикле операторы - телом цикла. В C++ существует несколько языковых конструкций для ор- ганизации циклов. В настоящей работе мы рассматриваем цикл for, который иногда также называют итерационным циклом. Общий формат его записи: for (<инициализация>; <условие_продолжения>; <изменение_счетчика>) { <блок операторов>; } 5!
Цикл for начинается с выполнения блока <инициализации>, где, как правило, определяется начальное значение счетчика цикла. Далее следует проверка <условия_продолжения>, и в случае, если это условие истинно, целиком выполняется <блок_операторов> в теле цикла. На этом завершается первый шаг цикла, и управление вновь передается заголовку for, кото- рый производит <изменение_счетчика>. Следующий шаг также будет включать в себя проверку <условия_продолжения> и, в случае его истинности, последовательное выполнение опера- торов тела цикла. Циклическое повторение будет продолжено до тех пор, пока <условие_продолжения> не станет ложным. На этом выполнение цикла прекращается, и управление передается следующему оператору за пределами тела цикла for. Блок-схема этого алгоритма представлена на рисунке: Таким образом, for по определению является циклом с пред- условием. Отметим, что блок инициализации в нем выполняется только один раз. 52
В качестве примера использования этой конструкции, рассмотрим листинг программы, решающей сформулированную выше задачу о выводе на экран всех целых чисел от 0 до 99. Вывод значений в цикле #pragma hdrstop tinclude <iostream.h> #include <conio.h> #pragma argsused int main(int argc, char* { int k; for(k=0; k<100; k=k+l) { cout«k<<endl; } getch(); return 0; } //----------------------- argv[]) // объявляем переменную-счетчик // цикл по к от 0 до 99 с шагом 1 // тело цикла: вывод на экран к // задержка Еще раз отметим здесь некоторые особенности записи цикла for. Во-первых, каждый из блоков заголовка (внутри круглых скобок) отделяется от другого точкой с запятой. Во-вторых, точка с запятой после заголовка не ставится (так как запись опе- ратора на этом не закончена). В-третьих, непосредственно после заголовка должно быть расположено повторяемое тело цикла, выделенное фигурными скобками. В приведенном примере переменная-счетчик к объявлена в программе отдельной записью int к. Однако C++ также допус- кает объявление счетчика непосредственно в заголовке цикла: for(int k=0; k<100; k=k+l) { cout«k«endl; } *53
В C++ Builder такая переменная будет действительна и видна только внутри цикла for, тогда как область действия переменной к из примера выше распространяется до конца программы. В качестве счетчика цикла может использоваться не только целочисленная, но и вещественная переменная. Шаг изменения счетчика также может быть любым, в том числе дробным и от- рицательным. К примеру, следующий фрагмент кода выводит на экран значения функции sin(x) на интервале [0, 2л] с шагом л/180: for(float х=0; х<2*М_Р1; х=х+М_Р1/180) { cout « х « " " « sin(x) « endl; } Аналогично if-else операторы в теле цикла for (внутри фи- гурных скобок) принято смещать на несколько позиций вправо для улучшения читаемости программного кода. 2. Сокращенные варианты записи. В случае, когда тело цикла состоит только из одного опера- тора, допускается отсутствие ограничивающих его фигурных скобок, что довольно часто используется для сокращения запи- си. В остальном конструкция остается неизменной: for (<инициализация>; <условие__продолжения>; <изменение_счетчика>) оператор; Отдельные (или все) блоки в заголовке цикла for могут быть пустыми, однако разделительные точки с запятой являются обя- зательными. К примеру,запись: for(;;;) { <операторы>; } является допустимой и означает бесконечный цикл повторения 54
блока операторов. Несмотря на кажущуюся абсурдность такого цикла в работающей программе, конструкции подобного вида иногда используются программистами. Здесь выход из цикла организуется с помощью оператора break, который означает за- вершение цикла и выход из него: for(;;;) { <операторы>; if(<условие>) break; } В заголовке цикла for также часто используются сокращен- ные варианты записи некоторых арифметических операций, например, операций инкремента и декремента. Некоторые (но далеко не все) из таких сокращений приведены в таблице: Стандартная запись Описание Сокращенная запись Пример использования А = А+ 1; увеличить значение переменной А на 1 А++; i++; А = А-1; уменьшить значение переменной А на 1 А-; index—; А = А + В; увеличить значение А на величину В А+=В; x+=0.1; А = А-В; уменьшить значение А на величину В А-=В; result-= 10; А = А*С; увеличить значение А в С раз А *= С; R ♦= rs; A = A/D; уменьшить значение А вЭраз A/=D; S /= 10.; '55
В частности, записи: к = к + 1; к++; к += 1; в программе являются эквивалентными и означают одно и то же действие - увеличение значения к на единицу. N Пример 2. Рассчитайте сумму N слагаемых ряда S = Хак к=0 Заданными считаются: 1-е слагаемое ао и рекуррентное соотно- шение, связывающее к-е слагаемое акс предыдущим (к-1)-м сла- гаемым ak-i в виде ак = ак_] + d = a0 + d-k (арифметическая про- грессия). Значения N, а0, d вводятся с клавиатуры. Решение. Будем использовать вспомогательную перемен- ную ак для хранения значения очередного члена ак и перемен- ную sum для вычисления суммы. Расчет организуем с помощью цикла for, в котором будем последовательно вычислять значение ак, прибавлять его к sum и выводить на экран текущую инфор- мацию (номер шага к, значение очередного слагаемого, теку- щую сумму). //-------------- Расчет суммы ряда -------------- #pragma hdrstop #include <iostream.h> #include <conio.h> #pragma argsused int main(int argc, char* argv[]) { float d, aO, ak; // вещественные d, aO, ak int k, N; // целочисленные k, N 56
cout«”Vvedite N « "; cin»N; cout«"Vvedite aO = "; cin»aO; cout«"Vvedite d = "; cin>>d; // вводим с клавиатуры исходные // значения - N, aO, d float sum = 0; for(k=0; k<=N; k++) { ak = aO + d*k; sum = sum + ak; cout«"shag "«k«": ak=" «ak«", S="«sum«endl; } cout«"Summa - "«sum; getch(); return 0; // вспомогательная переменная // цикл по k от 0 до N // начало тела цикла II 1. вычисляем ak // 2. добавляем ak к sum // 3. выводим на экран II окончание тела цикла Н результат на экран И---------------------------- Наберите и откомпилируйте код этой программы. Исследуй- те результаты ее работы. Изобразите блок-схему и объясните алгоритм работы этого приложения. 3. Вложенные операторы цикла. Аналогично операторам условия if-else циклы for могут быть вложены друг в друга, причем степень «вложенности» также может быть произвольной. В качестве счетчиков такие циклы, как правило, используют различные переменные. Основное применение вложенных циклов в компьютерных программах связано с перебором значений в нескольких измере- ниях (то есть нескольких координат). В качестве примера рас- смотрим задачу о расчете значений функции 2 переменных z(x, у) = ехр(- х)7у внутри квадрата хе [-л, л], уе [-л, л] с шагом л/8 по обеим сторонам. Задача, может быть решена программно 57
с помощью вложенных циклов, как показано ниже (приведен только фрагмент): for(float x=-M_PI; x<M_PI; x+=M_PI/8) for(float y=-M_PI; y<M_PI; y+=M_PI/8) cout « x « " "« у « ” " « exp (-x) *sqrt (y) « endl; Здесь внешний цикл перебирает все значения х-координаты точки и запускает вложенный в него цикл по у-координатам. Во внутреннем цикле искомые значения функции выводятся на эк- ран. Рассмотрим еще один пример использования вложенных циклов. Пример 3. На пустой шахматной доске находится черный ферзь в позиции (n, т). Найдите все возможные положения бе- лого короля, в которых он не находится под ударом. Текущие координаты ферзя вводятся с клавиатуры. Решение. В простейшем варианте задача может быть ре- шена перебором всех возможных положений короля (k, 1) и вы- бором тех из них, где он в безопасности. Учитывая возможности ферзя атаковать по вертикали, по горизонтали и по обеим диа- гоналям, можно легко сформулировать условия «безопасной» позиции: • к != п - нет атаки по вертикали • 1 != m - нет атаки по горизонтали • 1 - k != m - п - нет атаки по диагонали «северо-восток» • l + k!=m + n- нет атаки по диагонали «северо-запад» В силу того, что все условия должны быть соблюдены одно- временно, их необходимо объединить с помощью логической операции «И». 58
Приводим листинг программы, решающей поставленную за дачу: //-----------Шахматная задача 2------------- ♦pragma hdrstop ♦include <iostream.h> ♦include <conio.h> ♦pragma argsused int main(int argc, char* argv[]) { int n, m, к, 1, num - 0; cout « ’’Enter black queen position:” « endl; cout « ” colunm n = ”; cin » n; cout « ” row m = cin >> m; cout « endl « ’’Safe white king positions:” « endl; for(k=l; k<«8; k++) { for(1-1; 1<=8; 1++) { if( (k!=n)&& (l!«m) && (l-k!-m-n)&& (l+k!=m+n) ) { cout « ”(” « к num++; } } } cout « ’’number of safe getch(); return 0; } //-------------------------- // цикл по столбцам // цикл по строкам // если все условия выполнены // выводим позицию (к,1) на экран « « 1 « ”)” « endl; //и увеличиваем счетчик на 1 // конец цикла по строкам // конец цикла по столбцам positions - ” « num; 59
Наберите код программы в среде C++ Builder и запустите ее на выполнение. Исследуйте результаты при различных n, т. Со- ставьте блок-схему и объясните алгоритм работы программы. Объясните назначение переменной num. Можно ли в приведенном листинге сократить какие-либо за- писи операторов for и if? Типичные ошибки программирования 1. Лишняя точка с запятой сразу после круглых скобок в объявлении цикла for. Эта ошибка не будет распознана компи- лятором и будет воспринята как цикл с пустым телом. Стоящие после точки с запятой операторы в фигурных скобках будут вы- полнены только один раз. 2. Используемая в качестве счетчика цикла переменная не объявлена. В этом случае компилятор выдаст сообщение “Unde- fined symbol...”. Противоположный ошибочный вариант - это многократное объявление переменной-счетчика в блоке инициа- лизации, что вызовет сообщение компилятора “Multiple declara- tion for...”. 3. Некорректно записан блок изменения счетчика. К при- меру, вместо к++ или к=к+1 написано к+1, что является ошиб- кой. Компилятор в этом случае не выдаст никаких сообщений, однако при запуске программа зациклится. 4. С осторожностью используйте циклы, в которых счетчик является переменной вещественного типа. Потенциальная воз- можность логической ошибки в этом случае заложена в <усло- вии_продолжения>. К примеру, цикл вида for(float х=1; х<=5; х++) может быть выполнен не 5 раз, как ожидается про- граммистом, а всего 4. Это связано с погрешностью компьютер- ного представления вещественных чисел. Более надежный вари- ант записи - for(float х=1.0; х<5.001; х+=1.0). 60
Контрольные вопросы 1. Приведите общую форму записи оператора for и поясни- те назначение всех его блоков. Объясните алгоритм работы цик- ла на соответствующей блок-схеме. В каких случаях использу- ются сокращенные формы записи? 2. Найдите синтаксические и логические ошибки в приве- денных конструкциях. Считайте, что переменные i, j объявлены ранее как целые (int), переменные х, у - как вещественные (float). a) for(i=0, i<5, i++) б) for(i=0; i<5; i++); j++; j++; в) for(int k=0; k<=j; k=k+2) r) for(int i=10; i<=l; i—) cout«"k!"; { else j *» 2; cout<<"k?"; cout«j; д) for(j=0; j<2; j+=0.1) e) {for(j=0; j<2; j++) x = j*0.1; x = sin(j *0.1); у = exp(-2*j); cout«x; 3. Определите, что будет выведено на экран в результате выполнения приведенных ниже фрагментов. Предполагается, что переменные i, j, к объявлены как целочисленные (int) и ини- циализированы значениями 1, 5 и 10 соответственно. a) for(i=0; i<3; i++) k = k+1; cout«i« j <<k«endl; 6) for(i=0; i<3; i++) k++; cout«k; 61
в) for(i=5; i>=3; i—) cout«i«endl; д) for(i=0; i<10; i++) if(i<j) cout«i; ж) for(i=0; i<3; i++) { к - k-5; if(i<k) printf("$$$"); else printf("###"); r) for(i=5; i>0; i=i-2) cout«i«endl; e) for(i=0; i<10; i+=2) if(i<j) cout« j; 3) for(i»0; i<3; i++) ( for(j=0; j<3; j++) { if(i<j) printf("$$$"); else printf("###"); } } Практические задания 1. Напишите программу, вычисляющую значения функции у = f(x) на заданном отрезке [a,b] с заданным шагом Ах. По результатам расчетов постройте график функции. а) у = е 2х, [0,1], Ах = 0.05; б) у = sin(x), в) у = arctg(x), [0,2nJ Ах = л/10; [0,51 Ах = 0.2; ч X г) у = ехр - — I 2* ч 1 Д) У = :—г; 1 + х ч А 1 1 е)У = 4 ——т V х X [0.9,21 Ах = 0.05; Ж)У = -— 1-е [0.1,2} Ах = 0.1; з) у = 79-х2 ; ч 1-е х и) у =-------------------------; [-3,31 Ах = 0.25; 1 + е-х [-1,21 Ах = 0.1. 62
2. Напишите программу, вычисляющую факториал задан- ного целого числа N с использованием цикла for. 3. Напишите программу, вычисляющую хк (где х - вещест- венное, к - целое) с использованием цикла for. 4. Напишите программу, вычисляющую сумму ряда 10 1.2 •)s=E7; k=0 z Ю v2 Os(x)=£b; к-0 прих= 1,2, 3; yexp(-n) D)s ysin(2i), £ 2п + 1 ’ ft i! ’ д)8(х)=£2ф>; m-1 прих = 0, 1,2; 5. Напишите программу, вычисляющую приближенные значения математической функции, используя формулу ее раз- ложения в ряд. Последовательно сделайте расчеты с N- 1, 3, 5, 10 слагаемыми ряда. Сравните получаемые результаты с точным значением: <ю к а)е’=У —; ВИ б) COS X = 2_, к=0 t х2 . х4 (2к)! ’ 2 24 в) sin х = 2_, к=0 „2к+1 Л х3 х5 = X-----+---- 6 120 63
6. Напишите программу, выводящую на экран символы «*» согласно приведенным ниже шаблонам. Обязательным является использование циклов: 7. Напишите программу, вычисляющую количество «счаст- ливых» трамвайных билетов в рулоне серии АВС, то есть с 6- значными номерами вида АВСххх. «Счастливым» считать билет с номером ABCDEF, таким, что A+B+C=EH-E+F. Значения А, В, С вводятся с клавиатуры. 8. Последовательность чисел Фибоначчи характеризуется тем, что она начинается с 0, 1, и каждый последующий элемент является суммой двух предыдущих (0, 1, 1, 2, 3, 5, 8, 13, 21, ...). Напишите программу, выводящую на экран заданное количест- во N чисел Фибоначчи, где N задается с клавиатуры. 9. Целое число называется простым, если оно делится толь- ко на 1 и самого себя. Напишите программу, определяющую, является ли введенное с клавиатуры целое число простым. 10. Напишите программу, которая вычисляет наибольший общий делитель двух заданных с клавиатуры целых чисел А и В и выводит его на экран. 11. На депозитный счет в банке была внесена сумма S на срок R (лет) с процентной ставкой Р (%) годовых. Предполагая, что проценты по вкладу начисляются ежегодно, напишите про- грамму, выводящую на экран сумму на счете по истечении 1-го, 2-го,.... R-ro года. 64
Тема 5 МАССИВЫ I. ПОЭЛЕМЕНТНЫЕ ОПЕРАЦИИ 1. Одномерные (линейные) массивы. Линейным массивом в программе на C++ называется упоря- доченный набор однотипных переменных, которые располага- ются в памяти последовательно (см. рис.): А[0] A[1] А[2] А[3] А[4] А[5] А[6] A[n-2] А{п-1] элемент 1 Массив является простейшей структурой данных, облег- чающей работу с большими объемами информации путем их упорядочения. В случае с массивами упорядочение происходит за счет индексирования элементов, то есть обращения к каждому из них по порядковому номеру. Показанный на рисунке массив состоит из п элементов с индексами от 0 до л-1, в который запи- саны числа 5, 21, 0,12 и т. д. Любой массив в C++ характеризуется тремя параметрами: именем, типом элементов и размером. Как и обычная перемен- ная, перед использованием массив должен быть объявлен. Об- щая форма записи объявления; тип_элементов имя_массива[размер_массива] ; Здесь тип_элементов - это любой из известных стандартных типов (int, float, double, char и т.д.), имя_массива - уникальное 65
имя (идентификатор), используемое для обращения к массиву, размер_массива - количество его элементов. В качестве послед- него параметра в объявлении может быть использована только целочисленная константа или константное выражение. Примеры объявлений: int А [15]; // массив из 15 целочисленных элементов с именем А float х[3]; // массив х из 3-х элементов типа float Объявление массива является командой компилятору на вы- деление памяти для хранения его элементов. Общее количество выделенной памяти зависит не только от числа элементов, но и от размера каждого элемента, то есть от его типа. Например, текстовая строка из 1000 символов (тип char) займет Р = 1000*sizeof(char) = 1000 байтов, а массив из такого же количест- ва вещественных чисел двойной точности (тип double) займет уже в восемь раз больше - Р = 1000*sizeof(double) = 8000 байтов. Нумерация элементов в массиве начинается с нуля. Таким образом, первый элемент массива имеет индекс 0, а последний - индекс п-1, где п - размер массива. Обращение к элементу про- изводится с использованием имени массива и индекса элемента в квадратных скобках. Например, запись “х [о] = 5.5;” оз- начает “присвоить значение 5.5 нулевому элементу массива х”. Для работы с массивами характерным является использова- ние итерационных циклов for. С их помощью организуется вы- полнение однотипных операций со всеми элементами массива, в частности поэлементный ввод-вывод, поэлементные арифмети- ческие операции и др. Рассмотрим это на следующем примере. Пример 1. Напишите программу, запрашивающую у поль- зователя 10 целых чисел и выводящую на экран их сумму. бб
Решение. Будем использовать массив с именем А и раз- мером 10 для хранения введенных чисел. Ввод данных и сумми- рование организуем поэлементно с помощью циклов for. //-----------Сумма элементов массива---------------- #pragma hdrstop #include <conio.h> #include <iostream.h> #pragma argsused int main(int argc, char* argv[]) { int A[10]; // объявляем массив из 10 целых for(int i=0; i<10; i++) // организуем цикл no i от 0 до 9 { cout « "input A[" « i « "] - // приглашение cin » A[i]; // вводим A[i] ) int sum - 0; // объявляем переменную for(int i=0; i<10; i++) // организуем цикл sum = sum + A[i]; //в цикле суммируем элементы cout « "\nSumma: " « sum; // выводим результат на эк- ран getch(); // задержка return 0; } //-------------------------------------------------- Наберите код этой программы в среде C++ Builder и запус- тите ее на выполнение. Проверьте правильность получаемых с ее помощью результатов. Нарисуйте блок-схему и объясните алгоритм ее работы. Объясните смысл использования дополни- тельной переменной sum в этой программе. 2. Многомерные массивы. Массивы в программах на C++ могут быть не только линейны- ми. Довольно частым является использование двух (и более) -мер- 67
ных структур. К примеру, прямоугольная матрица - типич- ная структура, представимая с помощью двумерного массива; а ЗН-тензор может быть записан как соответствующий трехмер- ный массив. Многомерный массив в C++ организован по принципу «мас- сива массивов». Общий формат его объявления: тип имя[Ы1][Ы2] ... [NM]; Здесь М - число индексов (или размерность) массива. Индексы изменяются в пределах от 0 до N1 - 1, от 0 до N2 - 1, от 0 до N3 - 1,..., от 0 до NM - 1 соответственно. К примеру, запись int G[5] [ 4 ]; означает объявление двумерного массива целых чисел с именем G и размерами 5x4. На рисунке такой массив представлен в виде таблицы: G[0][0] 5 21 0 12 G[0][3] G[1][0] 8 -3 14 23 55 -1 0 78 44 4 0 9 G[4][0] 33 0 -2 0 <- G[4][3] Здесь первый индекс является номером строки, второй - но- мером столбца таблицы, с диапазонами изменения от 0 до 4 и от О до 3 соответственно. Доступ к элементам многомерного массива в программе производится так же, как и в одномерном случае, то есть путем указания имени массива и набора индексов в квадратных скоб- ках. Например, операция присваивания значения 0 послед- нему элементу будет записана как G[4][3] = 0. 68
При работе с многомерными массивами удобно использо- вать вложенные циклы for. С их помощью можно выполнить заданное действие с каждым из элементов массива путем пере- бора всех значений индексов. Приведенный ниже фрагмент про- граммного кода выводит на экран все элементы массива G: for(int i=0; i<5; i++) // цикл по строкам i { for(int j=0; j<4; j++) // цикл по строкам j cout « G[i] [j] « "\t"; // выводим G[i] [j] cout « endl; // перевод на новую строку } Алгоритм работы этого фрагмента иллюстрируется следую- Здесь внешний цикл по I последовательно пробегает все зна- чения от 0 до 5. При каждом i запускается внутренний цикл по j 69
от 0 до 4. В теле этого цикла на экран выводятся значение эле- мента G[i]|j] и знак табуляции (горизонтальный отступ). Внут- ренний цикл продолжается до тех пор, пока не будут перебраны все значения j, то есть не будет выведена вся i-я строка. По за- вершении внутреннего цикла экранный курсор перемещается на новую строку манипулятором endl, и далее внешний цикл про- должает свою работу, последовательно выводя на экран другие строки массива. Пример 2. Имеется вещественная квадратная матрица раз- мером 4x4. Напишите программу, вычисляющую произведение элементов в каждой ее строке. Матрица вводится с клавиатуры. Решение. Условимся использовать для хранения матрицы массив float Х[4][4]. Расчет произведения реализуем согласно следующему алгоритму. Введем вспомогательную переменную (к примеру, float Р). Заметим, что в i-й строке расположены элементы X[i][j], где] меняется от 0 до 3 включительно. Органи- зуем цикл по j, внутри которого будем домножать Р на X[i][j]. Тогда на выходе из цикла Р будет содержать искомое произве- дение. Выведем его на экран и продолжим расчеты для следую- щей строки. Для правильной работы алгоритма перед началом расчетов в каждой строке матрицы необходимо присвоить Р значение 1. //------- Произведение элементов строки --------- tpragma hdrstop #include <conio.h> #include <iostream.h> #pragma argsused int main(int argc, char* argv[]) { float X[4][4]; // объявляем массив 4x4 for(int i=0; i<4; i++) 70
for(int j=0; j<4; j++) { cout « "input X[" « i « « j « "] » cin » X[i][j]; // вводим элементы матрицы ) cout « ”\n Results:\n"; for(int i=0; i<4; i++) ( float P = 1.0; for(int j=0; j<4; j++) P = P * X[i][j]; cout « "\n proizvedenie " « « ”-i stroki = ” « P; } getch(); return 0; } //------------------------------ // цикл по строкам // вспомогательная переменная // цикл по элементам в строке // домножаем Р на X[i][j] i // выводим результат на экран Наберите и откомпилируйте код этой программы в С++ Builder. Проверьте результаты, выдаваемые программой. 3. Типизированные константы. В рассмотренном выше примере код программы содержит явные выражения, задающие размеры массива X. Он объявлен как float Х[4][4], то есть с явным указанием размерности, и да- лее везде по ходу программы цифра 4 используется явно при записи циклов. Такая техника программирования является допустимой и даже часто используемой, однако создает некоторые трудности в плане масштабируемости программы. В данном случае под масштабируемой мы будем понимать программу, которая может быть легко перестроена для работы с массивами других разме- ров. В рассмотренном выше примере при изменении размера 71
массива X нам придется просмотреть весь код программы, заме- няя 4 на другое целое число. Этого можно избежать, если ввести типизированные кон- станты, которые будут использоваться для указания размеров массива. Так же, как и переменная, типизированная константа имеет уникальное имя и тип, однако ее значение не может быть изменено по ходу выполнения программы. Это дает право ис- пользовать ее в объявлении массива. Типизированная константа должна быть объявлена с ключе- вым словом const, вслед за которым указывается ее тип (int, float, double, char, и т. д.), далее, через пробел, - ее имя и ини- циализирующее выражение const тип имя = выражение; Например, запись const int N = 4; означает объявле- ние целочисленной константы с именем N и значением 4. В рас- смотренном выше примере N могла быть использована как при объявлении массива float X[N][N], так и везде далее вместо 4. Такая программа будет легко масштабируемой в силу того, что в ней достаточно изменить значение N работы с массивами дру- гих размеров. Типизированная константа может быть объявлена в любом месте программы до момента своего первого использования. Однако хорошим стилем считается объявление всех констант в самом начале программного файла, после подключения библио- тек директивами #include. 4. Инициализация элементов массива. В рассмотренных выше примерах начальные значения эле- ментов массива задавались пользователем с клавиатуры. Можно поступить иначе и каждому из элементов присвоить начальное значение с помощью оператора «=». Это потребует довольно 72
большого количества записей - по отдельному оператору для каждого из элементов. C++ дает программисту еще один, более удобный способ. Массив может быть инициализирован при объ- явлении. Для этого в строке объявления сразу вслед за указанием типа элементов, имени массива и его размеров записывается знак присваивания, и далее в фигурных скобках задаются значе- ния элементов через запятую: тип имя[размерИ] = { знач1, знач2, значЗ, . значИ }; Запись означает, что сразу после размещения массива в опе- ративной памяти каждому из элементов должно быть присвоено соответствующее значение из списка. Если список значений в фигурных скобках короче, чем размер массива, то оставшиеся элементы будут инициализированы значением по умолчанию, то есть обнулены. В следующем примере float mark[5] = { 7.3, 4.0, 2.2, 12.1, 8.9 }; создается массив с именем mark, состоящий из 5 чисел типа float, которые инициализируются значениями 7.3, 4.0, 2.2 и т. д. Это эквивалентно следующему набору операторов: float mark[5]; mark[0]=7.3; mark[l]=4.0; mark[2]=2.2 и т. д. Многомерный массив также может быть инициализирован в строке объявления. Для этого достаточно помнить о том, что многомерный массив в C++ - это «массив массивов», о чем уже говорилось выше. Пример: int F[3][3] = { {3,0,2}, (1,9, 8}, {5,7,4}}; Здесь создается двумерный массив с именем F и размерами 3x3, элементы которого получают начальные значения F[0][0] = 3, F[0][l] = 0, F[0][2] = 2, F[l][0] = 1 и т. д. 73
Пример 3. Пусть А и В - две квадратные матрицы разме- ром 3x3. Требуется написать программу, рассчитывающую их произведение С = АВ. Решение. Искомое произведение С - это также матрица 3x3, элементы которой рассчитываются по формуле 2 Cj (0<i,j£2). Аналогично примеру 1 (см. на к=0 с. 66-67), организуем суммирование с помощью вспомогатель- ной переменной s и цикла по к. Для перебора всех использу- ем два дополнительных вложенных друг в друга цикла по i и по j. Эти циклы будут внешними по отношению к циклу по к. //------------- Перемножение матриц ------------- Ipragma hdrstop #include <conio.h> #include <iostream.h> #pragma argsused const int N = 3; // используем константу N=3 int main(int argc, char* argv[]) { float A[N][N] = { (1, (2, (3, float B[N][N] = { {1, {1, {1, float C[N][N]; 1, 1), 2, 2], 3, 3} }; // исходная матрица A 2/ 3}, 2, 3}, 2, 3} }; // исходная матрица В // матрица произведения С for(int i=0; i<N; i++) // цикл по строкам С { for(int j=0; j<N; ( j++) // цикл по столбцам С 74
float s = 0.0; for(int k=0; k<N; k++) s += A[i][k]*B[k][j]; C[i][j] = s; // вспомогательная переменная // цикл суммирования по к // добавляем к s новое слагаемое // записываем s в C[i][j] cout « " Results: \n"; // далее выводим С на экран for(int i=0; i<N; i++) { for(int j=0; j<N; j++) cout « C[i][j] « ”\t"; cout « endl; getch(); return 0; } //----------------------------------------------------- Типичные ошибки программирования 1. Выход за пределы массива в цикле for. Возникает при обращении к несуществующему элементу (с отрицательным ин- дексом или индексом, большим настоящего размера массива минус 1). Одна из самых часто встречающихся и одновременно трудно отслеживаемых ошибок. Не определяется компилятором. Может иметь разнообразные последствия - от некорректных результатов работы программы до зависания компьютера. 2. Для размера массива вместо константного выражения используется имя переменной. Сопровождается сообщением “Error: Constant expression required”. 3. Неправильное объявление двумерного массива т[х][у] как т[х,у]. Аналогичная ошибка - ссылка на элемент т[х,у]. Вызывают сообщения: “Error: Array bounds missing ]” и “Error: Illegal use of...”. 75
4. Количество начальных значений в списке инициализации массива превышает его размер. Ошибка распознается на этапе компиляции и сопровождается сообщением “Error: Too many initializers”. 5. Попытка изменить значение типизированной константы после ее объявления. Приводит к сообщению “Error: Cannot modify a const object ”. Контрольные вопросы 1. Общие формы объявления одномерного и многомерного массивов. Диапазоны изменения индексов. Доступ к элементам массива. Примеры. 2. Использование итерационных циклов for для выполнения поэлементных операций с одномерными и двумерными масси- вами. Примеры. 3. Типизированные константы - объявление и инициализа- ция. Использование в масштабируемых программах. Пример. 4. Найдите синтаксические и логические ошибки в приве- денных ниже конструкциях: а) int i, j; float D[i][j]; 6) int a; int a[3] = a; в) const double N = 2; double Matrix[N]; Г) const int S; S = 5; float G[S]; д) int N = 4; double Matrix[N]; e) int Q[3,3]; Q[0,0] = 1.; 76
ж) int L[2] [2] [2] ; L[2][2][2] = 0; з) float A [ 3 ]; for(int i=0; i<=3; i++) A[i] = sin(i/10.); и) const int r - 2; к) char str[4] = (1.2, 3.5, int L[r] = 0; 8.0,- 1.3}; 5. Определите, что будет выведено на экран в результате выполнения приведенных ниже фрагментов. Объясните работу этих конструкций пошагово. a) int А[5]={1,2,3,4,5}; cout « "А[0]=" « А[0] ; в) int С[5]; for(int i=0; i<5; i++) C[i] = 2*i; cout « C[3]; 6) int b [3] =={ 9, 8,7 }; cout « b[0] << endl « b[l] « endl « b[2]; r) int DDD[5]; for(int k=0; k<5; k++) { DDD[k] == 0. ; cout « "!" ; } д) int E[3]={0,1,2}; E[0]++; int r=E[0]+E[1]+E[2]; cout << r; ж) int g[2][2] = {{1,2}, {3,4}}; for(int i=0; i<2; i++) cout << g[i][i]; e) int f[3]={0,l,2}; for(int k=2; k>=0; k—) cout « f[k]; 3) int H[2][2] = {{5,6}, {7,8}}; for(int i=0; i<2; i++) cout « H[i][1-i]; Практические задания 1. Напишите программу, запрашивающую у пользователя N целых чисел и выводящую их на экран в обратном порядке. 77
2. Напишите программу, запрашивающую у пользователя N вещественных чисел и выводящую на экран: а) сумму чисел с четными порядковыми номерами; б) сумму чисел с нечетными порядковыми номерами. 3. Напишите программу, запрашивающую у пользователя N целых чисел и выводящую на экран: а) только положительные числа; б) только отрицательные числа. 4. Напишите программу, запрашивающую у пользователя N вещественных чисел и выводящую на экран их среднее ариф- метическое. 5. Напишите программу, запрашивающую у пользователя N вещественных чисел и выводящую на экран их среднее гео- метрическое. 6. Даны две целочисленные квадратные матрицы размером N х N. Напишите программу, рассчитывающую их сумму. 7. Дан вектор в N-мерном пространстве. Напишите про- грамму, вычисляющую его длину. 8. Даны два вектора в N-мерном пространстве. Напишите программу, рассчитывающую их скалярное произведение. 9. Даны два вектора в 3-мерном пространстве. Напишите программу, рассчитывающую их векторное произведение. 10. Дана матрица целых чисел размером 4x4. Напишите программу, вычисляющую сумму элементов: а) на главной диагонали; б) на побочной диагонали. И. Напишите программу, запрашивающую у пользователя N целых чисел и выводящую на экран: а) количество нулей в последовательности; 78
б) количество положительных чисел; в) количество отрицательных чисел. 12. Даны два вектора в трехмерном пространстве. Напишите программу, вычисляющую угол между направлениями этих век* торов. 13. Даны квадратная матрица и вектор в трехмерном про- странстве. Напишите программу, вычисляющую их произве- дение. 14. N точек на плоскости заданы последовательно координа- тами (хо,уо), (Х1,у0, ... (хм-1,ун-1). Напишите программу, рассчи- тывающую длину образованной этими точками ломаной линии. 15. Дана квадратная матрица размерами N х N. Напишите программу, выполняющую обращение матрицы: а) относительно главной диагонали (транспонирование); б) относительно побочной диагонали; в) относительно «центра» матрицы; г) относительно горизонтальной линии, проходящей через центр; д) относительно вертикальной линии, проходящей через центр. Тема б МАССИВЫ П. АЛГОРИТМЫ ПОИСКА И СОРТИРОВКИ 1. Линейный поиск по условию. Поиск необходимого элемента в большом объеме данных - одна из часто возникающих, проблем в разнообразных компью- 79
терных приложениях. Для решения этой задачи разработано множество алгоритмов. Выбор того или иного алгоритма поиска зависит в основном от степени структурированности (или внутренней упорядоченности) исходных данных. Если они не структурированы, программисты вынуждены применять мало- производительные, хотя и простые в реализации, методы. Для упорядоченных данных могут использоваться значительно бо- лее скоростные и специализированные методы. В настоящей работе нами будет рассмотрен простейший алгоритм линейного поиска по условию, который может применяться к любым мас- сивам C++ (одномерным и многомерным), в том числе и неупо- рядоченным. Рассмотрим сначала одномерный вариант. Пусть перед нами стоит следующая задача: имеется массив данных, в котором требуется найти элемент, удовлетворяющий заданному условию (например, равный нулю). Организуем перебор всех элемен- тов массива, начиная с нулевого, с помощью итерационного цикла for. Для каждого элемента будем проверять выполнение заданного условия. В случае если условие выполнено, запоми- наем индекс найденного элемента во вспомогательной перемен- ной. По выходе из цикла искомый элемент может быть получен через его индекс. С небольшими изменениями этот же алгоритм может ис- пользоваться и для поиска группы элементов, удовлетворяющих условию. Проиллюстрируем это на примере. Пример 1. Дан массив X из N целых чисел. Напишите про- грамму, подсчитывающую количество элементов, хранящих значение А. //---------------- Подсчет элементов --------------- #pragma hdrstop #include <conio.h> 80
#include <iostream.h> const int N « 10; // N - размер массива #pragma argsused int main(int argc, char* argv[]) { int X[N], A; // объявляем X и A for (int i=0; i<N; i++) // вводим элементы массива { cout « "input X[" « i « cin » X[i]; } cout « "\n input A="; // вводим значение A cin » A; int sum =0; // доп. переменная sum for(int i=0; i<N; i++) // в цикле перебираем все X[i] if(X[i]==A) // если X[i] равен A sum++; // то увеличиваем sum на 1 cout << "\n kol-vo chisel ” « A « ” v massive = ” « sum; // выводим результат getchO ; return 0; Алгоритм также может быть легко обобщен на многомерный случай. Для этого достаточно организовать перебор всех эле- ментов многомерного массива, к примеру, с помощью вло- женных циклов. Пример 2. Дана квадратная матрица размером N х N. Най- дите все элементы с отрицательными значениями и обнулите их. Решение. Пусть массив Matrix[N][N] хранит исходную матрицу. Поставленная задача решается следующей программой (для краткости приведен только фрагмент кода): 81
for(int i=0; i<N; i++) // перебираем строки матрицы for(int j=0; j<N; j++) // перебираем столбцы if(Matrix[i][j]<0) // если элемент меньше О, Matrix[i][j] • 0; //то обнуляем его 2. Поиск максимального (минимального) элемента. Методы поиска максимального (или минимального) элемен- та в массиве несколько отличаются от методов поиска по усло- вию, в силу того что искомое значение заранее не известно. Модифицируем описанный в пункте 1 алгоритм следующим образом. Введем вспомогательную переменную (к примеру, шах) и запишем в нее значение нулевого элемента массива. Да- лее организуем перебор всех оставшихся элементов в цикле. Ес- ли по ходу встречается элемент со значением, большим max, то записываем его в max, переопределяя, таким образом, значение этой переменной. После перебора всех эле- ментов max будет хранить ис- комый (в данном случае мак- симальный) элемент массива. Блок-схема этого алгорит- ма показана на рисунке. Обобщения метода на слу- чай поиска минимума и на многомерный случай очевид- ны. В первом случае необхо- димо заменить знак сравнения X[i] и max («больше» на «меньше»), во втором - организовать перебор элементов по всем индексам многомерного массива. Реализация на языке C++ и того и другого показана в следую- щем примере. 82
Пример 3. Дана прямоугольная матрица А размерами N х М. Напишите программу, вычисляющую наибольший и наимень- ший из ее элементов. поиск максимума-минимума ♦pragma hdrstop ♦include <iostream.h> ♦include <conio.h> const int N = 3, M = 4; // размеры массива ♦pragma argsused int main(int argc, char* argv[]) { float A[N1 [Ml = {{2,-4, 5, 0}, {1, 6, 8,-2}, {3, 9, 7, 4}}; float max = A[0][0]; float min = A[0][0]; for(int i=0; i<N; i++) { for(int j=0; j<M; j++) { if(A[i][j]>max) max = A[i][j]; if(A[i][j]<min) min » A[i][j]; ) } cout « "\n max = n « max; cout « ”\n min = " « min; getch(); return 0; } //----------------------------- II задаем матрицу // вводим две переменные (для // минимума и максимума) // перебираем строки // перебираем столбцы // если элемент > max, //то записываем его в max // если элемент < min, // то записываем его в min // выводим max // выводим min 83
3. Сортировка методом «прямого выбора». Под сортировкой будем понимать размещение набора дан- ных в определенном порядке, что используется, как правило, для облегчения поиска нужного элемента или группы элемен- тов. Это также одна из важных задач компьютерной обработки данных. От эффективности алгоритмов сортировки зависит, на- пример, производительность работы баз и банков данных. Мы рассмотрим два простейших метода сортировки: метод «прямого выбора» и метод «пу- зырька». Для определенности бу- дем считать, что перед нами стоит задача сортировки одномерного массива A[N] по убыванию. Сор- тировка по возрастанию может быть проведена аналогичным об- разом. Алгоритм метода «прямого выбора» основан на последова- шаг 1 0 5 3 9 7 шаг 2 9 5 3 0 7 шагЗ 9 7 3 0 5 шаг 4 9 7 5 0 3 итог 9 7 5 3 0 тельном переборе всех элементов Метод «прямого выбора» массива в поиске максимального и перемещении этого элемента на первую позицию в массиве. После этого процедура повторя- ется с оставшимися N-1 элементами - из них в свою очередь выбирается максимальный, и он меняется местами со вторым элементом массива. Процедура применяется последовательно N- 1 раз, пока все элементы не окажутся упорядоченными гаранти- рованно. Пример работы алгоритма показан пошагово на ри- сунке (см. выше). Здесь исходный массив из 5 элементов сорти- руется в 4 этапа. Приведенный ниже фрагмент кода решает эту задачу: // ------- Сортировка «прямым выбором» ---------- const int N = 10; // размер массива float A[N] = {5, 7, 1, 9, 6, 2, 8, 0, 4, 3}; // исход, массив 84
cout « "\nPered sortirovkoi:\n”; for(int i=0; i<N; i++) // cout « A[i] « " for(int i=0; i<N; i++) // { int max_index = i; // float max » A[i]; for(int j=i; j<N; j++) // { if(A[j]>=max) // { max_index » j; // max = A[j]; // } } float tmp = A[i]; // A[i] = A[max_index]; // A[max_index] - tmp; // } выводим в исходном порядке цикл по шагам сортировки вводим доп. переменные цикл поиска наибольшего элемента если очередной элемент > max то запоминаем его индекс и изменяем значение max доп. переменная для перестановки меняем местами элементы A[i] и A[max_index] cout « "\nPosle sortirovki:\n"; for(int i=0; i<N; i++) // выводим отсортированный массив cout « A[i] « " //--------------------------------------------------------- 4. Сортировка методом «пузырька». Метод «пузырька» получил свое название оттого, что продвижение максимальных элементов массива к его вершине происходит постепенно, подобно всплытию пузырька на по- верхность воды. Как и предыдущий алгоритм, этот метод требует нескольких про- ходов массива. На каждом проходе сравнивается пара соседних друг с другом элементов. Если пара рас- положена в порядке возрастания, 85
6. Рассмотрите фрагменты программ, выполняющих сорти- ровку массивов. Выделите в них блоки, ответственные: 1) за объявление и инициализацию констант и массивов; 2) вывод массивов на экран; 3) перестановку элементов; 4) поиск максимального элемента. 7. Рассмотрите представленные фрагменты кода. Сформу- лируйте одной фразой, какое действие выполняет каждый фраг- мент (например, «выводит на экран все положительные эле- менты массива Z», «сортирует массив Р по убыванию» и т. д.). Предполагается, что в каждом из примеров массив инициализиро- ван некоторым набором значений (на месте знака многоточия ”...”). a) int А[10] = (...}, s=0; for(int i=0; i<10; i+=2) s+=A[i]; в) int M[25>U); for(int k=0; k<25; k++) if(M[k]==5) cout « д) float X[50] = {...); for(int n=0; n<50; n++) if((0<X[n])&&(X[n]<1)) cout « X[n]; 6) float K[3] [3] = {...}, s=0; for(int i=0; i<3; i++) s+=K[2J [i]; r) float H[5] [5] = {...J ; for(int i=0; i<5; i++) for (int j=0; j<5; j++) H[i][j]*=2; e) float Y[50] = {...}; for(int m=0; m<49; m++) Y[m] = Y[m+1]; 8. Определите, что будет выведено на экран в результате выполнения приведенных фрагментов кода. Объясните работу этих конструкций пошагово. a) int С[3]={1,2,3}; for(int i=0; i<3; i++) CIO] += C[i]; cout « C[0]; 6) int C[3]=(1,2,3}; for(int i=0; i<3; i++) C[i] += C[2-i]; cout « C[0]+C[1]+C[2]; 88
в) int I[3]={3Z2Z1}; for(int j=0; j<3; j+=2) cout « I [ j ] ; r) int S[3]={1}, f=l; for(int i=0; i<3; i++) f += S [i]; cout « f; д) int A[2] [2]={{1,2},{3,4}}; for(int i=0; i<2; i++) for(int j=0; j<2; j++) A[i] [j] += 1; cout « A[0][1]+A[1] [0] ; e) int Z[4]={1,0,1,0}; for(int i=0; i<4; i++) if(Z[i]>0) cout « Z[i]; ж) int X[2][2] = { {0,1}, {1, 0}}; int p = 0; for(int i=0; i<2; i++) p += X[0] [i] ; cout « p; 3) int Y[2][2]={{0,1},{1,0}}; int r = 0; for(int i=0; i<2; i++) r += Y[i] [0]; cout « r; Практические задания 1. Напишите программу, находящую корень некоторого уравнения вида f(x)=C на отрезке [a,b], с помощью прямого перебора значений этой функции с шагом Дх. Сравните полу- ченный результат с точным аналитическим значением. Иссле- дуйте и объясните зависимость точности результатов от Дх . 2. Напишите программу, вычисляющую минимум и макси- мум заданной преподавателем функции вида у = f (х) на отрезке [a,b], с помощью прямого перебора значений этой функции с шагом Дх. Сравните полученные результаты с точными ана- литическими значениями. Исследуйте и объясните зависимость точности результатов от Дх . 3. Дан набор из N целых чисел. Напишите программу, оп- ределяющую, является ли этот набор: а) упорядоченным по возрастанию; 89
б) упорядоченным по убыванию; в) симметричным относительно своей «середины». 4. Дан набор из N вещественных чисел Хк. Напишите про- грамму, рассчитывающую количество элементов, попадающих на отрезок [А, В], то есть удовлетворяющих условию А £ Хк £ В, где А и В - заданные вещественные числа. 5. Дана матрица вещественных чисел размером N х N. На- пишите программу, находящую и выводящую на экран: а) минимальный элемент на главной диагонали; б) минимальный элемент на побочной диагонали; в) максимальный недиагональный элемент. 6. Дан упорядоченный набор из N целых чисел. Напишите программу, определяющую, в какой порядковой позиции Р на- ходится элемент с заданным значением F. Значение Р - вывести на экран. Исходный массив и F вводятся с клавиатуры. Варианты задания: а) найти первый по порядку элемент; б) найти последний по порядку элемент. 7. Дан набор из N целых чисел. Напишите программу, уда- ляющую из набора: а) все отрицательные числа; б) все нули; в) все положительные числа. 8. Дана матрица вещественных чисел размером N х N. На- пишите программу, выводящую на экран: а) все положительные элементы; б) все отрицательные элементы. Элементы необходимо вывести в строку, разделяя их пробелом. 90
9. Дана матрица целых чисел размером N х N. Напишите программу, выводящую на экран: а) количество положительных элементов; б) количество отрицательных элементов; в) количество нулевых элементов. 10. Модой числовой последовательности называется наибо- лее часто встречаемое в этой последовательности значение. На- пишите программу, вычисляющую моду заданного набора N целых чисел. И. Медианой упорядоченного набора чисел Xi, х2, хз, ..., хц называется его «середина», то есть значение среднего элемента. Напишите программу, вычисляющую медиану последователь- ности N чисел, которые вводятся с клавиатуры в неупорядочен- ном виде. 12. N точек на плоскости заданы последовательно координа- тами (хо, уо), (xi, у]), ... (xn-i, уы-i)- Напишите программу, опре- деляющую, является ли образованная этими точками фигура выпуклой. 13. Дана квадратная матрица размерами N х N. Напишите программу, определяющую, является ли матрица симметричной: а) относительно главной диагонали; б) относительно побочной диагонали; в) относительно своего «центра»; г) относительно горизонтальной линии, проходящей через центр; д) относительно вертикальной линии, проходящей через центр. 14. Числовым палиндромом называется число, одинаково читаемое справа налево и слева направо (например, 1467641, < 91
8118 и т. д.). Напишите программу, определяющую, является ли заданное с клавиатуры число А палиндромом. Подсказка: для выделения из А десятичных цифр удобно воспользоваться опе- рацией «%» - остатка от деления. 15. На шахматной доске находятся белый король в позиции (i, j) и N черных фигур в позициях (ki, 10, (k2,12), ...(км, In)- На- пишите программу, находящую все варианты следующего хода белого короля. 16. Варианты заданий: а) в качестве черных фигур выступают пешки; б) ладьи; в)короли. Тема 7 ФУНКЦИИ 1. Определение функции. Понятие функции в C++ аналогично понятиям подпрограм- мы или процедуры, которые имеются в большинстве языков программирования высокого уровня. Их использование связано с принципами модульного программирования, в основе которого лежит разделение программы на автономные фрагменты, или модули. Такое разделение становится необходимым в случае, когда объем программы выходит за рамки нескольких строчек исходного кода. Функция в C++ - это автономный модуль, решающий неко- торую задачу и служащий определенной цели. Примером яв- ляются все рассмотренные ранее функции стандартных библио- тек stdio.h, conio.h, math.h. Однако пользователь может нё толь- ко использовать готовые функции, но и создавать собственные. Более того, несколько функций пользователя могут быть впо- 92
следствии объединены в библиотеку. Написанная и протестиро- ванная один раз, функция может быть использована многократ- но, в том числе в других программах (при условии ее корректно- го подключения). В соответствии с реализуемой целью, функция может требо- вать для своей работы один или несколько входных параметров, или аргументов. Она также может возвращать некоторый ре- зультат. Пример: функция sqrt из библиотеки math.h прини- мает в качестве входного параметра вещественное число х и возвращает другое вещественное число, а именно - значение квадратного корня из х. Внутреннее устройство (или реализа- ция) этой функции скрыты от пользователя, однако он может получить ее результаты путем вызова этой функции, напри- мер, следующей записью: у = sqrt(x). Перед использованием функцию необходимо определить, задав ее имя, количество и тип ее аргументов, а также тип воз- вращаемого ей результата. Общая форма записи: тип_результата имя_функции (список_аргументов) { <объявления локальных переменных>; <операторы>; return <возвращаемое__значение>; } Имя функции, как правило, отражает выполняемое ею дей- ствие. Для результата может использоваться любой из стандарт- ных типов C++ (int, float, double, char и др.). Список аргументов должен содержать набор объявлений входных параметров функции с указанием типа каждого из параметров. Все аргумен- ты в списке должны быть разделены запятыми. Выражения в фигурных скобках определяют тело функции. При необходимости в нем могут содержаться объявления ло- кальных переменных, которые действительны только внутри -93
функции в момент ее вызова и уничтожаются при выходе из нее. Операторы, расположенные вслед за локальными объявлениями, программно реализуют те цели, для которых функция организо- вана. Рассчитанный с их помощью результат возвращается в ме- сто вызова функции оператором return. Пример 1. Напишите функцию, выбирающую наименьшее из трех вещественных чисел. Решение. Входные параметры для функции - 3 вещест- венных числа, например а, Ь, с, результат - также вещественное число, содержащее минимальное из них. Функция может быть определена следующим образом: float minimal(float float b, float с) // заголовок ( float m = a; if (b<m) ft H локальная переменная m выбираем наименьшее из 2-х m - b; if (c<m) // выбираем наименьшее из 2-х m - c; return m; } // возвращаем результат m к месту вызова Существуют функции, не требующие для своей работы входных параметров. Примером может служить getch() из биб- лиотеки conio.h. При определении таких функций список аргу- ментов должен быть оставлен пустым или вместо него указыва- ется ключевое слово void (пустой). В любом из этих случаев круглые скобки в определении функции обязательны. В программах на C++ также нередки случаи, когда функция не возвращает результирующих значений (например, printf, scanf, getch и др.). При определении такой функции тип резуль- тата указывается как void, а оператор return не должен содер- жать возвращаемых значений. 94
Пример 2. Напишите функцию, целиком заполняющую эк- ран монитора текстовыми строками “_С++!”. Решение. Назовем функцию fill_screen. Так как для нее не требуются исходные данные, а результат не выражается числом, то список аргументов и тип результата опишем как пустые (void). void fill_screen(void) // функция без аргументов и { // без возвращаемого значения int п= 80*25/5; // необходимое число копий for(int i=l; i<=n; i++) cout « "_C++!"; return; // возврат к месту вызова } Здесь в теле функции введена локальная переменная п для расчета количества надписей, достаточных для заполнения всего экрана. При расчете учтено, что в текстовом режиме его размер составляет 80 х 25 символов, а размер каждой надписи - 5 сим- волов. 2. Вызов функции. Формальные и фактические параметры. Для обращения к функции (ее вызова) используется имя функции с указанием набора передаваемых ей параметров в круглых скобках имя_функции(список_фактических_параметров) Результатом этой операции является возвращаемое функци- ей значение. Вызов функции может быть произведен из любого места программы, в котором допускаются исполняемые опера- торы. Функция fill_screen из примера 2 (см. выше) может быть вызвана оператором: fill_screen(); < 95
Круглые скобки при обращении к функции обязательны, да- же если она не принимает аргументов. Рассмотрим теперь следующий фрагмент кода, в котором вызывается функция minimal из примера 1 (см. на с. 94): float х = 2.5, у = 3.1, z * 5.8; // float min; // min = minimal(х,у,z); // cout « "min of them = " « min; // 3 числа для сравнения перемённая для результата вызываем функцию результат на экран Здесь результат, возвращаемый функцией, заносится в до- полнительную переменную min и далее выводится на экран. Отметим важную особенность использования функций. Оп- ределение функции в списке аргументов содержит формальные параметры (float a, float b и float с - см. пример 1 на с. 94), зна- чения которых неизвестны на этапе написания тела функции. Они обретают конкретное содержание в момент вызова функ- ции, когда в скобках указываются фактические параметры, то есть переменные или константы, имеющие определенное значе- ние (как х, у, z из примера выше). Имена формальных и факти- ческих параметров не обязаны быть одинаковыми. Неукосни- тельным требованием является лишь соответствие их типов, то есть тип первого в списке фактического параметра (float х) дол- жен совпадать с типом первого формального параметра (float а), тип второго (float у) - со вторым (float b) и т. д. Пример 3. Напишите функцию, вычисляющую расстояние между двумя точками на плоскости (xj, yi) и (хг, уз). Используй- те эту функцию для расчета суммарной длины ломаной линии, заданной набором из N точек. Решение. Назовем функцию dist. Ее аргументы - четыре вещественных числа xl, yl, х2, у2, тип результата - также веще- ственное число. Для вычисления расстояния между точками 96
применим известную формулу L = д/(х2 - Xj )2 + (у2 - У] )2 . В теле основной функции main организуем два массива для хра- нения х- и у-координат всех точек. //-------------- расчет длины ломаной ------------- #pragma hdrstop #include <conio.h> tinclude <iostream.h> tinclude <math.h> // определение функции float diet (float xl, float yl, float x2, float y2) { float d; // локальная переменная d eqrt (pow(x2-xl,2)4pow(y2-ylr2)) ; // вычисляем расстояние return d; // возвращаем результат } #pragma argsused int main(int argc, char* argv[]) { const int N = 5; H число точек float X[N], Y[N]; // массивы для координат for(int i=0; i<N; i++) ( // вводим все координаты cout « i+1 « " point coordinates:\n"; cout « ” x = cin » X[i]; cout « ” у = ”; cin » Y[i]; } float L = 0.0; // доп. переменная for(int i=0; i<N-l; i++) // перебираем пары точек L +e diat(X[i] ,Y[i] ,X[i+l] ,Y[i+l]); // вычисляем длину cout « "\n\n Dlina lomanoi « " « L; // выводим результат getch(); return 0; } //----------------------------------------------------- 97
При вызове функции dist (выделено полужирным шрифтом) в качестве фактических параметров использованы элементы массивов X[N] и Y[N]. Запись является корректной, так как тип каждого из элементов массива (float) совпадает с типом соответ- ствующего формального параметра. Откомпилируйте эту про- грамму и запустите на выполнение. Проверьте результаты ее работы на простых примерах. Обратите внимание на то, что порядок выполнения операто- ров в этом примере отличается от привычного. В соответствии с правилами C++, программа начинается с функции main, несмот- ря на то, что функция dist описана раньше. Управление в dist передается только в моменты ее вызова, причем это происходит многократно на протяжении программы. 3. Прототипы функций. Прототип функции - это ее опережающее объявление. В прототипе указывается только имя функции, тип результата и типы аргументов. Он не содержит реализации (тела) функции, а всего лишь указывает компилятору, что ее определение будет дано ниже в тексте программы. Основное преимущество приме- нения прототипов состоит в том, что опережающие объявления дают возможность программировать вызов функций, которые в данной точке программы еще не определены. Если программа использует прототип функции, то обычно он располагается перед main или внутри нее, а определение (реализация) функции дается после main. Прототип должен пол- ностью соответствовать заголовочной строке в определении функции. Исключение составляют лишь имена формальных па- раметров, которые могут быть опущены. Описание прототипа всегда заканчивается символом точки с запятой: тип_функции имя(список_типов); 98
Например, прототипы функций minimal и fill screen из рассмотренных выше примеров должны быть записаны как float minimal(float, float, float, float); void fill_screen(void); Пример 4. Напишите функцию, вычисляющую факториал заданного целого числа N. Используйте эту функцию для выво- да на экран факториалов всех целых чисел от 0 до 10. Решение. Будем использовать итеративный метод расчета факториала, согласно его определению N! = 1-2-3-... N. Аргу- мент и возвращаемое значение функции опишем как целочис- ленные (int). //---------------- Расчет факториала -------------- #pragma hdrstop #include <conio.h> #include <iostream.h> #include <math.h> int factorial(int); // прототип функции factorial #pragma argsused int main(int argc, char* argv[]) // главная функция - main { const int N = 10; for(int i=0; i<=N; i++) // вызываем функцию в цикле cout«i«" ’ = "«factorial (i) «endl; getch(); return 0; int factorial(int n) if(n<0) // определение функции factorial // проверка на отрицательный // аргумент cout « "Error: n<0!"; // вывод сообщения об ошибке return -1; 99
int г = 1.; for(int i=l; i<=n; i++) // итеративный расчет n! r *= i; return r; // возвращаем результат } //------------------------------------------------- Типичные ошибки программирования 1. В заголовке определения или в прототипе функции в списке аргументов вместо запятой используется точка с запятой (int a; int b). Эта ошибка сопровождается сообщением «Error: Expression syntax». 2. Однотипные аргументы функции ошибочно определяют- ся как (float х, у) вместо (float х, float у). Компилятор ответит на это сообщением «Error: type name expected». 3. Первая строка определения функции ошибочно заверша- ется символом точки с запятой. Это приведет к сообщению «Er- ror: Declaration terminated incorrectly». 4. Отсутствует оператор return в функции, которая должна возвращать значение. На этапе компиляции это не будет вос- принято как синтаксическая ошибка, однако будет выведено предупреждение «Warning: function should return a value». В про- тивоположной ситуации, при попытке возвратить результат из функции, объявленной как void, компилятор выдаст сообщение об ошибке «Error: function cannot return a value». 5. Один или несколько аргументов функции повторно объ- являются как локальные переменные. Компилятор распознает эту логическую ошибку и ответит на нее сообщением «Error: multiple declaration...». 100
6. Определение одной функции внутри другой. Такая ошибка приведет к сообщению «Error: Declaration syntax error». 7. Попытка вызова функции, которая не описана ранее и для которой не найден соответствующий прототип. Сообще- ние компилятора - «Error: call to undefined function». Контрольные вопросы 1. Определение пользовательской функции. Аргументы, возвращаемое значение и тело функции. Пример. 2. Функции без аргументов и функции, не возвращающие результат. Примеры. 3. Вызов функции и возврат из нее. Оператор return. При- мер. 4. Формальные и фактические параметры функции. Соот- ветствие их типов. Пример. 5. Прототип функции. Общая форма записи и назначение прототипов. Пример. 6. Рассмотрите следующие определения функций. Дайте их краткое описание (имя, тип результата, количество и тип аргу- ментов). Одной фразой сформулируйте цель, которую реализует каждая из этих функций (например, «вычисляет сумму двух аргументов», «выводит на экран целые числа от 0 до 100» и т. д.). a) int P(int xl, int x2) 6) int S(int x, int y) { < int x3 = x2*xl; if(x>y) return y; return x3; else return x; } } 101
в) void myprint(int x) { cout « "x=" « x; return; } д) void repeat(char symbol) { for(int i=0; i<20; i++) cout « symbol; return; } r) void say_yes(void) ( cout « "Yes!"; return; e) void minpow(float x, int k) ( float у = pow(x, k); cout « y; return; 7. Найдите ошибки в следующих конструкциях: a) int F(int k) б) { int k = 0; return k; } в) int summa(int a, b) { int c = a + b; return c; ) д) int raznost(int n, int m) { int result = m - n; return; } float G(int x, float y) { return x + y; } void myprintf(int k) { cout « "k«" « k; return k; } e) void S(int, int) { cout « int « int; return; } r) Практические задания 1. Напишите пользовательскую функцию, вычисляющую площадь заданной геометрической фигуры: а) площадь круга по его радиусу; б) площадь трапеции по двум основаниям и высоте; в) площадь треугольника по трем сторонам. 102
2. Напишите пользовательскую функцию, вычисляющую объем заданного тела: а) объем шара по радиусу; б) объем конуса по радиусу основания и высоте; в) объем пирамиды по площади основания и высоте; г) объем шарового сегмента по его высоте и радиусу шара; д) объем усеченного конуса по высоте и радиусам двух ос- нований; е) объем усеченной пирамиды по высоте и площадям двух оснований. 3. Производная от функции y = f(x) в точке х = х0 может быть рассчитана численно по следующей формуле: ,/ ч df f(x0 + Ax)-f(x0) f (х0) = — ® , при малых Дх. dx v=v Дх Для некоторой y = f(x) напишите пользовательскую функ- цию, вычисляющую f'(x0) Аргументами функции должны быть вещественные х0 и Дх. Проведите расчеты значений производ- ной на заданном отрезке [А, В] с шагом 5х. Сравните результа- ты с точным аналитическим решением. Исследуйте и объясните зависимость точности расчетов от Дх. 4. Вторая производная от функции у = f(x) в точке х = х0 может быть рассчитана численно по формуле: \d2f f(x0 + Ax)-2f(x„)+f(x0 - Дх) “-’’dx2 “ Дх2 х=х0 при малых Дх. 103
Для некоторой y = f(x) напишите пользовательскую функ- цию, вычисляющую f*(x0). Аргументами функции должны быть вещественные х0 и Дх. Проведите расчеты значений второй производной на отрезке [А, В] с шагом 5х. Сравните результа- ты с точным аналитическим решением. Исследуйте и объясните зависимость точности расчетов от Дх. 5. Напишите функцию, принимающую в качестве аргумен- тов декартовы координаты вектора в пространстве и возвра- щающую модуль этого вектора. 6. Напишите функцию, принимающую в качестве аргумен- тов декартовы координаты двух векторов в пространстве и воз- вращающую угол между этими векторами. 7. Напишите функцию, вычисляющую скалярное произве- дение двух векторов. В качестве аргументов функции исполь- зуйте декартовы координаты векторов. 8. Напишите функцию, заполняющую окно приложения за- данным текстовым символом. 9. Напишите функцию, вычисляющую длину гипотенузы прямоугольного треугольника по двум его катетам. 10. Целое число называется совершенным, если все его дели- тели в сумме дают само это число (например, 6- совершен- ное число, так как 6 = 1 + 2 + 3). Напишите функцию, опреде- ляющую, является ли заданное число совершенным. 11. Целое число называется простым, если оно делится только на 1 и на само себя (например, 2, 3, 5 - простые чис- ла). Напишите функцию, определяющую, является ли заданное число простым. 104
12. Напишите функцию, принимающую в качестве аргумен- та целое число и возвращающую его с обратным порядком деся- тичных цифр (например, 3951 -> 1593). 13. Напишите функцию, вычисляющую день недели (поне- дельник, вторник, среда и т. д.) для заданной даты. Дата опреде- лена тремя целыми числами - числом, месяцем и годом. Функ- ция возвращает номер дня в неделе (1,2, 3 и т. д.). 14. Напишите функцию, вычисляющую количество дней, прошедших между двумя датами. Даты заданы с помощью трех целых чисел - числа, месяца и года. 15. Напишите функцию, вычисляющую наибольший общий делитель двух заданных целых чисел. 105
ПРИЛОЖЕНИЯ Приложение 1 Порядок выполнения практических работ. Требования к отчету Допуск обучающегося к выполнению практических работ в рамках данного курса возможен только на условиях соблюдения им правил безопасности и внутренних правил работы с персо- нальными компьютерами. Практические занятия, предусмотренные при изучении каж- дой темы, предполагают самостоятельный анализ задания, раз- работку, отладку и тестирование соответствующей программы. Алгоритм выполнения практической работы: 1. Предварительно изучить теоретический материал соответ- ствующей темы. 2. Оформить в тетради «шапку» отчета (см. Приложение 2, с. 107-108). 3. Получить у преподавателя и записать в тетради практиче- ское задание. 4. Разработать и реализовать программу. 5. Протестировать ее работу при различных входных пара- метрах. 6. Получить и записать результаты. 7. Отчитаться по практической части работы. 8. Полностью оформить отчет, подготовиться к сдаче теории. 9. Отчитаться по теоретической части работы. Требования к отчету по практической части: 1. Показать на примерах правильность результатов, полу- ченных с помощью разработанной программы. 106
2. При необходимости кратко сформулировать алгоритм ра- боты программы и выделить в программе основные блоки, от- ветственные за выполнение определенных действий (напри- мер, ввод исходных данных, объявления переменных, вывод на экран и т. д.). 3. Знать и при необходимости объяснить работу всех исполь- зованных в программе языковых конструкций. 4. Знать и при необходимости объяснить назначение и смысл всех использованных констант и переменных. Требования к отчету по теоретической части: 1. Правильно и аккуратно оформить отчет в тетради. 2. Ответить на контрольные вопросы. З. При необходимости ответить на дополнительные вопросы преподавателя. Приложение 2 Образец оформления отчета по практической работе Практическая работа №1 Операции ввода-вывода. Арифметические операции Учащийся Сидоров А. А., 10 «Б» Программа: дата подпись учителя Теория: дата подпись учителя Задание 1. Напишите программу, вычисляющую произведе- ние двух заданных с клавиатуры чисел. Г07
Теория: Консольный ввод-вывод. ... (кратко о библиотеке, основных операторах и т. д.) Потоковый ввод-вывод. ... (кратко о библиотеке, объектах cin и cout и т. д.) Арифметические операции. ... (кратко о бинарных операциях с примерами) Математические функции. ... (кратко о библиотеке math.h и основных функциях) Программа: #include <iostream.h> #include <conio.h> #pragma argsused int main(int argc, char* argv[]) { float a,b; // объявляем переменные a,b cout « "Vvedite a = "; cin » a; // вводим а с клавиатуры cout « "Vvedite b = "; cin » b; // вводим b с клавиатуры float c = a * b; // вычисляем c = a * b cout « "Resultat: "; cout « a « "*" « b « "=" « с;// выводим с на экран getch (); return 0; Входные данные и результаты 1) Vvedite а = 2 Vvedite b = 2 Resultat: 2*2=4 2) Vvedite a = 5 Vvedite b = 5 Resultat: 5*5=25 108
Приложение 3 Основные функции стандартных библиотек языка С 1. Функции консольного ввода/вывода. Функция: void clrscr(void); Библиотека: conio.h Назначение: Очистка текущего текстового окна программы (очистка экрана). Аргументы - нет. Возвращаемое значение - нет. Функция: void gotoxy(int х, int у); Библиотека: conio.h Назначение: Установка курсора в нужную позицию экрана (текстового окна). Аргументы - текстовые координаты курсора (1<х<44, 1<у<80). Если задан- ные в качестве аргументов значения (х, у) выходят за допустимые границы, вызов функции gotoxy() игнорируется. Возвращаемое значение - нет. Функция: int wherex(void); Библиотека: conio.h Назначение: Возвращает текущую горизонтальную позицию курсора в текстовом окне программы. Аргументы - нет. Возвращаемое значение - целое чис- ло в диапазоне от 1 до 80 включи- тельно, соответствующее х-позиции курсора. 109
Функция: Библиотека: int wherey(void); conio.h Назначение: Возвращает текущую вертикальную позицию курсора в текстовом окне программы. Возвращаемое значение - целое число Аргументы - нет. в диапазоне от 1 до 44 включительно, соответствующее у-позиции курсора. Функция: Библиотека: void delline(void); conio.h Назначение: Удаление текущей текстовой строки (в которой находится курсор) и перемещение всех расположенных ниже строк на одну позицию вверх. Аргументы - нет. Возвращаемое значение - нет. Функция: Библиотека: void insline(void); conio.h Назначение: Вставка пустой текстовой строки в точку расположения курсора и сме- щение всех расположенных ниже строк на одну позицию вниз. Аргументы - нет. Возвращаемое значение - нет. Функция: Библиотека: void _setcursortype(int cur_t) ; conio.h Назначение: Установка формы текстового курсора. Аргумент - целое число cur_t> принимаю- щее одно из значений: NOCURSOR - курсор невидим, Возвращаемое значение - нет. NORMALCURSOR - обычный курсор, _SOLIDCURSOR - блочный курсор. ПО
Функция: void textcolor(int newcolor); Библиотека: conio.h Назначение: Установка цвета, используемого для вывода текстовых символов на экран. Действует только при работе с функциями прямого консольного вывода (например, putch и cprintf). Аргумент - целое число, номер цвета. Вместо числовых значений также могут использоваться символьные константы, определенные в файле conio.h: BLACK 0 - черный BLUE 1 - синий GREEN 2 - зеленый CYAN 3 - голубой RED 4 - красный MAGENTA 5 - малиновый BROWN 6 - коричневый LIGHTGRAY 7 - светло-серый DARKGRAY 8 - темно-серый LIGHTBLUE 9 - ярко-синий LIGHTGREEN 10 - ярко-зеленый LIGHTCYAN 11 - ярко-голубой LIGHTRED 12 - ярко-красный LIGHTMAGENTA 13 - ярко-малиновый YELLOW 14-желтый WHITE 15-белый Возвращаемое значение - нет. Функция: Библиотека: void textbackground(int new- conio.h color); Назначение: Установка цвета фона, используемого при выводе текстовых символов на экран. Как и предыдущая функция, работает только с функциями прямого консольного вывода. 111
Аргументы - целое число от 0 до 7, или одна из следующих символьных кон- стант: BLACK 0- черный BLUE 1 - синий GREEN 2 - зеленый Возвращаемое значение - нет. CYAN 3 - голубой RED 4- красный MAGENTA 5 - малиновый BROWN 6- коричневый LIGHTGRAY 7- светло-серый. Функция: int putch(int с) ; Библиотека: conio.h Назначение: Выводит на экран текстовый символ, используя прямой видеовывод. Цвет выводимого символа и цвет фона определяются текущими значе- ниями, установленными с помощью функций textcolor и textbackground. Аргумент - код текстового символа. Функция не транслирует управляющие символы. Возвращаемое значение - при удач- ном завершении - код выведенного символа, при неудачном - EOF. Функция: int cprintf(const char ♦format[, argument, ...]); Библиотека: conio.h Назначение: Форматируемый вывод на экран. В зависимости от значения глобаль- ной переменной _directvideo, используются либо функции BIOS, либо прямой доступ к видеопамяти. Аргументы - форматная строка и набор числовых переменных. Все аргументы аналогичны соответствующим аргумен- там функций printf, scanf. Возвращаемое значение: число сим- волов, выведенных на экран. 112
Функция: Библиотека: void textmode(int newmodo) ; conio.h Назначение: Установка текстового режима, используемого в окне программы. Аргумент: символьная константа, опре- деленная в файле conio.h и определяю- щая номер текстового режима. Наибо- лее часто используемые режимы: LASTMODE -предыдущий BW40 - ч/б, 40 столбцов Возвращаемое значение: нет. С40 - цветной, 40 столбцов BW80 - ч/б, 80 столбцов С80 - цветной, 80 столбцов MONO - монохромный, 80 столбцов С4350 - режим EGA-43 и VGA-50 2. Функции работы с файлами. Функция: Библиотека: FILE *fopen (const char stdio.h ♦filename, const char *mode) ; Назначение: Открывает файл с заданным именем для чтения/записи. Связывает от- крытый файл с потоком ввода/вывода. Аргументы: filename - текстовая строка с именем открываемого файла. Может содержать указание пути к файлу. mode - режим открытия файла. Прини- мает следующие значения: г w а г+ - открытие файла для чтения - создание файла для записи - добавление к существующему файлу - обновление существующего фай- ла (чтение и запись) - создание нового файла для об- новления (чтения и записи) - открытие файла для чтения Возвращаемое значение: В случае успешного завершения функция возвращает указатель на связанный с файлом поток вво- да/вывода. Указатель может исполь- зоваться для последующих операций ввода/вывода. В случае ошибки воз- вращается значение NULL. 113
Функция: int fclose(FILE *stream); Библиотека: stdio.h Назначение: Закрывает файл. Аргумент: Возвращаемое значение: указатель на открытый файловый по- ноль в случае успешного завершения, ток. и ненулевое значение в случае ошибки. Функция: int fprintf(FILE *stream, const char *format[, argu- ment , Библиотека: stdio.h Назначение: Форматированный вывод данных в файл. Аргументы: указатель на открытый файловый поток stream, форматная строка format и про- извольное число числовых аргументов. Все аргументы fprintf аналогичны соот- ветствующим аргументам printf (за ис- ключением первого). Возвращаемое значение: В случае удачного завершения - фактическое число байтов, записан- ных в файл. В случае ошибки - зна- чение EOF. Функция: int fscanf(FILE *stream, const char *format[, ad- dress , ...]); Библиотека: stdio.h Назначение: Форматированный ввод данных из файла. Аргументы: указатель на открытый файловый поток stream, форматная строка format и про- извольное число адресов числовых ар- гументов. Все аргументы fscanf анало- гичны соответствующим аргументам printf (за исключением первого). Возвращаемое значение: В случае удачного завершения - чис- ло полей данных, фактически счи- танных из файла. При попытке чте- ния из конца файла - значение EOF. 114
Функция: char *fputs(char *s, FILE *stream); Библиотека: stdio.h Назначение: Запись текстовой строки в файловый поток. Аргументы: текстовая строка s, указатель на файло- вый поток stream (поток должен быть открыт для записи). Возвращаемое значение: при удачном завершении - неотри- цательное число, в случае ошибки - NULL. Функция: char *fgets(char *s, int n, FILE *stream) ; Библиотека: stdio.h Назначение: Чтение текстовой строки из файлового потока. Аргументы: текстовая строка (s), максимальное число байт, доступное для чтения (п), указатель на открытый файловый поток (stream). Возвращаемое значение: в случае удачного завершения - ука- затель на считанную текстовую стро- ку, в случае ошибки - NULL Функция: int feof(FILE *stream); Библиотека: stdio.h Назначение: Проверка на достижение конца файла. Аргумент: указатель на открытый файловый по- ток. Возвращаемое значение: ненулевое значение, если достигнут конец файла, в противном случае - ноль. 115
Функция: int fseek(FILE *stream, long offset, int whence); Библиотека: stdio.h Назначение: Переустановка файлового указателя в позицию, соответствующую off- set байтам относительно файловой позиции whence. Аргументы: stream - открытый файловый поток, offset - относительное смещение, Возвращаемое значение: whence - одно из следующих значений: нуль в случае успешного завершения SEEKSET 0 - начало файла операции, код ошибки - в противном SEEK_CUR 1 - текущее положе- случае. ние указателя SEEKJEND 2 - конец файла. 3. Функции символьной классификации. Функция: Библиотека: int isalpha(int с); с type, h Назначение: Определяет, является ли аргумент алфавитным символом. По умолчанию алфавитным считается символ, попадающий в диапазон ‘a’-‘z’, Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с - символ алфавита. Функция: int isdigit(int с) ; Библиотека: ctype.h Назначение: Определяет, является ли аргумент десятичной цифрой. Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с - десятичная цифра (‘0’-‘9’). 116
Функция: Библиотека: int ispunct(int с); ctype.h Назначение: Определяет, является ли аргумент символом пунктуации. По умолча- нию символами пунктуации считаются все символы, не являющиеся алфавитно-цифровыми (за исключением символа пробела ‘ ‘)- Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с - символ пунктуации. Функция: int iscntrl(int с); Библиотека: ctype.h Назначение: Определяет, является ли аргумент управляющим символом. По умол- чанию управляющие символы - это символ удаления 0x7F и все симво- лы из диапазона 0x00 - 0x1 F. Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с - управляющий символ. Функция: Библиотека: int islower(int с); ctype.h Назначение: Определяет, является ли аргумент алфавитным символом нижнего ре- гистра (по умолчанию ‘a’-‘z’). Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с -алфавитный символ в ниж- нем регистре. 117
Функция: int isupper(int с); Библиотека: ctype.h Назначение: Определяет, является ли аргумент алфавитным символом верхнего ре- гистра (по умолчанию ‘A’-‘Z’). Аргумент: ASCII-код символа. Возвращаемое значение: ненулевое, если с - символ алфавита в верхнем регистре. 4. Функции символьных преобразований. Функция: double atof(const char *s); Библиотека: stdlib.h Назначение: Преобразование текстовой строки вида [пробелы] [±] [ddd] [.] [ddd] [e|E[±]ddd] в вещественное число (ddd - произвольный набор десятич- ных цифр). Аргумент: символьная строка s с тек- стовым представлением вещественного числа. Возвращаемое значение: в случае успешного преобразования - веще- ственное число, в противном слу- чае - код ошибки. Функция: Библиотека: int atoi (const char *s) ; stdlib.h Назначение: Преобразование текстовой строки вида [пробелы] [±] [ddd] в целое чис- ло (ddd - произвольный набор десятичных цифр). Аргумент: символьная строка с тексте- Возвращаемое значение: в случае вым представлением целого числа. успешного преобразования - целое число, в противном случае - ноль. 118
Функция: Библиотека: int tolower(int ch); ctype. h Назначение: Преобразование текстового символа в нижний регистр. Аргумент: ASCII-код символа. Возвращаемое значение: код симво- ла в нижнем регистре. Функция: int toupper(int ch); Библиотека: ctype. h Назначение: Преобразование текстового символа в верхний регистр. Аргумент: ASCII-код символа. Возвращаемое значение: код симво- ла в верхнем регистре. 5. Строковые функции. Функция: int strcxnp (const char *sl, const char *s2); Библиотека: string.h Назначение: Сравнение двух текстовых строк. Выполняется путем последовательно- го посимвольного сравнения аргументов до тех пор, пока не будет най- дено первое различие либо пока не будет достигнут конец строки. Аргументы: две символьные строки. Возвращаемое значение: si меньше, чем s2 <0 si равно s2 =0 si больше, чем s2 > 0. 119
Функция: char *strcpy(char *dest, const char *src); Библиотека: string.h Назначение: Копирование одной текстовой строки в другую. Аргументы: src - копируемая строка, dost - строка, в которую производится копи- рование. Возвращаемое значение: текстовая строка. Функция: int strlen(const char *s) ; Библиотека: string.h Назначение: Длина текстовой строки. Аргумент: Возвращаемое значение: текстовая строка. количество символов в строке. Функция: char *strcat(char *dest, const char *src); Библиотека: string.h Назначение: Объединение двух текстовых строк (конкатенация). Реализуется путем добавления второй строки в конец первой. Аргументы: src - добавляемая строка, dost - строка, к которой добавляется src. Возвращаемое значение: объединенная текстовая строка. 120
Функция: char *strchr(const char *s, int c); Библиотека: string.h Назначение: Поиск заданного символа в текстовой строке. Аргументы: s - строка поиска, с - код символа. Возвращаемое значение: если строка содержит искомый сим- вол - указатель на его позицию, в противном случае - NULL. Функция: char *strlwr(char *s); Библиотека: string.h Назначение: Преобразование текстовой строки в нижний регистр. Аргумент: Возвращаемое значение: текстовая строка. текстовая строка в нижнем регистре. Функция: char *strupr(char *s); Библиотека: string.h Назначение: Преобразование текстовой строки в верхний регистр. Аргумент: Возвращаемое значение: текстовая строка. текстовая строка в верхнем регистре. Функция: Библиотека: char *strrev(char *s) ; string.h Назначение: Обращение текстовой строки (замена прямого порядка следования сим- волов на обратный). Аргумент: Возвращаемое значение: текстовая строка. строка с обратным порядком следо- вания символов (за исключением завершающего нулевого символа). 121
Функция: Библиотека: char *strset(char *s, int ch) ; string.h Назначение: Заполнение строки необходимым числом копий заданного символа. Аргументы: Возвращаемое значение: s - текстовая строка, ch - код символа. текстовая строка з. 6. Функции системного времени и даты. Функция: Библиотека: void get time (struct time dos.h * timep); Назначение: Получение системного времени. Функция заполняет структуру, пере- данную в качестве параметра, значениями, полученными от системного таймера (часы, минуты, секунды, миллисекунды). Аргумент: timep - указатель на структуру struct time / Возвращаемое значение: нет. I unsigned char ti_min; //минуты unsigned char ti_hour; //часы unsigned char ti_hund; //миллисекунды unsigned char ti sec; //секунды }; Функция: void settime(struct time *timep); Библиотека: dos.h Назначение: Изменение системного времени. Новое значение времени (часы, мину- ты, секунды, миллисекунды) передается системному таймеру через структуру, указанную в качестве параметра. Аргумент: timep - указатель на структуру struct time i Возвращаемое значение: нет. t unsigned char ti_min; //минуты unsigned char ti_hour; //часы unsigned char ti^hund; //миллисекунды unsigned char ti sec; //секунды }; 122
Функция: void getdate(struct time *datep); Библиотека: dos.h Назначение: Получение системной даты. Функция заполняет структуру, переданную в качестве параметра, значениями текущего года, месяца и дня. Аргумент: da t ер - указатель на структуру struct date { int da_year; // текущий год char da_day; // день месяца char da mon; // месяц (1-январь) }; Возвращаемое значение: нет. Функция: void setdate(struct time *datep); Библиотека: dos.h Назначение: Установка системной даты. Новая дата (год, месяц, день месяца) пере- дается через структуру, указанную в качестве параметра. Аргумент: datер - указатель на структуру struct date Возвращаемое значение: нет. j int da_year; // текущий год char da_day; // день месяца char da mon; // месяц (1-январь) ); Функция: Библиотека: char *__strtime (char *buf) ; time.h Назначение: Возвращает текущее системное время как текстовую строку вида HH:MM:SS, где НН - часы, ММ - минуты, SS - секунды. Аргумент: Возвращаемое значение: текстовая строка с минимальным раз- заполненная текстовая строка, мером 9 символов (исключая завер- шающий нулевой символ). 1ft
Функция: char *_strdate(char *buf); Библиотека: time.h Назначение: Возвращает текущую системную дату как текстовую строку вида MM/DD/YY, где ММ - текущий месяц, DD - день месяца, YY - год. Например, 10/16/07 - 16 октября 2007 года. Аргумент: текстовая строка с минимальным раз- мером 9 символов (исключая завер- шающий нулевой символ). Возвращаемое значение: заполненная текстовая строка. 7. Функции генерации (псевдо)случайных чисел. Функция: void randomize(void); Библиотека: stdlib.h Назначение: Инициализация генератора случайных чисел. Аргументы: Возвращаемое значение: нет. нет. Функция: Библиотека: int rand(void); stdlib.h Назначение: Генерирует целое случайное число с равномерным распределением в диапазоне от 0 до RANDMAX. Константа RANDMAX определена в файле stdlib.h. Аргументы: Возвращаемое значение: нет. случайное число. 124
Функция: int random(int num); Библиотека: stdlib.h Назначение: Генерирует целое случайное число с равномерным распределением в диапазоне от 0 до (num-1). Использует мультипликативный конгруэнт- ный генератор с периодом 232. Аргументы: нет. Возвращаемое значение: случайное число от 0 до (num-1). Приложение 4 Примеры консольных программ Программа № 1. Пользовательский интерфейс. Приведенный ниже листинг программы демонстрирует не- которые важные приемы работы с текстовой консолью - управ- ление положением курсора, управление цветом выводимого на экран текста, а также анализ и реакцию на нажатие пользовате- лем различных клавиш. В коде программы используются только простейшие языковые конструкции (цикл for и набор операто- ров if), а также несколько функций из библиотек conio.h. Спра- вочная информация о назначении и аргументах этих функций содержится в Приложении 3 (см. на с. 109-125). Приведенный листинг может использоваться в качестве шаблона для построе- ния простых программ с красивым и удобным пользовательским интерфейсом. Приложение позволяет: • позиционировать курсор в нужном месте текстового окна с помощью стрелок на клавиатуре; 125
• выводить на экран коды нажатых клавиш; • выводить на экран цветной текст клавишей Enter; • управлять цветом выводимого текста с помощью клавиш «+/-»; • очищать экран клавишей забоя (backspace); • осуществлять выход из программы, который происходит при нажатии на клавишу Esc. Рисунок показывает пример текстового окна этой про- граммы (в черно-белом варианте): Colored text) Colored text! Colored text? Colored text! Colored text! Colored text! Colored text! Colored text! //-------------Colors and keys #include <conio.h> tinclude <iostream,h> #pragma hdrstop #pragma argsused int main(int argc, char* argv[J) { int x»lr y=l; // текущие координаты курсора int color=l; // текущий цвет текста bool quit=false; // контроль окончания программы int key=0; // код нажатой клавиши 126
for( ; quit==false; ) // цикл работает до тех пор, { // пока quit ~ false gotoxy(l,l); // установка курсора cout « "Cursor: (" « х « « у « ")";// позиция clreol(); cout « "\nText color: ” « color; // цвет clreol(); cout « "\nKey pressed: " « key; // код клавиши clreol(); gotoxy(x,y); key = getch(); // считываем код клавиши if(key==0) // управляющая клавиша? key = getch(); if(key==27) // если нажат Esc quit=true; if(key==8) // если нажат backspace clrscr(); if(key»=13) // если нажат Enter textcolor(color); cprintf("Colored text!") ; ) if((key»-72)&&(y>l)) // нажата клавиша «Вниз» у—; i f((key==8 0)& &(y<4 4)) // нажата клавиша «Верх» У++; if((key==75)&&(x>l)) // нажата клавиша «Влево» x—; if((key==77)&&(x<80)) // нажата клавиша «Вправо» x++; if((key==45)&&(color>l)) // нажата клавиша «+» color—; if((key==43)&&(color<16)) // нажата клавиша «-» color++; ) return 0; } // 12'7
Программа № 2. Игра «Тараканьи бега». Приведенный ниже листинг показывает простейшую реали- зацию игры «Тараканьи бега». Программа использует только базовые средства языка С и небольшой набор вспомогательных функций библиотек conio.h и stdlib.h. Основу алгоритма состав- ляет генерация (псевдо)случайных чисел, которая реализована с помощью функций int random(int). Описание этой и других функций, встречающихся в программе, содержится в Приложе- нии 3 (см. на с. 109-125). Пример текстового окна программы (по окончании «забега»): fcoWGTttfV. .finished! Winner is BUG «It bug bug bug 3: кНННННННННкННННИНПНННИкННННПП Листинг программы № 2: //-------------Тараканьи бега #include <stdlib.h> #include ciostream.h> #include <con,io.h> #pragma hdrstop 128
Ipragma argsused int main(int argc, char* argv[]) { int bugl=7, bug2=7, bug3=7; // позиции «жуков» char sled=’M’; clrscr(); gotoxy(1,5); cout « "bug gotoxy(1,7); cout « "bug gotoxy(1,9); cout « "bug 1:" « sled; 2:" « sled; 3:" « sled; gotoxy(1,1); cout « "Press any key getch(); gotoxy(1,1); cout « "Go BUGS! ! ! "; clreol(); randomize(); for(bool quit=false; quit== { int stepl « random(2); bugl +- stepl; int step2 « random(2); bug2 +• step2; int step3 = random(2); bug3 += step3; gotoxy(buglr5); cout « sled; gotoxy(bug2,7); cout « sled; gotoxy(bug3,9); cout « sled; if((bugl==80)||(bug2« quit=true; to start..."; // инициализация генератора false; ) // генерируем шаг 1-го «жука» // шагаем // генерируем шаг 2-го «жука» // шагаем // генерируем шаг 3-го «жука» // шагаем // отображаем 1-го «жука» // отображаем 2-го «жука» // отображаем 3-го «жука» «80)||(bug3==80)) // добрались до финиша Sleep(100); // небольшая задержка 129
} gotoxy(12,1); cout « ”... finished! if((bugl==bug2)&&(bugl»=80)I I (bugl==bug3)&&(bugl==80)|| (bug2==bug3)&&(bug2==80)) { cout « ”\nNo winner bug!”; getch(); return 0; } // как минимум двое пришли // к финишу одновременно - // нет победителя int winner; // номер победителя if((bugl>bug2)&&(bugl>bug3)) winner « 1; if((bug2>bugl)&&(bug2>bug3)) winner » 2; if((bug3>bugl)&&(bug3>bug2)) winner = 3; cout « "\nWinner is BUG #” « winner « ”!”; getch(); return 0; ) //----------------------------------------------- 130
ЛИТЕРАТУРА 1. Архангельский, А. Я. C++ Builder 6: спр. пособие. Кн. 1. Язык C++. - М.: БИНОМ, 2002. 2. Березин, Б. И., Березин, С. Б. Начальный курс С и C++. - М.: Диалог-МИФИ, 1996. 3. Дейтел, X, Дейтел, П. Как программировать на C++. - М.: БИНОМ, 2000. 4. Литвиненко, Н. А. Технология программирования на C++. Начальный курс. - СПб.: BHV-СПб., 2005. 5. Подбельский, В. В. Язык C++. - 5-е изд. - М.: Финансы и ста- тистика, 2000. 6. Страуструп, Б. Введение в язык C++. - 3-е изд. - М.: БИ- НОМ паблишере, 2002. 7. Страуструп, Б. Язык программирования C++. Специальное издание. - СПб.: Невский диалект, 2004. 8. Топп, У., Форд, У. Структуры данных в C++. - М.: БИНОМ, 2000. 9. Холингворт, Дж. Borland C++ Builder 6: руководство разработ- чика.-М.: SAMS, 2003. 10. Эккель, Б., Эллисон, Ч. Философия C++. Практическое про- граммирование. - СПб.: Питер, 2004. 11. http://physics.volsu.ru (раздел «Библиотека -> Программиро- вание») - книги, пособия, учебники и документация по про- граммированию на языке C++. 131
СОДЕРЖАНИЕ Введение...............................................3 Примерное распределение занятий по программированию на языке C++ (рекомендуемое количество часов)..........6 Тема 1. C++ Builder и консольные приложения ...........7 Программа, язык программирования. Создание консольного приложения в C++ Builder. Компиляция, компоновка и запуск программы. Общая структура программы на языке C++. Ис- пользование библиотек. Объявления и инициализация пере- менных. Стандартные типы данных Тема 2. Операции ввода-вывода. Арифметические операции ....21 Консольный ввод-вывод. Потоковый ввод-вывод. Арифмети- ческие операции и математические функции Типичные ошибки программирования.................32 Контрольные вопросы..............................33 Практические задания.............................34 Тема 3. Оператор условия if-else......................36 Назначение и синтаксис. Сокращенные варианты записи. Вло- женные операторы условия. Составные логические выражения Типичные ошибки программирования.................45 Контрольные вопросы..............................45 Практические задания.............................47 Тема 4. Оператор цикла for............................50 Назначение и синтаксис. Сокращенные варианты записи. Вло- женные операторы цикла Типичные ошибки программирования.................60 Контрольные вопросы..............................61 Практические задания.............................62 Тема 5. Массивы I. Поэлементные операции..............65 Одномерные (линейные) массивы. Многомерные массивы. Типизированные константы. Инициализация элементов массива Типичные ошибки программирования.................75 Контрольные вопросы..............................76 Практические задания.............................77 132
Тема 6. Массивы II. Алгоритмы поиска и сортировки ....79 Линейный поиск по условию. Поиск максимального (мини- мального) элемента. Сортировка методом «прямого выбора». Сортировка методом «пузырька» Типичные ошибки программирования.................86 Контрольные вопросы..............................87 Практические задания.............................89 Тема 7. Функции.......................................92 Определение функции. Вызов функции. Формальные и факти- ческие параметры. Прототипы функций Типичные ошибки программирования................100 Контрольные вопросы.............................101 Практические задания............................102 Приложения Приложение 1. Порядок выполнения практических ра- бот. Требования к отчету.............................106 Приложение 2. Образец оформления отчета по практи- ческой работе........................................107 Приложение 3. Основные функции стандартных биб- лиотек языка С.......................................109 1. Функции консольного ввода/вывода..........109 2. Функции работы с файлами..................113 3. Функции символьной классификации..........116 4. Функции символьных преобразований..........118 5. Строковые функции.........................119 6. Функции системного времени и даты.........122 7. Функции генерации (псевдослучайных чисел..124 Приложение 4. Примеры консольных программ.......125 Программах® 1. Пользовательский интерфейс....125 Программа № 2. Игра «Тараканьи бега».........128 Литература...........................................131 133
Охраняется законом об авторском праве. Воспроизведение всего пособия или любой его части, а также реализация тиража запрещаются без письменного разрешения издателя. Любые попытки нарушения закона будут преследоваться в судебном порядке. Приглашаем к сотрудничеству учителей, методистов и других специалистов в области образования для поиска и рекомендации к публикации интересных материалов, разработок, проектов по учебной и воспитательной работе. Издательство «Учитель» вы- плачивает вознаграждение за работу по поиску материала. Издательство так- же приглашает к сотрудничеству авторов и гарантирует им выплату гонора- ров за предоставленные работы. E-mail: metod-uch@bk.ru Телефон: (8442) 4S41-43; 66-17-39 Подробности см. на сайте издательства «Учитель»: www.uchitel-izd.ru Сергей Владимирович Феськов, кандидат физико-математических наук, доцент кафедры ТФ и ВП ВолГУ ИНФОРМАТИКА 10—11 классы Программирование на языке C++ (материалы к занятиям) Ответственные за выпуск Л. Е. Гринин, А. В. Перепелкина Редактор А. В. Перепелкина Редакторы-методисты Л. В. Голубева, В. Н. Максимочкина Технический редактор Л. В. Иванова Редактор-корректор С. В. Бакунина Корректор Т. И. Коробкнна Компьютерная верстка Е. П. Федоровой Издательство «Учитель» 400067, г. Волгоград, п/о 67, а/я 32 Подписано в печать 01.02.08. Формат 60x84/16. Бумага газетная. Гарнитура Тип Таймс. Печать офсетная. Усл. печ. л. 8,0. Тираж 7000 экз. Заказ 610. Отпечатано с оригинал-макета в ВО ГУПП «Николаевская межрайонная типография». 404033 г. Николаевск, Волгоградской обл., ул. Октябрьская, 4.
УВАЖАЕМЫЙ ПОКУПАТЕЛЬ! Наше издательство успешно работает на российском книжном рынке уже семнадцатый год. За это время миллионы учащихся, родителей, учителей и людей самых разных воз- растов и профессий воспользовались нашими услугами. Мы предоставляем возможность заказать книги по почте. Оплата заказанных книг производится только после их получения на почте (наложенный платеж), поэтому наши клиенты нам доверяют. Наш каталог включает в себя более тысячи названий книг и брошюр нашего и целого ряда московских издательств. Помимо методической литературы (в т. ч. на компакт- дисках) для учителей и учебных пособий для школьников всех классов и абитуриентов, есть также пособия для малышей, студентов, родителей. Ниже мы помещаем содержание нашего информационного проспекта (каталога) и отдельные темы из него. Серия «Весь школьный курс в вопросах и ответах» Серия «Тренажеры. Тесты. Самоучители» Серия «Готовимся к Единому Государственному Экзамену» Пособия по всем предметам для уч-ся 5-11 кл. и поступающих в вузы Серия «Дошкольник» Пособия для начальной школы Серия «В помощь администрации школы» Серия «Воспитание в школе» Серия «Новое в преподавании в школе» Серия «Профильное образование» Серия «Общешкольные мероприятия» Серия» Внеклассная работа в школе» Серия «В помощь воспитателям и вожатым» Серия «Летний отдых» Пособия для преподавателей 1-11 кл. Пособия для студентов вузов Серия «Сам себе репетитор» Серия «Как поступить в вуз» Решение задач и выполнение заданий из школьных учебников Медицина: серия «Если ты заболел» Тема «Школа развития памяти и воображения» Серия «Домашние хлопоты» Тема «Родители и^ети» Тема «Мир занятии и увлечений» Цена пособий указана без почтовых расходов. Почтовые расходы составляют от 34 до 45% от суммы заказа. Цена в связи с инфляцией может меняться. НОВИНКИ В ПОМОЩЬ АДМИНИСТРАЦИИ школы 12016. Справочник заместителя директора по начальной школе. 156 с. Цена 49 р. 1215а. Справочник заместителя директора по воспитательной работе. 144 с. Цена 43 р. 1201а. Справочник заместителя директора по учебной работе. 186 с. Цена 48 р. 50 к. 1111а. Патриотическое воспитание (система работы, планирование, разработки занятий) (для организаторов и классных руководителей). 170 с. Цена 46 р. Б-СД-1 к. Книга «Управление школой: документация и отчетность» (содержит те же разделы, что и компьютерный вариант, но в сокращённом виде). Цена 54 р. б/ск. 1215в. Система работы администрации школы по профилактике наркомании (пла- нирование, комплекс административных и внеклассных мероприятии, координация действий различных структур). 159 с. Цена 48 р. 95ч. Олимпиадный марафон. 10 кл. (для завучей и учителей-предметников) (математи- ка, химия, физика, география, биология, литература, русский язык, обществознание, исто- рия, правоведение, иностранные языки). 92 с. Цена 35 р. 1268. Техника педагогического общения. Практикум для учителей и классных руководителей. 74 с. Цена 33 р. 50 к. 1250. Взаимодействие школы и семьи (педагогический всеобуч). 91 с. Цена 37 р. 50 к. 1255. Деловое совещание в школе. 75 с. Цена 35 р. 50 к. 1253. Профориентация в профильном обучении старшеклассников (учебно- методические материалы для разработки элективных курсов). 120 с. Цена 45 р. 12056. Педагогические советы. Вып. 1 (разработки, подготовка и технологические схемы). 157 с. Цена 47 р. 50 к.
1284. Пожарная безопасность в общеобразовательном учреждении (норматив- ные документы, инструкции). 153 с. Цена 45 р. 1281. Финансово-хозяйственная деятельность руководителя образовательного учреждения. 119 с. Цена 43 р. 1280. Санитарные правила и нормы в организации деятельности образователь- ных учреждений. 164 с. Цена 48 р. 50 к. 1282. Летний оздоровительный лагерь: нормативно-правовая база (планирование, программа работы, должностные инструкции, обеспечение безопасности). 197 с Цена 52 р. 50 к. КОМПАКТ-ДИСКИ ДЛЯ КОМПЬЮТЕРА Б-СД-1. Управление школой: ведение документации и нормативная база (содер- жит разделы: нормативно-правовая база ОУ, приказы, формы внешней и внутренней отчётности, справки, диагностические материалы). Цена 130 р. б/ск. Б-С-2. Управление школой. Методическая работа (нормативная база, методиче- ское обеспечение УВП, методический кабинет, образовательные технологии, диагно- стический инструментарий). Цена 140 р. б/ск. Б-С-4. Организационно-хозяйственная деятельность руководителя (создан на основе пособий 1280; 1281; 1282; 1284, а также дополнительно включены материалы из разделов: ТБ, ГО, ЧС). Цена 130 р. б/ск. Б-С-5. Коммуникативно-педагогическая деятельность в школе (создан на основе пособий 12056; 1250; 1253; 1255; 1268. Цена 130 р. б/ск. Б-С-6. Заместители директора в школе. Практика управления, справочники (учебная работа, воспитательная работа, методическая работа, начальная школа, диагностический инструментарий, создан на основе пособий 1201а, 12016, 1215а, см. с. 4, с добавлением нового материала). Цена 140 р. б/ск. Б-С-8. Профильное образование в школе: практика и теория (нормативная база, элективные курсы, проектная деятельность, из опыта работы, комплекты слайд- презентаций для проведения курсовых и семинарских занятии по профильной и предпро- фильной подготовке учащихся). Цена 140 р. б/ск. ь-С-10. Портфолио ученика. Оценка достижений школьников (программа, реко- мендации, методики, формы документации, презентации). Цена 140 р. б/ск. Программное сопровождение материалов для всех дисков оснащено системой поиска, имеются возможности для распечатки, редактирования, составления собственных документов и накопления их в архиве. Минимальные системные требования: операционная система Microsoft Windows 98 или последующие версии и устройство для чтения компакт-дисков. Если Вас интересует продукция нашего издательства, Вы можете написать нам и бесплат- но получить полный каталог (информационный проспект). Кроме того, Вы получите право на определенную скидку, поскольку уже будете считаться нашими клиентами. Если Вам что-то понравилось в вышеприведенных разделах, можно делать заказ сразу. Заказы присылайте по адресу: 400067, г. Волгоград, п/о 67, а/я 32, издательство «Учитель*. Код (8442). Тел.: 42-24-79, 42-20-63. СХЕМА ПРОЕЗДА к издательству «Учитель» в г. Волгограде (Кировский район) Рынок ГЁГ Авангард Й1 Энерготехникум Юг Ул. 64-й Армии (2-я Продольная) Север Офис Ул. Минина, Д. ь. 18.21 Т«Л.42-ЗМ1 Кинотеатр "Авангард* И Авангард Сбербанк И Церковь Ул.Кфм, д133я, кв. Тел.42’2МЗ Для оформления заказа достаточно написать только порядковые номера нуж- ных Вам пособий. Полностью и разбор- чиво указывайте свой адрес, его нужно писать дважды: в письме и на конверте. Заказ можно сделать такие по электронной почте. Для этого сообщите номера нухеых Вам пособий и свой адрес. Скидки сохраняются. E-mail: Pochta-uch@mail.ru MS-uch@visteom.ru По вопросам оптовых поставок обращаться потел.:, 42-57-92, 42-70-77, 42-11-58, 42-70-32, 42-70-43, 44-85-53, 42-70-46. E-maii: uchitel@avtlg.ru Optuch@vlink.ru Представительство в г. Москве: ул. ьасовская, д. 6. Тел./факс: 8 (495) 788-39-19. E-mail: uchttel-mosK@westmail.ru Смотрите информацию о нас на сайте: WWW.uchttel-lzd.ru