КОМПЬЮТЕРНЫЕ КУРСЫ
Основы программирования на языке С+ +
Ф и з т е х - К о л л е д ж при М Ф Т И
Учебное пособие к курсу
Основы
программирования на языке С++ Ч а с т ь I. И з д а н и е третье
Мунтян А.Ю.
М о с к в а 2005
Мунтян Александр
Юрьевич.
«Основы
программирования
на
С+ + ,
Часть
I».
У ч е б н о е п о с о б и е п о курсу. © « Ф и з т е х ш к о л а » 2 0 0 5 г . Р е д а к т о р В о р о б ь е в А . В . Н а о с н о в е 2 - г о и з д а н и я под И з о с и м о в и ч а Ильина.
В а ш е м у вниманию предлагается 3-е издание курса лекций по программированию на языке C/C++, читаемого в Физтех-Колледже. Д а н н ы й курс включает в себя два семестра. Настоящее пособие рассчитано на один семестр и посвящено изучению i
Хотя преподавание ведется на примере языка C/C++, многие рассматриваемые аспекты важны как для полноценного освоения современной компьютерной техники, так и для программирования вообще независимо от конкретного языка. И изменениями.
Оглавление
Глава 1. Введение Глава 2.Алгоритмы 10 Глава 3. Графика Глава 4. Типы данных Глава 5. Ввод и вывод Глава 6. Условные операторы Глава 7. Циклические конструкции Глава 8.Операторы Глава 9. Массивы Глава 10.Строги и указатели Глава 11.Функции Глава 12.Файлы Литература
данных цикла
while
и
do..while.
17 24 30 37 45 53 60 67 75 81 88
«
Глава
1
Введение Уважаемый
читатель!
Применение
компьютеров
во
всех
благодаря их у н и к а л ь н ы м в о з м о ж н о с т я м ,
областях
нашей
жизни
возрастает
не
только
но также в связи с н е у к л о н н ы м у м е н ь ш е н и е м
размеров Э В М и падением цен на них. Компьютеры, миллионы
которые
долларов,
25
сегодня
лет
могут
назад
быть
занимали
заменены
большие
помещения
кремниевой
и
микросхемой
стоили
размером
м е н ь ш е ногтя, с т о я щ е й , в о з м о ж н о , всего н е с к о л ь к о д о л л а р о в . И р о н и я судьбы заключается в том, что к р е м н и й является одним из наиболее р а с п р о с т р а н е н н ы х на земле м а т е р и а л о в : он
входит
в
состав
обычного
вычисления
настолько
миллионов
компьютеров
производстве,
песка.
Технология
экономичными, общего
управлении
и
что
во
всем
назначения,
личной
жизни.
За
кремниевых мире
микросхем
используется
помогающих несколько
лет
около
людям это
сделала
в
число
200
бизнесе,
легко
может
удвоиться. П о э т о м у так высока потребность в
Программы -
Программисты понятны
специалистах,
компьютерные
умеющих писать
ц е л е н а п р а в л е н н ы е наборы и н с т р у к ц и й для компьютера. используют
компьютеру,
другие
разные
требуют
языки
программирования.
предварительного
Некоторые
преобразования
в
из
них
машинный
к о д . С е г о д н я с у щ е с т в у ю т с о т н и я з ы к о в , и в с е и х у с л о в н о м о ж н о р а з д е л и т ь н а т р и группы*; 1.
Машинные языки.
2.
Языки
3.
Я з ы к и высокого уровня.
Любой
компьютер
Машинный язык при
ассемблера.
это
проектировании
содержат
строки
может
понимать
лишь
«природный язык»
элементов
чисел,
этого
которые
свой
компьютера.
являются
машинный язык.
собственный
определенного
компьютера.
Машинные
командами
языки
компьютеру
Он
определяется
в
общем
на
выполнение
б о л ь ш и н с т в а э л е м е н т а р н ы х о п е р а ц и й ( с л о ж е н и е , у м н о ж е н и е , д е л е н и е и т.д.). языки на
машинно-зависимы,
компьютере
восприятия.
К
Машинные
т.е. к а ж д ы й и з т а к и х я з ы к о в м о ж е т б ы т ь и с п о л ь з о в а н т о л ь к о
определенного примеру,
случае
вот
типа.
Машинные
программа,
которая
языки
тяжелы
складывает
для
человеческого
сверхурочную
зарплату
с
о с н о в н о й и з а п о м и н а е т результат к а к общую зарплату: +1300042774 +1400593419 +1200274027 Со слишком
временем
стало
очевидно,
м е д л е н н о и утомительно для
программисты
начали
элементарных операций. преобразования специальные ассемблера
использовать
также
программирование
английские
на -
языке
ассемблера
ассемблеры.
складывает
на
аббревиатуры
Эти с о к р а щ е н и я с ф о р м и р о в а л и о с н о в у
программ
программы
что
большинства программистов.
сверхурочную
в
зарплату
код
фрагмент
(overpay)
з а п о м и н а е т результат к а к о б щ у ю зарплату (grosspay), но он
для
языкгбс
строк чисел
представления
языков ассемблера.
машинный
Следующий
машинных Вместо
с
были
Для
разработаны
программы основной
более п о н я т е н по
на
языке
(basepay)
и
сравнению
со своим м а ш и н н ы м аналогом: LOAD ADD
basepay overpay
S T O R E grosspay Х о т я т а к о й к о д б о л е е п о н я т е н л ю д я м , о н н е п о н я т е н к о м п ь ю т е р у д о тех п о р , п о к а н е будет п р е о б р а з о в а н в м а ш и н н ы й к о д .
Использование компьютеров резко возросло п р о г р а м м ы н а этих я з ы к а х все еще требовали задач.
Для
ускорения
процесса
с появлением я з ы к о в ассемблера,
много
программирования
в к о т о р ы х и н о г д а д о с т а т о ч н о н а п и с а т ь всего
уровня,
задачи.
Программы,
м а ш и н н ы й код,
которые
называются
языке высокого уровня,
преобразуют
были
один
разработаны
языки
высокого
оператор для р е ш е н и я реальной
инструкции
на
языках
высокого
П р о г р а м м а расчета зарплаты,
компиляторами.
но
команд для р е ш е н и я даже простых
уровня
написанная
в на
может уложиться в одну строчку:
grosspay = basepay + overtimepay Я з ы к и высокого уровня гораздо удобнее для программистов, и
машинный
применение.
код.
Но,
С++
-
несмотря
один
из
на
это,
наиболее
лишь
мощных
немногие и
из
наиболее
чем я з ы к и ассемблера
них
получили
широкое
распространенных языков
в ы с о к о г о у р о в н я , это я з ы к , н а к о т о р о м н а п и с а н о б о л ь ш и н с т в о с а м ы х п о п у л я р н ы х п а к е т о в п р о г р а м м . И н е о с т а е т с я с о м н е н и й в т о м , что С + +
останется самым популярным я з ы к о м
программирования. П о ч е м у же
С++?
П р о г р а м м ы н а С + + легко п е р е н о с и т ь и з о д н о й п р о г р а м м н о - а п п а р а т н о й с р е д ы в другую.
Это
значит,
что
если
при
написании
программы
не используются
библиотеки,
зависящие от конкретного компилятора, или операции, э ф ф е к т и в н о с т ь которых зависит во многом
от
особенностей
твоего
компьютера,
то
твоя
программа
будет
везде
работать
одинаково правильно. Функциональная свои
добавления
в
язык,
р а з н о о б р а з н ы х задач. содержит
расширяемость. что
Программист
значительно
С + + рассчитан на
имеет
возможность
расширяет возможности
расширение
по
своему
при
вносить
решении
замыслу,
самых
поскольку
небольшое число операторов. Самое важное в программах на С + + заключено в
функциях,
а язык
сам
по
себе
не
имеет других внутренних
функций,
кроме
основной
ф у н к ц и и (функции main) Программистам кодируются
особенно
алгоритмы.
краткость
нравится
Большинство
операторов
выражений,
языка
которыми
возвращают
в
С++
некоторые
з н а ч е н и я , что п о з в о л я е т п р е д с т а в л я т ь в ы р а ж е н и я в к р а т к о й ф о р м е . С + + обеспечивает
эффективного
формирование
машинного
кода п р о г р а м м ы ,
ч т о д о с т и г а е т с я его п р и в я з к о й к о с о б е н н о с т я м а р х и т е к т у р ы Э В М . Краткая
и с т о р и я языка С+ +
Язык компании С
С
был
создан
в
начале
70-х
годов Д э н н и с о м
Ритчи,
был
разработан
как
язык
для
программирования
в
операционной системе Unix.
ОС Unix была н а п и с а н а на я з ы к е
7
PDP-11.
и
перенесена
предшественник, является
который
работал в
Bell T e l e p h o n e L a b o r a t o r i e s .
затем
на
язык В, созданный
последователем
Ричардсом
в
языка
рамках
На
BCPL.
проекта
С
оказал
Томпсоном,
Язык
BCPL
был
Вскоре Unix
по
тем
значительное который,
"Комбинированный
Кембриджском университете в Лондоне. 1974 - 7 5
язык
Кэном
новой
временам
ассемблера для Э В М PDPr-
создан
в
язык
в 1969
влияние свою г.
его
очередь,
Мартином в
программирования"
б ы л а п е р е п и с а н а на я з ы к е С + + , и в
г о д а х О С U n i x ф и р м ы Bell L a b o r a t o r i e s стала п е р в ы м к о м м е р ч е с к и м п р о д у к т о м ,
р е а л и з у ю щ и м идею о том, что о п е р а ц и о н н а я система может быть у с п е ш н о н а п и с а н а языке высокого уровня, В
1978
программирования "K&R" "K&R"
- в
г. С".
если этот я з ы к я в л я е т с я д о с т а т о ч н о м о щ н ы м и г и б к и м .
Брайан Эта
Керниган
работа,
остальном мире,
которая
и в
Дэннис своем
стала с т а н д а р т о м
существовали к о м п и л я т о р ы языка
6000 и I B M 370.
на
С
кругу
Ритчи
написали
называлась
о п и с а н и я я з ы к а С.
для Э В М P D P - 1 1 ,
В д а л ь н е й ш е м этот с п и с о к был п р о д о л ж е н .
книгу
"белой
"Язык
книгой"
и
На момент создания
I n t e r d a t a 8/32,
Honeywell
В 8080 и
к о н ц е 70-х
и Z80
с
пустили
в
начали
появляться трансляторы С для м и к р о Э В М
операционной продажу
системой С Р / М . Скотт Газери и Д ж и м
Tiny-C
("Крошечный
С")
-
на процессорах
Гибсон
интерпретатор,
разработали
основанный
на
п о д м н о ж е с т в е я з ы к а . Е г о и н т е р а к т и в н а я с р е д а п р о г р а м м и р о в а н и я о ч е н ь п о х о ж а н а ту, ч т о имеет чрезвычайно создал
свой
компилятор
Компилятор Small-C.
популярный
Small-C,
Проблема
т р а н с л я т о р Basic
Small-C
("Малый
основанный курицы
на
фирмы
С") д л я
ОС
Microsoft.
СР/М
Затем
используя ранние
другими,
Кэйн
был н а п и с а н на самом
самого
когда К э й н вместе с
Рон
когда К э й н создал первую версий)
компилятора на основе интерпретатора Tiny-C. себя,
1980г.
и м и к р о п р о ц е с с о р а 8080.
подмножестве языка С,
и я й ц а была решена,
В
Small-C методом раскрутки создал версии компилятора,
сделал более с о в е р ш е н н ы й к о м п и л я т о р .
Small-C компилирует и с х о д н ы й модуль на
языке
С++
процессора
Кэйн
в
модуль
на языке
п р е д о с т а в и л свой
ассемблера
8080.
Следует
отметить,
что
к о м п и л я т о р и его и с х о д н ы й т е к с т в о б щ е с т в е н н у ю с о б с т в е н н о с т ь .
Примерно
в
это
же
время Лео
Золман
представил
С Р / М , также основанный на подмножестве языка С.
свой к о м п и л я т о р
Д о с т о и н с т в а м и этого
BDS-C
для
компилятора
были высокая скорость и возможность совместной компоновки перемещаемых объектных модулей
в
загрузочном
модуле.
Вскоре после B D S - C основанные
на
были
полном
созданы компиляторы,
множестве
языка
п р о г р а м м и р о в а н и я на С + + для м и к р о Э В М . мире
микро ЭВМ
IBM PC
компиляторы
к о м п и л я т о р о в для В
настоящее
С.
1981
Это
г.,
дало
импульс
в связи с созданием
СР/М
и
развитию IBM
PC,
в
был сделан з н а ч и т е л ь н ы й скачок вперед.
После появления Некоторые
В
п р е д н а з н а ч е н н ы е для
были
стали
появляться
получены
п р о ц е с с о р а 8080, д р у г и е
время
путем
были
на р ы н к е п р е д с т а в л е н ы
и
компиляторы
С для
преобразования
ПЭВМ.
соответствующих
разработаны специально
б о л е е двух д е с я т к о в
этой для
компиляторов
IBM
PC.
языка
С
для IBM P C . В
1983
г.
К о м и т е т X3J11
Американский
для
создания
не только на я з ы к ,
но и
стандартных функций.
Институт
Стандартов
стандарта языка С.
на
программную
(ANSI)
сформировал Технический
Стандартизация
будет р а с п р о с т р а н я т ь с я
среду к о м п и л я т о р а ,
а также на библиотеку
В работе комитета участвуют
представители
основных
фирм
-
п о с т а в щ и к о в к о м п и л я т о р о в С, в том числе и для I B M P C , а также м н о г и е другие светила из
мира программирования
на языке
С.
Усилия
средств массовой и н ф о р м а ц и и . Предлагаемый все з а и н т е р е с о в а н н ы е с т о р о н ы могли Поскольку комитета этого
большинство
ХЗ Л 1 ,
стандарта,
то
поставщиков
разрабатываемые
(компилятор
Borland
комитета X3J11
ознакомиться
с ним и внести
компиляторов ими С
новые 3.1
привлекли
внимание
стандарт был опубликован для того, чтобы
для
для
версии IBM
IBM
PC
свои
компиляторов PC
предложения.
участвуют будут
подчиняется
в
работе
в
рамках
большинству
т р е б о в а н и й стандарта на я з ы к и библиотеку). Язык подчиняясь решении
С++
является
стандарту ANSI
объектно-ориентированным С,
расширением
дает р а з р а б о т ч и к у к а ч е с т в е н н о
самых р а з н о о б р а з н ы х задач.
новые
языка
С
возможности
ж, при
Работа
в
Borland
С+ +
3.1
И н т е г р и р о в а н н а я с р е д а B o r l a n d С + + 3.1
п р е д с т а в л я е т с о б о й т е к с т о в о й р е д а к т о р со
в с т р о е н н ы м к о м п и л я т о р о м . В в е р х н е й ч а с т и э к р а н а р а с п о л а г а е т с я м е н ю . В м е н ю F i l e есть следующие
опции:
•
New - создание нового файла;
•
Load - загрузка р а н е е с о х р а н е н н о г о ф а й л а ;
•
Save - с о х р а н е н и е т е к у щ е г о
•
Save as - с о х р а н и т ь п о д н о в ы м и м е н е м ;
•
Quit - в ы х о д .
файла;
З д е с ь и д а л е е п е р е ч и с л я ю т с я н е в с е о п ц и и , а т о л ь к о те, к о т о р ы е б ы в а ю т о с о б е н н о полезны
начинающим
показанное
на
программистам.
рисунке.
У
окна
При
есть
выборе
некоторые
пункта New атрибуты.
А
создается
новое
именно:
имя
окно, файла,
о б р а б а т ы в а е м о г о в о к н е (для н о в о г о ф а й л а будет н а п и с а н о N O N A M E 0 0 . C P P ) , п о р я д к о в ы й номер
окна
(окно
можно
выбрать,
нажав
к л а в и ш у Alt
+
этот
номер),
местоположение
курсора (номер строки и столбца). Также имеются вертикальная и горизонтальная полоса прокрутки.
В
левом
н а ж а в Alt + F 3 ) . одно
из
в е р х н е м углу - м а р к е р
О д н о в р е м е н н о на
них может быть а к т и в н ы м .
закрытия
окна (окно также можно
закрыть,
э к р а н е могут н а х о д и т ь с я н е с к о л ь к о о к о н , но т о л ь к о Оно
обрамляется двойной рамочкой,
а неактивные
о к н а - о д и н а р н о й . П е р е к л ю ч е н и е между о к н а м и п р о и с х о д и т п р и н а ж а т и и F6. С п о м о щ ь ю м а н и п у л я т о р а м ы ш ь м о ж н о и з м е н я т ь р а з м е р ы о к н а ( в з я в ш и с ь з а п р а в ы й н и ж н и й угол) и п е р е м е щ а т ь о к н о по э к р а н у ( в з я в ш и с ь за д в о й н у ю р а м о ч к у ) , р а з в о р а ч и в а т ь на весь э к р а н ( п р а в ы й в е р х н и й м а р к е р и л и к л а в и ш а F5) и в о с с т а н а в л и в а т ь д о п е р в о н а ч а л ь н о г о р а з м е р а в повторным нажатием на маркер. М а р к е р закрытия окна
I
И м я файла в окне
Для активного окна д в о й н ы е л и н и и , для неактивного - оди¬ нарные
Т е к у щ и й номер строки и столбца
Номер окна
Изменение размера о к н а
П е р е м е щ е н и е текста вверх
Маркер м е с т о п о л о ж е н и я текста в окне
Поле, соответствующее общему вертикальному размеру текста в о к н е
Маркер местоположения фрагмента текста в окне П е р е м е щ е н и е текста вниз 1:1:
Если файл модифици¬ рован, то здесь будет располагаться звездочка
П е р е м е щ е н и е текста влево
Поле, соответствующее общему горизонтально¬ му размеру текста в о к н е
Перемещение текста вправо
Для
запуска
программы
компилятора
достаточно
нажать
(если Ctrl
удачно
прошли
F9.
Появится
+
предыдущие действия) окно,
и
отображающее
само
процес
к о м п и л я ц и и . Е с л и о ш и б о к н е т , т о с р а з у ж е будет з а п у щ е н а п р о г р а м м а . Е с л и е с т ь о ш и б ю
то в н и ж н е й части э к р а н а п о я в и т с я еще одно о к н о с п е р е ч и с л е н и е м всех в с т р е т и в ш и х с я о ш и б о к и у к а з а н и е :
Загрузить (рекомендуется
новый это
файл
делать
с о х р а н е н и и Borland С + +
можно,
нажав
периодически)
3.1
клавишу
F3.
используется
Для
клавиша
сохранения F2.
При
файл, перво
А
п о п р о с и т в а с у к а з а т ь и м я ф а й л а и м е с т о , куда вы х о т и т е ег<
сохранить. Встроенный текстовый редактор позволяет работать с блоками и н ф о р м а ц и и . Чтобь задать
блок,
нужно,
удерживая клавишу
Shift
с
помощью
клавиш
управления
курсором
выделить н у ж н ы й текст. Далее, с блоком м о ж н о делать следующие в е щ и (см. также м е н к Edit): К о п и р о в а т ь в буфер обмена
(Ctrl + I n s ) ;
В с т а в и т ь из б у ф е р а (Shift + I n s ) ; Вставить в ы д е л е н н ы й блок текста(СШ + К + С ) ; У д а л и т ь и з т е к с т а п р о г р а м м ы (Ctrl + D e l ) . Чтобы получить описание функции, необходимо подвести
к этой ф у н к ц и и курсор
и н а ж а т ь с о ч е т а н и е к л а в и ш Ctrl + F 1 . Ч т о б ы удалить действиях
(случайно
целую
строчку,
что-то
было
необходимо
удалено)
нажать
можно
Ctrl
отменить
+
Y.
При
последние
неправильных изменения
п о м о щ ь ю к о м б и н а ц и и Alt + B a c k s p a c e . Д л я п о в т о р е н и я о т м е н е н н ы х д е й с т в и й : +
с
Shift + Alt
Backspace.
Первая программа З а д а ч а п р о г р а м м ы - в ы в е с т и на э к р а н с т р о ч к у « H e l l o w o r l d !!! Запустите
интегрированную
следующий
среду
Borland
С++
3.1,
».
создайте
новый
файл
и
наберите
текст:
Текст п р о г р а м м ы на С + +
/*
Моя
#
include
void
первая
программка
*/
<stdio.h>
main()
printf("Hello
//начало
world
!
\n") ;
//конец
О т к о м п и л и р у й т е ее и запустите. На экране появится надпись "Hello world!", но как т о л ь к о п р о г р а м м а будет в ы п о л н е н а д о п о с л е д н е й с т р о ч к и , н а э к р а н е в н о в ь п о я в и т с я о к н о
Borland
С + +.
Чтобы
увидеть
результат
выполнения
программы,
необходимо
нажать
сочетание клавиш AU+F5. Рассмотрим Первая комментарий.
программу построчно.
строчка
заключена
Комментарии
в
никак
скобочки
не
вида
влияют
на
/*
*/.
работу
Это
программы
так
называемый
и
используются
т о л ь к о д л я п о я с н е н и я и с х о д н о г о кода. В д а н н о м случае в к о м м е н т а р и и з а п и с а н о н а з в а н и е программы.
Существует еще одна ф о р м а записи к о м м е н т а р и е в .
Если в тексте программы
в с т р е ч а ю т с я п о д р я д д в а с и м в о л а //, т о в с е , ч т о р а с п о л а г а е т с я д о к о н ц а с т р о ч к и ,
считается
к о м м е н т а р и е м . В н а ш е й п р о г р а м м е слова «начало» и «конец» я в л я ю т с я к о м м е н т а р и я м и , <и компилятор не принимает их во внимание. Следующая английского
строчка
языка
будет в ы д е л е н а
значит
зеленым
«подключить».
В
цветом.
программе
Слово будет
include
в
переводе
использована
с
функция
printf(), о п и с а н и е к о т о р о й н а х о д и т с я в ф а й л е stdio.h - с т а н д а р т н о й б и б л и о т е к е ф у н к ц и й . Программы на С + + выполнять
элементарные
содержат элементы, операции
при
называемые функциями.
работе
программы.
Они
Очистить
призваны
экран,
вывести
с т р о к у , н а р и с о в а т ь н а э к р а н е круг и м н о г о е д р у г о е - все э т о д е л а ю т ф у н к ц и и . П о л ь з у я с ь набором операторов С + + , программистов стандартных
на
С++
функций.
Вы можете сами создавать такие ф у н к ц и и , но большая часть
пользуется
уже
вправду,
зачем
И
заранее
созданными
тратить
время
функциями
из
на р е ш е н и е задач,
р е ш е н ы р а н ь ш е ? Д л я того ч т о б ы и м е т ь в о з м о ж н о с т ь и с п о л ь з о в а т ь
эти
библиотек
к о т о р ы е уже
ф у н к ц и и в своих
программах, необходимо сообщить компилятору, в каком файле-библиотеке они описаны. Если
нужно
которой
содержатся
степень,
извлечение
написать
подключить основные
другие
библиотеки,
тригонометрические
арифметического
квадратного
например,
функции, корня
и
математическую,
операции т.д.,
то
возведения
в в
нам
необходимо
описана стандартная математическая
библиотека.
следующее:
#include
<math.h>
math.h - имя
файла,
Стандартных библиотек в
в котором
C/C++
очень много.
М ы будем
знакомиться
с н и м и по мере
изучения новых функций. Д а л е е идет с л е д у ю щ а я void
конструкция:
main()
{ }
Это ф у н к ц и я main(), которая присутствует в л ю б о й программе на C / C + + , и и м е н н о с нее начинается в ы п о л н е н и е п р о г р а м м ы . Тело ф у н к ц и и main() о г р а н и ч е н н о фигурными скобками.
Внутри
функция
вывода
является
наличие
параметры.
них на
записываются
экран
круглых
-
скобок.
Здесь мы передаем В
выводится
на
новую
строке, экран
которая
-"\п".
printf().
Внутри
них
строку текста.
кавычки и может содержать внутри алфавита).
операторы
функция
программы.
передается
записываются
функции
с т р о к у , п о с л е т о г о к а к будет н а п е ч а т а н о
нашем
случае
записана
всех
функций
передаваемые
функции
чертой
Строка должна быть заключена в д в о й н ы е
себя л ю б ы е с и м в о л ы
Это у п р а в л я ю щ и й
В
Отличительной
символ.
(в том ч и с л е и буквы русского
printf(), Его
есть
цель
-
символ,
который
перенести
курсор
не на
«Hello w o r l d ! » .
О б р а т и т е в н и м а н и е , ч т о после функции ставится точка с запятой.
ь
Гпава
2
Алгоритмы . . . в ы й т и в 7.30. Д о й т и до о с т а н о в к и т р а м в а я - на э т о у й д е т 2 м и н у т ы , д а л ь ш е т трамвае под номером 15минут, и, команд
26
направлена
надо
проехать до
остановки
45 минут на метро до
наконец,
на
достижение
одной
«Станция
станции общей
метро
«Динамо».
цели
-
Шаболовская»
-
Эта последовательность
добраться
до
места
работь
в о в р е м я . Г о в о р я и н а ч е , э т о алгоритм, ц е л ь к о т о р о г о - б ы т ь в п у н к т е н а з н а ч е н и я к 9 ч а с а м . Алгоритм либо
цели.
это п о с л е д о в а т е л ь н о с т ь
Можно
сказать,
что
это
событий строго
(команд, действий),
определенная
ведущих к какой-
процедура,
гарантирующая
п о л у ч е н и е результата за к о н е ч н о е ч и с л о ш а г о в , с о д е р ж а щ а я в себе д е й с т в и я , в результате каждого
из которых мы
становимся
еще
ближе
к решению
ц е п о ч к а д е й с т в и й н а з ы в а е т с я алгоритмическим п р о ц е с с о м ,
главной
задачи.
Указанная
а каждое отдельное действие
- его шагом. Рассмотрим
порядок действий,
которые нужно выполнить,
чтобы посчитать
объем
параллелепипеда. Шаг
1.
Узнать значения сторон
основания
(а,Ь) и в ы с о т ы ( п ) . Шаг
2.
Вычислить
площадь
основания
по
формуле S = а * Ь . Шаг
Вычислить
3.
объем
по
формуле
V=S*h.
Любой
алгоритм должен Определенным
1.
содержать
в
и
быть: однозначным.
себе
Это
элементов,
значит,
которые
в ы п о л н я т ь эту п о с л е д о в а т е л ь н о с т ь к о м а н д . была
выбрана
последнего алгоритм,
заглавная
шага).
К
буква
S,
тексту
предъявляются
еще
то
буквы,
каждой
не
того,
должен
кто
обозначения
будет
площади
так площадь должна обозначаться
компьютерной более
алгоритм
запутать
(Если для
программы,
жесткие требования:
должно быть ни одного лишнего символа. каждой
что
могут
поставленной
до
описывающей в
программе
не
Н е о б х о д и м о понимать значение запятой,
чтобы
программа
выполнялась без ошибок. Результативным и выполнимым. С о с т а в л я я
2.
нужно стоит
всегда п о м н и т ь о к о н е ч н о й цели пытаться узнать
цвет
сторон
последовательность действий,
и не делать л и ш н и х о п е р а ц и й .
параллелепипеда,
если
нужно
его о б ъ е м . Массовым
3.
Не
посчитать *
или у н и в е р с а л ь н ы м .
параллелепипеда,
выполнив
Это значит, каждый
что
независимо
шаг алгоритма,
мы
от р а з м е р о в
точно
узнаем
его
объем. Записывать алгоритмы можно по-разному: •
в
•
в виде программ;
•
в
виде виде
блок-схем; текстовых
лекарств и др.).
описаний
(например,
рецепты
приготовления
пищи,
Блок-схема
алгоритма
последовательности
-
это
графическое
описание
алгоритма
как
действий.
Р а с с м о т р и м элементы, из которых состоит блок-схема, на следующем п р и м е р е . Пример 2 . 1 .
Составьте и запишите алгоритм нахождения площади прямоугольника.
П л о щ а д ь п р я м о у г о л ь н и к а н а х о д и т с я по ф о р м у л е : S = а • Ь. Д л я ее в ы ч и с л е н и я н а м н у ж н о ввести
з н а ч е н и я сторон п р я м о у г о л ь н и к а - а и Ь. Далее надо подсчитать площадь Б и в
к о н ц е вывести результат на э к р а н .
Алгоритм в виде блок-схем записывается следующим
образом:
Блок-схема состоит из следующих элементов: Для понятно,
того
чтобы
откуда он
специальный
человеку,
который
начинается,
в
элемент блок-схемы,
будет
разбираться
графическом который
способе
в
вашем
записи
алгоритме,
алгоритма
символизирует начало
было
существует
алгоритма.
Это
овал,
в н у т р и к о т о р о г о н а п и с а н о " Н а ч а л о " . Э л е м е н т " н а ч а л о " и м е е т о д и н в ы х о д (т.е. в ы х о д я щ у ю стрелку),
и
ни
одного
входа
(т.е.
входящей
в о з г л а в л я е т б л о к схему, т . е . п е р е д н и м
стрелки),
н и ч е г о нет,
это
говорит
о
том,
что
а п о с л е него следует а л г о р и т м .
он Этот
блок используется в каждом алгоритме.
Начало
Любой расчеты.
Для
параллелограмма
алгоритм ввода с
требует
значений
перечислением
входные с
алгоритма.
данные,
клавиатуры вводимых
с
помощью
предусмотрен
переменных
внутри
Б л о к ввода и н ф о р м а ц и и .
которых
элемент него.
и
производятся
блок-схемы
в
виде
В
обычно
прямоугольнике
записывают
арифметические
выражения,
формулы
к а к и е - л и б о д е й с т в и я , к о т о р ы е нужно в ы п о л н и т ь для п о л у ч е н и я требуемого результата.
Блок обработки и н ф о р м а ц и и . Внутри блока записываются формулы, знаки операций и функций.
Целью результат
любого
алгоритма
необходимо
является
получение
какого-либо
результата.
И
этот
вывести на экран. Для вывода значений переменных используете;
следующая блок-схема. Внутри нее записываются в ы в о д и м ы е з н а ч е н и я .
»
Блок вывода и н ф о р м а ц и и .
В к о н ц е алгоритма обычно ставится элемент блок-схемы " К о н е ц " .
К нему подходит
л и ш ь одна стрелочка и не выходит ни о д н о й .
К о н е ц алгоритма.
Это
пример
отдельные
исходных данных В
любом
выполнения
алгоритма.
линейного
операторы и
выполняются промежуточных
алгоритме
операций.
Линейным
в
называется
естественном
порядке
алгоритм, независимо
в от
котором значений
результатов.
очень
важно
Рассмотрим
правильно
«алгоритм
определить
утреннего
последовательность
пробуждения»,
который
в ы п о л н я е т м о л о д о й человек, вставая утром и собираясь в ш к о л у : (1) встать с постели, (2) п р и н я т ь душ, (3) одеться, (4) позавтракать, (5) выйти из дома.
В ы п о л н е н и е этого п л а н а
п о з в о л и т ему х о р о ш о п о д г о т о в и т ь с я к учебному д н ю . Давайте
предположим,
что
те
же
шаги
выполняются
в
несколько
иной
п о с л е д о в а т е л ь н о с т и : ( 1 ) встать с постели, ( 2 ) одеться, ( 3 ) п р и н я т ь душ, ( 4 ) позавтракать, (5)
выйти
мокрым.
из
дома.
Только
В
этом
правильная
случае
наш
молодой
последовательность
человек
отправится
действий
позволит
в
школу
получить
слегка верный
результат. Давайте
теперь
рассмотрим
пример
алгоритма
с
ветвлениями.
Алгоритм
с
в е т в л е н и я м и предусматривает в ы п о л н е н и е одного из заранее заготовленных операторов «в з а в и с и м о с т и от результата п р о в е р к и некоторого условия. Пример
2.2.
Запишите
запрашивает два числа и вывести на экран.
в
виде
блок-схемы
определяет, какое из
алгоритм
этих чисел б о л ь ш е .
программы,
которая
Результат необходимо
Алгоритм
начинается
с
блока
"Начало".
Далее,
спускаясь
вниз
по
стрелочке,
мы
в с т р е ч а е м б л о к в в о д а з н а ч е н и й А и В. З д е с ь п р е д п о л а г а е т с я , ч т о мы з а д а е м з н а ч е н и я
А и
В с к л а в и а т у р ы . П о с л е их в в о д а и д е т б л о к у с л о в и я . Блок условного элемента
является
достижении
блока
оператора изображается то,
что
ветвления
к
нему
с
подходит
алгоритм
дальше
помощью одна может
ромбика.
стрелочка, пойти
Особенностью а
по
выходят
одной
две.
и з двух
этого При
веток
в
з а в и с и м о с т и от того, верно ли з а п и с а н н о е условие внутри р о м б и к а на д а н н ы й м о м е н т или нет. Если в е р н о , то двигаемся по стрелочке с н а д п и с ь ю "Да", если нет, то по стрелочке с надписью
"Нет".
Алгоритмы,
содержащие
блоки
условия,
называются
алгоритмами
с
ветвлениями.
Блок условия.
Внутри блока записываются условия
направления действия алгоритма.
Е с л и А > В ( у с л о в и е в е р н о ) , то мы и д е м по в е т о ч к е " Д а " н а л е в о и в п е р е м е н н у ю М а х записываем
значение
переменную
М а х будет з а п и с а н о
А
(т.к.
А
-
наибольшее),
иначе
идем
по
веточке
"Нет",
и
в
В . Д а л е е и д е т о б щ и й б л о к в ы в о д а м а к с и м а л ь н о г о nncjfa
на э к р а н . И в к о н ц е алгоритма ставится блок " К о н е ц " . К а к видите, ничего с л о ж н о г о нет. Алгоритмы применяются
не только
в программировании,
м н о г и е я в л е н и я н а ш е й ж и з н и могут быть о п и с а н ы а л г о р и т м а м и . правильного
алгоритма,
учитывающего
различные
условия,
и
если
приглядеться,
Более того, может
то
составление
помочь
принять
наилучшее решение в сложившейся ситуации. Пример 2.3. через горы.
Вы о т п р а в и л и с ь
с группой туристов в поход.
На этот у ч а с т о к пути о т в е д е н о 3 часа.
Часть маршрута проходит
По о к о н ч а н и и этого о т р е з к а вас ждет
п е р е п р а в а через реку, а за ней лагерь. П а р о м на п е р е п р а в е ходит т о л ь к о о д и н раз в д е н ь , \ е с л и г р у п п а н е у с п е е т п р о й т и эту ч а с т ь п у т и , т о п р и д е т с я з а н о ч е в а т ь н а б е р е г у р е к и , чегс н и к т о из членов группы не желает. Во в р е м я пути один из н о в и ч к о в упал и серьёзно п о р а н и л с я . К а к поступить?
Блок-схема
позволяет
наглядно
представить
все
возможные
варианты
развития
с о б ы т и й и в ы б р а т ь о п т и м а л ь н о е р е ш е н и е задачи. В н а ш е м п р и м е р е в п о л н е о ч е в и д н о , что комфортному
ночлегу
противопоставлена
жизнь
друга,
и
ни
один
здравомыслящий
ч е л о в е к н е о с т а в и т его у м и р а т ь . Между тем приведенные меняющихся
задачи,
примеры,
которые и
для
ставит
того
ж и з н е н н ы х ситуациях,
реальность,
чтобы
хорошо
чаще
всего
намного
ориентироваться
н е о б х о д и м о уметь п р а в и л ь н о
в
тяжелее,
сложных,
чем
быстро
составлять алгоритмы
действий. Пример
2.4.
Составьте
блок-схему
алгоритма,
у р а в н е н и я . Л и н е й н о е у р а в н е н и е и м е е т в и д ах + b = О
вычисляющего
корни
линейного
Задачи к главе 2 . А л г о р и т м ы Задача программу,
2.1.
Составьте
которая
стоимость
поездки
блок-схему
выводит на
дачу
и
в
виде
и,
используя
текстового
обратно,
если
функцию
описания
известно
printf(),
алгоритм,
расстояние
до
напишите
вычисляющий дачи(Ь),
расход
б е н з и н а н а 100 к м п у т и ( К ) и ц е н а о д н о г о л и т р а б е н з и н ( р ) . Задача 2.2. В п е р в о м с о с у д е н а х о д и т с я в о д а , во в т о р о м - с п и р т . схему
и,
используя
функцию
printf,
напишите
программу,
Составьте
которая
выводит
блокв
виде
т е к с т о в о г о о п и с а н и я алгоритм, цель которого - п о м е н я т ь местами с о д е р ж и м о е сосудов. Задача используя
2.3.
Заданы
функцию
три
printf,
стороны
напишите
треугольника программу,
а,
b,
с.
которая
Составьте
выводит
в
блок-схему
виде
и,
текстового
о п и с а н и я а л г о р и т м , о п р е д е л я ю щ и й , я в л я е т с я л и этот т р е у г о л ь н и к р а в н о б е д р е н н ы м . Задача напишите
2.4.
Дано
программу,
число
а.
которая
Составьте выводит
блок-схему в
виде
и,
используя
текстового
функцию
описания
printf,
алгоритм,
о п р е д е л я ю щ и й , я в л я е т с я ли это ч и с л о ч е т н ы м . Задача используя
2.5.
Дана
функцию
последовательность
printf,
напишите
из
4
программу,
чисел.
которая
Составьте выводит
в
блок-схему
и,
виде
текстового
printf,
напишите
о п и с а н и я алгоритм, находящий н а и м е н ь ш е е из них. Задача
2.6.
Составьте
блок-схему
и,
используя
функцию
программу, которая выводит в виде текстового о п и с а н и я алгоритм, в ы ч и с л я ю щ и й корни квадратного Задача используя
уравнения. 2.7.
И м е ю т с я два сосуда о б ъ е м о м
функцию
printf,
напишите
3
программу,
и
5
литров.
которая
Составьте
выводит
в
б л о к - с х е м у и,
виде
текстового
о п и с а н и я алгоритм, цель которого - з а п о л н и т ь б о л ь ш и й из них 4 литрами воды, используя только
эти два сосуда.
Гпава3 Графика Л ю б а я к о м п ь ю т е р н а я п р о г р а м м а - это п о с л е д о в а т е л ь н о с т ь к о м а н д , выполнить позволит
компьютер, получить
иначе
точный
говоря
результат
п р о г р а м м и с т - это ч е л о в е к ,
алгоритм.
в
любых
И
только
условиях.
которые должен
правильный
Именно
алгоритм
поэтому
хороший
с п о с о б н ы й быстро и п р а в и л ь н о р е ш и т ь даже самую сложную
задачу. П р о г р а м м и с т - э т о с п е ц и а л и с т , у м е ю щ и й с о с т а в л я т ь а л г о р и т м ы , а
совсем не тот,
кто знает н а и з у с т ь все о п е р а т о р ы я з ы к а п р о г р а м м и р о в а н и я . С о с т а в л я я п р о г р а м м у , следует п о м н и т ь о том, что каждая строчка, к а ж д ы й её с и м в о л и м е ю т свое место и играют важную роль.
Графика Для
организации
универсальных
графических
программной
и
каталоге
и
BGI
Interface).
графики
Имя
драйверов
аппаратной
частей
имеют такое файла
фирма
BORLAND
программ,
-
компьютера.
же р а с ш и р е н и е ,
обычно
отображает,
выпустила
обеспечивающих
Графические
а именно
для
ряд
работы
*.bgi с
взаимодействие
драйвера
(BGI
каким
-
довольно
находятся
Borland
именно
в
Graphics
графическим
р е ж и м о м о н п р е д н а з н а ч е н . В н а ш е м с л у ч а е э т о ф а й л egavga.bgi. Д а л е е м ы у в и д и м , к а к его п о д к л ю ч и т ь в п р о г р а м м е . Т а к ж е н е о б х о д и м о в м е н ю O p t i o n s - > Linker - >
Libraries...
п о с т а в и т ь к р е с т и к в с т р о ч к е G r a p h i c s library. Видеорежимом видеокарты
называется
(видеоадаптера).
В
набор
параметров,
отличие
от текстового
поддерживаемый режима в
аппаратурой
видеорежиме возможен
вывод не только текстовой, но и графической и н ф о р м а ц и и . Изображение формируется из точек,
так
называемых
пикселей
я в л я е т с я разрешение экрана. 640
пикселей
по
(pixel).
Например,
горизонтали
и
480
Самым
640x480. пикселей
известным
атрибутом
видеорежима
Это означает, что на э к р а н е в ы в о д и т с я по
вертикали.
Встречаются
и
другие
р а з р е ш е н и я : 320x200, 640x480, 800x600, 1024x768 и т. д. Начало
системы
координат
(т.е.
точка
с
координатами
(0,0))
находится
в
левом
в е р х н е м углу э к р а н а . О с ь X н а п р а в л е н а в п р а в о , к а к и в е в к л и д о в о й с и с т е м е к о о р д и н а т , » а в о т ось Y , в о т л и ч и е о т п р и в ы ч н о й
системы координат,
- вниз.
П о э т о м у все р и с у е м ы е
о б ъ е к т ы будут и м е т ь п о л о ж и т е л ь н ы е к о о р д и н а т ы к а к п о X , т а к и п о Y . Важно
отметить, что т.к.
нумерация пикселей начинается
с нуля, то
н и ж н я я т о ч к а , в и д и м а я н а э к р а н е , будет и м е т ь к о о р д и н а т ы (639, 4 7 9 ) . (0,0)
639
X
самая правая
В и д е о р е ж и м ы т а к ж е р а з л и ч а ю т с я п о глубине п и к с е л е й ( p i x e l d e p t h ) . Э т о т п а р а м е т р определяет
количество
следовательно,
различных
количество
значений,
принимаемых
отображаемых цветов.
Например,
отдельным
пикселем,
и,
в видеорежиме с глубиной
п и к с е л е й 8 б и т к а ж д ы й п и к с е л ь м о ж е т и м е т ь о д и н и з 256 р а з л и ч н ы х ц в е т о в ( 2 = 2 5 6 ) . режимах с
16-битной
глубиной
пикселей поддерживается отображение до
Г л у б и н а п и к с е л е й о б ы ч н о р а в н а 4,
8,
16, 2 4 и л и 3 2 б и т а м . М ы с в а м и будем р а б о т а т ь в
о д н о м и з с а м ы х п р о с т ы х г р а ф и ч е с к и х р е ж и м о в - 640x480
с г л у б и н о й ц в е т а 4 б и т а , т.е.
нашем
называется
распоряжении
режимы
с
будет
большим
16
цветов.
разрешением
В
65536 ц в е т о в .
и
Такой
режим
большим
количеством
VGA.
цветов
в
Графические
называют
SVGA
(SuperVGA) р е ж и м а м и . Еще кое-где м о ж н о встретить старые графические режимы, такие, к а к E G A , C G A , в к о т о р ы х и с п о л ь з о в а л о с ь от 2 до
16 ц в е т о в , а р а з р е ш е н и е не п р е в ы ш а л о
320x200. Н и ж е приведен набор строк,
которые должны присутствовать
в любой
программе,
н а з н а ч е н и е м которой является работа с г р а ф и к о й . /*
Шаблон
п р о г р а м м ы для р а б о т ы
с
графикой
*/
#include
#include void
{
//начало
int
/
main()
gd,
программы
gm;
gd = DETECT; initgraph(&gd, &gm,
"z:\\bgi");
// Здесь идет последовательность графических функций. getch() ; closegraph();
}
//конец
Для
работы
с
программы
графикой
необходимо
находится описание графических функций. ней описана функция, п р о г р а м м ы вплоть до функцию,
мы
подключить За ней
graphics.h
библиотеку
-
в
ней
п о д к л ю ч а е т с я б и б л и о т е к а conio.h.
В
к о т о р у ю м ы будем и с п о л ь з о в а т ь д л я о с т а н о в к и в ы п о л н е н и я к о д а н а ж а т и я л ю б о й к л а в и ш и на клавиатуре -
получим
getch();
в о з м о ж н о с т ь увидеть результат в ы п о л н е н и я
.
Используя
эту
программы до того,
к а к о н будет с к р ы т о к н о м р е д а к т о р а к о д а . int gd,
gd
gm;
= DETECT;
Далее нам понадобятся две переменные целого типа (подробно о типах данных мы п о г о в о р и м в с л е д у ю щ е й г л а в е ) . Э т о gd и gm ( с о к р а щ е н и е от g r a p h i c s d e t e c t и g r a p h i c s m o d e ) . П е р в а я о п р е д е л я е т д р а й в е р г р а ф и ч е с к о г о р е ж и м а ( C G A , E G A , V G A и т.д.). Е с л и п е р е м е н н о й п р и с в о и т ь з н а ч е н и е DETECT (как сделано в н а ш е м случае), то определение (детектирование) наиболее подходящего драйвера и видеорежима происходит автоматически. Во вторую переменную заносится номер графического режима. В нашем случае этой п е р е м е н н о й мы н и ч е г о не п р и с в а и в а е м , но она нам все р а в н о нужна.
initgraph(&gd,
Функция аргумента.
initgraph()
"z:\\bgi") ;
переводит
экран
в
графический
П е р в ы е д в а - э т о а д р е с а п е р е м е н н ы х gd и g m .
передается строчка, Далее
&gm,
пишутся
режим.
Она
имеет
три
качестве третьего аргумента
с о д е р ж а щ а я п у т ь к ф а й л у egavga.bgi. графические
функции,
формирующие
Н а п р и м е р , л и н и и , п р я м о у г о л ь н и к и , о к р у ж н о с т и и т.д. closegraph();
В
изображение
на
экране.
Закрытие графического режима
осуществляется
с
помощью
функции
closegraph().
П о с л е о к о н ч а н и я работы в графическом р е ж и м е необходимо корректно завершить работу с ним и
выйти в текстовый режим.
Если мы
этого не сделаем,
система автоматически
с д е л а е т э т о з а н а с , н о э т о будет а в а р и й н а я с и т у а ц и я ? и с л е д у ю щ е е о т к р ы т и е г р а ф и ч е с к о г о р е ж и м а м о ж е т п р о й т и н е у д а ч н о . Н и к а к и х в х о д н ы х п а р а м е т р о в эта ф у н к ц и я н е т р е б у е т . В в ы б р а н н о м г р а ф и ч е с к о м р е ж и м е д о с т у п н ы 16 цветов. В ф у н к ц и я х , п р и н и м а ю щ и х в
качестве
параметра цвет,
приведенный
Таблица
в
таблице
нужно
указать название
цвета или
его
н о м е р (от 0 до
15),
цветов.
цветов 0
BLACK
черный
1
BLUE
синий
2
GREEN
зеленый
3
CYAN
голубой
4
RED
красный
5
MAGENTA
фиолетовый
6
BROWN
коричневый
7
LIGHGRAY
светло-серый
8
DARKGRAY
темно-серый
9
LIGHTBLUE
светло-синий
10
LIGHTGREEN
светло-зеленый
11
LIGHTCYAN
светло-голубой
12
LIGHTRED
светло-красный
13
LIGHTMAGENTA
светло-фиолетовый
14
YELLOW
желтый
15
WHITE
белый
С р е д и ф у н к ц и й , ф о р м и р у ю щ и х и з о б р а ж е н и е , стоит отметить: setcolor(color)
-
устанавливает
текущий
цвет.
Именно
ф и г у р ы . П е р е м е н н а я color м о ж е т п р и н и м а т ь з н а ч е н и е о т 0 д о putpixel(x, у, line(xl,
yl,
этим
цветом
рисуются
все
15.
c o l o r ) - р и с у е т т о ч к у с к о о р д и н а т а м и (х,у) ц в е т о м color.
х2,
у2)
- рисует л и н и ю текущим
цветом
от т о ч к и
(xl,yl) до т о ч к и
(х2,
У2). rectangle(xl, краям
экрана,
(х2,у2)
углов.
yl,
на
х2,
у2)
основании
-
рисует
прямоугольник
п о л о ж е н и я левого
со
верхнего
сторонами, (xl,yl)
и
параллельными правого
нижнего
circle(x, у, г) - р и с у е т о к р у ж н о с т ь р а д и у с о м г с ц е н т р о м в т о ч к е ( х , у ) . агс(х, у, start, e n d , г) - р и с у е т дугу о к р у ж н о с т и р а д и у с о м г с ц е н т р о м в т о ч к е (х,у) от у г л а s t a r t д о у г л а end. setbkcolor(color)
-
устанавливает
цвет
фона.
Переменная
color
может
принимать
з н а ч е н и е от 0 до 15. setfillstyle(p,
color) - у с т а н а в л и в а е т т и п
м о ж е т п р и н и м а т ь з н а ч е н и я от 0 до
заливки.
Параметр
р
задает узор
заливки и
12. В т о р о й п а р а м е т р - color, з а д а е т ц в е т з а л и в к и .
floodfill(x, у ,
border)
и м е е т ц в е т border,
Полный помощью
а т о ч к а (х,у)
перечень
встроенной
Пример
можно
любую
замкнутую
фигуру,
граница
которой
находится внутри закрашиваемой области.
функций,
справочной
3.1.Написать
синий
залить
описанных системы
программу,
которая
черный
в
graphics.h,
библиотеке
можно
получить
( к л а в и ш а F1).
выводит на экран
флаг
Олимпийских
игр.
красный
желтый
зеленый
Т е к с т п р о г р а м м ы на С + + :
#include
#include
void
main()
{ int
gd,gm;
gd=DETECT; initgraph(&gd,&gm,"z : W b g i " ) setbkcolor(15 )
;
//
установить
I/ setcolor(l) ;
цвет
фона
рисуем //
установить
c i r c l e ( 100 , 100 , 3 5 ) ;
//
-
верхний
цвет
нарисовать
бельм ряд
кольца, кольцо
колец
указывается
:-:г:/_ес
цвета
заданного цвета
setcolor(O); circle(160,100,35) setcolor(4) ; circle(220,100,35) // setcolor(YELLOW) ; circle(130,140,35); setcolor(GREEN); c i r c l e t 1 9 0 , 1 4 0 , 35 ) ; getch( ) ; closegraph(); }
рисуем //
установить //
нижний
цвет
нарисовать
ряд
кольца,
кольцо
колец указывается
заданного
цвета
название
цвета
с
Анимация
»
Как
сделать
Для
этого
некоторое время это
так,
чтобы
нужно
сначала
изображение дать
на
команду
з а к р а с и т ь его ц в е т о м
экране
монитора
компьютеру
отобразить
фона и одновременно
создаст у пользователя и л л ю з и ю д в и ж е н и я и з о б р а ж е н и я
двигалось? объект,
а
через
нарисовать в другом месте -
по
экрану.
Процесс
создания
такой иллюзии называется анимацией. Пример
3.2.
п е р е к л ю ч а е т его Приступая все
команды
Чтобы
можно
delay(n)
из
компьютер секунда =
Написать
к решению,
так
быстро,
было
видеть
которая
мы
рисует
светофор
и
зеленого.
следует учесть
что
то,
увидим
переключение
библиотеки
остановит 1000
программу,
цвета от к р а с н о г о до
функций
выполнение
что
компьютер
выполнит
только
конечный
результат.
цветов,
dos.h
-
используется
выполнив
программы
п
на
функция
эту
команду,
миллисекунд
(1
миллисекунд).
Ф р а г м е н т п р о г р а м м ы на С + + : setcolor(WHITE);//рисуем
контур
светофора
rectangle(10,10,175,470); circle(90,90,70); circle(90,235,70) ; circle(90,380,70); Betfillstyle(1,RED);//устанавливаем floodfill(90,90(WHITE) ; delay(2000);//
пауза
2
цвет
//закрашиваем
заливки
верхний
-
красный
круг
красным
цветом
секунды
setfillstyle(1,BLACK);//перекрашиваем
верхний
круг
в
цвет
черный
фона
floodfill(90,90,WHITE);
setfillstyle(1,YELLOW); floodfill(90,235,WHITE); d e l a y ( 2 00 0 ) ;
//
2
пауза
setfillstyle(1,BLACK);
//устанавливаем //закрашиваем
цвет
заливки
средний
круг
-
желтый
желтым
цветом
секунды //перекрашиваем
средний
//устанавливаем
цвет
круг
в
цвет
фона
-
зеленый
-
черный
floodfill(90,235,WHITE); setfillstyle(1,GREEN); floodfill(90,380,WHITE);
Пример 3.3.
//закрашиваем
Н а п и ш и т е программу,
заливки
нижний
круг
зеленым
цветом
которая рисует на э к р а н е рыбу и двигает её слева
направо.
setcolor(RED); / /
рисуем
рыбу
красным
arc(200,200,20,190,45);//верхняя
цветом
сторона
arc(200,170,170,340,45);//нижняя
сторона
»
c i r c l e ( 2 3 0 , 1 8 0 , 1 ) ; //глаз line(220,210,220,160);//линия/
выделяющая
line(154,205,154,163);//линия/
завершающая
delay(3000) ;
//пауза
3
секунды
голову хвост
З а д а н и я к главе 3. П р а к т и ч е с к о е з н а к о м с т в о . Графика Задача
3.1.
Напишите
программу,
которая
выводит
на
экран
Государственный
флаг
России. Задача 3.2. Н а п и ш и т е п р о г р а м м у , к о т о р а я р и с у е т д о м с л е д у ю щ е г о в и д а :
Задача 3.3. Н а п и ш и т е п р о г р а м м у , ц е л ь к о т о р о й - с о з д а т ь и л л ю з и ю у в е л и ч е н и я к в а д р а т а на экране:
Задача 3.4. Н а п и ш и т е п р о г р а м м у , к о т о р а я р и с у е т о к р у ж н о с т ь , д в и ж у щ у ю с я п о э к р а н у . Задача
3.5.
Напишите
программу,
которая
рисует
з а м е н я е т её на н е й т р а л ь н у ю , а потом на веселую.
сначала
грустную
рожицу,
далее
Гпава4 ь
Типы
данных
Какие правила необходимо соблюдать при н а п и с а н и и программ? Тело
программы,
инструкция
вызывает
программы.
При
написанной
на
некоторые
написании
языке
действия
С++, на
инструкций
состоит
из
инструкций.
соответствующем
применяются
шаге
Каждая
выполнения
определенные
символы,
составляющие алфавит языка. Алфавит я з ы к а С + + включает в себя: •
буквы л а т и н с к о г о алфавита:
•
а р а б с к и е ц и ф р ы : 0, 1,2, 3, 4, 5, 6, 7, 8, 9; специальные + Плюс
з а г л а в н ы е от А до Z и с т р о ч н ы е от а до z;
символы: Кавычки С
-
Минус
*
Звездочка
Круглые
/
О
П р я м о й слеш
скобки
Квадратные
=
[]
Равно
<
{}
Фигурные
Меньше
%
Процент
>
Больше
&
Амперсант
!
Восклицательный
?
Вопросительный
знак знак
Решетка
~
Тильда
\
Запятая Двоеточие Точка с запятой
? Л
скобки
скобки
Вертикальная Обратный
черта
слеш
Подчеркивание Пробел
Крышечка
Использование
русских
строковых выражениях.
в
#
1
Точка ?
только
Апостроф
используемых
для
визуального
букв
(и других
Количество
специфических
символов)
возможно
пробелов и нажатий клавиши
форматирования
текста,
не
имеет
для
<Enter>,
компилятора
значения. Точка с запятой служит признаком конца оператора, и ч а щ е в с е г о и м е н н о э т о т знак забывают поставить новички. К о м п и л я т о р р а з л и ч а е т с т р о ч н ы е и заглавные буквы, и в н е к о т о р ы х с л у ч а я х замена строчной буквы
заглавной или наоборот может вызвать ошибку.
В качестве имени переменной и л и ф у н к ц и и м о ж е т с л у ж и т ь н а б о р б у к в л а т и н с к о г о алфавита,
цифр
обязательно должно
и
символа
с буквы или
совпадать
подчеркивания,
знака подчеркивания
с любым
ключевым
словом.
при (rt,
этом first,
Если
начинаться huge, _ а ) .
переменная
это
имя
должно
И м я п е р е м е н н о й не
или
функция
с таким
и м е н е м уже и с п о л ь з у ю т с я в с и с т е м е , т о м о ж е т в о з н и к н у т ь о ш и б к а с о в п а д е н и я и м е н и е щ е на стадии к о м п и л я ц и и . Длина имени н е фиксируется различают
имена
по
разному
(в р а з у м н ы х пределах),
количеству
начальных
но р а з н ы е к о м п и л я т о р ы
символов,
что
тоже
может
служить
источником ошибки. В к а ч е с т в е и м е н и запрещено использовать с л е д у ю щ и е к л ю ч е в ы е с л о в а : asm
do
if
static
volatile
auto
double
int
struct
while
break
else
long
switch
case
enum
register
typedef
interrupt
_es
char
extern
return
union
_cs
huge
const
float
short
unsigned
cdecl
continue
for
signed
void
near
default
goto
sizeof
_ss
_ds far pascal
export
»
Переменная памяти;
представляет
собой
данные,
хранящиеся
в
определенных
ячейках
значение п е р е м е н н о й , в отличие от константы, может быть изменено в ходе
в ы п о л н е н и я программы. Вид данных (целые, дробные числа, строки и так далее) и способ их представления и хранения определяются типом п е р е м е н н о й , который указывается при объявлении или определении п е р е м е н н о й . К а к уже о т м е ч а л о с ь в ы ш е , идентификаторы переменных, т.е. и х имена, н е м о г у т совпадать с ключевыми словами,
п о э т о м у являются неизвестными компилятору.
В
связи с этим до первого и с п о л ь з о в а н и я переменной ее обязательно нужно объявить. Если п е р е м е н н а я просто объявляется, то ее начальное значение может быть либо нулем, либо к а к и м - т о п р о и з в о л ь н ы м , соответствующим тем байтам, которые были записаны в ячейках п а м я т и , отведенных под переменную. Чтобы избежать неопределенности, мы будем либо определять
переменные,
либо
придавать
им
начальные
значения
до
первого
и с п о л ь з о в а н и я в качестве значений чего-либо. О б щ а я структура объявления переменной м о ж е т б ы т ь п р е д с т а в л е н а т а к :
тип_данных идентификатор; Например:
int а;
Если нужно
объявить несколько
ИЛИ long double b; переменных одного типа, то их и д е н т и ф и к а т о р ы можно
перечислять через запятую:
тип_данных идентификатор! , идентификатор2 ; Например: int а,Ь,с; Общая структура определения переменной отличается только тем, что идентификатору сразу же присваивается начальное значение, одновременно определять и объявлять переменные одинакового типа:
причем
можно
тип_данных идентификатор=значение; Например:
int а=5;
или
тип_данных идентификатор1=значение1, идентификатор2=значение2; Например:
int
а = о^ = 9;
или
тип_данных идентификатор!, идентификатор2=значение; Например:
int а,с=10;
Базовые типы В качестве базовых типов данных определены целые числа и дробные числа, а также ссылочный тип, с помощью которого, н а п р и м е р , можно хранить строки. Для хранения целых чисел п р и м е н я ю т с я типы char и сохранять числа от -128 до тип
int,
причем
первый может
127, то есть объем этого типа составляет один байт. Обычно
char используют для хранения символов в кодировке ASCII
(см.
приложение
1),
поэтому он так и называется. Д л и н а типа int равняется м а ш и н н о м у слову и для 16-ти разрядных систем составляет 2
байта,
а для
32-х разрядных - 4 байта.
Мы
будем
рассматривать
16-ти разрядную
систему, н а п р и м е р , Borland С + + 3.1, поэтому с его помощью можно представить числа от -32768
до
32767.
Это
так
называемые
знаковые
типы,
в
них
для
хранения
числа
используются не все биты, а только 7 и 15, и этот последний, старший бит равняется 0 для положительных чисел и
1
для отрицательных. Каждое число по модулю разлагается на
с т е п е н и д в о й к и , н а п р и м е р , 25
4
d
=
3
1*2
+
2
1*2
1
+ 0*2
+ 0*2
+
1*2° =
11001b. Д л я х р а н е н и я
о т р и ц а т е л ь н ы х ч и с е л и с п о л ь з у е т с я д о п о л н и т е л ь н а я д в о и ч н а я а р и ф м е т и к а , т о есть берется положительное число, сложении
в с е его
одинаковых по
биты инвертируются,
модулю,
но разных по
и к нему добавляется
знаку чисел
д в о и ч н о й а р и ф м е т и к и получим 0. Н а п р и м е р , для типа char системе как 01111111, Для
целых
а-127 как
чисел
с
1,
тогда п р и
использованием
правил
127 з а п и с ы в а е т с я в д в о и ч н о й
10000001.
существует
модификатор
unsigned,
который
позволяет
использовать базовые т и п ы для хранения беззнаковых чисел. Например:
unsigned
char
-
д и а п а з о н о т 0 д о 255
int
-
диапазон
или unsigned
о т 0 д о 65535.
Д л я х р а н е н и я д р о б н ы х (вещественных) Вещественные
числа
3956.768,
в научной:
либо
представляется
в
быть
на которую
факт:
представлены
0.3956768е+4,
в и д е мантиссы,
степени десятки, следующий
могут
ч и с е л и с п о л ь з у ю т с я т и п ы float и double.
то
то
есть
есть
либо
основания,
и
умножают мантиссу.
бесконечная
геометрическая
в
обычной
0 . 3 9 5 6 7 6 8 * 10 .
записи,
Во
втором
экспоненты,
Для
хранения
прогрессия
в данном
мантиссы
сходится 1
например,
случае ч и с л о
к
2
случае
-
используют
определенному 3
ч и с л у . Н а п р и м е р , е с л и будем с к л а д ы в а т ь 1 / 2 + 1 / 4 + 1 / 8 + . . . и л и 1/2 + 1 / 2 + 1 / 2 + . . . , т о в и т о г е получим в сумме
1 , п р и ч е м е с л и м ы будем с к л а д ы в а т ь н е д о б е с к о н е ч н о с т и , а д о к а к о й - т о
определенной степени п более,
чем
на
подставляя
в
о т л и ч н о е от
1/2
(например,
Если
10), т о м ы п о л у ч и м ч и с л о ,
теперь
соответствующие
мы
биты
будем
двоичного 1
2(-1)
представления
0,
степени
то
1
не
двойки,
получим
число,
Л-)П_1
l/2
,
р а з л а г а я его п о
отрицательным степеням
и так далее.
float
Типы мантиссы,
о т л и ч а ю щ е е с я от
какие-то
1 . Т а к и м о б р а з о м , с п о м о щ ь ю п бит м ы м о ж е м п р е д с т а в и т ь л ю б у ю д р о б н у ю
часть в е щ е с т в е н н о г о числа с точностью двойки
выкидывать
то
double
и
есть
отличаются
точностью,
и
количеством
битов,
отводимых
битов,
отводимых для
на х р а н е н и е
хранения
экспоненты,
то
есть
д и а п а з о н о м от самых маленьких до самых больших чисел. К
перечисленным
уменьшающие Причем
и
модификатор
системах
для
типам
short
определен,
мы
его
не
следующей
таблице:
что
будем
слово
в
применяться
количество
определен
совместимости,
Отметим,
могут
увеличивающие
только
16-ти
в
для
разрядной
принимать
int
байтов,
во
типа
int
системе
внимание.
длинных
модификаторы отводимых и он
для
нужен
Перечислим
сочетаниях
с
в
лишен
и
long,
хранения
short
типа.
32-х
разрядных
смысла,
хотя
описанные типы
модификаторами
и в
может
опускаться, н а п р и м е р , u n s i g n e d и u n s i g n e d int о з н а ч а ю т о д н о и то ж е . Кроме
того,
переменной, Например:
если то
const
нужно
предотвратить
она объявляется int
а=5;
как
изменение
константа
с
какой-либо
величины,
использованием
например,
модификатора
const.
При попытке модифицировать значение константы в программе возникнет ошибка компиляции.
Операции с переменными И т а к , мы р а з о б р а л и с ь , что такое п е р е м е н н ы е , теперь п о с м о т р и м , что с н и м и м о ж н о делать.
Например,
сложение,
операции: целым
и
из
них
можно
вычитание,
вещественным
типам
составлять
умножение,
данных.
н а п р и м е р , два слагаемых и так далее, целый
и
вещественный,
то
Они
выражения,
деление.
Эти
используют
и если т и п ы
результат преобразуется
используя
математические
операции
два
применимы
значения
или
операндов не совпадают, автоматически
к
к
операнда, например,
более д л и н н о м у и
о б щ е м у типу, н а п р и м е р , к в е щ е с т в е н н о м у . Е с л и т и п ы обоих о п е р а н д о в совпадают, то тип результата
совпадает
д е л е н и я п о модулю
с
ними.
Исключение
составляет
операция
взятия
остатка
от
- %. О н а п р и м е н я е т с я т о л ь к о к ц е л ы м ч и с л а м и в ы д а е т о с т а т о к от
деления первого на второе. К
арифметическим
которые
применяются
уменьшают
к
операциям одному
соответственно
также
операнду
значение
инкремент
относят
целого
операнда
на
типа. 1.
Эти
++
Различаются
декремент
—,
увеличивают
и
и
операции
префиксная
форма
(+ + п е р е м е н н а я ) и п о с т ф и к с н а я ( п е р е м е н н а я + + ). Д л я б о л ь ш и н с т в а случаев это не и м е е т з н а ч е н и я , н о и н о г д а м е н я е т с я п о с л е д о в а т е л ь н о с т ь в ы п о л н е н и я . П р е ф и к с н а я всегда выдает з н а ч е н и е о п е р а н д а уже и з м е н е н н о е ,
а п о с т ф и к с н а я сначала выдает з н а ч е н и е операнда, а
п о т о м его и з м е н я е т . Важной
операцией
присваивание
является
значения
переменной.
Например,
если
мы хотим присвоить п е р е м е н н о й х значение п е р е м е н н о й у, то п и ш е м х
= у;
а не н а о б о р о т . Можно
присваивать
переменной
результат
выражений,
математических
действий, н а п р и м е р : х
=2 * у + 8 ;
М о ж н о у с т р а и в а т ь м н о ж е с т в е н н о е присваивание, х
например:
= у = 5;
т о г д а с н а ч а л а в у з а п и ш е т с я 5, а п о т о м в х - з н а ч е н и е у (в т е к у щ и й м о м е н т 5). Кроме
того,
довольно
часто
встречаются
ситуации,
когда
в
переменную
нужно
з а п и с а т ь е е ж е значение, н о , н а п р и м е р , у м н о ж е н н о е н а какое-то число. Т о г д а н у ж н Ъ написать к о н с т р у к ц и ю вида: Х
х*3;
=
н о д л я э т о г о м о ж н о п р и м е н и т ь с о к р а щ е н н ы й вариант: Х
*
=
3;
Эта з а п и с ь о б о з н а ч а е т т о ж е с а м о е . Т а к и е с о к р а щ е н н ы е з а п и с и , и л и п р и с в а и в а н и я , с о п р я ж е н н ы е с о п е р а ц и е й , с у щ е с т в у ю т д л я всех а р и ф м е т и ч е с к и х о п е р а ц и й . Все
операции
Существование
обладают
приоритета
различным
надо
к р а й н е м случае, для п о д с т р а х о в к и К а к уже у п о м и н а л о с ь ,
всегда
приоритетом, иметь
в
виду
то
есть
при
порядком
составлении
выполнения. выражений,
в
расставлять скобки ( ) .
результат
выражения
зависит
от
операндов,
а
особенно
от
левого операнда в о п е р а ц и и п р и с в а и в а н и я . Тем не менее, иногда требуется я в н ы м образом преобразовать следующая
переменную
одного
типа
к
другому
типу.
При
этом
используется
конструкция:
(требуемый_тип)
например: (int)
х;
переменная;
*
Преобразование безболезненно.
более
Обратное
коротких
типов
преобразование
в
более
является
п е р е м е н н о й не выходит за д и а п а з о н требуемого типа,
длинные
всегда
корректным,
в противном
происходит
если
значение
случае может с и л ь н о s
и з м е н и т ь с я з н а ч е н и е , н а п р и м е р , с м е н и т ь с я з н а к ч и с л а и д а ж е его м о д у л ь . Продемонстрируем
с к а з а н н о е н а примере с л е д у ю щ е й п р о г р а м м ы .
Тип
используется
значение
данных
char
c h a r будет в ы в е д е н о
отображения
результатов
на
на экран, экране
выводить
библиотеки
значения
на
хранения
преобразуем
монитора мы
б и б л и о т е к и iostream.h, к о т о р а я и м е е т вид как
для
экран,
мы
c o u t «
символов, его
будем
в
использовать
<выводимое
очистим
его
с
поэтому,
прежде
ц е л о ч и с л е н н ы й тип функцию
значение>
помощью
функции
clrscr()
Пример 4.1. #include ttinclude void main() { const int s=2; //определяем константу //определяем переменные int а=3; char с=4; float z=3.14; clrscr();//очистить экран
с=а—s;//c станет равно cout<<(int)c<<endl;
5
a»z-a; //а станет равно 9 cout<
3
a=a%c;// а станет равно О cout<
cout
из
П е р е д тем
conio.h:
z- z - a ; t l x станет равно 6.14 cout<
чем
int. Д л я
- означает «перейти на новую строку»
из
З а д а н и я к главе 4.Типы д а н н ы х З а д а ч а 4.1 Какое имя не может принимать переменная: Задача 4.2 О п р е д е л и т е з н а ч е н и я п е р е м е н н ы х а,Ь,с и F п о с л е в ы п о л н е н и я п р о г р а м м ы :
Глава
5
Ввод
и
вывод
данных ь
Решение
даже
самой
ввода-вывода
информации.
оперативную
память
простой
задачи
Ввод д а н н ы х
компьютера
для
на -
компьютере
это
передача
дальнейшей
не
обработки.
передачи данных для отображения на мониторе компьютера. «диалог»
пользователя
и
компьютера,
именно
обходится
информации
без
с
Вывод
операций
клавиатуры
-
это
в
процесс
Эти о п е р а ц и и обеспечивают
поэтому в любых программах
они играют
очень важную роль.
В ы в о д д а н н ы х . Ф у н к ц и я printf() К а к н а б у м а г е м о ж н о н а п и с а т ь п р е д л о ж е н и е « в о д н о м р у б л е сто к о п е е к » ? 1.
Можно
2.
Можно использовать математические символы:
1 рубль
3.
Можно
указать
знака после
100.00
копейки.
4.
использовать ц и ф р ы : числа
с
в
1 рубле
точностью
до
100 копеек. второго
=
100 копеек. запятой:
1.00 рубля
=
М о ж н о н а п и с а т ь ч а с т ь п р е д л о ж е н и я н а о д н о й с т р о к е , а д р у г у ю его ч а с т ь п е р е н е с т и на н о в у ю
строку:
1.00 рубля
= 100.00 копейки.
*
Н е з а в и с и м о от того, к а к мы н а п и ш е м эти слова, их смысл не и з м е н и т с я (в рубле не станет больше копеек). Меняется только оформление. Форматированный
вывод
данных
-
это
отображение
информации
на
экране
монитора в соответствии с заранее созданным шаблоном о ф о р м л е н и я . То, как отображается и н ф о р м а ц и я , может иметь большое значение. С п и с о к покупок записанный
так:
Тетради,
Ручки,
12 шт.,
- разобрать очень тяжело.
20 шт.
Правильное
о ф о р м л е н и е п р и д а с т ему совсем другой с м ы с л : Тетради Ручки В
- 12
-
20
языке
шт.
шт.
С++
форматированный
вывод данных
обеспечивает
функция
printfQ.
Ф у н к ц и я о п и с а н а в б и б л и о т е к е stdio.h и в о б щ е м виде она м о ж е т быть п р е д с т а в л е н а так: printf (
"управляющая строка",
аргумент
1,
а р г у м е н т 2,
...
аргумент N
);
Пример 5.1. О т о б р а з и т ь н а э к р а н е с п и с о к в и д а : Девушки -
12 ч е л о в е к .
П а р н и - 20 ч е л о в е к . int
а
=12,
Ь=20;
p r i n t f ( " Д е в у ш к и - %i ч е л о в е к . \ п Парни -
Управляющая
строка
обязательно
%i ч е л о в е к . " , а , Ь ) ;
заключается
в двойные
кавычки
и
состоит
из
э л е м е н т о в трех т и п о в : 1.
о б ы ч н ы е с и м в о л ы , к о т о р ы е п р о с т о к о п и р у ю т с я н а э к р а н без и з м е н е н и й ( в примере
1
это
слова
«Девушки»,
«Парни»,
«человек»
и
символы
« -
»
и
пробел); 2.
у п р а в л я ю щ и е с и м в о л ь н ы е к о н с т а н т ы (\п)- с о ч е т а н и я с и м в о л о в , к о т о р ы е н е выводятся на экран.
Их цель - о ф о р м л е н и е выводимой строки. Доступны
следующие символьные константы: \а - п о д а ч а з в у к о в о г о с и г н а л а ; \Ь - перевод курсора на одну п о з и ц и ю влево;
\n - переход на новую
строчку;
\t - г о р и з о н т а л ь н а я т а б у л я ц и я ; \\ - в ы в о д с и м в о л а \; \" - вывод с и м в о л а "; 3.
с п е ц и ф и к а ц и я п р е о б р а з о в а н и я (% i) - э т о « п р е д у п р е ж д е н и е » к о м п ь ю т е р у о том,
Каждая
к а к о г о х а р а к т е р а и н ф о р м а ц и я будет в ы в о д и т ь с я н а э к р а н .
с п е ц и ф и к а ц и я преобразования начинается со
знака %. Д а л е е идет буква,
обозначающая тип выводимого значения. Например: %с - з н а ч е н и е м аргумента я в л я е т с я с и м в о л (тип д а н н ы х char); %s - з н а ч е н и е м аргумента я в л я е т с я строка с и м в о л о в (тип д а н н ы х c h a r ) ; %d или %i - з н а ч е н и е м аргумента я в л я е т с я целое число (тип д а н н ы х int); %f double),
значением
например,
компьютерах для %4.2f о з н а ч а е т ,
аргумента
3.141593.
отделения
что для
является
По
вещественное
умолчанию
целой
части
число
выводится
от дробной
6
данных после
4
позиции,
float
или
запятой
используется точка).
в ы в о д а ч и с л а будет з а р е з е р в и р о в а н о
предназначены для дробной части.
(тип
знаков
Запись
две
(в
вида
из которых
Если н е о б х о д и м о , чтобы в ы в о д и л и с ь т о л ь к о два знака
п о с л е з а п я т о й , т о н а д о н а п и с а т ь т а к : %.2f; % g и л и % G - т а к ж е в ы в о д и т в е щ е с т в е н н о е ч и с л о , и с к л ю ч а я н е з н а ч а щ и е н у л и . Т.е. ч и с л о 5.2300 будет н а п е ч а т а н о т а к :
5.23.
Т а б л и ц а 1. Ти
п
данных char a = 6 8 ;
В
double
int a = 6 8 ;
a=68.15900;
printf("%c",a);
D
D
-
printf("%i",a);
68
68
0
printf("%f',a);
—
—
68.159000
printf("%4f',a);
—
—
68.159000
printf("%4.1f',a);
—
printf("%.2f',a);
—
—
68.16
printf("%g'»;
-
таблице
данных и
показан
результат,
68.2 68.159 который
будет
выведен
при
соответствующем
типе
спецификации преобразования.
О б р а т и т е в н и м а н и е на то, что при с н и ж е н и и т о ч н о с т и результата те числа, к о т о р ы е не
выводятся
выводимого
на
экран
результата.
в
соответствии
Число
68.159,
с
запросом,
выведенное
с
используются
точностью
до
для
двух
округления
знаков
з а п я т о й , будет в ы г л я д е т ь т а к : 68.16.
после •»
Если после знака % записан не символ преобразования, то он выводится на экран. Таким образом, строка %% приводит к выводу на экран знака %. Функция аргументов
printf и с п о л ь з у е т у п р а в л я ю щ у ю
и
выражения,
каковы
вызовы
их
типы.
функций.
спецификации. П р и м е р 5.2. int
х
char
=
10,
у=20,
ch;
float
fl,
double
f2;
d;
z = x + y ch
=
fl
=
3.14;
f2
=
fl
d
=
0.5;
*
2.5;
z;
строку,
Аргументами
Главное,
чтобы
могут их
чтобы быть
значения
определить,
сколько
переменные,
всего
константы,
соответствовали
заданной
printf( printf( printf( printf( printf ( printf(
"Выводим только текст \п" ); "Значение переменной х = %i \п", х ); "Переменные у и z равны%3 и%31 соответственно", у, z ) ; "А теперь напечатаем три звездочки %с %с %с ", ch, ch, ch ); "\t Сделали отступ \n пропустили строчку \п и еще одну " }; "%f %f %.2f ", fl, f2, d );
Результат выполнения программы : Выводим только текст Значение переменной х = 10 Переменные у и z равны 20 и 30 соответственно А теперь напечатаем три звездочки * * * Сделали отступ пропустили строчку и еще одну 3.140000 7.850000 0.50
Пример 5.3. Для покраски дома необходимо купить краски двух цветов: красной для крыши и желтой для стен. Требуется составить программу, которая, зная размеры дома, определяет, сколько понадобится краски, чтобы покрасить лицевую сторону дома. Окна красить не нужно.
int а=10, b=5, с=2, d=3, h=3; // Задаем размеры дома float SI, S2; / / S I - площадь крыши, S2 - площадь стены SI = 0.5 * а * h; * S 2 = a * b - 3 * ( c * d ) ; printf("Нужно купить %2.1f красной краски \n", S 1 ) ; printf("и %2.1f желтой краски \n", S 2 ) ;
В С++ есть функции, цель которых - только форматирование текста. Они абсолютно не влияют на содержание передаваемой информации. Среди таких функций стоит отметить (библиотека conio.h): textcolor(color) - устанавливает цвет текста. Значение color может быть взято любое из диапазона 0..15; textbackground(color) - задает цвет фона у выводимого символа. Если эту функцию вызвать перед очисткой экрана, то весь экран буде цвета color; gotoxy(x, у) - перемещает курсор на строчку у в столбик х экрана. Сам экран в текстовом режиме имеет разрешение 80x50, т.е. 80 знакомест на каждой строчке, и таких строчек 50. Далее текст будет выводиться, начиная с этого места.
П р и м е р 5.4. Написать программу, которая выводит в центре экрана на светло-сером фоне желтыми буквами слово «Солнце».
textbackground(LIGHTGRAY); textcolor(YELLOW); gotoxy(40,25); printf("Солнце");
Ввод данных. Функция scanf() В написанной выше программе есть один недостаток. Программа всегда считает данные для одного и того же дома. А что делать, если надо покрасить несколько различных домов? Мы можем исправлять каждый раз код программы, задавая новые значения переменных а, Ь, с, d, h. Но пользователю будет намного удобнее вводить размеры дома с клавиатуры. Для ввода информации в языке С++ предусмотрена функция scanf из библиотеки stdio.h. Она имеет следующий вид: scanf ("управляющая строка", &аргумент_1, &аргумент_2, ... &аргумент_Ы) ;
Например: int х ; scanf("%i",
&х);
?
Ее описание во многом схоже с функцией printf. Управляющая строка содержит только спецификаторы преобразования, т.е. тип и количество вводимых с клавиатуры значений. Эти значения записываются в соответствующие аргументы. В качестве аргументов в функцию scanf подаются не сами переменные, а их адреса в памяти компьютера. Символ '&' - амперсант в сочетании с именем переменной передает ее адрес. Перечислим лишь некоторые спецификаторы преобразования для функции scanf: %с - ввод одного символа; %d или %i - ввод целого числа типа int; %D или %1 - ввод целого числа типа long; %f - ввод вещественного 4Hcra(float); %s - ввод строки символов. П р и м е р
5.5. Ввести с клавиатуры 3 целых числа, посчитать их сумму и вывести её
на экран. int х, у, z; printf("Введите целое число: " ) ; scanf("%i", & х ) ; printf("Введите еще два целых числа: " ) ; scanf("%i %i", &у, & z ) ; ^ p r i n t f ("Сумма трех чисел = % i " , х + у + z) ;
П р и м е р 5.6. Напишите программу для кассового аппарата, которая высчитывает стоимость товара. Входные данные: цена за 1 кг продукта и масса покупки. float price, mass; // цена и масса printf("Введите цену з а 1 к г : " ) ; scanf("%f", &price); printf("Введите м а с с у : " ) ;
scanf("%f", Smass); p r i n t f ( " С в а с %.2f р у б .
\n
Спасибо
за
покупку!
price
*
mass);
Ввод и вывод информации с помощью потоков В языке С++ есть другой, возможно, более удобный способ ввода/вывода информации. Это работа с потоками. Удобство заключается в том, что не требуется указывать тип вводимых и выводимых значений. Программа сама определяет его, исходя из объявления переменных. Для работы с потоками необходимо подключить файл iostream.h. Тогда мы сможем работать с двумя потоками: cin и cout - стандартные входной и выходной потоки. Запись в поток и считывание из потока осуществляется с помощью операций « и ». Например: int х ; cin » х; х++; c o u t << х;
//
считываем значение
с
клавиатуры в
// выводим на э к р а н и з м е н е н н о е
переменную х
значение переменной х
Если надо ввести или вывести несколько переменных, то можно написать так: int x l , х2, хЗ; c i n » xl » х2 » хЗ; x l += х2 + х З ; c o u t << "Сумма т р е х ч и с е л
=
"
«
xl
<<
"Ли";
Программа прочитает три целых числа в переменные xl, х2 и хЗ, сложит их и выведет на экран надпись "Сумма трех чисел = ", а затем результат, хранящийся в xl, и в конце перейдет на новую строку. Кроме того, для перехода на новую строку можно использовать другую конструкцию: c o u t <<
"Сумма
трех чисел
= "
<< xl
<<endl;
Но независимо от того, какую форму записи вы выберете, результат выполнения программы никак не изменится.
34
Задачи к главе 5. Ввод и вывод данных Задача 5.1. Напишите программу, которая выводит на экран имя и фамилию преподавателя, далее на новой строке с отступом выводит Ваше имя и фамилию, затем снова на новой строке с двумя отступами - дату проведения занятия. <имя и фамилия преподавателя> <Ваше имя и фамилия> <дата проведения занятия>
в
7^. Задача 5.2. Напишите программу, которая цветами российского флага выводит: «Российская Федерация» Задача 5.3. Напишите программу, цель которой - вывести на экран значение переменной г = 3.140000 следующим образом: 1)3
2)3.1
3)3.14
4)3.140
Задача 5.4. Напишите программу, в которой с клавиатуры вводится число купленных в магазине компьютеров, цена одного компьютера в евро и курс евро, а выводится общая стоимость покупки в рублях. Рекомендуемый вид экрана: Вычисление стоимости покупки в рублях. Введите исходные данные: Количество компьютеров (шт.) -> 10 Цена одной единицы (евро) -> 1 0 0 0 Курс евро (рублей/евро) -> 3 7 , 3 Общая стоимость покупки в рублях:
* 373 000 рублей
Задача 5.5. Напишите программу, которая преобразует введенное с клавиатуры дробное число в денежный формат. Например, число 12,5 должно быть преобразовано к виду 12 руб. 50 коп. Рекомендуемый вид экрана: Преобразование числа в денежный формат. Введите дробное число -> 3 2 , 7 32,7 руб.
-
это 32 руб. 70 коп.
Задача 5.6. С клавиатуры вводятся три числа. Напишите программу, которая вычисляет среднее арифметическое и среднее геометрическое этих чисел. Задача 5.7. Напишите программу пересчета величины временного интервала, заданного в минутах, в величину, выраженную в часах и минутах. Рекомендуемый вид экрана: Введите величину временного интервала ->
(в минутах)
150
150 минут - э т о 2 ч .
3 0 мин.
Задача 5.8. Напишите программу вычисления величины дохода по вкладу. Процентная ставка (в % годовых) и время хранения (в днях) задаются во время работы программы. Рекомендуемый вид экрана: Вычисление дохода по вкладу. Введите исходные данные: Величина вклада (руб.) -> 2 5 0 0 Срок вклада (дней) -> 30 Процентная ставка (годовых) - > 2 0
Доход: 41,10 руб. Сумма по окончании срока вклада:
2541,10 руб.
Задача 5.9. Напишите программу, которая выводит введенный с клавиатуры текст. При этом пользователь задает цвет и положение текста на экране. Задача 5.10. Напишите программу, которая рисует окружность, радиус которой вводится s с клавиатуры. Задача 5.11. Напишите программу, которая рисует грузовик, и закрашивает его цветом, введенным с клавиатуры. При этом размеры груза (длина и высота) вводятся с клавиатуры.
Гпава 6
Условные операторы Если наша цель не намокнуть под дождем, то мы должны взять с собой зонт, когда на небе тучи. Другое дело, если небо ясное - зонт можно не брать. В математике тоже встречаются условия: 2 если х > 0, то у = х ; если х < 0, то у = 2х + 1. , Это же условие можно записать короче: если х > 0, то у = х ; иначе у = 2х + 1. В жизни часто приходится выполнять действия в зависимости от определенных условий, именно поэтому условные операторы имеют огромное значение в любом языке программирования. В языке С++ для программирования таких ситуаций существует условный оператор if. Полная форма записи этого оператора выглядит так: if
(
условие ) олератор_1;
else оператор_2;
Здесь if (если), else (иначе) - ключевые слова, оператор_1 и оператор_2 - простые или составные операторы. Если выполняется условие, записанное в круглых скобках, тЪ работает оператор_1, иначе (если условие не выполняется) - оператор_2. Иногда говорят так: "Если условие истинно, то выполняется оператор_1, иначе (если условие ложно) оиератор_2". В качестве операторов 1 и 2 могут стоять также условные операторы. Обратите внимание на то, что условие в с е г д а заключается в скобки. Для рассмотренного примера, запись на языке С++ будет следующей: if
(х
>
0) у = х
* х;
у = 2
* х +
else 1;
Значение х должно быть определено заранее, до выполнения условного оператора. В блок-схемах условный оператор обозначается ромбом. Внутри ромба пишется условие. Далее от него идут две стрелочки: одна с надписью "Да" - по этой ветке идем в случае, если условие истинно, и "Нет" - когда условие ложно.
Для примера о том, нужно ли брать с собой зонт, создаем такую конструкцию:
Для сравнения чисел доступны следующие операции:
и
Знак операции > >= < <= ==
Назначение операции Больше Больше или равно Меньше Меньше или равно Равно Не равно
Пример х >7 х>=8 х <7 х<=8 х==9 х !=8
Пример 6.1. С клавиатуры вводится длина шеи трех жирафов, цель программы найти самого высокого жирафа. /* Самый высокий жираф */ f l o a t а , Ь , с , max; p r i n t f ("Жирафы ! Введите каждый длину своей шеи: \ п " ) ; scanf ("%f %f %f ", &a, &b, & c ) ; i f ( a > b && a > с ) p r i n t f ( " П е р в ы й жираф самый высокий ! V n " ) ; else i f (b > c) p r i n t f ( " В т о р о й жираф самый высокий ! \ n " ) ; else p r i n t f ( " Т р е т и й жираф самый высокий ! \ п " ) ;
Логические операции.
»
3
А как записать такое условие: "Если х > 10 и х < 40, то надо подсчитать х , иначе - 2 * х + 3"? Для этого существуют логические операции. Наиболее часто используемые операции - это логическое "и", "или", "не". Записываются они с помощью специальных символов: && - операция "и", || - операция "или", ! - операция "не". Традиционно эти операции должны давать одно из двух значений: истину или ложь. В языке С++ принято следующее правило: истина - это любое ненулевое значение, ложь - это нулевое значение. Выражения, использующие логические операции, возвращают 0 для ложного значения и 1 - для истинного. Условие «все х находятся в промежутке от 5 до 10», можно записать так «х > 5 и х < 10». Или на языке С++: х > 5 && х < 10. Условие «все х находятся вне промежутка от 5 до 10» можно записать так: «х < 5 или х > 10». Или на языке С++: х < 5 || х > 10 , или так !(х > 5 && х < 10)
1
Пример 6.2. Проверить истинность выражений х > 5 && х < 10, х < 5 || х > 10, !(х<5), если известно, что х=5. int х=5; printf("%i\n",х>5&&х<10); printf("%i\n",x < 5 | | x > 10); printf("%i\n",!(x<5));
Результат выполнения программы: 0 0
1
J
Теперь условие "Если х > 10 и х < 40, то надо подсчитать x , иначе - 2 * х + 3" мы можем написать так: if ( х > 1 0 & & х < 4 0 ) у = х * х * х ; else у = 2 * х + 3;
Условие не обязательно должно иметь форму операции отношения (>, <, = и т.д.). Оно может принимать вид любого выражения, вырабатывающего результат. Если он отличен от нуля, то условие, как уже говорилось, будет истинным. Если 0, то ложным. Например, запись if (х + 1) оператор1; else оператор2;
вполне допустима. Если х + 1 отлично от нуля, то работает оператор1, иначе - оператор2. Правила составления программы позволяют программисту записывать операторы >в свободной форме. Однако для удобства восприятия программы рекомендуется слово else писать под тем словом if, к которому оно относится, например: if (а == Ь) if (с < d) х = 5; else х = 12; else х = 34;
Этот пример соответствует следующей алгебраической записи:
Действие условного оператора может быть расширенно использованием составного оператора. Когда в ответ на истинность условия должны быть выполнены два и больше ь операторов, то их заключают в фигурные скобки: if (условие) {// э т и о п е р а т о р ы оператор_1; о п е р а т о р 2;
выполняются,
если
условие
истинно
оператор_Ы; } else {//эти операторы выполняются, оператор_1; оператор_2; оператор__К; }
если условие ложно.
Внутри составных операторов могут быть также условные операторы, содержащие простые или составные операторы. Мы рассмотрели полную форму условного оператора. В языке допускается и краткая форма, которая имеет вид: if (условие) оператор_1; Если условие истинно, то выполняется оператор!, иначе (если условие ложно) оператор_1 пропускается. * В виде блок схемы краткую форму записи оператора if можно представить так:
В С++ существует другая форма записи условного оператора. Это операция «знак вопроса - двоеточие». В общем виде условный оператор выглядит так: результат = условие ? значение^! : значение_2; Если условие, стоящее перед знаком вопроса, истинно, то результату присваивается значение_1, стоящее до двоеточия, иначе - значение_2, стоящее после двоеточия. Основное отличие оператора «?:» от оператора if заключается в том, что if не вырабатывает значения, а результат операции «?:» можно присвоить в переменную. Например, нужно написать программу для нахождения максимального значения из двух чисел. С помощью if мы бы записали так: int a, b, max; if (а > b) max = а; else max = b; ъ
А вот тот же код, но только уже написанный при помощи операции «?:» int a, b, max; max = а > b ? а : b;
Если а больше Ь, то переменной max будет присвоено значение а, иначе - значение Ь. В языке С++ принято следующее правило. Любое выражение с оператором присваивания, заключенное в круглые скобки, имеет значение, равное присваиваемому. Например, выражение (р = 5 + 3) имеет значение 8. После этого можно написать другое
выражение, например: ((р = 5 + 3) < 10), которое в данном случае будет всегда давать истинное значение. Пример 6.3. Вычислить значение функции у = 1/х при заданном значении аргумента х. Если введенное значение х = 0, то вычисление не производить. /* Вычисляем у = 1/х */ float х, у; printf ("Введите значение переменной х: \ п " ) ; scanf ("%f", & х ) ; if(x == 0) printf("Недопустимое значение переменной х else { У = 1/х; printf("При х = %.2f, у = %.2f \п", х, у ) ;
!\п"); *
}
Оператор выбора switch В условном операторе if мы можем пойти только по двум путям. Но зачастую бывают ситуации, когда мы должны выбирать из большого количества вариантов. Конечно, это можно реализовать с помощью вложенных операций if. Но в С++ предусмотрена специальная конструкция: оператор выбора switch (переключатель), позволяющий пойти по одной из нескольких веток алгоритма. Это особенно часто используется при создании меню, В самом общем виде оператор выглядит так: switch( выражение ) { case константа_1 : case константа_2 :
вариант_1; вариант_2;
break; break;
case константа N : вариант N; default : вариант_Ы+1;
break;
} Здесь используются ключевые слова switch, case, default и break. Конструкция работает следующим образом. Сначала высчитывается выражение в круглых скобках. Полученное значение сравнивают со всеми константами (константными выражениями). Все константы должны быть различными. Если константа равна выражению, то выполняется соответствующий вариант (одна или несколько инструкций). Вариант с ключевым словом default реализуется, если ни один другой не подошел (вариант default может и отсутствовать). Если default отсутствует, а все результаты сравнения отрицательны, то ни один вариант не выполняется. Для прекращения последующих проверок после успешного выбора некоторого варианта используется оператор break, обеспечивающий немедленный выход из переключателя switch. В операторе switch, как и в if, допускаются вложенные инструкции. „ Пример 6.4. Напишите программу - калькулятор. Необходимо создать меню с четырьмя пунктами. Программа спрашивает 2 числа и, в зависимости от выбранного пункта меню, складывает, вычитает, перемножает, делит между собой эти числа или просто выходит из программы. float a, b, res=0; int ch; scanf("%f %f", &a, & b ) ; printf(" 1. Сложить \ n " ) ; printf(" 2. Вычесть \ n " ) ; printf(" 3. Умножить \ n " ) ;
41
printf(" 4. РазделитьХп ) ; scanf("%i",Sen); // Выбираем пункт меню switch( ch ) // В зависимости от значения ch выполняем нужную //операцию { res = a + b break; case res = a - b break; case break; res = a * b case break; res = a / b case printf( '"Вы ошиблись! ") ; } printf("Ответ : %2.2f", r e s ) ;
Задачи к главе б.Условные операторы Оператор if Задача 6.1. Известно, что оптимальный вес вычисляется по формуле: рост (в сантиметрах) - 100. Напишите программу, которая вычисляет оптимальный вес и выдает рекомендации. Рекомендуемый вид экрана: Введите свой рост и вес: 1 7 0 68 Вам надо поправиться на 2,00 килограмма.
Задача 6.2. Напишите программу проверки знания даты основания Санкт-Петербурга. Рекомендуемый вид экрана: В каком году был основан Санкт-Петербург? Введите число и нажмите <Enter>
»
->1705
Неверно,
Санкт-Петербург был основан в 1703.
Задача 6.3. Напишите программу проверки знания начала Второй мировой войны. Рекомендуемый вид экрана: Когда началась Вторая мировая война? ->1939
Правильно.
Задача 6.4. Напишите программу, вычисляющую стоимость покупки с учетом скидки. Скидка 10 % предоставляется, если сумма покупки больше 1000 рублей. Рекомендуемый вид экрана: Введите стоимость покупки: ->1200
Вам предоставляется скидка 10%. Сумма с учетом скидки 1080,00 руб.
Задача 6.5. С клавиатуры вводятся 3 числа. Напишите программу, которая выводит числа в строку в порядке возрастания. Рекомендуемый вид экрана: Введите 3 числа: 8 5 9 5 8 9
Задача 6.6. Напишите программу решения линейного уравнения вида ах + b = 0. 2
Задача 6.7. Напишите программу решения квадратного уравнения ах + Ьх + с = 0. Задача 6.8. В восточном календаре принят 60-летний цикл, состоящий из 12-летних под циклов, обозначаемых названиями цветов: зеленый, красный, желтый, белый и черный. В каждом под цикле годы носят названия животных: крысы, коровы, тигра, зайца, дракона, змеи, лошади, овцы, обезьяны, курицы, собаки и свиньи. С клавиатуры вводится номер года. Необходимо вывести его название, если 1984 год был началом цикла - годом зеленой крысы. Задача 6.9. С клавиатуры вводятся радиусы двух кругов, координаты центров которых совпадают. Напишите программу, которая выводит их на экран и закрашивает наименьший из них синим цветом, а больший - желтым. Если радиусы совпадают, то программа должна сообщить об этом пользователю и увеличить радиус, введенный первым на 5 пикселей. Задача 6.10. С клавиатуры вводятся координаты трех горизонтальных линий в произвольном порядке (т.е. линия, координаты которой были введены последними, может
быть между двумя другими). Напишите программу, которая всегда окрашивает самую верхнюю линию в красный цвет, следующую - в зеленый и последнюю - в желтый цвета.
Оператор case Задача 6.11. Напишите программу, которая запрашивает у пользователя номер текущего месяца и сообщает время года. Рекомендуемый вид экрана: Введите номер месяца: 11 Зима.
Задача 6.12. Напишите программу, которая после введенного с клавиатуры числа (от 1 до 999), дописывает слово «рубль» в правильной форме (21 рубль, 332 рубля, 890 рублей). Задача 6.13. Напишите программу, которая вычисляет дату следующего дня. Рекомендуемый вид экрана: Введите числами сегодняшнюю дату Последний день месяца! С наступающим новым годом! Завтра 1.1.2005
44
(число месяц год):31 12 2 0 0 4
Гпава 7
Циклические конструкции Иногда для решения задачи нужно выполнить одно и то же действие несколько раз подряд. К примеру, для того чтобы вывести на экран строку «НеПо world!!!» десять раз, можно дать компьютеру столько же команд, используя функцию printf(), а можно дать одну команду «повторить printf() десять раз». Решение многих задач содержит повторяющиеся действия. В языке С++ предусмотрены операторы повторения, которые называются циклами. Применение циклов в программе позволяет эффективно использовать ресурсы компьютера, сокращает длину программы и время на ее составление. Для удобства программирования в языке предусмотрены три вида операторов цикла: for - оператор цикла с параметром. while - оператор цикла с предварительным условием (предусловием); do while - оператор цикла с последующим условием (постусловием); Для всех трех видов операторов цикла характерно следующее: • повторяющиеся действия записываются всего лишь один раз; • необходимо предусмотреть выход из цикла или по естественному его окончанию, или с помощью оператора break. Если этого не предусмотреть, то циклические действия будут повторяться бесконечно. В этом случае говорят, что "программа зациклилась".
Оператор цикла for
»
Когда заранее известно, сколько раз компьютер должен выполнить определенный набор операций, используют оператор цикла с параметром for. Для представления циклической конструкции в блок-схемах используют блок цикл. Он представляет собой продолговатый шестигранник. По стрелке сверху мы попадаем внутрь цикла. Выполняем первоначальную установку значения переменной, которая будет отсчитывать количество выполненных шагов цикла - счетчика или параметра цикла (i = 0). Далее записываем условие, при невыполнении которого цикл будет прерван (i < 10). Проверяем выполнимость условия, и если оно истинно, идем по стрелочке вниз и выполняем операции в теле цикла. Так называют последовательность команд, выполняемых в одном шаге цикла. Дойдя до конца тела цикла, мы поднимаемся по стрелочке вверх, в заголовок цикла. Изменяем значение параметра (здесь увеличиваем на единицу) и вновь проверяем условие (i < 10). Если условие не выполняется, то выходим из цикла направо. Блок цикла с параметром. Внутри блока записываются через точку с запятой: • начальное значение параметра; • условие выполнения цикла; • изменение параметра на каждом шаге цикла.
45
Пример 7 . 1 . Составить блок-схему алгоритма, который печатает на экране 50 звездочек.
Начинается а л г о р и т м с блока "Начало". В нашем примере цикл будет выполняться до тех пор. пока п е р е м е н н а я i н е станет равна 50 (согласно условию i < 50). Начальное значение переменной-счетчика установлено в ноль. Это означает, что будет выполнено 50 шагов (от 0 до 4 9 . включая ноль). В ходе очередного этапа выполнения цикла на экран выводится одна з в е з д о ч к а , после чего компьютер возвращается в заголовок цикла и увеличивает i на единицу. Далее проверяется выполнимость условия (i < 50). И если условие истинно, то начинается новый шаг цикла. Как только условие нарушается, цикл завершается, и мы попадаем на элемент блок-схемы "Конец". Форма записи оператора for имеет следующий вид: *
for {
ъ-zzz ъ. •.
ек::е_1; ssqp а«:ение_2 ; выражение 3)
:•
for - служебное слово. Далее в круглых скобках идут выражения, разделенные точкой с запятой. := : - это инициализация параметра цикла. Иначе говоря, это выражение задает первоначальное значение переменной, по значению которой компьютер определит, следует ли продолжать выполнение цикла. гыс =.тек::5_2 - это условие выполнения цикла. Если условие истинно, то выполняются операторы циклической части программы. Если условие ложно, то происходит выход из цикла без выполнения операторов циклической части. 5ьгса:ке:-:::5_з - обычно изменяет значение параметра цикла на каждом шаге. Так, программа, описывающая блок-схему из примера 1, будет иметь следующий вид: int i; for(i=0;i<50;i++) { printf{"*"); }
s
Обратите внимание на отсутствие знака « ; » после скобок оператора for. Поставить этот знак там было бы грубой ошибкой. В этом случае переменная i увеличится до 50, но ни одна звездочка не будет выведена на экран.
Пример 7.2. Напишите программу, которая выводит сумму N чисел, введенных пользователем. /* iNSа-
int i,N,S=0,a; параметр цикла; количество чисел; сумма чисел; введенное с клавиатуры число.
*/
s c a n f & N ) ; for(i=0;i
Проследим, как меняются значения переменных, зная, что количество чисел N=3 и переменная а принимает значения 5,7 и 9. i 0 1 2
а 5 7 9
S 5 12 21
(0+5) (5+7) (12+9)
Пример 7.3. Написать программу, которая вычисляет значения yi = 2х + 1 и уг = х" при х =0, 1, 2, 3, 4. int i,yl,y2; for(i=0;i<5;i++) { yl=i*i; y2=2*i + 1; printf ("x= %i yl= %i y2=%i\n",i,yl,y2! } yi
0 1 2
0 1 4 9 16
со
i(x)
4
9-
У2 1 3 5 7 9 1 2
3
4
Выражение, описывающее шаг цикла, не обязательно должно увеличивать значение параметра цикла. В следующем примере значение параметра цикла убывает. Пример 7.4. Написать программу, выводящую на экран таблицу квадратов четных чисел от 0 до 10 в убывающем порядке. '» int i; for(i=10;i>=0;i-=2) { printf("%i %i\n",i,i*i); }
47
Результат выполнения программы: 10 8 6 4 2 0
100 64 36 16 4
Одновременно с изменением значения переменной цикла можно выполнять и другие операции. Например, нам нужны две переменные, одна из которых увеличивается на единицу, а другая уменьшается на двойку. В этом случае операторы записываются в круглых скобках через запятую. Пример 7.5. Приведенный цикл выполняется 5 раз и не зависит от значений переменной]: S
int i, j; for (i = 0, j = 1 0 ; i < 5 ; i++, j-= 2) { printf("%i %i \n", i, j ) ; }
Здесь сначала происходит инициализация переменных i и j. Далее проверяется условие выполнения цикла i < 5. Телом цикла является оператор вывода printf. Если тело цикла состоит всего лишь из одного оператора, то фигурные скобки можно не ставить. Каждый раз после вывода значений i и j на экран выполняется третье выражение, представленное двумя операциями: i++ и j = j - 2, разделеными запятой. Любое из трех выражений в цикле for может отсутствовать, однако точка с запятой должна оставаться всегда. Пример 7.5 можно записать так: int i=0, j = 10; for (; i < 5; i++, j-= 2) { printf("%i %i \n", i, j ) ; }
s
или так: int i=0, j=.10; for (; i < 5; ) { printf("%i %i \n", i, j ) ; i++; j — 2; }
Независимо от записи, результат выполнения останется неизменным. Переменные i и j во время работы цикла изменяются следующим образом: i 0
j 10
1
8
2
6
3
4
4
2
Бесконечный цикл Так называют циклическую конструкцию, в которой не пред;-л естественного завершения. Эту конструкцию цикла for( ; ; ), удобно применять, если требуется учесть условие, наступление которого не зависит от параметра цикла. К 48
примеру, в программе, запрашивающей пароль и выводящей на него приветствие, невозможно определить заранее, с какой попытки пользователь введет пароль правильно. В таких программах применяют операторы управления циклом — break и continue. Ключевое слово break прерывает выполнение цикла, a continue начинает новый шаг, не доходя до конца тела цикла. Пример 7.6. Напишите программу, запрашивающую пароль пользователя (целое пятизначное число). Если пароль правильный, то выводится приветствие и выполнение программы прерывается. Если пароль неправильный, то выводится сообщение об ошибке и вновь предлагается ввести пароль. LONG pwd=12 34 5 , pwdl; for(;;) //бесконечный цикл { printf("Введите пароль:") scanf("%I",&pwdl); if(pwdl!=pwd) // проверка пароля { printf("Неправильный пароль! Попробуйте ещё раз! \ п " ) ; continue; // вернуться в начало цикла } printf("Пароль верен! Здравствуйте! \ п " ) ; break; //прервать выполнение цикла }
В этом примере при неправильном пароле компьютер, не доходя до конца тела цикла, переходит в заголовок. Если пароль верен, то условие не выполняется и цикл прерывается. Если при работе с бесконечным циклом была допущена ошибка, то компьютер в ходе выполнения программы может перестать отвечать на внешние запросы зациклиться. В таких случаях используют сочетание клавиш Ctrl + Break. Эта команда приостановит выполнение программы и укажет строчку кода, на которой произошла остановка. Вложенный цикл. Цикл, который находится в теле другого цикла, называют вложенным. Продемонстрируем такой цикл на примере. Пример 7.7. Написать программу, которая выводит 3 ряда (по 7 элементов в каждом) случайно подобранных чисел в диапазоне от 0 до 10 и вычисляет сумму элементов каждого ряда. Рекомендуемый вид экрана: 0 2 8 3 2 7 9 3 | 3 1 5 7 0 9 3 8 | 5 8 9 0 2 4 8 7 |
34 36 43
Для того чтобы использовать в программе случайные числа, необходимо сначала инициализировать генератор случайных чисел при помощи функции randomize(), которая описана в библиотеке stdlib.h. Генерацию случайного числа выполняет функция гапёот(параметр). В качестве параметра указывают число - верхнюю границу диапазона, из которого выбирается значение (нижняя граница - ноль). # include <stdlib.h> int a,s=0; randomize(); // генератор случайных чисел for(int i=0;i<3;i++) //в этом цикле выводится каждый ряд { for(int j=0;j<8;j++)//в этом цикле выводятся элементы ряда { printf("%2i",a=random(10));
9 s+=a; } printf("I s=0;
//сумма элементов ряда %i\n",s); //если эту операцию не выполнить, то сумма //элементов предыдущего ряда будет складываться //с суммой текущего ряда
50
Задачи к главе 7. Циклические конструкции Задача 7.1. Напишите программу, которая десять раз выводит на экран текущую дату. Задача 7.2. Напишите программу, которая выводит таблицу квадратов первых десяти целых положительных чисел. Рекомендуемый вид экрана: Число 1 2 3 4 5 6 7 8 9 10
Квадрат 1 4 9 16 25 36 49
64 81 100
Задача 7.3. Напишите программу, которая вычисляет сумму первых п целых положительных четных чисел. Количество суммируемых чисел вводится во время работы программы. Рекомендуемый вид экрана: Вычисление суммы положительных четных чисел. Введите количество суммируемых чисел:12 Сумма первых 12 положительных четных чисел равна 156.
Задача 7.4. Напишите программу, которая вычисляет сумму первых п членов ряда 1,3,5,7...к. Количество суммируемых членов ряда задается во время работы программы. Рекомендуемый вид экрана: Вычисление суммы ряда 1,3,5,7...к Введите количество суммируемых членов ряда: Сумма первых 4 членов ряда равна 16.
4 , 2
Задача 7.5. Напишите программу, которая вычисляет сумму ряда '/г + /з + 3/л+-• - + N / n + i • Значение N задается во время работы программы. Рекомендуемый вид экрана: Введите значение N: 5 Сумма ряда равна 3.55
Задача 7.6. Напишите программу, которая выводит таблицу значений функции (х и у) 2 у = 5х - х + 2 в диапазоне от -1 до 1 с шагом 0,2. Задача 7.7. Факториалом числа п называют произведение целых чисел от 1 до п, при этом факториал нуля равен единице. Факториал обозначается восклицательным знаком. К примеру, 3! = 6 или 0! = 1. Напишите программу, вычисляющую факториал числа п, введенного пользователем. Рекомендуемый вид экрана: Вычисление факториала. Введите число, факториал которого нужно вычислить: 7 71 = 5040.
Задача 7.8. Напишите программу, которая проверяет навыки устного умножения чисел в диапазоне от 0 до 20. В ходе работы программы на экран выводятся 10 выражений. Элементы произведения выбираются случайным образом. Компьютер фиксирует ответы 51
пользователя и, сравнивая их с правильными ответами, выставляет оценку по шкале: 10 или 9 правильных ответов - отлично, 8 / 7 - хорошо, 6 / 5 -удовлетворительно, меньше 5 - неудовлетворительно. Рекомендуемый вид экрана: Проверка навыков устного умножения: 15 х 11 = 1 6 5 11 X 5 = 55 3 х 8 = 25 * 8 = 24 Неверно! 3 7 х 13 = 91 4 = 32 8 х 12 х 13 = 156 18 х 19 = 3 4 2 2 х 1 = 2 5 х 19 = 95 8 х 8 = 64 Результат: 9 баллов - отлично.
52
Глава 8 Операторы цикла while и do..while Если число повторений заранее неизвестно, а задано только условие повторения, используются операторы while и do...while.
Оператор цикла с предусловием while
>
Шагая по дороге к дому, мы часто не задумываемся о том, сколько шагов осталось сделать до двери подъезда. Мы делаем очередной шаг, если видим, что не можем дотянуться рукой до двери. Это типичная ситуация, которую описывает оператор цикла с предварительным условием while. В блок-схемах оператор while изображается следующим образом:
•
В ромбе записывается условие выполнения цикла. Если условие истинно, тогда мы движемся вниз и выполняем тело цикла, в противном случае - выходим из цикла. Фрагмент блок-схемы, описывающей путь от остановки до подъезда, будет иметь такой вид
В общем виде этот оператор записывается так: while
(условие) { //операторы циклической / / ч а с т и программы
}
Слово while является служебным. Каждый раз предварительно проверяется значение условия, стоящего в круглых скобках. Пока оно истинно, выполняются операторы циклической части, заключенные в фигурные скобки. Как только условие перестает выполняться, происходит выход за пределы цикла. Если с самого начала условие ложно, то операторы циклической части не выполняются ни разу. Пример 8.1. Напишите программу, которая вычисляет значения функции у = х , при х = 2, 4, 6, 8, 10. Фрагмент программы на С++: i n t х, х = 2; while
у; (х <=
10)
{ у = х * х; p r i n t f ( " П р и х = %i х = х + 2;
у = %i \ п " ,
х,
у);
}
Во время выполнения программы переменные принимают следующие значения: Значение Истина . Истина Истина Истина Истина Ложь
Условие 2<= 10 4<=10 6 <= 10 8 <= 10 10 <= 10 12 <= 10
ы
X
4 6 8 10 12
у 4 16 36 64 100 Выход из цикла
Если в циклической части стоит всего один оператор, то фигурные скобки можно не ставить, и оператор цикла принимает вид: while
(условие)
оператор;
Например: i n t п=0; w h i l e (n<10)
printf("%i",n++);
» Пример 8.2. Напишите программу, которая определяет количество знаков целого числа, которое вводится пользователем. long n,i=10,k=l; s c a n f & n ) ; while(n/i!=0)
{ k++; i*=10; } cout<
Программа последовательно делит введенное число п на 10, 100, 1000 и т.д., фиксируя количество знаков в делителе. Как только целая часть частного становится равна нулю, выполнение цикла прерывается и выводится ответ. 54
Во время выполнения программы переменные принимают следующие значения: п= 1234 i Условие (n/i!=0) Значение к 10 1234/10 ! = 0 Истина 2 100 1234/100 ! = 0 Истина 3 1000 1234/1000 ! = 0 Истина 4 10000 1234/10000 != 0 Ложь Выход из цикла
Оператор цикла с постусловием do...while Оператор do...while аналогичен оператору while, но отличается от него тем, что условие проверяется после очередного выполнения операторов тела цикла (очередной итерации), и этим гарантируется хотя бы однократное выполнение цикл. Поэтому этот оператор называют циклом с последующим условием (постусловием). В блок-схемах оператор do...while изображается следующим образом:
При входе в конструкцию сразу же выполняется тело цикла, а затем проверяется условие в ромбе. Если оно истинно, то возвращаемся на начало и повторяем все заново, иначе — выходим из цикла. Конструкция do...while состоит из заголовка do, тела и условия окончания, которое записывается в круглых скобках после ключевого слова while. В конце всегда ставится точка с запятой. do
{ //операторы циклической / / ч а с т и программы
} while
(условие);
Как и в случае с оператором while, если тело цикла содержит лишь один оператор, то фигурные скобки можно не ставить. do
оператор;
while
(условие);
Например: i n t n=0; d o p r i n t f ("% i " , n + + ) ;
while
(n<10);
Пример 8.3. Напишите программу, которая вычисляет значение функции у = х , прих = 2, 4, 6, 8, 10. Фрагмент программы на С++: i n t х, у х = 2; do
;
{ у = х * х;
\n", х, у ) ;
printf("%f,%f х += 2 ;
} while
(х <=
10);
Здесь сначала задается первое значение аргумента х = 2. Далее в теле цикла: 1. вычисляется значение у при текущем значении х; 2. значения х и у выводятся на экран; 3. вычисляется новое значение аргумента х прибавлением числа 2 к предыдущему значению х. Цикл выполняется до тех пор, пока выражение х <= 10 не станет ложным. В процессе выполнения этой части программы переменные принимают следующие значения: X
2 4 6 8 10
У 4 16 36 64 100
Условие 4<= 10 6<= 10 8 <=10 10 <=10 12 <= 10
х+=2 4 6 .8 10 12
Значение Истина Истина Истина Истина Выход из цикла
Пример 8.4. Напишите программу, которая проверяет, сколько знаков во введенном с клавиатуры числе. Если количество знаков не равно 4, то программа выводит сообщение об ошибке и предлагает ввести число еще раз. long long
п,1; i;
do { 1=1; i=10; cout<<"Введите cin>>n; w h i l e ( n / i »=0) { 1++; i*=10;
четырехзначное
число:"<<endl;
} if(11=4) c o u t « " Вы
ошиблись ! " « e n d l ;
} while(1!=4);
Этот фрагмент - пример вложенного цикла while в конструкции do...while.
s
Бесконечный цикл. Напомним, бесконечный цикл - это конструкция, в которой не предусмотрено естественного завершения. В работе с операторами цикла do...while и while зацикливание - самая распространенная ошибка начинающих. Составление условия относительно переменной, не изменяемой операторами тела цикла, неизбежно приводит к бесконечному выполнению этого цикла. Например: int i=8,n; while(i>0) n++ ; }
Если же в рамках решения задачи требуется использовать бесконечный цикл, то достаточно в качестве условия указать выражение, которое будет истинным всегда, но при этом обязательно предусмотреть вариант завершения цикла. Например: int i=0; while(1==1) { i++; if(i==8) break; }
Этот цикл будет выполняться до тех пор, пока переменная i не станет равна восьми, что приведет к принудительному завершению цикла оператором break.
57
Задачи к главе 8. Операторы цикла while и do..while Задача 8.1. Напишите программ}, которая печатает на экране узор, состоящий из звездочек, так, как это изображено на рисунке. Количество строк вводится во время выполнения программы Рекомендуемый вид экрана: Введите количество строк: * **
***** ****
***
***
i|t jfc }ft 3ft $z %
**
Вариант 1
z
***** **** *** »«
*
»
Вариант 2
Вагиант5
1
* ** *** **** *****
4
Задача 8.2. Напишите программу, которая вычисляет с у м м у среднее арифметическое последовательности положительных чисел, которые вводятся с клавиатуры Ввод чисел прекращается, когда вводится 0. Задача 8.3. Определите произведение цифр, входящих в состав числа которое вводится с клавиатуры. Количество знаков вводимого числа не ограничено. Рекомендуемый вид экрана. Введите число: Ответ: 120
12345
Задача 8.4. Игра «Угадай число». Напишите программу, которая « з а д у м ы в а е т » число в диапазоне от 1 до 10 и предлагает пользователю угадать число за 5 попыток. Рекомендуемый вид экрана. Игра «Угадай число». Компьютер «задумал» число от 1 до 10. Угадайте его за 5 попыток. Введите число. -> 5 Нет. ->3. Вы выиграли! Поздравляю!
Задача 8.5. Напишите программу, которая определяет максимальное число из введенной с клавиатуры последовательности положительных чисел (длина последовательности не ограничена). Ввод прекращается, если введен 0. Задача 8.6. В ассортименте магазина 5 наименований продукции. Напишите программу, которая запрашивает пары чисел (номер товара - количество товара). Количество пар не ограничено. Ввод прекращается, если введена пара 0 0. Цель программы - определить, на какую сумму было продано товара каждого наименования и сколько составляет дневная выручка. Рекомендуемый вид экрана. Номер 1 2 3 4 5
Наименование Хлеб Печенье Молоко Картофель Масло
Цена 8,50 34,70 9,90 11,40 20,90
Введите номер товара и его количество: 1 5 1 3 4 0
-
2 3 5 8 5 0
Результат: Номер 1 2 3 4 5
Наименование Хлеб Печенье Молоко Картофель Масло
Цена 8,50 34,70 9,90 11,40 20,90
Количество 7 0 8 5 3
Сумма 59,5 0 79,2 57 62 , 7
Итог по всем 258,4
Задача 8.7. Дано вещественное число X (|Х| < 1) и целое число N (N > 0). Вывести 2 3 N_1 N X - Х /2 + Х /3 - ... + (-1) X /N. Задача 8.8. Напишите программу, которая выводит 16 окружностей, закрашенных разными цветами. Задача 8.9. Напишите программу, которая рисует на экране круг, движущийся по экрану и отскакивающий от границ экрана. После каждого столкновения цвет круга изменяется, а скорость движения замедляется. Программа выполняется до момента полной остановки . круга. Задача 8.10. Напишите программу, которая выводит на экран изображение шахматной доски. Черные клетки изображаются звездочкой, белые - пробелом. Рекомендуемый вид экрана: *
к
к
к
•к -к * *
*
* -к -к •к к к -к
к к
к
-к •к
к
к
* к
к
к к
Задача 8.11. Напишите программу, которая выводит на экран график функции 2 у = -2.4х + 5х - 3 в диапазоне от -2 до 2. Задача 8.12. Напишите программу, которая выводит на экран узор, изображенный ниже. Такой рисунок получается при пересечении окружностей, количество которых в одной строке и одном столбце задается пользователем.
имер
Гпава
9
Массивы При написании различных программ иногда нам приходится иметь дело с большим количеством данных одного типа. Например, у нас есть семь целых чисел: 5, 10, -3, 72, 0, 27, 34 Мы можем записать эти числа в переменные: a s , v d , l o p , f, k o k , is, d d r .
Но лучше было бы придумать одно общее имя, а переменные пронумеровать (или, как еще говорят, проиндексировать), как в математике: Ао, А ь А2, А3, А4, А5, А6 В повседневной жизни мы тоже часто встречаемся с такой формой записи. В поезде, например, все места пронумерованы, а всех людей, которые едут в вагоне, можно назвать пассажирами. И обратиться к любому из них можно так: "Пассажир 2 места, предъявите билетик!". В программировании для удобства работы с данными одного типа введено понятие массива. Массив - это конечная совокупность данных одного типа, упорядоченных по значениям одного типа. Каждый элемент массива обозначается именем массива с индексом. Как же правильно записать массив? В математике, физике, химии и других точных науках можно встретить следующие формы записи: • с помощью нижних индексов: А0, АЬА2, А3, А 4, А 5, А6; • индексов заключенных в круглые скобки: А(0), А(1), А (2), А (3), А (4), А (5), А (6); • с помощью фигурных скобок:
{Ai}, 1=0,1,2, - п . В языке С++ индексация производится при помощи квадратных скобок: А [0], А [1], А [2], А[3], А[4], А[5], А[6], где А - имя массива, а число, указанное в скобках, - индекс. Обратите внимание, нумерация начинается с нуля. Если мы хотим использовать массив в программе, то необходимо его заранее объявить, как в случае с переменными. При объявлении массива нужно указать тип массива (т.е. тип хранящихся в нем переменных), имя массива и его размер. Имя массива должно быть подобрано по правилам создания имен идентификаторов. То есть в имени можно использовать только буквы, цифры и знак подчеркивания, и имя не должно начинаться с цифры. Общий дид описания массива следующий: тип
имя[количество
из int А [ 7 ] ;
,объявление
семи
элементов] ;
целых
чисел:
Так как нумерация элементов начинается с 0, то последний доступный элемент массива а[6]. В языке С++ нет контроля при обращении за пределы массива, т.е. если мы напишем а[9], то программа скомпилируется и запустится, но значение, полученное из массива, в этом случае будет не определено. На самом деле мы получим число, находящееся в памяти на 10 месте от начала массива. А так как массиву отведено только 7 ячеек памяти, то значение, записанное на 10 позиции, определить нельзя. Нужно быть внимательным при работе с массивами. Если попытаться записать данные за пределы массива, то можно уничтожить другую информацию, хранящуюся в памяти. Если это окажутся системные данные, то работа операционной системы и других 60
программ может быть нарушена. Часто неправильная индексация массива приводит к зависанию ОС или даже к ее перезагрузке. Можно описать сразу несколько массивов одного типа: int а[10], b[17], с [ 5 0 ] ; char str[40], c h [ 5 ] ;
Размер массива (т.е. количество его элементов) должен быть задан целым положительным числом или числовой константой. Запись вида: int i ? int m a s [ i ] ;
недопустима, так как i - это переменная, и компилятор не знает заранее, сколько памяти необходимо выделить для массива. Правильное описание имеет вид: * const int n = 10; int m a s [ n ] ; ИЛИ
int m a s [ 1 0 ] ;
При описании массива его можно сразу инициализировать, т.е. задать всем элементам начальные значения: double arg[3] = {3.56, 7.32, - 0 . 0 1 } ;
В этом случае arg[0] = 3.56, arg[l] = 7.32, arg[2] = -0.01. При инициализации размер массива можно не указывать (он автоматически определяется путем подсчета количества перечисляемых значений): char str[]
= {'а','b','с','m','е','f'};
Под массив str будет выделено 6 байт, т.к. каждый его элемент занимает 1 байт (тип : char), а их всего шесть. И str[0] = а', str[l] = 'b', ... str[5] = Т. Элементы массива могут стоять как в левой, так и в правой части оператора присваивания и в выражениях. То есть их можно использовать точно так же, как и переменные: Ь[3] = Ь[5] + 1; sum += a [ k ] ;
*
f1 = mas[2 * i + 1] ;
Для последовательного обращения к элементам массива удобно использовать циклические конструкции. Пример 9.1. Фрагмент программы, цель которого - заполнить массив значениями, которые вводит пользователь. int i; int m a s [ 1 0 ] ; for( i = 0; i < 10; i++ ) scanf(
&mas[i] );
Пример 9.2. Фрагмент программы, цель которого - вывести массив значений на экран: int i; int mas[10] ; for( i = 0; i < 10; i++ ) printf{ " % i " , mas[i] );
Пример 9.3. С клавиатуры вводятся значения массива, состоящего из 5 элементов. Найдите сумму всех элементов массива, а также первый максимальный элемент массива и его номер. Решая эту задачу, следует обратить внимание на то, что условие требует нахождения именно первого максимального значения, так как их может быть несколько. К примеру, если все элементы массива меньше 9, а элементов со значением 9 два, то необходимо вывести номер элемента, введенного раньше. 61
int A[5],i,Summa=0,pos,max;//i - параметр цикла //Summa - здесь будет храниться сумма //max - максимальное значение среди элементов //pos - номер элемента for( i=0;i<5;i++) //блок ввода элементов массива { scanf("%i",&A[i]); } max = A[0];//предположим, pos=0; for(
что максимальный элемент введен первым
i=0;i<5;i++)
{ 8
Summa+=A[i]; if (A[i] > max )//если текущий элемент по значению больше, чем { //максимальный, то max=A[i]; //изменяем значение максимума и pos=i+l; // запоминаем его номер } printf("CyMMa=%3i Максимальное значение=%31 номер=%31\п",Summa,max,pos);
Многомерные массивы Массивы, с которыми мы работали до сих пор, содержали только одну строку такие массивы называются одномерными. Но язык С++ позволяет создавать п-мерные массивы. К примеру, двумерный массив можно интерпретировать как матрицу. Каждая ячейка матрицы задается двумя индексами - номером столбца и строки. Трехмерный массив можно представить в виде куба. В нем уже будут три индекса - столбик, строчка и ряд. Пересечение соответствующих значений - ячейка в виде маленького куба, в котором хранятся данные. Массивы данных, описываемые более чем одним индексом, называют многомерн ым и.
Объявление многомерного массива производится следующим образом: тип
имя [размер!] [размер 2] ... [размер N ] ;
Например, чтобы объявить массивы, изображенные на рисунке, достаточно написать: int а[б][б ]; double b[4][4][4];
Двумерный массив можно рассматривать как массив массивов. Действительно, каждая строчка - это одномерный массив. А матрица - это массив таких строчек. Чтобы обратиться к любому элементу массива, мы должны указать номер строчки, а затем номер позиции в строчке (столбец).
имя массива [номер строки ] [номер столбца] Например: а[0][0] = 10; a[j][i] = a[i][j] + 4; z = a[3][4]++;.
С трехмерным массивом ситуация аналогичная. Это есть не что иное, как массив таких матриц, выстроенных рядом. Добавляется еще одно измерение - номер матрицы. Обращение к элементам такого массива задается тремя индексами: Ь[3][0][1] = 3.14; f = b[i][j][k] + b[i][j][k]; b[0][0][3] *= 7.34;
По аналогии можно определить массив с любой размерностью (лишь бы памяти хватило). Данные "кубики" можно раздать студентам, и получится 4-мерный массив: новый индекс - номер студента. Студенты сидят в разных классах - номер класса - еще один индекс - в итоге получается 5-мерный массив. На каждом этаже института несколько таких классов. Номер этажа - еще одно измерение. Получили 6-мерный массив. И так можно продолжать бесконечно долго. Теперь, чтобы найти значение в определенном "кубике", надо задать номер этажа, номер класса на этом этаже, номер студента, сидящего в этом классе, а также номер столбца, строчки и ряда в его "кубике". Но на практике редко используются массивы с размерностью больше двух. При объявлении многомерного массива, его элементам так же можно задать начальные значения: int mas[2][3] = {{7, 6, 33}, {-4, 56, 0 } } ; int arr[][] = {{4, 5, 7 } , {2, 4, 6 } } ;
Для хранения массива выделяется непрерывный участок памяти. Если мы объявили двумерный массив целых чисел int а[2][3], то элементы этого массива будут лежать в памяти последовательно следующим образом: а[0][0], a[0][lj, а[0][2], а[1][0], а[1][1], а[1][2]. Обратите внимание на то, что быстрее всего изменяется самый правый индекс у массива. Двумерные массивы обычно обрабатываются во вложенных циклах. Управляющая переменная внешнего цикла - первый индекс массива (изменяется медленно), а управляющая переменная внутреннего цикла - второй индекс массива (изменяется быстро). Например: int i, j ; int bob[10][20]; for(i = 0; i < 10; i++) { //тело цикла_1 for(j = 0; j < 20; j++) //оператор тела цикла_1 p r i n t f Г %3i " , b o b [ i ] [ j ] ) ; //тело цикла_2 printf(" \ n " ) ; //оператор тела цикла_1 }
Этот фрагмент выводит на экран массив bob в виде матрицы. Для каждого значения переменной i выполняется 20 раз тело внутреннего цикла, т.е. выводится i-ая строка массива. Далее каждый раз после завершения этого цикла переходим на новую строку на экране, и для следующего значения переменной i повторяем те же действия. Пример 9.4. Напишите программу, которая заполняет массив размером ЮхЮ значениями из квадрата Пифагора - таблицы умножения, а потом выводит его на экран. /* Таблица умножения*/ const int n = 10; // размерность массива int a[n][n], i, j ; for(i = 0 ; i < n; i++) forfj = 0; j < n; j++) a[i][j] = (i + 1) * (j + 1 ) ; // заполнение таблицы умножения
63
for(i
= 0 ;
i <
n;
i++)
{ f o r ( j = 0 ; j < n; printf("%4i", a[i][j]); printf("\n") ;
//
вызол :.;а";:з =
:-:a
зксан
}
В работе с матрицами различают главную и побочную диагонали. Так. в матрице: 1 2
3
числа 1, 6 и 0 (они выделены жирным) составляют главную диагональ. а числа 3, 6 и 8 (они выделены курсивом) - побочную.
5 6 1 # 9 0
Пример 9.5. Напишите программу, цель которой - в квадратной м а т р и ц е размером 5x5 элементов, заполненной случайными значениям, п о п е в а т ь м е с т а м и главную fi побочную диагонали. /*
Меняем в м а т р и ц е м е с т а м и д и а г о н а л и */ c o n s t i n t n = 5; // р а з м е р матрицы i n t a [ n ] [ n ] , i , j , tmp; randomize(); for(i = 0 ; i <
n;
i++)
{ for(j {
=
a
0;
j
< n;
j++)
=
[i][j] random(100); p r i n t f ("%3i", a [ i ] [ j ] ) ;
// з а п о л н я е м « а т р е щ у сщучамньми числами // и сразу же печатаем ее экран
} printf("\п");
} for(i
= 0 ;
i <
n;
i++)
{ ?. - е с е м е н н о й t m p
tmp = a [ i ] [ i ] ; a[i][i] = a[i][n-i-1]; a [ i ] [ n - i - 1 ] = tmp;
•
на диагонали
}
»
64
в
Задачи к главе 9.Массивы Задача 9.1. Напишите программу, в ходе выполнения которой с клавиатуры вводится одномерный массив из 7 целых чисел и выводится количество ненулевых элементов. Перед вводом каждого элемента на экране должна появляться подсказка с его номером. Задача 9.2. Напишите программу, которая выводит минимальный элемент введенного с клавиатуры одномерного массива целых положительных чисел. Если введен 0, то программа останавливает ввод и требует ввести вместо нуля любое положительное число. Задача 9.3. Напишите программу, которая вычисляет среднее арифметическое ненулевых элементов введенного с клавиатуры одномерного массива. С клавиатуры вводится количество элементов и сами элементы массива целых чисел. Рекомендуемый вид экрана: Введите количество элементов массива: 3 Введите элементы массива: А[0]->1 А[1]->0 А[2]->2 Количество ненулевых элементов массива: 2 Среднее арифметическое ненулевых элементов массива:
1.5
Задача 9.4. Напишите программу, которая проверяет, находится инициализированном в программе массиве введенное с клавиатуры целое число. Рекомендуемый вид экрана:
ли
в
Массив: 12 3 4 5 8 9 Введите число: 5 Такое число есть среди элементов массива.
Задача 9.5. Напишите программу, которая проверяет, образуют ли элементы введенного с клавиатуры целочисленного массива возрастающую последовательность. ь
Задача 9.6. Напишите программу, которая переставляет элементы введенного с клавиатуры целочисленного массива в убывающем порядке. Массив состоит из десяти элементов. Задача 9.7. Напишите программу, которая вводит с клавиатуры двумерный массив и вычисляет сумму элементов по строкам и столбцам. Задача 9.8. Напишите программу, которая позволит пользователю вводить матрицу так, как он записывал её на бумаге. Количество строк и столбцов матрицы вводятся во время выполнения программы. Рекомендуемый вид экрана: Введите количество строк матрицы: Введите количество строк матрицы: Введите элементы матрицы: <очистка экрана> 1 2 3 4 5 6 7 8 9
3 3
Задача 9.9. Напишите программу, которая меняет местами элементы квадратной матрицы размера 4x4 относительно главной диагонали. Элементы матрицы вводятся с клавиатуры.
Задача 9.10. Напишите программу, которая обменивает местами две строки квадратной матрицы. Номера строк и элементы массива вводятся с клавиатуры. Задача 9.11. Напишите программу игры «Угадай число». Компьютер «загадывает» трехзначное число, а пользователь пытается угадать его. На каждом шаге угадывающий делает предположение, а компьютер выводит, сколько цифр угадано и сколько из них находятся на своем месте. Рекомендуемый вид экрана: Компьютер «задумал» трехзначное число. Отгадайте его. Для завершения игры введите число - 1 . 123 Угадано: 0 На своих местах: 0 Ваш вариант 654 Угадано: 2 На своих местах: 2 Ваш вариант 954 Угадано: 1 На своих местах: 1 Ваш вариант 658 Угадано: 3 На своих местах: 3 Ваш вариант *** Вы выиграли !***
Задача 9.12. Напишите программу, которая выводит на экран рисунок, получаемый при соединении линиями пяти точек. Координаты точек вводятся пользователем. Задача 9.13. Используя двумерный массив, напишите программу, которая перемещает треугольник по экрану. Координаты вершин треугольника вводятся пользователем.
9
Гпава
10
Строки и указатели Текст как этой, так и любой другой книги представляет собой определенную последовательность слов. Каждое слово есть последовательность букв. Исходя из этого, можно сказать, что буквы являются наименьшей единицей представления информации, то есть для хранения и обработки текстовой информации люди используют буквы. Компьютер, напротив, для обработки любой информации использует числа и не знает другого языка, кроме языка цифр. Для того чтобы связать две различные системы представления информации и таким образом обеспечить эффективное взаимодействие пользователя и машины, были предложены таблицы, в которых буквы и специальные символы (точка, тире, запятая и т.д.) имеют числовой эквивалент. В попытке стандартизации представления символов большинство производителей компьютеров проектируют их так, чтобы использовать одну из наиболее популярных кодирующих схем - ASCII (см. таблицу ASCII-кодов, Приложение 1). ASCII означает «Американский стандартный код для информационного обмена» («American Standart Code for Informational Interchange))). Существуют и другие схемы кодирования. ASCII часто называют символьным кодом или символьным набором. Манипуляции символами на самом деле подразумевают манипуляцию соответствующими численными кодами, а не самими символами. Это объясняет взаимозаменяемость символов и малых целых (тип char) в С++. Символьные переменные объявляются как и любые другие переменные С++: char a,b,c;
Переменная инициализируется символьным значением, заключаемым в одиночные кавычки, или целочисленным значением, входящим в диапазон типа char: char symb='A' ;
или так:
s
char symb = 65;
Инициализируя символьные переменные, следует учитывать регистр символов (прописная «А» и строчная «а» имеют различный код в таблице ASCII) Самый простой способ ввода символов - чтение по одному символу с клавиатуры с помощью функции gercharQ. Она описана в библиотеке stdio.h и имеет вид: int getchar();
Функция возвращает значение целого типа. Это число можно интерпретировать как ASCII-код введенного символа. Для того чтобы узнать, какой символ был введен с клавиатуры, необходимо объявить переменную целого типа (или типа char) и записать в нее результат, возвращаемый функцией: char ch; ch = getchar ( ) ;
Чтобы выводить символы на экран, используют функцию putchar(), которая описана в библиотеке stdio.h. Например: putchar (ch); — выводит символ, записанный в переменную ch. putchar (6 8 ) ; — выводит символ с ASCII-кодом 68. Это буква 'А'.
putchar(32+4) ; — выводит символ с ASCII-кодом 36. Это '$'
Заметим, что для функции getchar() после выбора символа необходимо нажать клавишу <Enter>. Иногда это создает определенные неудобства. Функции getch() и getche() устраняют их. Они имеют следующий вид: int getch(); int getche() ;
Обе эти функции вводят символ сразу же после нажатия клавиши (здесь не надо нажимать клавишу <Enter>). Отличие между ними заключается в том, что getcheQ отображает вводимый символ на экране дисплея, a getch() - нет. Описания этих функций находятся в файле conio.h. Также символы можно вводить и выводить, используя функции scanf(): char symb; scanf("%c",&symb);
и printf(): char symb='A'; printf("%c - %i
",
symb,
symb);
//эта функция выведет
символ и его
код.
Так как имеет смысл говорить, что один численный код больше, меньше или равен другому численному коду, стало возможным сопоставлять различные символы друг с другом. Пример 10.L Напишите программу, которая посимвольно считывает текст, введенный с клавиатуры, и считает количество букв п в нем независимо от регистра. Условием окончания цикла является проверка введенного символа на код 13 (код клавиши <Enter>). int counter = 0 ; char ch = ' ' ; while (ch 1= 13)
// счетчик буквы "N" /./ буква текста
{
» ch = getche(); if(ch == 1 N 1 || ch == counter++;
1
n')
} printf("\n Количество букв 'N' в тексте = %i \n", counter);
Пример 10.2. Вывести на экран все прописные буквы латинского алфавита. Поскольку прописные буквы латинского алфавита упорядочены, то можно составить следующий код: char ch; for(ch = 'A'; ch <= 'Z'; ch++) putchar(ch);
Строки определяются как массивы символов, то есть массивы типа char. При хранении строки последним ее символом является специальный символ с ASCII кодом 0, передаваемый как '\0'. Он не отображается на экране, однако хранится в последней ячейке, поэтому длина массива для хранения строки должна на единицу превышать ее длину. Если создать массив типа char определенной длины, например: char str[80];
то в нем можно будет сохранить строку любой длины, не превышающей 79. Поместить строку в массив можно либо посимвольно (при этом не забыть про нулевой символ в 68
конце), либо с помощью стандартных функций. Также можно разместить строку при создании массива, например: char str[6] = {
У
Е','е','1','1','о'};
либо так: char str[6]
= "Hello";
Как и в случае обычных массивов, здесь можно написать так: char str[] =
{
Х
Н','е','1','1',
'о' };
либо так: char str[]
= "Hello";
В памяти элементы строки будут храниться, как показано на рисунке: STR[
0]
/ н
е
/ 1
1
0
\0
Однако и в этом случае длина массива определяется при его создании, и разместить в этом массиве более длинную строку не удастся. Поэтому рекомендуется создавать строки максимальной длины, то есть в 255 символов, даже если первоначально в нее записывается более короткая строка. В этом случае «лишние» ячейки будут выделены, но не будут использоваться, а в дальнейшем это позволит избежать многих проблем. Итак, рекомендуемый способ создания массива примерно такой: char s t r [ 2 5 5 ]
= "";
для изначально пустой строки и:
char s t r [ 2 5 5 ] = " С т р о ч к а т е к с т а " ;
для непустой строки. Пример 10.3. Напишите программу, которая выводит первое слово введенного с клавиатуры предложения. int i=0; char symb[255]; scanf("%s",&symb); while(i! = ' ' ) {
ь
printf("%c",symb[i]); i++; }
Пример 10.4. Напишите программу, которая заменяет строчные буквы их прописными эквивалентами. int i=0; char str[255 ] ; scanf("%s",Sstr); while(str[i]! = ' \ 0 ' ) { if(str[i]>='a') str[i]-=32; / / с о г л а с н о т а б л и ц е A S C I I , р а з н и ц а между i++; // с т р о ч н ы м и и п р о п и с н ы м и б у к в а м и - 32 с и м в о л а } printf("%s",str);
Строки также можно вводить-выводить, используя функции библиотеки stdio.h: gets() - ввести строку: char str[120 ] ; gets(str);
и puts() - вывести строку: char str[120]; puts(str);
69
,
Указатели Все данные, которые используются в программе, хранятся в памяти компьютера. Память, в свою очередь, разбита на ячейки по 8 бит (т.е. по 1 байту), и каждая ячейка имеет свой адрес, который задается целыми числами в порядке возрастания. В языке С++ есть возможность обращаться к данным в оперативной памяти компьютера напрямую, т.е. через адрес ячейки памяти. Во многом благодаря этой возможности язык и получил столь широкое распространение среди программистов. Для работы с адресами памяти в языке вводится особый тип переменных указатель. Указатель - это переменная, которая может хранить в себе адрес памяти другой переменной (массива, функции, объекта). Как и другие переменные, указатели должны быть объявлены до их использования в программе: тип
*имя;
Здесь т и п определяет тип объектов, адреса которых могут храниться в указателе, и м я имя указателя. Указателю может быть выбрано любое имя в соответствии с правилами создания идентификатора. Перед именем ставится звездочка, что и является отличительным признаком указателя: * int *а, *Ь, char *d;
*с;
Объявление char *d говорит о том, что значение, записанное по адресу d, имеет тип char. Чтобы записать адрес некоторой переменной в указатель (или, как говорят, заставить указатель «смотреть» на эту переменную), нужно перед именем переменной поставить операцию & (взятие адреса), а полученный результат присвоить указателю: int х ; int *р; Р = &х;
Теперь указатель р будет хранить в себе адрес переменной х. Операцию & нельзя применять к константам и выражениям; конструкции вида &(х + 5) или &27 недопустимы. Как, зная адрес, узнать, какое значение находится по этому адресу? Для этих целей определена операция *. Иногда ее называют проходом по адресу. Если перед указателем поставить звездочку, то возвращаемым значением будет число, хранящееся по адресу, записанному в указателе. Например, если р = &х; у = *р; то у = х. Указатели могут встречаться и в выражениях. Если р - указатель на целое, т.е. имело место объявление int *р;, то *р может появиться там же, где и любая другая переменная, не являющаяся указателем. Таким образом, следующие выражения вполне допустимы: *р = 7; *т *= 5; (*д)++;
Первое из них заносит число 7 в ячейку памяти по адресу р, второе увеличивает значение по адресу m в пять раз, третье добавляет единицу к содержимому ячейки с адресом g. В последнем случае круглые скобки необходимы, т.к. операции * и ++ с одинаковым приоритетом выполняются справа налево. В результате если, например, g = 5, то (*g)++ приведет к тому, что *g = 6, a *g++ всего лишь изменит сам адрес g (операция ++ выполняется над адресом g, а не над значением *g по этому адресу). Указатели можно использовать как операнды в арифметических операциях. Если р - указатель, то операция р++; увеличит его значение; теперь оно является адресом следующего элемента. Указатели и целые числа можно складывать. Конструкция р + п (р - указатель, п - целое число) задает адрес n-го объекта, на который указывает р. Это справедливо для любых объектов (int, char, float и т.п.). *
Как связаны массивы и указатели? Как уже было описано выше, адрес конкретной ячейки вычисляется компилятором, к я из адреса первой ячейки, то есть начала массива, индексов и размера базового типа, что очень похоже на арифметику указателей. На самом деле, массивы и указатели это практически одно и тоже. С одной стороны, чтобы получить адрес массива можно взять адрес первой его ячейки, с другой стороны, имя массива без квадратных скобок само по себе является указателем на массив. Полученный тем или иным способом адрес массива можно присвоить указателю на тот же тип, который является типом данного массива. После этого можно обращаться к любому элементу массива, увеличивая или уменьшая в рамках арифметики указателей значение указателя на требуемое количество ячеек. С другой стороны, любой указатель, даже если он хранит не адрес массива, можно индексировать с помощью квадратных скобок, таким образом получая смещение на то количество байт, которое дает произведение индекса на размер типа указателя. Итак, пусть имеется массив: int arr[4] = {1,2,3,4};
и указатель: int *р;
Тогда указателю можно присвоить адрес массива:
*
р = &агг[0];
или так: р = агг;
После этого можно вывести на экран значение третьей ячейки массива, ее индекс равен 2: printf("%i ", arr[2]); либо т а к : printf("%i ", * (р+2)); либо даже т а к : printf("%i ", р [ 2 ] ) ;
Пример 10.5. В ходе выполнения программы объявляется целочисленный массив агг [ 4 ] и указатель р, после чего указателю присваивается адрес начала массива, что позволяет далее обращаться к элементам массива агг, используя идентификатор указателя, так, как если бы был объявлен массив с именем р. int агг[4] = {1,2,3,4}; int *р; р=агг; p r i n t f ( " % i %i %i \n", a r r [ 2 ] ,
*(p+2),
p[2]);
В результате выполнения программы будет выведено три тройки. Строки можно определять через указатели, только в этом случае необходимо сразу же присваивать им начальное значение, иначе программа может выдавать удивительные результаты, так как длина строки не будет изначально определена. Естественно, даже при инициализации не всегда можно поручиться, что строки большей длины, чем начальная, будут корректно обрабатываться. Тем не менее, такой способ тоже имеет право на существование. Так строка: char
*s="hello";
полностью эквивалентна char
s[]="hello";
Как и в случае с обычными массивами, такой указатель можно изменять с использованием арифметики указателей. Тогда размер строки будет увеличиваться или уменьшаться, то есть либо в строку не будут входить первые символы, либо в качестве первых будут выдаваться символы, соответствующие данным, расположенным в памятки до строки, а только затем остальная строка. Важно понимать, что признаком конца строки является символ '\0', поэтому ее длина определяется компилятором автоматически, а не
прописывается в первой ячейке, как это делается в некоторых других языках программирования. Кроме того, такой указатель тоже можно индексировать, используя квадратные скобки. > Например: char str[255]; printf("Введите строчку текста: " ) ; scanf("%s", & s t r ) ; printf("Строка равна = %s \n", s t r ) ; printf("Третья буква = %c \n", str[4]); printf("Сдвинем указатель вправо на один символ % s " ,
str + 1 ) ;
На экране появится приглашение ввести строку. Пусть введено слово "Hello". Компьютер выведет на экран "Hello", затем пятую букву этой строки 'о'. Последний оператор вывода будет печатать строчку str, начиная со 2-го символа ('е') и до конца строки ('\0'). В нашем случае на экране появится: "ello". При вводе строки в функции scanf необходимо указывать адрес памяти, начиная с которого будет записываться вводимое значение. Но т.к. имя массива - str - является одновременно адресом начала строки, то вместо записи scanf("%s", &str[0]) можно написать проще: scanf("%s", &str). Обратите внимание на то, что спецификатор ввода/вывода для строки - %s, в то время как для символа %с. Пример 10.6. Напишите программу, которая просит ввести пароль, содержащий любые символы, что резко уменьшит шансы подобрать этот пароль const char password[] = "u8h5nkv888"; // строка-пароль char pass[255]; // вводимая строка do { printf("Введите пароль : " ) ; scanf("Is", &pass); } // пока pass не равна строке while(strcmp(pass, password) != 0 ) ; // password, выполняем цикл printf("Добро пожаловать в систему ! \ п " ) ;
В программе использована новая функция strcmp(strl, str2), которая умеет сравнивать две строки посимвольно. Если строчки равны, то она возвращает ноль. Если бы мы написали просто while(pass != password), то тогда бы получился бесконечный цикл, т.к. в этом случае сравниваются указатели, т.е. адреса начала строк passs и password. А они, конечно же, имеют разные значения. Функции для работы со строками определены в заголовочном файле string.h, который подключается в начале программы. Среди них стоит отметить: 1. strcpy(sl,s2) - копирует строку s2 в массив s i . Возвращает строку s i ; 2. strucpy(sl,s2,n) - копирует не более п символов из s2 в s i . Возвращает строку s i ; 3. strcat(sl,s2) - объединяет строку s2 и si. Возвращает строку s i ; 4. strcmp(sl,s2) - сравнивает две строки si и s2; 5. strlen(sl) - возвращает длину строки s i ; 6. s3 = strstr(sl,s2) - строка s3 содержит все символы строки si начиная от той позиции, где впервые встречается строка s2. *
Пример 10.7. Напишите программу, которая объединяет слова «Российская» и«Федерация» в одно предложение. При этом важно, чтобы переменные, в которых хранятся слова, сохранили свои значения. * char result[255]; 1 char space = \ sl[] = "Russian", strcpy(result,s1); strcat(result, s p a c e ) ; strcat(result, s 2 ) ; printf("%s\n", r e s u l t ) ;
73
s2 = "Federation";
Задачи к главе 10. Указатели и строки Задача 10.1. Напишите программу, которая спрашивает имя пользователя, а потом выводит личное приветствие. Рекомендуемый вид экрана: Как Ваше имя? Вася Здравствуйте, Вася!
Задача 10.2. Напишите программу, которая выводит на экран всю таблицу ASCII по 15 символов. Очередная группа символов появляется при нажатии пользователем любой клавиши. Задача 10.3. Напишите программу, которая выводит код клавиши, нажатой пользователем. Программа выполняется до тех пор, пока не нажата клавиша <Esc>. Задача 10.4. Напишите программу, которая переставляет символы введенного слова в обратном порядке. Рекомендуемый вид экрана: , Введите слово: поезд дзеоп
Задача 10.5. С клавиатуры вводится полный путь к файлу. Напишите программу, которая выделяет из этой строки имя файла Рекомендуемый вид экрана: С:\windows\system32\activeds.dll activeds.dll
Задача 10.6. Напишите программу, введенного пользователем. Рекомендуемый вид экрана:
которая выводит второе слово
предложения,
Сидоров Петр Иванович Петр
Задача 10.7. Напишите программу, которая проверяет, является ли введенная с клавиатуры строка целым числом. Рекомендуемый вид экрана: 27,5
Введенная строка не является целым числом
s
Задача 10.8. Напишите программу, которая определяет, есть ли в строке введенное пользователем слово. Рекомендуемый вид экрана: Введите строку: Организация Объединенных Наций Введите слово: наций Такое слово присутствует в строке Введите слово: нац Такого слова в строке нет
Задача 10.9. Напишите программу, которая удаляет из строки все пробелы.
Гпава
11
Функции Вы обращали внимание на тот факт, что в текстах песен припевы не пишут каждый раз после очередного куплета, а, написав только один раз, далее в песне просто печатают слово «припев». В программировании также часто приходится иметь дело с повторяющимся кодом. И чтобы не заниматься бессмысленным его размножением, достаточно один раз описать данный участок кода в виде отдельной функции, а далее, в местах, где необходимо выполнить данный код, просто вызывать эту функцию. У функций есть очень много преимуществ: во-первых, сокращается код программы. Во-вторых, такая программа состоит из вызовов функций, по названию которых можно определить выполняемые ими действия. Такую программу легче читать. Отладив один раз функцию, вы можете ее использовать вновь и вновь, уменьшая этим риск возникновения ошибок и опечаток. В-третьих, функции можно собирать вместе для создания целых библиотек, которые мы подключаем в начале файла с помощью директивы #include. При создании своих функций необходимо соблюдать следующие правила: 1. Функция не может быть описана внутри другой функции. В языке С++ вс,е функции глобальны. 2. Каждая функция имеет тип возвращаемого значения, имя, список входных параметров и тело функции. 3. Имя функции должно быть выбрано согласно правилам создания идентификаторов. Целесообразно отразить в имени функции те действия, которые она выполняет. Например, если вы написали функцию возведения в куб, то неразумно ее называть Vasja(), даже если автор ее Вася. Более подходящее для нее имя Cube(). 4. Функция должна быть описана перед главной функцией main() или иметь прототип. Описание функции в программе имеет вид: /* о п и с а н и е функции */ т и п имя__функции ( п а р а м е т р ы ) тело
функции;
}; /* о с н о в н а я функция main()
*/
{ тело
функции m a i n ;
}
Сначала идет описание функции с указанием типа возвращаемого значения, именем функции и передаваемыми ей параметрами. Далее в фигурных скобках записывается тело функции - те действия, которые часто встречаются в программе. Выполнение программы всегда начинается с функции main. В программе может быть только одна функция main(). Внутри нее и происходят вызовы описанной нами функции.
Пример 11.1. Напишите программу, в которой описана функция, выводящая 10 звездочек. #include <stdio.h> #include
'
void Stars()
// описание функции Stars
{ int i; for (i = 0; i < 10; i++) putchar(); printf ("\n") ;
// объявление локальной переменной
}; void main()
// главная функция - начало выполнение программы
{ clrscr(); Stars (); // вызов функции Stars() printf("Привет, Вася ! " ) ; Stars ( ) ; // вызов функции Stars() }
Здесь мы описываем функцию Stars(), которая печатает 10 звездочек и переходит на новую строку. Эта функция ничего не возвращает. Для таких случаев предусмотрен тип void - ничто. Далее в круглых скобках указываются входные параметры функции. Их тоже нет, но круглые скобки обязательны. Внутри функции могут быть определены свои внутренние или локальные переменные. Они доступны только внутри функции и никак не пересекаются с переменными в функции main(). Поэтому если в main() уже есть такая же переменная целого типа i, то компилятор поймет, что это разные переменные и не спутает их. Давайте сделаем нашу функцию Stars() более универсальной: хотелось бы, чтобы она печатала каждый раз не по 10 звездочек, а столько, сколько ей скажут. Для этого можно завести глобальную переменную п, которая описывается вне всех функций, - в самом начале. Её значение доступно из любой части программы. Итак: int п; void Stars ()
{
,
,
int i; for (i = 0; i < n; i++) putchar( 1 * ' ) ; printf("\n"); };
// описание глобальной переменной // описание функции Stars() // объявление локальной переменной // цикл: вывести n звездочек
15
void main() // главная функция - начало выполнение программы { clrscr(); n = 5; Stars(); // вызов функции Stars() 'printf("Привет, Вася ! " ) ; n = 15; Stars(); // вызов функции Stars() }
Перед каждым вызовом функции Stars() мы присваиваем переменной п определенное значение, которое обозначает количество выводимых звездочек на экран. Программа стала более универсальной, но можно сделать еще лучше. Сейчас мы
привязали нашу функцию к глобальной переменной п, что, честно говоря, нехорошо. Представьте такую ситуацию: вы написали функцию и включили ее в библиотеку. Программисту достаточно подключить библиотечный файл с помощью директивы dude, и он сможет пользоваться вашей функцией. Но он ничего не знает про глобальную переменную п и, соответственно, как задать количество звездочек. А есщ функции нужно задать несколько параметров, то для каждой заводить глобальную переменную? Для этих целей предусмотрен механизм передачи параметров внутрь функции. В описании функции мы указываем, сколько каких типов и под какими именами передаются параметры внутрь функции. А при вызове функции в круглых скобках указываем передаваемые значения. Ими могут быть числа, переменные, константы, результаты других функций и т.д. Перепишем наш пример: / / о п и с а н и е ф у н к ц и и Stars()
void Stars(int n ) { int i ; for (i = 0; i < n; putchar(**'); printf("\n"); };
i++)
объявление локальной переменной цикл: вывести n з в е з д о ч е к
// г л а в н а я функция - н а ч а л о выполнение программы
void main() { int z = 7; clrscr(); Stars(5); printf("Привет,
// //
с параметром
//
Вася
Stars(z + 3 ) ;
описание
локальной
переменной
z
/ / в ы з о в ф у н к ц и и Stars() ! " ) ;
с параметром 5
/ / в ы з о в ф у н к ц и и Stars()
с п а р а м е т р о м 10
}
В заголовке функции Stars() написано, что функция при вызове будет требовать в качестве параметра целое число, которое запишется в переменную п. Такую переменную еще иногда называют формальным параметром. Цикл внутри функции выполнится п раз, после чего переменная п будет уничтожена. При новом обращении к функции Stars() указывается новое значение входного параметра. Зачастую функция выполняет какие-нибудь расчеты, и результат этих вычислений нужно вернуть обратно в программу. Тип результата, вырабатываемый функцией, указывается при ее описании перед именем функции. После выполнения всех расчетов значение возвращается с помощью оператора return. в Пример 11.2. Напишите программу, в которой описана функция, возводящая в квадрат число, введенное с клавиатуры. float Square(float х)
// о п и с а н и е ф у н к ц и и Square()
с параметром
{ float res; res = х * х; return res; }; void main() { float a, b, с; // о п и с а н и е л о к а л ь н о й п е р е м е н н о й z clrscr{); a = 5.5; b = Square(a); // в ы ч и с л я е м к в а д р а т ч и с л а a с = Square(b + 3 ) ; // в ы ч и с л я е м к в а д р а т ч и с л а b + 3 p r i n t f ( " Р е з у л ь т а т в ы ч и с л е н и й = %.2f", с ) ; }
Описанная функция Square() имеет один входной параметр типа float. Это значение записывается внутри функции в переменную х. Локальной переменной res присваивается квадрат значения х. С помощью оператора return это значение «подставляется» вместо функции Square(). Функции может быть передано несколько параметров (тогда они перечисляются через запятую), но возвращает она только одно значение. Пример 11.3. Напишите программу, в которой описана функция, цель которой состоит в вычислении среднего арифметического двух чисел, введенных пользователем. float Average(int х, int у) { return (х + у) / 2 . 0 ; };
// Функция вычисления среднего двух целых
void main() { int a, b; printf("Введите два числа : " ) ; scanf("%i % i " , &a, & b ) ; printf("Среднее арифметическое этих чисел = %.lf \n", Average(a, b ) ) ; }
» В функции описаны два входных параметра целого типа. Несмотря на то что тип у них одинаковый, мы не можем написать так: float Average(int х, у). Т.е. для каждой переменной необходимо указывать ее тип. Внутри одной функции могут встречаться несколько операторов return. Например, функция для нахождения максимального числа из двух целых: int max(int a, int b) { if (a > b) return a; else return b; }
Если в программе определяется несколько функций, то иногда удобней определить их после функции main(), а до нее описать их прототип: int max(int a, int b ) ; float Square(float x ) ;
// прототип функции max // описание функции Square() с параметром
void main() // функция main() { float a, b, c; clrscr(); a = 5.5; b = Square(a)? с = Square(b + 3 ) ; printf("Результат вычислений = %.2f", с ) ; }; int max(int a, int b) { if (a > b) return a; else return b; }
// реализация функции max()
float Square(float x)
// реализация функции Square()
с параметром
{
float res; res = x * x; return res;
*
};
Рассмотрим еще один важный вопрос: как передавать массивы в качестве параметра функции? Следует передавать не сами значения массива, а указатель на начало массива, т.е. адрес в памяти. Пример 11.4. Напишите программу, в которой описана функция, реализующая посимвольный вывод строки на экран. /* Бегущая строка */ void OutText(char *str) { int i = 0; while(str[i] != *\0') { printf ("%с", str [i] ).; sound(500); delay(100); nosound(); i++; > }
// функция требует указатель на тип char
// цикл: пока не конец строки,
void main() { char name[20]; textcolor(14); textbackground(0); clrscr() ; OutText("Привет ! \ n " ) ; OutText("Это пример работы функции OutText() scanf("%s", S n a m e ) ; OutText(name); OutText("Функция описана корректно \ n " ) ; getch();
выполнять
,
\h");
В программе реализована функция OutText(), входным параметром которой является указатель на массив типа char (т.е. строка). Эта строка выводится в цикле while() посимвольно, до тех пор, пока компьютер не встретит символ окончания строки '\0'. После вывода очередной буквы подается звуковой сигнал с помощью функции 8оип(1(частота), описанной в библиотеке dos.h, где частота - целое число, выраженное в герцах (например, для ноты "ля" это 440 Гц). Далее следует пауза выполнения программы длиной 0.5 секунды, во время которой звуковой сигнал не прекращается. После завершения паузы звук выключается функцией nosound(), и тело цикла выполняется заново.
Задачи к главе 11.Функции Задача 11.1. Напишите функцию, которая сравнивает два целых числа и возвращает один символ: >, < или =. ь
Задача 11.2. Напишите функцию, которая вычисляет значение а , не используя стандартную функцию pow().
'»
Задача 11.3. Напишите функцию, которая считает количество гласных букв во введенной строке. Задача 11.4. Напишите функцию, которая случайным образом генерирует пароль из 8 символов. В пароле должны присутствовать только латинские буквы и цифры. Задача 11.5. Напишите функцию - телеграф, которая кодирует введенное предложение, азбукой Морзе, зная что: Б в.— г — . А .3--.. Д -•• Е . и.. И.— л.-.. к-.0 — м Н-. П р.-. С ... Т У ..ф ц-.-. ч — . X .... ш— ы я э ю . . ~ Задача 11.6. Напишите функцию, которая генерирует и выводит на экран всевозможные сочетания цифр и букв в пароле из 4 символов. Задача 11.7. Напишите функцию, которая рисует на экране рамку. В качестве параметра функция получает размеры рамки и координаты левого верхнего угла. Задача 11.8. Напишите функции, которые рисуют на экране линиями все 10 (от 0 до 9) цифр. В качестве параметра функция получает цифру и её положение на экране. Задача 11.9. Используя задачу 11.7, напишите программу-секундомер, которая в графическом режиме отсчитывает на экране 30 секунд.
Гпава 12 Файлы В файлах размещаются данные, предназначенные для длительного хранения. Каждому файлу приписывается используемое при обращении к нему уникальное имя. Для работы с файлами в С++ необходимо подключить стандартную библиотеку stdio.h. Все файлы можно условно разделить на две категории: текстовые и двоичные (их еще называют бинарными). Текстовые - это файлы, в которых записан только текст. Такие файлы обычно имеют расширения *.txt, *.ini, *.bat, *.log и т.д. Например, файлы, в которых содержатся исходные тексты программ, также являются текстовыми. То есть файлы с расширениями *.с, *.срр, *.pas, *.asm и т.д. можно просмотреть любым текстовым редактором, например WordPad'oM. Файлы, содержащие информацию, коды программ, рисунки, звуковые данные и т.д., являются бинарными (двоичными). Например, *.ехе, *.com, *.avi, *.dat, *.bmp - двоичные файлы. Файлы с расширением *.doc тоже относятся к двоичным, т.к. кроме текста они могут содержать и другую информацию, например, рисунки, графики, таблицы. Прежде чем читать или записывать информацию в файл, он должен быть открыт. Это можно сделать с помощью функции fopen. Она возвращает указатель на файл. Далее в программе мы будем работать именно с указателем на файл, а не писать каждый раз имя того или иного файла. Указатель на файл необходимо объявить: FILE *ist;
FILE - имя типа, описанное в стандартном определении stdio.h, ist - указатель на файл. Обращение к функции fopen в программе производится выражением: ist
=
гореп("имя
файла",
"вид
использования
файла");
Необходимо указать полный путь к файлу, включая диск, например: "c:\\my_file.txt", "a:\\doc\\data.txt". Если файл находится в том же каталоге, что и программа, которая к нему обращается, то можно ограничиться именем файла и его расширением "temp.txt". "вид использования файла" - это константа, которая определяет цель открытия файла: "rt" - открыть существующий текстовый файл для чтения; "wt" - создать новый текстовый файл для записи (если файл с указанным именем уже существует, то он будет переписан); * "at" - дополнить текстовый файл; "rt+" - открыть существующий текстовый файл для записи и чтения; "wt+" - создать новый файл для записи и чтения. Здесь используются сокращения от английских слов г (read) - читать, w (write) писать, a (add) - добавлять. Буква t (text) - означает, что мы будем работать с текстовым файлом. Если мы хотим работать с бинарным файлом, то вместо t надо написать b (binary). Например, ist = fopen("max.dat", "rb") - открывает двоичный файл max.dat из текущего каталога для чтения. Если в результате обращения к функции fopen возникает ошибка (например, файла max.dat не существует), то она возвращает указатель на константу NULL. Поэтому после каждого вызова функции fopen желательно проверять значение ссылки указателя. К примеру, так:
if(ist = fopen("max.dat",
"rb")==NULL)
printf("Ошибка открытия ф а й л а ! " ) ;
После окончания работы с файлом его нужно закрыть. Это делается с помощью функции fclose. В качестве входного параметра ей необходимо передать указатель на тот файл, который мы хотим закрыть, fclose(ist);
Рассмотрим другие библиотечные функции, используемые для работы с файлами (все они описаны в файле stdio.h): 9 1. Функция putc записывает символ в файл: putcfch,
i s t ) ;
ch - символ для записи (переменная типа char), ist - указатель на файл, возвращенный функцией fopen. 2. Функция getc читает символ из файла: ch
=
getc(ist) ;
Здесь также ch типа char, ist - указатель на файл, из которого читается очередной символ и записывается в ch. Если вызывать эту функцию в цикле, то будут последовательно прочитаны все символы из файла. При достижении конца файла функция вернет значение константы EOF (End Of File) - коноц файла. 3. Функция feof определяет конец файла при чтении двоичных данных: status
=
feof(ist);
Здесь ist - указатель на файл, status - переменная типа int, в которую при достижении конца файла записывается ненулевое значение. В противном случае записывается 0. 4. Функция fputs записывает строку символов в файл. Она отличается от функции puts только тем, что в качестве второго параметра должен быть записан еще и указатель на файл. Например: FILE
*ist;
i s t = fopen("my.txt",
wt") ;
fputs("Привет,
i s t ) ;
Вася!"
fclose(ist);
Записывает в файл, связанный с указателем ist строчку текста "привет, Вася!". 5. Функция fgets читает строчку символов из файла. Она отличается от функции gets только тем, что в качестве второго параметра должен быть записан еще и указатель на файл. Например: FILE
*р;
char
str[50 ] ;
р
=
fopen ("с: W s t o r y . t x t " ,
fgets(str,
"rt") ;
p ) ;
fclose(p);
82
6. Функция fprintf выполняет те же действия, что и функция printf, но работает с файлом. Ее отличие в том, что в качестве первого параметра также задается указатель на файл: FILE *р; int х = 10; р = f o p e n ("а : W d a t a . t x t " , " w t " ) ; fprintf(p, " З н а ч е н и е п е р е м е н н о й x = %i", fclose(p);
x); *
Функция выводит строчку текста и значение переменной х, но только не на экран, как это делала функция printf, а в файл a:\data.txt. 7. Функция fscanf отличается от похожей на неё функции scanf тем, что у неё первый параметр - указатель на файл, и читает информацию она не с клавиатуры, а из файла. FILE *р; char str[100]; int х, у; р = fopen("noname.cpp", " r t " ) ; fscanf(p, "Is %i %i", &str, &x, & y ) ; fclose(p);
Здесь мы читаем из файла строчку текста (до первого пробела) и далее два целых числа х и у. 8. При открытии файла мы автоматически оказываемся в его начале и далее перемещаемся по файлу, читая последовательно данные. А что, если нам необходимо прочитать только одно число, находящееся на 100 позиции? Или нужная информация находится в конце файла? Для этих целей существует функция fseek, которая позволяет выполнять чтение и запись с произвольной позиции файла. Она имеет вид: fseek(ist, count, access);
Здесь ist - указатель на файл, count - номер байта относительно заданной начальной позиции, access - способ задания начальной позиции. Переменная access может принимать следующие значения: 0 - начальная позиция задана в начале файла; 1 - начальная позиция считается текущей; 2 - начальная позиция считается с конца файла.
,
Например: /* Ч и т а е т 1 0 - ы й с и м в о л из ф а й л а fseek(ist, 10, 0 ) ; ch = getc(ist);
с у к а з а т е л е м ist
/ * Ч и т а е т 5-ый с и м в о л о т к о н ц а ф а й л а fseek(ist, - 5 , 2 ) ; ch = getc(ist);
*/
*/
/* Читает из файла 10 символов через один и печатает их на экран */ for(i = 0; i < 10; i++) { fseek(ist, 2, 1 ) ; fscanf(ist, "%c", & c h ) ; printf("%c", c h ) ; }
Пример 12.1. Напишите программу, которая сохраняет в файл имя, возраст и вес студента, введенные пользователем в ходе выполнения программы. int main() { FILE *f; char name[15]; int age; int weight; f
=
*
// имя // возраст // вес
fopen("x:\\\\database.txt",
"wt+);
// создаем на диске x: файл if (f == NULL) { printf("Ошибка создания файла ! \ n " ) ; return 1; // выход из программы } /* Считываем данные с клавиатуры */ printf("Введите имя студента : " ) ; scanf("%s", &name); printf("Введите его возраст : " ) ; scanf("%i", &age); printf("Введите вес : " ) ; scanf("%f", &weight);
*
/* Сохраним все это в файл */ fprintf(f, "%s \n %i \n %f", name, age, weight); fclose(f); }
// закроем файл
Пример 12,2. Напишите программу, которая считывает из файла имя, возраст и вес студента и выводит их на экран. int main() { FILE *f; char name[15]; int age; float weight;
// имя // возраст // вес
(f == NULL) { printf("He могу открыть файл ! \ n " ) ; return 1; // выход из программы } /* Считываем данные из файла */ fscanf(f, "%s %i %\", Sname, Sage, Sweight);
„
/* Выводим данные на экран */ printf("Имя студента : %s \n", n a m e ) ; printf("Возраст : %i \n", a g e ) ; printf("Вес : %f \n", weight ); fclose(f); return 0;
// закроем файл
}
Пример 12.3. Напишите программу, которая посимвольно выводит на экран содержимое текстового файла: /* Программа для чтения текстовых файлов */ FILE *f; char ch; f
=
// Указатель на файл // Читаемый символ
fopen("х:\\\\my.txt",
while (feof (f) ===0) { ch = getc(f); printf("%с", c h ) ; } fclose(f);
"rt");
// цикл: пока не конец файла f, выполняем цикл
Задачи к главе 1 2 . Файлы Задача 12.1. Напишите программу, в которой описана функция, цель которой - сообщать пользователю об ошибке открытия файла, если такая имеет место, и открывать файл, если ошибок нет. В качестве входного параметра функция принимает имя файла, введенное пользователем. Задача 12.2. Напишите программу, которая создает файл numbers.txt и записывает в него 5 введенных пользователем чисел. Задача 12.3. Напишите программу, которая вычисляет среднее арифметическое чисел, находящихся в файле numbers.txt. Задача 12.4. Напишите программу, которая дописывает в файл phones.txt имя, отчество и номер телефона абонента. Информация вводится пользователем в ходе выполнения программы. Задача 12.5. Напишите программу, которая осуществляет поиск по телефонной книге phones.txt и в случае нахождения соответствий выводит информацию об абоненте или абонентах (если совпадений несколько) на экран. Задача
12.6.
«добавление
Напишите в
программу,
которая
телефонный, справочник»
объединяет
(задача 12.4.)И
(задача 12.5.).При запуске программы выводится меню:
возможности
«поиск
в
программ
телефонной книге»
,
**** Телефонный справочник**** 1. Добавление 2. Поиск 3. Завершение работы Введите номер пункта меню:
Задача 12.7. Напишите программу, которая считывает изменение курса валют пары EUR/USD (значение курса и номер, которым по счету вводится значение) и записывает в файл. А потом считывает эти значения из файла и выводит на экран график дневного изменения курса. Задача 12.8. Напишите программу, которая считывает параметры пяти эллипсов, вводимые пользователем с клавиатуры, и записывает их в файл. А потом выводит эти эллипсы на экран.
Приложение 1.Таблица кодов ASCII
»
Литература 1. Керниган Б., Ричи Д. "Язык программирования "С". 2. Азаров А. "Программирование на C/C++. Часть 1". 3. Шилдт Г. "С - для профессиональных программистов". 4. Стивен А. "Техника программирования на Turbo С". 5. Березин Б., Березин С. "Начальный курс С и С++". 6. Скляров В. "Программирование на языках С и С++". 7. Поддубная Л., Шаньгин В. "Мне нравится паскаль". 8. Шикин А. "Компьютерная графика". 9. Культин Н. "Turbo Pascal в задачах и примерах". 10. Попов В. "Turbo Pascal для школьников". 11. Дейтел X., Дейтел П. "Как программировать на С++".