Aлексеев - Програмирование на языке C++ в среде Qt Greator

Формат документа: pdf
Размер документа: 5.52 Мб




Прямая ссылка будет доступна
примерно через: 45 сек.



  • Сообщить о нарушении / Abuse
    Все документы на сайте взяты из открытых источников, которые размещаются пользователями. Приносим свои глубочайшие извинения, если Ваш документ был опубликован без Вашего на то согласия.

В серии:Библиотека ALT Linux
Программирование на языке С++ в среде Qt Creator
Е. Р. Алексеев, Г. Г. Злобин, Д. А. Костюк,
О. В. Чеснокова, А. С. Чмыхало Москва
ALT Linux 2015

УДК 004.43
ББК 32.973.26-018.1А47
А47 Программирование на языке С++ в среде Qt Creator:
/ Е. Р. Алексеев, Г. Г. Злобин, Д. А. Костюк,О. В. Чеснокова,
А. С. Чмыхало  М. : ALT Linux, 2015.  448 с. : ил.  (Биб-
лиотека ALT Linux).
ISBN 978-5-905167-16-4
Книга является учебником по алгоритмизации и программиров а-
нию на С++и пособием по разработке визуальных приложений в среде Qt
Creator . Также в книге описаны среда программирования Qt Creator,
редактор Geany, кроссплатформенная билиотека построения графиков
MathGL . При чтении книги не требуется предварительного знакомств а с
программированием. Издание предназначено для студентов, аспирантов и препода вате-
лей вузов, а также для всех, кто изучает программирование на С++
и осваивает кроссплатформенный инструментарий Qtдля разработки
программного обеспечения.
Сайт книги: http://www.altlinux.org/Books:Qt- C++
УДК 004.43
ББК 32.973.26-018.1
По вопросам приобретения обращаться: ООО Альт Линукс (495)662-38-83 E-mail: sales@altlinux.ru http://altlinux.ru
Материалы, составляющие данную книгу, распространяются н а условиях лицензии GNU
FDL. Книга содержит следующий текст, помещаемый на первую с траницу обложки: В серии
“Библиотека ALT Linux”. Название: Программирование на я зыке С++ в среде Qt Creator.
Книга не содержит неизменяемых разделов. Авторы разделов у казаны в Предисловии. ALT
Linux  торговая марка компании ALT Linux. Linux  торговая м арка Линуса Торвальдса.
Прочие встречающиеся названия могут являться торговыми ма рками соответствующих вла-
дельцев.
ISBN 978-5-905167-16-4 © Е. Р. Алексеев, Г. Г. Злобин, Д. А. Костюк,
О. В. Чеснокова, А. С. Чмыхало, 2015
© ALT Linux, 2015

ОглавлениеПредисловие 7
Глава 1. Знакомство с языком С++ 8
1.1 Первая программа на C++. . . . . . . . . . . . . . . . . . . . . . 8
1.2 Среда программирования Qt Creator. . . . . . . . . . . . . . . 11
Глава 2. Общие сведения о языке С++17
2.1 Алфавит языка . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2 Данные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3 Константы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.4 Структурированные типы данных . . . . . . . . . . . . . . . . . .21
2.5 Указатели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.6 Операции и выражения . . . . . . . . . . . . . . . . . . . . . . . . 23
2.7 Стандартные функции . . . . . . . . . . . . . . . . . . . . . . . . 31
2.8 Структура программы . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.9 Ввод и вывод данных . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.10 Задачи для самостоятельного решения . . . . . . . . . . . . . . .40
Глава 3. Операторы управления 44
3.1 Основные конструкции алгоритма . . . . . . . . . . . . . . . . . .44
3.2 Составной оператор . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.3 Условные операторы . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.4 Операторы цикла . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.5 Решение задач с использованием циклов . . . . . . . . . . . . . .70
3.6 Задачи для самостоятельного решения . . . . . . . . . . . . . . .86
Глава 4. Использование функций при программировании на C++100
4.1 Общие сведения о функциях . . . . . . . . . . . . . . . . . . . . . 100
4.2 Передача параметров в функцию . . . . . . . . . . . . . . . . . .104
4.3 Возврат результата с помощью оператора return . . . . . . . . . .106
4.4 Решение задач с использованием функций . . . . . . . . . . . . .106
4.5 Рекурсивные функции . . . . . . . . . . . . . . . . . . . . . . . . 121
4.6 Перегрузка функций . . . . . . . . . . . . . . . . . . . . . . . . . 123
4.7 Шаблоны функций . . . . . . . . . . . . . . . . . . . . . . . . . . 125
4.8 Область видимости переменных в функциях . . . . . . . . . . . .126
4.9 Функция main(). Параметры командной строки . . . . . . . . . .127

4Оглавление
4.10 Задачи для самостоятельного решения. . . . . . . . . . . . . . .129
Глава 5. Массивы 134
5.1 Статические массивы в С(С++). . . . . . . . . . . . . . . . . . . 134
5.2 Динамические массивы в С(С++) . . . . . . . . . . . . . . . . . .136
5.3 Отличие статического и динамического массива . . . . . . . . . .139
5.4 Основные алгоритмы обработки массивов . . . . . . . . . . . . .139
5.5 Указатели на функции . . . . . . . . . . . . . . . . . . . . . . . . 166
5.6 Совместное использование динамических массивов . . . . . . . .169
5.7 Задачи для самостоятельного решения . . . . . . . . . . . . . . .175
Глава 6. Статические и динамические матрицы 185
6.1 Статические матрицы С(С++). . . . . . . . . . . . . . . . . . . . 185
6.2 Динамические матрицы . . . . . . . . . . . . . . . . . . . . . . . 186
6.3 Обработка матриц в С(С++). . . . . . . . . . . . . . . . . . . . . 187
6.4 Решение некоторых задач линейной алгебры . . . . . . . . . . . .197
6.5 Задачи для самостоятельного решения . . . . . . . . . . . . . . .215
Глава 7. Организация ввода-вывода в C++226
7.1 Форматированный ввод-вывод в C++. . . . . . . . . . . . . . . . 226
7.2 Работа с текстовыми файлами в C++. . . . . . . . . . . . . . . . 230
7.3 Обработка двоичных файлов . . . . . . . . . . . . . . . . . . . . . 236
7.4 Функции fscanf() и fprintf() . . . . . . . . . . . . . . . . . . . . . . 240
Глава 8. Строки в языке C++ 242
8.1 Общие сведения о строках в C++. . . . . . . . . . . . . . . . . . 242
8.2 Операции над строками . . . . . . . . . . . . . . . . . . . . . . . 243
8.3 Тип данных string . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
8.4 Задачи для самостоятельного решения . . . . . . . . . . . . . . .247
Глава 9. Структуры в языке C++ 249
9.1 Общие сведения о структурах . . . . . . . . . . . . . . . . . . . .249
9.2 Библиотеки для работы с комплексными числами . . . . . . . . .256
9.3 Задачи для самостоятельного решения . . . . . . . . . . . . . . .264
Глава 10. Объектно-ориентированное программирование 267
10.1 Возникновение объектного подхода в программировании . . . . .267
10.2 Классы и объекты в C++. . . . . . . . . . . . . . . . . . . . . . . 271
10.3 Создание и удаление объектов . . . . . . . . . . . . . . . . . . . .285
10.4 Наследование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
10.5 Обработка исключений . . . . . . . . . . . . . . . . . . . . . . . . 305
10.6 Шаблоны классов . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
10.7 Элементы стандартной библиотеки C++. . . . . . . . . . . . . . . 321
10.8 Задачи для самостоятельного решения . . . . . . . . . . . . . . .326
Программирование на языке С++ в среде Qt Creator

Оглавление5
Глава 11. Знакомство сQt. Подготовка к работе 329
11.1 Знакомство с Qt. Обзор истории . . . . . . . . . . . . . . . . . . 329
11.2 Лицензирование Qt. . . . . . . . . . . . . . . . . . . . . . . . . . 332
11.3 Справка и ресурсы . . . . . . . . . . . . . . . . . . . . . . . . . . 333
11.4 Обзор настроек среды Qt Creator. . . . . . . . . . . . . . . . . 334
11.5 Задачи для самостоятельного решения . . . . . . . . . . . . . . .339
Глава 12. Структура проекта. Основные типы 340
12.1 Файлы проекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
12.2 Компиляция проекта . . . . . . . . . . . . . . . . . . . . . . . . . 342
12.3 Консольный проект Qt.Вывод сообщений. . . . . . . . . . . . . . 345
12.4 Работа с текстовыми строками в Qt . . . . . . . . . . . . . . . . .347
12.5 Контейнерные классы в Qt. . . . . . . . . . . . . . . . . . . . . . 348
12.6 Работа с файлами . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
12.7 Задачи для самостоятельного решения . . . . . . . . . . . . . . .354
Глава 13. Создание графического интерфейса средствами Qt 355
13.1 Виджеты (Widgets) . . . . . . . . . . . . . . . . . . . . . . . . . . 355
13.2 Компоновка (Layouts) . . . . . . . . . . . . . . . . . . . . . . . . . 359
13.3 Политики размера (Size Policies) . . . . . . . . . . . . . . . . . . .363
13.4 Сигнально-слотовые соединения . . . . . . . . . . . . . . . . . . .365
13.5 Создание сигналов (signals) и слотов (slots) . . . . . . . . . . . .367
13.6 Элементы графического интерфейса. . . . . . . . . . . . . . . . .371
13.7 Задачи для самостоятельного решения . . . . . . . . . . . . . . .373
Глава 14. Создание элементов графического интерфейса 374
14.1 Класс QObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
14.2 Управление памятью. Иерархии объектов . . . . . . . . . . . . .380
14.3 События (Events). Обработка событий (Event handling) . . . . . .383
14.4 Фильтры событий (Event filters) . . . . . . . . . . . . . . . . . . .385
14.5 Создание собственного элемента интерфейса . . . . . . . . . . .389
14.6 Рисование элементов. Класс QPainter . . . . . . . . . . . . . . . .391
14.7 Задачи для самостоятельного решения . . . . . . . . . . . . . . .394
Глава 15. Разработка приложений с графическим интерфейсом 395
15.1 Окна. Класс QMainWindow . . . . . . . . . . . . . . . . . . . . . . 395
15.2 Быстрая разработка с помощью Qt Designer . . . . . . . . . . . .396
15.3 Программирование формы созданной в Qt Designer . . . . . . . .401
15.4 Стандартные диалоги . . . . . . . . . . . . . . . . . . . . . . . . . 404
15.5 Ресурсы программы . . . . . . . . . . . . . . . . . . . . . . . . . . 408
15.6 Создание собственных диалогов . . . . . . . . . . . . . . . . . . .410
15.7 Сохранение настроек . . . . . . . . . . . . . . . . . . . . . . . . . 414
15.8 Использование сторонних разработок в собственном про екте. .415
15.9 Задачи для самостоятельного решения . . . . . . . . . . . . . . .417
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

6Оглавление
Приложение A. Использование компилятора командной строки
и текстового редактора Geany 419
Приложение B. Общие сведения о библиотеке MathGL 428
B.1 Установка MathGL в Linux. . . . . . . . . . . . . . . . . . . . . . . 428
B.2 Использование MathGL при построении двух- и трёхмерных
графиков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
Список литературы 443
Предметный указатель 444
Программирование на языке С++ в среде Qt Creator

ПредисловиеКнига, которую открыл читатель, является с одной стороны уч ебником по
алгоритмизации и программированию на C++, а с другой  пособием по разра-
ботке визуальных приложений в среде Qt Creator. В книге описаны среда про-
граммирования Qt Creatorи редакторGeany. При чтении книги не требуется
предварительного знакомства с программированием. В первой части книги (главы 1–9) на большом количестве приме ров пред-
ставлены методы построения программ на языке C++, особое внимание уделено
построению циклических программ, программированию с испо льзованием функ-
ций, массивов, матриц и указателей. Вторая часть книги (глава 10) посвящена объектно-ориентир ованному про-
граммированию на C++.
В третьей части книги (главы 11–15) читатель научится созда вать кроссплат-
форменные визуальные приложения с помощью Qt Creatorи познакомится с
библиотекой классов Qt.
В книге присутствуют задания для самостоятельного решения.
В приложениях описан текстовый редактор Geany, а также кросс-
платформенная библиотека MathGL, предназначенная для пос троения раз-
личных двух- и трёхмерных графиков. Главы 1–9 написаны Е. Р. Алексеевым и О. В. Чесноковой. Автором раздела по
объектно-ориентированному программированию является Д. А. Костюк. Главы
11–15, посвящённые программированию с использованием инс трументарияQt,
написаны Г. Г. Злобиным и А. C. Чмыхало.
Авторы благодарят компанию ALT Linux ( www.altlinux.ru) и лично Алексея
Смирнова и Владимира Чёрного за возможность издать очередн ую книгу по
свободному программному обеспечению.

Глава 1
Знакомство с языкомС++
В этой главе читатель напишет свои первые программы на языке С(С++), по-
знакомится с основными этапами перевода программы с языка C++в машинный
код. Второй параграф главы посвящён знакомству со средой Qt Creator.
1.1 Первая программа на C++
Знакомство с языком С++начнём с написания программ, предназначенных
для решения нескольких несложных задач.
Задача 1.1. Заданы две стороны прямоугольника a, b. Найти его площадь и
периметр.
Как известно, периметр прямоугольника P= 2 ·( a + b), а его площадь S= a·b .
Ниже приведён текст программы.
1 #i n c l u d e < i o s t r e a m >
2 u s i n g namespace s t d ;
3 i n t m a i n ( )
4 {
5 f l o a ta , b , s , p ;
6 c o u t << " a = ";
7 c i n >>a ;
8 c o u t << " b = ";
9 c i n >>b ;
10 p = 2 ∗ ( a+b ) ;
11 s=a ∗ b ;
12 c o u t << "Периметр прямоугольника равен "<< p << e n d l ;
13 c o u t << "Площадь прямоугольника равна "<< s << e n d l ;
14 r e t u r n 0 ;
15 }
Давайте построчно рассмотрим текст программы и познакомим ся со струк-
турой программы на С++и с некоторыми операторами языка.
Строка 1. Указывает компилятору (а точнее, препроцессору), что надо и с-
пользовать функции из стандартной библиотеки iostream. Библиотека iostream
нужна для организации ввода с помощью инструкции cinи вывода  с помощью
cout . В программе на языке C++должны быть подключены все используемые
библиотеки.

1.1. Первая программа наC++ 9
Строка 2.Эта строка обозначает, что при вводе и выводе с помощью cinи
cout будут использоваться стандартные устройства (клавиатура и экран), если
эту строку не указывать, то каждый раз при вводе вместо cinнадо будет писать
std::cin , а вместо cout –- std::cout .
Строка 3. Заголовок главной функции (главная функция имеет имя main).
В простых программах присутствует только функция main().
Строка 4. Любая функция начинается с символа {.
Строка 5. Описание вещественных ( float) переменных a(длина одной сто-
роны прямоугольника), b(длина второй стороны прямоугольника), s(площадь
прямоугольника), p(периметр прямоугольника). Имя переменной 1
состоит из
латинских букв, цифр и символа подчёркивания. Имя не может н ачинаться с
цифры. В языке С++большие и малые буквы различимы. Например, имена PR_1,
pr_1 ,Pr_1 иpR_1  разные.
Строка 6. Вывод строки символов a=с помощью cout. Программа выведет
подсказку пользователю, что необходимо вводить переменную a
Строка 7. Ввод вещественного числа aс помощью cin. В это момент про-
грамма останавливается и ждёт, пока пользователь введёт зн ачение переменойa
с клавиатуры.
Строка 8 . Вывод строки символов b=с помощью cout.
Строка 9. Ввод вещественного числа bс помощью cin.
Строка 10. Оператор присваивания для вычисления периметра прямоугол ь-
ника (переменная p) по формуле 2·(a + b) . В операторе присваивания могут
использоваться круглые скобки и знаки операций: +(сложение), −(вычитание),
∗ (умножение), / (деление).
Строка 11. Оператор присваивания для вычисления площади прямоуголь-
ника.
Строка 12. Вывод строки Периметр прямоугольника равен и значения
p на экран. Константа endlхранит строку \n, которая предназначена для
перевода курсора в новую строку дисплея 2
. Таким образом строка
cout <<"Периметр прямоугольника равен " << p < выводит на экран текст "Периметр прямоугольника равен " 3
, значение пере-
менной p, и переводит курсор в новую строку.
Строка 13. Вывод строки "Площадь прямоугольника равна " , значения пло-
щади прямоугольника s, после чего курсор переводится в новую строку дисплея.
Строка 14. Операторreturn, который возвращает значение в операционную
систему. Об этом подробный разговор предстоит в п. 4.9.Сейч ас следует запом-
нить: если программа начинается со строки int main(), последним оператором
должен быть 4
return 0 .
1
В литературе равнозначно используются термины имя переме нной и идентификатор.
2 Обращаем внимание читателя, что символ пробел является обы чным символом, который
ничем не отличается от остальных. Для вывода пробела на экра н его надо явно указывать в
строке вывода. 3С пробелом после слова равен.
4 Вообще говоря, вместо нуля может быть любое целое число.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

10Глава 1. Знакомство с языкомС++
Строка 15.Любая функция (в том числе и main) заканчивается символом }.
Мы рассмотрели простейшую программу на языке С++, состоящую из опера-
торов ввода данных, операторов присваивания (в которых про исходит расчёт по
формулам) и операторов вывода. Программа на языке С++представляет собой одну или несколько функций.
В любой программе обязательнодолжна быть одна функция main(). С этой
функции начинается выполнение программы. Правилом хороше го тона в про-
граммировании является разбиение задачи на подзадачи, и в г лавной функции
чаще всего должны быть операторы вызова других функций. Общ ую структуру
программы на языке C++можно записать следующим образом.
Директивы препроцессора
Объявление глобальных переменных
Тип_результата f 1 ( Список_переменных ) {
Операторы }
Тип_результата f 2 ( Список_переменных ) {
Операторы }
. . .
Тип_результата f n ( Список_переменных ) {
Операторы }
Тип_ результата m a i n ( Список_переменных )
{
Операторы
}
На первом этапе знакомства с языком мы будем писать программ ы, состоящие
только из функции main, без использования глобальных переменных. Структура
самой простой программы на C(C++)имеет вид.
Директивы препроцессора
Тип_ результата m a i n ( Список_переменных ) {
Операторы }
Введённая в компьютер программа на языке С++должна быть переведена в
двоичный машинный код (формируется исполняемый файл). Для этого суще-
ствуют специальные программы, называемые трансляторами. В се трансляторы
делятся на два класса:
•интерпретаторы  трансляторы, которые переводят каждый оператор
программы в машинный код, и по мере перевода операторы выпол няют-
ся процессором;
• компиляторы переводят всю программу целиком, и если перевод всей про-
граммы прошёл без ошибок, то полученный двоичный код можно з апускать
на выполнение.
Процесс перевода программы в машинный код называется трансляцией. Если
в качестве транслятора выступает компилятор, то используют терминкомпиля-
Программирование на языке С++ в среде Qt Creator

1.2. Среда программированияQt Creator 11
цияпрограммы. При переводе программы с языка С++в машинный код исполь-
зуются именно компиляторы, и поэтому применительно к языку С++термины
компилятор и транслятор эквивалентны.
Рассмотрим основные этапы обработки компилятором програм мы на языке
С++ и формирования машинного кода.
1. Сначала с программой работает препроцессор 5
, он обрабатывает директи-
вы, в нашем случае это директивы включения заголовочных файл ов (фай-
лов с расширением .h)  текстовых файлов, в которых содержится опи-
сание используемых библиотек. В результате формируется по лный текст
программы, который поступает на вход компилятора.
2. Компилятор разбирает текст программ на составляющие элем енты, про-
веряет синтаксические ошибки и в случае их отсутствия форми рует объ-
ектный код (файл с расширением .oили . ob j). Получаемый на этом этапе
двоичный код не включает в себя двоичные коды библиотечных фу нкций
и функций пользователя.
3. Компоновщик подключает к объектному коду программы объектные моду-
ли библиотек и других файлов (если программа состоит из неск ольких фай-
лов) и генерирует исполняемый код программы (двоичный файл ), который
уже можно запускать на выполнение. Этот этап называется ком поновкой
или сборкой программы.
После написания программы её необходимо ввести в компьютер. В той книге
будет рассматриваться работа на языке C++в среде Qt Creator 6
. Поэтому перед
вводом программы в компьютер надо познакомиться со средой пр ограммирова-
ния.
1.2 Среда программирования Qt Creator
Среда программирования Qt Creator(IDE QT Creator ) находится в репози-
тории большинства современных дистрибутивов Linux (OC Lin ux Debian, OC
Linux Ubuntu, OC ROSA Linux, ALT Linux и др.). Установка осущес твляется
штатными средствами вашей операционной системы (менеджер пакетов Synaptic
и др.) из репозитория, достаточно установить пакет qtcreat or, необходимые па-
кеты и библиотеки будут доставлены автоматически. Последн юю версию IDEQt
Creator можно скачать на сайте QtPro ject ( http://qt-project.org/downloads ).
Установочный файл имеет расширение .run. Для установки приложения, необхо-
димо запустить его на выполнение. Установка проходит в граф ическом режиме.
5
Препроцессор преобразовывает текст директив в форму, поня тную компилятору. О данных
на выходе препроцессора говорят, что они находятся в препро цессированной форме.
6 Тексты программ, приведённые в первой части книги (главы 1– 9), без серьёзных изменений
могут быть откомпилированы с помощью любого современного к омпилятора с языкаС(С++ ).
Авторы протестировали все программы из первой части книги с помощьюQT Creator иIDE
Geany (с использованием g++версии 4.8).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

12Глава 1. Знакомство с языкомС++
После запуска программы пользователь увидит на экране окно , подобное пред-
ставленному на рис. 1.1 7
.
Рис. 1.1: Окно Qt Creator
При работе в Qt Creatorвы находитесь в одном из режимов:
1. Welcome (Начало)  отображает экран приветствия, позволяя быстро з а-
гружать недавние сессии или отдельные проекты. Этот режим м ожно уви-
деть при запуске Qt Creatorбез указания ключей командной строки.
2. Edi t (Редактор)  позволяет редактировать файлы проекта и исхо дных
кодов. Боковая панель слева предоставляет различные виды д ля переме-
щения между файлами.
3. Debug (Отладка)  предоставляет различные способы для просмотра со-
стояния программы при отладке.
4. Pro jects (Проекты)  используется для настройки сборки, запуска и ре -
дактирования кода.
5. Analyze (Анализ)  в Qt интегрированы современные средства анализа
кода разрабатываемого приложения.
6. Help (Справка)  используется для вывода документации библиоте ки Qt
и Qt Creator .
7. Output (Вывод)  используется для вывода подробных сведений о прое к-
те.
7 Окно на вашем компьютере визуально может несколько отличат ься от представленного
на рис. 1.1, авторы использовали IDE Qt Creatorверсии 2.6.2, основанную на QT 5.0.1.
Программирование на языке С++ в среде Qt Creator

1.2. Среда программированияQt Creator 13
Рассмотрим простейшие приёмы работы в среде Qt Creatorна примере со-
здания консольного приложения для решения задачи 1.1. Для э того можно по-
ступить одним из способов:
1. В меню File(Файл) выбрать команду New File or Pro ject(Новый файл
или проект) (комбинация клавиш Ctrl+N).
2. Находясь в режиме Welcome(Начало) главного окна QtCreator (рис. 1.1)
щёлкаем по ссылке Develop(Разработка) и выбираем команду Create
Pro ject (Создать проект).
После это откроется окно, подобное представленному на рис. 1.2. Для созда-
ния простейшего консольного приложения выбираем Non-Qt Pro ject(Проект
без использования Qt)  Plain C++Pro ject (Простой проект на языке С++).
Далее выбираем имя проекта и каталог для его размещения (см. рис. 1.3)8
.
Следующие два этапа создания нашего первого приложения оста вляем без из-
менения 9
. После чего окно IDE Qt Creatorбудет подобно представленному на
рис. 1.4. Заменим текст Hello, Word стандартного приложен ия, на текст про-
граммы решения задачи 1.1.
Рис. 1.2: Окно выбора типа приложения в Qt Creator
Для сохранения текста программы можно воспользоваться ком андойСохра-
нить илиСохранить всё из менюФайл. Откомпилировать и запустить про-
грамму можно одним из следующих способов:
1. Пункт меню Сборка-Запустить .
2. Нажать на клавиатуре комбинацию клавиш Ctrk+R.
3. Щёлкнуть по кнопке Запустить (
).
Окно с результатами работы программы представлено на рис. 1 .5.
8
Рекомендуем для каждого проекта выбирать отдельный катало г. Проект  это несколько
взаимосвязанных между собой файлов и каталогов. 9О назначении этих этапов будет рассказано в дальнейших разд елах книги.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

14Глава 1. Знакомство с языкомС++
Рис. 1.3: Выбор имени и каталога нового проекта
Рис. 1.4: Главное окно создания консольного приложения
Авторы сталкивались с тем, что в некоторых дистрибутивах Ubun tu Linux и
Linux Mint после установки Qt Creatorне запускались консольные приложения.
Если читатель столкнулся с подобной проблемой, скорее всег о надо корректно
настроить терминал, который отвечает за запуск приложений в консоли. Для
этого вызываем команду Tools  Options  Environment (см. ри с. 1.6). Параметр
Terminal (Терминал) должен быть таким же, как показано на рис. 1.6. Пр оверь-
те установлен ли в Вашей системе пакет xterm, и при необходим ости доставьте
его. После этого не должно быть проблем с запуском консольны х приложений.
Аналогичным образом можно создавать и запускать любое консол ьное при-
ложение.
Программирование на языке С++ в среде Qt Creator

1.2. Среда программированияQt Creator 15
Рис. 1.5: Результаты работы программы решения задачи 1.1
Рис. 1.6: Окно настроек средыQt Creator
Дальнейшее знакомство со средой Qt Creatorпродолжим, решая следующую
задачу.
Задача 1.2. Заданы длины трёх сторон треугольника a, b и c(см. рис. 1.7).
Вычислить площадь и периметр треугольника.
Для решения задачи можно воспользоваться формулой Герона
S= q
p2

p 2 −
a
p 2−
b
p 2−
c
, где p= a+ b+ c периметр.
Решение задачи можно разбить на следующие этапы:
1. Определение значений a, b и c(ввод величин a, b, c с клавиатуры в память
компьютера).
2. Расчёт значений pи sпо приведённым выше формулам.
3. Вывод pи sна экран дисплея.
Ниже приведён текст программы. Сразу заметим, что в тексте м огут встречаться
строки, начинающие с двух наклонных (//). Это комментарии. Комментариине
являются обязательными элементами программы и ничего не соо бщают компью-
теру, они поясняют человеку, читающему текст программы, назн ачение отдель-
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

16Глава 1. Знакомство с языкомС++
Рис. 1.7: Треугольник
ных элементов программы. В книге комментарии будут широко и спользоваться
для пояснения отдельных участков программы.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t a , b , c , s , p ;
c o u t << "Введите длины сторон треугольника "<< e n d l ;
/ / Ввод значений длин треугольника a , b , c .
c i n >>a>>b>>c ;
/ / Вычисление периметра треугольника .
p=a+b+c ;
/ / Вычисление площади треугольника .
s= s q r t ( p / 2 ∗ ( p/2 −a ) ∗ ( p/2 −b ) ∗ ( p/2 −c ) ) ;
/ / Вывод на экран дисплея значений площади и периметра треуголь ника.
c o u t << "Периметр треугольника равен "< r e t u r n 0 ;
}
Кроме используемой в предыдущей программе библиотеки iostream, в стро-
ке 2 подключим библиотеку math.h, которая служит для использования мате-
матических функций языка С(С++ ). В данной программе используется функция
извлечения квадратного корня  sqrt(x). Остальные операторы (ввода, выво-
да, вычисления значений переменных) аналогичны используе мым в предыдущей
программе.
Таким образом, выше были рассмотрены самые простые програм мы (линей-
ной структуры), которые предназначены для ввода исходных д анных, расчёта
по формулам и вывода результатов.
Программирование на языке С++ в среде Qt Creator

Глава 2
Общие сведения о языкеС++
В этой главе читатель познакомится с основными элементами я зыкаС++: ал-
фавитом, переменными, константами, типами данных, основн ыми операциями,
стандартными функциями, структурой программы и средствам и ввода-вывода
данных.
2.1 Алфавит языка
Программа на языке С++может содержать следующие символы:
• прописные, строчные латинские буквы A, B, C, . . . , x, y, z и зна к подчёр-
кивания;
• арабские цифры от 0 до 9;
• специальные знаки: " { } , | [ ] ( ) +  / % * . \ ’ : ? < = > ! & # ˜ ; ˆ
• символы пробела, табуляции и перехода на новую строку.
Из символов алфавита формируют ключевые слова и идентификато ры. Клю-
чевые слова  это зарезервированные слова, которые имеют спе циальное значе-
ние для компилятора и используются только в том смысле, в кото ром они опре-
делены (операторы языка, типы данных и т.п.). Идентификато р  это имя про-
граммного объекта, представляющее собой совокупность букв , цифр и символа
подчёркивания. Первый символ идентификатора  буква или зн ак подчёрки-
вания, но не цифра. Идентификатор не может содержать пробел . Прописные и
строчные буквы в именах различаются, например, ABC,abc ,Abc  три различ-
ных имени. Каждое имя (идентификатор) должно быть уникальн ым в пределах
функции и не совпадать с ключевыми словами.
В тексте программы можно использовать комментарии. Если те кст начина-
ется с двух символов косая черта // и заканчивается символ ом перехода на
новую строку или заключён между символами /* и */, то компилят ор его игно-
рирует. / ∗ Комментарий может
выглядеть так! ∗ /
/ / А если вы используете такой способ,

18Глава 2. Общие сведения о языкеС++
/ /то каждая строка должна начинаться
/ / с двух символов косая черта.
Комментарии удобно использовать как для пояснений к програ мме, так и для
временного исключения фрагментов программы при отладке.
2.2 Данные
Для решения задачи в любой программе выполняется обработка к аких-либо
данных. Данные хранятся в памяти компьютера и могут быть самы х различ-
ных типов: целыми и вещественными числами, символами, стро ками, массива-
ми. Типы данных определяют способ хранения чисел или символо в в памяти
компьютера. Они задают размер ячейки, в которую будет записан о то или иное
значение, определяя тем самым его максимальную величину ил и точность за-
дания. Участок памяти (ячейка), в котором хранится значение определённого
типа, называется переменной. У переменной есть имя (иденти фикатор) и значе-
ние. Имя служит для обращения к области памяти, в которой хра нится значение.
Во время выполнения программы значение переменной можно из менить. Перед
использованием любая переменная должна быть описана. Опера тор описания
переменных в языке С++имеет вид:
тип имя_переменной;
или тип список_переменных;
Типы данных языка С++можно разделить на основные и составные.
К основным типам данных языка относят:
• char  символьный;
• int  целый;
• float  с плавающей точкой;
• double  двойной точности;
• bool  логический.
Для формирования других типов данных используют основные ти пы и так
называемые спецификаторы. Типы данных, созданные на базе с тандартных ти-
пов с использованием спецификаторов, называют составными т ипами данных. В
С++ определены четыре спецификатора типов данных:
• short  короткий;
• long  длинный;
• signed  знаковый;
• unsigned  беззнаковый.
Далее будут рассмотрены назначение и описание каждого типа .
2.2.1 Символьный тип Данные типа charв памяти компьютера занимают один байт 1
. Это связано с
тем, что обычно под величину символьного типа отводят столь ко памяти, сколь-
1
В кодировке utf-8 каждый символ кириллицы занимает 2 байта.
Программирование на языке С++ в среде Qt Creator

2.2. Данные19
ко необходимо для хранения любого из 256 символов клавиатуры. Символьный
тип может быть со знаком или без знака (табл. 2.1).
Таблица 2.1: Символьные типы данных
Тип Диапазон Размер
char –128. . . 127 1 байт
unsigned char 0. . . 255 1 байт
signed char –128. . . 127 1 байт
Пример описания символьных переменных:
c h a r c , s t r ; / /Описаны две символьные переменные.
При работе с символьными данными нужно помнить, что если в вы ражении
встречается одиночный символ, он должен быть заключён в один арные кавычки.
Например, ’a’,’b’ ,’+’ ,’3’ .
Последовательность символов, то есть строка, при использо вании в выраже-
ниях заключается в двойные кавычки: "Hello!".
2.2.2 Целочисленный тип Переменная типа intв памяти компьютера может занимать два, четыре или
восемь байтов. Это зависит от разрядности процессора.
Диапазоны значений целого типа представлены в таблице 2.2. По умолча-
нию все целые типы считаются знаковыми, т.е. спецификатор signedможно не
указывать.
Таблица 2.2: Целые типы данных
Тип Диапазон Размер
int –2147483647 . . . 2147483647 4 байта
unsigned int 0 . . . 4294967295 4 байта
signed int –2147483647 . . . 2147483647 4 байта
short int –32767 . . . 32767 2 байта
long int –2147483647 . . . 2147483647 4 байта
unsigned short int 0 . . . 65535 2 байта
signed short int –32767 . . . 32767 2 байта
long long int –(263
–1) . . . ( 263
–1) 8 байт
signed long int –2147483647 . . . 2147483647 4 байта
unsigned long int 0 . . . 4294967295 4 байта
unsigned long long int 0 . . . 264
–1 8 байт
Пример описания целочисленных данных:
i n t a , b , c ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

20Глава 2. Общие сведения о языкеС++
u n s i g n e d l o n g i n tA , B , C ;
2.2.3 Вещественный тип Внутреннее представление вещественного числа в памяти ком пьютера отли-
чается от представления целого числа. Число с плавающей точк ой представлено
в экспоненциальной форме mE±p, где m мантисса (целое или дробное число с
десятичной точкой), p порядок (целое число). Для того чтобы перевести число
в экспоненциальной форме к обычному представлению с фиксир ованной точкой,
необходимо мантиссу умножить на десять в степени порядок. Н апример,
− 6.42 E + 2 = −6.42 ·10 2
= −642 ,
3 .2 E −6 = 3 .2 ·10 −
6
= 0 .0000032
Обычно величины типа floatзанимают 4 байта, из которых один двоичный
разряд отводится под знак, 8 разрядов под порядок и 23 под ман тиссу. Поскольку
старшая цифра мантиссы всегда равна 1, она не хранится. Величины типа doubleзанимают 8 байт, в них под порядок и мантиссу от-
водится 11 и 52 разряда соответственно. Длина мантиссы опре деляет точность
числа, а длина порядка его диапазон. Спецификатор типа longперед именем
типа double указывает, что под величину отводится 10 байт.
Диапазоны значений вещественного типа представлены в табл ице 2.3.
Таблица 2.3: Вещественные типы данных
Тип Диапазон Размер
float 3.4Е-38 . . . 3.4E+38 4 байта
double 1.7Е-308 . . . 1.7E+308 8 байт
long double 3.4Е-4932 . . . 3.4E+4932 10 байт
Пример описания вещественных переменных:
double x1 , x2 , x 3 ;
f l o a t X , Y , Z ;
2.2.4 Логический тип Переменная типа boolможет принимать только два значения true(истина)
или false (ложь). Любое значение не равное нулю интерпретируется как true, а
при преобразовании к целому типу принимает значение равное 1. Значениеfalse
представлено в памяти как 0.
Пример описания данных логического типа:
b o o l F , T ;
Программирование на языке С++ в среде Qt Creator

2.3. Константы21
2.2.5 Тип void
Множество значений этого типа пусто. Он используется для оп ределения
функций, которые не возвращают значения, для указания пусто го списка ар-
гументов функции, как базовый тип для указателей и в операци и приведения
типов.
2.3 Константы
Константы это величины, которые не изменяют своего значения в процессе
выполнения программы. Оператор описания константы имеет в ид:
сonst тип имя_константы = значение;
Константы в языке С++могут быть целыми, вещественными, символьными
или строковыми. Обычно компилятор определяет тип констант ы по внешнему
виду, но существует возможность и явного указания типа, нап ример,
const double pi=3.141592653589793;
Кроме того, константа может быть определена с помощью дирек тивы2
#define . Эта директива служит для замены часто использующихся конст ант,
ключевых слов, операторов или выражений некоторыми идентиф икаторами.
Идентификаторы, заменяющие текстовые или числовые констан ты, называют
именованными константами. Основная форма синтаксиса дире ктивы следующая:
#d e f i n e идентификатор текст
Например,
#d e f i n e P I 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3
i n t m a i n ( )
. . .
2.4 Структурированные типы данных
Структурированный тип данных характеризуется множествен ностью образу-
ющих его элементов. В C++это массивы, строки, структуры и файлы.
Массив  совокупность данных одного и того же типа 3
. Число элементов
массива фиксируется при описании типа и в процессе выполнен ия программы не
изменяется.
В общем виде массив можно описать так:
тип имя [размерность_1][размерность_2]...[размерность_N];
Например,
f l o a t x [ 1 0 ] ; / /Описан массив из 10 вещественных чисел.
i n t a [ 3 ] [ 4 ] ; / /Описан двумерный целочисленный массив, матрица из 3-х строк и 4-х столбцов.
double b [ 2 ] [ 3 ] [ 2 ] ; / /Описан трехмерный массив.
Для доступа к элементу массива достаточно указать его поряд ковый номер, а
если массив многомерный (например, таблица), то несколько номеров:
2
Структура программы и директивы описаны в п. 2.8
3 Подробно работа с одномерными и двумерными массивами описа на в главах 5 и 6.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

22Глава 2. Общие сведения о языкеС++
имя_массива[номер_1][номер_2]...[номер_N]
Например:x[5],a[2][3] ,b[1][2][2] .
Элементы массива в С++нумеруются с нуля. Первый элемент, всегда имеет
номер ноль, а номер последнего элемента на единицу меньше за данной при его
описании размерности: c h a r C [ 5 ] ; / /Описан массив из 5 символов, нумерация от 0 до 4.
Строка  последовательность символов 4
. В С++ строки описывают как массив
элементов типа char. Например:
c h a r s [ 2 5 ] ; / /Описана строка из 25 символов.
Структура 5
это тип данных, который позволяет объединить разнородные д анные
и обрабатывать их как единое целое.
Например
s t r u c t f r a c t i o n / /Объявлена структура правильная дробь.
{
/ / Определяем поля структуры:
i n t num ; / /поле числитель,
i n t d e n ; / /поле знаменатель.
} . . .
f r a c t i o n d , D [ 2 0 ] ; / /Определена переменная d, массив D[20], типа fraction.
. . .
d . num ; / /Обращение к полю num переменной d.
D [ 4 ] . d e n ; / /Обращение к полю den четвёртого элемента массива D.
2.5 Указатели
Указатели широко применяются в С++. Можно сказать, что именно наличие
указателей сделало этот язык удобным для программирования . С другой сторо-
ны это одна из наиболее сложных для освоения возможностей С++. Идея работы с
указателями состоит в том, что пользователь работает с адре сом ячейки памяти.
Как правило, при обработке оператора объявления переменно й
тип имя_переменной;
компилятор автоматически выделяет память под переменную
имя_переменной в соответствии с указанным типом:
c h a r C ;/ /Выделена память под символьную переменную C
Доступ к объявленной переменной осуществляется по её имени . При этом все об-
ращения к переменной заменяются на адрес ячейки памяти, в кот орой хранится
её значение. При завершении программы или функции, в которо й была описана
переменная, память автоматически освобождается.
Доступ к значению переменной можно получить иным способом  определить
собственные переменные для хранения адресов памяти. Такие переменные назы-
вают указателями. С помощью указателей можно обрабатывать м ассивы, строки
и структуры, создавать новые переменные в процессе выполне ния программы,
4
Работа со строками описана в главе 8
5 Работа со структурами описана в главе 9.
Программирование на языке С++ в среде Qt Creator

2.6. Операции и выражения23
передавать адреса фактических параметров функциям и адреса функций в ка-
честве параметров. Итак, указатель это переменная, значением которой являетс я адрес памяти,
по которому хранится объект определённого типа (другая пер еменная). Напри-
мер, если С это переменная типа char, а Р  указатель на С, знач ит в Р находится
адрес по которому в памяти компьютера хранится значение пере менной С.
Как и любая переменная, указатель должен быть объявлен. При о бъявлении
указателей всегда указывается тип объекта, который будет х раниться по данному
адресу: тип *имя_переменной;
Например:
i n t ∗ p ; / /По адресу, записанному в переменной p, будет храниться перем енная типа int
Звёздочка в описании указателя, относится непосредственн о к имени, поэтому
чтобы объявить несколько указателей, её ставят перед имене м каждого из них:
f l o a t ∗ x , y , ∗ z ; / /Описаны указатели на вещественные числа xи z(сами вещественные
/ / значения  *x,*z ), а так же вещественная переменная y, её адрес  &y.
2.6 Операции и выражения Выражение задаёт порядок выполнения действий над данными и состоит из
операндов (констант, переменных, обращений к функциям), к руглых скобок и
знаков операций. Операции делятся на унарные (например, -с) и бинарные (на-
пример, а+b). В таблице 2.4 представлены основные операции языка С++.
Таблица 2.4: Основные операции языка С++
Операция Описание
Унарные операции
++ увеличение значения на единицу
-- уменьшение значения на единицу
˜ поразрядное отрицание
! логическое отрицание
- арифметическое отрицание (унарный минус)
+ унарный плюс
& получение адреса
* обращение по адресу
(type) преобразование типа
Бинарные операции
+ сложение
- вычитание
* умножение
/ деление
% остаток от деления
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

24Глава 2. Общие сведения о языкеС++
Таблица 2.4  продолжение
Операция Описание
<< сдвиг влево
>> сдвиг вправо
< меньше
> больше
<= меньше или равно
>= больше или равно
== равно
!= не равно
& поразрядная конъюнкция (И)
ˆ поразрядное исключающее ИЛИ
| поразрядная дизъюнкция (ИЛИ)
&& логическое И
|| логическое ИЛИ
= присваивание
*= умножение с присваиванием
/= деление с присваиванием
+= сложение с присваиванием
-= вычитание с присваиванием
%= остаток от деления с присваиванием
<<= сдвиг влево с присваиванием
>>= сдвиг вправо с присваиванием
&= поразрядная конъюнкция с присваиванием
|= поразрядная дизъюнкция с присваиванием
^= поразрядное исключающее ИЛИ с присваиванием
Другие операции
? условная операция
, последовательное вычисление
sizeof определение размера
(тип) преобразование типа
Перейдём к подробному рассмотрению основных операций язык а.
2.6.1 Операции присваивания Обычная операция присваивания имеет вид: имя_переменной=значение;
где значение это выражение, переменная, константа или функция. Выпол-
няется операция так. Сначала вычисляется значение выражен ия указанного в
правой части оператора, а затем его результат записывается в область памяти,
имя которой указано слева.
Например,
Программирование на языке С++ в среде Qt Creator

2.6. Операции и выражения25
b = 3 ;/ /Переменной b присваивается значение, равное трём.
a=b ; / /Переменной а присваивается значение b.
c=a +2∗b ; / /Переменной c присваивается значение выражения.
c=c + 1 ; / /Значение переменой с увеличивается на единицу.
a=a ∗ 3 ; / /Значение переменой а увеличивается в три раза.
Задача 2.1. Пусть в переменной ахранится значение, равное 3, а в переменную
b записали число 5. Поменять местами значения переменных аи b.
Для решения задачи понадобится дополнительная переменная c(см. рис. 2.1).
В ней временно сохраняется значение переменной а. Затем, значение переменной
b записывается в переменную a, а значение переменной cв переменную b.
c=a ; / /Шаг 1. с=3
a=b ; / /Шаг 2. a=5
b=c ; / /Шаг 3. b=3
Рис. 2.1: Использование буферной переменной
Если в операторе присваивания левая и правая часть это перем енные разных
типов, то происходит преобразование : значение переменной в правой части пре-
образуется к типу переменной в левой части. Следует учитыва ть, что при этом
можно потерять информацию или получить другое значение. ВС++ существует возможность присваивания нескольким переменн ым одного
и того же значения. Такая операция называется множественным присваиванием
и в общем виде может быть записана так: имя_1 = имя_2 = ... = имя_N = значение;
Запись a=b=c=3.14159/6; означает, что переменным a, b и cбыло присвоено
одно и то же значение 3.14159/6.
Операции + =,− =,∗ =,/ = называют составным присваиванием . В таких
операциях при вычислении выражения стоящего справа исполь зуется значение
переменной из левой части, например так: x+=p ; / /Увеличение x на p, то же что и x=x+p.
x − =p ; / /Уменьшения x на p, то же что и x=x-p.
x∗=p ; / /Умножение x на p, то же что и x=x*p.
x/=p ; / /Деление x на p, то же что и x=x/p.
2.6.2 Арифметические операции Операции +, −, ∗, / относят к арифметическим операциям . Их назначе-
ние понятно и не требует дополнительных пояснений. При прог раммировании
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

26Глава 2. Общие сведения о языкеС++
арифметических выражений следует придерживаться простых правил. Соблю-
дать очерёдность выполнения арифметических операций. Сна чала выполняются
операции умножения и деления (1-й уровень), а затем сложени я и вычитания
(2-й уровень). Операции одного уровня выполняются последов ательно друг за
другом. Для изменения очерёдности выполнения операций исп ользуют скобки.
Таблица 2.5 содержит примеры записи алгебраических выраже ний.
Таблица 2.5: Примеры записи алгебраических выражений
Математическая запись Запись на языке С++
2·a + b·(c + d) 2*a+b*(c+d)
3 ·a
+ b c+ d 3*(a+b)/(c+d)
3·a − 2·b
c ·d (3*a-2*b)/(c*d) или (3*a-2*b)/c/d
(b − a)2
c
+ 1 d
− 2−
a
2
+ 1
b2
+ cd (b-a)*(b-a)/(c+1/(d-2))- (a*a+1)/(b*b+c*d)
Операции инкремента ++идекремента -- так же причисляют к арифмети-
ческим, так как они выполняют увеличение и уменьшение на един ицу значения
переменной. Эти операции имеют две формы записи: префиксную (операция за-
писывается перед операндом) и постфиксную (операция запис ывается после опе-
ранда). Так, например оператор p=p+1;можно представить в префиксной фор-
ме ++p; и в постфиксной p++;. Эти формы отличаются при использовании их в
выражении. Если знак декремента (инкремента) предшествуе т операнду, то сна-
чала выполняется увеличение (уменьшение) значения операн да, а затем операнд
участвует в выражении. Например, x = 1 2 ;
y=++x ; / /В переменных x и y будет храниться значение 13.
Если знак декремента (инкремента) следует после операнда, то сначала опе-
ранд участвует в выражении, а затем выполняется увеличение (уменьшение)
значения операнда: x = 1 2 ;
y=x++; / /Результат  число 12 в переменной y, а в x  13.
Остановимся на операциях целочисленной арифметики .
Операция целочисленного деления /возвращает целую часть частного (дроб-
ная часть отбрасывается) в том случае, если она применяется к целочисленным
операндам, в противном случае выполняется обычное деление :11 /4 = 2 или
11 .0 /4 = 2 .75 .
Операция остаток от деления %применяется только к целочисленным опе-
рандам: 11%4 = 3 .
К операциям битовой арифметики относятся следующие операции:&, |, ˆ,
˜ , << ,>> . В операциях битовой арифметики действия происходят над дв оичным
представлением целых чисел.
Программирование на языке С++ в среде Qt Creator

2.6. Операции и выражения27
Арифметическое И(& ). Оба операнда переводятся в двоичную систему, затем
над ними происходит логическое поразрядное умножение опер андов по следую-
щим правилам:
1&1=1, 1&0=0, 0&1=0, 0&0=0.
Например, если А=14иВ=24 , то их двоичное представление 
А=0000000000001110 иВ=0000000000011000 . В результате логического умноже-
ния A and B получим 0000000000001000 или 8 в десятичной системе счисления
(рис. 2.2). Таким образом, A&B=14&24=8.
Рис. 2.2: Пример логического умно-
жения Рис. 2.3: Пример логического сложе- ния
Арифметическое ИЛИ (|). Здесь также оба операнда переводятся в двоич-
ную систему, после чего над ними происходит логическое пора зрядное сложение
операндов по следующим правилам:
1|1=1, 1|0=1, 0|1=1, 0|0=0.
Например, результат логического сложения чисел А=14иВ=24 будет равен A
|B=30 (рис. 2.3).
Арифметическое исключающее ИЛИ (ˆ). Оба операнда переводятся в двоич-
ную систему, после чего над ними происходит логическая пора зрядная операция
ˆ по следующим правилам:
1ˆ1=0, 1ˆ0=1, 0ˆ1=1, 0ˆ0=0.
Арифметическое отрицание (˜). Эта операция выполняется над одним опе-
рандом. Применение операции ˜ вызывает побитную инверсию д воичного пред-
ставления числа (рис. 2.4).
Рис. 2.4: Пример арифметического отрицания
Сдвиг влево (M< влево на Lпозиций. Рассмотрим операцию 15 << 3. Число 15 в двоичной си-
стеме имеет вид 1111. При сдвиге его на 3 позиции влево получим 1111000. В
десятичной системе это двоичное число равно 120. Итак, 15 << 3 =120 (рис. 2.5).
Заметим, что сдвиг на один разряд влево соответствует умнож ению на два, на
два разряда  умножению на четыре, на три  умножению на восем ь. Таким
образом, операция M << Lэквивалентна умножению числа Mна 2 в степени L.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

28Глава 2. Общие сведения о языкеС++
Рис. 2.5: Пример операции Сдвиг
влево Рис. 2.6: Пример операции Сдвигвправо
Сдвиг вправо (M>>L ). Число M, представленное в двоичной системе, сдвигается
вправо на Lпозиций, что эквивалентно целочисленному делению числа Mна 2 в
степени L. Например, 15 >> 1=7(рис. 2.6),15 >> 3= 2 .
2.6.3 Логические операции ВС++ определены следующие логические операции || (или), &&(и), !(не).
Логические операции выполняются над логическими значениям иtrue (истина)
и false (ложь). В языке Сложь  0, истина  любое значение 6
= 0. В таблице 2.6
приведены результаты логических операций.
Таблица 2.6: Логические операции
A B !A A&&B A||B
0 0 1 0 0
0 1 1 0 1
1 0 0 0 1
1 1 0 1 1
2.6.4 Операции отношения
Операции отношения возвращают в качестве результата логическое значе-
ние. Таких операций шесть: >, >= ,<, <= ,== ,!= . Результат операции отношения
 логическое значение true(истина) или false(ложь).
2.6.5 Условная операция Для организации разветвлений в простейшем случае можно исп ользовать
условную операцию ? :. Эта операция имеет три операнда и в общем виде мо-
жет быть представлена так:
условие ? выражение1 : выражение2;
Работает операция следующим образом. Если условие истинно ( не равно 0),
то результатом будет выражение1, в противном случае выражение2. Например,
операция y=x<0 ? -x : x; записывает в переменную yмодуль числа х.
Программирование на языке С++ в среде Qt Creator

2.6. Операции и выражения29
2.6.6 Операция преобразования типа
Для приведения выражения к другому типу данных в С++существует опера-
ция преобразования типа :
(тип) выражение;
Например, в результате действий x=5; y=x/2; z=(float) x/2;переменная
y примет значение равное 2 (результат целочисленного делени я), а переменная
z = 2.5 .
2.6.7 Операция определения размера Вычислить размер объекта или типа в байтах можно с помощью операции
определения размера , которая имеет две формы записи:
sizeof (тип); илиsizeof выражение;
Например, предположим, что была описана целочисленная пер еменнаяint
k=3; . Исходя из того, что тип intзанимает в памяти 4 байта, в переменную
m=sizeof k; будет записано число 4.
В результате работы команд double z=123.456; p=sizeof (k+z); значение
переменной pстало равно 8, т. к. вещественный тип doubleболее длинный (8
байтов) по сравнению с типом int(4 байта) и значение результата было преоб-
разовано к более длинному типу. В записи операции sizeof (k+z)были исполь-
зованы скобки. Это связано с тем, что операция определения т ипа имеет более
высокий приоритет, чем операция сложения. При заданном зна ченииz=123.456 ;
та же команда, но без скобок p=sizeof k+z;вычислитp=4+123.456=127.456.
Команда s = sizeof "Hello"; определит, что под заданную строку в памяти
было выделено s=6байтов, т. к. объект состоит из 5 символов и один байт на
символ окончания строки.
2.6.8 Операции с указателями
При работе с указателями часто используют операции получения адреса&и
разадресации *(табл. 2.7).
Таблица 2.7: Операции получения адреса &и разадресации *
Описание Адрес Значение, хранящееся по адресу
тип *p p *p
тип p &p p
Операция получения адреса &возвращает адрес своего операнда. Например:
f l o a t a ; / /Объявлена вещественная переменная а
f l o a t ∗a d r _ a ; / /Объявлен указатель на тип float
a d r _ a=&a ; / /Оператор записывает в переменную adr_a адрес переменной a
Операция разадресации *возвращает значение переменной, хранящееся по
заданному адресу, т.е. выполняет действие, обратное опера ции&:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

30Глава 2. Общие сведения о языкеС++
f l o a ta ; / /Объявлена вещественная переменная а.
f l o a t ∗a d r _ a ; / /Объявлен указатель на тип float.
a= ∗a d r _ a ; / /Оператор записывает в переменную aвещественное значение,
/ / хранящееся по адресу adr_a.
К указателям применяют операцию присваивания. Это значит, что значение
одного указателя можно присвоить другому. Если указатели о дного типа, то для
этого применяют обычную операцию присваивания:
/ / Описана вещественная переменная и два указателя.
f l o a t P I = 3 . 1 4 1 5 9 , ∗p1 , ∗p 2 ;
/ / В указатели p1 и p2 записывается адрес переменной PI.
p 1=p 2=&P I ;
Если указатели ссылаются на различные типы, то при присваива нии значения
одного указателя другому, необходимо использовать преобр азование типов. Без
преобразования можно присваивать любому указателю указате льvoid* .
Рассмотрим пример работы с указателями различных типов:
f l o a t P I = 3 . 1 4 1 5 9 ; / /Объявлена вещественная переменная.
f l o a t ∗p 1 ; / /Объявлен указатель на float.
double ∗p 2 ; / /Объявлен указатель на double.
p 1=&P I ; / /Переменной p1присваивается значение адреса PI.
p 2 =( double ∗) p 1 ; / /Указателю на doubleприсваивается значение,
/ / которое ссылается на тип float.
В указателях p1иp2 хранится один и тот же адрес ( p1=0012FF7C), но значе-
ния, на которые они ссылаются разные ( *p1=3.14159,*p2=2.642140e-308 ). Это
связано с тем, указатель типа *floatадресует 4 байта, а указатель *double
8 байт. После присваивания p2=(double *)p1;при обращении к*p2происходит
следующее: к переменной, хранящейся по адресу p1, дописывается ещё следую-
щих 4 байта из памяти. В результате значение *p2не совпадает со значением
*p1 .
Таким образом, при преобразовании указателей разного типа приведение ти-
пов разрешает только синтаксическую проблему присваивани я. Следует пом-
нить, что операция *над указателями различного типа, ссылающимися на один
и тот же адрес, возвращает различные значения.
Над адресами С++определены следующие арифметические операции :
• сложение и вычитание указателей с константой ;
• вычитание одного указателя из другого ;
• инкремент ;
• декремент .
Сложение и вычитание указателей с константой nозначает, что указатель
перемещается по ячейкам памяти на столько байт, сколько зан имаетnперемен-
ных того типа, на который он указывает. Например, пусть указ атель имеет сим-
вольный тип, и его значение равно 100. Результат сложения эт ого указателя с
единицей  101, так как для хранения переменной типа charтребуется один
байт. Если же значение указателя равно 100, но он имеет целоч исленный тип, то
результат его сложения с единицей будет составлять 104, так как для переменной
типа intотводится четыре байта.
Программирование на языке С++ в среде Qt Creator

2.7. Стандартные функции31
Эти операции применимы только к указателям одного типа и имеют смысл в
основном при работе со структурными типами данных, наприме р массивами.
Фактически получается, что значение указателя изменяется на величину
sizeof(тип) . Если указатель на определённый тип увеличивается или умен ь-
шается на константу, то его значение изменяется на величину этой константы,
умноженную на размер объекта данного типа. Например: / / Объявление массива из 10 элементов.
double mas [ 1 0 ] = { 1 . 2 9 , 3 . 2 3 , 7 . 9 8 , 5 . 5 4 , 8 . 3 2 , 2 . 4 8 , 7 . 1 } ;
double ∗p 1 ; / /Объявление указателя на double
p 1=&mas [ 0 ] ; / /Присвоение указателю адреса нулевого элемента массива.
p 1=p 1 + 3 ; / /Увеличение значения адреса на 3*8=24 (размер типа double), в результате указатель
/ / сместится на три ячейки, размером double каждая.
Вычитание двух указателей определяет, сколько переменных данного типа
размещается между указанными ячейками. Разность двух указ ателей это раз-
ность их значений, делённая на размер типа в байтах. Так разн ость указателей
на третий и нулевой элементы массива равна трём, а на третий и девятый 
шести. Суммирование двух указателей не допускается. Операции инкремента идекремента , соответственно, увеличивают или
уменьшают значение адреса: double ∗p 1 ;
f l o a t ∗p 2 ;
i n t ∗i ;
p 1++; / /Увеличение значения адреса на 8.
p 2++; / /Увеличение значения адреса на 4.
i ++; / /Увеличение значения адреса на 4.
К указателям так же применимы операции отношения ==,!= ,<, >, <= ,>= .
Иными словами, указатели можно сравнивать. Например, если iуказывает на
пятый элемент массива, а jна первый, то отношение i > jистинно. Кроме
того, любой указатель всегда можно сравнить на равенство с ко нстантой нуле-
вого указателя (NULL)6
. Однако все эти утверждения верны, если речь идёт об
указателях, ссылающихся на один массив. В противном случае р езультат ариф-
метических операций и операций отношения будет не определё н.
2.7 Стандартные функции ВC++ определены стандартные функции над арифметическими операнда-
ми 7
. В таблице 2.8 приведены некоторые из них.
Таблица 2.8: Стандартные математические функции
Обозначение Действие
abs(x) Модуль целого числа x
6
Константу нулевого указателя можно присвоить любому указа телю и такой указатель при
сравнении не будет равен любому реальному указателю. 7Работа с математическими функциями возможна только при под ключении библиотеки
math.h (п. 2.6)
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

32Глава 2. Общие сведения о языкеС++
Таблица 2.8  продолжение
Обозначение Действие
fabs(x) Модуль вещественного числаx
sin(x) Синус числаx
cos(x) Косинус числа x
tan(x) Тангенс числаx
atan(x) Арктангенс числа x, x ∈ (− 2
; 2
) acos(x) Арккосинус числа
x
asin(x) Арксинус числаx
exp(x) Экспонента,ex
log(x) Натуральный логарифм, (
x >0)
log10(x) Десятичный логарифм, ( x >0)
sqrt(x) Корень квадратный, ( x >0)
pow(x,y) Возведение числа xв степень y
ceil(x) Округление числа xдо ближайшего большего целого
floor(x) Округление числа xдо ближайшего меньшего целого
Примеры записи математических выражений с использованием встроенных
функций представлены в таблице 2.9.
Таблица 2.9: Примеры записи математических выражений
Математическая запись Запись на языке С++
3
p(
a + b)2 pow((a+b)
∗(a+b),1./3) или
pow(pow(a+b,2),1./3)
cos 4
(x ) pow(cos(x), 4)
e2
x exp(2 ∗x)
e 5 sin(
x 2
) exp(5
∗sin(x/2))
sin 2
(√ x
) pow(sin(sqrt(x)) ,2)
ln( |x − 2|) log ( fabs (x −2))
log
ba log (a)/log(b)
lg
(x 2
+ 1)
lg (4) log10(x ∗x+1)/log10(4)
sin( x2
+ y2
) + cos (
x 2
+ y2
) 2 ·y +p x
2
+ y2 z=x
∗x+y ∗y; sin (z)+cos(z/(2 ∗y))+sqrt(z);
Определённую проблему представляет применение функции pow(x,y). При
программировании выражений, содержащих возведение в степ ень, надо внима-
тельно проанализировать значения, которые могут принимат ьx иy, так как в
некоторых случаях возведение xв степень yневыполнимо.
Так, ошибка возникает, если x отрицательное число, а y дробь. Предполо-
жим, что y правильная дробь вида k
m
. Если знаменатель
mчётный, это означа-
ет вычисление корня чётной степени из отрицательного числа , а значит, операция
Программирование на языке С++ в среде Qt Creator

2.8. Структура программы33
не может быть выполнена. В противном случае, если знаменательmнечётный,
можно воспользоваться выражением z = –pow(fabs(x),y). Например, вычисле-
ние кубического корня из вещественного числа можно предста вить командой:
z=(x<0)? −pow(fabs(x),( double)1/3): pow(x,( double)1/3);
2.8 Структура программы Программа на языкеС++состоит из функций,описаний идиректив препро-
цессора .
Одна из функций должна обязательно носить имя main. Элементарное опи-
сание функции имеет вид:
тип_результата имя_функции (параметры) { оператор1;
оператор2;
...
операторN;
}
Здесь, тип_результата  это тип того значения, которое функция должна вы-
числить (если функция не должна возвращать значение, указы вается типvoid),
имя_функции  имя, с которым можно обращаться к этой функции, параметры
список аргументов функции (может отсутствовать), оператор1,оператор2 ,... ,
операторN  операторы, представляющие тело функции, они обязательно з аклю-
чаются в фигурные скобки и каждый оператор заканчивается точ кой с запятой.
Как правило, программа на С++состоит из одной или нескольких, не вложенных
друг в друга, функций.
Основному тексту программы предшествуют директивы препроцессора, пред-
назначенные для подключения библиотек , которые в общем виде выглядят так:
#i n c l u d e <имя_библиотеки >
Каждая такая строка даёт компилятору команду присоединить программный
код, который хранится в отдельном файле с расширением .h. Такие файлы назы-
вают файлами заголовков . С их помощью можно выполнять ввод-вывод данных,
работать с математическими функциями, преобразовывать да нные, распреде-
лять память и многое другое. Например, описание стандартны х математических
функций находится в заголовочном файле math.h.
Общую структуру программы на языке С++можно записать следующим об-
разом:
директивы препроцессора
описание глобальных переменных
тип_результата имя1(параметры1) {
описание переменных функции имя1; операторы1;
}
тип_результата имя2(параметры2) {
описание переменных функции имя2;
операторы2;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

34Глава 2. Общие сведения о языкеС++
}
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
тип_результата имяN(параметрыN) {
описание переменных функции имяN;
операторыN;
}
тип_результата main(параметры) {
описание переменных главной функции;
операторы главной функции;
}
По месту объявления переменные в языке Си можно разделить на три класса:
локальные, глобальные и формальные параметры функции.
Локальные переменные объявляются внутри функции и доступны только в
ней. Например:
i n t f 1 ( )
{ / /В функции f1описана другая переменная s,
i n t s ;
s = 6 ; / /ей присвоено значение 6 .
} i n t f 2 ( )
{ / /В функции f2определена ещё одна переменная s,
l o n g i n t s ;
s = 2 5 ; / /ей присвоено значение 25.
}
i n t m a i n ( )
{
/ /В функции mainопределена вещественная переменная s,
f l o a t s ;
s = 4 . 5 ; / /и ей присвоено значение 4.5.
}
Глобальные переменные описываются до всех функций и доступны из любого
места программы. Например:
f l o a t s ;/ /Определена глобальная переменная s .
i n t f 1 ( )
{
/ /В функции f1переменной sприсваивается значение 6 .
s = 6 ;
} i n t f 2 ( )
{
/ /В функции f2переменной sприсваивается значение 2.1.
s = 2 . 1 ;
} i n t m a i n ( )
{ / /В главной функции переменной sприсваивается значение 4 . 5 .
s = 4 . 5 ;
}
Формальные параметры функций описываются в списке параметр ов функ-
ции. Работа с функциями подробно описана в главе 4.
Программирование на языке С++ в среде Qt Creator

2.9. Ввод и вывод данных35
2.9 Ввод и вывод данных
Ввод-вывод данных в языкеС++осуществляется либо с помощью функций
ввода-вывода в стиле С, либо с использованием библиотеки классов С++. Пре-
имущество объектов С++в том, что они легче в использовании, особенно если
ввод-вывод достаточно простой. Функции ввода-вывода, уна следованные отС
громоздкие, но более гибко управляют форматированным вывод ом данных.
Функция
printf(строка форматов, список выводимых переменных);
выполняет форматированный вывод переменных, указанных в списке, в соот-
ветствии со строкой форматов. Функция
scanf(строка форматов, список адресов вводимых переменных);
выполняет ввод переменных , адреса которых указанны в списке, в соответ-
ствии со строкой форматов. Строка форматов содержит символы, которые будут выводиться на экран
или запрашиваться с клавиатуры, и так называемые специфика ции.Специфи-
кации это строки, которые начинаются символом %и выполняют управление
форматированием: % флаг ширина . точность модификатор тип
Параметры флаг,ширина ,точность имодификатор в спецификациях могут
отсутствовать. Значения параметров спецификаций приведе ны в таблице 2.10.
Таблица 2.10: Символы управления
Параметр Назначение
Флаги
- Выравнивание числа влево. Правая сторона дополняется
пробелами. По умолчанию выравнивание вправо.
+ Перед числом выводится знак + или -
Пробел Перед положительным числом выводится пробел, перед
отрицательным –
# Выводится код системы счисления: 0 перед восьмерич-
ным числом, 0х(0Х ) перед шестнадцатеричным числом.
Ширина
n Ширина поля вывода. Если nпозиций недостаточно, то
поле вывода расширяется до минимально необходимого.
Незаполненные позиции заполняются пробелами.
0n То же, что и n, но незаполненные позиции заполняются
нулями.
Точность
ничего Точность по умолчанию
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

36Глава 2. Общие сведения о языкеС++
Таблица 2.10  продолжение
Параметр Назначение
n Для типовe, E, f выводить nзнаков после десятичной
точки
Модификатор
h Для d, i, o, u, x, X тип short int .
l Дляd, i, o, u, x, X тип long int .
Тип
с Символьный тип char.
d Десятичное intсо знаком.
i Десятичное intсо знаком.
o Восьмеричное int unsigned.
u Десятичноеint unsigned .
x, X Шестнадцатеричное int unsigned, прихиспользуются
символы a-f , при Х A-F.
f Значение со знаком вида [-]dddd.dddd.
e Значение со знаком вида [-]d.dddde[+|-]ddd.
E Значение со знаком вида [-]d.ddddE[+|-]ddd.
g Значение со знаком типа eили fв зависимости от зна-
чения и точности.
G Значение со знаком типа eили Fв зависимости от зна-
чения и точности.
s Строка символов.
Кроме того, строка форматов может содержать некоторые спец иальные сим-
волы, которые приведены в таблице 2.11.
Таблица 2.11: Специальные символы
Символ Назначение
\b Сдвиг текущей позиции влево.
\n Перевод строки.
\r Перевод в начало строки, не переходя на новую строку.
\t Горизонтальная табуляция.
\’ Символ одинарной кавычки.
\” Символ двойной кавычки.
\? Символ?
Первой строкой программы, в которой будут применяться функ ции ввода-
вывода языка С, должна быть директива #include . Заголовочный
файл stdio.h содержит описание функций ввода-вывода.
Рассмотрим работу функций на примере следующей задачи.
Программирование на языке С++ в среде Qt Creator

2.9. Ввод и вывод данных37
Задача 2.2.Знаяa, b, c  длины сторон треугольника, вычислить площадь S
и периметр Pэтого треугольника.
Входные данные: a, b, c. Выходные данные: S, P.
Для вычисления площади применим формулу Герона:
S = p
r
·(r − a) ·(r − b) ·(r − c), где r= a
+ b+ c 2  полупериметр.
Далее приведены две программы для решения данной задачи и ре зультаты
их работы (рис. 2.7–2.8). / / ЗАДАЧА 2.2 Вариант первый
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d i o . h>
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t a , b , c , S , r ; / /Описание переменных.
p r i n t f ( " a = ") ; / /Вывод на экран символов a=.
/ / В функции scanf для вычисления адреса переменной применяетс я операция &.
s c a n f ( " % f ",& a ) ; / /Запись в переменную а значения введённого с клавиатуры .
p r i n t f ( " b = ") ; / /Вывод на экран символов b=.
s c a n f ( " % f ",& b ) ; / /Запись в переменную b значения введённого с клавиатуры.
p r i n t f ( " c = ") ; / /Вывод на экран символов c=
s c a n f ( " % f ",& c ) ; / /Запись в переменную cзначения введённого с клавиатуры.
r =( a+b+c ) / 2 ; / /Вычисление полупериметра.
S= s q r t ( r ∗( r −a ) ∗( r −b ) ∗( r −c ) ) ; / /Вычисление площади треугольника.
p r i n t f ( " S = % 5 . 2 f \ t " , S ) ;/ /Вывод символов S=, значения S и символа табуляции \t.
/ / Спецификация %5.2fозначает, что будет выведено вещественное
/ / число из пяти знаков, два из которых после точки.
p r i n t f ( " p = % 5 . 2 f \ n " , 2∗r ) ; / /Вывод символов p=, значения выражения 2*r
/ / и символа окончания строки.
/ / Оператор printf("S=%5.2f \t p=%5.2f \n",S,2*r) выдаст тот же результат.
r e t u r n 0 ;
}
Рис. 2.7: Результаты работы программы к задаче 2.2 (вариант 1)
/ / ЗАДАЧА 2.2. Вариант второй
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d i o . h>
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t a , b , c , S , r ;
p r i n t f ( " V v e d i t e a , b , c \ n " ) ;/ /Вывод на экран строки символов.
s c a n f ( " % f % f % f " ,& a , & b , & c ) ; / /Ввод значений.
r =( a+b+c ) / 2 ;
S= s q r t ( r ∗( r −a ) ∗( r −b ) ∗( r −c ) ) ;
p r i n t f ( " S = % 5 . 2 f \ t p = % 5 . 2 f \ n " , S , 2∗r ) ; / /Вывод результатов.
r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

38Глава 2. Общие сведения о языкеС++
Рис. 2.8: Результаты работы программы к задаче 2.2 (вариант 2)
2.9.1 Объектно-ориентированные средства ввода-вывода. Описание объектов для управления вводом-выводом содержит ся в заголо-
вочном файле iostream. При подключении этого файла с помощью директивы
#include в программе автоматически создаются объекты-потоки8
cin для ввода с клавиатуры иcout длявывода на экран , а также операции по-
мещения в поток <<и чтения из потока >>.
Итак, с помощью объекта cinи операции >>можно ввести значение любой
переменной. Например, если переменная iописана как целочисленная, то ко-
манда cin>> i; означает, что в переменную iбудет записано некое целое чис-
ло, введённое с клавиатуры. Если нужно ввести несколько пер еменных, следует
написать cin>>x>>y>>z; .
Объект coutи операция <<позволяют вывести на экран значение любой
переменной или текст. Текст необходимо заключать в двойные к авычки, кро-
ме того, допустимо применение специальных символов \tи\n (таблица 2.11).
Запись cout< cout< символом табуляции.
Задача 2.3. Дано трехзначное число. Записать его цифры в обратном поряд ке
и вывести на экран новое число.
Разберём решение данной задачи на конкретном примере. Здес ь будут ис-
пользоваться операции целочисленной арифметики.
Пусть P=456. Вычисление остатка от деления числа Pна 10даст его послед-
нюю цифру (количество единиц в числе P): 456 % 10 =6.
Операция деления нацело числа Pна 10позволит уменьшить количество раз-
рядов и число станет двузначным:
456 / 10 = 45.
Остаток от деления полученного числа на 10будет следующей цифрой числа
P (количество десятков в числе P):
45 % 10 = 5.
Последнюю цифру числа P(количество сотен) можно найти так:
456 / 100 = 4.
8 Поток  виртуальный канал связи, создаваемый в программе дл я передачи данных
Программирование на языке С++ в среде Qt Creator

2.9. Ввод и вывод данных39
Так как в задаче требовалось записать цифры числаPв обратном порядке,
значит в новом числе будет 6сотен, 5десятков и 4единицы:
S = 6*100 + 5*10 + 4 = 654.
Далее приведён текст программы, реализующей данную задачу д ля любого
трехзначного числа.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗a r g v [ ] )
{
u n s i g n e d i n t P , S ;/ /Определение целочисленных переменных без знака .
c o u t << " P = "; / /Вывод на экран символов P=.
c i n >>P ; / /Ввод заданного числа P .
S=P%10 ∗100+P/10%10 ∗10+P / 1 0 0 ; / /Вычисление нового числа S .
c o u t << " S = "< r e t u r n 0 ;
}
Задача 2.4. Пусть целочисленная переменная iи вещественная переменная d
вводятся с клавиатуры. Определить размер памяти, отведённ ой для хранения
этих переменных и их суммы, в байтах. Вычислить, сколько пам яти будет выде-
лено для хранения строки С Новым Годом!. Вывести на экран размеры различ-
ных типов данных языка С++в байтах.
Далее приведён текст программы.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t i ; / /Определение целочисленной переменной .
double d ;/ /Определение вещественной переменной .
c o u t << " i = "; c i n >> i ; / /Ввод переменной i .
c o u t << " d = "; c i n >>d ; / /Ввод переменной d .
/ / Размер памяти ,отведённой под переменную i .
c o u t << "Размер i : "< / / Размер памяти, отведённой под переменную d .
c o u t << "Размер d : "< / / Размер памяти, отведённой под значение выражения i +d .
c o u t << "Размер i + d : "< c o u t << "Размер строки <С Новым Годом!>: ";
/ / Размер памяти, отведённой под строку.
c o u t << s i z e o f "С Новым годом! "<< " \ n " ;
/ / Вычисление размеров различных типов данных:
c o u t << "Размер c h a r : "< c o u t << "Размер i n t : "< c o u t << "Размер s h o r t i n t : " < c o u t << "Размер l o n g i n t : " < c o u t << "Размер l o n g l o n g i n t : " ;
c o u t << s i z e o f (l o n g l o n g i n t )<<" \ n " ;
c o u t << "Размер f l o a t : " < c o u t << "Размер d o u b l e : " < c o u t << "Размер l o n g d o u b l e : " < r e t u r n 0 ;
}
Результаты работы программы 9
9
Обратите внимание, что при использовании кодировки utf-16 один кириллический символ
занимает в памяти 2 байта.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

40Глава 2. Общие сведения о языкеС++
i= 23
d= 45.76
Размер i: 4
Размер d: 8
Размер i+d: 8
Размер <С Новым годом!>:26
Размер char: 1
Размер int: 4
Размер short int: 2
Размер long int: 4
Размер long long int:8
Размер float: 4
Размер double: 8
Размер long double: 12
2.10 Задачи для самостоятельного решения
2.10.1 Ввод-вывод данных. Операция присваивания.
Разработать программу на языке С++. Все входные и выходные данные в зада-
чах  вещественные числа . Для ввода и вывода данных использовать функции
scanf иprintf .
1. Даны катеты прямоугольного треугольника aи b. Найти гипотенузу cи
углы треугольника , .
2. Известна гипотенуза cи прилежащий угол прямоугольного треугольника.
Найти площадь треугольника Sи угол .
3. Известна диагональ квадрата d. Вычислить площадь Sи периметр Pквад-
рата.
4. Дан диаметр окружности d. Найти длину окружности Lи площадь круга S.
5. Даны три числа  a, b, c. Найти среднее арифметическое и среднее геомет-
рическое заданных чисел.
6. Даны катеты прямоугольного треугольника aи b. Найти гипотенузу cи
периметр P.
7. Дана длина окружности L. Найти радиус окружности Rи площадь круга S.
8. Даны два ненулевых числа aи b. Найти сумму S, разность R, произведение
P и частное dквадратов заданных чисел.
9. Поменять местами содержимое переменных AиB и вывести новые значе-
ния AиB.
10. Точки AиB заданы координатами на плоскости: A(x
1, y
1)
, B (x
2, y
2)
. Найти
длину отрезка AB.
11. Заданы два катета прямоугольного треугольника aи b. Вычислить площадь
S и периметр P.
12. Даны переменные A,B ,C . Изменить их значения, переместив содержимое
A вB,B  в C,C  в A, и вывести новые значения переменных A,B ,C .
13. Известна диагональ ромба d. Вычислить площадь Sи периметр P.
14. Найти значение функции y= 4 ·(x + 1) 3
+ 5 ·(x − 1)5
+ 2 и её производной
при заданном значении x.
15. Даны два ненулевых числа aи b. Найти сумму S, разность R, произведение
P и частное Dмодулей заданных чисел.
Программирование на языке С++ в среде Qt Creator

2.10. Задачи для самостоятельного решения41
16. Известны координаты вершин квадратаAB C D:A (x
1, y
1)
и C(x
2, y
2)
. Найти
площадь Sи периметр P.
17. Даны длины сторон прямоугольника aи b. Найти площадь Sи периметр P.
18. Известно значение периметра Pравностороннего треугольника. Вычислить
площадь S.
19. Задан периметр квадрата P. Вычислить сторону квадрата a, диагональ d
и площадь S.
20. Дана сторона квадрата a. Вычислить периметр квадрата P, его площадь S
и длину диагонали d.
21. Три точки заданы координатами на плоскости: A(x
1, y
1)
, B(x
2, y
2)
и
C (x
3, y
3)
. Найти длины отрезков ABиB C .
22. Даны переменные A, B, C. Изменить их значения, переместив содержимое
A вC,C  в B,B  в A, и вывести новые значения переменных A,B ,C .
23. Даны числа  a
1,
a
2,
a
3,
a
4,
a
5. Найти их среднее арифметическое и среднее
геометрическое значения.
24. Найти значение функции y= 3
2
·
(x + 3) 4
− 1 5
·
(x − 1)5
и её производной при
заданном значении x.
25. Точки AиB заданы координатами в пространстве: A(x
1, y
1, z
1)
,
B (x
2, y
2, z
2)
. Найти длину отрезка AB.
2.10.2 Операции целочисленной арифметики. Разработать программу на языке С++. Все входные данные в задачах  це-
лые числа. Для ввода и вывода данных использовать объектно- ориентированные
средства ввода-вывода.
1. Расстояние Lзадано в сантиметрах. Найти количество полных метров в
нём и остаток в сантиметрах.
2. Масса Mзадана в килограммах. Найти количество полных тонн в ней и
остаток в килограммах.
3. Размер файла Bдан в байтах. Найти количество полных килобайтов, ко-
торые занимает данный файл и остаток в байтах.
4. Дано двузначное число. Вывести на экран количество десят ков и единиц в
нём.
5. Дано двузначное число. Найти сумму его цифр.
6. Дано двузначное число. Найти произведение его цифр.
7. Дано двузначное число. Вывести число, полученное при пер естановке цифр
исходного числа.
8. Дано трехзначное число. Определить, сколько в нём единиц , десятков и
сотен.
9. Дано трехзначное число. Найти сумму его цифр.
10. Дано трехзначное число. Найти произведение его цифр.
11. Дано трехзначное число. Вывести число, полученное при п ерестановке
цифр сотен и десятков исходного числа.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

42Глава 2. Общие сведения о языкеС++
12. Дано трехзначное число. Вывести число, полученное при п ерестановке
цифр сотен и единиц исходного числа.
13. Дано трехзначное число. Вывести число, полученное при п ерестановке
цифр десятков и единиц исходного числа.
14. С начала суток прошло Nсекунд. Найти количество полных минут, про-
шедших с начала суток и остаток в секундах.
15. С начала суток прошло Nсекунд. Найти количество полных часов, про-
шедших с начала суток и остаток в секундах.
16. Дано двузначное число. Найти сумму квадратов его цифр.
17. Дано двузначное число. Найти квадрат разности его цифр.
18. Расстояние Lзадано в метрах. Найти количество полных километров в нём
и остаток в метрах.
19. Масса Mзадана в граммах. Найти количество полных килограммов в ней
и остаток в граммах.
20. Размер файла Bдан в килобайтах. Найти количество полных мегабайтов,
которые занимает данный файл и остаток в килобайтах.
21. Расстояние Lзадано в дециметрах. Найти количество полных метров в нём
и остаток в сантиметрах.
22. С начала года прошло Kдней. Найти количество полных недель, прошед-
ших с начала года и остаток в днях.
23. С начала года прошло Kчасов. Найти количество полных дней, прошедших
с начала года и остаток в часах.
24. Дано трехзначное число. Найти сумму квадратов его цифр.
25. Дано трехзначное число. Найти квадрат суммы его цифр.
2.10.3 Встроенные математические функции Разработать программу на языке С++. Все входные и выходные данные в зада-
чах  вещественные числа . Для ввода и вывода данных использовать функции
scanf иprintf .
Вычислить значение выражения y= f(x ) при заданном значении x. Вариан-
ты заданий представлены в таблице 2.12.
Программирование на языке С++ в среде Qt Creator

2.10. Задачи для самостоятельного решения43
Таблица 2.12:Задачи для самостоятельного решения
№ Выражениеf(x ) № Выражение f(x )
1 7
rx
2
+ 2 .7 · ·cos q |
x 3
| − 2 + ex 2 tg 4
x + sin 2
x −
e2
x 2
+3 .6 x − 1
3 ŕ ŕŕ|
x 4
− cos x| − 9
q 1 + √ x
6ŕ ŕŕ
+ sin 3
ex
+ 1 4 log 4|
e x
− 4| − 7
v
u
u
t
ŕ ŕŕŕŕ
2
·x
3.21 + cos 2
7ŕ ŕŕŕŕ
5 3
rq|
x |+ |ctg 2
x + e
x 2
· −
x3
| 6 x 5
+ log 2
3
(3
x2
+ 5) + 9
q (
− 6x 2
)2
7 1
− log |x − cos(2 x− )|
6 + x4
x − 1 +5
√ x
3 8 ex
+ 3
+ 3
s tg ŕ ŕŕ ŕ
x
5 x
2
+ 13 .22 ŕ ŕŕ ŕ
+ cos 3
x
9 x1+
3
· 4
−3x 3
− 5
s (
x + 1) 4
+ lg ŕ ŕŕŕ
x x
+ 1 ŕ ŕŕŕ 10 5
rx
3
+ cos q |
x 3
| + e
x cos(3
·x + 15
)
11 e2
x
+ 5
s ctg
(
x − )9 x 4
+ 3 .4 + sin
2
6.2 x 12 5
q(
x + tg a)2
− 1
− ln|e x
+ cos 8
| 2
13 log(
ex
+ 27) −v
u
u
t
ŕ ŕŕŕŕ
x
3
+ 5
√ x
7
+ 14
sin 5 x+ 5 .1 · ŕ ŕŕŕŕ 14 ln
|cos( x− 2· )| − 3
s 1 +
e
x sin
x− 3
15
v
u
u
tŕ ŕŕŕŕx
3
+ 3
√ x
4
− 1
sin x+ + ex ŕ ŕŕŕŕ 16 3
s1 + 3
·
1 + x2 +
|arctg 2
x3
|
17 tg 2
|x |+ 3 2
x 2
− ex
+ 7
√ x 2
cos
2
x 18 x4
− 5
r
− q |
x 3
| + sin 2x x
2
+ 1
19 log( ex
+ 6) −3
r (
x − 4)2
+ 1 .47 sin q |
·x | 20 x5
sin
|x − 7| + log
2
(x 2
+ 2 .5) − 3
q (
− 6.1 x 2
)2
21 ctg 2
x
· 3 −ş
q |
x | − 3.4 ť
x2
− 10
+ ln( x2
+ 3) 22
ŕ ŕŕŕ ŕlog
5|
x 3
− ex
| − 3
s 2
x
cos( x+ 1 .23 · )ŕ ŕŕŕ ŕ
23 ŕ ŕŕ
|
cos
7−
ex
| − 7
q 2 + √ x
5ŕ ŕŕ
+ ln x
4
+ 1 6 24 log( x2
+ 2) −sin 2
x + 5
r 2
− q |
x |+ sin e
x
+ 1
25 log 2ex
− cos x +
3
s
|
tg(2 x)|
2 .6 + x2
+ x3
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В.
, Чмыхало А. С.

Глава 3
Операторы управленияВ этой главе описаны основные операторы языка C++: условный оператор if,
оператор выбора switch, операторы цикла while,do . . . while иfor . Изложена
методика составления алгоритмов с помощью блок-схем. Прив одится большое
количество примеров составления программ различной сложн ости.
3.1 Основные конструкции алгоритма При разработке простейших программ несложно перейти от сло весного опи-
сания к написанию программы. Однако большинство реально ра зрабатываемых
программ довольно сложные и созданию программы предшеству ет разработка
алгоритма 1
. Алгоритм  это чёткое описание последовательности действий, ко-
торые необходимо выполнить, для того чтобы при соответству ющих исходных
данных получить требуемый результат. Одним из способов пре дставления ал-
горитма является блок-схема. При составлении блок-схемы все этапы решения
задачи изображаются с помощью различных геометрических фиг ур. Эти фи-
гуры называют блоками и, как правило, сопровождают надписями . Последова-
тельность выполнения этапов указывают при помощи стрелок, с оединяющих эти
блоки. Типичные этапы решения задачи изображаются следующим и геометри-
ческими фигурами:
• блок начала-конца (рис. 3.1). Надпись внутри блока: нача ло (конец);
• блок ввода-вывода данных (рис. 3.2). Надпись внутри блока : ввод (вывод
или печать) и список вводимых (выводимых) переменных;
• блок решения или арифметический (рис. 3.3). Внутри блока з аписывается
действие, вычислительная операция или группа операций;
• условный блок (рис. 3.4). Логическое условие записываетс я внутри блока. В
результате проверки условия осуществляется выбор одного и з возможных
путей (ветвей) вычислительного процесса.
1 От algorithmi ,algorismus , первоначально латинская транслитерация имени математик а
аль-Хорезми.

3.1. Основные конструкции алгоритма45
Рис. 3.1:Блок
начала-конца ал- горитма Рис. 3.2: Блок
ввода-вывода данных Рис. 3.3:
Арифметичёс-
кий блок Рис. 3.4: Условный блок
Рис. 3.5: Ли-
нейный процесс Рис. 3.6: Разветвляющийся процесс Рис. 3.7: Циклический про-
цесс
Рассмотренные блоки позволяют описать три основные конструкции алго-
ритма : линейный процесс, разветвляющийся процесс и циклический п роцесс.
Линейный процесс это конструкция, представляющая собой последовательное
выполнение двух или более операторов (рис. 3.5). Разветвляющийся процессза-
даёт выполнение одного или другого оператора в зависимости от выполнения
условия (рис. 3.6). Циклический процесс задаёт многократное выполнение опе-
ратора или группы операторов (рис. 3.7).
Нетрудно заметить, что каждая из основных конструкций алго ритма имеет
один вход и один выход. Это позволяет вкладывать конструкци и друг в друга
произвольным образом и составлять алгоритмы для решения за дач любой слож-
ности.
Одним из важных понятий при написании программ на С(С++ ) является по-
нятие составного оператора.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

46Глава 3. Операторы управления
3.2 Составной оператор
Составной оператор  это группа операторов, отделённых друг от друга
точкой с запятой, начинающихся с открывающей фигурной скобки { и заканчи-
вающихся закрывающейся фигурной скобкой }: { оператор_1;
...
оператор_n;
}
Транслятор воспринимает составной оператор как одно целое .
Рассмотрим операторы языка С++, реализующие основные конструкции алго-
ритма.
3.3 Условные операторы
Одна из основных конструкций алгоритма  разветвляющийся процесс. Он
реализован в языке С++двумя условными операторами: ifиswitch . Рассмотрим
каждый из них.
3.3.1 Условный оператор
При решении большинства задач порядок вычислений зависит о т определён-
ных условий, например, от исходных данных или от промежуточ ных результатов,
полученных на предыдущих шагах программы. Для организации вычислений в
зависимости от какого-либо условия в С++предусмотрен условный оператор if,
который в общем виде записывается следующим образом: i f (условие) оператор_1 ;e l s e оператор_2 ;
где условие  это логическое (или целое) выражение, переменная или конс танта,
оператор_1 иоператор_2  любой оператор языка С(С++).
Работает условный оператор следующим образом. Сначала вычи сляется зна-
чение выражения, указанного в скобках. Если оно не равно нул ю, т.е. имеет зна-
чение истина ( true), выполняется оператор_1. В противном случае, когда выра-
жение равно нулю, т.е. имеет значение ложь ( false), выполняется оператор_2.
Алгоритм, который реализован в условном операторе if, представлен на рис. 3.8.
Например, чтобы сравнить значения переменных aи bнужно написать сле-
дующий программный код: c i n >>a ; c i n >>b ;i f ( a==b ) c o u t << " a равно b ";
e l s e c o u t << " a не равно b " ;
Внимание! Не путайте знак проверки равенства ==и оператор присваива-
ния =. Например, в записи if (a=0) b=1;синтаксической ошибки нет. Операция
присваивания a=0формирует результат и его значение проверяется в качестве
условия. В данном примере присваивание b=1не будет выполнено никогда, так
как переменная aвсегда будет принимать значение равное нулю, то есть ложь.
Верная запись: if (a==0) b=1; .
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы47
Рис. 3.8: Алгоритм условного опера-
тораif ... else Рис. 3.9: Алгоритм условного опера-
тораif
Внимание! Если в задаче требуется, чтобы в зависимости от значения усл о-
вия выполнялся не один оператор, а несколько, их необходимо заключать в фи-
гурные скобки, как составной оператор. В этом случае компил ятор воспримет
группу операторов как один: i f (условие )
{ оператор_1;
оператор_2; . . .
} e l s e
{ оператор_3;
оператор_4; . . .
}
Альтернативная ветвь elseв условном операторе может отсутствовать, если
в ней нет необходимости: i f (условие )оператор;
или i f (условие )
{
оператор_1;
оператор_2;
...
}
В таком усечённом виде условный оператор работает так: оператор(груп-
па операторов) либо выполняется, либо пропускается, в зави симости от значения
выражения, представляющего условие. Алгоритм этого условно го процесса пред-
ставлен на рис. 3.9.
Пример применения условного оператора без альтернативной ветвиelseмо-
жет быть таким:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

48Глава 3. Операторы управления
c i n >>a ; c i n >>b ;
c = 0 ;
/ / Значение переменной cизменяется только при условии, что aне равно b
i f ( a ! = b ) c=a+b ;
c o u t << " c = "< Условные операторы могут быть вложены друг в друга. При влож ениях
условных операторов всегда действует правило: альтернати ваelse считается
принадлежащей ближайшему if. Например, в записи
i f (условие_1) i f(условие_2) оператор_А ; e l s eоператор_Б;
оператор_Б относится к условию_2, а в конструкции
i f (условие_1) { i f(условие_2) оператор_А ; }
e l s e оператор_Б;
он принадлежит оператору ifсусловием_1 .
Рассмотрим несколько задач с применением условных процесс ов.
Задача 3.1. Дано вещественное число x. Для функции, график которой приве-
дён на рис. 3.10, вычислить y= f(x ).
Рис. 3.10: Графическое представление задачи 3.1
Аналитически функцию, представленную на рис. 3.10, можно зап исать так:
y (x ) =   
4
, x −2
1 , x 1
x 2
, −2< x < 1
Составим словесный алгоритм решения этой задачи:
1. Начало алгоритма.
2. Ввод числа x(аргумент функции).
3. Если значение xменьше либо равно -2, то переход к п. 4, иначе переход
к п. 5.
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы49
4. Вычисление значения функции:y= 4 , переход к п. 8.
5. Если значение xбольше либо равно 1, то переход к п. 6, иначе переход
к п. 7.
6. Вычисление значения функции: y= 1 , переход к п. 8.
7. Вычисление значения функции: y= x2
.
8. Вывод значений аргумента xи функции y.
9. Конец алгоритма.
Блок-схема, соответствующая описанному алгоритму, предст авлена на
рис. 3.11.
Рис. 3.11: Блок-схема алгоритма решения задачи 3.1
Текст программы на языке C++будет иметь вид:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t X , Y ;
c o u t << " X = "; c i n >>X ;
i f ( X<= −2) Y= 4 ;
e l s e i f ( X>=1) Y= 1 ;
e l s e Y=X∗X ;
c o u t << " Y = "< r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

50Глава 3. Операторы управления
Задача 3.2.Даны вещественные числа xиy. Определить, принадлежит ли
точка с координатами ( x; y) заштрихованной области (рис. 3.12).
Рис. 3.12: Графическое
представление задачи 3.2 Рис. 3.13: Алгоритм решения зада- чи 3.2
Как показано на рис. 3.12, область ограничена линиями x= −1, x = 3 ,y = −2
и y= 4 . Значит точка с координатами ( x; y) будет принадлежать этой области,
если будут выполняться следующие условия: x −1, x 3, y −2 и y 4.
Иначе точка лежит за пределами области.
Блок-схема, описывающая алгоритм решения данной задачи, пр едставлена
на рис. 3.13. Текст программы к задаче 3.2:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t X , Y ;
c o u t << " X = "; c i n >>X ;
c o u t << " Y = "; c i n >>Y ;
i f ( X>= −1 && X<=3 && Y>= −2 && Y<=4)
c o u t << " Точка принадлежит области " << e n d l ;
e l s e c o u t << " Точка не принадлежит области " << e n d l ;
r e t u r n 0 ;
}
Задача 3.3. Даны вещественные числа xиy. Определить, принадлежит ли
точка с координатами ( x; y) заштрихованной области (рис. 3.14).
Составим уравнения линий, ограничивающих заданные области . В общем ви-
де уравнение прямой, проходящей через точки с координатами (x
1, y
1)
и (x
2, y
2)
,
имеет вид:
x− x
1
x2 −
x
1 =
y
− y
1 y2 −
y
1
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы51
Рис. 3.14: Графическое представление задачи 3.3
. Треугольник в первой координатной области ограничен линия ми, проходя-
щими через точки:
1. (0,1) −(4,3) ;
2. (4,3) −(5,1) ;
3. (5,1) −(0,1) .
Следовательно, уравнение первой линии:
x− 0
4− 0=
y
− 1 3− 1⇒
x 4=
y
− 1 2 ⇒
y= 1 + 1 2·
x,
уравнение второй линии: x− 4
5− 4=
y
− 3 1− 3⇒
x− 4 = y
− 3 −2 ⇒ −
2·x + 8 = y− 3⇒ y= −2·x + 11
и уравнение третьей линии: y= 1 .
Линии, которые формируют треугольник во второй координатно й области,
проходят через точки:
1. (0,1) −(− 4,3) ;
2. (− 4,3) −(− 5,1) ;
3. (− 5,1) −(0,1) ;
Следовательно, уравнение первой линии:
x− 0
−4− 0=
y
− 1 3− 1⇒
x −
4 =
y
− 1 2 ⇒
y= 1 −1 2·
x,
уравнение второй линии: x+ 4
−5 + 4 =
y
− 3 1− 3⇒
x
+ 4 −1 =
y
− 3 −2 ⇒ −
2·x − 8 = −y+ 3 ⇒y= 2 ·x + 11
и уравнение третьей линии: y= 1 .
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

52Глава 3. Операторы управления
Таким образом, условие попадания точки в заштрихованную ча сть плоскости
имеет вид:
  y
1 + 1
2
·
x
y −2·x + 11
y 1 или  
y
1− 1 2
·
x
y 2·x + 11
y 1
Далее приведён текст программы для решения задачи 3.3.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t X , Y ;
c o u t << " X = "; c i n >>X ;
c o u t << " Y = "; c i n >>Y ;
i f ( ( Y<=1+( f l o a t) 1 / 2∗X && Y<= −2∗X+11 && Y>=1) | | ( Y<=1 −(f l o a t ) 1 / 2∗X && Y<=2 ∗X
+11 && Y>=1) ) c o u t << "Точка принадлежит области" << e n d l ;
e l s e c o u t << "Точка не принадлежит области" << e n d l ;
r e t u r n 0 ;
}
Задача 3.4. Написать программу решения квадратного уравнения
ax 2
+ bx +c= 0 .
Исходные данные: вещественные числа a, b и c коэффициенты квадратного
уравнения.
Результаты работы программы: вещественные числа x1 и x2  корни квад-
ратного уравнения либо сообщение о том, что корней нет.
Вспомогательные переменные: вещественная переменная d, в которой будет
храниться дискриминант квадратного уравнения.
Составим словесный алгоритм решения этой задачи.
1. Начало алгоритма.
2. Ввод числовых значений переменных a, b и c.
3. Вычисление значения дискриминанта dпо формуле d= b2
− 4ac .
4. Если d <0, то переход к п.5, иначе переход к п.6.
5. Вывод сообщения "Действительных корней нет" и переход к п.8.
6. Вычисление корней x1 = −
b+ √
d 2
a и
x2 = −
b− √ d 2
a .
7. Вывод значений x1 и x2 на экран.
8. Конец алгоритма.
Блок-схема, соответствующая этому описанию, представлена н а рис. 3.15.
Текст программы, которая реализует решение квадратного ур авнения:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t a , b , c , d , x1 , x 2 ;
/ / Ввод значений коэффициентов квадратного уравнения.
c o u t << " a = "; c i n >>a ;
c o u t << " b = "; c i n >>b ;
c o u t << " c = "; c i n >>c ;
d=b ∗b − 4∗ a ∗ c ; / /Вычисление дискриминанта.
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы53
Рис. 3.15: Алгоритм решения квадратного уравнения
i f ( d <0)
/ / Если дискриминант отрицательный, то вывод сообщения, о том что действительных корней нет,
c o u t << " Нет действительных корней " ;
e l s e
{
/ / иначе вычисление действительных корней
x 1=( −b+ s q r t ( d ) ) / 2 / a ;
x 2=( −b− s q r t ( d ) ) / ( 2 ∗a ) ;
/ / и вывод их значений.
c o u t << " X 1 = "< }
r e t u r n 0 ;
}
Задача 3.5. Составить программу нахождения действительных и комплекс ных
корней квадратного уравнения ax2
+ bx +c= 0 .
Исходные данные: вещественные числа a, b и c коэффициенты квадратного
уравнения.
Результаты работы программы: вещественные числа x1 и x2  действитель-
ные корни квадратного уравнения либо x1 и x2  действительная и мнимая
части комплексных корней квадратного уравнения.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

54Глава 3. Операторы управления
Вспомогательные переменные: вещественная переменная d, в которой будет
храниться дискриминант квадратного уравнения.
Можно выделить следующие этапы решения задачи:
1. Ввод коэффициентов квадратного уравнения a, b и c.
2. Вычисление дискриминанта dпо формуле d= b2
− 4ac .
3. Проверка знака дискриминанта. Если d 0, то вычисление действительных
корней: x1 = −
b+ √
d 2
a и
x2 = −
b− √ d 2
a и вывод их на экран. При отрицательном
дискриминанте выводится сообщение о том, что действительн ых корней
нет, и вычисляются комплексные корни 2
x1 = −
b
2a +
i√ |
d |2a ,
x2 = −
b 2a −
i√ |
d |2a .
У обоих комплексных корней действительные части одинаковы е, а мнимые
отличаются знаком. Поэтому можно в переменной x1 хранить действительную
часть числа −
b
2a , в переменной
x2  модуль мнимой части √ |
d |2a , а в качестве
корней вывести x1 + i·x 2 и x1 − i·x 2.
На рис. 3.16 изображена блок-схема решения задачи. Блок 1 пр едназначен
для ввода коэффициентов квадратного уравнения. В блоке 2 ос уществляется вы-
числение дискриминанта. Блок 3 осуществляет проверку знак а дискриминанта,
если дискриминант отрицателен, то корни комплексные, их ра счёт происходит
в блоке 4 (действительная часть корня записывается в переме ннуюx1, модуль
мнимой  в переменную x2), а вывод  в блоке 5 (первый корень x1+ i·x 2, второй
 x1 − i·x 2). Если дискриминант положителен, то вычисляются действите льные
корни уравнения (блок 6) и выводятся на экран (блок 7).
Текст программы, реализующей поставленную задачу:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t a , b , c , d , x1 , x 2 ;
c o u t << " a = "; c i n >>a ;
c o u t << " b = "; c i n >>b ;
c o u t << " c = "; c i n >>c ;
d=b ∗b − 4∗ a ∗ c ;
i f ( d <0)
{ / / Если дискриминант отрицательный, то вывод соответствующе го сообщения.
c o u t << " Нет вещественных корней \ n " ;
x 1= −b / ( 2 ∗a ) ; / /Вычисление действительной части комплексных корней.
x 2= s q r t ( f a b s ( d ) ) / ( 2 ∗a ) ; / /Вычисление модуля мнимой части комплексных корней
/ / Сообщение о комплексных корнях уравнения вида ax2
+ bx +c= 0 .
c o u t << " Комплексные корни уравнения \ n " ;
c o u t < / / Вывод значений комплексных корней в виде x1 ± ix2
i f ( x2 >=0)
{
c o u t < c o u t < }
e l s e
{
2 Комплексные числа записываются в виде a+ ib, где a действительная часть комплекс-
ного числа, b мнимая часть комплексного числа, i мнимая единица √

1. Подробно о
комплексных числах можно прочитать в главе 9.
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы55
Рис. 3.16: Алгоритм решения задачи 3.5
c o u t < c o u t < }
} e l s e
{
/ / Если дискриминант положительный, вычисление действитель ных корней и вывод их на экран.
x 1=( −b+ s q r t ( d ) ) / 2 / a ;
x 2=( −b− s q r t ( d ) ) / ( 2 ∗a ) ;
c o u t << " Вещественные корни уравнения \ n " ;
c o u t < c o u t << " X 1 = "< } r e t u r n 0 ;
}
Результаты работы программы к задаче 3.5 показаны ниже.
a=-5
b=-3
c=-4
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

56Глава 3. Операторы управления
Нет вещественных корней
Комплексные корни уравнения
-5x^2+-3x+-4=0
-0.3-0.842615i -0.3+0.842615i
==============================
a=2
b=-3
c=1
Вещественные корни уравнения
2x^2+-3x+1=0
X1=1 X2=0.5
Задача 3.6.Составить программу для решения кубического уравнения
ax 3
+ bx 2
+ cx +d= 0 .
Кубическое уравнение имеет вид
ax3
+ bx 2
+ cx +d= 0 (3.1)
После деления на aуравнение 3.1 принимает канонический вид:
x3
+ rx 2
+ sx +t= 0 , (3.2)
где r= b
a
,
s = c a
,
t = d a
.
В уравнении 3.2 сделаем замену x= y− r
3
и получим приведённое уравнение:
y 3
+ py +q= 0 , (3.3)
где p= 3
s− r2
3 ,
q = 2
r3 27 −rs 3
+
t.
Число действительных корней приведённого уравнения (3.3) зависит от знака
дискриминанта (табл. 3.1) D= ( p
3
)3
+ ( q 2
)2
.
Таблица 3.1: Количество корней кубического уравнения
Дискриминант Количество действитель-
ных корней Количество комплексных
корней
D 0 1 2
D < 0 3
Корни приведённого уравнения могут быть рассчитаны по форм улам Карда-
но:
y1 =
u+ v
y 2 = −
u+ v
2 +u
− v 2 i√ 3
y 3 = −
u+ v
2 −u
− v 2 i√ 3
, (3.4)
где u= 3
q

q2 +√ D
, v= 3
q −
q2 −√ D
.
При отрицательном дискриминанте уравнение (3.1) имеет три действитель-
ных корня, но они будут вычисляться через вспомогательные к омплексные ве-
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы57
личины. Чтобы избавиться от этого, можно воспользоваться формулами:
y 1 = 2 3


cos( 3
)
,
y 2 = 2 3

cos( 3
+ 2
3 )
,
y 3 = 2 3

cos( 3
+ 4
3 )
, (3.5)
где = q

p327 ,
cos( ) = −
q 2 .
Таким образом, при положительном дискриминанте кубическо го уравнения
(3.3) расчёт корней будем вести по формулам (3.4), а при отри цательном  по
формулам (3.5). После расчёта корней приведённого уравнен ия (3.3) по форму-
лам (3.4) или (3.5), необходимо по формулам
xk =
y
k − r
3, k
= 1,2 ,3 ..,
перейти к корням заданного кубического уравнения (3.1). Блок-схема решения кубического уравнения представлена на рис. 3.18.
Описание блок-схемы. В блоке 1 вводятся коэффициенты кубич еского урав-
нения, в блоках 2–3 рассчитываются коэффициенты каноническ ого и приведён-
ного уравнений. Блок 4 предназначен для вычисления дискрим инанта. В блоке 5
проверяется знак дискриминанта кубического уравнения. Ес ли он отрицателен,
то корни вычисляются по формулам 3.5 (блоки 6–7). При положит ельном зна-
чении дискриминанта расчёт идёт по формулам 3.4 (блок 9, 10) . Блоки 8 и 11
предназначены для вывода результатов на экран.
Текст программы с комментариями приведён ниже 3
.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
#d e f i n e p i 3 . 1 4 1 5 9 / /Определение константы
i n t m a i n ( )
{ f l o a t a , b , c , d , D , r , s , t , p , q , r o , f i , x1 , x2 , x3 , u , v , h , g ;
/ / Ввод коэффициентов кубического уравнения.
c o u t << " a = "; c i n >>a ;
c o u t << " b = "; c i n >>b ;
c o u t << " c = "; c i n >>c ;
c o u t << " d = "; c i n >>d ;
/ / Расчёт коэффициентов канонического уравнения по формуле 3 .2
r=b / a ; s=c / a ; t=d / a ;
/ / Вычисление коэффициентов приведённого уравнения по форму ле 3.3
p = ( 3 ∗s− r∗ r ) / 3 ; q =2 ∗r∗ r∗ r /27 −r∗ s /3+ t ;
/ / Вычисление дискриминанта кубического уравнения
D=(p / 3 ) ∗( p / 3 ) ∗( p / 3 ) +( q / 2 ) ∗( q / 2 ) ;
i f ( D<0)
{ / /Формулы 3.5
3
При расчёте величин uи vв программе предусмотрена проверка значения подкоренного
выражения.
Если
q
2 ∓√ D >
0, то u= 3
q
q2 +√ D
, а v= 3
q
q2 −√ D
.
Если
q
2 ∓√ D <
0, то u= 3
q |

q2 +√ D
|, а v= 3
q |

q2 −√ D
|.
Соответственно, при нулевом значении подкоренного выраже нияuи vобращаются в ноль
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

58Глава 3. Операторы управления
Рис. 3.17: Алгоритм решения кубического уравнения
r o= s q r t ( ( f l o a t) (−p∗p ∗p / 2 7 ) ) ;
f i = −q / ( 2 ∗r o ) ;
f i =p i /2 −a t a n ( f i / s q r t (1 −f i ∗f i ) ) ;
x 1 =2 ∗pow ( r o , ( f l o a t) 1 / 3 )∗c o s ( f i / 3 ) −r / 3 ;
x 2 =2 ∗pow ( r o , ( f l o a t) 1 / 3 )∗c o s ( f i /3+2 ∗p i / 3 ) −r / 3 ;
x 3 =2 ∗pow ( r o , ( f l o a t) 1 / 3 )∗c o s ( f i /3+4 ∗p i / 3 ) −r / 3 ;
c o u t << " \ n x 1 = " < c o u t << " \ t x 3 = " < } e l s e
{
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы59
/ /Формулы 3.4
i f (− q /2+ s q r t (D) >0) u=pow ( ( −q /2+ s q r t (D) ) , ( f l o a t) 1 / 3 ) ;
e l s e i f (− q /2+ s q r t (D) <0) u= −pow ( f a b s ( −q /2+ s q r t (D) ) , ( f l o a t) 1 / 3 ) ;
e l s e u = 0 ;
i f (− q/2 −s q r t (D) >0) v=pow ( ( −q/2 −s q r t (D) ) , ( f l o a t) 1 / 3 ) ;
e l s e
i f (− q/2 −s q r t (D) <0) v= −pow ( f a b s ( −q/2 −s q r t (D) ) , ( f l o a t) 1 / 3 ) ;
e l s e v = 0 ;
x 1=u+v −r / 3 ; / /Вычисление действительного корня кубического уравнения.
h= −(u+v ) /2 −r / 3 ; / /Вычисление действительной
g =(u −v ) / 2 ∗s q r t ( ( f l o a t) 3 ) ;/ /и мнимой части комплексных корней
c o u t << " \ n x 1 = " < i f ( x2 >=0)
{ c o u t < c o u t < }
e l s e
{ c o u t < c o u t < }
}
i f ( g >=0)
{ c o u t << " \ t x 2 = " < c o u t << " \ t x 3 = " < } e l s e
{ c o u t << " \ t x 2 = " < c o u t << " \ t x 2 = " < }
}
r e t u r n 0 ;
}
Задача 3.7. Заданы коэффициенты a, b и cбиквадратного уравнения ax4
+ bx 2
+
c = 0 . Найти все его действительные корни.
Входные данные :a, b, c.
Выходные данные :x1, x2, x3, x4.
Для решения биквадратного уравнения необходимо заменой y= x2
привести
его к квадратному уравнению ay2
+ by +c= 0 и решить это уравнение.
Опишем алгоритм решения этой задачи (рис. 3.18):
1. Ввод коэффициентов биквадратного уравнения a, b и c(блок 1).
2. Вычисление дискриминанта уравнения d(блок 2).
3. Если d <0(блок 3), вывод сообщения, что корней нет (блок 4), а ина-
че определяются корни соответствующего квадратного уравнен ияy1 и y2
(блок 5).
4. Если y1 < 0и y2 < 0(блок 6) , то вывод сообщения, что корней нет (блок 7).
5. Если y1 ≥ 0и y2 ≥ 0(блок 8), то вычисляются четыре корня по формулам
± √
y
1,
± √ y
2 (блок 9) и выводятся значения корней (блок 10).
6. Если условия 4) и 5) не выполняются, то необходимо проверит ь знакy1. Ес-
ли y1 ≥ 0(блок 11), то вычисляются два корня по формуле ±√
y
1 (блок 12),
иначе (если y2 ≥ 0) вычисляются два корня по формуле ±√
y
2 (блок 13).
Вывод вычисленных значений корней (блок 14).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

60Глава 3. Операторы управления
Рис. 3.18: Алгоритм решения биквадратного уравнения
Текст программы решения биквадратного уравнения приведён ниже.
Внимание! Если в условном операторе проверяется двойное условие, нео б-
ходимо применять логические операции ||,&& ,!. Например, условие если y1 и
y 2 положительны правильно записать так: if (y1>=0 && y2>=0).
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{ / / Описание переменных:
/ / a , b , c −коэффициенты биквадратного уравнения,
/ / d −дискриминант,
/ / x 1 , x 2 , x 3 , x 4 −корни биквадратного уравнения,
/ / y1 , y 2 −корни квадратного уравнения a y^2+b y+c =0 ,
f l o a t a , b , c , d , x1 , x2 , x3 , x4 , y1 , y 2 ;
/ / Ввод коэффициентов уравнения.
c o u t << " a = "; c i n >>a ;
c o u t << " b = "; c i n >>b ;
c o u t << " c = "; c i n >>c ;
d=b ∗b − 4∗ a ∗ c ; / /Вычисление дискриминанта.
i f ( d <0) / /Если дискриминант отрицательный, вывод сообщения Корней нет.
c o u t << "Нет действительных корней \ n ";
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы61
e l s e/ /Если дискриминант положительный ,
{
/ / Вычисление корней соответствующего квадратного уравнения .
y 1=( −b+ s q r t ( d ) ) / 2 / a ;
y 2=( −b− s q r t ( d ) ) / ( 2 ∗a ) ;
/ / Если оба корня квадратного уравнения отрицательные ,
i f ( y1 <0 && y2 <0)
/ / вывод сообщения Корней нет
c o u t << "Нет действительных корней \ n ";
/ / Если оба корня квадратного уравнения положительные ,
e l s e i f ( y1>=0 && y2 >=0)
{ / / Вычисление четырёх корней биквадратного уравнения
x 1= s q r t ( y 1 ) ;
x 2= −x 1 ;
x 3= s q r t ( y 2 ) ;
x 4= −s q r t ( y 2 ) ;
/ / Вывод корней уравнения на экран .
c o u t << " \ t X 1 = " < c o u t << " \ t X 3 = " < } / / Если не выполнились условия
/ / 1 . y1<0 иy2<0
/ / 2 . y1>=0 иy2 >=0,
/ / то проверяем условие y1 >=0.
e l s e i f ( y1 >=0)/ /Если оно истинно
{ / /вычисляем два корня биквадратного уравнения.
x 1= s q r t ( y 1 ) ;
x 2= −x 1 ;
c o u t << " X 1 = "< }
e l s e
{ / /Если условие y1>=0ложно, то вычисляем два корня биквадратного уравнения
x 1= s q r t ( y 2 ) ;
x 2= −x 1 ;
c o u t << " X 1 = "< }
}
r e t u r n 0 ;
}
Читателю предлагается самостоятельно модифицировать про грамму таким
образом, чтобы она находила все корни (как действительные, так и комплексные)
биквадратного уравнения.
3.3.2 Оператор варианта
Оператор варианта switchнеобходим в тех случаях, когда в зависимости от
значений какой-либо переменной надо выполнить те или иные о ператоры:
s w i t c h (выражение)
{
c a s e значение_1: Операторы_1; break;
c a s e значение_2: Операторы_2; break;
c a s e значение_3: Операторы_3; break;
...
c a s e значение_n: Операторы_n; break;
d e f a u l t :Операторы; break;
}
Оператор работает следующим образом. Вычисляется значение выражения
(оно должно быть целочисленным). Если выражение принимает значение_1, то
выполняются операторы_1. Если выражение принимает значение_2, то выпол-
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

62Глава 3. Операторы управления
няетсяоператоры_2 и так далее. Если выражение не принимает ни одно из значе-
ний, то выполняются операторы, расположенные после ключевог о словаdefault .
Альтернативная ветвь defaultможет отсутствовать, тогда оператор имеет
вид: s w i t c h (выражение)
{
c a s e значение_1: Операторы_1; break;
c a s e значение_2: Операторы_2; break;
c a s e значение_3: Операторы_3; break;
...
c a s e значение_n: Операторы_n; break;
}
Оператор breakнеобходим для того, чтобы осуществить выход из операто-
ра switch . Если оператор breakне указан, то будут выполняться следующие
операторы из списка, несмотря на то, что значение, которым о ни помечены, не
совпадает со значением выражения.
Рассмотрим применение оператора варианта.
Задача 3.8. Вывести на печать название дня недели, соответствующее зада нно-
му числу D, при условии, что в месяце 31 день и 1-е число  понедельник.
Для решения задачи воспользуемся операцией %, позволяющей вычислить
остаток от деления двух чисел, и условием, что 1-е число  пон едельник. Если
в результате остаток от деления (обозначим его R) заданного числа Dна семь
будет равен единице, то это понедельник, двойке  вторник, т ройке  среда и так
далее. Следовательно, при построении алгоритма необходим о использовать семь
условных операторов, как показано рис. 3.19. Решение задач и станет значительно
проще, если при написании программы воспользоваться опера тором варианта
switch :
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d i n t D , R ;/ /Описаны целые положительные числа.
c o u t << " D = "; c i n >>D ; / /Ввод числа от 1 до 31.
R=D% 7 ; s w i t c h (R)
{ c a s e 1 : c o u t << "Понедельник \ n ";break ;
c a s e 2 : c o u t << "Вторник \ n ";break ;
c a s e 3 : c o u t << "Среда \ n ";break ;
c a s e 4 : c o u t << "Четверг \ n ";break ;
c a s e 5 : c o u t << "Пятница \ n ";break ;
c a s e 6 : c o u t << "Суббота \ n ";break ;
c a s e 0 : c o u t << "Воскресенье \ n ";break ;
}
r e t u r n 0 ;
}
В предложенной записи оператора варианта отсутствует ветв ьdefault . Это
объясняется тем, что переменная Rможет принимать только одно из указанных
значений, т.е. 1, 2, 3, 4, 5, 6 или 0. Однако программа будет ра ботать неправиль-
но, если пользователь введёт значение D, превышающее 31. Чтобы избежать
подобной ошибки лучше сделать дополнительную проверку вхо дных данных:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
Программирование на языке С++ в среде Qt Creator

3.3. Условные операторы63
Рис. 3.19: Алгоритм решения задачи 3.8
i n t m a i n ( )
{
u n s i g n e d i n t D , R ;
c o u t << " \ n D = " ; c i n >>D ;
i f ( D< 3 2 ) / /Проверка введённого значения.
{ R=D% 7 ;s w i t c h (R)
{ c a s e 1 : c o u t << "Понедельник \ n ";break ;
c a s e 2 : c o u t << "Вторник \ n ";break ;
c a s e 3 : c o u t << "Среда \ n ";break ;
c a s e 4 : c o u t << "Четверг \ n ";break ;
c a s e 5 : c o u t << "Пятница \ n ";break ;
c a s e 6 : c o u t << "Суббота \ n ";break ;
c a s e 0 : c o u t << "Воскресенье \ n ";break ;
}
}
/ / Сообщение об ошибке в случае некорректного ввода.
e l s e c o u t << "ОШИБКА! \ n ";
r e t u r n 0 ;
}
Задача 3.9. По заданному номеру месяца mвывести на экран его название.
Для решения данной задачи необходимо проверить выполнение двенадцати
условий. Если mравно единице, то это январь, если двойке, то февраль, тройк е
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

64Глава 3. Операторы управления
 март и так далее. Понятно, что область возможных значений п еременнойm
находится в диапазоне от 1 до 12 и если пользователь введёт чи сло не входящее
в этот интервал, то появится сообщение об ошибке.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d i n t m ;/ /Описано целое положительное число.
c o u t << " m = "; c i n >>m ;
s w i t c h (m)
{
/ / В зависимости от значения mвыводится название месяца.
c a s e 1 : c o u t << "Январь \ n ";break ;
c a s e 2 : c o u t << "Февраль \ n ";break ;
c a s e 3 : c o u t << "Март \ n ";break ;
c a s e 4 : c o u t << "Апрель \ n ";break ;
c a s e 5 : c o u t << "Май \ n ";break ;
c a s e 6 : c o u t << "Июнь \ n ";break ;
c a s e 7 : c o u t << "Июль \ n ";break ;
c a s e 8 : c o u t << "Август \ n ";break ;
c a s e 9 : c o u t << "Сентябрь \ n ";break ;
c a s e 1 0 : c o u t << "Октябрь \ n ";break ;
c a s e 1 1 : c o u t << "Ноябрь \ n ";break ;
c a s e 1 2 : c o u t << "Декабрь \ n ";break ;
/ / Если значение переменной mвыходит за пределы области
/ / допустимых значений, то выдаётся сообщение.
d e f a u l t : c o u t << "ОШИБКА! \ n ";break ;
}
r e t u r n 0 ;
}
3.4 Операторы цикла Циклический процесс или простоциклэто повторение одних и тех же дей-
ствий. Последовательность действий, которые повторяются в цикле, называют
телом цикла . Один проход цикла называют шагомилиитерацией . Перемен-
ные, которые изменяются внутри цикла и влияют на его окончание , называются
параметрами цикла .
При написании циклических алгоритмов следует помнить след ующее. Во-
первых, чтобы цикл имел шанс когда-нибудь закончиться, сод ержимое его те-
ла должно обязательно влиять на условие цикла. Во-вторых, у словие должно
состоять из корректных выражений и значений, определённых ещё до первого
выполнения тела цикла.
ВС++ для удобства пользователя предусмотрены три оператора, ре ализую-
щих циклический процесс: while,do...while иfor .
3.4.1 Оператор цикла с предусловием На рис. 3.20 изображена блок-схема алгоритма цикла с предусловием. Опера-
тор, реализующий этот алгоритм в С++, имеет вид:
w h i l e (условие) оператор;
Программирование на языке С++ в среде Qt Creator

3.4. Операторы цикла65
здесьусловие  логическое или целочисленное выражение, оператор любой
оператор языка С(С++).
Рис. 3.20: Алгоритм циклической структуры с предусловием
Работает цикл с предусловием следующим образом. Вычисляетс яусловие .
Если оно истинно (не равно нулю), то выполняется оператор, иусловие прове-
ряется вновь. В противном случае цикл заканчивается, и упра вление передаётся
оператору, следующему за телом цикла. Условие вычисляется п еред каждой ите-
рацией цикла. Если при первой проверке выражение равно нулю, цикл не выпол-
нится ни разу. Тип выражения должен быть арифметическим или приводимым
к нему.
Если тело цикла состоит более чем из одного оператора, необх одимо исполь-
зовать составной оператор: w h i l e (условие)
{ оператор 1;
оператор 2;
...
оператор n;
}
Рассмотрим пример. Пусть необходимо вывести на экран табли цу значений
функции y= esin(
x)
cos( x) на отрезке [0;] с шагом 0.1. Применив цикл с пред-
условием , получим:
#i n c l u d e < s t d i o . h>
#i n c l u d e
#d e f i n e P I 3 . 1 4 1 5 9
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t x , y ; / /Описание переменных
x = 0 ; / /Присваивание параметру цикла стартового значения
/ / Цикл с предусловием
w h i l e ( x<=P I ) / /Пока параметр цикла не превышает конечное значение
{ / /выполнять тело цикла
y=e x p ( s i n ( x ) ) ∗c o s ( x ) ; / /Вычислить значение y
/ / Вывод на экран пары xи y .
p r i n t f ( " \ t x = % 5 . 2 f \ t y = % 5 . 4 f \ n " , x , y ) ;
x + = 0 . 1 ; / /Изменение параметра цикла
/ / ( переход к следующему значению x )
} / /Конец цикла
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

66Глава 3. Операторы управления
r e t u r n0 ;
}
В результате работы данного фрагмента программы на экран по следователь-
но будут выводиться сообщения со значениями переменных xиy:
x= 1.00 y=1.2534
x= 1.10 y=1.1059
x= 1.20 y=0.9203
x= 1.30 y=0.7011
x= 1.40 y=0.4553
x= 1.50 y=0.1918
x= 1.60 y=-0.0793
x= 1.70 y=-0.3473
x= 1.80 y=-0.6017
x= 1.90 y=-0.8328
x= 2.00 y=-1.0331 x= 2.10 y=-1.1969
x= 2.20 y=-1.3209
x= 2.30 y=-1.4045
x= 2.40 y=-1.4489
x= 2.50 y=-1.4576
x= 2.60 y=-1.4348
x= 2.70 y=-1.3862
x= 2.80 y=-1.3172
x= 2.90 y=-1.2334
x= 3.00 y=-1.1400
x= 3.10 y=-1.0416
3.4.2 Оператор цикла с постусловием В цикле с предусловием предварительной проверкой определя ется, выпол-
нять тело цикла или нет, до первой итерации. Если это не соотв етствует логике
алгоритма, то можно использовать цикл с постусловием. На рис. 3.21 видно,
что в этом цикле проверяется, делать или нет очередную итера цию, лишь после
завершения предыдущей. Это имеет принципиальное значение лишь на первом
шаге, а далее циклы ведут себя идентично.
Рис. 3.21: Алгоритм циклической структуры с постусловием
В С++ цикл с постусловием реализован конструкцией
do оператор w h i l e(условие) ;
здесь условие  логическое или целочисленное выражение, оператор любой
оператор языка С(С++). Если тело цикла состоит более чем из о дного оператора:
do {
оператор_1;
оператор_2;
...
Программирование на языке С++ в среде Qt Creator

3.4. Операторы цикла67
оператор_n;
}
w h i l e (условие);
Работает цикл следующим образом. В начале выполняется опера тор, пред-
ставляющий собой тело цикла. Затем вычисляется условие. Есл и оно истинно
(не равно нулю), оператор тела цикла выполняется ещё раз. В пр отивном случае
цикл завершается, и управление передаётся оператору, след ующему за циклом.
Таким образом, не трудно заметить, что цикл с постусловием в сегда будет
выполнен хотя бы один раз, в отличие от цикла с предусловием, который может
не выполниться ни разу.
Если применить цикл с постусловием для создания программы, которая вы-
водит таблицу значений функции y= esin(
x)
cos( x) на отрезке [0;] с шагом 0.1,
получим:
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d i o . h>
#i n c l u d e
#d e f i n e P I 3 . 1 4 1 5 9
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t x , y ; / /Описание переменных
x = 0 ; / /Присваивание параметру цикла стартового значения
do / /Цикл с постусловием
{ / / Выполнять тело цикла
y=e x p ( s i n ( x ) ) ∗c o s ( x ) ;
p r i n t f ( " \ t x = % 5 . 2 f \ t y = % 5 . 4 f \ n " , x , y ) ;
x + = 0 . 1 ; / /Изменение параметра цикла
}
w h i l e ( x<=P I ) ; / /пока параметр цикла не превышает конечное значение
r e t u r n 0 ;
}
Результаты работы этой программы будут такими же как на стр. 66.
3.4.3 Оператор цикла for с параметром Кроме того, в С++предусмотрен цикл for с параметром :
f o r (начальные_присваивания;условие;последействие)
оператор;
где начальные_присваивания  оператор или группа операторов, разделённых
запятой 4
, применяются для присвоения начальных значений величинам, исполь-
зуемым в цикле, в том числе параметру цикла, и выполняются оди н раз в начале
цикла; условие  целое или логическое выражение, которое определяет усло-
вие входа в цикл, если условие истинно (не равно нулю), то цикл выполняется;
последействие  оператор или группа операторов, разделённых запятой, кот о-
рые выполняются после каждой итерации и служат для изменения параметра
цикла; оператор  любой оператор языка, представляющий собой тело цикла.
Последействие илиоператор должны влиять на условие, иначе цикл никогда
4
Запятая в С++это операция последовательного выполнения операторов
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

68Глава 3. Операторы управления
не закончится.Начальные_присваивания ,выражение илипоследействие в запи-
си оператора forмогут отсутствовать, но при этом точки с запятой должны
оставаться на своих местах.
Опишем алгоритм работы цикла for:
1. Выполняются начальные_присваивания .
2. Вычисляется условие, если оно не равно 0 ( true), то выполняется переход
к п.3. В противном случае выполнение цикла завершается.
3. Выполняется оператор.
4. Выполняется оператор последействиеи осуществляется переход к п.2,
опять вычисляется значение выраженияи т.д.
Понятно, что этот алгоритм представляет собой цикл с предус ловием (рис. 3.22).
Рис. 3.22: Алгоритм работы цикла с параметром
В дальнейшем, чтобы избежать создания слишком громоздких а лгоритмов,
в блок-схемах цикл forбудем изображать, так как показано на рис. 3.23.
В случае если тело цикла состоит более чем из одного оператор а, необходимо
использовать составной оператор: f o r (начальные_присваивания; условие; последействие)
{ оператор_1;
...
оператор_n;
}
Применение цикла forрассмотрим на примере печати таблицы значений функ-
ции y= esin(
x)
cos( x) на отрезке [0;] с шагом 0.1:
#i n c l u d e < s t d i o . h>
#i n c l u d e
#d e f i n e P I 3 . 1 4 1 5 9
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t x , y ;
Программирование на языке С++ в среде Qt Creator

3.4. Операторы цикла69
Рис. 3.23: Блок-схема цикла с параметром
/ / Параметру цикла присваивается начальное значение, если он о не превышает конечное значение,
/ / то выполняются операторы тела цикла и значение параметра из меняется, в противном случае
/ / цикл заканчивается.
f o r ( x = 0 ; x<=P I ; x + = 0 . 1 )
{
y=e x p ( s i n ( x ) ) ∗c o s ( x ) ;
p r i n t f ( " \ t x = % 5 . 2 f \ t y = % 5 . 4 f \ n " , x , y ) ;
} r e t u r n 0 ;
}
Программный код выдаст результат, представленный на стр. 6 6.
3.4.4 Операторы передачи управления Операторы передачи управления принудительно изменяют поря док выполне-
ния команд. В С++таких операторов четыре: goto,break ,continue иreturn .
Оператор goto метка , гдеметка обычный идентификатор, применяют для
безусловного перехода, он передаёт управление оператору с меткой:метка:
оператор ;5
.
Оператор breakосуществляет немедленный выход из циклов while,
do . . . while иfor , а так же из оператора выбора switch. Управление передаётся
оператору, находящемуся непосредственно за циклом или опе ратором выбора.
Оператор continueначинает новую итерацию цикла, даже если предыдущая
не была завершена.
Оператор return выражение завершает выполнение функции и передаёт
управление в точку её вызова. Если функция возвращает значе ние типаvoid,
то выражение в записи оператора отсутствует. В противном сл учае выражение
должно иметь скалярный тип.
5 Обычно применение оператора gotoприводит к усложнению программы и затрудняет от-
ладку. Он нарушает принцип структурного программирования , согласно которому все блоки,
составляющие программу, должны иметь только один вход и оди н выход. В большинстве ал-
горитмов применения этого оператора можно избежать
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

70Глава 3. Операторы управления
3.5 Решение задач с использованием циклов
Рассмотрим использование циклических операторов на конкр етных приме-
рах.
Задача 3.10. Написать программу решения квадратного уравнения ax2
+ bx +c=
0 . Предусмотреть проверку ввода данных.
Решение квадратного уравнения было подробно рассмотрено в задаче 3.4. Од-
нако алгоритм, изображённый на рис. 3.15, не будет работать , если пользователь
введёт нулевое значение в переменную a(при попытке вычислить корни урав-
нения произойдёт деление на ноль). Чтобы избежать подобной ошибки нужно
в программе предусмотреть проверку входных данных, наприм ер, так как по-
казано на рис. 3.24. Вводится значение переменной a, если оно равно нулю, то
ввод повторяется, иначе следует алгоритм вычисления корне й квадратного урав-
нения. Здесь применяется цикл с постусловием, так как значение переменной
необходимо ввести, а затем проверить его на равенство нулю.
Рис. 3.24: Блок-схема проверки ввода данных
Программа решения задачи:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t a , b , c , d , x1 , x 2 ;
/ / Проверка ввода значения коэффициента a .
do / /Выполнять тело цикла пока а равно нулю
{
c o u t << " a = "; c i n >>a ;
}
w h i l e ( a==0) ;
c o u t << " b = "; c i n >>b ;
c o u t << " c = "; c i n >>c ;
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов71
d=b∗b − 4∗ a ∗ c ;
i f ( d <0) c o u t << "Нет вещественных корней ";
e l s e
{
x 1=( −b+ s q r t ( d ) ) / 2 / a ;
x 2=( −b− s q r t ( d ) ) / ( 2 ∗a ) ;
c o u t << " X 1 = "< } r e t u r n 0 ;
}
Задача 3.11. Найти наибольший общий делитель (НОД) натуральных чисел A
и B.
Входные данные :A иB.
Выходные данные :A  НОД.
Для решения поставленной задачи воспользуемся алгоритмом Евклида: будем
уменьшать каждый раз большее из чисел на величину меньшего д о тех пор, пока
оба значения не станут равными, так, как показано в таблице 3 .2.
Таблица 3.2: Поиск НОД для чисел A= 25 иB = 15 .
Шаг A B
Исходные данные 25 15
Шаг 1 10 15
Шаг 2 10 5
Шаг 3, НОД 5 5
В блок–схеме, представленной на рис. 3.25, для решения пост авленной зада-
чи используется цикл с предусловием , то есть тело цикла повторяется до тех
пор, пока Aне равно B. Следовательно, при создании программы воспользуемся
циклом while:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d i n t a , b ;
c o u t << " A = "; c i n >>a ;
c o u t << " B = "; c i n >>b ;
/ / Если числа не равны, выполнять тело цикла
w h i l e ( a ! = b )
/ / Если число Aбольше, чем B ,то уменьшить его значение на B ,
i f ( a>b ) a=a −b ;
/ / иначе уменьшить значение числа Bна A
e l s e b=b−a ;
c o u t << "НОД = "< r e t u r n 0 ;
}
Результат работы программы не изменится, если для её решени я воспользо-
ваться циклом с постусловием do...while:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

72Глава 3. Операторы управления
Рис. 3.25: Поиск наибольшего общего делителя двух чисел.
u n s i g n e d i n t a , b ;
c o u t << " A = "; c i n >>a ;
c o u t << " B = "; c i n >>b ;
do
i f ( a>b ) a=a −b ; e l s e b=b−a ;
w h i l e ( a ! = b ) ;
c o u t << "НОД = "< r e t u r n 0 ;
}
Задача 3.12. Вычислить факториал числа N(N ! = 1 ·2 ·3 ·. . . ·N ).
Входные данные :N  целое число, факториал которого необходимо вычис-
лить.
Выходные данные :factorial  целое число, значение факториала числа N,
произведение чисел от 1 до N.
Промежуточные переменные: i параметр цикла, целочисленная перемен-
ная, последовательно принимающая значения 2, 3, 4 и так далее доN.
Блок-схема приведена на рис. 3.26.
Итак, вводится число N. Переменной factorial, предназначенной для хране-
ния значения произведения последовательности чисел, прис ваивается начальное
значение, равное единице. Затем организуется цикл, параме тром которого высту-
пает переменная i. Если значение параметра цикла не превышает N, то выпол-
няется оператор тела цикла, в котором из участка памяти с име немfactorial
считывается предыдущее значение произведения, умножаетс я на текущее значе-
ние параметра цикла, а результат снова помещается в участок памяти с именем
factorial . Когда параметр iпревысит N, цикл заканчивается, и на экран вы-
водится значение переменой factorial, которая была вычислена в теле цикла.
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов73
Рис. 3.26: Алгоритм вычисления факториала.
Обратите внимание, как в программе записан оператор цикла. Здесь опе-
раторы ввода и операторы присваивания стартовых значений з аписаны как
начальные присваивания циклаfor, а оператор накапливания произведения и
оператор модификации параметра цикла представляют собой последействие:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d l o n g l o n g i n t f a c t o r i a l ; 1
u n s i g n e d i n t N , i ;
f o r ( c o u t << " N = ", c i n >>N , f a c t o r i a l = 1 , i = 2 ; i <=N ; f a c t o r i a l ∗= i , i ++) ;
c o u t << "факториал = "<< f a c t o r i a l << " \ n ";
r e t u r n 0 ;
}
Задача 3.13. Вычислить сумму натуральных чётных чисел, не превышаю-
щих N.
Входные данные :N  целое число.
Выходные данные :S  сумма чётных чисел.
Промежуточные переменные: i параметр цикла, принимает значения 2, 4,
6, 8 и так далее, также имеет целочисленное значение.
При сложении нескольких чисел необходимо накапливать резу льтат в опре-
делённом участке памяти (S), каждый раз считывая из этого уч астка (S) преды-
дущее значение суммы (S) и прибавляя к нему слагаемое i. Для выполнения
первого оператора накапливания суммы из участка памяти нео бходимо взять
такое число, которое не влияло бы на результат сложения. Пер ед началом цик-
ла переменной, предназначенной для накапливания сумы, нео бходимо присвоить
значение нуль. Блок-схема решения этой задачи представлен а на рис. 3.27.
Решим задачу двумя способами: с применением циклов whileиfor :
/ / Решение задачи с помощью цикла w h i l e
#i n c l u d e < i o s t r e a m >
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

74Глава 3. Операторы управления
Рис. 3.27: Алгоритм вычисления суммы чётных натуральных чис ел.
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d i n t N , i , S ;
c o u t << " N = "; c i n >>N ;
S = 0 ; i = 2 ;
w h i l e ( i <=N)
{
S=S+ i ;i = i + 2 ;
}
c o u t << " S = "< r e t u r n 0 ;
}
/ / −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
/ / Решение задачи с помощью цикла f o r
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d i n t N , i , S ;
f o r ( c o u t << " N = ", c i n >>N , S = 0 , i = 2 ; i <=N ; S+=i , i +=2) ;
c o u t << " S = "< r e t u r n 0 ;
}
Задача 3.14. Дано натуральное число N. Определить K количество делите-
лей этого числа, меньших самого числа (Например, для N=12 делители 1, 2, 3,
4, 6. Количество K=5).
Входные данные :N  целое число.
Выходные данные : целое числоK количество делителей N.
Промежуточные переменные: i параметр цикла, возможные делители чис-
ла N.
В блок-схеме, изображённой на рис. 3.28, реализован следующ ий алгоритм: в
переменную K, предназначенную для подсчёта количества делителей задан ного
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов75
числа, помещается значение, которое не влияло бы на результат, т.е. нуль. Далее
организовывается цикл, в котором изменяющийся параметр iвыполняет роль
возможных делителей числа N. Если заданное число Nделится нацело на пара-
метр цикла i, это означает, что iявляется делителем N, и значение переменной
K следует увеличить на единицу. Цикл необходимо повторить N
2
раз.
Рис. 3.28: Алгоритм определения делителей натурального чис
ла.
Текст программы на С++:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d i n t N , i , K ;
c o u t << " N = "; c i n >>N ;
f o r (K= 0 , i = 1 ; i <=N / 2 ; i ++) i f(N% i ==0) K++;
c o u t << " K = "< r e t u r n 0 ;
}
Задача 3.15. Дано натуральное число N. Определить, является ли оно простым.
Натуральное число Nназывается простым, если оно делится без остатка только
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

76Глава 3. Операторы управления
на единицу и на само себя. Число 13  простое, так как делится т олько на 1 и
13, а число 12 таковым не является, так как делится на 1, 2, 3, 4 , 6 и 12.
Входные данные :N  целое число.
Выходные данные : сообщение.
Промежуточные переменные: i параметр цикла, возможные делители чис-
ла N.
Необходимо проверить, есть ли делители числа Nв диапазоне от 2до N/2
(рис. 3.29). Если делителей нет, N простое число, иначе оно таковым не яв-
ляется. Обратите внимание на то, что в алгоритме предусмотр ено два выхода
из цикла. Первый  естественный, при исчерпании всех значен ий параметра, а
второй  досрочный. Нет смысла продолжать цикл, если будет н айден хотя бы
один делитель из указанной области изменения параметра.
Рис. 3.29: Алгоритм определения простого числа.
При составлении программы на языке С++досрочный выход из цикла удобно
выполнять при помощи оператора break:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов77
u n s i g n e d i n tN , i ;
b o o l P r ;
c o u t << " N = "; c i n >>N ;
P r= t r u e ;/ /Предположим, что число простое
f o r ( i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0) / /Если найдётся хотя бы один делитель, то
{
P r= f a l s e ;/ / число простым не является и
break ;/ / досрочный выход из цикла
} i f ( P r ) / /Проверка значения логического параметра и вывод на печать
/ / соответствующего сообщения
c o u t < e l s e
c o u t < r e t u r n 0 ;
}
Задача 3.16. Дано натуральное число N. Определить количество цифр в числе.
Входные данные :N  целое число.
Выходные данные :kol  количество цифр в числе.
Промежуточные данные :M  переменная для временного хранения значе-
ния N6
.
Для того, чтобы подсчитать количество цифр в числе, необход имо опреде-
лить, сколько раз заданное число можно разделить на десять н ацело. Например,
пусть N= 12345 , тогда количество цифр kol= 5. Результаты вычислений сведе-
ны в таблицу 3.3.
Таблица 3.3: Определение количества цифр числа
kol N
1 12345
2 12345 / 10 = 1234
3 1234 / 10 = 123
4 123 / 10 = 12
5 12 / 10 = 1
1 / 10 = 0
Алгоритм определения количества цифр в числе представлен на рис. 3.30.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d l o n g i n t N , M;
u n s i g n e d i n t k o l ;
c o u t << " N = "; c i n >>N ;
f o r (M=N , k o l = 1 ; M/ 1 0 > 0 ; k o l ++,M/ = 1 0 ) ;
c o u t << " k o l = "< r e t u r n 0 ;
}
6 При решении задачи (см. алгоритм на рис. 3.30) исходное числ о изменятся, поэтому, чтобы
его, не потерять, копируем исходное число Nв переменную M, и делить будем уже M.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

78Глава 3. Операторы управления
Рис. 3.30: Алгоритм определения количества цифр в числе.
Задача 3.17. Дано натуральное число N. Определить, содержит ли это число
нули и в каких разрядах они расположены (например, число 110 11110111 содер-
жит ноль в третьем и восьмом разрядах, а число 120405  в перво м и третьем).
Входные данные :N  целое число.
Выходные данные :pos  позиция цифры в числе.
Промежуточные данные :i  параметр цикла, M переменная для времен-
ного хранения значения N.
В связи с тем, что разряды в числе выделяются начиная с последн его, для
определения номера разряда в числе, необходимо знать колич ество цифр в чис-
ле 7
. Таким образом, на первом этапе решения задачи необходимо о пределитьkol
 количество цифр в числе. Затем нужно выделять из числа цифр ы, если оче-
редная цифра равна нулю, вывести на экран номер разряда, кото рый занимает
эта цифра. Процесс определения текущей цифры числа N= 120405 представлен
в таблице 3.4.
7 Алгоритм нахождения количества цифр в числе был рассмотрен в предыдущей задаче.
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов79
Таблица 3.4: Определение текущей цифры числа
i Число М Цифра Номер позиции
1 120405 120405 % 10 = 5 0
2 12040/10 = 1204 12040 % 10 = 0 1
3 1204/10 = 120 1204 % 10 = 4 2
4 120/10 = 12 120 % 10 = 0 3
5 12/10 = 1 12 % 10 = 2 4
6 1/10 = 0 1 % 10 = 1 5
Программный код к задаче 3.17.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d l o n g i n t N ,M;i n tk o l , i ;
c o u t << " N = "; c i n >>N ;
f o r ( k o l = 1 ,M=N ;M/ 1 0 > 0 ; k o l ++,M/ = 1 0 ) ;
f o r (M=N , i = 0 ; i i f (M%10==0) c o u t << " Позиция = "< r e t u r n 0 ;
}
Задача 3.18. Дано натуральное число N. Получить новое число, записав цифры
числа Nв обратном порядке. Например, 17852  25871.
Входные данные :N  целое число.
Выходные данные :S  целое число, полученное из цифр числа N, записанных
в обратном порядке.
Промежуточные данные :i  параметр цикла, M переменная для вре-
менного хранения значения N,kol  количество разрядов в заданном числе,
R = 10 kol
 старший разряд заданного числа.
Рассмотрим пример. Пусть N= 17852 , тогдаS= 2 ·10 4
+ 5 ·10 3
+ 8 ·10 2
+ 7 ·
10 1
+ 1 ·10 0
= 25871 .
Значит, для решения поставленной задачи, нужно знать колич ество разрядов
в заданном числе kolи его старший разряд R= 10 kol
. Новое число Sформируют
как сумму произведений последней цифры заданного числа на с тарший разряд
S + = M%10 ∗R . Цикл выполняют kolраз, при каждой итерации уменьшая само
число и старший разряд в десять раз.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d l o n g i n t N , M, R , S ;i n tk o l , i ;
c o u t << " N = "; c i n >>N ;
f o r (R= 1 , k o l = 1 ,M=N ;M/ 1 0 > 0 ; k o l ++,R ∗= 1 0 ,M/ = 1 0 ) ;
f o r ( S = 0 ,M=N , i = 1 ; i <=k o l ; S+=M%10 ∗R ,M/ = 1 0 ,R/ = 1 0 , i ++) ;
c o u t << " S = "< r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

80Глава 3. Операторы управления
Задача 3.19.Проверить, является ли заданное число Nпалиндромом 8
. Напри-
мер, числа 404, 1221  палиндромы.
Входные данные :N  целое число.
Выходные данные :сообщение .
Промежуточные данные :i  параметр цикла, M переменная для вре-
менного хранения значения N,kol  количество разрядов в заданном числе,
R = 10 kol
 старший разряд заданного числа, S целое число, полученное из
цифр числа N, записанных в обратном порядке.
Можно предложить следующий алгоритм решения задачи. Записа ть цифры
заданного числа Nв обратном порядке (задача 3.18), получится новое число S.
Сравнить полученное число Sс исходным N. Если числа равны, то заданное
число является палиндромом.
Текст программы на языке С++:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d l o n g i n t N , M, R , S ;
i n t k o l , i ;
c o u t << " N = "; c i n >>N ;
f o r (R= 1 , k o l = 1 ,M=N ;M/ 1 0 > 0 ; k o l ++,R ∗= 1 0 ,M/ = 1 0 ) ;
f o r ( S = 0 ,M=N , i = 1 ; i <=k o l ; S+=M%10 ∗R ,M/ = 1 0 ,R/ = 1 0 , i ++) ;
i f (N==S ) c o u t << " Число - палинром " << e n d l ;
e l s e c o u t << " Число не является палиндромом " << e n d l ;
r e t u r n 0 ;
}
Задача 3.20. Поступает последовательность из Nвещественных чисел. Опре-
делить наибольший элемент последовательности.
Входные данные :N  целое число; X вещественное число, определяет те-
кущий элемент последовательности.
Выходные данные :M ax  вещественное число, элемент последовательности
с наибольшим значением.
Промежуточные переменные :i  параметр цикла, номер вводимого элемента
последовательности.
Алгоритм поиска наибольшего элемента в последовательности следующий
(рис. 3.31). Вводится N количество элементов последовательности и X
первый элемент последовательности. В памяти компьютера отв одится ячейка,
например с именем M ax, в которой будет храниться наибольший элемент после-
довательности  максимум. Далее предполагаем, что первый э лемент последо-
вательности наибольший и записываем его в M ax. Затем вводим второй элемент
последовательности и сравниваем его с предполагаемым макс имумом. Если ока-
жется, что второй элемент больше, его записывают в ячейку M ax. В противном
случае никаких действий не предпринимаем. Потом переходим к вводу следу-
ющего элемента последовательности ( X), и алгоритм повторяется с начала. В
8
Палиндром  это число, слово или фраза одинаково читающееся в обоих направлениях,
или, другими словами, любой симметричный относительно сво ей середины набор символов.
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов81
результате в ячейкеM axсохранится элемент последовательности с наибольшим
значением 9
.
Рис. 3.31: Алгоритм поиска наибольшего числа в последовател ьности.
Текст программы на С++:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ u n s i g n e d i n t i , N ;
f l o a t X , Max ;
c o u t << " N = "; c i n >>N ;
c o u t << " X = "; c i n >>X ; / /Ввод первого элемента последовательности
/ / Параметр цикла принимает стартовое значение i =2 ,т.к. первый элемент
/ / уже введён предположим, что он максимальный, т.е. Max=X .
f o r ( i = 2 , Max=X ; i <=N ; i ++)
{
c o u t << " X = "; c i n >>X ; / /Ввод следующих элементов последовательности.
/ / Если найдётся элемент, превышающий максимум, записать его в ячейкуMax ,
/ / теперь он предполагаемый максимум.
i f ( X>Max ) Max=X ;
}
/ / Вывод наибольшего элемента последовательности.
c o u t << " M a x = "< r e t u r n 0 ;
}
9 Для поиска наименьшего элемента последовательности (мини мума), предполагают, что
первый элемент  наименьший, записывают его в ячейку min, а затем среди элементов после-
довательности ищут число, значение которого будет меньше ч ем предполагаемый минимум.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

82Глава 3. Операторы управления
Задача 3.21.Вводится последовательность целых чисел, 0  конец последо ва-
тельности. Найти наименьшее число среди положительных, ес ли таких значений
несколько 10
, определить, сколько их.
Блок-схема решения задачи приведена на рис. 3.32.
Рис. 3.32: Алгоритм поиска минимального положительного чис ла в последова-
тельности.
Далее приведён текст подпрограммы с подробными комментари ями11
.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
f l o a t N , Min ; i n tK ;
/ / Предположим, что в последовательности нет положительных чис ел, K=0.
/ / Вводим число и если оно не равно нулю
f o r ( c o u t << " N = ", c i n >>N , K= 0 ;N! = 0 ; c o u t << " N = ", c i n >>N)
/ / проверяем является ли оно положительным.
i f ( N>0)
/ / если K=0, поступил 1-й положительный элемент, предположим, чт о он минимальный.
i f (K==0) {K= 1 ; Min=N ; }
/ / если элемент не первый, сравниваем его с предполагаемым мин имумом,
/ / если элемент меньше, записываем его в Minи сбрасываем счётчик
e l s e i f ( N 10
Предположим вводится последовательность чисел 11, -3, 5, 1 2, -7, 5, 8,-9, 7, -6, 10, 5, 0.
Наименьшим положительным числом является 5. Таких минимум ов в последовательности 3.
11 Алгоритм поиска максимального (минимального) элементов п оследовательности подробно
описан в задаче 3.20
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов83
/ /если элемент равен минимуму, увеличиваем значение счётчика.
e l s e i f (N==Min ) K++; / /Конец цикла
/ / Если значение счётчика не равно нулю, печатаем значение
/ / минимального элемента и количество таких элементов.
i f (K! = 0 ) c o u t << " M i n = "< / / в противном случае выдаём сообщаем.
e l s e c o u t << " В последовательности нет положительных элементов \ n " ;
r e t u r n 0 ;
}
Задача 3.22. Определить, сколько раз последовательность из Nпроизвольных
чисел меняет знак.
Чтобы решить задачу, нужно попарно перемножать элементы по следователь-
ности. Если результат произведения пары чисел  отрицатель ное число, значит,
эти числа имеют разные знаки.
Пусть в переменной Bхранится текущий элемент последовательности, в A
предыдущий. Введём первое число A(до цикла) и второе B(в цикле). Если их
произведение отрицательно, то увеличиваем количество сме н знака на 1 (k++).
После чего сохраняем значение Bв переменную Aи повторяем цикл (рис. 3.33).
Рис. 3.33: Алгоритм решения задачи 3.22.
Предлагаем читателю самостоятельно разобраться с текстом программы на
С++ :
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ f l o a t A , B ;i n ti , K , N ;
c o u t << " N = "; c i n >>N ;
f o r (K= 0 , c o u t << " A = ", c i n >>A , i = 2 ; i <=N ; i ++)
{ c o u t << " B = "; c i n >>B ;
i f (A∗B<0) K++;
A=B ;
} c o u t << " K = "< r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

84Глава 3. Операторы управления
Задача 3.23.Поступает последовательность из Nвещественных чисел. Опре-
делить количество простых чисел в последовательности.
Блок-схема алгоритма изображена на рис. 3.34. Обратите вни мание, что для
решения задачи было организовано два цикла. Первый цикл обе спечивает ввод
элементов последовательности. Второй цикл находится внут ри первого и опре-
деляет, является ли поступившее число простым (задача 3.15 ).
Рис. 3.34: Алгоритм поиска простых чисел в последовательнос ти.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d l o n g i n t X ;
u n s i g n e d i n t N ;
i n t i , k , j ;
b o o l P r ;
f o r ( k = 0 , c o u t << " N = ", c i n >>N , i = 1 ; i <=N ; i ++)
{ f o r ( c o u t << " X = ", c i n >>X , P r= t r u e, j = 2 ; j <=X / 2 ; j ++)
i f (X%j ==0)
{
P r= f a l s e ;
break ;
}
i f ( P r ) k++;
}
i f ( k==0) c o u t << " Простых чисел нет \ n " ;
e l s e c o u t << " Количество простых чисел k = " < r e t u r n 0 ;
}
Программирование на языке С++ в среде Qt Creator

3.5. Решение задач с использованием циклов85
Задача 3.24.ДаноKнаборов ненулевых целых чисел. Каждый набор содержит
не менее двух элементов, признаком его завершения является число 0. Найти
количество наборов, элементы которых возрастают.
Блок-схема алгоритма решения задачи показана на рис. 3.35. Нетрудно заме-
тить, что алгоритм реализован с помощью двух циклических пр оцессов. Внут-
ренний цикл проверяет является ли последовательность возр астающей, а внеш-
ний повторяет алгоритм для новой последовательности.
Рис. 3.35: Алгоритм решения задачи 3.24.
Программный код решения задачи 3.24:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d i n t K , i , k o l , A , B ; b o o lp r ;
f o r ( c o u t << " K = ", c i n >>K , k o l = 0 , i = 1 ; i <=K ; i ++)
{
f o r ( p r=t r u e , c o u t << " A = ", c i n >>A ; A! = 0 ; A=B )
{
c o u t << " B = "; c i n >>B ;
i f ( B! = 0 && A>=B ) p r= f a l s e;
} i f ( p r ) k o l ++;
}
c o u t << " k o l = "<< k o l < r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

86Глава 3. Операторы управления
3.6 Задачи для самостоятельного решения
3.6.1 Разветвляющийся процесс. Вычисление значения функции.
Разработать программу на языке С++. Дано вещественное число a. Для функ-
ции y= f(x ), график которой приведён ниже, вычислить f(a ). Варианты зада-
ний представлены на рис. 3.36–3.60.
Рис. 3.36: Задание 1 Рис. 3.37: Задание 2 Рис. 3.38: Задание 3
Рис. 3.39: Задание 4 Рис. 3.40: Задание 5 Рис. 3.41: Задание 6
Рис. 3.42: Задание 7 Рис. 3.43: Задание 8 Рис. 3.44: Задание 9
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения87
Рис. 3.45: Задание 10 Рис. 3.46: Задание 11 Рис. 3.47: Задание 12
Рис. 3.48: Задание 13 Рис. 3.49: Задание 14 Рис. 3.50: Задание 15
Рис. 3.51: Задание 16 Рис. 3.52: Задание 17 Рис. 3.53: Задание 18
Рис. 3.54: Задание 19 Рис. 3.55: Задание 20 Рис. 3.56: Задание 21
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

88Глава 3. Операторы управления
Рис. 3.57: Задание 22 Рис. 3.58: Задание 23
Рис. 3.59: Задание 24 Рис. 3.60: Задание 25
3.6.2 Разветвляющийся процесс. Попадание точки в область на плоскости
Разработать программу на языке С++. Даны вещественные числа xиy. Опре-
делить, принадлежит ли точка с координатами ( x; y) заштрихованной области.
Варианты заданий представлены на рис. 3.61–3.85.
Рис. 3.61: Задание 1 Рис. 3.62: Задание 2 Рис. 3.63: Задание 3
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения89
Рис. 3.64: Задание 4 Рис. 3.65: Задание 5 Рис. 3.66: Задание 6
Рис. 3.67: Задание 7 Рис. 3.68: Задание 8 Рис. 3.69: Задание 9
Рис. 3.70: Задание 10 Рис. 3.71: Задание 11 Рис. 3.72: Задание 12
3.6.3 Разветвляющийся процесс. Пересечение линий и решение уравнений.
Разработать программу на языке С++для следующих заданий:
1. Задан круг с центром в точке O(x
0, y
0)
, радиусом R
0 и точка
A(x
1, y
1)
.
Определить, находится ли точка внутри круга.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

90Глава 3. Операторы управления
Рис. 3.73: Задание 13 Рис. 3.74: Задание 14 Рис. 3.75: Задание 15
Рис. 3.76: Задание 16 Рис. 3.77: Задание 17 Рис. 3.78: Задание 18
Рис. 3.79: Задание 19 Рис. 3.80: Задание 20 Рис. 3.81: Задание 21
2. Задана окружность с центром в точке O(x
0, y
0)
и радиусом R
0. Определить,
пересекается ли заданная окружность с осью абсцисс, если пе ресекается 
найти точки пересечения.
3. Задана окружность с центром в точке O(x
0, y
0)
и радиусом R
0. Определить,
пересекается ли заданная окружность с осью ординат, если пе ресекается 
найти точки пересечения.
4. Задана окружность с центром в точке O(0 ,0) и радиусом R
0 и прямая
y = ax +b. Определить, пересекаются ли прямая и окружность. Если пере -
секаются, найти точки пересечения.
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения91
Рис. 3.82: Задание 22 Рис. 3.83: Задание 23
Рис. 3.84: Задание 24 Рис. 3.85: Задание 25
5. Заданы окружности. Первая с центром в точке O(x
1, y
1)
и радиусом R
1,
вторая с центром в точке O(x
2, y
2)
и радиусом R
2. Определить, пересека-
ются окружности, касаются или не пересекаются.
6. Заданы три точки A(x
1, y
1)
, B (x
2, y
2)
,C (x
3, y
3)
. Определить, какая из точек
наиболее удалена от начала координат.
7. Заданы три точки A(x
1, y
1)
, B (x
2, y
2)
, C (x
3, y
3)
. Определить, какая из точек
B или Cнаименее удалена от точки A.
8. Определить, пересекаются ли линии y= ax +bи y= kx +m. Если пересе-
каются, найти точку пересечения.
9. Определить, пересекает ли линия y= ax +bось абсцисс. Если пересекает,
найти точку пересечения.
10. Определить, пересекаются ли линии y= ax3
+ bx2
+ cx +dи y= kx +m.
Если пересекаются, найти точки пересечения.
11. Определить, пересекаются ли линии y= ax 3
+ bx 2
+ cx +dи y= kx 3
+ mx 2
+
nx +p. Если пересекаются, найти точки пересечения.
12. Определить, пересекаются ли линии y= ax 3
+ bx 2
+ cx +dи y= ax 3
+ mx 2
+
nx +p. Если пересекаются, найти точки пересечения.
13. Определить, пересекаются ли линии y= ax 3
+ bx 2
+ cx +dи y= mx 2
+ nx +p.
Если пересекаются, найти точку пересечения.
14. Определить, пересекает ли линия y= ax 3
+ bx2
+ cx +dось абсцисс. Если
пересекает, найти точку пересечения.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

92Глава 3. Операторы управления
15. Определить, пересекаются ли параболыy= ax 2
+ bx +cи y= dx 2
+ mx +n.
Если пересекаются, то найти точки пересечения.
16. Определить, пересекаются ли линии y= bx2
+ cx +dи y= kx +m. Если
пересекаются, найти точки пересечения
17. Найти точки пересечения линии y= ax 2
+ bx +cс осью абсцисс. Если линии
не пересекаются выдать соответствующее сообщение.
18. Определить, пересекаются ли линии y= ax4
+ bx3
+ cx2
+ dx +fиy=
bx 3
+ mx 2
+ dx +p. Если пересекаются, найти точки пересечения.
19. Определить, пересекаются ли линии y= ax 4
+ bx 2
+ kx +cи y= mx 2
+ kx +p.
Если пересекаются, найти точки пересечения.
20. Определить, пересекает ли линия y= ax 4
+ bx 2
+ cось абсцисс. Если пере-
секает, найти точки пересечения.
21. Найти комплексные корни уравнения y= ax 4
+ bx2
+ c. Если в уравнении
нет комплексных корней, вывести соответствующее сообщение .
22. Найти комплексные корни уравнения y= ax 3
+ bx 2
+ cx +d. Если в уравнении
нет комплексных корней, вывести соответствующее сообщение .
23. Найти комплексные корни уравнения y= ax2
+ bx +c. Если в уравнении
нет комплексных корней, вывести соответствующее сообщение .
24. Заданы точки A(x
1, y
1, z
1)
и B(x
2, y
2, z
2)
. Определить, какая из точек наи-
менее удалена от начала координат.
25. Даны координаты точки, не лежащей на координатных осях OXиOY .
Определить номер координатной четверти, в которой находит ся данная
точка.
3.6.4 Циклический процесс. Вычисление значений функции Разработать программу на языке С++. Для решения задачи использовать опе-
раторы for,while ,do . Варианты заданий:
1. Вывести на экран таблицу значений функции синус в диапазо не от−2·
до 2· с шагом
8
.
2. Вывести на экран таблицу квадратов первых десяти целых по ложительных
чисел.
3. Вывести на экран таблицу значений функции косинус в диапа зоне от−2·
до 2· с шагом
8
.
4. Вывести на экран таблицу кубов первых десяти целых положи тельных чи-
сел.
5. Вывести на экран таблицу значений квадратов синусов в диа пазоне от−
до с шагом
12
.
6. Вывести на экран таблицу значений квадратов косинусов в д иапазоне от 0
до 2· с шагом
10
.
7. Вывести на экран таблицу квадратов первых десяти целых чё тных поло-
жительных чисел.
8. Вывести на экран таблицу квадратов первых десяти целых не чётных поло-
жительных чисел.
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения93
9. Вывести на экран таблицу значений удвоенных синусов в диапазоне от−a
до aс шагом h. Значения aи h вводятся с клавиатуры.
10. Вывести на экран таблицу значений удвоенных косинусов в диапазоне отa
до bс шагом h. Значения a, b и h вводятся с клавиатуры.
11. Вывести на экран таблицу кубов первых десяти целых нечёт ных положи-
тельных чисел.
12. Вывести на экран таблицу кубов первых десяти целых чётны х положитель-
ных чисел.
13. Вывести на экран таблицу значений функции y= e2
x
в диапазоне от −a до
a с шагом h. Значения aи h вводятся с клавиатуры.
14. Вывести на экран таблицу значений функции y= 5 ·e−
3x
в диапазоне от a
до bс шагом h. Значения a, b и h вводятся с клавиатуры.
15. Вывести на экран таблицу квадратов первых десяти целых о трицательных
чисел.
16. Вывести на экран таблицу кубов первых десяти целых отриц ательных чи-
сел.
17. Вывести на экран таблицу квадратных корней первых десят и целых поло-
жительных чисел.
18. Вывести на экран таблицу кубических корней первых десят и целых поло-
жительных чисел.
19. Вывести на экран таблицу значений функции y= 2 ·x 2
+ 3 ·x − 1в диапазоне
от −a до aс шагом h. Значения aи h вводятся с клавиатуры.
20. Вывести на экран таблицу значений функции y= 5 .4 ·x 3
− 2.8 ·x 2
− x+ 1 .6
в диапазоне от aдо bс шагом h. Значения a, b и h вводятся с клавиатуры.
21. Вывести на экран таблицу квадратных корней первых десят и целых поло-
жительных чётных чисел.
22. Вывести на экран таблицу квадратных корней первых десят и целых поло-
жительных нечётных чисел.
23. Вывести на экран таблицу значений функции y= −1.8 ·x3
− e2
x + 1
6
в
диапазоне от −3 до 4с шагом 1
2
.
24. Вывести на экран таблицу значений функции y= −1.3 ·x 2
− e
x
4 в диапазоне
от −2 до 2с шагом 1
4
.
25. Вывести на экран таблицу степеней двойки в диапазоне от 0 до 10 с шагом 1.
3.6.5 Циклический процесс. Последовательности натуральных чисел
Разработать программу на языке С++для следующих заданий:
1. Дано целое положительное число N. Вычислить сумму натуральных нечёт-
ных чисел не превышающих это число.
2. Дано целое положительное число N. Вычислить произведение натуральных
чётных чисел не превышающих это число.
3. Дано целое положительное число N. Вычислить количество натуральных
чисел кратных трём и не превышающих число N.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

94Глава 3. Операторы управления
4. Задано целое положительное числоn. Определить значение выражения:
P = n
!
n
P
i =1 i.
5. Вычислить количество натуральных двузначных чётных чис ел не делящих-
ся на 10.
6. Задано целое положительное число n. Определить значение выражения:
P = n
P
i =1 i
2
n
! .
7. Вычислить сумму натуральных удвоенных чисел не превышающ их 25.
8. Задано целое положительное число n. Определить значение выражения:
P = n
P
i =3 i
− 2
(n +1)! .
9. Дано целое положительное число N. Вычислить сумму квадратов нату-
ральных чётных чисел не превышающих это число.
10. Дано целое положительное число N. Вычислить количество натуральных
чисел кратных пяти и не превышающих число N.
11. Определить значение выражения: P= 5
P
i =0 3
i
5! .
12. Дано целое положительное число N. Вычислить сумму удвоенных нату-
ральных нечётных чисел не превышающих это число.
13. Задано целое положительное число n. Определить значение выражения:
P = n
P
i =2 i
2
− i.
14. Найти сумму нечётных степеней двойки. Значение степени изменяется от
1 до 9.
15. Задано целое положительное число n. Определить значение выражения:
P = 1
3
· n
P
i =1 2
·i2
− i+ 1 .
16. Дано целое положительное число N. Вычислить произведение натуральных
чисел кратных трём и не превышающих число N.
17. Задано целое положительное число n. Определить значение выражения:
P =n
+2
P
i =3 2
·i − 4.
18. Вычислить сумму натуральных трёхзначных чисел кратных пяти и не де-
лящихся на десять.
19. Определить значение выражения: P= 10
P
i =0 2
i
.
20. Вычислить количество натуральных двузначных нечётных чисел не деля-
щихся на 5.
21. Задано целое положительное число n. Определить значение выражения:
P = n
− 1
P
i =0 i
+1
(2 n)! .
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения95
22. Задано целое положительное числоn. Определить значение выражения:
P = 15
P
i =5 i
(2
·n +1)! .
23. Найти произведение чётных степеней двойки. Значение ст епени изменяется
от 0 до 8.
24. Вычислить произведение натуральных чисел не превышающи х 15.
25. Вычислить произведение натуральных двузначных чисел к ратных трём и
не делящихся на 10.
3.6.6 Циклический процесс. Последовательности произвольных чисел
Разработать программу на языке С++для следующих заданий:
1. Вводится последовательность ненулевых чисел, 0  конец п оследователь-
ности. Определить сумму положительных элементов последов ательности.
2. Вычислить сумму отрицательных элементов последователь ности изNпро-
извольных чисел.
3. Вводится последовательность ненулевых чисел, 0  конец п оследователь-
ности. Определить, сколько раз последовательность поменя ет знак.
4. В последовательности из Nпроизвольных чисел подсчитать количество
нулей.
5. Вводится последовательность ненулевых чисел, 0  конец п оследователь-
ности. Определить наибольшее число в последовательности.
6. Вводится последовательность из Nпроизвольных чисел найти наименьшее
число в последовательности.
7. Вводится последовательность ненулевых чисел, 0  конец п оследователь-
ности. Определить среднее значение элементов последовате льности.
8. Вводится последовательность из Nпроизвольных чисел, найти среднее зна-
чение положительных элементов последовательности.
9. Вводится последовательность ненулевых чисел, 0  конец п оследователь-
ности. Подсчитать процент положительных и отрицательных ч исел.
10. Вводится последовательность из Nпроизвольных чисел. Определить про-
цент положительных, отрицательных и нулевых элементов.
11. Вводится последовательность из Nпроизвольных чисел. Вычислить раз-
ность между наименьшим и наибольшим значениями последоват ельности.
12. Вводится последовательность из Nположительных целых чисел. Найти
наименьшее число среди чётных элементов последовательнос ти.
13. Вводится последовательность из Nцелых чисел. Определить, является ли
эта последовательность знакочередующейся.
14. Определить, является ли последовательность из Nпроизвольных чисел
строго возрастающей (каждый следующий элемент больше предыд ущего).
15. Вводится последовательность произвольных чисел, 0  ко нец последова-
тельности. Определить, является ли эта последовательност ь строго убыва-
ющей (каждый следующий элемент меньше предыдущего).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

96Глава 3. Операторы управления
16. Вводится последовательность ненулевых целых чисел, 0  конец последова-
тельности. Определить среднее значение чётных элементов п оследователь-
ности.
17. Вводится последовательность из Nпроизвольных чисел, найти среднее зна-
чение отрицательных элементов последовательности.
18. В последовательности из Nцелых чисел подсчитать количество чётных и
нечётных чисел.
19. Вводится последовательность целых чисел, 0  конец посл едовательности.
Определить процент чётных и нечётных чисел в последователь ности.
20. Вводится последовательность из Nцелых чисел. Определить, содержит ли
последовательность хотя бы два соседних одинаковых числа.
21. Вводится последовательность целых чисел, 0  конец посл едовательности.
Определить наибольшее число среди нечётных элементов посл едователь-
ности.
22. Вводится последовательность произвольных чисел, 0  ко нец последова-
тельности. Определить сумму и количество чисел в последова тельности.
23. Вводится последовательность из Nпроизвольных чисел. Найти сумму по-
ложительных и сумму отрицательных элементов последовател ьности.
24. Вводится последовательность произвольных чисел, 0  ко нец последова-
тельности. Определить отношение минимального и максималь ного элемен-
тов друг к другу.
25. Вводится последовательность из Nцелых чисел. Определить количество
одинаковых рядом стоящих чисел.
3.6.7 Циклический процесс. Работа с цифрами в числе Разработать программу на языке С++для следующих заданий:
1. Определить, является ли целое положительное число совершённым. Совер-
шённое число равно сумме всех своих делителей, не превосход ящих это
число. Например, 6=1+2+3 или 28=1+2+4+7+14.
2. Проверить, является ли пара целых положительных чисел дружественны-
ми . Два различных натуральных числа являются дружественными, если
сумма всех делителей первого числа (кроме самого числа) рав на второму
числу. Например, 220 и 284, 1184 и 1210, 2620 и 2924, 5020 и 556 4.
3. Определить, является ли целое положительное число недостаточным.
Недостаточное число всегда больше суммы всех своих делител ей за исклю-
чением самого числа.
4. Вводится целое положительное число. Определить количес тво чётных и
нечётных цифр в числе.
5. Вводится целое положительное число. Найти число, которо е равно сумме
кубов цифр исходного числа.
6. Вводится целое положительное число. Определить, совпад ает ли сумма
цифр, расположенных до середины числа, с суммой цифр распол оженных
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения97
после. Например, задано число из восьми цифр 12112021. Здесь, сумма пер-
вых четырёх цифр, равна сумме следующих четырёх цифр 1 + 2 + 1 + 1 =
2 + 0 + 2 + 1 = 5 . Или, задано число из семи цифр 3456444, тогда 3 + 4 + 5 =
4 + 4 + 4 = 12 . Здесь цифра 6 не учитывается.
7. Вводится целое положительное число. Найти суммы чётных и нечётных
цифр заданного числа.
8. Задано целое положительное число. Определить количеств о его чётных и
нечётных делителей.
9. Проверить, являются ли два целых положительных числа взаимно про-
стыми . Два различных натуральных числа являются взаимно простыми ,
если их наибольший общий делитель равен единице.
10. Определить, является ли целое положительное число составным. Состав-
ное число имеет более двух делителей, то есть не является простым.
11. Вводится целое положительное число. Найти наименьшую ц ифру числа.
12. Задано целое положительное число. Определить, являетс я ли оночислом
Армстронга . Число Армстронга  натуральное число, которое равно сумме
своих цифр, возведённых в степень, равную количеству его ци фр. Напри-
мер, десятичное число 153  число Армстронга, потому что: 13
+ 3 3
+ 5 3
=
1 + 27 + 125 = 153 .
13. Вводится целое положительное число. Найти произведени е всех ненулевых
цифр числа.
14. Вводится целое положительное число. Найти наибольшую ц ифру числа.
15. Вводится целое положительное число. Определить позици ю наибольшей
цифры в числе.
16. Вводится целое положительное число. Найти число, котор ое равно сумме
удвоенных цифр исходного числа.
17. Вводится целое положительное число. Найти число, котор ое равно сумме
квадратов цифр исходного числа.
18. Задано целое положительное число. Определить сумму его делителей.
19. Вводится целое положительное число. Определить позици ю наименьшей
цифры в числе.
20. Проверить, что два целых положительных числа не являются взаимно про-
стыми . Различные натуральные числа не являются взаимно простыми, ес-
ли их наибольший общий делитель отличен от единицы.
21. Убедиться, что заданное целое положительное число не явл яетсяпалин-
дромом . Числа-палиндромы симметричны относительно своей середи ны,
например, 12021 или 454.
22. Убедиться, что заданное целое положительное число не явл яетсясовершён-
ным . Совершённое число равно сумме всех своих делителей, не пре восхо-
дящих это число. Например, 6=1+2+3 или 28=1+2+4+7+14.
23. Проверить, что два целых положительных числа не являются дружествен-
ными . Два различных натуральных числа являются дружественными, если
сумма всех делителей первого числа (кроме самого числа) рав на второму
числу. Например, 220 и 284, 1184 и 1210, 2620 и 2924, 5020 и 556 4.
24. Вводится целое положительное число. Найти число, котор ое равно сумме
утроенных цифр исходного числа.
25. Вводятся два целых положительных числа. Найти сумму их ц ифр.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

98Глава 3. Операторы управления
3.6.8 Вложенные циклы
Разработать программу на языке С++для следующих заданий:
1. Дано натуральное число P. Вывести все простые числа не превосходящие
P .
2. Дано натуральное число P. Вывести все совершённые числа не превосхо-
дящие P.
3. Вводится последовательность положительных целых чисел , 0  конец по-
следовательности. Определить количество совершённых чис ел в последо-
вательности.
4. Вводится последовательность положительных целых чисел , 0  конец по-
следовательности. Определить количество простых чисел в п оследователь-
ности.
5. Вводится последовательность из Nположительных целых чисел. Для каж-
дого элемента последовательности вычислить факториал.
6. Вводится последовательность из Nположительных целых чисел. Вывести
на экран все числа  палиндромы. Если таких чисел нет, выдать соответ-
ствующее сообщение.
7. Вводится последовательность из Nположительных целых чисел. Опреде-
лить разрядность каждого числа.
8. Вводится последовательность из Nположительных целых чисел. Вывести
на экран количество делителей каждого числа.
9. Вводится последовательность положительных целых чисел , 0  конец по-
следовательности. Определить сумму цифр каждого элемента последова-
тельности.
10. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо -
го набора является число 0. Для каждого набора вывести колич ество его
элементов. Вычислить общее количество элементов.
11. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Для каждого набора вычислить средн ее арифме-
тическое его элементов.
12. Даны Kнаборов целых чисел по Nэлементов в каждом наборе. Для каж-
дого набора найти наибольшее значение его элементов.
13. Даны Kнаборов целых чисел по Nэлементов в каждом наборе. Опреде-
лить, есть ли среди наборов данных знакочередующиеся послед овательно-
сти.
14. Даны Kнаборов целых чисел по Nэлементов в каждом наборе. Опреде-
лить, есть ли среди наборов данных строго возрастающие после дователь-
ности.
15. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Для каждого набора найти наименьше е значение
его элементов.
16. Даны Kнаборов целых чисел по Nэлементов в каждом наборе. Для каж-
дого набора вычислить произведение ненулевых элементов.
Программирование на языке С++ в среде Qt Creator

3.6. Задачи для самостоятельного решения99
17. ДаныKнаборов целых чисел по Nэлементов в каждом наборе. Найти
наибольшее число для всех наборов.
18. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Вычислить среднее арифметическое всех элемен-
тов во всех наборах.
19. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Найти количество возрастающих набо ров.
20. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Найти количество убывающих наборов .
21. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Найти количество наборов не являющи хся знако-
чередующимися.
22. Дано Kнаборов ненулевых целых чисел. Признаком завершения каждо го
набора является число 0. Найти количество наборов элементы которых не
возрастают и не убывают.
23. Даны целые положительные числа NиM (N < M ). Вывести все целые
числа от Nдо M включительно; при этом каждое число должно выво-
диться столько раз, каково его значение (например, число 5 в ыводится 5
раз).
24. Дано целое число N >0. Найти сумму 1! + 2! + 3! + . . . + N!
25. Даны целые числа NиM (N < M ). Вывести все целые числа от Nдо M
включительно; при этом число Nдолжно выводиться 1 раз, число N+ 1
должно выводиться 2 раза и т. д.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

Глава 4
Использование функций при
программировании наC++
В практике программирования часто складываются ситуации, к огда одну и
ту же группу операторов, реализующих определённую цель, тре буется повто-
рить без изменений в нескольких местах программы. Для избав ления от столь
нерациональной траты времени была предложена концепция по дпрограммы.
Подпрограмма  именованная, логически законченная группа операторов
языка, которую можно вызвать для выполнения любое количеств о раз из раз-
личных мест программы. В языке C++подпрограммы реализованы в виде функ-
ций [4].
4.1 Общие сведения о функциях. Локальные и глобальные переменные
Функция  это поименованный набор описаний и операторов, выполняющи х
определённую задачу. Функция может принимать параметры и в озвращать зна-
чение. Информация, передаваемая в функцию для обработки, н азываетсяпара-
метром , а результат вычисления функции её значением. Обращение к функ-
ции называют вызовом. Как известно (п. 2.8), любая программа на C++состоит
из одной или нескольких функций. При запуске программы перв ой выполня-
ется функция main. Если среди операторов функции mainвстречается вызов
функции, то управление передаётся операторам функции. Ког да все операторы
функции будут выполнены, управление возвращается операто ру, следующему за
вызовом функции.
Перед вызовом функция должна быть обязательно описана. Описание функ-
ции состоит из заголовка и тела функции:
тип имя_функции(список_переменных) { тело_функции
}

4.1. Общие сведения о функциях101
Заголовок функциисодержит:
• тип возвращаемого функцией значения, он может быть любым; если ф унк-
ция не возвращает значения, указывают тип void;
• имя_функции;
• список_переменных  перечень передаваемых в функцию величин ( аргу-
ментов ), которые отделяются друг от друга запятыми; для каждой пере -
менной из списка указывается типиимя ; если функция не имеет аргумен-
тов, то в скобках указывают либо тип void, либо ничего.
Тело функции представляет собой последовательность описаний и операто ров,
заключённых в фигурные скобки.
В общем виде структура программы наC++ может иметь вид:
директивы компилятора
тип имя_1(список_переменных) {
тело_функции_1;
}
тип имя_2(список_переменных) { тело_функции_2;
}
...
тип имя_n(список_переменных) {
тело_функции_n;
}
i n t m a i n ( список_переменных )
{ / /Тело функции может содержать операторы вызова функций имя_1, имя_2, ..., имя_n
тело_основной_функции;
}
Однако допустима и другая форма записи программного кода :
директивы компилятора
тип имя_1(список_переменных);
тип имя_2(список_переменных);
...
тип имя_n(список_переменных); i n t m a i n ( список_переменных )
{
/ /Тело функции может содержать операторы вызова функций имя_1, имя_2, ..., имя_n
тело_основной_функции;
}
тип имя_1(список_переменных) {
тело_функции_1;
}
тип имя_2(список_переменных) {
тело_функции_2;
}
...
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

102Глава 4. Использование функций при программировании на C++
тип имя_n(список_переменных)
{
тело_функции_n;
}
Здесь функции описаны после функции main(), однако до неё перечислены
заголовки всех функций. Такого рода опережающие заголовки н азываютпро-
тотипами функций . Прототип указывает компилятору тип данных, возвращае-
мых функцией, тип переменных, выступающих в роли аргументов , и порядок их
следования. Прототипы используются для проверки правильно сти вызова функ-
ций в основной программе. Имена переменных, указанные в про тотипе функции,
компилятор игнорирует: / / Записи равносильны.
i n t f u n c ( i n ta ,i n t b ) ;
i n t f u n c ( i n t,i n t ) ;
Вызвать функцию можно в любом месте программы. Для вызова функции
необходимо указать её имяи в круглых скобках, через запятую перечислить имена
или значения аргументов , если таковые имеются:
имя_функции(список_переменных);
Рассмотрим пример. Создадим функцию f(), которая не имеет входных зна-
чений и не формирует результат. При вызове этой функции на эк ран выводится
строка символов "С Новым Годом, " .
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
v o i d f ( )/ /Описание функции.
{
c o u t << " С Новым Годом , " ;
}
i n t m a i n ( )
{ f ( ) ; / /Вызов функции.
c o u t << " Студент! " << e n d l ;
f ( ) ; / /Вызов функции.
c o u t << " Преподаватель! " << e n d l ;
f ( ) ; / /Вызов функции.
c o u t << " Народ! " << e n d l ;
}
Результатом работы программы будут три строки:
С Новым Годом, Студент!
С Новым Годом, Преподаватель!
С Новым Годом, Народ!
Далее приведён пример программы, которая пять раз выводит н а экран фра-
зу "Здравствуй, мир!" . Операция вывода строки символов оформлена в виде
функции fun(). Эта функция также не имеет входных значений и не формирует
результат. Вызов функции осуществляется в цикле:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
v o i d f u n ( )
{
c o u t << " Здравствуй, мир ! " << e n d l ;
}
Программирование на языке С++ в среде Qt Creator

4.1. Общие сведения о функциях103
i n tm a i n ( )
{
f o r (i n t i = 1 ; i <=5; f u n ( ) , i ++) ;
}
Если тип возвращаемого значения не void, то функция может входить в со-
став выражений. Типы и порядок следования переменных в определении и при
вызове функции должны совпадать . Для того чтобыфункция вернулакакое-
либо значение, в ней должен быть оператор:
return (выражение);
Далее приведён пример программы, которая вычисляет значен ие выражения
sin 2
( ) + cos 2
( ) при заданном значении . Здесь функция radianвыполняет
перевод градусной меры угла в радианную 1
.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#d e f i n e P I 3 . 1 4 1 5 9
u s i n g namespace s t d ;
double r a d i a n (i n td e g , i n tmin , i n ts e c )
{
r e t u r n ( d e g∗P I /180+ min ∗P I / 1 8 0 / 6 0 + s e c ∗P I / 1 8 0 / 6 0 / 6 0 ) ;
}
i n t m a i n ( )
{ i n t DEG, MIN , SEC ; doubleRAD ;
/ / Ввод данных.
c o u t << " I n p o u t : " << e n d l ; / /Величина угла:
c o u t << " D E G = " ; c i n >>DEG ; / /градусы,
c o u t << " M I N = " ; c i n >>MIN ; / /минуты,
c o u t << " S E C = " ; c i n >>SEC ; / /секунды.
/ / Величина угла в радианах.
RAD=r a d i a n (DEG, MIN , SEC ) ; / /Вызов функции.
c o u t << " V a l u e i n r a d i a n A = " < / / Вычисление значения выражения и его вывод.
c o u t << " s i n ( A ) ^ 2 + c o s ( A ) ^ 2 = " ;
c o u t << pow ( s i n (RAD) , 2 )+pow ( c o s (RAD) , 2 ) << e n d l ;
r e t u r n 0 ;
}
Переменные, описанные внутри функции, а также переменные и з списка ар-
гументов, являются локальными. Например, если программа содержит пять раз-
ных функций, в каждой из которых описана переменная N, то для C++это пять
различных переменных. Область действия локальной перемен ной не выходит за
рамки функции. Значения локальных переменных между вызова ми одной и той
же функции не сохраняются.
Переменные, определённые до объявления всех функций и дост упные всем
функциям, называют глобальными. В функции глобальную переменную можно
отличить, если не описана локальная переменная с теми же име нем.
Глобальные переменные применяют для передачи данных между ф ункциями,
но это затрудняет отладку программы. Для обмена данными меж ду функциями
используют параметры функций и значения, возвращаемые функ циями.
1
Чтобы найти радианную меру какого-нибудь угла по заданной г радусной мере, нужно
помножить число градусов на
180
, число минут на 180
·60 , число секунд на 180
·60 ·60 и найденные
произведения сложить.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

104Глава 4. Использование функций при программировании на C++
4.2 Передача параметров в функцию
Обмен информацией между вызываемой и вызывающей функциями о су-
ществляется с помощью механизма передачи параметров .Список_переменных ,
указанный в заголовке функции, называется формальными параметрамиили
просто параметрами функции.Список_переменных в операторе вызова функции
 это фактические параметры илиаргументы .
Механизм передачи параметров обеспечивает замену формальных парам ет-
ров фактическими параметрами и позволяет выполнять функцию с различны-
ми данными. Между фактическими параметрами в операторе выз ова функции
и формальными параметрами в заголовке функции устанавлива ется взаимно од-
нозначное соответствие. Количество, типы и порядок следования формальных и
фактических параметров должны совпадать .
Передача параметров выполняется следующим образом. Вычисляются выра-
жения, стоящие на месте фактических параметров. В памяти вы деляется место
под формальные параметры в соответствии с их типами. Затем ф ормальным па-
раметрам присваиваются значения фактических. Выполняется проверка типов
и при необходимости выполняется их преобразование. Передача параметров в функцию может осуществляться по значениюипо
адресу .
При передаче данных по значению функция работает с копиями ф актиче-
ских параметров, и доступа к исходным значениям аргументов у неё нет. При
передаче данных по адресу в функцию передаётся не переменна я, а её адрес, и,
следовательно, функция имеет доступ к ячейкам памяти, в кот орых хранятся
значения аргументов. Таким образом, данные, переданные по значению, функ-
ция изменить не может, в отличие от данных, переданных по адр есу.
Если требуется запретить изменение параметра внутри функц ии, используют
модификатор const. Заголовок функции в общем виде будет выглядеть так:
тип имя_функции (c o n s t тип_переменной* имя_переменной, ...)
Например:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t f 1 (i n t i )/ /Данные передаются по значению
{
r e t u r n ( i ++) ;
}
i n t f 2 (i n t∗j ) / /Данные передаются по адресу. При подстановке фактического параметра,
/ / для получения его значения, применяется операция разадреса ции *.
{
r e t u r n ( (∗j ) ++) ;
}
i n t f 3 (c o n s t i n t ∗k ) / /Изменение параметра не предусмотрено .
{
r e t u r n ( (∗k ) ++) ;
}
i n t m a i n ( )
{ i n t a ;
c o u t << " a = "; c i n >>a ;
f 1 ( a ) ;
c o u t << " a = "< Программирование на языке С++ в среде Qt Creator

4.2. Передача параметров в функцию105
f 2 (& a ) ;/ /Для передачи фактического параметра используется операци я взятия адреса &.
c o u t << " a = "< f 3 (& a ) ;
c o u t << " a = "< r e t u r n 0 ;
}
Результат работы программы:
Введено значение переменной a.
a=5
Значение переменной a после вызова функции f1 не изменилось.
a=5
Значение переменной a после вызова функции f2 изменилось.
a=6
Значение переменной a после вызова функции f3 не изменилось.
a=6
Удобно использовать передачу данных по адресу, если нужно ч тобы функция
изменяла значения переменных в вызывающей программе.
Далее приведён пример программы, в которой исходя из радиан ной меры
некоторого угла вычисляется величина смежного с ним угла. Н а экран выво-
дятся значения углов в градусной мере. Функция degreeвыполняет перевод из
радианной меры в градусную 2
. Эта функция ничего не возвращает. Её аргумен-
тами являются значениепеременной rad, определяющее величину угла в радиа-
нах, и адреса переменных deg,min ,sec , в которых будут храниться вычисленные
результаты  градусная мера угла.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#d e f i n e P I 3 . 1 4 1 5 9
u s i n g namespace s t d ;
v o i d d e g r e e ( doubler a d ,i n t∗d e g , i n t∗min , i n t∗s e c )
{ ∗d e g= f l o o r ( r a d ∗1 8 0 / P I ) ;
∗ min= f l o o r ( ( r a d ∗1 8 0 / PI −(∗ d e g ) ) ∗6 0 ) ;
∗ s e c= f l o o r ( ( ( r a d ∗1 8 0 / PI −(∗ d e g ) ) ∗6 0 −(∗ min ) ) ∗6 0 ) ;
} i n t m a i n ( )
{ i n t DEG, MIN , SEC ; doubleRAD ;
c o u t << " I n p o u t : " << e n d l ;
c o u t << " V a l u e i n r a d i a n A = " ; c i n >>RAD ;
d e g r e e (RAD, &DEG, &MIN, &SEC ) ;
c o u t << DEG<< " "< d e g r e e ( PI −RAD, &DEG, &MIN, &SEC ) ;
c o u t << DEG<< " "< r e t u r n 0 ;
}
2 Чтобы найти градусную меру угла по заданной радианной, нужн о помножить число ра-
диан на 180

; если из полученной дроби выделить целую часть, то получим г
радусы; если из
числа полученного умножением оставшейся дробной части на 6 0, выделить целую часть, по-
лучим минуты; секунды вычисляются аналогично из дробной ча сти минут.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

106Глава 4. Использование функций при программировании на C++
4.3 Возврат результата с помощью оператора return
Возврат результата из функции в вызывающую её функцию осуществляет-
ся оператором
return выражение;
Работает оператор следующим образом. Вычисляется значение выражения,
указанного после return, и преобразуется к типу возвращаемого функцией зна-
чения. Выполнение функции завершается, а вычисленное знач ение передаётся
в вызывающую функцию. Любые операторы, следующие в функции за оп ера-
тором return , игнорируются. Программа продолжает свою работу с оператор а,
следующего за оператором вызова данной функции.
Оператор returnможет отсутствовать в функциях типа void, если возврат
происходит перед закрывающейся фигурной скобкой, и в функци иmain .
Также функция может содержать несколько операторов return, если это
определено потребностями алгоритма. Например, в следующей программе функ-
ция equation вычисляет корни квадратного уравнения. Если a= 0 (уравнение
не является квадратным), то в программу передаётся значени е равное−1, ес-
ли дискриминант отрицательный (уравнение не имеет действи тельных корней),
то 1, а если положительный, то вычисляются корни уравнения и в программу
передаётся 0.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t e q u a t i o n ( f l o a ta ,f l o a t b ,f l o a t c ,f l o a t ∗x1 , f l o a t ∗x 2 )
{ f l o a t D=b∗b − 4∗ a ∗ c ;
i f ( a ==0) r e t u r n −1 ;
e l s e i f ( D<0)r e t u r n 1 ;
e l s e
{ ∗x 1=( −b+ s q r t (D) ) / 2 / a ;
∗ x 2=( −b− s q r t (D) ) / 2 / a ;
r e t u r n 0 ;
}
}
i n t m a i n ( )
{
f l o a t A , B , C , X1 , X2 ; i n tP ;
c o u t << " E n t e r t h e c o e f f i c i e n t s o f t h e e q u a t i o n : " << e n d l ;
c o u t << " A = "; c i n >>A ;
c o u t << " B = "; c i n >>B ;
c o u t << " C = "; c i n >>C ;
P=e q u a t i o n ( A , B , C , &X1 , &X2 ) ;
i f ( P== −1) c o u t << " i n p u t E r r o r " << e n d l ;
e l s e i f ( P==1) c o u t << " N o r e a l r o o t s " < e l s e c o u t << " X 1 = "< r e t u r n 0 ;
}
4.4 Решение задач с использованием функций Рассмотрим несколько задач с применением функций.
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций107
Задача 4.1.Вводится последовательность из Nцелых чисел, найти среднее
арифметическое совершённых чисел и среднее геометрическо е простых чисел
последовательности.
Напомним, что целое число называется простым, если оно делится нацело
только на само себя и единицу. Подробно алгоритм определени я простого числа
описан в задаче 3.15 (рис. 3.29). В этой задаче кроме простых чисел фигурируют
совершённые числа. Число называется совершённым, если сумма всех делителей,
меньших его самого, равна этому числу. Алгоритм, с помощью ко торого можно
определить делители числа, подробно рассмотрен в задаче 3. 14 (рис. 3.28).
Для решения поставленной задачи понадобятся две функции:
• prostoe  определяет, является ли число простым, аргумент функции ц е-
лое число N; функция возвращает 1, если число простое и 0  в противном
случае.;
• soversh  определяет, является ли число совершённым; входной парам етр
целое число N; функция возвращает 1, если число является совершённым
и 0  в противном случае.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u n s i g n e d i n t p r o s t o e (u n s i g n e d i n t N)/ /Описание функции.
{
/ /Функция определяет, является ли число простым.
i n t i , p r ;
f o r ( p r = 1 , i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0) { p r = 0 ; break; }
r e t u r n p r ;
}
u n s i g n e d i n t s o v e r s h (u n s i g n e d i n t N)/ /Описание функции.
{ //Функция определяет, является ли число совершённым.
u n s i g n e d i n t i , S ;
f o r ( S = 0 , i = 1 ; i <=N / 2 ; i ++)
i f (N% i ==0) S+= i ; / /Сумма делителей.
i f ( S==N) r e t u r n 1 ;
e l s e r e t u r n 0 ;
} u s i n g namespace s t d ;
i n t m a i n ( )
{
u n s i g n e d i n t i , N , X , S , kp , k s ;
l o n g i n t P ;
c o u t << " N = "; c i n >>N ;
f o r ( kp=k s=S = 0 ,P= 1 , i = 1 ; i <=N ; i ++)
{
c o u t << " X = "; c i n >> X ; / /Вводится элемент последовательности.
i f ( p r o s t o e (X) ) / /X  простое число.
{
kp++; / /Счётчик простых чисел.
P ∗=X ; / /Произведение простых чисел.
} i f ( s o v e r s h (X) ) / /X  совершённое число.
{ k s ++; / /Счётчик совершённых чисел.
S+=X ; / /Сумма совершённых чисел.
}
}
i f ( kp >0) / /Если счётчик простых чисел больше нуля,
/ / считаем среднее геометрическое и выводим его,
c o u t << " Среднее геометрическое = " < © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

108Глава 4. Использование функций при программировании на C++
e l s e/ /в противном случае –– сообщение об отсутствии простых чисел.
c o u t << " Нет простых чисел \ n " ;
i f ( k s >0) / /Если счётчик совершённых чисел больше нуля,
/ / считаем среднее арифметическое и выводим его,
c o u t << " Среднее арифметическое = " <<(f l o a t ) S / k s < e l s e / /в противном случае  сообщение об отсутствии совершённых чисе л.
c o u t << " Нет совершённых чисел \ n " ;
r e t u r n 0 ;
}
Задача 4.2. Вводится последовательность целых чисел, 0  конец последо ва-
тельности. Найти минимальное число среди простых чисел и ма ксимальное 
среди чисел, не являющихся простыми.
Для решения данной задачи создадим функцию prostoe, которая будет про-
верять, является ли число Nпростым. Входным параметром функции будет це-
лое положительное число N. Функция будет возвращать значение 1, если число
простое, и 0 в противном случае. Алгоритм поиска максимума (минимума)
подробно описан в задаче 3.20 (рис. 3.31). Текст программы:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
u n s i g n e d i n t p r o s t o e (u n s i g n e d i n t N)
{ i n t i , p r ;
f o r ( p r = 1 , i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0) { p r = 0 ; break; }
r e t u r n p r ;
} i n t m a i n ( )
{ i n t kp = 0 , knp = 0 , min , max , N ;
f o r ( c o u t << " N = ", c i n >>N ; N! = 0 ; c o u t << " N = ", c i n >>N)
/ / В цикле вводится элемент последовательности N .
i f ( p r o s t o e (N) ) / /N простое число ,
{ kp++; / /счётчик простых чисел.
i f ( kp==1) min=N ; / /Предполагаем, что первое простое число минимально,
e l s e i f ( N } e l s e / /N простым не является,
{
knp++; / /счётчик чисел не являющихся простыми.
i f ( knp==1) max=N ; / /Предполагаем, что первое не простое число максимально,
e l s e i f ( N>max ) max=N ; / /если найдётся большее число, сохраняем его.
}
i f ( kp >0) / /Если счётчик простых чисел больше нуля,
c o u t << " m i n = "< e l s e / /в противном случае 
c o u t << " Нет простых чисел " ;/ / сообщение об отсутствии простых чисел.
i f ( knp >0) / /Если счётчик чисел не являющихся простыми больше нуля,
c o u t << " m a x = "< e l s e / /в противном случае 
c o u t << " Нет составных чисел " ;/ /сообщение об отсутствии чисел
/ / не являющихся простыми.
r e t u r n 0 ;
}
Задача 4.3. Вводится последовательность из Nцелых положительных чисел. В
каждом числе найти наименьшую и наибольшую цифры 3
.
3Выделение цифры из числа подробно описано в задаче 3.16
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций109
Программный код к задаче 4.3.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
u n s i g n e d i n t Cmax (u n s i g n e d l o n g l o n g i n t P )
{
u n s i g n e d i n t max ;
i f ( P==0) max = 0 ;
f o r (i n t i =1 ; P ! = 0 ; P/ = 1 0 )
{ i f ( i ==1) {max=P% 1 0 ; i ++;}
i f ( P%10>max ) max=P% 1 0 ;
}
r e t u r n max ;
}
u n s i g n e d i n t Cmin (u n s i g n e d l o n g l o n g i n t P )
{ u n s i g n e d i n t min ;
i f ( P==0) min = 0 ;
f o r (i n t i = 1 ; P ! = 0 ; P/ = 1 0 )
{ i f ( i ==1) { min=P% 1 0 ; i ++;}
i f ( P%10 } r e t u r n min ;
} i n t m a i n ( )
{ u n s i g n e d i n t N , k ;
u n s i g n e d l o n g l o n g i n t X ;
f o r ( c o u t << " N = ", c i n >>N , k = 1 ; k<=N ; k++)
{
c o u t << " X = "; c i n >>X ;
c o u t << "Максимальная цифра = "< c o u t << "Минимальная цифра = "< }
r e t u r n 0 ;
}
Задача 4.4. Вводится последовательность целых положительных чисел, 0 
конец последовательности. Определить, сколько в последов ательности чисел-
палиндромов 4
.
Алгоритм определения палиндрома подробно описан в задаче 3. 19. Далее при-
ведён программный код к задаче 4.4
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
b o o l p a l i n d r o m ( u n s i g n e d l o n g l o n g i n t N)
{ / / Функция определяет, является ли число Nпалиндромом, возвращает true, если N
/ / палиндром, и falseв противном случае
u n s i g n e d l o n g i n t M, R , S ;
i n t k o l , i ;
f o r (R= 1 , k o l = 1 ,M=N ;M/ 1 0 > 0 ; k o l ++,R ∗= 1 0 ,M/ = 1 0 ) ;
f o r ( S = 0 ,M=N , i = 1 ; i <=k o l ; S+=M%10 ∗R ,M/ = 1 0 ,R/ = 1 0 , i ++) ;
i f (N==S ) r e t u r n t r u e ;
e l s e r e t u r n f a l s e ;
}
i n t m a i n ( )
{ u n s i g n e d l o n g l o n g i n t X ;
i n t K ;
f o r (K= 0 , c o u t << " X = ", c i n >>X ; X! = 0 ; c o u t << " X = ", c i n >>X)
i f ( p a l i n d r o m (X) ) K++;
4
Палиндром  любой симметричный относительно своей середин ы набор символов.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

110Глава 4. Использование функций при программировании на C++
c o u t <<" Количество палиндромов равно K = " < r e t u r n 0 ;
}
Задача 4.5. Заданы два числа  Xв двоичной системе счисления, Yв системе
счисления с основанием пять. Найти сумму этих чисел. Резуль тат вывести в
десятичной системе счисления.
Любое целое число N, заданное в b-ичной системе счисления, можно предста-
вить в десятичной системе счисления:
N=P
n ·
bb
+ P
n− 1 ·
bn
− 1
+ ... +P
2 ·
b2
+ P
1 ·
b + P
0 = n
X
i =0 P

bi
,
где b основание системы счисления (целое положительное фиксированное чис-
ло), P
i 
разряд числа: 0 P
i
b− 1, i = 0 ,1 ,2 , ..., n. Например,
743 10 = 7
·10 2
+ 4 ·10 1
+ 3 ·10 0
= 700 + 40 + 3 = 743 10;
1011101
2=
1 ·2 6
+ 0 ·2 5
+ 1 ·24
+ 1 ·23
+ 1 ·22
+ 0 ·21
+ 1 ·20
= 64 + 16 + 8 + 4 + 1 = 93 10.
Создадим функцию для перевода целого числа N, заданного в b-ичной систе-
ме счисления, в десятичную систему счисления.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
u n s i g n e d l o n g l o n g i n t DecNC (u n s i g n e d l o n g l o n g i n t N ,u n s i g n e d i n t b )
{
/ / Функция выполняет перевод числа N,заданного в b-ичной системе счисления,
/ / в десятичную систему счисления
u n s i g n e d l o n g l o n g i n t S , P ;
f o r ( S = 0 ,P= 1 ;N! = 0 ; S+=N%10 ∗P , P ∗=b , N/ = 1 0 ) ;
r e t u r n S ;
}
i n t m a i n ( )
{
u n s i g n e d l o n g l o n g i n t X , Y ;u n s i g n e d i n t bX , bY ;
c o u t << " X = "; c i n >>X ; / /Ввод числа X .
c o u t << " b = "; c i n >>bX ; / /Ввод основания с/с.
c o u t << " Y = "; c i n >>Y ; / /Ввод числа X .
c o u t << " b = "; c i n >>bY ; / /Ввод основания с/с.
/ / Вывод заданных чисел в десятичной с/с.
c o u t < c o u t < / / Вычисление суммы и вывод результата.
c o u t < c o u t < r e t u r n 0 ;
}
Задача 4.6. Задано число Xв десятичной системе счисления. Выполнить пере-
вод числа в системы счисления с основанием 2, 5 и 7.
Вообще, для того чтобы перевести целое число из десятичной с истемы счис-
ления в другую, необходимо выполнить следующие действия:
1. Разделить данное число на основание новой системы счисле ния: остаток от
деления  младший разряд нового числа;
2. Если частное от деления не равно нулю, продолжать деление, как указано
в п.1.
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций111
На рис. 4.1 приведён пример ручного перевода числа 256, заданного в десятич-
ной системе счисления, в восьмеричную. В результате получим 256
(10) = 400
(8).
256
8
− 256 32 8
0 −32 4
0
Рис. 4.1: Пример перевода числа в новую систему счисления
Далее приведён текст программы, реализующей решение задачи 4.6.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
u n s i g n e d l o n g l o n g i n t NC(u n s i g n e d l o n g l o n g i n t N ,u n s i g n e d i n t b )
{
u n s i g n e d l o n g l o n g i n t S , P ;
f o r ( S = 0 ,P= 1 ;N! = 0 ; S+=N%b ∗P , P ∗= 1 0 ,N/=b ) ;
r e t u r n S ;
} i n t m a i n ( )
{ u n s i g n e d l o n g l o n g i n t X ;
c o u t << " X = "; c i n >>X ; / /Ввод числа X .
/ / Перевод числа Xв заданные системы счисления.
c o u t < c o u t < c o u t < r e t u r n 0 ;
}
Задача 4.7. Найти корни уравнения x2
− cos(5 ·x ) = 0 .
Для решения задачи использовать:
• метод половинного деления ,
• метод хорд ,
• метод касательных (метод Ньютона),
• метод простой итерации .
Оценить степень точности предложенных численных методов, определив, за
сколько итераций был найден корень уравнения. Вычисления п роводить с точ-
ностью = 10 −
3
.
Вообще говоря, аналитическое решение уравнения
f(x ) = 0 (4.1)
можно найти только для узкого класса функций. В большинстве случаев прихо-
дится решать уравнение (4.1) численными методами. Численное решение урав-
нения (4.1) проводят в два этапа: сначала необходимо отделить корни уравне-
ния , т.е. найти достаточно тесные промежутки, в которых содерж ится только
один корень, эти промежутки называют интервалами изоляции корня; на вто-
ром этапе проводят уточнение отделённых корней, т.е. находят корни с заданной
точностью .
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

112Глава 4. Использование функций при программировании на C++
Интервал можно выделить, изобразив график функции, или как им-либо дру-
гим способом. Но все способы основаны на следующем свойстве н епрерывной
функции: если функция f(x ) непрерывна на интервале [a, b ]и на его концах име-
ет различные знаки, f(a ) ·f (b ) < 0, то между точками имеется хотя бы один
корень. Будем считать интервал настолько малым, что в нём на ходится только
один корень. Рассмотрим самый простой способ уточнения кор ней.
Графическое решение задачи 4.7 показано на рис. 4.2. Так как функция
f (x ) = x2
− cos(5 ·x ) дважды пересекает ось абсцисс, можно сделать вывод о
наличии в уравнении x2
− cos(5 ·x ) = 0 двух корней. Первый находится на ин-
тервале [− 0.4; −0.2] , второй принадлежит отрезку [0.2; 0 .4] .
Рис. 4.2: Геометрическое решение задачи 4.7
Рассмотрим предложенные в задаче численные методырешения нелинейных
уравнений. Метод половинного деления (дихотомии) . Пусть был выбран интервал изо-
ляции [a, b ](рис. 4.3). Примем за первое приближение корня точку c, которая
является серединой отрезка [a, b ]. Далее будем действовать по следующему ал-
горитму: 1. Находим точку c= a
+ b
2 ;
2. Находим значение f(c );
3. Если f(a ) ·f (c ) < 0, то корень лежит на интервале [a, c ], иначе корень
лежит на интервале [c, b ];
4. Если величина интервала меньше либо равна , то найден корень с точно-
стью , иначе возвращаемся к п.1.
Итак, для вычисления одного из корней уравнения x2
− cos(5 ·x ) = 0 методом
половинного деления достаточно знать интервал изоляции ко рняa= 0 .2; b= 0 .4
и точность вычисления = 10 −
3
.
Блок-схема алгоритма решения уравнения методом дихотомии приведена на
рис. 4.4. Понятно, что здесь c корень заданного уравнения.
Однако, несмотря на простоту, такое последовательное суже ние интервала
проводится редко, так как требует слишком большого количес тва вычислений.
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций113
Рис. 4.3: Графическая интерпретация метода половинного деления
Кроме того, этот способ не всегда позволяет найти решение с з аданной точно-
стью. Рассмотрим другие способы уточнения корня. При примен ении этих спосо-
бов будем требовать, чтобы функция f(x ) удовлетворяла следующим условиям
на интервале [a, b ]:
1. функция f(x ) непрерывна вместе со своими производными первого и вто-
рого порядка. Функция f(x ) на концах интервала [a, b ]имеет разные знаки
f (a ) ·f (b ) < 0;
2. первая и вторая производные f′
( x ) и f′′
(x ) сохраняют определённый знак
на всём интервале [a, b ].
Метод хорд . Этот метод отличается от метода дихотомии тем, что очеред-
ное приближение берём не в середине отрезка, а в точке пересе чения с осьюX
(рис. 4.5) прямой, соединяющей точки (a, f (a )) и(b, f (b )) .
Запишем уравнение прямой, проходящей через точки с координ атами(a, f (a ))
и (b, f (b )) :
y− f(a )
f (b ) − f(a ) =
x
− a b− a, y
=f
(b ) − f(a ) b − a ·
(x − a) + f(a ) (4.2)
Прямая, заданная уравнением (4.2), пересекает ось Xпри условии y= 0 .
Найдём точку пересечения хорды с осью X:
y = f
(b )− f(a )
b− a ·
(x − a) + f(a ), x= a− f
(a )·( b − a) f (b )− f(a ) ,
итак, c= a− f
(a )
f (b )− f(a )(
b − a).
Далее необходимо вычислить значение функции в точке c. Это и будет при-
ближённое значение корня уравнения.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

114Глава 4. Использование функций при программировании на C++
Рис. 4.4: Алгоритм решения уравнения методом дихотомии
Для вычисления одного из корней уравнения x2
− cos(5 ·x) = 0 методом
хорд достаточно знать интервал изоляции корня, например, a= 0 .2; b= 0 .4 , и
точность вычисления = 10 −
3
. Блок-схема метода представлена на рис. 4.6.
Метод касательных (метод Ньютона ). В одной из точек интервала [a ;b],
пусть это будет точка a, проведём касательную (рис. 4.7). Запишем уравнение
этой прямой:
y= k·x + m (4.3)
Так как эта прямая является касательной, и она проходит чере з точку
( c, f (c )) , то k= f′
( c ).
Следовательно,
y = f′
( x ) ·x + m, f (c ) = f′
( c ) ·c + m, m =f(c ) − c·f ′
( c ),
y = f′
( c ) ·x + f(c ) − c·f ′
( c ), y =f′
( c ) ·(x − c) + f(c ).
Найдём точку пересечения касательной с осью X:
f ′
( c ) ·(x − c) + f(c ) = 0 ,x= c− f
(c )
f ′
( c )
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций115
Рис. 4.5: Графическая интерпретация метода хорд
Если |f (x )| < , то точность достигнута, и точка x решение; иначе необхо-
димо переменной cприсвоить значение xи провести касательную через новую
точку c; так продолжать до тех пор, пока |f (x )| не станет меньше . Осталось
решить вопрос, что выбрать в качестве точки начального приб лиженияc.
В этой точке должны совпадать знаки функции и её второй произ водной.
А так как нами было сделано допущение, что вторая и первая про изводные не
меняют знак, то можно проверить условие f(x ) ·f′′
(x ) > 0на обоих концах
интервала, и в качестве начального приближения взять ту точ ку, где это условие
выполняется.
Здесь, как и в предыдущих методах, для вычисления одного из к орней урав-
нения x2
− cos(5 ·x ) = 0 достаточно знать интервал изоляции корня, например,
a = 0 .2; b = 0 .4 , и точность вычисления = 10 −
3
. Блок-схема метода Нью-
тона представлена на рис. 4.8. Понятно, что для реализации э того алгоритма
нужно найти первую и вторую производные функции f(x ) = x2
− cos(5 ·x):
f ′
( x ) = 2 ·x + 5 ·sin(5 ·x ) ,f(x ) = 2 + 25 ·cos (5·x ).
Метод простой итерации . Для решения уравнения этим методом необходимо
записать уравнение (4.1) в виде x= (x ), задать начальное приближение x
0 ∈
[ a ;b] и организовать следующий итерационный вычислительный проц есс:
x k+1 =
(x
k)
, k = 0 ,1 ,2 , ...
Вычисление прекратить, если |x
k+1 −
x
k|
< (  точность).
Если неравенство | ′
( x )| < 1выполняется на всём интервале [a ;b], то после-
довательность x
0, x
1, x
2, ..., x
n, ...
сходится к решению x∗
(т.е. lim
k →∞ x
k =
x∗
).
Значение функции (x ) должно удовлетворять условию | ′
( x )| < 1для то-
го, чтобы можно было применить метод простых итераций. Усло вие| ′
( x )| < 1
является достаточным условием сходимости метода простой итерации.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

116Глава 4. Использование функций при программировании на C++
Рис. 4.6: Алгоритм метода хорд
Уравнение (4.1) можно привести к виду x= (x ) следующим образом. Умно-
жить обе части уравнения f(x ) = 0 на число . К обеим частям уравнения
·f (x ) = 0 добавить число x. Получим x= x+ ·f (x ). Это и есть уравне-
ние вида x= (x ), где
(x ) = x+ ·f (x ) (4.4)
Необходимо чтобы неравенство | ′
( x )| < 1выполнялось на интервале [a ;b],
следовательно, | ′
( x )| = |1 + ·f ′
( x )| и |1 + ·f ′
( x )| < 1(|1 + ·f ′
( a )| < 1,
| 1 + ·f ′
( b )| < 1), а значит, с помощью подбора параметраможно добиться
выполнения условия сходимости .
Для вычисления корней уравнения x2
− cos(5 ·x ) = 0 воспользуемся графиче-
ским решением (рис. 4.2) и определим интервал изоляции одно го из корней, на-
пример, a= 0 .2; b= 0 .4 . Подберём значение , решив неравенство |1+ ·f ′
( x )| < 1:
| 1 + ·f ′
( a )| < 1и |1 + ·f ′
( b )| < 1,
f (x ) = x2
− cos(5 ·x ), f ′
( x ) = 2 ·x + 5 ·sin(5 ·x ),
f ′
( a ) = 2 ·0.2 + 5 ·sin(5 ·0.2) ≈4.6 ,f′
( b ) = 2 ·0.4 + 5 ·sin(5 ·0.4) ≈5.35 ,
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций117
Рис. 4.7: Графическая интерпретация метода касательных
| 1 + ·4.6 | < 1и |1 + ·5.35 |< 1.
     
1 + 4 .6 · < 1
1 + 4 .6 · > −1

< 0
> −0.37 ⇒     
< 0
> −0.4

< 0
> −0.37 ⇒

∈ (− 0.4; 0)
∈ (− 0.37; 0)
и, следовательно, ∈ (− 0.37; 0) .
Таким образом, исходными данными для программы будут начал ьное зна-
чение корня уравнения x
0 = 0
.2 , значение параметра (пусть = −0.2 ), и
точность вычислений = 0 .001 .
Для вычисления второго корня заданного уравнения параметр подбирают
аналогично.
Блок-схема метода простой итерации приведена на рис. 4.9.
Далее представлен текст программы, реализующий решение зад ачи 4.7.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
/ / Функция, определяющая левую часть уравнения f(x ) = 0 .
double f (double x )
{ r e t u r n ( x∗x− c o s ( 5 ∗x ) ) ;
}
/ / Функция, реализующая метод половинного деления.
i n t D i c h o t o m y ( doublea ,double b ,double ∗c , double e p s )
{ i n t k = 0 ;
do
{ ∗c =( a+b ) / 2 ;
i f ( f (∗c ) ∗f ( a ) <0) b= ∗c ;
e l s e a=∗c ;
k++;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

118Глава 4. Использование функций при программировании на C++
Рис. 4.8: Алгоритм метода Ньютона
} w h i l e ( f a b s ( a −b )>=e p s ) ;
r e t u r n k ;
}
/ / Функция, реализующая метод хорд.
i n t C h o r d ( double a ,double b ,double ∗c , double e p s )
{ i n t k = 0 ;
do {
∗c=a −f ( a ) / ( f ( b ) −f ( a ) ) ∗( b −a ) ;
i f ( f (∗c ) ∗f ( a ) >0) a= ∗c ;
e l s e b=∗c ;
k++;
}
w h i l e ( f a b s ( f ( ∗c ) )>=e p s ) ;
r e t u r n k ;
}
double f 1 (double x )/ /Первая производная функции f(x ).
{
Программирование на языке С++ в среде Qt Creator

4.4. Решение задач с использованием функций119
Рис. 4.9: Алгоритм метода простой итерации
r e t u r n ( 2∗x +5 ∗s i n ( 5 ∗x ) ) ;
}
double f 2 (double x )/ /Вторая производная функции f(x ).
{
r e t u r n ( 2 + 2 5∗c o s ( 5 ∗x ) ) ;
}
/ / Функция, реализующая метод касательных.
i n t T a n g e n t ( doublea ,double b ,double ∗c , double e p s )
{ i n t k = 0 ;
i f ( f ( a ) ∗f 2 ( a ) >0) ∗c=a ;
e l s e ∗c=b ;
do {
∗c = ∗c− f ( ∗c ) / f 1 ( ∗c ) ;
k++;
}
w h i l e ( f a b s ( f ( ∗c ) )>=e p s ) ;
r e t u r n k ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

120Глава 4. Использование функций при программировании на C++
doublef i (double x ,double L )/ /Функция, заданная выражением 4.4 .
{
r e t u r n ( x+L∗f ( x ) ) ;
}
/ / Функция, реализующая метод простой итерации.
i n t I t e r a t i o n ( double∗x , double L ,double e p s )
{ i n t k = 0 ; double x 0 ;
do {
x 0= ∗x ;
∗ x= f i ( x0 , L ) ;
k++;
} w h i l e ( f a b s ( x0 −∗x )>=e p s ) ;
r e t u r n k ;
}
i n t m a i n ( )
{
double A , B , X , P ;
double e p = 0 . 0 0 1 ; / /Точность вычислений.
i n t K ;
c o u t << " a = "; c i n >>A ; / /Интервал изоляции корня.
c o u t << " b = "; c i n >>B ;
c o u t << " Решение уравнения x ^ 2 - c o s ( 5 * x ) = 0 . " << e n d l ;
c o u t << " Метод дихотомии: " << e n d l ;
K=D i c h o t o m y ( A , B, &X , e p ) ; c o u t << " Найденное решение x = " < c o u t << " , количество итераций k = " < c o u t << " Метод хорд: " << e n d l ;
K=C h o r d ( A , B, &X , e p ) ;
c o u t << " Найденное решение x = " < c o u t << " , количество итераций k = " < c o u t << " Метод касательных : " << e n d l ;
K=T a n g e n t ( A , B, &X , e p ) ;
c o u t << " Найденное решение x = " < c o u t << " , количество итераций k = " < c o u t << " Метод простой итерации : " << e n d l ;
X=A ; c o u t << " L = "; c i n >>P ;
K= I t e r a t i o n (&X , P , e p ) ; c o u t << " Найденное решение x = " < c o u t << " , количество итераций k = " < r e t u r n 0 ;
}
Результаты работы программы:
a=0.2
b=0.4
Решение уравнения x^2-cos(5*x)=0.
Метод дихотомии:
Найденное решение x=0.296094, количество итераций k=8
Метод хорд:
Найденное решение x=0.296546, количество итераций k=2
Метод касательных:
Найденное решение x=0.296556, количество итераций k=2
Метод простой итерации:
L=-0.2
Найденное решение x=0.296595, количество итераций k=3
Программирование на языке С++ в среде Qt Creator

4.5. Рекурсивные функции121
4.5 Рекурсивные функции
Под рекурсией в программировании понимают функцию, которая вызывает
сама себя. Рекурсивные функции чаще всего используют для компактной реа-
лизации рекурсивных алгоритмов. Классическими рекурсивн ыми алгоритмами
могут быть возведение числа в целую положительную степень, вычисление фак-
ториала. С другой стороны, любой рекурсивный алгоритм можно реализовать
без применения рекурсий. Достоинством рекурсии является к омпактная запись,
а недостатком  расход памяти на повторные вызовы функций и п ередачу па-
раметров, существует опасность переполнения памяти.
Рассмотрим применение рекурсии на примерах [7, 8].
Задача 4.8. Вычислить факториал числа n.
Вычисление факториала подробно рассмотрено в задаче 3.12 ( рис. 3.25). Для
решения этой задачи с применением рекурсии создадим функци юfactoial , ал-
горитм которой представлен на рис. 4.10.
Рис. 4.10: Рекурсивный алгоритм вычисления факториала
Текст программы с применением рекурсии:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
l o n g i n t f a c t o r i a l ( i n tn )
{
i f ( n<=1)
r e t u r n n ;
e l s e
r e t u r n n∗ f a c t o r i a l ( n −1) ;
}
i n t m a i n ( )
{
i n t i ;l o n g i n t f ;
c o u t << " i = "; c i n >> i ;
f = f a c t o r i a l ( i ) ;
c o u t < r e t u r n 0 ;
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

122Глава 4. Использование функций при программировании на C++
Задача 4.9.Вычислитьn-ю степень числа a(n  целое число).
Результатом возведения числа aв целую степень nявляется умножение это-
го числа на себя nраз. Но это утверждение верно только для положительных
значений n. Если nпринимает отрицательные значения, то a−
n
= 1
a
n
. В случае
n = 0 ,a0
= 1 .
Для решения задачи создадим рекурсивную функцию stepen, алгоритм ко-
торой представлен на рис. 4.11.
Рис. 4.11: Рекурсивный алгоритм вычисления степени числа
Текст программы с применением рекурсии:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
f l o a t s t e p e n ( f l o a ta ,i n t n )
{
i f ( n==0)
r e t u r n 1 ;
e l s e i f ( n <0)
r e t u r n 1 / s t e p e n ( a , −n ) ;
e l s e r e t u r n a∗ s t e p e n ( a , n −1) ;
}
i n t m a i n ( )
{
i n t i ;f l o a t s , b ;
c o u t << " b = "; c i n >>b ;
c o u t << " i = "; c i n >> i ;
s=s t e p e n ( b , i ) ;
c o u t << " s = "< r e t u r n 0 ;
}
Задача 4.10. Вычислитьn-е число Фибоначчи.
Если нулевой элемент последовательности равен нулю, первый  единице,
а каждый последующий представляет собой сумму двух предыдущ их, то это
последовательность чисел Фибоначчи (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... ).
Программирование на языке С++ в среде Qt Creator

4.6. Перегрузка функций123
Алгоритм рекурсивной функцииfibonachiизображён на рис. 4.12.
Рис. 4.12: Рекурсивный алгоритм вычисления числа Фибоначч и
Текст программы:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
l o n g i n t f i b o n a c h i ( u n s i g n e d i n t n )
{
i f ( ( n==0) | | ( n==1) )
r e t u r n n ;
e l s e r e t u r n f i b o n a c h i ( n −1)+ f i b o n a c h i ( n −2) ;
} i n t m a i n ( )
{
i n t i ;l o n g i n t f ;
c o u t << " i = "; c i n >> i ;
f = f i b o n a c h i ( i ) ;
c o u t << " f = "< r e t u r n 0 ;
}
4.6 Перегрузка функций Язык C++позволяет связать с одним и тем же именем функции различные
определения, то есть возможно существование нескольких фу нкций с одинако-
вым именем. У этих функций может быть разное количество пара метров или
разные типы параметров. Создание двух или более функций с од ним и тем же
именем называется перегрузкой имени функции . Перегруженные функции созда-
ют, когда одно и то же действие следует выполнить над разными т ипами входных
данных.
В приведённом далее тексте программы три функции с именем Pow. Пер-
вая выполняет операцию возведения вещественного числа aв дробную степень
n = k
m
, где
kи m  целые числа. Вторая возводит вещественное число aв
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

124Глава 4. Использование функций при программировании на C++
целую степеньn, а третья  целое число aв целую степень 5
n. Какую имен-
но функцию вызвать компилятор определяет по типу фактическ их параметров.
Так, если a вещественное число, а k целое, то оператор Pow(a,k)вызо-
вет вторую функцию, так как она имеет заголовок float Pow(float a, int n).
Команда Pow((int)a,k) приведёт к вызову третьей функции float Pow(int a,
int n) , так как вещественная переменная aпреобразована к целому типу. Пер-
вая функция float Pow(float a, int k, int m) имеет три параметра, значит,
обращение к ней осуществляется командой Pow(a,k,m).
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
#i n c l u d e
f l o a t Pow (f l o a t a ,i n t k ,i n t m)/ /Первая функция
{
c o u t << "Функция 1 \ t ";
i f ( a ==0)
r e t u r n 0 ;
e l s e i f ( k==0)
r e t u r n 1 ;
e l s e i f ( a >0)
r e t u r n e x p ( (f l o a t) k /m∗l o g ( a ) ) ;
e l s e i f (m% 2 ! = 0 )
r e t u r n −( e x p ( ( f l o a t) k /m∗l o g ( −a ) ) ) ;
} f l o a t Pow (f l o a t a ,i n t n ) / /Вторая функция
{
f l o a t p ;i n t i ;
c o u t << "Функция 2 \ t ";
i f ( a ==0)
r e t u r n 0 ;
e l s e i f ( n==0)
r e t u r n 1 ;
e l s e i f ( n <0)
{ n=−n ;
p = 1 ; f o r ( i = 1 ; i <=n ; i ++)
p ∗=a ;
r e t u r n (f l o a t ) 1 / p ;
}
e l s e
{
p = 1 ;f o r ( i = 1 ; i <=n ; i ++)
p ∗=a ;
r e t u r n p ;
}
} f l o a t Pow (i n ta ,i n t n )/ /Третья функция
{ i n t i , p ;
c o u t << "Функция 3 \ t ";
i f ( a ==0)
r e t u r n 0 ;
e l s e i f ( n==0)
r e t u r n 1 ;
e l s e i f ( n <0)
{
5 Как известно, операция an
не определена при a= 0 иn = 0 , а так же при возведении
отрицательного значения aв дробную степень n= k
m
, где
m чётное число (п. 2.7).Пусть
наши функции в этих случаях возвращают 0.
Программирование на языке С++ в среде Qt Creator

4.7. Шаблоны функций125
n=−n ;
p = 1 ;
f o r ( i = 1 ; i <=n ; i ++)
p ∗=a ;
r e t u r n (f l o a t ) 1 / p ;
} e l s e
{ p = 1 ;
f o r ( i = 1 ; i <=n ; i ++)
p ∗=a ;
r e t u r n p ;
}
}
i n t m a i n ( )
{
f l o a t a ;i n t k , n , m ;
c o u t << " a = "; c i n >>a ;
c o u t << " k = "; c i n >>k ;
c o u t << " s = "< c o u t << " s = "< c o u t << " a = "; c i n >>a ;
c o u t << " k = "; c i n >>k ;
c o u t << " m = "; c i n >>m ;
c o u t << " s = "< r e t u r n 0 ;
}
Результаты работы программы:
a=5.2
k=3
Функция 2 s=140.608
Функция 3 s=125
a=-8
k=1
m=1
Функция 1 s=-8
a=5.2
k=-3
Функция 2 s=0.00711197
Функция 3 s=0.008
a=-8
k=1
m=3
Функция 1 s=-2
4.7 Шаблоны функций Шаблон  это особый вид функции. С помощью шаблона функции можно
определить алгоритм, который будет применяться к данным ра зличных типов.
Механизм работы шаблона заключается в том, что на этапе компи ляции кон-
кретный тип данных передаётся в функцию в виде параметра.
Простейшую функцию–шаблон в общем виде можно записать так [6 ]:
t e m p l a t e заголовок
{ тело функции
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

126Глава 4. Использование функций при программировании на C++
Обычно в угловых скобках указывают список используемых в фун кции типов
данных. Каждый тип предваряется служебным словом class. В общем случае в
списке могут быть не только типы данных, но и имена переменны х.
Рассмотрим пример шаблона поиска наименьшего из четырёх чи сел.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
/ / Определяем абстрактный тип данных с помощью служебного слов аType .
t e m p l a t e
Type minimum ( Type a , Type b , Type c , Type d ) { / /Определяем функцию с использованием типа данных Type .
Type min=a ; i f ( b i f ( c i f ( d r e t u r n min ;
} i n t m a i n ( )
{ i n t i a , i b , i c , i d , m i n i ; f l o a tr a , r b , r c , r d , m i n r ;
c o u t << " V v o d 4 t h e l i h c h i s l a \ t " ;
c i n >>i a >>i b >>i c >>i d ;
m i n i=minimum ( i a , i b , i c , i d ) ; / /Вызов функции minimum ,в которую передаём
/ / 4 целых значения.
c o u t << " \ n "< c o u t << " V v o d 4 v e c s h e s t v e n i h c h i s l a \ t " ; c i n >>r a >>r b>>r c >>r d ;
m i n r=minimum ( r a , r b , r c , r d ) ; / /Вызов функции minimum ,в которую передаём
/ / 4 вещественных значения.
c o u t << " \ n "< r e t u r n 0 ;
}
4.8 Область видимости переменных в функциях Как известно (п. 2.8), по месту объявления переменные в язык еC++ делятся
на три класса: локальные, глобальные и переменные, описанн ые в списке фор-
мальных параметров функций. Все эти переменные имеют разную область ви-
димости.
Локальные переменные объявляются внутри функции и доступны только в
ней. О таких переменных говорят, что они имеют локальную види мость, то есть,
видимы только внутри функции.
Глобальные переменные описывают вне всех функций. Поскольку они доступ-
ны из любой точки программы, то их область видимости охватыва ет весь файл.
Одно и тоже имя может использоваться при определении глобал ьной и ло-
кальной переменной. В этом случае в теле функции локальная п еременная имеет
преимущество и закрывает собой глобальную. Вне этой функц ии работает
глобальное описание переменной.
Из функции, где действует локальное описание переменной, м ожно обратить-
ся к глобальной переменной с таким же именем, используя оператор расширения
области видимости
::переменная;
Рассмотрим пример:
#i n c l u d e < i o s t r e a m >
Программирование на языке С++ в среде Qt Creator

4.9. Функция main(). Параметры командной строки127
u s i n g namespaces t d ;
f l o a t p r = 1 0 0 . 6 7 8 ; / /Переменная p rопределена глобально.
i n t p r o s t o e ( i n tn )
{
i n t p r = 1 , i ; / /Переменная p rопределена локально.
i f ( n <0) p r = 0 ;
e l s e
f o r ( i = 2 ; i <=n / 2 ; i ++)
i f ( n% i ==0) { p r = 0 ; break; }
c o u t << " l o c a l p r = " <

c o u t << " g l o b a l p r = " < <:: p r<<" \ n ";/ /Вывод глобальной переменной.
r e t u r n p r ;
} i n t m a i n ( )
{ i n t g ;
c o u t << " g = "; c i n >>g ;
i f ( p r o s t o e ( g ) ) c o u t << " g - p r o s t o e \ n ";
e l s e c o u t << " g - n e p r o s t o e \ n " ;
r e t u r n 0 ;
}
Результаты работы программы:
g=7
local pr=1 //Локальная переменная.
global pr=100.678 //Глобальная переменная.
g - prostoe
4.9 Функция main(). Параметры командной строки
Итак, любая программа на C++состоит из одной или нескольких функций,
причём одна из них должна обязательно носить имя main(основной, главный).
Именно этой функции передаётся управление после запуска пр ограммы. Как
любая функция, mainможет принимать параметры и возвращать значения. У
функции mainдве формы записи:
• без параметров: тип m a i n ( ) { тело функции } ,
• и с двумя параметрами: тип m a i n ( i n ta r g c , c h a r∗a r g v [ ] ) { тело функции } .
Первый параметр argcопределяет количество параметров, передаваемых в
функцию mainиз командной строки. Второй параметр argv указатель на мас-
сив указателей типа char(массив строк). Каждый элемент массива ссылается
на отдельный параметр командной строки. При стандартном за пуске программы
argc равно 1, argv массив из одного элемента, этим элементом является имя
запускаемого файла. Рассмотрим следующую программу.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d l i b . h>
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗a r g v [ ] )
{ i n t i ;
c o u t << " В командной строке " < © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

128Глава 4. Использование функций при программировании на C++
f o r( i = 0 ; i
c o u t << " Аргумент № " < r e t u r n 0 ;
}
Текст программы хранится в файле 1.cpp. При стандартном запуске про-
грамма выведет следующую информацию:
В командной строке 1 аргументов
Аргумент № 0 ./1
Программа выводит количество параметров командной строки и последователь-
но все параметры. При стандартном запуске – количество аргу ментов командной
строки  1, этим параметром является имя запускаемого файла (в нашем случае,
имя запускаемого файла  ./1).
Запустим программу следующим образом:
./1 abc 34 6 + 90 Вася Маша
Результаты работы программы представлены ниже.
В командной строке 8 аргументов
Аргумент № 0 ./1
Аргумент № 1 abc
Аргумент № 2 34
Аргумент № 3 6
Аргумент № 4 +
Аргумент № 5 90
Аргумент № 6 Вася
Аргумент № 7 Маша
Рассмотрим приложение, в которое в качестве параметров ком андной строки
передаётся число1, операция, число2 . Функция выводит
число1 операция число2 .
Текст программы приведён на ниже 6
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d l i b . h>
#i n c l u d e < c s t r i n g >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
/ / Если количество параметров больше или равно 4, то были введе ны два числа и знак операции.
i f ( a r g c >=4)
/ / Если операция ∗, то выводим число1 ∗число2.
{ i f ( ! s t r c m p ( a r g v [ 2 ] , " * ") ) c o u t << a t o f ( a r g v [ 1 ] ) ∗a t o f ( a r g v [ 3 ] ) << e n d l ;
e l s e
/ / Если операция +, то выводим число1 +число2.
i f ( ! s t r c m p ( a r g v [ 2 ] , " + ") ) c o u t << a t o f ( a r g v [ 1 ] ) + a t o f ( a r g v [ 3 ] ) << e n d l ;
e l s e
/ / Если операция −, то выводим число1 −число2.
i f ( ! s t r c m p ( a r g v [ 2 ] , " - ") ) c o u t << a t o f ( a r g v [ 1 ] ) −a t o f ( a r g v [ 3 ] ) << e n d l ;
e l s e
/ / Если операция /, то выводим число1/число2.
i f( ! s t r c m p ( a r g v [ 2 ] , " / ") ) c o u t << a t o f ( a r g v [ 1 ] ) / a t o f ( a r g v [ 3 ] ) << e n d l ;
6
Функция atofпреобразовывает строку символов в вещественное число, а ес ли преобразо-
вание невозможно, то результатом функции atofбудет число 0.0. Функция strcmpсравнивает
две строки и возвращает 0 в случае совпадения строк. Подробн ее об этих функциях можно
прочесть в главе, посвящённой строкам.
Программирование на языке С++ в среде Qt Creator

4.10. Задачи для самостоятельного решения129
e l s ec o u t << " неправильный знак операции " << e n d l ;
}
e l s e c o u t << " недостаточное количество операндов " << e n d l ;
r e t u r n 0 ;
}
Ниже приведены варианты запуска программы и результаты её р аботы7
.
Предлагаем читателю самостоятельно разобраться с результ атами всех тестовых
запусков приложения.
./4 1.3 + 7.8
9.1
./4 1.3 - 7.8
-6.5
./4 1.3 / 7.8
0.166667
./4 1.3 \* 7.8
10.14
./4 1.3 % 7.8
неправильный знак операции
./4 1.3+ 7.8
недостаточное количество операндов
4.10 Задачи для самостоятельного решения
4.10.1 Применение функций при работе с последовательностями
чисел
Разработать программу на языке C++для следующих заданий:
1. Вводится последовательность целых положительных чисел , 0  конец по-
следовательности. Для каждого элемента последовательнос ти определить
и вывести на экран число, которое получится после записи циф р исходного
числа в обратном порядке.
2. Вводится последовательность целых чисел, 0  конец после довательности.
Определить, содержит ли последовательность хотя бы одно совершённое
число . Совершённое число равно сумме всех своих делителей, не пре восхо-
дящих это число. Например, 6 = 1 + 2 + 3или28 = 1 + 2 + 4 + 7 + 14 .
3. Вводится последовательность из Nцелых положительных элементов.
Определить, содержит ли последовательность хотя бы одно простое число.
Простое число не имеет делителей, кроме единицы и самого себ я.
4. Вводится последовательность из Nцелых положительных элементов. По-
считать количество чисел- палиндромов. Числа-палиндромы симметричны
относительно своей середины, например, 12021 или 454.
5. Вводится последовательность из Nцелых положительных элементов. Под-
считать количество совершённых и простых чисел в последова тельности.
6. Поступает последовательность целых положительных чисе л, 0  конец по-
следовательности. Определить, в каком из чисел больше всег о делителей.
7
Текст программы хранится в файле 4.cpp. Имя исполняемого файла ./4(ОС Lnux)
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

130Глава 4. Использование функций при программировании на C++
7. Поступает последовательность целых положительных чисе л, 0  конец по-
следовательности. Определить, в каком из чисел больше всег о цифр.
8. Вводится последовательность из Nцелых положительных элементов. Про-
верить, содержит ли последовательность хотя бы одну пару со седнихдру-
жественных чисел . Два различных натуральных числа являются друже-
ственными, если сумма всех делителей первого числа (кроме с амого числа)
равна второму числу. Например, 220 и 284, 1184 и 1210, 2620 и 2 924, 5020
и 5564.
9. Поступает последовательность целых положительных чисе л, 0  конец по-
следовательности. Каждый элемент последовательности пре дставляет со-
бой номер mодного из чисел Фибоначчи. Вычислить и вывести на экран
m -е число Фибоначчи . Напомним, что в последовательности Фибоначчи
каждое последующее число представляет собой сумму двух пред ыдущих
(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, . . . ). Например, четвёртое числ о Фибоначчи
равно 3, седьмое  13, а девятое  34.
10. Вводится последовательность из Nцелых положительных элементов. Най-
ти число с минимальным количеством цифр.
11. Вводится последовательность из Nцелых элементов. Для всех положи-
тельных элементов последовательности вычислить значение факториала.
Вывести на экран число и его факториал.
12. Поступает последовательность целых положительных чис ел, 0  конец по-
следовательности. Вывести на экран все числа последовател ьности, явля-
ющиеся составными и их делители. Составное число имеет более двух де-
лителей, то есть не является простым.
13. Вводится последовательность из Nцелых положительных элементов.
Определить, содержит ли последовательность хотя бы одно число Арм-
стронга . Число Армстронга  натуральное число, которое равно сумме
своих цифр, возведённых в степень, равную количеству его ци фр. Напри-
мер, десятичное число 153  число Армстронга, потому что: 13
+ 3 3
+ 5 3
=
1 + 27 + 125 = 153 .
14. Поступает последовательность целых положительных чис ел, 0  конец по-
следовательности. Найти среднее арифметическое простыхчисел в этой
последовательности. Простое число не имеет делителей, кро ме единицы и
самого себя.
15. Вводится последовательность из Nцелых положительных элементов.
Определить, сколько в последовательности пар соседних взаимно простых
чисел . Различные натуральные числа являются взаимно простыми, ес ли их
наибольший общий делитель равен единице.
16. В последовательности из Nцелых положительных элементов найти сумму
всех недостаточных чисел . Недостаточное число всегда больше суммы всех
своих делителей за исключением самого числа.
17. Вводится последовательность из Nцелых положительных элементов. По-
считать количество элементов последовательности, имеющих в своём пред-
ставлении цифру 0.
Программирование на языке С++ в среде Qt Creator

4.10. Задачи для самостоятельного решения131
18. ВводитсяNпар целых положительных чисел aи b. В случае, если a > b
вычислить: C= a
!
b!· ( a − b)! .
19. Вводится последовательность из Nцелых элементов. Для каждого элемен-
та последовательности найти среднее значение его цифр.
20. Вводится последовательность целых положительных чисе л, 0  конец по-
следовательности. Для каждого элемента последовательнос ти определить и
вывести на экран число, которое получится, если поменять ме стами первую
и последнюю цифры исходного числа.
21. Вводится последовательность из Nцелых элементов. Для каждого элемен-
та последовательности вывести на экран количество цифр и ко личество
делителей.
22. Вводится последовательность из Nцелых положительных элементов. Сре-
ди элементов последовательности найти наибольшее число- палиндром.
Числа-палиндромы симметричны относительно своей середин ы, например,
12021 или 454.
23. Поступает последовательность целых положительных чис ел, 0  конец по-
следовательности. Для каждого элемента последовательнос ти вывести на
экран сумму квадратов его цифр.
24. Вводится последовательность из Nцелых положительных элементов. Для
простых элементов последовательности определить сумму цифр. Прос тое
число не имеет делителей, кроме единицы и самого себя.
25. Вводится последовательность целых положительных чисе л, 0  конец по-
следовательности. Среди элементов последовательности на йти наименьшее
составное число . Составное число имеет более двух делителей, то есть не
является простым.
4.10.2 Применение функций для вычислений в различных системах счисления
Разработать программу на языке C++для решения следующей задачи. За-
даны два числа  AиB, первое в системе счисления с основанием p, второе в
системе счисления с основанием q. Вычислить значение Cпо указанной формуле
и вывести его на экран в десятичной системе счисления и систе ме счисления с
основанием r. Исходные данные для решения задачи представлены в табл. 4. 1.
Таблица 4.1: Задания для решения задачи о различных систе-
мах счисления
Вариант p q C r
1 2 8 A 2
·(A + B) 3
2 3 7 2·(A 2
+ B2
) 4
3 4 6 2 ·B 2
·(A + B) 5
4 5 2 (A − B)2
+ 3 ·A 6
5 6 4 A 2
+ A·B 7
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

132Глава 4. Использование функций при программировании на C++
Таблица 4.1  продолжение
Вариант p q C r
6 7 3 (5·B −2·A )2 8
7 8 2 (2
·A − 3·B )2 5
8 3 8 (
B −A)2
+ 2 ·A 6
9 4 7 B 3
− B2
+ 2 ·A 2
10 5 6 A 3
− A2
+ 3 ·B 8
11 6 5 (2 ·A − 3·B )2 3
12 7 4 A
2
+ 2 ·A + B2 5
13 8 3 A2
+ 3 ·B +B2 7
14 4 2 A2
− 2·A + B 6
15 5 8 3·B 2
− 2·B +A 3
16 6 7 A2
+ ( B−A)2 2
17 7 6 3
·B 2
+ 2 ·A ·B 8
18 8 5 2 ·A 2
+ 3 ·A ·B 7
19 2 4 B 3
− 2·B +A 3
20 3 8 A3
− 2·A + B 4
21 4 7 (5 ·A − 2·B )2 5
22 5 6 (
B 2
− 3·A )2 7
23 6 5 (
A 2
− 2·B )2 8
24 7 4 A 2
·B 2
− A·B 6
25 8 3 A ·B +A2
− B 2
4.10.3 Применение функций для решения нелинейных уравнений
Разработать программу на языке C++для вычисления одного из корней урав-
нения f(x ) = 0 методами, указанными в задании. Для решения задачи предвар и-
тельно определить интервал изоляции корня графическим мет одом. Вычисления
проводить с точностью = 10 −
4
. Оценить степень точности путём подсчёта ко-
личества итераций, выполненных для достижения заданной то чности. Исходные
данные для решения задачи представлены в табл. 4.2.
Таблица 4.2: Задания к задаче о решении нелинейных уравнений
№ Уравнение f(x ) = 0 Методы решения
1 x 0.2 ·sin( x+ 0 .5) = 0 метод половинного деления, метод хорд
2 x 2
lg( x+ 2) = 0 метод касательных, метод простой итерации
3 x2
20 ·sin( x) = 0 метод хорд, метод касательных
4 ln( x) + ( x+ 1) 3
= 0 метод дихотомии, метод простой итерации
5 x2
sin(5 x) = 0 метод половинного деления, метод касательных
6 ex
+ x2
2 = 0 метод хорд, метод простой итерации.
7 0.8 ·x 2
sin(10 ·x ) = 0 метод половинного деления, метод хорд
8 sin(7 ·x ) + 2 ·x 6 = 0 метод касательных, метод простой итерации
Программирование на языке С++ в среде Qt Creator

4.10. Задачи для самостоятельного решения133
Таблица 4.2  продолжение
№ Уравнениеf(x ) = 0 Методы решения
9 x ·ln( x) 1 = 0 метод хорд, метод касательных
10 2·lg( x) + 0 .5 ·x = 0 метод дихотомии, метод простой итерации
11 e
x
x2
= 0 метод половинного деления, метод касательных
12 x2
3·cos( x2
) = 0 метод хорд, метод простой итерации
13 sin(7 ·x ) x2
+ 15 = 0 метод половинного деления, метод хорд
14 (x 1)2
0.5 ·ex
= 0 метод касательных, метод простой итерации
15 2·ln( x) 0.2 ·x + 1 = 0 метод хорд, метод касательных
16 2 x·ex
= 0 метод дихотомии, метод простой итерации
17 0.1 ·x 3
+ 3 ·x 2
10 ·x 7 = 0 метод половинного деления, метод касательных
18 0.1 ·x 2
ex
= 0 метод хорд, метод простой итерации
19 e
2·x
2·x + 1 = 0 метод половинного деления, метод хорд
20 x2
3 + 0 .5 x
= 0 метод касательных, метод простой итерации
21 lg(4 ·x ) cos( x) = 0 метод хорд, метод касательных
22 ln( x) cos 2
(x ) = 0 метод дихотомии, метод простой итерации
23 4x
0.2 ·ex
= 0 метод половинного деления, метод касательных
24 x + 6 .5 ex
= 0 метод хорд, метод простой итерации.
25 0.5 x
+ 1 (x 2)2
= 0 метод половинного деления, метод хорд
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

Глава 5
МассивыЭта глава является ключевой в изучении программирования на С(С++). В ней
описаны методы построения алгоритмов и программ с использо ванием статиче-
ских и динамических массивов. В заключительном параграфе гл авы на большом
количестве примеров рассматривается совместное использо вание указателей, ди-
намических массивов и функций пользователя при решении сло жных задач об-
работки массивов.
5.1 Статические массивы в С(С++)
Часто для работы с множеством однотипных данных (целочисле нными зна-
чениями, строками, датами и т.п.) оказывается удобным испо льзовать массивы.
Например, можно создать массив для хранения фамилий студен тов, обучающих-
ся в одной группе. Вместо создания переменных для каждого ст удента, например
Студент1 ,Студент2 и т.д., достаточно создать один массив, где каждой фами-
лии из списка будет присвоен порядковый номер. Таким образо м, можно дать
следующее определение. Массив  структурированный тип данн ых, состоящий
из фиксированного числа элементов одного типа.
Массив в табл. 5.1 имеет 8 элементов, каждый элемент сохраня ет число веще-
ственного типа. Элементы в массиве пронумерованы (нумерац ия массивов начи-
нается с нуля). Такого рода массив, представляющий собой про сто набор данных
одного и того же типа, называют простым или одномерным массив ом. Для досту-
па к данным, хранящимся в определённом элементе массива, не обходимо указать
имя массива и порядковый номер этого элемента, называемый и ндексом.
Таблица 5.1: Одномерный числовой массив
№ элемента
массива 0 1 2 3 4 5 6 7
Значение 13.65 -0.95 16.78 8.09 -11.76 9.07 5.13 -25.64

5.1. Статические массивы вС(С++) 135
Если возникает необходимость хранения данных в виде матриц , в формате
строк и столбцов, то необходимо использовать двумерные мас сивы. В табл. 5.2
приведён пример массива, состоящего из четырёх строк и пяти столбцов. Это
двумерный массив. Строки в нём можно считать первым измерен ием, а столбцы
вторым. Для доступа к данным, хранящимся в этом массиве, нео бходимо указать
имя массива и два индекса, первый должен соответствовать но меру строки, а
второй номеру столбца, где хранится необходимый элемент.
Таблица 5.2: Двумерный числовой массив
1.5 -0.9 1.8 7.09 -1.76
3.6 0.5 6.7 0.09 -1.33
13.65 -0.95 16.78 8.09 -11.76
7.5 0.95 7.3 8.9 0.11
Если при описании массива определён его размер, то массив на зывают ста-
тическим. Рассмотрим работу с одномерными статическими ма ссивами в языке
С(С++) . Двумерные массивы подробно описаны в следующей главе.
5.1.1 Описание статических массивов Описать статический массив в С(С++)можно так:
тип имя_переменной [размерность];
размерность  количество элементов в массиве. Например:
i n t x [ 1 0 ] ; / /Описание массива из 10 целых чисел. Первый
/ / элемент массива имеет индекс 0, последний 9.
f l o a t a [ 2 0 ] ; / /Описание массива из 20 вещественных чисел.
/ / Первый элемент массива имеет индекс 0, последний 19.
Размерность массива и тип его элементов определяют объём пам яти, кото-
рый необходим для хранения массива. Рассмотрим ещё один при мер описания
массива: c o n s t i n t n = 1 5 ;/ /Определена целая положительная константа.
double B [ n ] ; / /Описан массив из 15 вещественных чисел.
При описании статического массива в качестве размерности м ожно исполь-
зовать целое положительное число или предопределённую кон станту.
Элементы массива в С(С++)нумеруются с нуля. Первый элемент всегда имеет
номер ноль, а номер последнего элемента на единицу меньше за данной при его
описании размерности: c h a r C [ 5 ] ; / /Описан массив из 5 символов, нумерация от 0 до 4.
5.1.2 Основные операции над массивами Доступ к каждому элементу массива осуществляется с помощью индекса 
порядкового номера элемента. Для обращения к элементу масс ива указывают
его имя, а затем в квадратных скобках индекс:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

136Глава 5. Массивы
имя_массива [индекс]
Например:
c o n s t i n t n = 1 5 ;
double C [ n ] , S ;
S=C [ 0 ] + C [ n −1 ] ; / /Сумма первого и последнего элементов массива С.
Массиву, как и любой другой переменной, можно присвоить нача льное зна-
чение (инициализировать). Для этого значения элементов ма ссива нужно пере-
числить в фигурных скобках через запятую:
тип имя_переменной[размерность]={элемент_0, элемент_1 , ...};
Например:
f l o a t a [ 6 ] = { 1 . 2 , ( f l o a t) 3 / 4 , 5 . / 6 , 6 . 1 } ;
/ / Формируется массив из шести вещественных чисел, значения эл ементам присваиваются по
/ / порядку. Элементы, значения которых не указаны (в данном случ ае a[4], a[5]), обнуляются:
/ / a[0]=1.2, a[1]=(float)3/4, a[2]=5./6, a[3]=6.1, a[4]=0, a [5]=0,
/ / для элементов a[1] и a[2] выполняется преобразование типов .
Рассмотрим, как хранится массив в памяти компьютера. Предпо ложим, была
описана переменная:
double x[30];
это значит, что в памяти компьютера выделяется место для хран ения 30 эле-
ментов типа double. При этом адрес выделенного участка памяти хранится в
переменной x. Таким образом, к значению нулевого элемента массива можно об-
ратится двумя способами:
1. В соответствии с синтаксисом языка С(С++)записать x[0].
2. Применить операцию *x, так как адрес начала массива хранится в пере-
менной x(по существу x указатель на double).
Если к значению xдобавить единицу (число 1), то мы сместимся на один эле-
мент типа double. Таким образом, x+1 адрес элемента массива xс индексом 1.
К первому элементу массива xтакже можно обратиться двумя способами: x[1]
или *(x+1) . Аналогично, к элементу с индексом 2 можно обращаться либо x[2],
либо *(x+2) . Таким образом, получается, что к элементу с индексом iможно
обращаться x[i]или*(x+i) .
При обработке массива (независимо от способа обращения x[i]или*(x+i) )
программист сам должен контролировать, существует ли элем ент массиваx[i]
(или *(x+i) ) и не вышла ли программа за границы массива.
Особенностью статических массивов является определение р азмера при на-
писании текста программы. При необходимости увеличить раз мер массива, необ-
ходимо изменить текст программы и перекомпилировать её. Пр и динамическом
выделении памяти для массивов в С(С++)можно использовать указатели и опе-
раторы (функции) выделения памяти.
5.2 Динамические массивы в С(С++)
Для создания динамического массива необходимо [1, 8]:
• описать указатель ( тип * указатель;);
Программирование на языке С++ в среде Qt Creator

5.2. Динамические массивы в С(С++)137
• определить размер массива;
• выделить участок памяти для хранения массива и присвоить указателю
адрес этого участка памяти.
Для выделения памяти в С++можно воспользоваться оператором newили функ-
циями языка С calloc ,malloc ,realloc . Все функции находятся в библиотеке
stdlib.h .
5.2.1 Функция malloc Функция mallocвыделяет непрерывный участок памяти размером sizeбайт
и возвращает указатель на первый байт этого участка. Обраще ние к функции
имеет вид: v o i d ∗m a l l o c ( s i z e _ t s i z e ) ;
где size  целое беззнаковое значение 1
, определяющее размер выделяемого
участка памяти в байтах. Если резервирование памяти прошло успешно, то функ-
ция возвращает переменную типа void*, которую можно преобразовать к любо-
му необходимому типу указателя. Если выделить память невоз можно, то функ-
ция вернёт пустой указатель NULL.
Например,
double ∗h ; / /Описываем указатель на double.
i n t k ;
c i n >>k ; / /Ввод целого числа k.
/ / Выделение участка памяти для хранения kэлементов типа double.
/ / Адрес этого участка хранится в переменной h.
h=( double ∗) m a l l o c ( k ∗s i z e o f (double ) ) ;/ /h адрес начала участка памяти,
/ / h+ 1 , h+ 2 , h+ 3 и т. д.  адреса последующих элементов типа double.
5.2.2 Функция calloc Функция callocпредназначена для выделения и обнуления памяти.
v o i d ∗c a l l o c ( s i z e _ t num , s i z e _ t s i z e ) ;
С помощью функции будет выделен участок памяти, в котором бу дет хра-
ниться numэлементов по sizeбайт каждый. Все элементы выделенного участка
обнуляются. Функция возвращает указатель на выделенный уча сток илиNULL
при невозможности выделить память. Например,
f l o a t ∗h ; / /Описываем указатель на float.
i n t k ;
c i n >>k ; / /Ввод целого числа k.
/ / Выделение участка памяти для хранения kэлементов типа float.
/ / Адрес этого участка хранится в переменной h .
h=( f l o a t ∗) c a l l o c ( k , s i z e o f(f l o a t ) ) ;/ / h  адрес начала участка памяти,
/ / h+ 1 , h+ 2 , h+ 3 и т. д.  адреса последующих элементов типа float.
1
size_t  базовый беззнаковый целочисленный тип языка С/С++, который выбирается та-
ким образом, чтобы в него можно было записать максимальный р азмер теоретически возмож-
ного массива любого типа. В 32-битной операционной системе size_tявляется беззнаковым
32-битным числом (максимальное значение 232
−1), в 64-битной  64-битным беззнаковым
числом (максимальное значение 264
−1).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

138Глава 5. Массивы
5.2.3 Функция realloc
Функция realloc изменяет размер ранее выделенного участка памяти. Обра-
щаются к функции так: c h a r ∗r e a l l o c ( v o i d∗p , s i z e _ t s i z e ) ;
где p указатель на область памяти, размер которой нужно изменит ь наsize.
Если в результате работы функции меняется адрес области пам яти, то новый
адрес вернётся в качестве результата. Если фактическое зна чение первого пара-
метра NULL, то функция reallocработает так же, как и функция malloc, то есть
выделяет участок памяти размером sizeбайт.
5.2.4 Функция free Для освобождения выделенной памяти используется функция free. Обраща-
ются к ней так: v o i d f r e e (v o i d ∗p ) ;
где p указатель на участок памяти, ранее выделенный функциями malloc,
calloc илиrealloc .
5.2.5 Операторы new и delete В языке С++есть операторы newдля выделения и freeдля освобождения
участка памяти.
Для выделения памяти для хранения nэлементов одного типа оператор new
имеет вид [5]:
x= new t y p e [ n ] ;
type  тип элементов, для которых выделяется участок памяти;
n  количество элементов;
x  указатель на тип данных type, в котором будет храниться адрес выде-
ленного участка памяти.
При выделении памяти для одного элемента оператор newимеет вид:
x= new t y p e ;
Например, f l o a t ∗x ; / /Указатель на тип данных f l o a t .
i n t n ;
c i n >>n ; / /Ввод n
/ / Выделение участка памяти для хранения nэлементов типа float. Адрес этого участка хранится
/ / в переменной x; x+1, x+2, x+3 и т. д.  адреса последующих элементов типа float.
Освобождение выделенного с помощью newучастка памяти осуществляется с
помощью оператора deleteследующей структуры:
d e l e t e [ ] p ;
p  указатель (адрес участка памяти, ранее выделенного с помо щью оператора
new ).
Программирование на языке С++ в среде Qt Creator

5.3. Отличие статического и динамического массива139
5.3 Отличие статического и динамического массива
В чём же отличие статического и динамического массива?
Предположим, описан статический массив: doublex[75];
Это означает, что выделен участок памяти для хранения 75 эле ментов типа
double (массив из 75 элементов типа double). Адрес начала массива хранится в
переменной x. Для обращения к i-му элементу можно использовать конструкции
x[i] или*(x+i) . Если понадобится обрабатывать массив более, чем из 75 эле-
ментов, то придётся изменить описание и перекомпилировать программу. При
работе с массивами небольшой размерности, большая часть па мяти, выделенной
под статический массив, будет использоваться вхолостую.
Допустим, задан динамический массив, например
double ∗x ; / /Указатель на d o u b l e
i n t k ;
c i n >>k ; / /Вводим размер массива k.
/ / Выделение памяти для хранения динамического массива из kчисел.
x= new double [ k ] ;/ /Адрес начала массива хранится в переменной x.
x =( double ∗) c a l l o c ( k , s i z e o f(f l o a t ) ) ;/ /Память можно будет выделить так
x =( double ∗) m a l l o c ( k ∗s i z e o f (f l o a t ) ) ;/ /или так
В этом случае, мы имеем указатель на тип данных double, вводим k размер
динамического массива, выделяем участок памяти для хранен ияkэлементов ти-
па double (массив из kэлементов типа double). Адрес начала массива хранится
в переменной x. Для обращения к i-му элементу можно использовать конструк-
ции x[i] или*(x+i) . В случае динамического массива мы сначала определяем
его размер (в простейшем случае просто вводим размер массив а с клавиату-
ры), а потом выделяем память для хранения реального количес тва элементов.
Основное отличие статического и динамического массивов со стоит в том, что в
динамическом массиве выделяется столько элементов, сколь ко необходимо.
Имя массива (статического или динамического) это адрес нач ала выделенного
для него участка памяти, значит обращаться к элементам масс ива можно двумя
способами  x[i]или*(x+i) .
5.4 Основные алгоритмы обработки массивов Все манипуляции с массивами в С++осуществляются поэлементно. Организо-
вывается цикл, в котором происходит последовательное обра щение к нулевому,
первому, второму и т.д. элементам массива. В общем виде алго ритм обработки
массива выглядит так, как показано на рис. 5.1.
Алгоритмы, с помощью которых обрабатывают одномерные массив ы, похо-
жи на обработку последовательностей (вычисление суммы, пр оизведения, поиск
элементов по определённому признаку, выборки и т. д.). Отли чие заключается в
том, что в массиве одновременно доступны все его компоненты , поэтому стано-
вится возможной, например, сортировка его элементов и друг ие, более сложные
преобразования.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

140Глава 5. Массивы
Рис. 5.1: Алгоритм обработки элементов массива
5.4.1 Ввод-вывод элементов массива Ввод и вывод массивов также осуществляется поэлементно. Бл ок-схемы ал-
горитмов ввода и вывода элементов массива X[N]изображены на рис. 5.2–5.3.
Рассмотрим несколько вариантов ввода массива:
/ / Вариант 1. Ввод массива с помощью функции scanf.
/ / При организации ввода используются специальные символы: та буляция  \t
/ / и переход на новую строку  \n.
#i n c l u d e < s t d i o . h>
i n t m a i n ( )
{ f l o a t x [ 1 0 ] ; i n ti , n ;
p r i n t f ( " \ n N = " ) ; s c a n f ( " % d ",& n ) ; / /Ввод размерности массива.
p r i n t f ( " \ n Введите элементы массива X \ n " ) ;
f o r ( i = 0 ; i s c a n f ( " % f ", x+ i ) ; / /Ввод элементов массива в цикле.
/ / Обратите внимание, x+ i адрес i-го элемента массива.
r e t u r n 0 ;
}
Рис. 5.2: Алгоритм ввода массива X[N]
Результат работы программы:
N=3
Введите элементы массива X
1.2
-3.8
0.49
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов141
Рис. 5.3: Алгоритм вывода массиваX[N]
/ / Вариант 2. Ввод массива с помощью функции scanfи вспомогательной переменной b.
#i n c l u d e < s t d i o . h>
i n t m a i n ( )
{ f l o a t x [ 1 0 ] , b ; i n ti , n ;
p r i n t f ( " \ n N = " ) ; s c a n f ( " % d ",& n ) ; / /Ввод размерности массива.
p r i n t f ( " \ nМассив X \ n ") ;
f o r ( i = 0 ; i { p r i n t f ( " \ nЭлемент % d \ t ", i ) ;/ /Сообщение о вводе элемента.
s c a n f ( " % f ",& b ) ; / /Ввод переменной b.
x [ i ] = b ; / /Присваивание элементу массива значения переменной b.
} r e t u r n 0 ;
}
Результат работы программы:
N=4
Массив X
Элемент 0 8.7
Элемент 1 0.74
Элемент 2 -9
Элемент 3 78
/ / Вариант 3. Ввод динамического массива с помощью cin.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t ∗X , N , i ;
c o u t << " \ n N = " ; c i n >>N ; / /Ввод размерности массива.
X= new i n t [ N ] ;/ /Выделение памяти для динамического массива из Nэлементов.
f o r ( i = 0 ; i { c o u t << " \ n X [ " < c i n >>X [ i ] ; / /Ввод элементов массива в цикле.
}
d e l e t e [ ] X ;
r e t u r n 0 ;
}
Результат работы программы:
N=4
X[0]=1
X[1]=2
X[2]=4
X[3]=5
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

142Глава 5. Массивы
Вывод статического или динамического массива можно осуществить несколь-
кими способами: / / Вариант 1. Вывод массива в виде строки.
f o r ( i = 0 ; i / / Вариант 2. Вывод массива в виде столбца.
f o r ( i = 0 ; i / / Вариант 3. Вывод массива в виде строки.
f o r ( i = 0 ; i / / Вариант 4. Вывод массива в виде столбца.
f o r ( i = 0 ; i 5.4.2 Вычисление суммы элементов массива Дан массив X, состоящий из Nэлементов. Найти сумму элементов этого
массива. Процесс накапливания суммы элементов массива дос таточно прост и
практически ничем не отличается от суммирования значений н екоторой числовой
последовательности. Переменной Sприсваивается значение, равное нулю, затем
к переменной Sпоследовательно добавляются элементы массива X. Блок-схема
алгоритма расчёта суммы приведена на рис. 5.4.
Рис. 5.4: Алгоритм вычисления суммы элементов массива
Соответствующий алгоритму фрагмент программы будет иметь в ид:
f o r ( S= i = 0 ; i S+=X [ i ] ;
c o u t << " S = "< 5.4.3 Вычисление произведения элементов массива Дан массив X, состоящий из Nэлементов. Найти произведение элементов
этого массива. Решение этой задачи сводится к тому, что знач ение переменнойP,
в которую предварительно была записана единица, последова тельно умножается
на значение i–го элемента массива. Блок-схема алгоритма приведена на ри с. 5.5.
Соответствующий фрагмент программы будет иметь вид:
f o r ( P= 1 , i = 0 ; i P ∗=X [ i ] ;
c o u t << " P = "< Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов143
Задача 5.1.Задан массив целых чисел. Найти сумму простых чисел и произв е-
дение отрицательных элементов массива. Алгоритм решения задачи состоит из следующих этапов.
1. Вводим массив X[N ].
2. Для вычисления суммы в переменную Sзаписываем значение 0, для вы-
числения произведения в переменную Pзаписываем 1.
3. В цикле ( iизменяется от 0 до N-1 с шагом 1) перебираем все элементы
массива X, если очередной элемент массива является простым числом, д о-
бавляем его к сумме, а если очередной элемент массива отрица телен, то
умножаем его на P.
4. Выводим на экран значение суммы и произведения.
Рис. 5.5: Вычисление произведения элементов массива
Блок-схема решения задачи представлена на рис. 5.6. Для реш ения задачи
применим функцию ( prostoe) проверки, является ли число простым. Текст про-
граммы с подробными комментариями приведён далее.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
/ / Текст функции prostoe.
b o o l p r o s t o e ( i n tN)
{
i n t i ;
b o o l p r ;
i f ( N<2) p r= f a l s e;
e l s e
f o r ( p r= t r u e , i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0)
{
p r=f a l s e ;
break ;
}
r e t u r n p r ;
} i n t m a i n ( )
{
i n t ∗X , i , N , S , P ;
c o u t << " Введите размер массива " ; c i n >>N ;/ /Ввод размерности массива.
X= new i n t [ N ] ;/ /Выделение памяти для хранения динамического массива X.
c o u t << " Ведите массив X \ n " ;/ / Ввод массива X.
f o r ( i = 0 ; i © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

144Глава 5. Массивы
{ c o u t <<" X ( "<>X [ i ] ; }
f o r ( P= 1 , S= i = 0 ; i { / /Если очередной элемент массива  простое число, добавляем е го к сумме.
i f ( p r o s t o e (X [ i ] ) ) S+=X [ i ] ;
/ / Если очередной элемент массива отрицателен, умножаем его на P.
i f (X [ i ] < 0 ) P ∗=X [ i ] ;
} c o u t << " S = "< d e l e t e [ ] X ;/ /Освобождение занимаемой массивом X памяти.
r e t u r n 0 ;
}
Рис. 5.6: Блок-схема алгоритма решения задачи 5.1
Результаты работы программы представлены ниже.
Введите размер массива 10
Ведите массив Х
X(0)=-7
X(1)=-9
X(2)=5
X(3)=7
X(4)=2
X(5)=4
X(6)=6
X(7)=8
X(8)=10
X(9)=12
S=14 P=63
Задача 5.2. Дан массивA, состоящий из kцелых положительных чисел. Запи-
сать все чётные по значению элементы массива Aв массив B.
На рис. 5.7 представлен фрагмент алгоритма решения данной з адачи. Здесь
индексы массива Aхранятся в переменной i, а для номеров массива Bзарезерви-
рована переменная m. Операция, выполняемая в блоке 1, означает, что в массиве
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов145
Aможет не быть искомых элементов. Далее организован цикл (бл ок 2), с помо-
щью которого можно обращаться к элементам массива A. Если условие в блоке
3 выполняется, то переменная mувеличивается на единицу, а значение соответ-
ствующего элемента массива Aзаписывается в массив В под номером m(блок
4). Условный блок 5 необходим для того, чтобы проверить, вып олнилось ли хотя
бы раз условие поиска (блок 2). Если массив Bсформирован, то он выводится
на экран (блоки 6, 7), в противном случае выдаётся соответст вующее сообщение
(блок 8).
Рис. 5.7: Алгоритм решения задачи 5.2
Приведённый ниже фрагмент программы реализует описанный а лгоритм:
f o r (m=−1, i = 0 ; i { i f (A [ i ]%2==0) / /Если элемент чётный, то
{
m++; / /увеличить значение индекса массива В
B [ m] =A [ i ] ; / /и записать элемент в массив В.
}
}
i f (m> −1) / /Если чётные элементы найдены, то распечатать сформированн ый массив.
f o r ( i = 0 ; i <=m ; c o u t < e l s e / /иначе, выдать сообщение,
c o u t << " Массив Bне сформирован! " << e n d l ;
5.4.4 Поиск максимального элемента в массиве и его номера Дан массив X, состоящий из nэлементов. Найти максимальный элемент мас-
сива и номер, под которым он хранится в массиве.
Алгоритм решения задачи следующий. Пусть в переменной с имене мMax хра-
нится значение максимального элемента массива, а в перемен ной с именемNmax–
его номер. Предположим, что нулевой элемент массива являет ся максимальным,
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

146Глава 5. Массивы
и запишем его в переменнуюMax, а в Nmax его номер (то есть ноль). Затем
все элементы, начиная с первого, сравниваем в цикле с максим альным. Если те-
кущий элемент массива оказывается больше максимального, т о записываем его
в переменную Max, а в переменную Nmax– текущее значение индекса i. Процесс
определения максимального элемента в массиве приведён в та блице 5.3 и изобра-
жён при помощи блок-схемы на рис. 5.8. Соответствующий фрагм ент программы
имеет вид: f o r ( Max=X [ 0 ] , Nmax= i = 0 ; i i f ( Max { Max=X [ i ] ;
Nmax= i ;
}
c o u t << " M a x = "< c o u t << " N m a x = " < Таблица 5.3: Определение максимального элемента и его номера в
массиве
Номера элементов 0 1 2 3 4 5
Исходный массив 4 7 3 8 9 2
Значение переменной M ax 4 7 7 8 9 9
Значение переменнойN max 1 2 2 4 5 5
Рис. 5.8: Поиск максимального элемента и его номера в массив е
При поиске максимального элемента и его номера, можно найти только номер
максимального элемента, а потом по номеру извлечь значение максимального
элемента из массива.
Текст программы поиска номера максимального элемента:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов147
{
f l o a t ∗X ;
i n t i , N , nom ;
c o u t << "Введите размер массива "; c i n >>N ; / /Ввод размерности динамического массива
X= new f l o a t [ N ] ;/ /Выделение памяти для хранения динамического массива X.
c o u t << " Введите элементы массива X \ n " ;/ / Ввод динамического массива X.
f o r ( i = 0 ; i c i n >>X [ i ] ;
/ / В переменной nomбудем хранить номер максимального элемента.
nom= 0 ; / /Предположим, что максимальным элементом является элемент с номером 0.
f o r ( i = 1 ; i / / Если очередной элемент больше X[nom], значит nom не является номером максимального
/ / элемента, элемент с номером iбольше элемента X[nom], поэтому переписываем
/ / число i в переменную nom.
i f (X [ i ] >X [ nom ] ) nom= i ;
c o u t << " Максимальный элемент = " < r e t u r n 0 ;
}
Совет. Алгоритм поиска минимального элемента в массиве будет отлич ать-
ся от приведённого выше лишь тем, что в условном блоке и, соот ветственно, в
конструкции ifтекста программы знак поменяется с < на >.
Рассмотрим несколько задач.
Задача 5.3. Найти минимальное простое число в целочисленном массиве x[ N].
Эта задача относится к классу задач поиска минимума (максим ума) сре-
ди элементов, удовлетворяющих условию. Подобные задачи расс матривались в
задачах на обработку последовательности чисел. Здесь пост упим аналогично.
Блок-схема приведена на рис. 5.9.
Необходимо первое простое число объявить минимумом, а все п оследующие
простые элементы массива сравнивать с минимумом. Будем в ци кле последо-
вательно проверять, является ли элемент массива простым чи слом (функция
prostoe ). ЕслиX[i]является простым числом, то количество простых чисел ( k)
увеличиваем на 1 ( k++), далее, проверяем, если kравен 1 ( if (k==1) ), то этот
элемент объявляем минимальным ( min=x[i]; nom=i;), иначе сравниваем его с
минимальным ( if (x[i] Текст программы:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
b o o l p r o s t o e ( i n tN)
{ i n t i ;b o o l p r ;
i f ( N<2) p r= f a l s e;
e l s e
f o r ( p r= t r u e , i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0)
{
p r= f a l s e ;
break ;
}
r e t u r n p r ;
} i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t i , k , n , nom , min , ∗x ;
c o u t << " n = "; c i n >>n ; / /Ввод количества элементов в массиве.
x= new i n t [ n ] ;/ /Выделяем память для динамического массива x.
c o u t << " Введите элементы массива X " ;/ / Ввод элементов массива.
f o r ( i = 0 ; i © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

148Глава 5. Массивы
c i n >>x [ i ] ;
/ / С помощью цикла по переменной i, перебираем все элементы в массиве x,
/ / k количество простых чисел в массиве.
f o r ( i =k = 0 ; i / / Проверяем, является ли очередной элемент массива простым ч ислом.
i f ( p r o s t o e ( x [ i ] ) ) / /Если x[i] простое число.
{
k++; / /Увеличиваем счётчик количества простых чисел в массиве.
/ / Если текущий элемент является первым простым числом в массив е,
/ / объявляем его минимумом, а его номер сохраняем в перемнной nom.
i f ( k==1) { min=x [ i ] ; nom= i ; }
e l s e
/ / Все последующие простые числа в массиве сравниваем с минимал ьным простым числом.
/ / Если текущее число меньше min, перезаписываем его в переменную min,
/ / а его номер  в переменную nom.
i f ( x [ i ] < min ) { min=x [ i ] ; nom= i ; }
}
/ / Если в массиве были простые числа, выводим значение и номер м инимального простого числа.
i f ( k >0)
c o u t << " m i n = "< / / Иначе выводим сообщение о том, что в массиве нет простых чисе л.
e l s e c o u t << " Нет простых чисел в массиве " << e n d l ;
r e t u r n 0 ;
}
Рис. 5.9: Блок-схема решения задачи 5.3
Аналогичным образом можно написать программу любой задачи по иска ми-
нимума (максимума) среди элементов, удовлетворяющих каком у-либо условию
(минимум среди положительных элементов, среди чётных и т.д .).
Задача 5.4. Найтиkминимальных чисел в вещественном массиве.
Перед решением этой довольно сложной задачи рассмотрим бол ее простую
задачу.
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов149
Найти два наименьших элемента в массиве. Фактически надо найти номера
( nmin1 ,nmin2 ) двух наименьших элементов массива. На первом этапе надо на йти
номер минимального ( nmin1) элемента массива. На втором этапе надо искать но-
мер минимального элемента, при условии, что он не равен nmin1. Вторая часть
очень похожа на предыдущую задачу (минимум среди элементов , удовлетворя-
ющих условию, в этом случае условие имеет вид i!=nmin1).
Решение задачи с комментариями:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t k v o , i , n , nmin1 , n m i n 2 ;
double ∗X ;
c o u t << " n = "; c i n >>n ;
X= new double [ n ] ;
c o u t << "Введите элементы массива X \ n ";
f o r ( i = 0 ; i c i n >>X [ i ] ;
/ / Стандартный алгоритм поиска номера первого минимального э лемента (nmin1).
f o r ( n m i n 1 = 0 , i = 1 ; i i f (X [ i ] / / Второй этап  поиск номера минимального элемента среди элем ентов, номер
/ / которых не совпадает nmin1.kvo  количество таких элементов.
f o r ( k v o= i = 0 ; i i f ( i ! = n m i n 1 ) / /Если номер текущего элемента не совпадает с nmin1 ,
{
k v o ++; / /увеличиваем количество таких элементов на 1.
/ / Номер первого элемента, индекс которого не равен nmin1,
/ / объявляем номером второго минимального элемента.
i f ( k v o ==1) n m i n 2= i ;
e l s e
/ / очередной элемент, индекс которого не равен nmin1, сравниваем с минимальным,
/ / если он меньше, номер перезаписываем в переменную nmin2.
i f (X [ i ] }
/ / Вывод двух минимальных элементов и их индексов.
c o u t << " n m i n 1 = " < c o u t << " n m i n 2 = " < r e t u r n 0 ;
}
По образу и подобию этой задачи можно написать задачу поиска трёх ми-
нимальных элементов в массиве. Первые два этапа (поиск номе ров двух мини-
мальных элементов в массиве) будут полным повторением кода , приведённого
выше. На третьем этапе нужен цикл, в котором будем искать ном ер минималь-
ного элемента, при условии, что его номер не равен nmin1иnmin2 . Авторы насто-
ятельно рекомендуют читателям самостоятельно написать под обную программу.
Аналогично можно написать программу поиска четырёх минимал ьных элемен-
тов. Однако при этом усложняется и увеличивается код програ ммы. К тому же,
рассмотренный приём не позволит решить задачу в общем случа е (найтиkми-
нимумов).
Для поиска kминимумов в массиве можно поступить следующим образом.
Будем формировать массив nmin, в котором будут храниться номера минималь-
ных элементов массива x. Для его формирования организуем цикл по переменной
j от 0 до k-1. При каждом вхождении в цикл в массиве nminэлементов будет j-1
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

150Глава 5. Массивы
элементов,i и мы будем искатьj-й минимум (формировать j-й элемент массива).
Алгоритм формирования j-го элемента состоит в следующем: необходимо найти
номер минимального элемента в массиве x, исключая номера, которые уже хра-
нятся в массиве nmin. Внутри цикла по jнеобходимо выполнить такие действия.
Для каждого элемента массива x(цикл по переменной i) проверить содержится
ли номер в массиве nmin, если не содержится, то количество (переменная kvo)
таких элементов увеличить на 1. Далее, если kvoравно 1, то это первый элемент,
который не содержится в массиве nmin, его номер объявляем номером минималь-
ного элемента массива ( nmin_temp=i;). Еслиkvo>1, сравниваем текущий элемент
x[i] с минимальным ( if (x[i] горитма поиска kминимальных элементов массива представлена на рис. 5.10 2
.
Далее приведён текст программы с комментариями.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t p , j , i , n , ∗nmin , k , k v o , nmin_temp ;
b o o l p r ;
double ∗x ;
c o u t << " n = "; c i n >>n ;
x= new double [ n ] ;
c o u t << "Введите элементы массива Х \ n ";
f o r ( i = 0 ; i c i n >>x [ i ] ;
c o u t << "Введите количество минимумов \ n "; c i n >>k ;
nmin= new i n t [ k ] ;
f o r ( j = 0 ; j { k v o = 0 ;
f o r ( i = 0 ; i {
/ /Цикл по переменной pпроверяет, содержится ли номер iв массиве nmin.
p r= f a l s e ;
f o r ( p = 0 ; p< j ; p++)
i f ( i ==nmin [ p ] ) p r= t r u e;
i f ( ! p r ) / /Если не содержится, то количество элементов увеличить на 1.
{ k v o ++;
/ / Если kvo=1, то найден первый элемент, который не содержится в м ассиве
/ / nmin, его номер объявляем номером минимального элемента мас сива
i f ( k v o ==1) nmin_temp= i ;
e l s e / / Если kvo>1, сравниваем текущий элемент x[i] с минимальным.
i f ( x [ i ] < x [ nmin_temp ] ) nmin_temp= i ;
}
}
nmin [ j ] = nmin_temp ; / /Номер очередного минимального элемента записываем в масси в.
} f o r ( j = 0 ; j c o u t << " n m i n 1 = " < r e t u r n 0 ;
}
Проверку, содержится ли число iв массиве nmin, можно оформить в виде
функции, тогда программа может быть записана следующим обра зом:
#i n c l u d e < i o s t r e a m >
2
В блок-схеме отсутствует ввод данных и вывод результатов.
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов151
Рис. 5.10: Блок-схема алгоритма поискаkминимальных элементов в массиве x.
u s i n g namespace s t d ;
/ / Функция проверяет, содержится ли число i в массиве x из n элемент ов.
/ / Функция возвращает true, если содержится, и false, если не соде ржится.
b o o l p r o v e r k a ( i n ti ,i n t ∗x , i n t n )
{ b o o l p r ;
i n t p ;
p r= f a l s e ;
f o r ( p = 0 ; p i f ( i ==x [ p ] ) p r= t r u e;
r e t u r n p r ;
} i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t j , i , n , ∗nmin , k , k v o , nmin_temp ;
double ∗x ;
c o u t << " n = "; c i n >>n ;
x= new double [ n ] ;
c o u t << " Введите элементы массива Х \ n " ;
f o r ( i = 0 ; i c i n >>x [ i ] ;
c o u t << " Введите количество минимумов \ n " ; c i n >>k ;
nmin= new i n t [ k ] ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

152Глава 5. Массивы
f o r( j = 0 ; j {
k v o = 0 ;f o r ( i = 0 ; i {
/ / Вызов функции proverka, определяем, содержится ли число iв массиве nmin из jэлементов
i f ( ! p r o v e r k a ( i , nmin , j ) )
{ k v o ++;
i f ( k v o ==1) nmin_temp= i ;
e l s e
i f ( x [ i ] < x [ nmin_temp ] ) nmin_temp= i ;
}
}
nmin [ j ] = nmin_temp ;
}
f o r ( j = 0 ; j c o u t << " n m i n 1 = " < r e t u r n 0 ;
}
Авторы настоятельно рекомендуют читателю разобрать все верс ии решения
задачи 5.4.
Задача 5.5. Поменять местами максимальный и минимальный элементы в мас -
сиве X.
Алгоритм решения задачи можно разбить на следующие этапы.
1. Ввод массива.
2. Поиск номеров максимального ( nmax) и минимального ( nmin) элементов
массива.
3. Обмен элементов местами. Не получится записать в лоб ( X[nmax]=X
[nmin]; X[nmin]=X[nmax]; ). При таком присваивании мы сразу же теряем
максимальный элемент. Поэтому нам понадобится временная ( буфер-
ная) переменная temp. Обмен элементов местами должен быть т аким:
temp=X[nmax]; X[nmax]=X[nmin]; X[nmin]=temp;
Далее приведён текст программы с комментариями.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t i , N , nmax , nmin ;
f l o a t temp ;
c o u t << " N = "; c i n >>N ;
f l o a t X [ N ] ;
c o u t << " Введите элементы массива Х \ n " ;
f o r ( i = 0 ; i c i n >>X [ i ] ;
/ / Поиск номеров максимального и минимального элементов масс ива.
f o r ( nmax=nmin = 0 , i = 1 ; i {
i f (X [ i ] i f (X [ i ] >X [ nmax ] ) nmax= i ;
}
/ / Обмен максимального и минимального элементов местами.
temp=X [ nmax ] ; X [ nmax ] =X [ nmin ] ; X [ nmin ] = temp ;
c o u t << "Преобразованный массив Х \ n ";/ / Вывод преобразованного массива.
f o r ( i = 0 ; i c o u t < Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов153
c o u t < r e t u r n 0 ;
}
Задача 5.6. Найти среднее геометрическое среди простых чисел, располо жен-
ных между максимальным и минимальным элементами массива.
Среднее геометрическое kэлементов ( S G)можно вычислить по формуле
S G =k

P
,P  произведение kэлементов. При решении этой задачи необхо-
димо найти произведение и количество простых чисел, распол оженных между
максимальным и минимальным элементами.
Алгоритм решения задачи состоит из следующих этапов:
1. Ввод массива.
2. Поиск номеров максимального ( nmax) и минимального ( nmin) элементов
массива.
3. В цикле перебираем все элементы массива, расположенные м ежду макси-
мальным и минимальным элементами. Если текущий элемент явл яется про-
стым числом, то необходимо увеличить количество простых чи сел на 1, и
умножить Pна значение элемента массива.
4. Вычислить S G=k

P
.
При решении этой задачи следует учитывать, что неизвестно, какой элемент
расположен раньше  максимальный или минимальный.
Текст программы с комментариями приведён ниже.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
b o o l p r o s t o e ( i n tN)
{ i n t i ;
b o o l p r ;
i f ( N<2) p r= f a l s e;
e l s e
f o r ( p r= t r u e , i = 2 ; i <=N / 2 ; i ++)
i f (N% i ==0)
{ p r= f a l s e ;
break ;
}
r e t u r n p r ;
} i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t i , k , n , nmax , nmin , p , ∗x ;
c o u t << " n = "; c i n >>n ; / /Ввод количества элементов в массиве.
x= new i n t [ n ] ;/ /Выделяем память для динамического массива x.
c o u t << "Введите элементы массива X "; / / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
/ / Поиск номеров максимального и минимального элементов в мас сиве.
f o r ( nmax=nmin= i = 0 ; i {
i f ( x [ i ] < x [ nmin ] ) nmin= i ;
i f ( x [ i ] > x [ nmax ] ) nmax= i ;
} i f ( nmin f o r ( p = 1 , k = 0 , i =nmin + 1 ; i © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

154Глава 5. Массивы
/ / Обратите особое внимание на использование в следующей строке фигурной скобки
/ / (составного оператора). В цикле всего один оператор!!! Пр и этом, при отсутствии
/ / составного оператора, программа начинает считать с ошибками! !!
{
/ /Проверяем, является ли очередной элемент массива простым ч ислом.
i f ( p r o s t o e ( x [ i ] ) ) / /Если x[i]  простое число.
{
/ / Домножаем y[i] на p, а также увеличиваем счётчик количества пр остых чисел в массиве.
k++;p ∗=x [ i ] ;
}
}
e l s e
f o r ( p = 1 , k = 0 , i =nmax + 1 ; i / / Проверяем, является ли очередной элемент массива простым ч ислом.
i f ( p r o s t o e ( x [ i ] ) ) / /Если x[i]  простое число.
{ / / Домножаем y[i] на p, а также увеличиваем счётчик количества пр остых чисел в массиве.
k++;p ∗=x [ i ] ;
}
/ / Если в массиве были простые числа, выводим среднее геометри ческое этих чисел на экран
i f ( k >0)
c o u t << " S G "< / / Иначе выводим сообщение о том, что в массиве нет простых чисе л.
e l s e c o u t << "Нет простых чисел в массиве "<< e n d l ;
r e t u r n 0 ;
}
5.4.5 Удаление элемента из массива Для удаления элемента с индексом mиз массива X, состоящего из nэле-
ментов, нужно записать (m + 1) -й элемент на место элемента m,(m + 2) -й  на
место (m + 1) -го и т.д., (n − 1) -й  на место (n − 2) -го. После удаления количество
элементов в массиве уменьшилось на 1 (рис. 5.11).
Рис. 5.11: Алгоритм удаления элемента из массива
Фрагмент программы на С++:
c o u t << " \ n m = " ; c i n >>m ; / /Ввод номера элемента, подлежащего удалению.
f o r ( i =m ; i n −− ;
f o r ( i = 0 ; i При написании программ, в которых удаляются элементы из масс ива, следу-
ет учитывать тот факт, что после удаления элемента все элеме нты, расположен-
ные после удалённого, изменяют свои номера (индексы уменьша ются на один).
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов155
Это особенно важно при удалении нескольких элементов из массива. Рассмотрим
несколько задач.
Задача 5.7. Удалить из массива x[20]все элементы с пятого по десятый.
При решении задач, связанных с удалением подряд идущих элем ентов, следу-
ет понимать, что после удаления очередного элемента следующ ий переместился
на место удалённого. Поэтому далее нужно будет удалять элем ент с тем же са-
мым номером. В нашем случае подлежит удалению 6 элементов с п ятого по деся-
тый. Однако, реально надо будет 6 раз удалить элемент с номер ом 5. Блок-схема
алгоритма представлена на рис 5.12, текст программы привед ён далее.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t i , j , n = 2 0 ;
f l o a t x [ n ] ; / /Выделяем память для динамического массива x.
c o u t << " Введите элементы массива X \ n " ;/ / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
f o r ( j = 1 ; j <=6; j ++) / /Шесть раз повторяем алгоритм удаления элемента с индексом 5 .
f o r ( i = 5 ; i x [ i ] = x [ i + 1 ] ;
c o u t << " Преобразованный массив X \ n " ;/ / Вывод элементов массива.
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
Рис. 5.12: Алгоритм решения задачи 5.7
Задача 5.8. Удалить из массива X[n]все положительные элементы.
При удалении отдельных элементов из массива следует учитыв ать: при уда-
лении элемента (сдвиге элементов влево и уменьшении n) не надо переходить к
следующему, а если элемент не удалялся, то, наоборот, надо пе реходить к следу-
ющему. Далее приведён текст программы решения задачи 5.8.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

156Глава 5. Массивы
i n tm a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t i , j , n ;
c o u t << " n = "; c i n >>n ;
f l o a t x [ n ] ;/ /Выделяем память для динамического массива x.
c o u t << " Введите элементы массива X \ n " ;/ / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
f o r ( i = 0 ; i i f ( x [ i ] > 0 ) / /Если текущий элемент положителен,
{ / /то удаляем элемент с индексом i.
f o r ( j = i ; j x [ j ] = x [ j + 1 ] ;
n −− ;
} e l s e i ++;/ /иначе  переходим к следующему элементу массива.
c o u t << " Преобразованный массив X \ n " ;/ / Вывод элементов массива.
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
Задача 5.9. Удалить из массива все отрицательные элементы, расположен ные
между максимальным и минимальным элементами массива X[n].
Решение этой задачи можно разделить на следующие этапы:
1. Ввод массива.
2. Поиск номеров максимального ( nmax) и минимального ( nmin) элементов
массива.
3. Определение меньшего ( a) и большего ( b) из чисел nmaxиnmin .
4. Далее, необходимо перебрать все элементы массива, распо ложенные меж-
ду числами с номерами aи b. Если число окажется отрицательным, то
его необходимо удалить. Однако на этом этапе нужно учитыват ь тонкий
момент. Если просто организовать цикл от a+1доb-1 , то при удалении
элемента изменяется количество элементов, расположенных междуaи b, и
номер последнего удаляемого элемента. Это может привести к тому, что не
всегда корректно будут удаляться отрицательные элементы, расположен-
ные между aи b. Поэтому этот цикл для удаления организован несколько
иначе.
Текст программы:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t i , j , k , n , nmax , nmin , ∗x , a , b ;
c o u t << " n = "; c i n >>n ; / /Ввод количества элементов в массиве.
x= new i n t [ n ] ;/ /Выделяем память для динамического массива x.
c o u t << " Введите элементы массива X \ n " ;/ / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
/ / Поиск номеров максимального и минимального элементов в мас сиве.
f o r ( nmax=nmin= i = 0 ; i { i f ( x [ i ] < x [ nmin ] ) nmin= i ;
i f ( x [ i ] > x [ nmax ] ) nmax= i ;
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов157
}
/ / Проверяем, что раньше расположено, минимум или максимум
i f ( nmin {
a=nmin ;
b=nmax ;
}
e l s e
{
a=nmax ;
b=nmin ;
}
/ / Перебираем все элементы, расположенные между максимумом и ми нимумом
f o r ( i =a + 1 , k = 1 ; k<=b −a− 1 ; k++)
i f ( x [ i ] < 0 ) / /Проверяем, является ли очередной элемент массива отрицате льным.
{ / / Если текущий элемент массива является отрицательным числом , удаляем его
f o r ( j = i ; j x [ j ] = x [ j + 1 ] ;
n −− ;
} e l s e i ++;/ /Если x[i]>=0, переходим к следующему элементу.
c o u t << " Преобразованный массив X \ n " ;
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
В качестве тестового можно использовать следующий массив:
34 ,4 ,− 7,− 8,− 10 ,7 ,− 100 ,− 200 ,− 300 ,1 . Здесь приведённая выше программа
работает корректно, а вариант f o r ( i =a + 1 ; i i f ( x [ i ] < 0 )
{ f o r ( j = i ; j x [ j ] = x [ j + 1 ] ;
n −− ;
}
e l s e i ++;
приводит к неправильным результатам. Рекомендуем читател ю самостоятельно
разобраться в особенностях подобных алгоритмов удаления.
Задача 5.10. В массивеX[n]найти группу наибольшей длины, которая состоит
из знакочередующихся чисел.
Если будут вычислены следующие значения:
•nach  номер первого элемента в группе;
• kon  номер последнего элемента в группе;
• k количество элементов в группе.
то, зная любые два из них, можно однозначно определить группу внутри массива.
Вначале количество элементов в знакочередующейся группе ра вно 1. Дело
в том, что если мы встретим первую пару знакочередующихся эле ментов, то
количество их в группе сразу станет равным 2. Однако все посл едующие пары
элементов будут увеличивать kна 1. И чтобы не решать проблему построения
последовательности значений k0,2,3,4,5,..., первоначальное значение kпримем
равным 1. Когда будем встречать очередную пару подряд идущи х соседних эле-
ментов, то kнеобходимо будет увеличить на 1.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

158Глава 5. Массивы
Алгоритм поиска очередной группы состоит в следующем: попарн о (x
i,
x
i+1 )
перебираем все элементы массива (параметр цикла iизменяется от 0 до n− 2).
Если произведение соседних элементов отрицательно ( x
i ·
x
i+1 <
0), то это
означает, что они имеют разные знаки и являются элементами гру ппы. В этом
случае количество (k ) элементов в группе увеличиваем на 1 ( k++). Если же про-
изведение соседних элементов положительно ( x

x
i+1 >
0), то эти элементы не
являются членами группы. В этом случае возможны два варианта :
1. Если k >1, то только что закончилась группа, в этом случае kon=i
номер последнего элемента в группе, k количество элементов в только
что закончившейся группе.
2. Если k= 1 , то это просто очередная пара незнакочередующихся элементо в.
После того, как закончилась очередная группа знакочередующ ихся элементов,
необходимо количество групп ( kgr) увеличить на 1 ( kgr++). Если это первая
группа ( kgr=1) знакочередующихся элементов, то в переменную maxзаписываем
длину этой группы ( max=k)3
, а в переменную kon_maxномер последнего элемента
группы ( kon_max=i ). Если это не первая группа ( kgr=1), то сравниваем maxи
длину текущей группы ( k). Если k>max, то в переменную maxзаписываем длину
этой группы ( max=k), а в переменную kon_maxномер последнего элемента группы
( kon_max=i ).
После этого в переменную kопять записываем 1 для формирования новой
группы элементов.
По окончанию цикла значение kможет быть больше 1. Это означает, что в
самом конце массива встретилась ещё одна группа. Для неё над о будет прове-
сти все те же действия, что и для любой другой группы. Далее при ведён текст
программы.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ f l o a t ∗x ;
i n t i , k , n , max , k g r , kon_max ;
c o u t << " n = "; c i n >>n ; / /Ввод размера массива.
x= new f l o a t [ n ] ;/ /Выделение памяти для массива.
c o u t << "Введите массив x \ n ";/ /Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
/ / Попарно перебираем элементы массива. Количество знакочер едующихся
/ / групп в массиве kgr=0, количество элементов в текущей группе  1.
f o r ( k g r= i = 0 , k = 1 ; i / / Если соседние элементы имеют разные знаки, то количество (k)
/ / элементов в группе увеличиваем на 1.
i f ( x [ i ] ∗x [ i + 1 ] < 0 ) k++;
e l s e
i f ( k >1) / /Если k>1, то только что закончилась группа, i  номер последнег о элемента
{ / / в группе, k  количество элементов в группе. Увеличиваем kgr на 1 .
k g r ++; i f ( k g r ==1) / /Если это первая группа (kgr=1) знакочередующихся элементов,
{
max=k ; / /то max  длина группы (max=k),
kon_max= i ; / /kon_max  номер последнего элемента группы.
3
В переменной
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов159
}
e l s e / /это не первая группа ( kgr6
= 1 ), сравниваем max и длину текущей группы.
i f ( k>max ) / /Если k>max,
{
max=k ; / /max  длина группы,
kon_max= i ; / /kon_max  номер последнего элемента группы.
}
k = 1 ; / /В переменную k записываем 1 для формирования новой группы элем ентов.
}
i f ( k >1) / /Если в конце массива была группа.
{
k g r ++; / /Количество групп увеличиваем на 1.
i f ( k g r ==1) / /Если это первая группа,
{
max=k ; / /то max  длина группы,
kon_max=n −1 ; / /группа закончилась на последнем элементе массива.
} e l s e
i f ( k>max ) / /Если длина очередной группы больше max.
{ max=k ; / /то в max записываем длину последней группы,
kon_max=n −1 ; / /группа закончилась на последнем элементе массива.
}
} i f ( k g r >0) / /Если знакочередующиеся группы были,
{ / /то выводим информацию о группе наибольшей длины,
c o u t << "В массиве "< c o u t << "Группа максимальной длины начинается с элемента Номер
" < " < f o r ( i =kon_max −max + 1 ; i <=kon_max ; i ++) / /а также саму группу.
c o u t < c o u t < }
e l s e / /Если знакочередующихся групп не было, то выводим сообщение об этом.
c o u t << " В массиве нет групп знакочередующихся элементов \ n " ;
r e t u r n 0 ;
}
5.4.6 Сортировка элементов в массиве Сортировка представляет собой процесс упорядочения элеме нтов в массиве
в порядке возрастания или убывания их значений. Например, м ассивYиз n
элементов будет отсортирован в порядке возрастания значен ий его элементов,
если
Y[0] < Y [1]< . . . < Y [n − 1],
и в порядке убывания, если
Y [0] > Y [1]> . . . > Y [n − 1].
Существует большое количество алгоритмов сортировки, но в се они базиру-
ются на трёх основных:
• сортировка обменом;
• сортировка выбором;
• сортировка вставкой.
Представим, что нам необходимо разложить по порядку карты в колоде. Для
сортировки карт обменомможно разложить карты на столе лицевой стороной
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

160Глава 5. Массивы
вверх и менять местами те карты, которые расположены в непра вильном поряд-
ке, делая это до тех пор, пока колода карт не станет упорядоче нной.
Для сортировки выбором из разложенных на столе карт выбирают самую
младшую (старшую) карту и держат её в руках. Затем из оставших ся карт вновь
выбирают наименьшую (наибольшую) по значению карту и помещают её поза-
ди той карты, которая была выбрана первой. Этот процесс повт оряется до тех
пор, пока вся колода не окажется в руках. Поскольку каждый ра з выбирается
наименьшая (наибольшая) по значению карта из оставшихся на столе карт, по
завершению такого процесса карты будут отсортированы по во зрастанию (убы-
ванию). Для сортировки вставкой из колоды берут две карты и располагают их в
необходимом порядке по отношению друг к другу. Каждая следу ющая карта,
взятая из колоды, должна быть установлена на соответствующе е место по отно-
шению к уже упорядоченным картам.
Итак, решим следующую задачу. Задан массив Yиз nцелых чисел. Располо-
жить элементы массива в порядке возрастания их значений.
5.4.6.1 Сортировка методом пузырька
Сортировка пузырьковым методом является наиболее известн ой. Её популяр-
ность объясняется запоминающимся названием, которое проис ходит из-за подо-
бия процессу движения пузырьков в резервуаре с водой, когда каждый пузырёк
находит свой собственный уровень, и простотой алгоритма. С ортировка методом
пузырька использует метод обменной сортировки и основан а на выполнении
в цикле операций сравнения и при необходимости обмена сосед них элементов.
Рассмотрим алгоритм пузырьковой сортировки более подробн о.
Сравним нулевой элемент массива с первым, если нулевой окаж ется больше
первого, то поменяем их местами. Те же действия выполним для первого и второ-
го, второго и третьего, i–го и ( i+ 1) –го, предпоследнего и последнего элементов.
В результате этих действий самый большой элемент станет на п оследнее (n− 1) -е
место. Теперь повторим данный алгоритм сначала, но последн ий (n− 1)-й эле-
мент рассматривать не будем, так как он уже занял своё место. После проведения
данной операции самый большой элемент оставшегося массива станет на (n− 2) -е
место. Так повторяем до тех пор, пока не упорядочим весь масс ив.
В табл. 5.4 представлен процесс упорядочивания элементов в массиве.
Таблица 5.4: Процесс упорядочивания элементов
Номер элемента 0 1 2 3 4
Исходный массив 7 3 5 4 2
Первый просмотр 3 5 4 2 7
Второй просмотр 3 4 2 5 7
Третий просмотр 3 2 4 5 7
Четвёртый просмотр 2 3 4 5 7
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов161
Нетрудно заметить, что для преобразования массива, состоящего изnэле-
ментов, необходимо просмотреть его n− 1раз, каждый раз уменьшая диапа-
зон просмотра на один элемент. Блок–схема описанного алгор итма приведена на
рис. 5.13.
Рис. 5.13: Сортировка массива пузырьковым методом
Обратите внимание на то, что для перестановки элементов (ри с. 5.13, блок 4)
используется буферная переменная b, в которой временно хранится значение эле-
мента, подлежащего замене. Текст программы, сортирующей эл ементы в массиве
по возрастанию методом пузырька, приведён далее.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t n , i , b , j ;
c o u t << " n = "; c i n >>n ;
f l o a t y [ n ] ;
f o r ( i = 0 ; i {
c o u t << " \ n Y [ " < c i n >>y [ i ] ;
} f o r ( j = 1 ; j f o r ( i = 0 ; i i f ( y [ i ] > y [ i + 1 ] ) / /Если текущий элемент больше следующего
{
b=y [ i ] ; / /Сохранить значение текущего элемента
y [ i ] = y [ i + 1 ] ; / /Заменить текущий элемент следующим
y [ i +1]=b ; / /Заменить следующий элемент на сохранённый в b
}
f o r ( i = 0 ; i r e t u r n 0 ;
}
Для перестановки элементов в массиве по убыванию их значени й необходимо
в программе и блок-схеме при сравнении элементов массива за менить знак >
на <.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

162Глава 5. Массивы
Однако, в этом и во всех далее рассмотренных алгоритмах не уч итывается
то факт, что на каком-то этапе (или даже в начале) массив уже м ожет оказаться
отсортированным. При большом количестве элементов (сотни и даже тысячи чи-
сел) на сортировку вхолостую массива тратится достаточно много времени.
Ниже приведены тексты двух вариантов программы сортировки по убыванию
методом пузырька, в которых алгоритм прерывается, если мас сив уже отсорти-
рован.
Вариант 1.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t n , i , b , j ;
b o o l p r ;
c o u t << " n = "; c i n >>n ;
f l o a t y [ n ] ;
f o r ( i = 0 ; i { c o u t << " \ n Y [ " < c i n >>y [ i ] ;
}
f o r ( j = 1 ; j { f o r ( p r= f a l s e , i = 0 ; i / / ( p r= f a l s e ) .
i f ( y [ i ] < y [ i + 1 ] ) / /Если текущий элемент меньше следующего
{ b=y [ i ] ; / /Сохранить значение текущего элемента
y [ i ] = y [ i + 1 ] ; / /Заменить текущий элемент следующим
y [ i +1]=b ; / /Заменить следующий элемент текущим
p r= t r u e ;/ / Если элемент менялись местами, массив ещё не отсортирован ( pr=true);
}
c o u t << " j = "< / / Если на j-м шаге соседние элементы не менялись, то массив уже о тсортирован,
i f ( ! p r ) break;/ / повторять смысла нет;
} f o r ( i = 0 ; i r e t u r n 0 ;
}
Вариант 2.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t n , i , b , j ;
b o o l p r=t r u e ;
c o u t << " n = "; c i n >>n ;
f l o a t y [ n ] ;
f o r ( i = 0 ; i {
c o u t << " \ n Y [ " < c i n >>y [ i ] ;
} f o r ( j = 1 ; p r ; j ++) / /Упорядочивание элементов массива по убыванию их значений.
{ / /Вход в цикл, если массив не отсортирован (pr=true).
f o r ( p r= f a l s e , i = 0 ; i / / ( p r= f a l s e ) .
i f ( y [ i ] < y [ i + 1 ] ) / /Если текущий элемент меньше следующего
{
b=y [ i ] ; / /Сохранить значение текущего элемента
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов163
y [ i ] = y [ i + 1 ] ;/ /Заменить текущий элемент следующим
y [ i +1]=b ; / /Заменить следующий элемент текущим
p r= t r u e ;/ / Элементы менялись местами, массив ещё не отсортирован ( p r=t r u e )
}
}
f o r ( i = 0 ; i r e t u r n 0 ;
}
5.4.6.2 Сортировка выбором Алгоритм сортировки выбором приведён в виде блок-схемы на ри с. 5.14. Идея
алгоритма заключается в следующем. В массиве Y, состоящем из nэлементов,
ищем самый большой элемент (блоки 2–5) и меняем его местами с последним
элементом (блок 7). Повторяем алгоритм поиска максимально го элемента, но
последний ( n− 1)-й элемент не рассматриваем, так как он уже занял свою пози-
цию.
Рис. 5.14: Сортировка массива выбором наибольшего элемент а
Найденный максимум ставим на ( n− 2)-ю позицию. Описанную выше опера-
цию поиска проводим n− 1раз, до полного упорядочивания элементов в массиве.
Фрагмент программы выполняет сортировку массива по возрас танию методом
выбора:
f o r ( j = 1 ; j f o r ( max=y [ 0 ] , nom= 0 , i = 1 ; i <=n −j ; i ++)
i f ( y [ i ] >max ) {max=y [ i ] ; nom= i ; }
Для упорядочивания массива по убыванию необходимо менять м инимальный
элемент с последним элементом.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

164Глава 5. Массивы
5.4.6.3 Сортировка вставкой
Сортировка вставкой заключается в том, что сначала упорядоч иваются два
элемента массива. Затем делается вставка третьего элемент а в соответствующее
место по отношению к первым двум элементам. Четвёртый элеме нт помещают в
список из уже упорядоченных трёх элементов. Этот процесс по вторяется до тех
пор, пока все элементы не будут упорядочены.
Прежде чем приступить к составлению блок–схемы, рассмотри м следующий
пример. Пусть известно, что в массиве из десяти элементов пе рвые шесть уже
упорядочены (с нулевого по пятый), а шестой элемент нужно вс тавить между
вторым и четвёртым. Сохраним шестой элемент во вспомогател ьной переменной,
а на его место запишем пятый. Далее четвёртый переместим на м есто пятого,
а третий на место четвёртого, тем самым выполнив сдвиг элеме нтов массива
на одну позицию вправо. Записав содержимое вспомогательно й переменной в
третью позицию, достигнем нужного результата.
Составим блок–схему алгоритма (рис. 5.15), учитывая, что в озможно описан-
ные выше действия придётся выполнить неоднократно.
Рис. 5.15: Сортировка массива вставкой
Организуем цикл для просмотра всех элементов массива, начи ная с первого
(блок 1). Сохраним значение текущего i–го элемента во вспомогательной пере-
менной b, так как оно может быть потеряно при сдвиге элементов (блок 2 ), и
присвоим переменной jзначение индекса предыдущего ( i− 1)–го элемента мас-
сива (блок 3). Далее движемся по массиву влево в поисках элем ента, меньшего
чем текущий, и, пока он не найден, сдвигаем элементы вправо н а одну позицию.
Для этого организуем цикл (блок 4), который прекратиться, к ак только будет
Программирование на языке С++ в среде Qt Creator

5.4. Основные алгоритмы обработки массивов165
найден элемент меньше текущего. Если такого элемента в массиве не найдётся
и переменная jстанет равной ( −1), то это будет означать, что достигнута левая
граница массива, и текущий элемент необходимо установить в первую позицию.
Смещение элементов массива вправо на одну позицию выполняе тся в блоке 5, а
изменение счётчика jв блоке 6. Блок 7 выполняет вставку текущего элемента в
соответствующую позицию. Далее приведён фрагмент программы , реализующей
сортировку массива методом вставки. f o r ( i = 1 ; i f o r ( b=y [ i ] , j =i −1 ; ( j > −1 && b Рассмотрим несколько несложных задач, связанных с упорядо чиванием.
Задача 5.11. Задан массивa[n ], упорядоченный по убыванию, вставить в него
некоторое число b, не нарушив упорядоченности массива.
Массив является упорядоченным по убыванию, если каждое посл едующий
элемент массива не больше предыдущего, т. е. при выполнении следующей сово-
купности неравенств a
0
a
1
a
2
... a
n− 3
a
n− 2
a
n− 1.
Для вставки в подобный массив некоторого числа без нарушени й упорядо-
ченности, необходимо:
1. Найти номер kпервого числа в массиве, которое a
k
b.
2. Все элементы массива a, начиная от n− 1до k-го, сдвинуть на один вправо 4
.
3. На освободившееся место с номером kзаписать число b.
Текст программы с комментариями приведён ниже.
#i n c l u d e < i o s t r e a m >
2 u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
4 {
i n t i , k , n ;
6 f l o a t b ;
c o u t << " n = "; c i n >>n ; / /Ввод размера исходного массива.
8 f l o a t a [ n + 1 ] ; / /Выделение памяти с учётом предстоящей вставки одного числа в массив.
c o u t << " Введите массив a \ n " ;/ / Ввод исходного упорядоченного по убыванию массива.
10 f o r( i = 0 ; i c i n >>a [ i ] ;
12 c o u t << " Введите число b = " ; c i n >>b ;/ /Ввод вставляемого в массив числа b .
/ / Если число b меньше всех элементов массива, записываем b в по следний элемент массива.
14 i f( a [ n −1]>=b ) a [ n ] = b ;
e l s e / /Иначе
16 {
f o r ( i = 0 ; i 18 i f( a [ i ]<=b )
{
20 k= i ;/ /Запоминаем его номер в переменной k .
break ;
22 }
f o r ( i =n −1 ; i >=k ; i −−)/ / Все элементы массива от n− 1-го до k-го сдвигаем на один вправо.
24 a [ i +1]= a [ i ] ;
a [ k ] = b ; / /Вставляем число bв массив.
26 }
c o u t << " Преобразованный массив a \ n " ;
28 f o r( i = 0 ; i <=n ; i ++)
c o u t <
4
Очень важно, что сдвиг осуществляем от n− 1-го до k-го, в противном случае элементы
массива оказались бы испорченными.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

166Глава 5. Массивы
30r e t u r n 0 ;
}
Обратите внимание, при решении задачи с массивом, упорядоч енным по воз-
растанию необходимо во фрагменте со строки 14 по строку 22 за менить все опе-
рации отношения на противоположные.
Задача 5.12. Проверить, является ли массив упорядоченным по возрастани ю.
Для проверки упорядоченности по возрастанию a[n]5
можно поступить сле-
дующим образом. Предположим, что массив упорядочен ( pr=true). Если хотя бы
для одной пары соседних элементов выполняется условие a
i > a
i+1 , то массив
не упорядочен по возрастанию ( pr=false). Текст программы с комментариями
приведён ниже. Читателю предлагается преобразовать прогр амму таким обра-
зом, чтобы осуществлялась проверка, упорядочен ли массив п о убыванию.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t i , n ;
b o o l p r ;
c o u t << " n = "; c i n >>n ; / /Ввод размера исходного массива.
f l o a t ∗a= new f l o a t [ n ] ;/ /Выделение памяти для массива.
c o u t << " Введите массив a \ n " ;/ / Ввод исходного массива.
f o r ( i = 0 ; i c i n >>a [ i ] ;
/ / Предполагаем, что массив упорядочен ( pr=true), перебираем все пары соседних значений
/ / (i  номер пары), при iравном n− 2будем сравнивать последнюю пару a[n-2]иa[n-1] .
f o r ( p r= t r u e , i = 0 ; i / / Если для очередной пары соседних элементов выяснилось, что предыдущий элемент больше
/ / последующего, то массив неупорядочен по возрастанию (pr=fal se), остальные пары соседних
/ / значений, можно не проверять (оператор break)
i f ( a [ i ] > a [ i + 1 ] ) { p r= f a l s e;break ; }
i f ( p r ) c o u t << " Массив упорядочен по возрастанию " ;
e l s e c o u t << " Массив не упорядочен по возрастанию " ;
r e t u r n 0 ;
}
5.5 Указатели на функции При решении некоторых задач возникает необходимость перед авать имя
функции как параметр. В этом случае формальным параметром я вляется указа-
тель на передаваемую функцию. В общем виде прототип указател я на функцию
можно записать так. t y p e ( ∗name_f ) ( t y p e 1 , t y p e 2 , t y p e 3 , . . . )
Здесь name_f  имя функции
type  тип, возвращаемый функцией,
type1, type2, type3,...  типы формальных параметров функции.
В качестве примера рассмотрим решение широко известной мат ематической
задачи.
5 Массив является упорядоченным по возрастанию, если выполн яются условияa
0
a
1
a 2
... a
n 3
a
n 2
a
n 1.
Программирование на языке С++ в среде Qt Creator

5.5. Указатели на функции167
Задача 5.13.Вычислитьb
R
a f
(x )dx методами Гаусса и Чебышёва.
Кратко напомним читателю методы численного интегрировани я.
Метод Гаусса состоит в следующем. Определённый интеграл неп рерывной
функции на интервале от -1 до 1 можно заменить суммой и вычисл ить по фор-
муле 1
R
− 1 f
(x )dx = n
P
i =1 A
if
(t
i)
, t
i  точки из интервала
[− 1,1] ,A
i  рассчиты-
ваемые коэффициенты. Методика определения A
i,
t
i представлена в [3]. Для
практического использования значения коэффициентов при n= 2 ,3 ,4 ,5 ,6 ,7 ,8
представлены в табл. 5.5.
Таблица 5.5: Значения коэффициентов в квадратурной формуле
Гаусса
n Массив t Массив A
2 −0.57735027 ,0.57735027 1 , 1
3 − 0.77459667 ,0, 0.77459667 5 / 9, 8/ 9, 5/ 9
4 − 0.86113631 ,−0.33998104 ,0.33998104 ,
0 .86113631 0 .34785484 ,0.65214516 ,0.65214516 ,0.34785484
5 − 0.90617985 ,−0.53846931 ,0, 0.53846931 ,
0 .90617985 0 .23692688 ,0.47862868 ,0.568888889 ,
0 .47862868 ,0.23692688
6 − 0.93246951 ,−0.66120939 ,−0.23861919 ,
0 .23861919 ,0.66120939 ,0.93246951 0 .17132450 ,0.36076158 ,0.46791394 ,0.46791394 ,
0 .36076158 ,0.17132450
7 − 0.94910791 ,−0.74153119 ,−0.40584515 ,0,
0 .40584515 ,0.74153119 ,0.94910791 0 .12948496 ,0.27970540 ,0.38183006 ,0.41795918 ,
0 .38183006 ,0.27970540 ,0.12948496
8 − 0.96028986 ,−0.79666648 ,−0.52553242 ,
− 0.18343464 ,0.18343464 ,0.52553242 ,
0 .79666648 ,0.96028986 0 .10122854 ,0.22238104 ,0.31370664 ,0.36268378 ,
0 .36268378 ,0.31370664 ,0.22238104 ,0.10122854
Для вычисления интеграла непрерывной функции на интервале отaдо
b квадратурная формула Гаусса может быть записана следующим о бразом
b
R
a f
(x )dx =b
− a
2 n
P
i =1 A
if
b+ a 2 ·b
− a 2 t
i
, значения коэффициентов A
i и
t
i приведе-
ны в табл. 5.5. При использовании квадратурной формулы Чебышёва, определ ённый инте-
грал непрерывной функции на интервале от −1 до 1записывается в виде следу-
ющей формулы 1
R
− 1 f
(x )dx =2
nn
P
i =1 f
(t
i)
, t
i  точки из интервала
[− 1,1] . Формула
Чебышёва для вычисления интеграла на интервале от aдо bможет быть записа-
на так b
R
a f
(x )dx =b
− a
n n
P
i =1 f

b+ a 2 ·b
− a 2 t
i
Методика определения t
i представлена
в [3]. Рассмотренные формулы имеют смысл при n= 2 ,3 ,4 ,5 ,6 ,7 ,9 , коэффици-
енты t
i представлены в табл. 5.6.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

168Глава 5. Массивы
Таблица 5.6: Значения коэффициентов в квадратурной формулеЧе-
бышёва
n Массив t
2 − 0.577350 ,0.577350
3 − 0.707107 ,0, − 0.707107
4 − 0.794654 ,− 0.187592 ,0.187592 ,0.794654
5 − 0.832498 ,− 0.374541 ,0, 0.374541 ,0.832498
6 − 0.866247 ,− 0.422519 ,− 0.266635 ,0.266635 ,0.422519 ,0.866247
7 − 0.883862 ,− 0.529657 ,− 0.323912 ,0, 0.323912 ,0.529657 ,0.883862
9 − 0.911589 ,− 0.601019 ,− 0.528762 ,− 0.167906 ,0, 0.167906 ,0.528762 ,0.601019 ,0.911589
Осталось написать функции вычисления определённого интег ралаb
R
a f
(x )dx
методами Гаусса и Чебышёва. Далее приведены тексты функций и функция
main(). В качестве тестовых использовались интегралы 2
R
0 sin
4
xdx ≈0.9701 ,
13
R
5 √
2
x − 1dx ≈32.667 .
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
/ / Функция вычисления определённого интеграла методом Чебышёв а.
/ / (a, b ) интервал интегрирования, *fn указатель на функцию типа double f (double).
double i n t _ c h e b i s h e v ( doublea ,double b ,
double (∗ f n ) ( double ) )
{ i n t i , n = 9 ;
double s ,
t [ 9 ] = { −0 . 9 1 1 5 8 9 , −0 . 6 0 1 0 1 9 , −0 . 5 2 8 7 6 2 , −0 . 1 6 7 9 0 6 , 0 , 0 . 1 6 7 9 0 6 , 0 . 5 2 8 7 6 2 ,
0 . 6 0 1 0 1 9 , 0 . 9 1 1 5 8 9 } ;
f o r ( s= i = 0 ; i s+=f n ( ( b+a ) / 2 + ( b −a ) / 2 ∗t [ i ] ) ;
s ∗=( b −a ) / n ;
r e t u r n s ;
}
/ / Функция вычисления определённого интеграла методом Гаусса.
/ / (a, b ) интервал интегрирования, *fn указатель на функцию типа double f (double)
double i n t _ g a u s s ( doublea ,double b ,double (∗ f n ) ( double ) )
{
i n t i , n = 8 ;
double s ,
t [ 8 ] = { −0 . 9 6 0 2 8 9 8 6 , −0 . 7 9 6 6 6 6 4 8 , −0 . 5 2 5 5 3 2 4 2 , −0 . 1 8 3 4 3 4 6 4 , 0 . 1 8 3 4 3 4 6 4 ,
0 . 5 2 5 5 3 2 4 2 , 0 . 7 9 6 6 6 6 4 8 , 0 . 9 6 0 2 8 9 8 6 } ,
A [ 8 ] = { 0 . 1 0 1 2 2 8 5 4 , 0 . 2 2 2 3 8 1 0 4 , 0 . 3 1 3 7 0 6 6 4 , 0 . 3 6 2 6 8 3 7 8 , 0 . 3 6 2 6 8 3 7 8 ,
0 . 3 1 3 7 0 6 6 4 , 0 . 2 2 2 3 8 1 0 4 , 0 . 1 0 1 2 2 8 5 4 } ;
f o r ( s= i = 0 ; i s+=A [ i ] ∗f n ( ( b+a ) / 2 + ( b −a ) / 2 ∗t [ i ] ) ;
s ∗=( b −a ) / 2 ;
r e t u r n s ;
}
/ / Функции f1иf2 типа double f(double), указатели на которые будут передаваться
/ / вint_gauss иint_chebishev .
double f 1 (double y )
{ r e t u r n s i n ( y )∗s i n ( y ) ∗s i n ( y ) ∗s i n ( y ) ;
}
Программирование на языке С++ в среде Qt Creator

5.6. Совместное использование динамических массивов169
doublef 2 (double y )
{
r e t u r n pow ( 2∗y − 1 , 0 . 5 ) ;
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
double a , b ;
c o u t << " Интеграл s i n ( x ) ^ 4 = \ n " ;
c o u t << " Введите интервал интегрирования \ n " ;
c i n >>a>>b ;
/ / Вызов функции int_gauss(a, b, f1) ,f1  имя функции, интеграл от которой надо посчитать.
c o u t << "Метод Гаусса: "< / / Вызов функции int_chebishev(a, b, f1) ,
/ / f1  имя функции, интеграл от которой надо посчитать.
c o u t << " Метод Чебышёва: " << i n t _ c h e b i s h e v ( a , b , f 1 )<< e n d l ;
c o u t << " Интеграл s q r t ( 2 * x - 1 ) = \ n " ;
c o u t << " Введите интервалы интегрирования \ n " ;
c i n >>a>>b ;
/ / Вызов функции int_gauss(a, b, f2) ,f2  имя функции, интеграл от которой надо посчитать.
c o u t << " Метод Гаусса: " < / / Вызов функции int_chebishev(a, b, f2) ,
/ / f2  имя функции, интеграл от которой надо посчитать.
c o u t << " Метод Чебышёва: " << i n t _ c h e b i s h e v ( a , b , f 2 )<< e n d l ;
r e t u r n 0 ;
}
Результаты работы программы приведены ниже
Интеграл sin(x)^4=
Введите интервалы интегрирования
0 2
Метод Гаусса:0.970118
Метод Чебышёва:0.970082
Интеграл sqrt(2*x-1)=
Введите интервалы интегрирования
5 13
Метод Гаусса:32.6667
Метод Чебышёва:32.6667
5.6 Совместное использование динамических массивов, указателей, функций в сложных задачах обработки
массивов
Функции в С(С++)могут возвращать только одно скалярное значение, однако
использование указателей в качестве аргументов функций по зволяет обойти это
ограничение и писать сложные функции, которые могут возвра щать несколько
значений.
Если в качестве аргумента в функцию передаётся указатель (а дрес), то нужно
иметь в виду следующее. При изменении в функции значений , хранящегося по
этому адресу, будет происходить глобальное изменение значений , хранящихся
по данному адресу в памяти компьютера. Таким образом, получа ем механизм, с
помощью которого можно возвращать множество значений. Для этого надо пере-
давать их как адреса (указатели). В литературе по программи рованию подобный
механизм зачастую называют передачей параметров по адресу . При этом не сле-
дует забывать о том, что этот механизм работает без всяких ис ключений. Любое
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

170Глава 5. Массивы
изменение значений, переданных в функцию по адресу, приводит к глобальному
изменению.
В качестве примера рассмотрим задачу удаления положительных элемен-
тов из массива (см. задачу 5.8). Пользуясь тем, что задача несложная, напи -
шем несколько вариантов функции удаления элемента с заданн ым номером из
массива.
Назовём функцию udal. Её входными параметрами будут:
• массив ( x),
• его размер ( n),
• номер удаляемого элемента ( k).
Функция возвращает:
• модифицированный массив ( x),
• размер массива после удаления ( n).
При передаче массива с помощью указателя исчезает проблема возврата в глав-
ную программу модифицированного массива, размер массива б удем возвращать
с помощью обычного оператора return.
Заголовок (прототип) функции udalможет быть таким:
i n t u d a l ( f l o a t∗x , i n t k ,i n t n )
Здесь x массив, k номер удаляемого элемента, n размер массива.
Весь текст функции можно записать так:
i n t u d a l ( f l o a t ∗x , i n t k ,i n t n )
{
i n t i ;
i f ( k>n −1) r e t u r n n ;
e l s e
{ f o r ( i =k ; i x [ i ] = x [ i + 1 ] ;
n −− ;
r e t u r n n ;
}
}
Ниже приведён весь текст программы удаления положительных элементов из
массива xc использованием функции udalи комментарии к нему.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t u d a l ( f l o a t ∗x , i n t k ,i n t n )
{ i n t i ;
/ / Если номер удаляемого элемента больше номера последнего эл емента,
/ / то удалять нечего, в этом случае возвращается неизменённый р азмер массива
i f ( k>n −1) r e t u r n n ;
e l s e
{
f o r ( i =k ; i x [ i ] = x [ i + 1 ] ;
n −− ;
r e t u r n n ;/ /Возвращаем изменённый размер массива.
}
Программирование на языке С++ в среде Qt Creator

5.6. Совместное использование динамических массивов171
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t i , n ;
c o u t << " n = "; c i n >>n ;
f l o a t x [ n ] ; / /Выделяем память для динамического массива x.
c o u t << "Введите элементы массива X \ n ";/ / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
f o r ( i = 0 ; i i f ( x [ i ] > 0 )
/ / Если текущий элемент положителен, то для удаления элемента с и ндексом i вызываем
/ / функцию udal, которая изменяет элементы, хранящиеся по адрес у x,
n=u d a l ( x , i , n ) ; / /и возвращает размер массива.
e l s e i ++;/ /иначе (x[i]<=0)  переходим к следующему элементу массива.
c o u t << "Преобразованный массив X \ n ";/ / Вывод элементов массива после удаления.
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
Эту функцию можно переписать и по-другому, передавая и масс ив и его раз-
мер как указатели, в этом случае функция будет такой: v o i d u d a l (f l o a t ∗x , i n t k ,i n t ∗n )
{
i n t i ;
f o r ( i =k ; i < ∗n − 1 ; i ++)
x [ i ] = x [ i + 1 ] ;
i f ( k< ∗n ) −−∗n ;
}
В этом случае изменится и обращение к udalв функции main.
Ниже приведён модифицированный текст программы удаления п оложитель-
ных элементов из массива xc использованием функции udal(float *x, int k,
int *n) и комментарии к нему.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
v o i d u d a l (f l o a t ∗x , i n t k ,i n t ∗n )
{
i n t i ;
/ / Если номер удаляемого элемента больше номера последнего эл емента, то удалять нечего,
/ / в этом случае возвращается неизменённый размер массива. Уда ляем элемент с номером k.
f o r ( i =k ; i < ∗n − 1 ; i ++)
x [ i ] = x [ i + 1 ] ;
/ / Уменьшаем на 1 значение, хранящееся по адресу n.
/ / Обратите внимание, что надо писать именно --*n,*n--  НЕПРАВИЛЬНО!!!!!!!!!!!!!!!
i f ( k< ∗n ) −−∗n ;
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ i n t i , n ;
c o u t << " n = "; c i n >>n ;
f l o a t x [ n ] ; / /Выделяем память для динамического массива x.
c o u t << " Введите элементы массива X \ n " ;/ / Ввод элементов массива.
f o r ( i = 0 ; i c i n >>x [ i ] ;
f o r ( i = 0 ; i i f ( x [ i ] > 0 ) / /Если текущий элемент положителен, то удаление элемента с инде ксом i,
/ / Вызываем функцию udal, которая изменяет элементы, хранящиес я по адресу x,
/ / и изменяет значение переменной n.
u d a l ( x , i , & n ) ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

172Глава 5. Массивы
e l s ei ++;/ /иначе (x[i]<=0)  переходим к следующему элементу массива.
c o u t << " Преобразованный массив X \ n " ;/ / Вывод элементов массива после удаления.
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
Авторы рекомендуют разобраться с этими примерами для пониман ия меха-
низма передачи параметров по адресу.
Задача 5.14. Из массива целых чисел удалить все простые числа, значение к ото-
рых меньше среднего арифметического элементов массива. По лученный массив
упорядочить по возрастанию. Алгоритм решения этой задачи без применения функций будет оч ень гро-
моздким, а текст программы малопонятным. Поэтому разобьём задачу на под-
задачи:
• вычисление среднего арифметического элементов массива;
• проверка, является ли число простым;
• удаление элемента из массива;
• упорядочивание массива.
Прототипы функций, которые предназначены для решения подз адач, могут
выглядеть так:
•float sr_arifm(int *x, int n)  вычисляет среднее арифметическое
массива x из n элементов;
• bool prostoe(int n)  проверяет, является ли целое число nпростым,
результат  логическое значение true, если число простое, и falseв про-
тивном случае;
• void udal(int *x, int m, int *n)  удаляет элемент с номеромmв мас-
сиве xиз nэлементов (рис. 6.4);
• void upor(int *x, int N, bool pr=true)  сортирует массивxиз nэле-
ментов по возрастанию или по убыванию, направление сортиров ки зависит
от значения параметра pr, если pr=true , то выполняется сортировка по
возрастанию, если pr=false, то по убыванию.
Текст программы с комментариями:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
f l o a t s r _ a r i f m ( i n t∗x , i n t n )/ /Функция вычисления среднего значения.
{
i n t i ;f l o a t s = 0 ;
f o r ( i = 0 ; i i f ( n >0) r e t u r n ( s / n ) ;
e l s e r e t u r n 0 ;
} b o o l p r o s t o e ( i n tn )/ /Функция для проверки, является ли число nпростым.
{
b o o l p r ;i n t i ;
f o r ( p r= t r u e , i = 2 ; i <=n / 2 ; i ++)
i f ( n% i ==0) { p r= f a l s e;break ; }
r e t u r n ( p r ) ;
}
Программирование на языке С++ в среде Qt Creator

5.6. Совместное использование динамических массивов173
v o i du d a l (i n t∗x , i n t m,i n t ∗n ) / /Функция удаления элемента из массива.
{
i n t i ;
f o r ( i =m ; i < ∗n − 1 ; ∗( x+ i ) = ∗( x+ i +1) , i ++) ;
−− ∗n ;
r e a l l o c ( ( i n t∗) x , ∗n∗ s i z e o f (i n t ) ) ;
}
v o i d u p o r (i n t∗x , i n t n ,b o o l p r=t r u e )/ / Функция сортировки массива.
{
i n t i , j , b ;
i f ( p r )
{
f o r ( j = 1 ; j <=n −1 ; j ++)
f o r ( i = 0 ; i <=n −1− j ; i ++)
i f (∗ ( x+ i ) > ∗( x+ i +1) )
{
b = ∗( x+ i ) ;
∗ ( x+ i ) = ∗( x+ i +1) ;
∗ ( x+ i +1)=b ;
}
}
e l s e f o r ( j = 1 ; j <=n −1 ; j ++)
f o r ( i = 0 ; i <=n −1− j ; i ++)
i f (∗ ( x+ i ) < ∗( x+ i +1) )
{ b = ∗( x+ i ) ;
∗ ( x+ i ) = ∗( x+ i +1) ;
∗ ( x+ i +1)=b ;
}
} i n t m a i n ( )
{ i n t ∗a , n , i ; f l o a ts r ;
c o u t << " n = "; c i n >>n ; / /Ввод размерности массива.
a =( i n t ∗) c a l l o c ( n , s i z e o f(i n t ) ) ; / /Выделение памяти.
c o u t << " Введите массив A \ n " ;
f o r ( i = 0 ; i > ∗( a+ i ) ; / /Ввод массива.
s r =s r _ a r i f m ( a , n ) ; / /Вычисление среднего арифметического.
c o u t << " s r = "< f o r ( i = 0 ; i { i f( p r o s t o e ( ∗( a+ i ) )&& ∗( a+ i )< s r ) / /Если число простое и меньше среднего,
u d a l ( a , i , & n ) ; / /удалить его из массива,
e l s e i ++; / /иначе, перейти к следующему элементу.
}
c o u t << " Массив A \ n " ;/ /Вывод модифицированного массива.
f o r ( i = 0 ; i c o u t << " \ n ";
u p o r ( a , n ) ; / /Сортировка массива.
c o u t << "Упорядоченный массив A \ n ";/ / Вывод упорядоченного массива.
f o r ( i = 0 ; i c o u t << " \ n ";
f r e e ( a ) ; / /Освобождение памяти.
r e t u r n 0 ;
}
Задача 5.15. Все положительные элементы целочисленного массива Gперепи-
сать в массив W. В массиве Wупорядочить по убыванию элементы, которые
расположены между наибольшим и наименьшим числами-палинд ромами.
Для создания этой программы напишем следующие функции:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

174Глава 5. Массивы
•int form (int *a, int n, int *b)  из массива целых чиселaформи-
рует массив положительных чисел b, n  количество чисел в массиве a,
функция возвращает число элементов в массиве b.
• bool palindrom (int n)  проверяет, является ли число nпалиндромом.
• sort (int *x, int n, int k, int p)  сортирует по возрастанию эле-
менты массива x[n], расположенные между k-м и p-м элементами массива.
Рекомендуем читателю самостоятельно разобрать текст прог раммы, реализу-
ющей решение задачи 5.15.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t d l i b . h>
#i n c l u d e
u s i n g namespace s t d ;
i n t k v o _ r a z r y a d ( i n tM)
{
l o n g i n t k ;
f o r ( k = 1 ;M> 9 ;M/ = 1 0 , k++) ;
r e t u r n k ;
}
b o o l p a l i n d r o m ( i n tn )
{ i n t k=k v o _ r a z r y a d ( n ) , s , p=n ;
f o r ( s = 0 ; p ! = 0 ; p / = 1 0 , k −−)
s +=(p %10) ∗pow ( 1 0 , k −1) ;
i f ( s==n ) r e t u r n t r u e ;e l s e r e t u r n f a l s e ;
}
i n t f o r m ( i n t∗a , i n t n ,i n t ∗b )
{ i n t i , k ;
f o r ( i =k = 0 ; i i f ( a [ i ] > 0 )
b [ k++]=a [ i ] ;
r e t u r n k ;
} v o i d s o r t ( i n t∗x , i n t n ,i n t k ,i n t p )
{
i n t i , nom , j ;
i n t b ;
f o r ( i =k + 1 ; i

{
nom= i ;f o r ( j = i + 1 ; j

i f ( x [ j ] < x [ nom ] ) nom= j ;
b=x [ p −1 ] ; x [ p −1]= x [ nom ] ; x [ nom] = b ;
p −− ;
}
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t ∗G, ∗W;
i n t nmax , nmin , kp , i , N , k ;
c o u t << " N = ";
c i n >>N ;
G=( i n t ∗) c a l l o c ( N , s i z e o f(i n t ) ) ;
W=( i n t ∗) c a l l o c ( N , s i z e o f(i n t ) ) ;
c o u t << " Ввод массива G \ n " ;
f o r ( i = 0 ; i c i n >>G [ i ] ;
k=f o r m ( G, N ,W) ;
c o u t << " Вывод массива W \ n " ;
f o r ( i = 0 ; i c o u t < Программирование на языке С++ в среде Qt Creator

5.7. Задачи для самостоятельного решения175
c o u t < f o r ( kp= i = 0 ; i i f ( p a l i n d r o m (W[ i ] ) )
{
kp++;
i f ( kp==1) { nmax= i ; nmin= i ; }
e l s e
{ i f (W[ i ] i f (W[ i ] >W[ nmax ] ) nmax= i ;
}
}
i f ( nmax s o r t (W, k , nmax , nmin ) ;
e l s e s o r t (W, k , nmin , nmax ) ;
c o u t << " Вывод преобразованного массива W \ n " ;
f o r ( i = 0 ; i c o u t < c o u t < r e t u r n 0 ;
}
Результаты работы программы представлены ниже.
N=17
Ввод массива G
-5 -6 191 121 12 -13 14 15 -5 100 666 -666 15251 16261 16262 991 -7 24
Вывод массива W
191 121 12 14 15 100 666 15251 16261 16262 991
Вывод преобразованного массива W
191 121 15251 666 100 15 14 12 16261 16262 991
5.7 Задачи для самостоятельного решения
5.7.1 Основные операции при работе с массивами
Разработать программу на языке C++для решения следующей задачи.
1. Задан массив целых чисел X(n ). Найти
• сумму чётных элементов массива;
• наибольшее из отрицательных чисел массива.
Из данного массива и некоторого массива того же типа, но друг ой раз-
мерности Y(m ), сформировать общий массив Z(n + m). Выполнить сорти-
ровку полученного массива по возрастанию модулей. Удалить из массива
число с номером k.
2. Задан массив вещественных чисел A(n ). Найти
• произведение положительных элементов массива;
• сумму отрицательных чисел, расположенных после максимал ьного
элемента массива.
Из данного массива и некоторого массива того же типа, но друг ой раз-
мерности B(m ), сформировать общий массив C(n + m). Преобразовать по-
лученный массив так, чтобы все его положительные элементы с тали отри-
цательными, и наоборот. Удалить предпоследний элемент мас сива.
3. Задан массив вещественных чисел A(n ). Найти
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

176Глава 5. Массивы
• произведение ненулевых элементов массива.
• сумму чётных чисел, расположенных до минимального элемен та мас-
сива.
Из заданного массива A(n ) все положительные числа переписать в мас-
сив B, а отрицательные в массив C. Удалить из массива A(n ) первый чёт-
ный элемент.
4. Задан массив целых чисел X(n ). Найти
• сумму положительных чётных элементов массива;
• количество элементов массива, расположенных после перво го нулевого
элемента.
Из данного массива и некоторого массива того же типа, но друг ой раз-
мерности Y(m ), сформировать общий массив Z(n + m). Удалить из полу-
ченного массива наибольший элемент.
5. Задан массив вещественных чисел X(n ). Найти
• сумму элементов с нечётными номерами;
• произведение элементов массива, расположенных между пер вым и по-
следним отрицательными элементами.
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности Y(m ), сформировать общий массив Z(n + m ). Удалить из полученного
массива наименьший элемент.
6. Задан массив вещественных чисел X(n ). Найти
• сумму положительных элементов массива;
• произведение элементов с нечётными индексами, расположе нных во
второй половине массива.
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности Y(m ), сформировать общий массив Z(n + m)таким образом, чтобы
в нём сначала располагались все отрицательные элементы, за тем элемен-
ты, равные нулю, и в заключение все положительные. Удалить из м ассива
Z (n + m)максимальный элемент.
7. Задан массив целых чисел B(n ). Найти
• произведение отрицательных элементов с чётными индексам и.
• максимальный элемент среди элементов, которые кратны 3. Из данного массива и некоторого массива того же типа, но друг ой раз-
мерности C(m ), сформировать массив A, состоящий только из неотрица-
тельных значений заданных массивов. Удалить из массива Aпервое число,
кратное 17.
8. Задан массив целых чисел X(n ). Найти
• сумму чисел, расположенных в первой половине массива;
• разность между значениями максимального и минимального э лемен-
тов массива.
Из данного массива сформировать новый массив Y, в который записать
все ненулевые элементы массива X(n ). Удалить из массива X(n ) последнее
чётное число.
9. Задан массив целых чисел X(n ). Найти
Программирование на языке С++ в среде Qt Creator

5.7. Задачи для самостоятельного решения177
• произведение элементов массива, кратных трём;
• сумму чисел, которые расположены между минимальным и макси-
мальными элементами массива.
Из данного массива сформировать новый массив Y(n ), в который перепи-
сать все элементы массива X(n ) в обратном порядке. Удалить из массива
Y (n ) минимальный и максимальный элементы.
10. Задан массив целых чисел X(n ). Найти
• сумму нечётных положительных элементов массива;
• количество чисел, которые расположены до первого нулевог о элемента
в массиве.
Записать элементы заданного массива в обратном порядке. Оп ределить по-
ложение максимального элемента до и после преобразования. Удалить мак-
симальный элемент.
11. Задан массив целых чисел X(n ). Найти
• сумму чётных элементов;
• количество чисел, которые расположены после минимальног о элемен-
та массива.
Заменить нулевые элементы заданного массива значениями их номеров.
Определить среднее арифметическое элементов массива до и п осле преоб-
разования. Удалить минимальный элемент массива X(n ).
12. Задан массив вещественных чисел X(n ). Найти
• процент отрицательных чисел в массиве;
• сумму первого и последнего положительных элементов.
Записать элементы заданного массива в обратном порядке. Оп ределить по-
ложение минимального элемента до и после преобразования. У далить ми-
нимальный элемент.
13. Задан массив целых чисел A(n ). Найти
• среднее арифметическое элементов массива;
• минимальный элемент и его индекс в первой половине массива .
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности B(m )сформировать общий массив C, в который переписать удво-
енные положительные значения элементов исходных массивов . Удалить из
массива Cпоследний чётный элемент.
14. Задан массив целых чисел A(n ). Найти
• сумму элементов массива, кратных 13;
• количество чётных чисел, расположенных до максимального элемента
массива.
Сформировать массив C, в который переписать квадраты отрицательных
элементов исходного массива A(n ). Удалить из массива Cтри последних
чётных элемента.
15. Задан массив целых чисел P(n ). Найти
• количество нечётных элементов массива;
• произведение чисел, расположенных до минимума.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

178Глава 5. Массивы
Первую половину массиваP(n ) переписать в массив R, а вторую в массив
Q . Найти сумму квадратов разностей элементов массивов RиQ. Удалить
из массива P(n ) последнее число, кратное 5.
16. Задан массив целых чисел X(n ). Найти
• сумму чётных элементов во второй половине массива;
• количество чисел расположенных между первым и последним о трица-
тельными элементами массива.
Из заданного массива X(n ) все положительные числа переписать в мас-
сив Y, а отрицательные в массив Z. Поменять местами максимальный и
минимальный элементы в массиве X(n ). Удалить третий элемент массива
X (n ).
17. Задан массив целых чисел X(n ). Найти
• количество чётных элементов в массиве;
• среднее геометрическое положительных элементов массива , располо-
женных в его первой половине.
Все отрицательные элементы заданного массива заменить зна чением его
максимального элемента. Удалить из массива первый нулевой элемент.
18. Задан массив целых чисел P(n ). Найти
• сумму модулей элементов массива;
• номер первого нулевого элемента.
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности R(m )сформировать общий массив Q, в который переписать поло-
жительные значения элементов исходных массивов. Удалить и з массиваQ
наибольший чётный элемент.
19. Задан массив целых чисел X(n ). Найти
• произведение чисел, кратных 7;
• количество чисел, которые расположены между первым и посл едним
чётными числами.
Из данного массива сформировать новый массив Y, в который переписать
первые kположительных элементов массива X(n ). Удалить из массива
X (n ) число, наименее отличающееся от среднего арифметического з наче-
ния элементов массива.
20. Задан массив целых чисел A(n ). Найти
• произведение ненулевых элементов массива;
• среднее арифметическое элементов массива, расположенны х в его пер-
вой половине.
Из данного массива и некоторого массива того же типа и размер ностиB(n )
сформировать массив C(n ) каждый элемент которого равен квадрату сум-
мы соответствующих элементов массивов A(n ) и B(n ). Удалить из массива
C (n ) наибольший и наименьший элементы.
21. Задан массив вещественных чисел X(n ). Найти
• произведение абсолютных значений элементов массива;
• количество нечётных элементов массива, расположенных в е го второй
половине.
Программирование на языке С++ в среде Qt Creator

5.7. Задачи для самостоятельного решения179
Из данного массива и некоторого массива того же типа и размерностиY(n )
сформировать массив Z(n ) каждый элемент которого равен квадрату раз-
ности соответствующих элементов массивов X(n ) и Y(n ). Удалить из мас-
сива Z(n ) минимальный элемент и поменять местами первый и последний
элементы.
22. Задан массив целых чисел A(n ). Найти
• сумму элементов массива, кратных трём;
• произведение ненулевых элементов массива с чётными индек сами.
Сформировать массива B, в который записать последние kэлементов мас-
сива A(n ). Удалить из массива A(n ) максимальный нечётный элемент.
23. Задан массив вещественных чисел P(n ). Найти
• количество положительных элементов массива;
• номера первого положительного и последнего отрицательно го элемен-
тов массива.
В массиве P(n ) поменять местами первые и последние пять элементов. Уда-
лить из массива P(n ) элемент, наименее отличающийся от среднего ариф-
метического.
24. Задан массив целых чисел B(n ). Найти
• среднее геометрическое элементов, которые кратны трём и х ранятся в
массиве под чётным индексом.
• минимальный элемент среди положительных чётных элементо в.
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности C(m )сформировать массив A, состоящий только из положительных
значений заданных массивов. Удалить из массива B(n ) первый чётный и
последний нечётный элементы.
25. Задан массив вещественных чисел X(n ). Найти
• номер минимального по модулю элемента массива;
• среднее арифметическое первых kположительных элементов.
Из данного массива и некоторого массива того же типа, но друг ой размер-
ности Y(m )сформировать общий массив Zтаким образом, чтобы сначала
располагались все отрицательные элементы, а затем все поло жительные.
Удалить из массива наибольшее и наименьшее простое число.
5.7.2 Применение функций для обработки массивов. Разработать программу на языке C++для решения следующей задачи.
1. Задан массив целых чисел X(n ). Все простые числа переписать в массив
Y . Из массива Yудалить 5 наибольших элементов массива. Вывести на
экран содержимое массива Yвдвоичной системе .
2. Заданы массивы целых чисел X(n ) и Y(k ). Все совершённые числа из этих
массивов переписать в массив Z. В массиве Zнайти четыре наименьших
элемента массива. Результаты вывести на экран в восьмеричной системе.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

180Глава 5. Массивы
3. Заданы массивы целых чиселX(n ) и Y(k ). Два наибольших элемента из
массива Xи пять последних простых чиселиз массиваYпереписать в
массив Z. Проверить содержит ли массив Zчисла, в которых есть цифра
7.
4. Заданы массивы целых чисел X(n ) и Y (k ). Три наименьших простых числа
из массива Yи числа из массива X, в которых есть цифры 1 и 9
переписать в массив Z. Из массива Zудалить все нечётные числа.
5. Задан массив целых чисел X(n ). Шесть наибольших чисел этого массива
переписать в массив Z. Удалить из массива Zвсе чётные числа. Вывести
на экран элементы массива Zввосьмеричной системе счисления .
6. Заданы массивы целых чисел X(n ) и Y(k ). Числа из массива X, в которых
нет нулей и составные числа из массиваY, переписать в массив Z. Най-
ти в массиве Zпять наибольших нечётных чисел. Выполнить сортировку
массивов X,Y иZ в порядке возрастания их элементов.
7. Заданы массивы целых положительных чисел. X(n )  в двоичной системе
счисления, а Y(k )  в восьмеричной. Все числа из массивов XиY пере-
писать в массив десятичных чисел Z. В массиве Zнайти пять наибольших
простых числа . Удалить из массива Zвсе составные числа .
8. Задан массив целых положительных чисел X(n ). Все простые числа дли-
ной не более пяти цифр переписать в массив Y. Удалить из массива два
наибольших и три наименьших числа.
9. Задан массив целых положительных чисел в пятеричной сист емеX(n ). Из
массива Xсформировать массив десятеричных чисел Z. Найти сумму трёх
наименьших и четырёх наибольших чисел массива Z.
10. Заданы массивы целых положительных чисел X(n ), Y (k ), Z (m ). Сформи-
ровать массив Uиз таких элементов массивов X,Y ,Z , которые в восьме-
ричной системе образуют возрастающую последовательность ци фр. Найти
пять наибольших чисел в массива U.
11. Задан массив целых положительных чисел X(n ). Все числа в которых нет
цифр 1, 2 и 3 переписать в массив Y. Найти сумму двух наибольших
и трёх наименьших простых чиселв массивеY.
12. Заданы массивы целых положительных чисел X(n ), Y (k ), Z (m ). Сформи-
ровать массив Uиз таких элементов массивов X,Y ,Z , которые состоят из
одинаковых цифр. Удалить из массива Uнаибольшее и наименьшее число.
Выполнить сортировку массивов X(n ), Y (k ), Z (m )в порядке возрастания
их элементов.
13. Задан массив целых положительных чисел X(n ). Все числа, в которых нет
цифры ноль, а их длина не менее трёх цифр переписать в массив Z. Поме-
нять местами наибольшее составное числои наименьшеепростое число в
массиве Z.
14. Задан массив целых чисел X(n ). Все положительные числа, состоящие из
одинаковых цифр, переписать в массив Z. Удалить из массива Zчисла с
чётной суммой цифр.
Программирование на языке С++ в среде Qt Creator

5.7. Задачи для самостоятельного решения181
15. Заданы массивы целых чиселX(n ) и Y(k ). Все числа, с нечётной суммой
цифр, переписать в массив Z. Найти три наибольших простых числав
массиве Z.
16. Заданы массивы целых чисел X(n ) и Y(k ). Три наибольших числа из мас-
сива Xи числа из массива Y, в которых нет чётных цифр переписать в
массив Z. Элементы массива Zвывести на экран в восьмеричной и деся-
тичной системах счисления.
17. Задан массив целых чисел X(n ). Семь наименьших простых чиселперепи-
сать в массив Z. Удалить из массива числа с чётной суммой цифр.
18. Заданы массивы целых чисел X(n ) и Y(k ). Положительные числа из масси-
ва Xи пять наибольших чисел из массива Yпереписать в массив Z. Найти
сумму четырехзначных чисел массива Z.
19. Заданы массивы целых положительных чисел: X(n )  в пятеричной, а Y(k )
в шестеричной системах счисления. Все числа из массивов пер еписать в
массив десятичных чисел Z. В массиве Zнайти пять наибольших чисел с
нечётной суммой цифр.
20. Заданы массивы целых положительных чисел X(n ), Z(m ). Все простые
числа из массивов XиZ, в которых есть цифры 1, 2 или 3 перепи-
сать в массив Y. Найти произведение двух наибольших и три наименьших
простых чисел массиваY.
21. Задан массив целых положительных чисел в двоичной систе меX(n ). Из
массива Xсформировать массив десятеричных чисел Z. Из массива Zуда-
лить четыре наименьших и три наибольших числа.
22. Заданы массивы целых положительных чисел X(n ), Y (k ), Z (m ). Сформи-
ровать массив Uиз элементов массивов X,Y ,Z , которые образуют убы-
вающую последовательность цифр. Найти сумму семи наименьши х чисел
массива U.
23. Задан массив целых положительных чисел X(n ). Переписать в массив Y
все числа-палиндромы, остальные числа переписать в массив Z. Удалить
из массива Zвсе числа которые есть нули или сумма цифр нечётна.
24. Заданы массивы целых положительных чисел X(n ), Y (k ), Z (m ). Числа,
которые не состоят из одинаковых цифр, переписать в массив U. Удалить
из массива Uчисла с чётной суммой цифр.
25. Задан массив целых положительных чисел X(n ). Все числа с чётной суммой
цифр переписать в массив Z. Элементы массива Zупорядочить в порядке
убывания суммы цифр.
5.7.3 Работа с группами элементов в массиве Разработать программу на языке C++для решения следующей задачи.
1. В массиве вещественных чисел найти предпоследнюю группу, которая со-
стоит только из отрицательных элементов.
2. В массиве вещественных чисел найти первую и последнюю груп пы знако-
чередующихся элементов.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

182Глава 5. Массивы
3. В массиве целых чисел найти вторую и третью группу, состоя щую из нечёт-
ных цифр.
4. В массиве целых чисел найти предпоследнюю группу, состоящ ую из воз-
растающей последовательности чисел.
5. Из массива целых чисел удалить предпоследнюю группу, сост оящую из воз-
растающей последовательности чисел.
6. Из массива целых чисел удалить последнюю группу, состоящу ю из убыва-
ющей последовательности нечётных чисел.
7. Из массива целых чисел удалить группу наибольшей длины, к оторая со-
стоит из возрастающей последовательности нечётных чисел.
8. В массиве целых чисел найти группу наименьшей длины, кото рая состоит
из убывающей последовательности чётных чисел.
9. Из массива целых чисел удалить две группы наибольшей длин ы, состоящие
из простых чисел, в которых нет чётных цифр.
10. Задан массив целых чисел. Вывести на экран первую и после днюю группы,
состоящие из простых чисел.
11. Из массива целых чисел удалить три группы наименьшей дли ны, состоящие
из простых чисел, в представлении которых нет цифры семь.
12. Из массива целых чисел удалить группу наибольшей длины, которая со-
стоит из возрастающей последовательности простых чисел.
13. Из массива целых чисел удалить все группы, которые состо ят из убываю-
щей последовательности чётных чисел.
14. В массиве вещественных чисел найти группу максимальной длины, которая
состоит из знакочередующихся чисел.
15. В массиве вещественных чисел найти группу минимальной д лины, которая
состоит из убывающей последовательности чисел.
16. Из массива вещественных чисел удалить все группы, состо ящие из невоз-
растающей последовательности чисел.
17. Из массива вещественных чисел удалить три группы наибол ьшей длины,
состоящие из возрастающей последовательности чисел.
18. В массиве целых чисел найти две последних группы, состоя щие из простых
чисел, причём цифры каждого числа образуют возрастающую посл едова-
тельность.
19. Из целочисленного массива удалить группу простых чисел минимальной
длины, цифры которых образуют убывающей последовательность .
20. Из целочисленного массива удалить группу минимальной д лины, состоя-
щую из элементов, представляющих собой возрастающую последо ватель-
ность чётных цифр.
21. В массиве целых чисел найти группы наименьшей и наибольш ей длины,
которые состоят из простых чисел.
22. В массиве целых чисел найти группу наибольшей длины, кот орая состоит
из неубывающей последовательности нечётных чисел.
23. Из массива целых чисел удалить две группы наименьшей дли ны, состоящие
из составных чисел, в записи которых нет цифр 0 и 2.
Программирование на языке С++ в среде Qt Creator

5.7. Задачи для самостоятельного решения183
24. Задан массив целых чисел. Вывести на экран первую и последнюю группы,
состоящие из простых чисел с нечётной суммой цифр в каждом.
25. Из массива целых чисел удалить три группы наибольшей дли ны, которые
состоят из отрицательных чисел с чётной суммой цифр в каждом .
5.7.4 Сортировка элементов массива Разработать программу на языке C++для решения следующей задачи.
1. Упорядочить по убыванию элементы целочисленного массива , расположен-
ные между двумя наибольшими чётными значениями.
2. Упорядочить в порядке возрастания модулей элементы масси ва, располо-
женные между наибольшим и наименьшим значениями.
3. Упорядочить в порядке убывания модулей элементы, располо женные меж-
ду первым и последним отрицательным значениями массива.
4. Упорядочить в порядке убывания элементы, расположенные м ежду вторым
положительным и предпоследним отрицательным значениями м ассива.
5. Упорядочить по возрастанию элементы целочисленного масс ива, располо-
женные между первым числом-палиндромом и последним отрица тельным
значением.
6. Упорядочить в порядке возрастания суммы цифр элементы цел очисленного
массива, расположенные между последним числом-палиндром ом и первым
простым числом.
7. Упорядочить по возрастанию модулей элементы целочисленн ого массива,
расположенные между третьим и пятым простыми числами.
8. Упорядочить по убыванию элементы целочисленного массива , расположен-
ные после минимального числа-палиндрома.
9. Удалить из целочисленного массива простые числа. В получ енном масси-
ве упорядочить по возрастанию модулей элементы, расположе нные после
наибольшего числа.
10. Удалить из целочисленного массива числа-палиндромы. В полученном мас-
сиве упорядочить по возрастанию модулей элементы, располо женные до
наименьшего простого числа.
11. Удалить из целочисленного массива все составные числа. Упорядочить эле-
менты массива в порядке возрастания суммы цифр чисел.
12. Удалить из целочисленного массива все числа, состоящие из одинаковых
цифр. Упорядочить элементы массива в порядке убывания суммы их цифр.
13. Задан массив целых положительных чисел. Сформировать н овый мас-
сив, куда записать элементы исходного массива, состоящие и з одинаковых
цифр. Упорядочить элементы полученного массива в порядке во зрастания
суммы цифр чисел.
14. Упорядочить по возрастанию модулей элементы, расположе нные между
двумя наименьшими значениями массива.
15. Упорядочить в порядке возрастания элементы, расположен ные между чет-
вёртым и девятым отрицательным числами массива.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

184Глава 5. Массивы
16. Упорядочить в порядке возрастания модулей элементы, рас положенные
между наибольшим и предпоследним положительным значениям и массива.
17. Упорядочить в порядке убывания модулей элементы, распол оженные меж-
ду пятым положительным и первым отрицательным значениями м ассива.
18. Упорядочить в порядке убывания модулей элементы целочис ленного
массива, расположенные между наибольшим и наименьшим числ ами-
палиндромами.
19. Упорядочить в порядке убывания суммы цифр элементы целоч исленно-
го массива, расположенные между последним и предпоследним числами-
палиндромами.
20. Упорядочить по возрастанию модулей элементы массива, ра сположенные
между двумя наименьшими положительными числами.
21. Упорядочить по возрастанию элементы целочисленного мас сива, располо-
женные между двумя наибольшими числами-палиндромами.
22. Удалить из целочисленного массива числа-палиндромы. В полученном мас-
сиве упорядочить по возрастанию модулей элементы, располо женные до
наименьшего значения.
23. Удалить из целочисленного массива отрицательные числа . В полученном
массиве упорядочить по убыванию элементы, расположенные м ежду двумя
наибольшими простыми числами.
24. Удалить из целочисленного массива простые числа. Упоряд очить элементы
массива в порядке убывания суммы цифр чисел.
25. Задан массив целых положительных чисел. Сформировать н овый массив,
куда записать элементы исходного массива, состоящие из неч ётных цифр.
Упорядочить элементы полученного массива в порядке убывани я суммы
цифр чисел.
Программирование на языке С++ в среде Qt Creator

Глава 6
Статические и динамические матрицыДанная глава посвящена обработке матриц в С++. На большом количестве
примеров будут рассмотрены возможности языка для обработк и статических и
динамических матриц. В завершающем параграфе будет рассмот рено исполь-
зование двойных указателей и функций на примере решения зад ач линейной
алгебры.
6.1 Статические матрицы С(С++)
Матрица  это двумерный массив, каждый элемент которого име ет два ин-
декса: номер строки  i, номер столбца  j.
Статический двумерный массив (матрицу) можно объявить так :
тип имя_переменной [n][m];
где тип определяет тип элементов массива, имя_переменной имя матрицы,
n  количество строк, m количество столбцов в матрице. Строки нумеруются
от 0 до n− 1, столбцы  от 0 до m−1.
Например,
double x[20][35];
Описана матрица вещественных чисел x, состоящая из 20 строк и 35 столбцов
(строки нумеруются от 0 до 19, столбцы от 0 до 34).
Как и любой другой переменной, матрице можно присвоить начал ьное зна-
чение, например int A[2][3]={{1,2,3}, {4,5,6}};
Для обращения к элементу матрицы необходимо указать её имя, и в квад-
ратных скобках номер строки, а затем в квадратных скобках  н омер столбца.
Например, x[2][4] элемент матрицы x, находящийся в третьей строке и пятом
столбце 1
.
Для работы с элементами матрицы необходимо использовать дв а цикла. Для
построчной обработки матрицы значениями параметра первог о (внешнего) цик-
ла будут номера строк матрицы, значениями параметра второг о (внутреннего)
1
Напоминаем, что нумерация строк и столбцов идёт с 0.

186Глава 6. Статические и динамические матрицы
цикла  номера столбцов (см. рис. 6.1). При построчной обраб отке матрицы
вначале поочерёдно рассматриваются элементы первой строки (столбца), затем
второй и т.д. до последней. Если необходимо обрабатывать ма трицу по столб-
цам, то необходимо организовать внешний цикл по столбцам, а внутренний по
строкам (см. рис. 6.2).
6.2 Динамические матрицы
В предыдущем параграфе мы рассмотрели описание статически х матриц, в
этом случае память для хранения матрицы выделяется в момент описания. Од-
нако в С++существует возможность создавать динамические матрицы. Д ина-
мические матрицы можно создавать с использованием обычных указателей и с
помощью двойных указателей. Рассмотрим оба способа работы с динамическими
матрицами последовательно.
Рис. 6.1: Блок-схема построчной об- работки матрицы Рис. 6.2: Блок-схема обработки мат-рицы по столбцам
6.2.1 Использование указателей для работы с динамическими матрицами
При работе с динамическими матрицами можно использовать об ычные ука-
затели. После описания указателя необходимо будет выделит ь память для хра-
нения N×M элементов ( N число строк, M число столбцов). Рассмотрим
в качестве примера выделение памяти для хранения целочисле нной матрицы
размером N×M .
i n t ∗A , N , M;
A=( i n t ∗) c a l l o c (N ∗M, s i z e o f (i n t ) ) ;
Для выделения памяти можно использовать также и функцию malloc
A=( i n t ∗) m a l l o c (N ∗M ∗s i z e o f (i n t ) ) ;
или операцию new
A= new i n t [ N∗M ] ;
Программирование на языке С++ в среде Qt Creator

6.3. Обработка матриц вС(С++) 187
Память мы выделили, осталось найти способ обратиться к элем енту матри-
цы. Все элементы матрицы хранятся в одномерном массиве разм еромN×M
элементов. Сначала в этом массиве расположена 0-я строка ма трицы, затем 1-я
и т.д. Поэтому для обращения к элементу A[i][j]необходимо по номеру строки
i и номеру столбца jвычислить номер этого элемента kв динамическом массиве.
Учитывая, что в массиве элементы нумеруются с нуля, k= iM +j. Обращение
к элементу A[i][j]будет таким: *(A+i*M+j)илиA[i*M+j] .
6.2.2 Использование двойных указателей для работы с динамическими матрицами
Основной способ работы с динамическими матрицами базирует ся на исполь-
зовании двойных указателей. Рассмотрим следующий фрагмент программы.
i n t m a i n ( )
{ i n t N ,M;
f l o a t ∗ ∗a ;
a= new f l o a t ∗[ N ] ;
}
С помощью оператора newсоздан массив из nэлементов 2
, в котором каждый
элемент является адресом, где хранится указатель (фактиче ски каждый указа-
тель  адрес строки матрицы). Осталось определить значение элементов масси-
ва. Для этого организуем цикл (переменная цикла iизменяется от 0 до N−1),
в котором будет выделяться память для хранения очередной ст роки матрицы.
Адрес этой строки будет записываться в a[i].
f o r ( i = 0 ; i a [ i ] = new f l o a t [M ] ;
После этого определён массив Nуказателей, каждый из которых адресует
массив из Mчисел (в данном случае вещественных типа float). Фактически
создана динамическая матрица размера N×M . Обращение к элементу динами-
ческой матрицы идёт так же, как и к элементу статической матр ицы. Для того,
чтобы обратиться к элементу a
i,j в программе на
C++, необходимо указать его
имя, и в квадратных скобках номер строки и столбца ( a[i][j]).
6.3 Обработка матриц в С(С++)
Рассмотрим основные операции, выполняемые над матрицами ( статическими
и динамическими) при решении задач.
Матрицы, как и массивы, нужно вводить (выводить) поэлемент но. Блок-
схема ввода элементов матрицы x[n][m]изображена на рис. 6.3.
2
В данном случае массив указателей на float.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

188Глава 6. Статические и динамические матрицы
Рис. 6.3: Ввод элементов
матрицы Рис. 6.4: Блок-схема построчного вывода матрицы
При выводе матрицы элементы располагаются построчно, напри мер:
6 −9 7 13
5 8 3 8
3 7 88 33
55 77 88 37
Алгоритм построчного вывода элементов матрицы приведён на р ис. 6.4.
Ниже приведён текст программы на C++ввода-вывода статической матрицы.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t i , j , N , M, a [ 2 0 ] [ 2 0 ] ;
c o u t << " N = ";
c i n >>N ; / /Ввод количества строк
c o u t << " M = ";
c i n >>M; / /Ввод количества столбцов
c o u t << " Ввод матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ; / /Ввод очередного элемента матрицы
c o u t << "Вывод матрицы A "<< e n d l ;
f o r ( i = 0 ; i {
f o r ( j = 0 ; j c o u t <
c o u t < }
}
Цикл для построчного вывода матрицы можно записать и так.
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
При вводе матрицы элементы каждой строки можно разделять пр обелами, сим-
волами табуляции или Enter. Ниже представлены результаты работы програм-
мы.
Программирование на языке С++ в среде Qt Creator

6.3. Обработка матриц вС(С++) 189
N=4
M=5
Ввод матрицы A
1 2 3
5 4
3 6 7 8 9
1 2 3 4 5 6 7 8 9 0
Вывод матрицы A
1 2 3 5 4
3 6 7 8 9
1 2 3 4 5
6 7 8 9 0
Далее на примерах решения практических задач будут рассмот рены основ-
ные алгоритмы обработки матриц и их реализация в C++. Перед этим давайте
вспомним некоторые свойства матриц (рис. 6.5):
• если номер строки элемента совпадает с номером столбца ( i= j), это озна-
чает, что элемент лежит на главной диагонали матрицы;
• если номер строки превышает номер столбца ( i > j), то элемент находится
ниже главной диагонали;
• если номер столбца больше номера строки ( i < j), то элемент находится
выше главной диагонали.
• элемент лежит на побочной диагонали, если его индексы удов летворяют
равенству i+ j= n− 1;
• неравенство i+ j < n −1характерно для элемента, находящегося выше
побочной диагонали;
• соответственно, элементу лежащему ниже побочной диагона ли соответству-
ет выражение i+ j > n −1.
Рис. 6.5: Свойства элементов матрицы
Задача 6.1. Найти сумму элементов матрицы, лежащих выше главной диагон а-
ли.
Алгоритм решения данной задачи (рис. 6.6) построен следующим образом: об-
нуляем ячейку для накапливания суммы (переменная s), затем с помощью двух
циклов (первый по строкам, второй по столбцам) просматрива ем каждый эле-
мент матрицы, но суммируем только в том случае, если этот эле мент находится
выше главной диагонали (при выполнении условия i < j).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

190Глава 6. Статические и динамические матрицы
Рис. 6.6: Блок-схема задачи 6.1 (ал-
горитм 1). Рис. 6.7: Блок-схема задачи 6.1 (ал-горитм 2).
Текст программы:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t s , i , j , n , m, a [ 2 0 ] [ 2 0 ] ;
c o u t << " N = ";
c i n >>n ;
c o u t << " M = ";
c i n >>m ;
c o u t << "Ввод матрицы A "<< e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
f o r ( s= i = 0 ; i f o r ( j = 0 ; j / / Если элемент лежит выше главной диагонали, то наращиваем сумм у.
i f ( j > i ) s+=a [ i ] [ j ] ;
c o u t << " S = "< }
На рис. 6.7 изображён ещё один алгоритм решения данной задач и. В нём про-
верка условия i < jне выполняется, но, тем не менее, в нём так же суммируются
элементы матрицы, находящиеся выше главной диагонали. В ну левой строке за-
данной матрицы необходимо сложить все элементы, начиная с п ервого. В первой
 все, начиная со второго, в i–й строке процесс начнётся с (i + 1) –го элемента
и так далее. Таким образом, внешний цикл работает от 0 до N−1, а второй от
i + 1 доM. Авторы надеются, что читатель самостоятельно составит прог рамму,
соответствующую описанному алгоритму.
Задача 6.2. Вычислить количество положительных элементов квадратной мат-
рицы, расположенных по её периметру и на диагоналях. Напомн им, что в квад-
ратной матрице число строк равно числу столбцов.
Прежде чем приступить к решению задачи, рассмотрим рисунок 6.8, на ко-
тором изображена схема квадратных матриц различной размер ности.
Из условия задачи понятно, что не нужно рассматривать все эл ементы за-
данной матрицы. Достаточно просмотреть первую и последнюю с троки, первый
Программирование на языке С++ в среде Qt Creator

6.3. Обработка матриц вС(С++) 191
Рис. 6.8: Рисунок к задаче 6.2.
и последний столбцы, а так же диагонали. Все эти элементы отм ечены на схеме,
причём чёрным цветом выделены элементы, обращение к которы м может про-
изойти дважды. Например, элемент с номером (0,0) принадлежит как к нулевой
строке, так и к нулевому столбцу, а элемент с номером (N −1, N −1) находится
в последней строке и последнем столбце одновременно. Кроме того, еслиN
число нечётное (на рисунке 6.8 эта матрица расположена слев а), то существу-
ет элемент с номером (N/ 2, N/ 2), который находится на пересечении главной и
побочной диагоналей. При нечётном значении N(матрица справа на рис. 6.8)
диагонали не пересекаются.
Итак, разобрав подробно постановку задачи, рассмотрим алг оритм её реше-
ния. Для обращения к элементам главной диагонали вспомним, что номера строк
этих элементов всегда равны номерам столбцов. Поэтому, есл и параметрiизме-
няется циклически от 0 до N−1, то A[i][i]  элемент главной диагонали.
Воспользовавшись свойством, характерным для элементов по бочной диагонали,
получим: i+ j+ 1 = N−→ j= N −i− 1,
следовательно, для i= 0 ,1 , . . . , N −1элемент А[i][N-i-1]  элемент побочной
диагонали. Элементы, находящиеся по периметру матрицы зап исываются сле-
дующим образом: А[0][i] нулевая строка, А[N-1][i] последняя строка и
соответственно А[i][0] нулевой столбец, А[i][N-1] последний столбец.
Текст программы решения задачи с пояснениями приведён дале е.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t k , i , j , N , a [ 2 0 ] [ 2 0 ] ;
c o u t << " N = ";
c i n >>N ;
c o u t << " Ввод матрицы A " << e n d l ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

192Глава 6. Статические и динамические матрицы
f o r( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
/ / k  количество положительных элементов матрицы,
/ / расположенных по её периметру и на диагоналях.
f o r ( i =k = 0 ; i {
i f( a [ i ] [ i ] > 0 ) k++; / /Элемент лежит на главной диагонали.
i f ( a [ i ] [ N −i− 1 ] > 0 ) k++; / /Элемент лежит на побочной диагонали.
} f o r ( i = 1 ; i {
i f( a [ 0 ] [ i ] > 0 ) k++; / /Элемент находится в нулевой строке.
i f ( a [ N −1 ] [ i ] > 0 ) k++; / /Элемент находится в последней строке.
i f ( a [ i ] [ 0 ] > 0 ) k++; / /Элемент находится в нулевом столбце.
i f ( a [ i ] [ N −1 ] > 0 ) k++; / /Элемент находится в последнем столбце.
}
/ / Элемент, находящийся на пересечении диагоналей, подсчита н дважды,
/ / надо уменьшить вычисленное значение k на один.
i f ( ( N% 2 ! = 0 )&&(a [ N / 2 ] [ N/ 2 ] > 0 ) ) k −−;
c o u t << " k = "< }
Задача 6.3. Проверить, является ли заданная квадратная матрица единич ной.
Единичной называют матрицу, у которой элементы главной диаг онали  еди-
ницы, а все остальные  нули. Например,





1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1 





Решать задачу будем так. Предположим, что матрица единична я, и попыта-
емся доказать обратное. Если окажется, что хотя бы один диаг ональный элемент
не равен единице, или любой из элементов вне диагонали не раве н нулю, то мат-
рица единичной не является. Воспользовавшись логическими операциями языка
С(С++) , все эти условия можно соединить в одно и составить программ у, текст
которой приведён ниже.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t p r , i , j , N , ∗ ∗a ;
c o u t << " N = ";/ / Ввод размерности матрицы
c i n >>N ;
a= new i n t ∗[ N ] ; / /Создаём квадратную динамическую матрицу
f o r ( i = 0 ; i a [ i ] = new i n t [ N ] ;
c o u t << " Ввод элементов матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
/ / Предположим, что матрица единичная, и присвоим переменной p r значение 1 (истина).
/ / Если значение этой переменной при выходе из цикла не изменит ся, это будет означать,
/ / что матрица действительно единичная.
f o r ( p r = 1 , i = 0 ; i f o r ( j = 0 ; j Программирование на языке С++ в среде Qt Creator

6.3. Обработка матриц вС(С++) 193
i f( ( ( i ==j ) &&(a [ i ] [ j ] ! = 1 ) ) | | ( ( i ! = j ) &&(a [ i ] [ j ] ! = 0 ) ) )
/ / Если элемент лежит на главной диагонали и не равен единице или элемент лежит вне
/ / главной диагонали и не равен нулю, то
{
p r = 0 ; / /Переменной pr присвоить значение 0 (ложь), это будет означат ь,
break ;/ / что матрица единичной не является, и выйти из цикла.
}
/ / Проверка значения переменной pr и вывод соответствующего со общения.
i f ( p r ) c o u t << "Единичная матрица \ n ";
e l s e c o u t << "Матрица не является единичной \ n ";
}
Задача 6.4. Преобразовать исходную матрицу так, чтобы нулевой элемент каж-
дой строки был заменён средним арифметическим элементов эт ой строки.
Для решения данной задачи необходимо найти в каждой строке с умму эле-
ментов, которую разделить на их количество. Полученный рез ультат записать в
нулевой элемент соответствующей строки. Текст программы пр иведён далее.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t i , j , N ,M;
double S ,∗ ∗a ;
c o u t << " N = ";/ / Ввод размерности матрицы.
c i n >>N ;
c o u t << " M = ";
c i n >>M;
a= new double ∗[ N ] ; / /Создаём динамическую матрицу
f o r ( i = 0 ; i a [ i ] = new double [M ] ;
c o u t << " Ввод элементов матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
/ / Цикл по i завершается записью среднего значения в нулевой эл емент строки и наращиванием i.
f o r ( i = 0 ; i f o r ( S= j = 0 ; j S+=a [ i ] [ j ] ;
c o u t << " Преобразованная матрица A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
Задача 6.5. Задана матрица A(n, m ). Поменять местами её максимальный и
минимальный элементы.
Алгоритм решения этой задачи следующий: находим максимальны й элемент
матрицы (max)и его индексы (imax, jmax), а также минимальный (min)и его
индексы (imin, jmin) . После чего элементы A[imax][jmax]иA[imin][jmin]
поменяем местами. Для поиска максимального элемента и его и ндексов в пере-
менную maxзапишем A[0][0], в переменные imax,jmax (номер строки и столбца,
где находятся максимальный элемент) запишем 0. Затем в двой ном цикле (цикл
по переменной i по строкам, цикл по переменной j по столбцам) перебираем
все элементы, и каждый из них сравниваем с максимальным (со з начением пере-
менной max). Если текущий элемент массива оказывается больше максима льного,
то его переписываем в переменную max, а в переменную imax текущее значе-
ние индекса i, в переменную jmax текущее значение j. Поиск минимального
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

194Глава 6. Статические и динамические матрицы
элемента матрицы аналогичен и отличается только знаком опе рации сравнения.
Далее представлен текст программы решения задачи 6.5.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t i , j , i m a x , jmax , i m i n , j m i n , N ,M;
double min , max , b , ∗ ∗a ;
c o u t << " N = ";/ / Ввод размеров матрицы.
c i n >>N ;
c o u t << " M = ";
c i n >>M;
a= new double ∗[ N ] ; / /Создаём динамическую матрицу
f o r ( i = 0 ; i a [ i ] = new double [M ] ;
c o u t << " Ввод элементов матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
/ / Двойной цикл для поиска максимального, минимального элеме нтов и их индексов.
f o r ( max=min=a [ 0 ] [ 0 ] , i m a x=j m a x=i m i n=j m i n= i = 0 ; i f o r ( j = 0 ; j {
i f ( a [ i ] [ j ] >max ) {max=a [ i ] [ j ] ; i m a x= i ; j m a x= j ; }
i f ( a [ i ] [ j ] < min ) { min=a [ i ] [ j ] ; i m i n= i ; j m i n= j ; }
}
/ / Обмен двух элементов матрицы.
b=a [ i m a x ] [ j m a x ] ; a [ i m a x ] [ j m a x ] = a [ i m i n ] [ j m i n ] ;
a [ i m i n ] [ j m i n ] = b ;
/ / Вывод преобразованной матрицы.
c o u t << " Преобразованная матрица A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
Задача 6.6. Преобразовать матрицу A(m, n )так, чтобы строки с нечётными
индексами были упорядочены по убыванию, с чётными  по возрас танию.
В связи с нумерацией строк в C++с нуля необходимо помнить, что нулевая,
вторая, четвёртая строки упорядочиваются по убыванию, а перв ая, третья, пятая
и т.д.  по возрастанию. Алгоритм решения этой задачи сводится к тому, что
уже известный нам по предыдущей главе алгоритм упорядочива ния элементов
в массиве выполняется для каждой строки матрицы. Блок-схем а приведена на
рис. 6.9. Текст программы с комментариями приведён ниже.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t i , j , k , N ,M;
double b ,∗ ∗a ;
c o u t << " M = ";/ / Ввод размеров матрицы.
c i n >>M;
c o u t << " N = ";
c i n >>N ;
a= new double ∗[ N ] ; / /Создаём динамическую матрицу
f o r ( i = 0 ; i a [ i ] = new double [M ] ;
c o u t << " Ввод элементов матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j Программирование на языке С++ в среде Qt Creator

6.3. Обработка матриц вС(С++) 195
Рис. 6.9: Блок-схема алгоритма задачи 6.6.
c i n >>a [ i ] [ j ] ;
f o r ( i = 0 ; i i f ( i %2==0) / /Если строка чётна, то
{ / /упорядочиваем элементы строки по возрастанию,
f o r ( k = 1 ; k f o r ( j = 0 ; j i f ( a [ i ] [ j ] > a [ i ] [ j + 1 ] )
{
b=a [ i ] [ j ] ;a [ i ] [ j ] = a [ i ] [ j + 1 ] ;
a [ i ] [ j +1]=b ;
}
} e l s e / /иначе нечётные строки упорядочиваем по убыванию.
f o r ( k = 1 ; k f o r ( j = 0 ; j i f ( a [ i ] [ j ] < a [ i ] [ j + 1 ] )
{ b=a [ i ] [ j ] ;
a [ i ] [ j ] = a [ i ] [ j + 1 ] ;
a [ i ] [ j +1]=b ;
}
c o u t << " Преобразованная матрица A " << e n d l ;/ /Вывод преобразованной матрицы.
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

196Глава 6. Статические и динамические матрицы
Задача 6.7.Поменять местами элементы главной и побочной диагонали мат ри-
цы A(k, k ).
Алгоритм решения задачи следующий: перебираем все строки мат рицы (цикл
по переменной iот 0до k− 1в тексте программы), и в каждой строке меняем ме-
стами элементы, расположенные на главной и побочной диагон алях (вi-й строке
надо поменять местами элементы A[i][i]иА[i][k-i-1] ). Текст программы с
комментариями приведён далее.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t i , j , k ;
double b ,∗ ∗ a ;
c o u t << " k = ";/ / Ввод размера матрицы.
c i n >>k ;
a= new double ∗[ k ] ; / /Создаём динамическую матрицу
f o r ( i = 0 ; i a [ i ] = new double [ k ] ;
c o u t << " Ввод элементов матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
f o r ( i = 0 ; i { / / В каждой строке обмен между элементами, лежащими на главной и п обочной диагоналях.
b=a [ i ] [ i ] ; a [ i ] [ i ] = a [ i ] [ k −1− i ] ;
a [ i ] [ k −1− i ] = b ;
}
c o u t << " Преобразованная матрица A " << e n d l ;/ /Вывод преобразованной матрицы.
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
Задача 6.8. Заполнить матрицу A(6 ,6) числами от 1до 36следующим образом:







 1 2 3 4 5 6
12 11 10 9 8 7
13 14 15 16 17 18
24 23 22 21 20 19
25 26 27 28 29 30
36 35 34 33 32 31 







Последовательно построчно заполняем матрицу возрастающей арифметиче-
ской последовательностью 1,2 ,3 , . . ., 36. Чётные строки заполняем от нулевого
элемента к последнему, а нечётные  от последнего к нулевому . Текст програм-
мы приведён далее.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
i n t ∗ ∗a , n = 6 , k = 0 , i , j ;
a= new i n t ∗[ n ] ; / /Выделяем память для хранения матрицы
f o r ( i = 0 ; i a [ i ] = new i n t [ n ] ;
f o r ( i = 0 ; i i f ( i %2==0) / /Строки с чётными номерами заполняем возрастающей последов ательностью
f o r ( j = 0 ; j a [ i ] [ j ]=++k ;
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры197
e l s e/ /Строки с нечётными номерами заполняем возрастающей послед овательностью чисел
f o r ( j =n −1 ; j >=0; j −−)/ / справа налево
a [ i ] [ j ]=++k ;
c o u t << " Вывод матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
r e t u r n 0 ;
}
6.4 Решение некоторых задач линейной алгебры В этом параграфе рассмотрим использование матриц при решен ии таких за-
дач линейной алгебры, как сложение, вычитание и умножение м атриц, решение
систем линейных алгебраических уравнений, вычисление опр еделителя и обрат-
ной матрицы.
Задача 6.9. Заданы четыре матрицы вещественных чисел A(N , M ), B (N , M ),
C (M , N ), D (M , N ). Вычислить матрицу C= (( A+ B)(C −D))2
.
Суммой (разностью) матриц одинаковой размерности AиB называется мат-
рица C, элементы которой получаются сложением C
i,j =
A
i,j +
B
i,j (вычитанием
C i,j =
A
i,j −
B
i,j ) соответствующих элементов исходных матриц.
Напомним алгоритм умножения матриц на примере
0
@ a
0,0 a
0,1 a
0,2
a 1,0 a
1,1 a
1,2
a 2,0 a
2,1 a
2,2 1
A
·0
@
b
0,0 b
0,1
b 1,0 b
1,1
b 2,0 b
2,1 1
A
Воспользовавшись правилом строка на столбец, получим ма трицу:
0
@ c
0,0 c
0,1
c 1,0 c
1,1
c 2,0 c
2,1 1
A
=0
@
a
0,0 ·
b
0,0 +
a
0,1 ·
b
1,0 +
a
0,2 ·
b
2,0 a
0,0 ·
b
0,1 +
a
0,1 ·
b
1,1 +
a
0,2 ·
b
2,1
a 1,0 ·
b
0,0 +
a
1,1 ·
b
1,2 +
a
1,2 ·
b
2,1 a
1,0 ·
b
0,1 +
a
1,1 ·
b
1,1 +
a
1,2 ·
b
2,1
a 2,0 ·
b
0,0 +
a
2,1 ·
b
1,0 +
a
2,2 ·
b
2,0 a
2,0 ·
b
0,1 +
a
2,1 ·
b
1,1 +
a
2,2 ·
b
2,1 1
A
Произведением матриц A(N , M )и B(M , L )является матрица C(N , L ), каж-
дый элемент которой C
i,j вычисляется по формуле:
C i,j =M
−1
P
k =0 A
i,k B
k,j , где
i= 0 , N −1и j= 0 , L−1.
Операция умножения имеет смысл только в том случае, если кол ичество
строк левой матрицы совпадает с количеством столбцов право й. Кроме того,
A ·B 6
= B·A .
При решении задачи будем использовать динамические матриц ы и двойные
указатели. Напишем следующие функции.
•float **sum_m(float **A, float **B, int N, int M)  функция фор-
мирует матрицу, которая является суммой двух матриц. Здесь A, B  ука-
затели на исходные матрицы, N, M  количество строк и столбцов матриц,
функция возвращает указатель на сформированную матрицу, к оторая яв-
ляется суммой двух матриц AиB.
• float **minus_m(float **A, float **B, int N, int M )  функция фор-
мирует матрицу, которая является разностью двух матриц. Зд есьA, B 
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

198Глава 6. Статические и динамические матрицы
указатели на исходные матрицы,N, M  количество строк и столбцов мат-
риц, функция возвращает указатель на сформированную матри цу, которая
является разностью двух матриц AиB.
• float **product_m(float **A, float **B, int N, int M, int L) 
функция формирует матрицу, которая является произведение м двух мат-
риц. Здесь A, B  указатели на исходные матрицы. Матрица Aимеет N
строк и Mстолбцов, матрица Bимеет Mстрока и Lстолбцов, функ-
ция возвращает указатель на сформированную матрицу, котор ая является
произведением двух матриц AиB.
• float **create_m(int N, int M)  функция создаёт матрицу, в которой
будет Nстрок и Mстолбцов, осуществляет ввод элементов матрицы, функ-
ция возвращает указатель на сформированную матрицу.
• void output_m(float **A, int N, int M)  функция построчного выво-
да на экран матрицы A, которая имеет Nстрок и Mстолбцов.
Далее приведён текст программы с комментариями.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
/ / функция вычисления суммы двух матриц.
f l o a t ∗ ∗sum_m( f l o a t∗ ∗A , f l o a t ∗ ∗B , i n t N ,i n t M)
{ i n t i , j ;
f l o a t ∗ ∗temp ; / /указатель для хранения результирующей матрицы
temp= new f l o a t ∗[ N ] ; / /выделение памяти для хранения результирующей матрицы
f o r ( i = 0 ; i temp [ i ] = new f l o a t [M ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j temp [ i ] [ j ] =A [ i ] [ j ] +B [ i ] [ j ] ;
r e t u r n temp ;/ /Возвращаем матрицу как двойной указатель
}
/ / функция вычисления разности двух матриц.
f l o a t ∗ ∗minus_m ( f l o a t∗ ∗A , f l o a t ∗ ∗B , i n t N ,i n t M)
{ i n t i , j ;
f l o a t ∗ ∗temp ; / /указатель для хранения результирующей матрицы
temp= new f l o a t ∗[ N ] ; / /выделение памяти для хранения результирующей матрицы
f o r ( i = 0 ; i temp [ i ] = new f l o a t [M ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j temp [ i ] [ j ] =A [ i ] [ j ] −B [ i ] [ j ] ;
r e t u r n temp ;/ /Возвращаем матрицу как двойной указатель
}
/ / функция вычисления произведения двух матриц.
f l o a t ∗ ∗product_m ( f l o a t∗ ∗A , f l o a t ∗ ∗B , i n t N ,i n t M,i n t L )
{
i n t i , j , k ;
f l o a t ∗ ∗temp ; / /указатель для хранения результирующей матрицы
temp= new f l o a t ∗[ N ] ; / /выделение памяти для хранения результирующей матрицы
f o r ( i = 0 ; i temp [ i ] = new f l o a t [ L ] ;
/ / Вычисляем произведение двух матриц, последовательно форми руя все элементы матрицы
f o r ( i = 0 ; i f o r ( j = 0 ; j / / Элемент с индексами i, j скалярное произведение i-й строки матрицы A
f o r ( temp [ i ] [ j ] = k = 0 ; k temp [ i ] [ j ]+=A [ i ] [ k ] ∗B [ k ] [ j ] ;
r e t u r n temp ;/ /Возвращаем матрицу как двойной указатель
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры199
}
/ / функция создаёт динамическую матрицу вещественных чисел раз мерностиNна M,
/ / в этой же функции осуществляется и ввод элементов матрицы
f l o a t ∗ ∗c r e a t e _ m ( i n tN ,i n t M)
{
i n t i , j ;
f l o a t ∗ ∗temp ;
temp= new f l o a t ∗[ N ] ;
f o r ( i = 0 ; i temp [ i ] = new f l o a t [M ] ;
c o u t << " Ввод матрицы \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>temp [ i ] [ j ] ;
r e t u r n temp ;
}
/ / функция осуществляет построчный вывод матрицы A(N,M)
v o i d output_m ( f l o a t∗ ∗A , i n t N ,i n t M)
{
i n t i , j ;
/ / Цикл по строкам. По окончанию вывода всех элементов строки  переход на новую строку.
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
f l o a t ∗ ∗A , ∗ ∗B , ∗ ∗C , ∗ ∗D, ∗ ∗ r e s u l t ; / /указатели для хранения исходных и
результирующей матриц
i n t N ,M;
c o u t << " N = "; c i n >>N ; / /Ввод размерностей матрицы
c o u t << " M = "; c i n >>M;
/ / Выделение памяти и ввод матриц A, B, C, D, обращением к функции create_m.
A=c r e a t e _ m ( N ,M) ;
B=c r e a t e _ m ( N ,M) ;
C=c r e a t e _ m (M, N) ;
D=c r e a t e _ m (M, N) ;
/ / Вычисление результирующей матрицы.
r e s u l t =product_m ( product_m (sum_m( A , B , N ,M) , minus_m ( C , D , M, N) , N , M, N) , product_m
(sum_m( A , B , N ,M) , minus_m ( C , D , M, N) , N , M, N) , N , N , N) ;
output_m ( r e s u l t , N , N) ; / /Вывод результирующей матрицы.
r e t u r n 0 ;
}
Далее без комментариев приведена программа решения задачи 6.9 с помощью
динамических матриц и обычных указателей 3
. Рекомендуем читателям самосто-
ятельно разобраться с этой версией программы.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
f l o a t ∗sum_m( f l o a t∗A , f l o a t ∗B , i n t N ,i n t M)
{
i n t i , j ;
f l o a t ∗temp ;
temp= new f l o a t [ N∗M ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j temp [ i ∗M+ j ] =A [ i ∗M+ j ] +B [ i ∗M+ j ] ;
r e t u r n temp ;
3
Обращаем внимание читателя, что при использовании одинарн ых указателей обращение
к элементам матрицы происходит быстрее. При обработке матр иц большой размерности (более
1000000 элементов) имеет смысл использовать именно одинар ные указатели для хранения и
обработки матриц. Это позволит ускорить работу программ на 10-15%.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

200Глава 6. Статические и динамические матрицы
}
f l o a t ∗minus_m ( f l o a t∗A , f l o a t ∗B , i n t N ,i n t M)
{ i n t i , j ;
f l o a t ∗temp ;
temp= new f l o a t [ N∗M ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j temp [ i ∗M+ j ] =A [ i ∗M+ j ] −B [ i ∗M+ j ] ;
r e t u r n temp ;
} f l o a t ∗product_m ( f l o a t∗A , f l o a t ∗B , i n t N ,i n t M,i n t L )
{
i n t i , j , k ;
f l o a t ∗temp ;
temp= new f l o a t [ N∗L ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j f o r ( temp [ i ∗L+ j ] = k = 0 ; k temp [ i ∗L+ j ]+=A [ i ∗M+k ] ∗B [ k ∗L+ j ] ;
r e t u r n temp ;
}
f l o a t ∗c r e a t e _ m ( i n tN ,i n t M)
{
i n t i , j ;
f l o a t ∗temp ;
temp= new f l o a t [ N∗M ] ;
c o u t << " Ввод матрицы \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>temp [ i ∗M+ j ] ;
r e t u r n temp ;
}
v o i d output_m ( f l o a t∗A , i n t N ,i n t M)
{
i n t i , j ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
}
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{
f l o a t ∗A , ∗B , ∗C , ∗D, ∗r e s u l t ;
i n t N ,M;
c o u t << " N = "; c i n >>N ;
c o u t << " M = "; c i n >>M;
A=c r e a t e _ m ( N ,M) ;
B=c r e a t e _ m ( N ,M) ;
C=c r e a t e _ m (M, N) ;
D=c r e a t e _ m (M, N) ; r e s u l t =product_m ( product_m (sum_m( A , B , N ,M) , minus_m ( C , D , M, N) , N , M, N) ,
product_m (sum_m( A , B , N ,M) , minus_m ( C , D , M, N) , N , M, N) , N , N , N) ;
output_m ( r e s u l t , N , N) ; r e t u r n 0 ;
}
Задача 6.10. Решить систему линейных алгебраических уравнений.
При решении этой задачи напишем универсальную функцию реше ния систе-
мы линейных алгебраических уравнений методом Гаусса, а в фу нкцииmain()
просто вызовем эту функцию. Вспомним метод Гаусса.
Пусть дана система линейных алгебраических уравнений (СЛА У) сnнеиз-
вестными
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры201
    a
00 x
0 +
a
01 x
1 +
... +a
0n − 1x
n− 1 =
b
0 ,
a 10 x
0 +
a
11 x
1 +
... +a
1n − 1x
n− 1 =
b
1 ,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a n− 10 x
0 +
a
n− 11 x
1 +
... +a
n− 1n − 1x
n− 1 =
b
n − 1 (6.1)
Обозначим через A= 



a
00 a
01 ... a
0n − 1
a 10 a
11 ... a
1n − 1
... ... ... ...
a n− 10 a
n− 11 ... a
n− 1n − 1



матрицу коэффициентов
системы (6.1), через b= 



b
0
b 1
...
b n − 1



 столбец её свободных членов, и через
x=



 x
0
x 1
...
x n− 1



 столбец из неизвестных (искомый вектор). Тогда система (6
.1) может
быть записана в виде матричного уравнения Ax=b.
Наиболее распространённым приёмом решения систем линейны х уравнений
является алгоритм последовательного исключения неизвестн ых метод Гаусса .
При решении систем линейных алгебраических уравнений этим методом все-
возможные преобразования производят не над уравнениями си стемы (6.1), а над
так называемой расширенной матрицей системы, которая получается путём до-
бавления к основной матрице Aстолбца свободных членов b.
Первый этап решения системы уравнений, называемый прямым ходом мето-
да Гаусса , заключается в приведении расширенной матрицы (6.2) к треугольно-
му виду . Это означает, что все элементы матрицы (6.2) ниже главной д иагонали
должны быть равны нулю.
A′
= 



a
00 a
01 ... a
0n − 1 b
0
a 10 a
11 ... a
1n − 1 b
1
... ... ... ... ...
a n− 10 a
n− 11 ... a
n− 1n − 1 b
n − 1



(6.2)
На первом этапе необходимо обнулить элементы 0-го столбца р асширенной
матрицы
A′
= 






a
00 a
01 a
02 ... a
0n − 1 b
0
0 a
11 a
12 ... a
1n − 1 b
1
0 0 a
22 ... a
2n − 1 b
2
0 0 0 ... a
3n − 1 b
3
... ... ... ... ... ...
0 0 0 ... a
n− 1n − 1 b
n − 1







(6.3)
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

202Глава 6. Статические и динамические матрицы
Для этого необходимо из каждой строки (начиная с первой) выч есть нулевую,
умноженную на некоторое число M. В общем виде этот процесс можно записать
так:
1-я строка = 1-я строка – M× 0-я строка
2-я строка = 2-я строка – M× 0-я строка
. . .
i -я строка = i-я строка – M× 0-я строка
. . .
n − 1-я строка = n− 1-я строка – M× 0-я строка
Понятно, что преобразование элементов первой строки будет происходить по
формулам:
a 10 =
a
10 −
M a
00
a 11 =
a
11 −
M a
01
. . .
a 1i =
a
1i −
M a
0i
. . .
a 1n − 1 =
a
1n − 1 −
M a
0n − 1
b 1 =
b
1 −
M b
0
Так как целью данных преобразований является обнуление пер вого элемента
строки, то Mвыбираем из условия: a
10 =
a
10 −
M a
00= 0
. Следовательно, M=
a 10
a00 .
Элементы второй строки и коэффициент Mможно рассчитать аналогично:
a 20 =
a
20 −
M a
00
a 21 =
a
21 −
M a
01
. . .
a 2i =
a
2i −
M a
0i
. . .
a 2n − 1 =
a
2n − 1 −
M a
0n − 1
b 2 =
b
2 −
M b
0
a 20 =
a
20 −
M a
00= 0
⇒M =a
20
a00 .
Таким образом, преобразование элементов i–й строки будет происходить сле-
дующим образом:
a i0 =
a
i0 −
M a
00
a i1 =
a
i1 −
M a
01
. . .
a ii =
a
ii −
M a
0i
. . .
a in −1 =
a
in −1 −
M a
0n − 1
b i =
b
i −
M b
0.
Коэффициент Mдля i–й строки выбирается из условия a
i0 =
a
i0 −
M a
00= 0
и равен M=a
i0
a
00 .
После проведения подобных преобразований для всех строк ма трица (6.2)
примет вид
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры203
A′
= 




a
00 a
01 ... a
0n − 1 b
0
0 a
11 ... a
1n − 1 b
1
0 a
21 ... a
2n − 1 b
2
... ... ... ... ...
0 a
n− 11 ... a
n− 1n − 1 b
n − 1





.
Блок-схема обнуления первого столбца матрицы приведена на рис. 6.10.
Очевидно, что если повторить описанный выше алгоритм для сл едующих
столбцов матрицы (6.2), то в результате будет получена матр ица (6.3). Алгоритм
этого процесса изображён на рис. 6.11.
Рис. 6.10: Блок-схема обнуления первого столбца матрицы Рис. 6.11: Блок-схема алгоритма
преобразования расширенной мат-рицы к треугольному виду
Заметим, что если в матрице (6.2) на главной диагонали встре тится элемент
a k,k , равный нулю, то расчёт коэффициента
M=a
ik
akk для
k-й строки будет невоз-
можен. Избежать деления на ноль можно, избавившись от нулев ых элементов на
главной диагонали. Для этого перед обнулением элементов в k–м столбце необхо-
димо найти в нём максимальный по модулю элемент (среди распо ложенных ниже
a k,k ), запомнить номер строки, в которой он находится, и поменят
ь её местами с
k -й. Алгоритм, отображающий эти преобразования, приведён на р ис. 6.12.
В результате выполнения прямого хода метода Гаусса матрица (6.2) преобра-
зуется в матрицу (6.3), а система уравнений (6.1) будет имет ь следующий вид:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

204Глава 6. Статические и динамические матрицы
       a
00 x
0 +
a
01 x
1 +
a
20 x
2 +
... +a
0n − 1x
n− 1 =
b
0 ,
a 11 x
1 +
a
21 x
2 +
... +a
1n − 1x
n− 1 =
b
1 ,
a 22 x
2 +
... +a
2n − 1x
n− 1 =
b
2 ,
...
a n− 1n − 1x
n− 1 =
b
n − 1 (6.4)
Решение системы (6.4) называют обратным ходом метода Гаусса.
Последнее (n − 1)-е уравнение системы (6.4) имеет вид: a
n− 1n − 1x
n− 1 =
b
n − 1.
Тогда, если a
n− 1n − 1 6
= 0 , то x
n− 1 = b
n − 1
a
n − 1n − 1. В случае, если
a
n− 1n − 1 = 0

b n − 1 = 0
, то система (6.4), а следовательно, и система (6.1) имеют бес конечное
множество решений.
При a
n− 1n − 1 = 0
иb
n − 1 6
= 0 система (6.4), а значит и система (6.1), решения не
имеет. Предпоследнее (n − 2)-е уравнение системы (6.4) имеет вид a
n− 2n − 2x
n− 2+
a n− 2n − 1x
n− 1 =
b
n − 2.
Рис. 6.12: Блок-схема алгоритма пе-
рестановки строк расширенной мат-
рицы Рис. 6.13: Блок-схема алгоритма об-
ратного хода метода Гаусса
Значит, x
n− 2 = b
n − 2−
a
n − 2n − 1x
n− 1
a
n − 2n − 2 .
Следующее (n − 3)-е уравнение системы (6.4) будет выглядеть так:
a n− 3n − 3x
n− 3 +
a
n− 3n − 2x
n− 2 +
a
n− 3n − 1x
n− 1 =
b
n − 3.
Отсюда имеем
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры205
x
n− 3 = b
n − 3−
a
n − 3n − 2x
n− 2−
a
n − 3n − 1x
n− 1 a
n − 3n − 3 , x
n− 3 = b
n − 3− n
− 1
P
j = n− 2a
n − 3j x
j a
n − 3n − 3 .
Таким образом, формула для вычисления i-го значения xбудет иметь вид:
x i = b
i− n
− 1
P
j = i+1 a
ij x
j
aii .
Алгоритм, реализующий обратный ход метода Гаусса, представл ен в виде
блок-схемы на рис. 6.13.
Объединив блок-схемы, изображённые на рис. 6.11, 6.12 и 6.1 3, получим об-
щую блок-схему метода Гаусса (рис. 6.14). Блоки 2-6 содержа т последовательный
ввод данных, где n это размерность системы линейных алгебраических урав-
нений, а сама система задаётся в виде матрицы коэффициентов при неизвестных
A и вектора свободных коэффициентов b. Блоки 7-18 предусматривают прямой
ход метода Гаусса, а блоки 23-27  обратный. Для вывода резул ьтатов преду-
смотрено несколько блоков вывода. Если результат проверки условий 19 и 20
положительный, то выдаётся сообщение о том, что система име ет бесконечное
множество решений (блок 21). Если условие 19 выполняется, а 20  нет, то по-
является сообщение о том, что система не имеет решений (блок 22). Сами же
решения системы уравнений, представленные вектором x, вычисляются (блоки
23–26) и выводятся экран/печать (блок 27) только в случае не выполнения усло-
вия.
Теперь алгоритм решения СЛАУ, представленный на рис. 6.14, разобьём на
главную функцию main()и функцию решения СЛАУ методом Гаусса. В функ-
ции main() будет находиться ввод исходных данных, обращение к функции SLAU
и вывод вектора решения. Функция SLAUпредназначена для решения системы
линейных алгебраических уравнений методом Гаусса.
При написании функции следует учитывать следующее: в методе Гаусса из-
меняются матрица коэффициентов и вектор правых частей. Поэт ому, для того
чтобы их не испортить, в функции SLAUматрицу коэффициентов и вектор пра-
вых частей необходимо скопировать во внутренние переменны е, и в функции
обрабатывать внутренние переменные-копии.
Функция SLAUвозвращает значение 0, если решение найдено, −1 если систе-
ма имеет бесконечное множество решений, −2  если система не имеет решений.
Ниже приведено решение задачи 6.10 с подробными комментари ями.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t SLAU ( double ∗ ∗m a t r i c a _ a , i n tn ,double ∗m a s s i v _ b , double∗x )
/ / Функция SLAU возвращает значение типа int: 0, если решение най дено,−1  если система имеет
/ / бесконечное множество решений, −2  если система не имеет решений.
/ / Формальные параметры функции: n размерность системы,
/ / matrica_a  матрица коэффициентов СЛАУ,
/ / massiv_b  вектор правых частей, x решение СЛАУ, передаются как указатели.
{
i n t i , j , k , r ;
double c , M, max , s ;
/ / Матрица a  копия матрицы коэффициентов, массив b  копия век тора правых частей.
double ∗ ∗a , ∗b ;
a= new double ∗[ n ] ; / /Выделение памяти для a и b.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

206Глава 6. Статические и динамические матрицы
Рис. 6.14: Блок-схема алгоритма решения СЛАУ методом Гаусс а
f o r ( i = 0 ; i a [ i ] = new double [ n ] ;
b= new double [ n ] ;
/ / Вaзаписываем копию матрицы коэффициентов, в bкопию вектора правых частей.
f o r ( i = 0 ; i f o r ( j = 0 ; j a [ i ] [ j ] = m a t r i c a _ a [ i ] [ j ] ;
f o r ( i = 0 ; i b [ i ] = m a s s i v _ b [ i ] ;
/ / Прямой ход метода Гаусса: приводим матрицу a(копию матрицы коэффициентов СЛАУ)
/ / к диагональному виду.
f o r ( k = 0 ; k Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры207
{/ /Поиск максимального по модулю элемента в k-м столбце.
max=f a b s ( a [ k ] [ k ] ) ;
r=k ;
f o r ( i =k + 1 ; i i f ( f a b s ( a [ i ] [ k ] ) >max )
{ max=f a b s ( a [ i ] [ k ] ) ;
r= i ;
}
f o r ( j = 0 ; j { / /максимальный по модулю элемент) строки.
c=a [ k ] [ j ] ;
a [ k ] [ j ] = a [ r ] [ j ] ;
a [ r ] [ j ] = c ;
} c=b [ k ] ;
b [ k ] = b [ r ] ;
b [ r ] = c ; f o r ( i =k + 1 ; i { f o r (M=a [ i ] [ k ] / a [ k ] [ k ] , j =k ; j a [ i ] [ j ] −=M ∗a [ k ] [ j ] ;
b [ i ] −=M ∗b [ k ] ;
}
}
/ / Обратный ход метода Гаусса.
i f ( a [ n −1 ] [ n −1]==0) / /Если последний диагональный элемент равен 0 и
i f ( b [ n −1]==0) / /последний коэффициент вектора свободных членов равен 0,
r e t u r n −1 ; / /то система имеет бесконечное множество решений
e l s e r e t u r n −2 ; / /последний коэффициент вектора свободных членов не равен 0,
/ / система решений не имеет.
e l s e / /Последний диагональный элемент не равен 0, начинается обра тный ход метода Гаусса.
{ f o r ( i =n −1 ; i >=0; i −−)
{ f o r ( s = 0 , j = i + 1 ; j s+=a [ i ] [ j ] ∗x [ j ] ;
x [ i ] = ( b [ i ] −s ) / a [ i ] [ i ] ;
}
r e t u r n 0 ;
}
} i n t m a i n ( )
{
i n t r e s u l t , i , j , N ;
double ∗ ∗a , ∗b , ∗x ;
c o u t << " N = ";/ / Ввод размерности системы.
c i n >>N ;
a= new double ∗[ N ] ; / /Выделение памяти для матрицы правых частей и вектора свобод ных
членов.
f o r ( i = 0 ; i a [ i ] = new double [ N ] ;
b= new double [ N ] ;
x= new double [ N ] ;
c o u t << " Ввод матрицы A " << e n d l ;/ /Ввод матрицы правых частей
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
c o u t << " Ввод вектора B " << e n d l ;/ /и вектора свободных членов.
f o r ( i = 0 ; i c i n >>b [ i ] ;
/ / Вызов функции решения СЛАУ методом Гаусса. По значению resul t можно судить, сколько
/ / корней имеет система. Если result=0, то система имеет единс твенное решение, result=−1 
/ / система имеет бесконечное множество решений, result= −2  система не имеет решений.
r e s u l t =SLAU ( a , N , b , x ) ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

208Глава 6. Статические и динамические матрицы
i f( r e s u l t ==0)
{ / /Вывод массива решения.
c o u t << " M a s s i v X " < f o r ( i = 0 ; i c o u t < c o u t < }
e l s e i f ( r e s u l t == −1)
c o u t << " Бесконечное множество решений \ n " ;
e l s e i f ( r e s u l t == −2)
c o u t << " Нет решений \ n " ;
}
Задача 6.11. Найти обратную матрицу к квадратной матрице A(N , N ).
Один из методов вычисления обратной матрицыоснован на решении систем
линейных алгебраических уравнений. Пусть задана некотора я матрицаA:
A = 



a
00 a
01 a
02 ... a
0n − 1
a 10 a
11 a
12 ... a
1n − 1
... ... ... ... ...
a n− 10 a
n− 11 a
n− 12 ... a
n− 1n − 1



(6.5)
Необходимо найти матрицу A−
1
, которая является обратной к матрице A:
Y =A−
1
= 



y
00 y
01 y
02 ... y
0n − 1
y 10 y
11 y
12 ... y
1n − 1
... ... ... ... ...
y n − 10 y
n − 11 y
n − 12 ... y
n− 1n − 1



(6.6)
Матрица (6.6) будет обратной к матрице (6.5), если выполняе тся соотношение
A ·A −
1
= E, где E это единичная матрица, или более подробно:



 a
00 a
01 ... a
0n − 1
a 10 a
11 ... a
1n − 1
... ... ... ...
a n− 10 a
n− 11 ... a
n− 1n − 1







y
00 y
01 ... y
0n − 1
y 10 y
11 ... y
1n − 1
... ... ... ...
y n − 10 y
n − 11 ... y
n− 1n − 1



=
E (6.7)
Результат перемножения матриц из соотношения (6.7) можно п редставить по-
элементно в виде nсистем линейных уравнений. Умножение матрицы (6.5) на
нулевой столбец матрицы (6.6) даст нулевой столбец единичн ой матрицы:
        a
00 y
00 +
a
01 y
10 +
... +a
0n − 1y
n − 10 = 1
,
a 10 y
00 +
a
11 y
10 +
... +a
1n − 1y
n − 10 = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ai0 y
00 +
a
i1 y
10 +
... +a
in −1y
n − 10 = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a n− 10 y
00 +
a
n− 11 y
10 +
... +a
n− 1n − 1y
n − 10 = 0.
При умножении матрицы Aна первый столбец обратной матрицы получается
следующая система линейных алгебраических уравнений.
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры209
       a
00 y
01 +
a
01 y
11 +
... +a
0n − 1y
n − 11 = 0
,
a 10 y
01 +
a
11 y
11 +
... +a
1n − 1y
n − 11 = 1
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ai0 y
01 +
a
i1 y
11 +
... +a
in −1y
n − 11 = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a n− 10 y
01 +
a
n− 11 y
11 +
... +a
n− 1n − 1y
n − 11 = 0
Система, полученная в результате умножения матрицы (6.5) н аi-й столбец мат-
рицы (6.6), будет выглядеть следующим образом:
     a
00 y
0i +
a
01 y
1i +
... +a
0n − 1y
n − 1i = 0
,
a 10 y
0i +
a
11 y
1i +
... +a
1n − 1y
n − 1i = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ai0 y
0i +
a
i1 y
1i +
... +a
in −1y
n − 1i = 1
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a n− 10 y
0i +
a
n− 11 y
1i +
... +a
n− 1n − 1y
n − 1i = 0
Понятно, что n-я система будет иметь вид:
     a
00 y
0n − 1 +
a
01 y
1n − 1 +
... +a
0n − 1y
n − 1n − 1 = 0
,
a 10 y
0n − 1 +
a
11 y
1n − 1 +
... +a
1n − 1y
n − 1n − 1 = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a i0 y
0n − 1 +
a
i1 y
1n − 1 +
... +a
in −1y
n − 1n − 1 = 0
,
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a n− 10 y
0n − 1 +
a
n− 11 y
1n − 1 +
... +a
n− 1n − 1y
n − 1n − 1 = 1 .
Решением каждой из приведённых выше систем будет i-й столбец обратной
матрицы. Количество систем равно размерности обратной мат рицы. Для отыс-
кания решений систем линейных алгебраических уравнений мо жно воспользо-
ваться методом Гаусса.
Описанный алгоритм представлен в виде блок-схемы на рис. 6. 15. Блоки 2–5
отражают формирование вектора правых частей системы линейн ых алгебраи-
ческих уравнений. Если условие в блоке 3 выполняется и элеме нт находится на
главной диагонали, то он равен единице, все остальные элеме нты нулевые. В
блоке 6 происходит вызов подпрограммы для решения системы у равнений ме-
тодом Гаусса. В качестве параметров в эту подпрограмму пере даётся исходная
матрица A, сформированный в блоках 2–5 вектор свободных коэффициент овB,
размерность системы n. Вектор Xбудет решением i-й системы уравнений и,
следовательно, i-м столбцом искомой матрицы Y.
Как видно из блок-схемы, приведённой на рис. 6.15, при нахож дении обратной
матрицы понадобится функция SLAU, рассмотренная при решении задачи 6.10.
Ниже приведён текст программы с подробными комментариями р ешения зада-
чи 6.11. В функции main()будет находиться ввод исходной матрицы, обращение
к функции INVERSEдля вычисления обратной матрицы. Из функции INVERSE
будет осуществляться вызов функции SLAUдля решения системы линейных ал-
гебраических уравнений.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

210Глава 6. Статические и динамические матрицы
#i n c l u d e< i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
/ / Функция решения системы линейных алгебраических уравнений ме тодом Гаусса.
i n t SLAU ( double ∗ ∗m a t r i c a _ a , i n tn ,double ∗m a s s i v _ b , double∗x )
{ i n t i , j , k , r ;
double c , M, max , s ;
double ∗ ∗a , ∗b ;
a= new double ∗[ n ] ;
f o r ( i = 0 ; i a [ i ] = new double [ n ] ;
b= new double [ n ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j a [ i ] [ j ] = m a t r i c a _ a [ i ] [ j ] ;
f o r ( i = 0 ; i b [ i ] = m a s s i v _ b [ i ] ;
f o r ( k = 0 ; k { max=f a b s ( a [ k ] [ k ] ) ;
r=k ;
f o r ( i =k + 1 ; i i f ( f a b s ( a [ i ] [ k ] ) >max )
{
max=f a b s ( a [ i ] [ k ] ) ;r= i ;
}
f o r ( j = 0 ; j {
c=a [ k ] [ j ] ;
a [ k ] [ j ] = a [ r ] [ j ] ;
a [ r ] [ j ] = c ;
}
c=b [ k ] ;
b [ k ] = b [ r ] ;
b [ r ] = c ; f o r ( i =k + 1 ; i {
f o r (M=a [ i ] [ k ] / a [ k ] [ k ] , j =k ; j a [ i ] [ j ] −=M ∗a [ k ] [ j ] ;
b [ i ] −=M ∗b [ k ] ;
}
}
i f ( a [ n −1 ] [ n −1]==0)
i f ( b [ n −1]==0)
r e t u r n −1 ;
e l s e r e t u r n −2 ;
e l s e
{ f o r ( i =n −1 ; i >=0; i −−)
{ f o r ( s = 0 , j = i + 1 ; j s+=a [ i ] [ j ] ∗x [ j ] ;
x [ i ] = ( b [ i ] −s ) / a [ i ] [ i ] ;
} r e t u r n 0 ;
}
f o r ( i = 0 ; i d e l e t e [ ] a [ i ] ;
d e l e t e [ ] a ;
d e l e t e [ ] b ;
}
/ / Функция вычисления обратной матрицы
i n t INVERSE ( double∗ ∗a , i n t n ,double ∗ ∗y )
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры211
/ /Формальные параметры: a  исходная матрица, n  размерность м атрицы, y  обратная
матрица.
/ / Функция будет возвращать 0, если обратная матрица существует, -1  в противном случае.
{
i n t i , j , r e s ;
double ∗b , ∗x ;
/ / Выделение памяти для промежуточных массивов b и x.
b= new double [ n ] ;
x= new double [ n ] ;
f o r ( i = 0 ; i {
/ /Формирование вектора правых частей для нахождения i-го столбца матрицы.
f o r ( j = 0 ; j i f ( j== i )
b [ j ] = 1 ;
e l s e b [ j ] = 0 ;
/ / Нахождение i-го столбца матрицы путём решения СЛАУ Ax=bметодом Гаусса.
r e s =SLAU ( a , n , b , x ) ;
/ / Если решение СЛАУ не найдено, то невозможно вычислить обратн ую матрицу.
i f ( r e s ! = 0 )
break ;
e l s e
/ / Формирование i-го столбца обратной матрицы.
f o r ( j = 0 ; j y [ j ] [ i ] = x [ j ] ;
}
/ / Проверка существования обратной матрицы, если решение одно го из уравнений Ax=b не
/ / существует, то невозможно найти обратную матрицу, и функция INV ERSE вернёт значение−1.
i f ( r e s ! = 0 )
r e t u r n −1 ;
/ / Если обратная матрица найдена, то функция INVERSE вернёт зна чение 0,
/ / а обратная матрица будет возвращаться через указатель double **y.
e l s e r e t u r n 0 ;
} i n t m a i n ( )
{
i n t r e s u l t , i , j , N ;
double ∗ ∗a , ∗ ∗b ; / /Двойные указатели для хранения исходной a и обратной b матрицы .
c o u t << " N = ";/ / Ввод размера матрицы.
c i n >>N ;
a= new double ∗[ N ] ; / /Выделение памяти для матриц a и b.
f o r ( i = 0 ; i a [ i ] = new double [ N ] ;
b= new double ∗[ N ] ;
f o r ( i = 0 ; i b [ i ] = new double [ N ] ;
c o u t << " Ввод матрицы A " < f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
r e s u l t =INVERSE ( a , N , b ) ; / /Вычисление обратной матрицы.
i f ( r e s u l t ==0) / /Если обратная матрица существует, то вывести её на экран.
{ c o u t << " Обратная матрица " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t < } e l s e
/ / Если обратная матрица не существует, то вывести соответствую щее сообщение.
c o u t << " Нет обратной матрицы " << e n d l ;
}
Задача 6.12. Найти определитель квадратной матрицы A(N , N ).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

212Глава 6. Статические и динамические матрицы
Рис. 6.15: Блок-схема алгоритма вычисления обратной матри цы
Пусть задана матрица (6.2), необходимо вычислить её определитель. Для
этого матрицу необходимо преобразовать к треугольному вид у (6.3), а затем вос-
пользоваться свойством, известным из курса линейной алгеб ры, которое гласит,
что определитель треугольной матрицы равен произведению е ё диагональных
элементов: detA= n
− 1
Q
i =0 a
ii .
Программирование на языке С++ в среде Qt Creator

6.4. Решение некоторых задач линейной алгебры213
Преобразование матрицы (6.2) к виду (6.3) можно осуществить с помощью
прямого хода метода Гаусса. Алгоритм вычисления определите ля матрицы, изоб-
ражённый в виде блок-схемы на рис. 6.16, представляет собой алгоритм прямого
хода метода Гаусса, в процессе выполнения которого проводи тся перестановка
строк матрицы. Эта операция приводит к смене знака определи теля. В блок-
схеме момент смены знака отражён в блоках 8–9. В блоке 8 опред еляется, будут
ли строки меняться местами, и если ответ утвердительный, то в блоке 9 проис-
ходит смена знака определителя. В блоках 15–16 выполняется непосредственное
вычисление определителя путём перемножения диагональных элементов преоб-
разованной матрицы.
На листинге приведён текст программы решения задачи 6.12 с к омментария-
ми.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
/ / Функция вычисления определителя.
double d e t e r m i n a n t ( double∗ ∗m a t r i c a _ a , i n tn )
/ / Формальные параметры: m a t r i c a _ a исходная матрица, n размер матрицы,
/ / функция возвращает значение определителя (тип double.)
{ i n t i , j , k , r ;
double c , M, max , s , d e t = 1 ;
/ / a  копия исходной матрицы.
double ∗ ∗a ;
/ / Выделение памяти для матрицы a .
a= new double ∗[ n ] ;
f o r ( i = 0 ; i a [ i ] = new double [ n ] ;
/ / Вaзаписываем копию исходной матрицы.
f o r ( i = 0 ; i f o r ( j = 0 ; j a [ i ] [ j ] = m a t r i c a _ a [ i ] [ j ] ;
/ / Прямой ход метода Гаусса.
f o r ( k = 0 ; k {
max=f a b s ( a [ k ] [ k ] ) ;r=k ;
f o r ( i =k + 1 ; i i f ( f a b s ( a [ i ] [ k ] ) >max )
{
max=f a b s ( a [ i ] [ k ] ) ;r= i ;
}
/ / Если строки менялись местами, то смена знака определителя.
i f ( r ! = k ) d e t= −d e t ;
f o r ( j = 0 ; j {
c=a [ k ] [ j ] ;
a [ k ] [ j ] = a [ r ] [ j ] ;
a [ r ] [ j ] = c ;
}
f o r ( i =k + 1 ; i f o r (M=a [ i ] [ k ] / a [ k ] [ k ] , j =k ; j a [ i ] [ j ] −=M ∗a [ k ] [ j ] ;
}
/ / Вычисление определителя.
f o r ( i = 0 ; i d e t ∗=a [ i ] [ i ] ;
/ / Возврат определителя в качестве результата функции.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

214Глава 6. Статические и динамические матрицы
f o r( i = 0 ; i d e l e t e [ ] a [ i ] ;
d e l e t e [ ] a ;
r e t u r n d e t ;
}
i n t m a i n ( )
{
i n t r e s u l t , i , j , N ;
double ∗ ∗a , b ;
c o u t << " N = ";
c i n >>N ;
a= new double ∗[ N ] ;
f o r ( i = 0 ; i a [ i ] = new double [ N ] ;
/ / Ввод значений исходной матрицы.
c o u t << " Ввод матрицы A " << e n d l ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c i n >>a [ i ] [ j ] ;
/ / Обращение к функции вычисления определителя.
c o u t << " определитель = " < }
Рис. 6.16: Блок-схема алгоритма вычисления определителя
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения215
В этой главе читатель познакомился с обработкой статических и динами-
ческих матриц в C++, а также с использованием функций для решения задач
обработки динамических матриц.
6.5 Задачи для самостоятельного решения
6.5.1 Основные операции при работе с матрицами
Разработать программу на языке С++для решения следующей задачи.
1. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• наименьший элемент;
• сумму положительных элементов;
• количество простых чисел, расположенных на диагоналях ма трицы.
Для заданной матрицы A(n × n) и матрицы того же типа и размерности
C (n × n) найти значение выражения B= 2 ·A + BT
.
2. В двумерном массиве C, состоящем из n× nцелых чисел, вычислить:
• сумму элементов;
• количество нечётных элементов;
• минимальное простое число среди элементов, расположенны х на глав-
ной диагонали.
Для заданной матрицы C(n × n) и матрицы того же типа и размерности
B (n × n) найти значение выражения A= ( B−C)·C T
3. В двумерном массиве B, состоящем из m×m целых чисел, вычислить:
• индексы наибольшего элемента;
• количество отрицательных элементов;
• среднее геометрическое среди простых чисел, расположенн ых на по-
бочной диагонали.
Для заданной матрицы размерности B(n × n) найти значение выражения
A = 3 ·B +BT
4. В двумерном массиве A, состоящем из n× m вещественных чисел, вычис-
лить: • сумму элементов;
• произведение ненулевых элементов;
• два наибольших значения матрицы.
Для заданной матрицы A(n × m )и матрицы того же типа и размерности
C (n × m)найти значение выражения B= 2 ·A + 1
3
·
C
5. В двумерном массиве B, состоящем из n× m вещественных чисел, вычис-
лить: • произведение элементов;
• сумму положительных элементов;
• два наименьших значения среди элементов расположенных по пери-
метру матрицы.
Для заданной матрицы B(n × m)и матрицы того же типа, но другой
размерности C(m ×n) найти значение выражения A= 3 ·B ·C .
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

216Глава 6. Статические и динамические матрицы
6. В двумерном массивеA, состоящем из n× nцелых чисел, вычислить:
• наименьший элемент;
• количество чётных чисел;
• сумму положительных элементов, которые представляют собо й воз-
растающую последовательность цифр.
Для заданной матрицы A(n × n) и матрицы того же типа и размерности
C (n × n) найти значение выражения B=A2
− CT
7. В двумерном массиве C, состоящем из n× nцелых чисел, вычислить:
• индексы наименьшего элемента;
• сумму квадратов отрицательных элементов;
• минимальное простое число среди элементов, расположенны х в за-
штрихованной части матрицы (рис. 6.17).
Для заданной матрицы C(n × n) и матрицы того же типа и размерности
B (n × n) найти значение выражения A= ( BT
+ C)2
Рис. 6.17: Рис. 6.18:
8. В двумерном массиве B, состоящем из n× nцелых чисел, вычислить:
• среднее арифметическое элементов;
• наименьший чётный элемент;
• количество чисел-палиндромов, расположенных в заштрихо ванной ча-
сти матрицы (рис. 6.18).
Для заданной матрицы B(n × n) и матрицы того же типа и размерности
C (n × n) найти значение выражения A= 1
2
·
B +C2
9. В двумерном массиве C, состоящем из n× nцелых чисел, вычислить:
• среднее геометрическое элементов;
• наибольший нечётный элемент;
• количество составных чисел среди элементов, расположенн ых в за-
штрихованной части матрицы (рис. 6.19).
Для заданной матрицы C(n × n) найти значение выражения A= C+CT
.
10. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• индексы наименьшего элемента;
• среднее арифметическое нечётных чисел;
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения217
Рис. 6.19: Рис. 6.20: Рис. 6.21: Рис. 6.22:
• количество положительных элементов, которые представля ют собой
убывающую последовательность цифр.
Для заданной матрицы A(n × n) найти значение выражения B= 1
5
·
A 2
.
11. В двумерном массиве B, состоящем из n× nвещественных чисел, вычис-
лить: • среднее арифметическое элементов;
• элемент наиболее отличающийся от среднего арифметическог о.
Отразить заданную матрицу относительно побочной диагонал и.
Для матрицы B(n × n) и матрицы того же типа и размерности C(n × n)
найти значение выражения A= 2 ·B −CT
.
12. В двумерном массиве C, состоящем из n× nцелых чисел, вычислить:
• среднее геометрическое элементов;
• элемент наименее отличающийся от среднего геометрическог о;
• количество положительных элементов с чётной суммой цифр, распо-
ложенных в заштрихованной части матрицы (рис. 6.20)
Для матрицы C(n × n) и матрицы того же типа и размерности B(n × n)
найти значение выражения A= ( B−C)·(B +C).
13. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• наименьший элемент и его индексы;
• среднее арифметическое положительных чётных элементов;
• произведение простых чисел-палиндромов, расположенных в заштри-
хованной части матрицы (рис. 6.21).
Для заданной матрицы A(n × n) и матрицы того же типа и размерности
C (n × n) найти значение выражения B=A2
− C2
.
14. В двумерном массиве C, состоящем из n× nцелых чисел, вычислить:
• наибольший элемент и его индексы;
• среднее арифметическое элементов, расположенных на диаг оналях
матрицы.
Сформировать новую матрицу A(n × n), каждый элемент которой будет
равен сумме цифр элемента матрицы C(n × n). Для матриц A(n × n) и
C (n × n) найти значение выражения B= ( A+ C)2
.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

218Глава 6. Статические и динамические матрицы
15. В двумерном массивеB, состоящем из m×m целых чисел, вычислить:
• произведение элементов;
• индексы наибольшего чётного элемента;
• сумму чисел-палиндромов, расположенных вне диагоналей м атрицы.
Для заданной матрицы размерности B(n × n) и матрицы того же типа
и размерности C(n × n) найти значение выражения A= C·B −BT
.
16. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• среднее арифметическое элементов;
• наименьший нечётный элемент, расположенный в заштрихова нной ча-
сти матрицы (рис. 6.22).
Сформировать новую матрицу B(n × n), каждый элемент которой равен
значению матрицы A(n × n), цифры которого записаны в обратном порядке.
Для матриц A(n × n) и B(n × n) найти значение выражения B=A+ C2
.
17. В двумерном массиве A, состоящем из n× m целых чисел, вычислить:
• сумму элементов;
• количество ненулевых элементов, расположенных по периме тру мат-
рицы;
• среднее геометрическое чисел, в представлении которых вс е цифры
различные.
Для заданной матрицы A(n × m )и матрицы того же типа и размерности
C (n × m)найти значение выражения B= 2 ·A − 3·C .
18. В двумерном массиве B, состоящем из n× m целых чисел, вычислить:
• произведение элементов;
• сумму элементов, расположенных вне периметра матрицы;
• наименьшее число, состоящее из одинаковых цифр. Для заданной матрицы B(n × m)и матрицы того же типа, но другой
размерности C(m ×k) найти значение выражения A= B·C .
19. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• среднее геометрическое элементов;
• индексы наибольшего чётного элемента, расположенного в з аштрихо-
ванной части матрицы (рис. 6.23).
Сформировать новую матрицу B(n × n), каждый элемент которой ра-
вен значению матрицы A(n × n) в восьмеричной системе счисления. Найти
значение выражения C= 3 ·A 2
.
20. В двумерном массиве B, состоящем из n× nцелых чисел, вычислить:
• сумму квадратов элементов;
• количество совершённых чисел, расположенного в заштрихо ванной ча-
сти матрицы (рис. 6.24).
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения219
Рис. 6.23: Рис. 6.24: Рис. 6.25: Рис. 6.26:
Сформировать новую матрицу A(n × n), каждый элемент которой равен
количеству делителей соответствующего значения матрицы B(n × n). Для
матриц A(n × n) и B(n × n) найти значение выражения C=BT
− A2
.
21. В двумерном массиве A, состоящем из n× nцелых чисел, вычислить:
• наименьшее абсолютное значение элементов;
• произведение ненулевых элементов, расположенного в зашт рихован-
ной части матрицы (рис. 6.25).
Сформировать новую матрицу B(n × n), каждый элемент которой равен
количеству цифр в соответствующем элементе матрицы A(n × n). Найти
значение выражения C=BT
·A .
22. В двумерном массиве B, состоящем из n× nцелых чисел, вычислить:
• произведение ненулевых элементов;
• наибольшее абсолютное значение элементов, расположенног о в за-
штрихованной части матрицы (рис. 6.26).
Сформировать новую матрицу C(n × n), каждый элемент которой ра-
вен значению матрицы B(n × n) в пятеричной системе счисления. Найти
значение выражения A= B·B T
.
23. В двумерном массиве C, состоящем из n× m вещественных чисел, вычис-
лить:
• сумму модулей элементов;
• количество нулевых элементов, расположенных вне перимет ра матри-
цы;
• два наибольших положительных значения.
Для заданной матрицы C(n × m)и матрицы того же типа, но другой
размерности B(m ×k) найти значение выражения A= C·B .
24. В двумерном массиве B, состоящем из n× nвещественных чисел, вычис-
лить:
• сумму квадратов элемента;
• индексы первого нулевого элемента матрицы;
• два наибольших значения, расположенных вне периметра мат рицы;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

220Глава 6. Статические и динамические матрицы
Для заданной матрицыB(n × n) найти значения выражений A= B·B T
и C =BT
·B .
25. В двумерном массиве A, состоящем из n× n вещественных чисел вычислить:
• произведение квадратов элемента;
• индекс последнего нулевого элемента матрицы;
• два наименьших значения, расположенных вне диагоналей ма трицы.
Из элементов заданной матрицы A(n × n) сформировать верхнетреуголь-
ную матрицу Vи нижнетреугольную матрицу U. Проверить равенство
A = V·U .
6.5.2 Работа со строками и столбцами матрицы Разработать программу на языке С++для решения следующей задачи.
1. Задана матрица целых чисел A(n × m ). Сформировать массив B(m ), в кото-
рый записать среднее арифметическое элементов каждого сто лбца задан-
ной матрицы. Вывести номера строк матрицы, в которых находи тся более
двух простых чисел .
2. Задана матрица вещественных чисел B(n × m). Сформировать массив
A (n ), в который записать среднее геометрическое положительных элемен-
тов каждой строки заданной матрицы. Определить количество столбцов,
упорядоченных по возрастанию.
3. Задана матрица целых чисел A(n × n). Все простые числа , расположенные
на побочной диагонали, заменить суммой цифрмаксимального элемента
соответствующей строки матрицы. Сформировать массив B(k ), в который
записать произведения элементов нечётных строк заданной м атрицы.
4. В матрице целых чисел X(n × n) поменять местами диагональные элементы,
упорядоченных по убыванию строк. Сформировать массив Y(k ), в который
записать суммы элементов чётных столбцов заданной матрицы .
5. Задана матрица целых чисел A(n × n). Максимальный элемент каждого
столбца заменить суммой цифрмаксимального элемента матрицы. Сфор-
мировать массив B(n ), в который записать количество чётных элементов в
каждой строке заданной матрицы.
6. Задана матрица целых чисел B(n × m). Максимальный элемент каждого
столбца заменить суммой цифрмодуля минимального элемента матрицы.
Сформировать массив A(n ), в который записать количество нечётных эле-
ментов в каждой строке заданной матрицы.
7. Задана матрица целых чисел A(n × n). Сформировать массив B(n ) из мак-
симальных элементов столбцов заданной матрицы. Вывести ин дексы чисел-
палиндромов, которые находятся на диагоналях матрицы.
8. Задана матрица вещественных чисел P(n × m). Сформировать массив R(k )
из номеров столбцов матрицы, в которых есть хотя бы один ноль . Найти
строку с максимальной суммой элементов и поменять её с перво й строкой.
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения221
9. Задана матрица вещественных чиселC(k × m). Сформировать вектор D(k )
из средних арифметических положительных значений строк ма трицы, и
вектор G(n ) из номеров столбцов, которые представляют собой знакочере-
дующийся ряд.
10. В каждом столбце матрицы вещественных чисел P(k × m)заменить ми-
нимальный элемент суммой положительных элементов этого же столбца.
Сформировать вектор D(n ) из номеров строк, представляющих собой зна-
кочередующийся ряд.
11. В матрице целых чисел A(n × m )обнулить строки, в которых более двух про-
стых чисел . Сформировать массив D(m )из минимальных значений столб-
цов матрицы.
12. В матрице вещественных чисел P(n × m)найти и вывести номера столб-
цов, упорядоченных по убыванию элементов. Сформировать ма ссивR(n )
из максимальных значений строк матрицы.
13. В матрице вещественных чисел D(n × m)найти и вывести номера строк,
упорядоченных по возрастанию элементов. Сформировать мас сивC(m ×2)
из номеров минимальных и максимальных значений столбцов ма трицы.
14. В матрице вещественных чисел P(n × m)найти и вывести номера столбцов,
упорядоченных по возрастанию. Сформировать вектор R(n × 2) из номеров
минимальных и максимальных значений строк матрицы.
15. В матрице вещественных чисел D(n × m)найти и вывести номера строк,
упорядоченных по убыванию. Сформировать вектор C(m ×2) из макси-
мальных и минимальных значений столбцов матрицы.
16. В матрице вещественных чисел X(n × n) найти максимальный и мини-
мальный элементы. Поменять местами элементы строки с макси мальным
значением и элементы столбца с минимальным значением.
17. Задана матрица целых чисел A(n × n). Сформировать массив B(n ), каж-
дый элемент которого равен количеству положительных элеме нтов с чёт-
ной суммой цифр в соответствующей строке матрицы. В столбцах матрицы
поменять местами наибольший и наименьший элементы.
18. Задана матрица целых чисел A(n × m). Сформировать массив B(m ), каж-
дый элемент которого равен количеству положительных чисел с суммой
цифр, кратной трём в соответствующем столбце матрицы. Найти строку с
максимальным произведением элементов.
19. Задана матрица целых чисел A(n × n). Все числа-палиндромы , расположен-
ные на главной диагонали, заменить суммой цифр модуля миним ального
элемента соответствующего столбца матрицы. Сформировать в екторD(n )
из произведений абсолютных ненулевых значений соответству ющих строк
матрицы.
20. Задана матрица целых чисел A(n × n). Поменять местами элементы на
диагоналях в столбцах, упорядоченных по возрастанию модул ей. Сформи-
ровать вектор B(n ), каждый элемент которого равен сумме составных зна-
чений в соответствующей строке матрицы.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

222Глава 6. Статические и динамические матрицы
21. Задана матрица целых чиселA(n × n). Минимальный элемент каждой стро-
ки заменить суммой цифр максимального простого элементаматрицы.
Сформировать вектор B(n ), каждый элемент которого  среднее геомет-
рическое ненулевых элементов в соответствующем столбце мат рицы.
22. Задана матрица целых чисел A(n × n). Максимальный элемент каждого
столбца заменить суммой цифр минимального простого элементаматри-
цы. Сформировать вектор B(n ), каждый элемент которого равен количе-
ству чётных элементов в соответствующей строке матрицы.
23. Задана матрица целых чисел A(n × n). Обнулить строки, в которых на
диагоналях нет чисел-палиндромов . Сформировать вектор B(n ), каждый
элемент которого равен количеству нечётных элементов в соо тветствующем
столбце матрицы.
24. Задана матрица вещественных чисел P(n × m). Найти столбец с минималь-
ным произведением элементов. Поменять местами элементы эт ого столбца
и элементы последнего столбца. Сформировать вектор R(n ) из сумм квад-
ратов соответствующих строк матрицы.
25. Задана матрица целых чисел A(n × m). В каждой строке заменить мак-
симальный элемент суммой цифрминимального элемента этой же строки.
Сформировать массив B(m ×2), пара элементов которого равна соответ-
ственно количеству чётных и нечётных чисел в соответствующе м столбце
матрицы.
6.5.3 Решение задач линейной алгебры Разработать программу на языке С++для решения следующей задачи.
1. Задана матрицы A(n × n) и B(n × n). Вычислить матрицу C= 2( A+ B−
1
) −
A T
·B .
2. Задан массив C(n ). Сформировать матрицы A(n × n) и B(n × n) по фор-
мулам: A
ij =
C

C
j,
B
i,j = A
i,j
max (A ).
Решить матричное уравнение X(A + E) = 3 B−E, где E единичная
матрица.
3. Даны массивы C(n ) и D(n ). Сформировать матрицы A(n × n) и B(n × n)
по формулам:
Aij =
C

D
j,
B
i,j = A
i,j
min (A ).
Решить матричное уравнение (2A − E)X =B+E, где E единичная
матрица.
4. Квадратная матрица A(n × n) называется ортогональной , еслиAT
= A−
1
.
Определить, является ли данная матрица ортогональной: 


 1 0
.42 0 .54 0 .66
0 .42 1 0 .32 0 .44
0 .54 0 .32 1 0 .22
0 .66 0 .44 0 .22 1 



.
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения223
5. Для матрицы
H=E− vv
T
|
v |2
, где
E единичная матрица, а v=    
1
0
1
1   
,
проверить свойство ортогональности: HT
= H−
1
.
6. Проверить, образуют ли базис векторы
f1 =    
1
− 2
1
1    
, f
2=    
2
− 1
1
− 1   
, f
3=    
5
− 2
− 3
1    
, f
4=    
1
− 1
1
− 1   
.
Если образуют, то найти координаты вектора x= [1 −1 3 −1]T
в
этом базисе. Для решения задачи необходимо показать, что оп ределитель
матрицы Fсо столбцами f
1,
f
2,
f
3,
f
4 отличен от нуля, а затем вычислить
координаты вектора xв новом базисе по формуле y= F−
1
·x .
7. Найти вектор xкак решение данной системы уравнений
   3
.75 x
1 −
0.28 x
2 + 0
.17 x
3 = 0
.75
2 .11 x
1 −
0.11 x
2 −
0.12 x
3 = 1
.11
0 .22 x
1 −
3.17 x
2 + 1
.81 x
3 = 0
.05 .
Вычислить модуль вектора x.
8. Вычислить скалярное произведение векторов xиy. Вектор y= |1 1 2 −3|,
а вектор xявляется решением СЛАУ:
     5
.7 x
1 −
7.8 x
2 −
5.6 x
3 −
8.3 x
4 = 2
.7
6 .6 x
1 + 13
.1 x
2 −
6.3 x
3 + 4
.3 x
4 =
−5.5
14 .7 x
1 −
2.8 x
2 + 5
.6 x
3 −
12.1 x
4 = 8
.6
8 .5 x
1 + 12
.7 x
2 −
23.7 x
3 + 5
.7 x
4 = 14
.7 .
9. Вычислить вектор X, решив СЛАУ
      4
.4 x
1 −
2.5 x
2 + 19
.2 x
3 −
10.8 x
4 = 4
.3
5 .5 x
1 −
9.3 x
2 −
14.2 x
3 + 13
.2 x
4 = 6
.8
7 .1 x
1 −
11.5 x
2 + 5
.3 x
3 −
6.7 x
4 =
−1.8
14 .2 x
1 + 23
.4 x
2 −
8.8 x
3 + 5
.3 x
4 = 7
.2 .
Найти Y=X ·X T
.
10. Вычислить вектор X, решив СЛАУ
   0
.34 x
1 + 0
.71 x
2 + 0
.63 x
3 = 2
.08
0 .71 x
1 −
0.65 x
2 −
0.18 x
3 = 0
.17
1 .17 x
1 −
2.35 x
2 + 0
.75 x
3 = 1
.28 .
Найти модуль вектора |2 X −3|.
11. Вычислить угол между векторами xиy= | − 1 5 −3|. Вектор xявляется
решением СЛАУ:   1
.24 x
1 + 0
.62 x
2 −
0.95 x
3 = 1
.43
2 .15 x
1 −
1.18 x
2 + 0
.57 x
3 = 2
.43
1 .72 x
1 −
0.83 x
2 + 1
.57 x
3 = 3
.88 .
12. Решив систему уравнений методом Гаусса:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

224Глава 6. Статические и динамические матрицы
    8
.2 x
1 −
3.2 x
2 + 14
.2 x
3 + 14
.8 x
4 =
−8.4
5 .6 x
1 −
12x
2 + 15
x
3 −
6.4 x
4 = 4
.5
5 .7 x
1 + 3
.6 x
2 −
12.4 x
3 −
2.3 x
4 = 3
.3
6 .8 x
1 + 13
.2 x
2 −
6.3 x
3 −
8.7 x
4 = 14
.3 .
Вычислить H=E−X X T
.
13. Решить СЛАУ A2
X =YT
, где A=    
2 1 5 2
5 2 2 6
2 2 1 2
1 3 3 1    
,
Y =|3 1 2 1 |.
14. Решить СЛАУ 2(AT
)2
X =Y, где A=    
2 1 5 2
5 2 2 6
2 2 1 2
1 3 3 1    
,
Y =   
3
1
2
1   
.
15. Заданы матрицы A(n × n) и B(n × n).
Найти определитель матрицы C=BT
·A .
16. Задан массив C(n ). Сформировать матрицы A(n × n) и B(n × n) по фор-
мулам: Aij =
C

C
j,
B
ij = A
ij
n
P
i =1 A
ii . Найти определитель
|2 E −A·B |.
17. Для матрицы I= 2 P−E, где E единичная матрица, а
P = 

26 −18 −27
21 15 21
12 8 13  
проверить свойство I2
= E. При помощи метода Гаусса решить СЛАУ I x=
| 1 1 1 |T
.
18. Квадратная матрица A(n × n) является симметричной , если для неё вы-
полняется свойство AT
= A. Проверить это свойство для матрицы



 1 0
.42 0 .54 0 .66
0 .42 1 0 .32 0 .44
0 .54 0 .32 1 0 .22
0 .66 0 .44 0 .22 1 



.
Вычислить A−
1
. Убедиться, что A·A −
1
= E.
19. Ортогональная матрица обладает следующими свойствами: • модуль определителя ортогональной матрицы равен 1;
• сумма квадратов элементов любого столбца ортогональной ма трицы
равна 1;
• сумма произведений элементов любого столбца ортогонально й матри-
цы на соответствующие элементы другого столбца равна 0.
Проверить эти свойства для матриц: 


−
2 3 .01 0 .12 −0.11
2 .92 −0.17 0 .11 0 .22
0 .66 0 .52 3 .17 2 .11
3 .01 0 .42 −0.27 −0.15 



,




2 2 .92 0 .66 3 .01
2 .92 −2 0 .11 0 .22
0 .66 0 .11 −2 2 .11
3 .01 0 .22 2 .11 −2



.
Программирование на языке С++ в среде Qt Creator

6.5. Задачи для самостоятельного решения225
20. Проверить, образуют ли базис векторы
f1 =    
0
.25
0 .333
0 .2
0 .1    
, f
2=    
0
.33
0 .25
0 .167
0 .143    
, f
3=    
1
.25
− 0.667
2 .2
3 .1    
, f
4=    

0.667
1 .333
1 .25
− 0.75    
.
Если образуют, то найти координаты вектора x= [1 1 1 1] T
в этом бази-
се. Для решения задачи необходимо показать, что определите ль матрицыF
со столбцами f
1,
f
2,
f
3,
f
4 отличен от нуля, а затем вычислить координаты
вектора xв новом базисе, решив СЛАУ F·y = x.
21. Решить СЛАУ: 


0
.42 0 .26 0 .33 −0.22
0 .74 −0.55 0 .28 −0.65
0 .88 0 .42 −0.33 0 .75
0 .92 0 .82 −0.62 0 .75 



·
X =   
1
1
1
0   
.
Для матрицы C=X ·X T
проверить условия ортогональности: C·C T
=
E иCT
·C =E.
22. Найти kA k
1 =
max m
P
j =1 |
a
ij |
и kA k
11 =
max m
P
i =1 |
a
ij |
для матрицы



 0
.75 0 .18 0 .63 −0.32
0 .92 0 .38 −0.14 0 .56
0 .63 −0.42 0 .18 0 .37
− 0.65 0 .52 0 .47 0 .27 




1
.
23. Найти kA k
111 =r
P
i,j a
2
i,j
для матрицы



 −
1.09 7 .56 3 .45 0 .78
3 .33 4 .45 −0.21 3 .44
2 .33 −4.45 0 .17 2 .21
4 .03 1 3 .05 0 .11 




1
.
24. Решить СЛАУ методом Гаусса     8
.2 x
1 −
3.2 x
2 + 14
.2 x
3 + 14
.8 x
4 =
−8.4
5 .6 x
1 −
12x
2 + 15
x
3 −
6.4 x
4 = 4
.5
5 .7 x
1 + 3
.6 x
2 −
12.4 x
3 −
2.3 x
4 = 3
.3
6 .8 x
1 + 13
.2 x
2 −
6.3 x
3 −
8.7 x
4 = 14
.3 .
Выполнить проверку A·x = b.
25. Задан массив H(k ). Сформировать матрицы B(k × k) и G(k × k) по форму-
лам
(B
ij =
H

H
j)
, G
ij = B
ij
min (B ).
Решить матричное уравнение (G +E)·X = 5 BT
− E, где E единичная
матрица.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

Глава 7
Организация ввода-вывода вC++
7.1 Форматированный ввод-вывод в C++
В этом параграфе мы вернёмся к рассмотренным ранее конструкциямcinи
cout , и рассмотрим возможности их использования для организаци иформати-
рованного ввода -вывода .
Для управления вводом-выводом в C++используются:
• флаги форматного ввода-вывода;
• манипуляторы форматирования.
7.1.1 Использование флагов форматного ввода-вывода Флаги позволяют включить или выключить один из параметров вывода на
экран. Для установки флага вывода используется следующая конструкция языка
C++ :
cout.setf(ios::flag)
Для снятия флага применяют конструкцию
cout.unsetf(ios::flag)
здесь flag имя конкретного флага.
Если при выводе необходимо установить несколько флагов, то можно вос-
пользоваться арифметической операцией или ( |). В этом случае конструкция
языка C++будет такой:
cout.setf(ios::flag1|ios::flag2|ios::flag3)
В данном случае flag1,flag2 ,flag3  имена устанавливаемых флагов вы-
вода. В таблице 7.1 приведены некоторые флаги форматного выводас примерами
их использования.

7.1. Форматированный ввод-вывод вC++ 227
Таблица 7.1: Некоторые флаги форматного вывода
Флаг Описание Пример использования1 Результат
right Выравнивание по правой
границе int
r=−25;
cout. setf ( ios :: right ) ;
cout.width(15);
cout<< "r="< r=-25 left Выравнивание по левой
границе (по умолчанию) double r=−25.45;
cout. setf ( ios :: left ) ;
cout.width(50);
cout<< "r="< r=-25.45 boolalpha Вывод логических
величин в текстовом виде
(true ,false ) boola=true ;
cout< cout. setf ( ios :: boolalpha);
cout< true
dec Вывод величин в
десятичной системе
счисления (по
умолчанию) int r=−25;
cout<< "r="< oct Вывод величин в
восьмеричной системе
счисления intp=23;
// Отменить, установленный
по умолчанию, вывод в
десятичной системе счисления
cout. unsetf ( ios :: dec) ;
// Установить вывод в
восьмеричной системе счисления
cout. setf ( ios :: oct) ;
cout<< "p="< p=27 hex Вывод величин в
шестнадцатеричной
системе счисления intp=23;
// Отменить, установленный
по умолчанию, вывод в
десятичной системе счисления
cout. unsetf ( ios :: dec) ;
// Установить вывод
в шестнадцатеричной
системе счисления
cout. setf ( ios :: hex);
cout<< "p="< p=17 showbase Выводить индикатор
основания системы
счисления intp=23;
cout. unsetf ( ios :: dec) ;
cout. setf ( ios :: hex| ios :: showbase);
cout<< "p="< p=0x17 uppercase Использовать прописные
буквы в
шестнадцатеричных
цифрах intp=29;
cout. unsetf ( ios :: dec) ;
cout. setf ( ios :: hex| ios :: uppercase);
cout<< "p="< p=1D showpos Выводить знак + для
положительных чисел int p=29;
cout. setf ( ios :: showpos);
cout<< "p="< p=+29 scientific Экспоненциальная форма
вывода вещественных
чисел double p=146.673;
cout. setf ( ios :: scientific ) ;
cout<< "p="< p=1.466730e+002
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

228Глава 7. Организация ввода-вывода вC++
Таблица 7.1  продолжение Флаг Описание Пример использования Результат
fixed Фиксированная форма
вывода вещественных
чисел (по умолчанию) doublep=146.673;
cout. setf ( ios :: fixed ) ;
cout<< "p="< p=146.673
Флаги удобно использовать в тех случаях, когда следует изме нить параметры
всех последующих операторов ввода-вывода. Использование б ольшого количе-
ства флагов для управления одним или несколькими оператора ми ввода-вывода
не совсем удобно, потом все установленные флаги придётся от ключать.
Ещё одним способом форматирования является использование манипулято-
ров непосредственно в конструкциях cinиcout .
7.1.2 Использование манипуляторов форматирования Манипуляторы встраиваются непосредственно в операторы ввода-вывода. C
одним из манипуляторов ( endl) читатель уже встречался начиная с первой главы
книги. В таблице 7.2 приведены основные манипуляторы форма тирования с при-
мерами их использования. Для корректного использования вс ех манипуляторов
необходимо подключить библиотеку: #include
Таблица 7.2: Некоторые манипуляторы форматирования
Манипулятор Описание Пример использования Результат
setw(n) Определяет ширину
поля вывода в n
символов int r=253;
cout. setf ( ios :: fixed ) ;
cout<< "r="< r= 253 setprecision(n) Определяет
количество цифр
(n − 1) в дробной
части числа double h=1234.6578;
cout. setf ( ios :: fixed ) ;
cout<< "h="< cout< cout< h=1234.658 dec Перевод числа в
десятичную систему
(по умолчанию) int r=0253;
cout<< "r="< oct Перевод числа в
восьмеричную
систему intr=253;
cout<< "r="< hex Перевод числа в
шестнадцатеричную
систему intr=253;
cout<< "r="< right Выравнивание по
правой границе intr=−25;
cout.width(15);
cout<< "r="< cout< r=-25
1 cout.width(n) устанавливает ширину поля вывода, подробнее об этом в п. 7.1 .2
Программирование на языке С++ в среде Qt Creator

7.1. Форматированный ввод-вывод вC++ 229
Таблица 7.2  продолжение Манипулятор Описание Пример использования Результат
left Выравнивание по
левой границе (по
умолчанию) intr=−25;
cout.width(15);
cout<< "r="< cout< r=-25 boolalpha Вывод логических
величин в текстовом
виде (
true,false ) boola=true ;
cout< noboolalpha Вывод логических ве-
личин в числовом ви-
де (1, 0) bool a=true ;
cout< showpos Выводить знак +
для положительных
чисел int p=29;
cout<< "p="< endl; p=+29
noshowpos Не выводить знак
+ для положи-
тельных чисел int p=29;
cout<< "p="<<
noshowpos< p=29
uppercase Использовать про-
писные буквы в
шестнадцатеричных
цифрах int p=253;
cout<< "p="< uppercase< p=FD
nouppercase Использовать строч-
ные буквы в шестна-
дцатеричных цифрах int p=253;
cout<< "p="< cout< p=fd showbase Выводить индикатор
основания системы
счисления int p=253;
cout<< "p="< < p=0XFD noshowbase Не выводить индика-
тор основания систе-
мы счисления int p=253;
cout<< "p="< cout< p=FD setfill(c) Установить символ с
как заполнитель cout<< "x="< setw(10)< cout< cout<<( oat)1/7< cout<< "x="< cout< cout< cout<<( oat)1/7< x=!!!!0.1429
x=0.1429!!!!
scientific Экспоненциальная
форма вывода веще-
ственных чисел double p=146.673;
cout<< "p="< endl;
p=1.466730e+002 fixed Фиксированная
форма вывода
вещественных чисел
(по умолчанию) cout<< "p="<<fixed< Кроме того, управлять шириной поля вывода можно с помощью оп ераторов:
• cout.width(n)  устанавливает ширину поля вывода  nпозиций;
• cout.precision(m)  определяетmцифр в дробной части числа.
2
Ещё один пример приведён при использовании манипулятора setfill
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

230Глава 7. Организация ввода-вывода вC++
В п. 7.1.1 и 7.1.2 были рассмотрены основные возможности фор матированного
ввода-вывода. При использовании конструкций cinиcout фактически проис-
ходит ввод-вывод в текстовый файл. При вводе текстовым файлом является
клавиатура ПК, при выводе в качестве текстового файла высту пает экран дис-
плея, cinиcout фактически являются именами потоков3
, которые отвечают за
ввод и вывод в текстовый файл. Поэтому многие рассмотренные возможности
форматированного ввода-вывода будут использоваться и при обработке тексто-
вых файлов.
Существует два основных типа файлов: текстовыеидвоичные . Файлы позво-
ляют пользователю считывать большие объёмы данных непосред ственно с диска,
не вводя их с клавиатуры.
7.2 Работа с текстовыми файлами в C++
Текстовыми называют файлы, состоящие из любых символов. Они органи-
зуются по строкам, каждая из которых заканчивается символом конец строки.
Конец самого файла обозначается символом конец файла. Пр и записи инфор-
мации в текстовый файл, просмотреть который можно с помощью любого тек-
стового редактора, все данные преобразуются к символьному т ипу и хранятся в
символьном виде.
Для работы с файлами используются специальные типы данных, н азываемые
потоками 4
. Поток ifstream служит для работы с файлами в режиме чтения.
Поток ofstream служит для работы с файлами в режиме записи. Для работы с
файлами в режиме как чтения, так и записи служит поток iofstream.
В программах на C++при работе с текстовыми файлами необходимо подклю-
чать библиотеки iostreamиfstream .
Для того, чтобы записать данные в текстовый файл , необходимо:
1. Описать переменную типа ofstream.
2. Открыть файл с помощью функции open.
3. Вывести информацию в файл.
4. Закрыть файл.
Для того, чтобы считать данные из текстового файла , необходимо:
1. Описать переменную типа ifstream.
2. Открыть файл с помощью функции open.
3. Считать информацию из файла, при считывании каждой порци и данных
необходимо проверять достигнут ли конец файла.
4. Закрыть файл.
7.2.1 Запись информации в текстовый файл Для того, чтобы начать работать с текстовым файлом, необход имо описать
переменную типа ofstream. Например, с помощью оператора
3
Подробнее о текстовых потоках речь пойдёт в п. 7.2
4 Вообще говоря, потоки являются классами, которым будет пос вящена специальная глава.
Программирование на языке С++ в среде Qt Creator

7.2. Работа с текстовыми файлами вC++ 231
ofstream F;5
будет создана переменная Fдля записи информации в файл . На следующем
этапе файл необходимо открыть для записи. В общем случае оператор открытия
потока будет иметь вид: F.open( "file", mode);
Здесь F переменная, описанная как ofstream,file  имя файла на диске,
mode  режим работы с открываемым файлом.
Файл может быть открыт в одном из следующих режимов:
ios::in  открыть файл в режиме чтения данных , этот режим является ре-
жимом по умолчанию для потоков ifstream;
ios::out  открыть файл в режиме записи данных (при этом информация в
существующем файле уничтожается), этот режим является режи мом по
умолчанию для потоков ofstream;
ios::app  открыть файл в режиме записи данных в конец файла;
ios::ate  передвинуться в конец уже открытого файла;
ios::trunc  очистить файл, это же происходит в режиме ios::out;
ios::nocreate  не выполнять операцию открытия файла, если он не существу-
ет 6
;
ios::noreplace  не открывать существующий файл.
Параметр modeможет отсутствовать, в этом случае файл открывается в режим е
по умолчанию для данного потока 7
.
После удачного открытия файла (в любом режиме) в переменной Fбудет хра-
ниться true, в противном случае false. Это позволит проверять корректность
операции открытия файла.
Открыть файл (в качестве примера возьмём файл abc.txt) врежиме записи
можно одним из следующих способов: / / Первый способ.
o f s t r e a m F ;
F . o p e n ( " a b c . t x t " , i o s : : o u t ) ;
/ / Второй способ,
/ / режим ios::out является режимом по умолчанию для потока ofstream
o f s t r e a m F ;
F . o p e n ( " a b c . t x t " )
/ / Третий способ объединяет описание переменной типа поток
/ / и открытие файла в одном операторе
o f s t r e a m F ( " a b c . t x t ", i o s : : o u t ) ;
После открытия файла в режиме записи будет создан пустой фай л, в кото-
рый можно будет записывать информацию. Если нужно открыть фа йл, чтобы
в него что-либо дописать, то в качестве режима следует использовать значение
ios::app .
После открытия файла в режиме записи, в него можно писать точ но также,
как и на экран, только вместо стандартного устройства вывод аcout необходимо
указать имя открытого для записи файла.
5 Далее термин поток будет использоваться для указания пер еменной, описанной как
ofstream ,ifstream ,iofstream , а термин файл для указания реального файла на диске.
6 При открытии файла в режиме ios::in происходит как раз обратн ое, если файл не суще-
ствует, он создаётся 7ios::in  для потоков ifstream,ios::out  для потоков ofstream.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

232Глава 7. Организация ввода-вывода вC++
Например, для записи в потокFпеременной aоператор вывода будет иметь
вид:
F< Для последовательного вывода в потокGпеременных b,c и dоператор вывода
станет таким:
G< Закрытие потока осуществляется с помощью оператора:
F.close();
В качестве примера рассмотрим следующую задачу.
Задача 7.1. Создать текстовый файл abc.txtи записать туда nвещественных
чисел.
Текст программы с комментариями:
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
i n t i , n ; double a ;
o f s t r e a m f ; / /Описывает поток для записи данных в файл.
f . o p e n ( " a b c . t x t " ) ;/ /Открываем файл в режиме записи,
/ / режим ios::out устанавливается по умолчанию.
c o u t << " n = "; c i n >>n ; / /Ввод количества вещественных чисел.
f o r ( i = 0 ; i {
c o u t << " a = "; c i n >>a ; / /Ввод очередного числа.
i f ( i f < e l s e f <
} f . c l o s e ( ) ; / /Закрытие потока.
r e t u r n 0 ;
}
Обратите внимание, что в текстовый файл записываются не толь ко веще-
ственные числа, но и символы табуляции. Таким образом, в кон це файла после
последнего числа находится символ табуляции. По этой причи не может возник-
нуть проблема при чтении информации (п. 7.2.2), так как симв ол табуляции
будет интерпретирован как вещественное число. Чтобы этого избежать в про-
грамме была применена следующая конструкция:
if (i Здесь реализована проверка ввода последнего числа. После н его символ та-
буляции отсутствует.
В результате работы программы будет создан текстовый файл abc.txt, ко-
торый можно просмотреть средствами обычного текстового ре дактора (рис. 7.1–
7.2).
7.2.2 Чтение информации из текстового файла
Для того, чтобы прочитать информацию из текстового файла , необходимо
описать переменную типа ifstream. После этого файл необходимо открыть для
Программирование на языке С++ в среде Qt Creator

7.2. Работа с текстовыми файлами вC++ 233
Рис. 7.1: Процесс работы программы к задаче 7.1. Ввод исходн ых данных.
Рис. 7.2: Текстовый файлabc.txt, созданный программой к задаче 7.1.
чтения с помощью оператора open. Если переменную назвать F, то первые два
оператора будут такими:
ifstream F;
F.open("abc.txt", ios::in); 8
После открытия файла в режиме чтения, из него можно считывать инфор-
мацию точно так же, как и с клавиатуры, только вместо стандар тного устройства
ввода cinнеобходимо указать имя потока, из которого будет происходить чтение
данных.
Например, для чтения из потока Fв переменную aоператор ввода будет иметь
вид:
F>>a;
Для последовательного ввода из потока Gв переменные b, с и dоператор
ввода станет таким:
G>>b>>c>>d;
8Указание режима ios::inможно, конечно, опустить, ведь для потока ifstreamзначение
ios::in является значением по умолчанию, тогда оператор open можно будет записать так
F.open( "abc.txt" );
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

234Глава 7. Организация ввода-вывода вC++
Два числа в текстовом файле считаются разделёнными, если меж ду ними
есть хотя бы один из символов: пробел, табуляция, символ кон ца строки.
Хорошо, если программисту заранее известно, сколько и каких значений хра-
нится в текстовом файле. Однако часто просто известен тип зн ачений, храня-
щихся в файле, при этом количество значений в файле может быт ь различным.
При решении подобной проблемы необходимо считывать значен ия из файла по
одному, а перед каждым считыванием проверять, достигнут ли конец файла.
Для проверки, достигнут или нет конец файла, служит функция
F.eof();
Здесь F имя потока, функция возвращает логическое значение: true если
достигнут конец файла, если не достигнут функция возвращае т значениеfalse.
Следовательно, цикл для чтения содержимого всего файла мож но записать
так. w h i l e ( ! F . e o f ( ) ) / /Организован цикл, условием окончания цикла
/ / является достижение конца файла, в этом случае F.eof()вернётtrue.
{ F>>a ; / /Чтение очередного значения из потока Fв переменную a.
...
<обработка значения переменной a>
}
Рассмотрим следующую задачу.
Задача 7.2. В текстовом файле abc.txtхранятся вещественные числа (рис. 7.2),
вывести их на экран и вычислить их количество.
Текст программы с комментариями приведён ниже.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i f s t r e a m f ; / /Поток для чтения.
f l o a t a ;i n t n = 0 ;
f . o p e n ( " a b c . t x t " ) ;/ /Открываем файл в режиме чтения.
i f ( f ) / /Если открытие файла прошло корректно, то
{ w h i l e ( ! f . e o f ( ) ) / /Организован цикл, выполнение цикла
/ / прервётся, когда будет достигнут конца файла.
{
f >>a ; / /Чтение очередного значения из потока fв переменную a.
c o u t < n++; / /Увеличение количества считанных чисел.
} f . c l o s e ( ) ; / /Закрытие потока.
c o u t << " n = "< }
e l s e c o u t << " Файл не найден " << e n d l ;/ /Если открытие файла прошло некорректно, то
/ / вывод сообщения, об отсутствии такого файла.
r e t u r n 0 ;
}
Результат работы программы к задаче 7.2:
3.14159 2.789 -21.14 543.89 -90.1 n=5
Программа работает корректно, если текстовый файл abc.txtбыл создан с
помощью программы к задаче 7.1. Предположим, что файл созда вался в тек-
Программирование на языке С++ в среде Qt Creator

7.2. Работа с текстовыми файлами вC++ 235
стовом редакторе, и пользователь ввёл после последней цифр ы символ пробела,
табуляции или перехода на новую строку. Тогда результат буд ет таким:
3.14159 2.789 -21.14 543.89 -90.1 -90.1 n= 6
Происходит это потому, что после чтения последней цифры из п отока ко-
нец файла не достигнут, оператор цикла выполняется ещё один раз, значение
переменной nувеличивается на единицу, а так как значение переменной aне из-
менилось, то выводится повторно. Один из способов решения д анной проблемы
может быть таким: w h i l e ( ! f . e o f ( ) )
{
f >>a ;i f ( ! f . e o f ( ) ) / /Проверяем, достигнут ли конец файла, если нет  печатаем знач ение a
{ c o u t < n++;
}
}
Если количество вещественных чисел, записанных в файл, изв естно заранее,
то текст программы можно переписать следующим образом:
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ i f s t r e a m f ;
f l o a t a ;i n t i , n = 5 ;
f . o p e n ( " a b c . t x t " ) ;
i f ( f )
{ f o r ( i = 1 ; i <=n ; f >>a , c o u t < f . c l o s e ( ) ;
}
e l s e c o u t << " Файл не найден " << e n d l ;
r e t u r n 0 ;
}
Существует возможность открывать файл с данными таким обра зом, чтобы
в него можно было дописывать информацию . Рассмотрим эту возможность на
примере решения следующей задачи.
Задача 7.3. В файлеabc.txt(рис. 7.2) хранится массив вещественных чисел,
дописать в файл этот же массив, упорядочив его по возрастани ю.
Алгоритм решения задачи очень простой. Считываем в массив да нные из
текстового файла, упорядочиваем массив, дописываем его в э тот же файл.
Для чтения данных из файла описываем поток ifstream, открываем его в
режиме чтения и последовательно, пока не достигнем конца фа йла, считываем
все элементы в массив. Сортировку проведём методом пузырьк а. Обратите вни-
мание, что поток нужно открыть так, чтобы была возможность д описать в конец
файла упорядоченный массив.
Текст программы с комментариями приведён ниже.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

236Глава 7. Организация ввода-вывода вC++
i n tm a i n ( )
{
i f s t r e a m f ; / /Поток для чтения.
o f s t r e a m g ; / /Поток для записи.
f l o a t ∗a , b ;
a= new f l o a t [ 1 0 0 ] ;
i n t i , j , n = 0 ;
f . o p e n ( " a b c . t x t " , i o s : : i n ) ; / /Открываем файл в режиме чтения.
i f ( f )
{ w h i l e ( ! f . e o f ( ) )
{
f >>a [ n ] ;
n++;
}
/ / Сортировка массива.
f o r ( i = 0 ; i f o r ( j = 0 ; j i f ( a [ j ] > a [ j + 1 ] )
{ b=a [ j ] ;
a [ j ] = a [ j + 1 ] ;
a [ j +1]=b ;
}
f . c l o s e ( ) ; / /Закрываем поток для чтения.
g . o p e n ( " a b c . t x t " , i o s : : a p p ) ; / /Открываем поток для того, чтобы дописать данные.
g<< " \ n " ;/ / Запись в файл символа конца строки
f o r ( i = 0 ; i i f ( i e l s e g<
g . c l o s e ( ) ; / /Закрытие файла.
}
e l s e c o u t << " Файл не найден " << e n d l ;
d e l e t e [ ] a ;
r e t u r n 0 ;
}
Содержимое файла abc.txtпосле запуска программы к задаче 7.3
3.14159 2.798 -21.14 543.89 -90.1
-90.1 -21.14 2.798 3.14159 543.89
7.3 Обработка двоичных файлов
Если в файле хранятся только числа или данные определённой с труктуры,
то для хранения таких значений удобно пользоваться двоичны ми файлами. В
двоичных файлах информация считывается и записывается в виде блоков опре-
делённого размера, в них могут храниться данные любого вида и структуры.
Порядок работы с двоичными и текстовыми файлами аналогичен . Для того,
чтобы записать данные в двоичный файл , необходимо:
1. Описать файловую переменную с помощью оператора FILE *filename;
Здесь filename  имя переменной, где будет храниться указатель на файл.
2. Открыть файл с помощью функции fopen.
3. Записать информацию в файл с помощью функции fwrite.
4. Закрыть файл с помощью функции fclose.
Для того, чтобы считывать данные из двоичного файла , необходимо:
Программирование на языке С++ в среде Qt Creator

7.3. Обработка двоичных файлов237
1. Описать переменную типаFILE *.
2. Открыть файл с помощью функции fopen.
3. Считать необходимую информацию из файла с помощью функци иfread ,
при считывании информации следить за тем, достигнут ли коне ц файла.
4. Закрыть файл с помощью функции fclose.
Рассмотрим основные функции, необходимые для работы с двои чными файлами.
Для открытия файла предназначена функция:
FILE *fopen(const *filename, const char *mode); где,filename  стро-
ка, в которой хранится полное имя открываемого файла, mode строка, которая
определяет режим работы с файлом; возможны следующие значен ия:
rb  открыть двоичный файл в режиме чтения;
wb  создать двоичный файл для записи, если файл существует, т о его
содержимое очищается.
ab  создать или открыть двоичный файл для добавления информа ции
в конец файла;
rb+  открыть существующий двоичный файл в режиме чтения и запис и;
wb+  открыть двоичный файл в режиме чтения и записи, существующ ий
файл очищается;
ab+  двоичный файл открывается или создаётся для исправления су-
ществующей информации и добавления новой в конец файла.
Функция fopenвозвращает в файловой переменной NULLв случае неудачного
открытия файла.
После открытия файла, в указателе содержится адрес 0-го бай та файла. По
мере чтения или записи значение указателя смещается на счит анное (записанное)
количество байт. Текущее значение указателя  номер байта, начиная с которого
будет происходить операция чтения или записи.
Для закрытия файла предназначена функция
int fclose(FILE *filename);
Она возвращает 0 при успешном закрытии файла и NULLв противном случае.
Для удаления файлов существует функция
int remove(const char *filename);
Эта функция удаляет с диска файл с именем filename. Удаляемый файл
должен быть закрыт. Функция возвращает ненулевое значение , если файл не
удалось удалить.
Для переименования файлов предназначена функция
int rename(const char *oldfilename, const char *newfilename);
здесь первый параметр  старое имя файла, второй  новое. Воз вращает 0
при удачном завершении программы.
Чтение из двоичного файла осуществляется с помощью функции
fread (void *ptr, size, n, FILE *filename)
Эта функция считывает из файла filenameв массивptr nэлементов размера
size . Функция возвращает количество считанных элементов. Посл е чтения из
файла указатель файла смещается на n*sizeбайт.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

238Глава 7. Организация ввода-вывода вC++
Запись в двоичный файлосуществляется с помощью функции
fwrite (const void *ptr, size, n, FILE *filename);
Функция записывает в файл filenameиз массива ptr nэлементов размера
size . Функция возвращает количество записанных элементов. Пос ле записи ин-
формации в файл, указатель файла смещается на n*sizeбайт.
Для контроля достижения конца файла есть функция
int feof(FILE * filename);
Она возвращает ненулевое значение, если достигнут конец фа йла.
Рассмотрим использование двоичных файлов на примере решен ия двух стан-
дартных задач.
Задача 7.4. Создать двоичный файл abc.dat, куда записать целое число nиn
вещественных чисел.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
FILE ∗f ; / /Описание файловой переменной.
i n t i , n ; double a ;
f =f o p e n ( " a b c . d a t " ," w b " ) ;/ /Создание двоичного файла в режиме записи.
c o u t << " n = "; c i n >>n ; / /Ввод числа n.
f w r i t e (&n , s i z e o f(i n t ) , 1 , f ) ; / /Запись числа в двоичный файл.
f o r ( i = 0 ; i {
c o u t << " a = "; c i n >>a ; / /Ввод очередного вещественного числа.
f w r i t e (& a , s i z e o f(double ) , 1 , f ) ; / /Запись числа в двоичный файл.
}
f c l o s e ( f ) ; / /Закрыть файл.
r e t u r n 0 ;
}
Задача 7.5. Вывести на экран содержимое созданного в задаче 7.4 двоично го
файла abc.dat .
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ FILE ∗f ; / /Описание файловой переменной.
i n t i , n ; double ∗a ;
f =f o p e n ( " a b c . d a t " ," r b " ) ;/ /Открыть существующий двоичный файл в режиме чтения.
f r e a d (&n , s i z e o f(i n t ) , 1 , f ) ; / /Читать из файла целое число в переменную n.
c o u t << " n = "< a= new double [ n ] ;/ /Выделение памяти для массива из nчисел.
f r e a d ( a , s i z e o f(double ) , n , f ) ; / /Чтение nвещественных чисел из файла в массив a.
f o r ( i = 0 ; i c o u t < f c l o s e ( f ) ; / /Закрыть файл.
r e t u r n 0 ;
}
Двоичный файл  последовательная структура данных, после открытия фай-
ла доступен первый байт. Можно последовательно считывать и з файла или за-
писывать их в него. Допустим, необходимо считать пятнадцат ое, а затем первое
число, хранящееся в файле. С помощью последовательного доступаэто можно
сделать следующим образом.
Программирование на языке С++ в среде Qt Creator

7.3. Обработка двоичных файлов239
FILE∗f ;
i n t i , n ; double a ;
f =f o p e n ( " f i l e . d a t " ," r b " ) ;
f o r ( i = 0 ; i < 1 5 ; f r e a d (& a , s i z e o f(double ) , 1 , f ) , i ++) ;
f c l o s e ( f ) ;
f =f o p e n ( " f i l e . d a t " ," r b " ) ;
f r e a d (& a , s i z e o f(double ) , 1 , f ) ;
f c l o s e ( f ) ;
Как видно, такое чтение чисел из файла, а затем повторное отк рытие файла 
не самый удачный способ. Гораздо удобнее использовать функцию перемещения
указателя файла к заданному байту:
int fseek(FILE *F, long int offset, int origin);
Функция устанавливает указатель текущей позиции файла F, в соответствии
со значениями начала отсчёта originи смешения offset. Параметр offsetра-
вен количеству байтов, на которые будет смещён указатель фа йла относительно
начала отсчёта, заданного параметром origin. Если значение offsetположи-
тельно, то указатель файла смещается вперёд, если отрицате льно  назад. Па-
раметр originдолжен принимать одно из следующих значений, определённых
в заголовке stdio.h:
SEEK_SET  отсчёт смещения offsetвести с начала файла;
SEEK_CUR  отсчёт смещения offsetвести с текущей позиции файла;
SEEK_END  отсчёт смещения offsetвести с конца файла.
Функция возвращает нулевое значение при успешном выполнен ии операции и
ненулевое, если возник сбой при выполнении смещения. Функция fseekфактически реализует прямой доступ к любому значению
в файле. Необходимо только знать месторасположение (номер байта) значения
в файле. Рассмотрим использование прямого доступа в двоичн ых файлах на
примере решения следующей задачи.
Задача 7.6. В созданном в задаче 7.4 двоичном файле abc.datпоменять местами
наибольшее и наименьшее из вещественных чисел. Алгоритм решения задачи состоит из следующих этапов:
1. Чтение вещественных чисел из файла в массив a.
2. Поиск в массиве aмаксимального ( max) и минимального ( min) значения и
их номеров ( imax,imin ).
3. Перемещение указателя файла к максимальному значению и з аписьmin.
4. Перемещение указателя файла к минимальному значению и за письmax.
Ниже приведён текст программы решения задачи с комментария ми.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ FILE ∗f ; / /Описание файловой переменной.
i n t i , n , i m a x , i m i n ;
double ∗a , max , min ;
f =f o p e n ( " a b c . d a t " ," r b + " ) ;/ / Открыть файл в режиме чтения и записи.
f r e a d (&n , s i z e o f(i n t ) , 1 , f ) ; / /Считать из файла в переменную n количество элементов в
файле.
a= new double [ n ] ;/ /Выделить память для хранения вещественных чисел,
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

240Глава 7. Организация ввода-вывода вC++
/ /эти числа будут хранится в массиве a.
f r e a d ( a , s i z e o f(double ) , n , f ) ; / /Считать из файла в массив a вещественные числа.
/ / Поиск максимального, минимального элемента в массиве a, и и х индексов.
f o r ( i m a x=i m i n = 0 , max=min=a [ 0 ] , i = 1 ; i {
i f ( a [ i ] >max )
{
max=a [ i ] ;i m a x= i ;
} i f ( a [ i ] < min )
{
min=a [ i ] ;i m i n= i ;
}
}
/ / Перемещение указателя к максимальному элементу.
f s e e k ( f , s i z e o f(i n t )+i m a x ∗s i z e o f (double ) ,SEEK_SET) ;
/ / Запись min вместо максимального элемента файла.
f w r i t e (&min , s i z e o f(double ) , 1 , f ) ;
/ / Перемещение указателя к минимальному элементу.
f s e e k ( f , s i z e o f(i n t )+i m i n ∗s i z e o f (double ) ,SEEK_SET) ;
/ / Запись max вместо минимального элемента файла.
f w r i t e (&max , s i z e o f(double ) , 1 , f ) ;
/ / Закрытие файла.
f c l o s e ( f ) ;
/ / Освобождение памяти, выделенной под массив a.
d e l e t e [ ] a ;
r e t u r n 0 ;
}
7.4 Функции fscanf() и fprintf() Чтение и запись данных в файл можно выполнять с помощью функц ий
fscanf() иfprintf() . Эти функции подобны функциям scanf()иprintf() ,
описанным в п. 2.9, за тем исключением, что работают не с клавиа турой и экра-
ном, а с файлами. Функции имеют следующие прототипы.
Функция чтения
fscanf(указатель на файл, строка форматов, адреса переменных);
Функция записи
fprintf(указатель на файл,строка форматов, список переменных);
Далее приведён фрагмент программного кода, который демонс трирует при-
мер записи информации в файл my.txt.
c h a r f i o [ 3 0 ] = " Махарадзе В. " ;
i n t a = 5 , b = 5 , c = 4 ;
f l o a t s= (f l o a t ) ( a+b+c ) / 3 ;
FILE ∗f ;
f =f o p e n ( " m y . t x t " ," w " ) ;
f p r i n t f ( f , " Оценки студента % s \ n " , f i o ) ;
f p r i n t f ( f , " математика % d , физика % d , химия % d \ n " , a , b , c ) ;
f p r i n t f ( f , " Средний балл = % . 2 f \ n " , s ) ;
f p r i n t f ( f , " \ n ") ;
f c l o s e ( f ) ;
В результате будет сформирован текстовый файл:
Оценки студента Махарадзе В.
математика 5, физика 5, химия 4
Программирование на языке С++ в среде Qt Creator

7.4. Функции fscanf() и fprintf()241
Средний балл = 4.67
Рассмотрим пример чтения данных из файла. Пусть в файле test.txtхра-
нится информация:
1 Иванов Пётр 170 78.1
2 Петров Иван 180 89.6
3 Карпов Борис 167 56.7
Тогда с помощью следующих команд можно считать информацию из файла
и вывести её на экран. i n t i , nom ;
f l o a t V e s ;
i n t R o s t ;
c h a r f i o [ 1 5 ] , name [ 1 5 ] ;
FILE ∗f ;
f =f o p e n ( " t e s t . t x t " ," r " ) ;
f o r ( i = 0 ; i < 3 ; i ++)
{
/ /Чтение из файла
f s c a n f ( f , " % d % s % s % d % f \ n " ,&nom , & f i o , & name , & R o s t , & V e s ) ;
/ / Вывод на экран
p r i n t f ( " % d % s % s % d % . 2 f \ n " , nom , f i o , name , R o s t , V e s ) ;
}
f c l o s e ( f ) ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

Глава 8
Строки в языкеC++
В главе дано общее представление о строках в C++. Описана их структура,
способы инициализации, возможности ввода-вывода, привед ены примеры обра-
ботки строк и текстов.
8.1 Общие сведения о строках в C++
Строка  последовательность символов. Для работы с символами в язы ке
C++ предусмотрен тип данных char. Если в выражении встречается одиночный
символ, он должен быть заключён в одинарные кавычки. При испо льзовании в
выражениях строка заключается в двойные кавычки. Признаком конца строки
является нулевой символ ’ \0’. В C++строки можно описать с помощью массива
символов (массив элементов типа char), в массиве следует предусмотреть место
для хранения признака конца строки (’ \0’).
Например,
c h a r s [ 2 5 ] ; / /Описана строка из 25 символов.
/ / Элемент s[25] предназначен для хранения символа конца строк и.
c h a r s [ 1 5 ] = " Привет " ;/ / Описана строка из 15 символов и ей присвоено значение.
/ / Определён массив из 3 строк по 30 байт в каждой.
c h a r m[ 3 ] [ 3 0 ] = { " Пример "," использования " ," строк " }
Для работы со строками можно использовать указатели ( char *). Адрес пер-
вого символа будет начальным значением указателя.
Рассмотрим пример объявления и ввода строк.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{
c h a r s 2 [ 2 5 ] , ∗s 3 , s 4 [ 3 0 ] ; / /Описываем 3 строки, s3  указатель.
c o u t << " Введите строку: " << e n d l ;
c o u t << " s 2 = "; c i n >>s 2 ; / /Ввод строки s2.
c o u t << " Была введена строка: " << e n d l ;
c o u t << " s 2 = "< s 3=s 4 ; / /Запись в s3 адреса строки s4. Теперь в указателях s3 и s4 хранитс я один адрес.
c o u t << " Введите строку: " << e n d l ;
c o u t << " s 3 = "; c i n >>s 3 ; / /Ввод строки s3.
c o u t << " Была введена строка: " << e n d l ;

8.2. Операции над строками243
c o u t <<" s 3 = "< c o u t << " Сформирована новая строка: " << e n d l ;
c o u t << " s 4 = "< r e t u r n 0 ;
}
Если запустить эту программу на выполнение, то в консольном окне прило-
жения будет получен следующий результат.
Введите строку:
s2=Привет!
Была введена строка:
s2=Привет!
Введите строку:
s3=Программируем?
Была введена строка:
s3=Программируем?
Сформирована новая строка:
s4=Программируем?
Однако если во вводимых строках появятся пробелы, программ а будет работать
не так, как ожидает пользователь:
Введите строку:
s2=Привет, Вася!
Была введена строка:
s2=Привет,
Введите строку:
s3=Была введена строка:
s3=Вася!
Сформирована новая строка:
s4=Вася!
Дело в том, что функция cinвводит строки до встретившегося пробела. Более
универсальной функцией является функция
cin.getline(char *s, int n);
она предназначена для ввода с клавиатуры строки sс пробелами, причём в
строке не должно быть более nсимволов. Например,
c h a r s [ 2 5 ] ;
c o u t << " Введите строку: " << e n d l ;
c o u t << " s 2 = "; c i n . g e t l i n e ( s , 2 5 ) ;
c o u t << " Была введена строка: " << e n d l ;
c o u t << " s 2 = "< Результат:
Введите строку:
s2=Привет, Вася!
Была введена строка:
s2=Привет, Вася!
8.2 Операции над строками
Строку можно обрабатывать как массив символов, используя а лгоритмы об-
работки массивов, или с помощью специальных функций обработки строк, неко-
торые из которых приведены в таблицах 8.1–8.2.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

244Глава 8. Строки в языкеC++
Таблица 8.1: Функции работы со строками, библиотека string.h
Прототип функ-
ции Описание функции Пример использова-
ния Результат
size_t strlen (const
char ∗s) Вычисляет длину строки sв
байтах char s [80];
cout<< "s=";
cin . getline ( s ,80) ;
cout<< "s="< << "Длина строки \t"<<
strlen(s)< s=Hello, Russia!
s=Hello, Russia!
Длина строки 14
char ∗strcat( char
∗ dest, const char ∗
scr) Присоединяет строку srcв
конец строки dest, получен-
ная строка возвращается в
качестве результата char s1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
cout<< "s2=";
cin . getline (s2 ,80) ;
cout<< "s="< ,s2);
s1=Hello,
s2=Russia!
s=Hello, Russia!
char ∗strcpy( char
∗ dest, const char ∗
scr) Копирует строку srcв место
памяти, на которое указыва-
ет dest char s1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
strcpy(s2 , s1) ;
cout<< "s2="< s1=Hello,Russia!
s2=Hello,Russia!
char ∗strncat( char
∗ dest, const char ∗
dest, size_t maxlen) Присоединяет строку maxlen
символов строки srcв конец
строки dest chars1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
cout<< "s2=";
cin . getline (s2 ,80) ;
cout<< "s="< s1,s2,6);
s1=Hello,
s2=Russia!
s=Hello, Russia
char ∗strncpy( char
∗ dest, const char ∗
scr, size_t maxlen) Копирует maxlenсимволов
строки srcв место памяти,
на которое указывает dest chars1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
strncpy(s2 , s1 ,5) ;
cout<< "s2="< s1=Hello,Russia!
s2=Hello
intstrcmp( const
char ∗s1, const
char ∗s2) Сравнивает две строки в
лексикографическом поряд-
ке с учётом различия про-
писных и строчных букв,
функция возвращает 0, ес-
ли строки совпадают, воз-
вращает −1, если s1рас-
полагается в упорядоченном
по алфавиту порядке рань-
ше, чем s2, и 1 в противопо-
ложном случае. char s1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
cout<< "s2=";
cin . getline (s2 ,80) ;
cout< endl;
s1=RUSSIA
s2=Russia
-1
int strncmp( const
char ∗s1, const
char ∗s2, size_t
maxlen) Сравнивает maxlenсимволов
двух строк в лексикогра-
фическом порядке, функция
возвращает 0, если строки
совпадают, возвращает -1,
если s1располагается в упо-
рядоченном по алфавиту по-
рядке раньше, чем s2, и 1 
в противоположном случае. char s1 [80], s2 [80];
cout<< "s1=";
cin . getline (s1 ,80) ;
cout<< "s2=";
cin . getline (s2 ,80) ;
cout< ;
s1=Hello,Russia!
s2=Hello,
0
Программирование на языке С++ в среде Qt Creator

8.3. Тип данных string245
Таблица 8.2: Функции работы со строками, библиотекаstdlib.h
Прототип функции Описание функции Пример использова-
ния Результат
doubleatof(const char ∗s) Преобразует строку в ве-
щественное число, в слу-
чае неудачного преобразова-
ния возвращается число 0.0 char a [10];
cout<< "a=";
cin>>a;
cout<< "a="< < a=23.57
a=23.57
int atoi ( const char ∗s) Преобразует строку в целое
число, в случае неудачного
преобразования возвращает-
ся число 0 char a [10];
cout<< "a=";
cin>>a;
cout<< "a="< < a=23
a=23
long atol(const char ∗s) Преобразует строку в длин-
ное целое число, в слу-
чае неудачного преобразова-
ния возвращается число 0 char a [10];
cout<< "a=";
cin>>a;
cout<< "a="< < a=23
a=23
Для преобразования числа в строку можно воспользоваться фу нкцией
sprintf из библиотеки stdio.h.
sprintf(s, s1, s2);
Она аналогична описанной ранее функции printf, отличие состоит в том, что
осуществляется вывод не на экран, а в выходную строку s.
Например, в результате работы следующих команд
char str[80];
sprintf (str, "%s %d %s", "С Новым ", 2014, "годом!!!");
в переменную strбудет записана строка "С Новым 2014 годом!!!" .
8.3 Тип данных string
Кроме работы со строками как с массивом символов, в C++существует спе-
циальный тип данных string. Для ввода переменных этого типа можно исполь-
зовать cin1
или специальную функцию:
getline(cin,s);
Здесь s имя вводимой переменной типа string.
При описании переменной типа stringможно сразу присвоить ей значение:
string имя_переменной(s);
Здесь имя_переменной  идентификатор типа string,s  строковая констан-
та. Например, команда
string v("Hello");
создаёт строку v, в которую записывается значение Hello.
Доступ к i-му элементу строки осуществляется стандартным образом:
имя_строки[номер_элемента];
Над строками типа stringопределены следующие операции:
1
При работе c командой cin, как отмечалось ранее, ввод осуществляется до пробела.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

246Глава 8. Строки в языкеC++
•присваивание , напримерs1=s2;
• объединение строк (s1+=s2 илиs1=s1+s2 )  добавляет к строке s1строку
s2 , результат хранится в строке s1, например:
#i n c l u d e < i o s t r e a m >
#i n c l u d e < s t r i n g >
u s i n g namespace s t d ;
i n t m a i n ( )
{
s t r i n g a , b ;
c o u t << " a = "; g e t l i n e ( c i n , a ) ;
c o u t << " b = "; g e t l i n e ( c i n , b ) ;
a+=b ; c o u t << " a = "< r e t u r n 0 ;
}
• сравнение строк на основе лексикографического порядка: s1==s2,s1!=s2 ,
s1s2 ,s1>=s2  результатом операций сравнения будет ло-
гическое значение;
При обработке строк типаstring можно использовать следующие функции 2
:
s.length()  возвращает длину строки s;
s.substr(pos, length)  возвращает подстроку из строки s, начиная с номера
pos длиной lengthсимволов;
s.empty()  возвращает значение true, если строка sпуста, false в против-
ном случае;
s.insert(pos, s1)  вставляет строкуs1в строку s, начиная с позиции pos;
s.remove(pos, length)  удаляет из строкиsподстроку lengthдлиной pos
символов;
s.find(s1, pos)  возвращает номер первого вхождения строки s1в строку s,
поиск начинается с номера pos, параметр posможет отсутствовать, в этом
случае поиск идёт с начала строки;
s.findfirst(s1, pos)  возвращает номер первого вхождения любого символа
из строки s1в строку s, поиск начинается с номера pos, параметр pos
может отсутствовать, в этом случае поиск идёт с начала строк и.
Задача 8.1. Некоторый текст хранится в файле text.txt. Подсчитать количе-
ство строк и слов в тексте.
Предлагаем читателю самостоятельно разобраться в приведё нном программ-
ном коде.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
#i n c l u d e < s t d l i b . h>
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{ i f s t r e a m f ;
i n t p , j , i , k o l , m, n = 0 ;
s t r i n g S [ 1 0 ] ;
f . o p e n ( " t e x t . t x t " ) ;
i f ( f )
2
В описанных ниже функциях строки sи s1 должны быть типа string.
Программирование на языке С++ в среде Qt Creator

8.4. Задачи для самостоятельного решения247
{
w h i l e ( ! f . e o f ( ) )
{ g e t l i n e ( f , S [ n ] ) ;
c o u t < n++;
}
f . c l o s e ( ) ;
c o u t < c o u t << " Количество строк в тексте - " < f o r ( k o l = 0 , i = 0 ; i {
m=S [ i ] . l e n g t h ( ) ;S [ i ]+= " ";
f o r ( p = 0 ; p {
j =S [ i ] . f i n d ( " ", p ) ;
i f ( j ! = 0 ) { k o l ++; p= j + 1 ; }
e l s e break ;
}
}
c o u t << " Количество слов в тексте - " < }
e l s e c o u t << " Файл не найден " << e n d l ;
r e t u r n 0 ;
}
Результаты работы программы:
Если видим, что с картины
Смотрит кто-нибудь на нас,
Или принц в плаще старинном,
Или в робе верхолаз,
Лётчик или балерина,
Или Колька, твой сосед,
Обязательно картина
Называется портрет.
Количество строк в тексте - 8
Количество слов в тексте - 29
8.4 Задачи для самостоятельного решения
Разработать программу на языке C++для следующих заданий, учитывая, что
исходная информация хранится в текстовом файле.
1. Подсчитать количество слов в каждой строке текста.
2. Подсчитать количество символов в тексте.
3. Подсчитать количество точек в тексте.
4. Подсчитать количество пробелов в тексте.
5. Удалить из теста все пробелы.
6. Удалить из теста все точки.
7. Вставить вместо каждого пробела восклицательный знак.
8. Вставить перед каждым восклицательным знаком вопросите льный.
9. Определить, содержит ли текст хотя бы один восклицательн ый знак, и в
какой строке.
10. Подсчитать количество слов в чётных строках текста.
11. Найти номер самой длинной строки текста.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

248Глава 8. Строки в языкеC++
12. Променять местами первую и последнюю строки текста.
13. Определить, есть ли в тексте пустые строки.
14. Определить, содержит ли текст хотя бы пару соседних один аковых строк.
15. Найти самую короткую строку текста и заменить её фразой С новым го-
дом!.
16. Найти самую длинную строку текста и заменить её пустой ст рокой.
17. Определить количество слов в нечётных строках текста.
18. Определить количество пробелов в чётных строках текста .
19. Определить количество предложений в тексте, учитывая, что предложение
заканчивается точкой, вопросительным или восклицательны м знаком.
20. Поменять местами самую длинную и самую короткую строки т екста.
21. Вывести на печать первое предложение текста, учитывая, что оно закан-
чивается точкой.
22. Определить количество пробелов в нечётных строках текс та.
23. Удалить из теста все восклицательные и вопросительные з наки.
24. Определить, содержит ли текст хотя бы один вопросительн ый знак, и в
какой строке.
25. Добавить в начало каждой строки текста её номер и пробел.
Программирование на языке С++ в среде Qt Creator

Глава 9
Структуры в языкеC++
В этой главе дано описание структурного типа данных. Этот ти п предназна-
чен для представления сложных данных и создания новых типов . Приведены
примеры использования структур для работы с комплексным чи слом.
Описана библиотека языка C++, позволяющая работать с комплексными чис-
лами.
9.1 Общие сведения о структурах
Из предыдущих глав известно, что массив это переменная для х ранения мно-
жества данных одного типа. Если возникает необходимость об рабатывать разно-
родную информацию как единое целое, то применяют тип данных структуры.
Он позволяет сгруппировать объекты различных типов данных под одним име-
нем.
Для того, чтобы объявить переменные структурного типа, вначале нуж-
но задать новый тип данных, указав имя структурыи еёэлементы . Элемен-
ты структуры называются полями, и могут иметь любой тип данных кроме
типа этой же структуры. Далее приведён пример создания стру ктурного типа
student , полями которого являются фамилия студента, шифр группы, го д нача-
ла обучения и оценки по четырём предметам: s t r u c t s t u d e n t
{
/ / Поля структуры:
c h a r f i o [ 3 0 ] ;
c h a r g r o u p [ 8 ] ;
i n t y e a r ;
i n t i n f o r m a t i k a , math , f i z i k a , h i s t o r y ;
}
На основании созданного структурного типа данных можно описать пере-
менные типаstudent :
s t u d e n t V a s y a ; / /Переменная Vasya типа student.
s t u d e n t ES [ 5 0 ] ; / /Массив, элементы которого имеют тип student.
s t u d e n t ∗x ; / /Указатель на тип данных student.

250Глава 9. Структуры в языкеC++
Обращаются к полямпеременной структурного типа так:
имя_структуры.поле
Например,
V a s y a . y e a r ; / /Обращение к полю year переменной Vasya.
ES [ 4 ] . math ; / /Обращение к полю math элемента ES[4].
Задача 9.1. Заданоnкомплексных чисел, которые хранятся в двоичном файле.
Найти значение наибольшего модуля среди заданных чисел.
Напомним, что комплексные числа это числа видаz= a+ b·i, где aи b
 действительные числа, аi мнимая единица ,i2
= −1. Комплексное число
расширяет понятие действительного числа . Если действительное число  это
любая точка на числовой прямой, то под комплексным числом пон имают точку
на плоскости (рис. 9.1). Модуль комплексного числа zвычисляют по формуле
| z | = √
a
2
+ b2
.
Для решения задачи 9.1 разработаны две программы. Первая со здаёт файл
исходных данных, вторая получает из него информацию и обраб атывает её в
соответствии с поставленной задачей.
Далее приведён текст программы создания двоичного файла с nкомплекс-
ными числами. В файл complex.datбудет записано число n, а затем последова-
тельно комплексные числа.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
u s i n g namespace s t d ;
i n t m a i n ( )
{ / /Структура Комплексное число.
s t r u c t c o m p l e x
{
/ / Поля структуры:
double Re ;/ /Действительная часть.
double Im ;/ /Мнимая часть.
} ;
c o m p l e x p ; / /Переменная для хранения комплексного чисела.
i n t i , n ;
FILE ∗f ;
c o u t << " n = "; c i n >>n ;
f =f o p e n ( " c o m p l e x . d a t " ," w b " ) ;
f w r i t e (&n , s i z e o f(i n t ) , 1 , f ) ;
f o r ( i = 0 ; i {
c o u t << " Введите комплексное число \ n " ;
/ / Ввод комплексного числа:
c i n >>p . Re ; / /действительная часть,
c i n >>p . Im ; / /мнимая часть.
/ / Вывод комплексного числа.
c o u t <

/ / Запись комплексного числа в двоичный файл.
f w r i t e (&p , s i z e o f( c o m p l e x ) , 1 , f ) ;
}
f c l o s e ( f ) ;
r e t u r n 0 ;
}
Программирование на языке С++ в среде Qt Creator

9.1. Общие сведения о структурах251
Рис. 9.1: Геометрическая модель
комплексного числа a+ b·i Рис. 9.2: Геометрическая интер-
претация комплексно-сопряжённого
числа
Следующая программа считывает информацию из файла complex.dat ко-
личество комплексных чисел в переменную n, а сами комплексные числа в массив
p . Затем происходит поиск комплексного числа с максимальным модулем в мас-
сиве p.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
s t r u c t c o m p l e x
{ double Re ;
double Im ;
} ;
c o m p l e x ∗p ;
i n t i , n , nmax ;
double max ;
FILE ∗f ;
f =f o p e n ( " c o m p l e x . d a t " ," r b " ) ;
f r e a d (&n , s i z e o f(i n t ) , 1 , f ) ;
p= new c o m p l e x [ n ] ;
f r e a d ( p , s i z e o f( c o m p l e x ) , n , f ) ;
/ / Поиск комплексного числа с максимальным модулем
max= s q r t ( p [ 0 ] . Re ∗p [ 0 ] . Re+p [ 0 ] . Im ∗p [ 0 ] . Im ) ;
f o r ( i = 1 , nmax = 0 ; i i f ( s q r t ( p [ i ] . Re ∗p [ i ] . Re+p [ i ] . Im ∗p [ i ] . Im )>max )
{ max= s q r t ( p [ i ] . Re ∗p [ i ] . Re+p [ i ] . Im ∗p [ i ] . Im ) ;
nmax= i ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

252Глава 9. Структуры в языкеC++
}
c o u t << " m a x = "< f c l o s e ( f ) ;
r e t u r n 0 ;
}
Задача 9.2. Даны два комплексных числа z
1 и
z
2. Выполнить над ними
основные
операции :
• сложение z
1 +
z
2,
• вычитание z
1 −
z
2,
• умножение z
1 ·
z
2,
• деление z
1
z2 ,
• возведение в степень n zn
1 ,
• извлечение корня n-й степени n

z
1
• вычисление комплексного сопряжённого числа ¯
z
1.
Суммой двух комплексных чисел z
1 =
a+ i·b и z
2 =
c+ i·d называется комплексное
число z= z
1 +
z
2 = (
a+ c) + i·(b + d).
Разностью двух комплексных чисел z
1 =
a+ i·b и z
2 =
c+ i·d называется
комплексное число z= z
1 −
z
2 = (
a− c) + i·(b − d).
Произведением двух комплексных чисел z
1 =
a+ i·b и z
2 =
c+ i·d называется
комплексное число z= z
1 ·
z
2 = (
a·c − b·d ) + i·(b ·c + a·d ).
Частным двух комплексных чисел z
1 =
a+ i·b и z
2 =
c+ i·d называется
комплексное число
z= z
1
z2 =
ac
+bd c2
+ d2 +
i· bc
−ad c2
+ d2
Числом, сопряжённым комплексному числу z= x+ i·y , называется число ¯
z =
x − i·y (рис. 9.2).
Всякое комплексное число, записанное в алгебраической формеz= x+ i·y ,
можно записать в тригонометрической z= r(cos + i·sin ) или в показательной
форме z= r·e i
·
, где r= p
x
2
+ y2
 модуль комплексного числа z, = arctan y x
 его аргумент (рис. 9.2).
Для возведения в степень комплексного числа , записанного в тригонометри-
ческой форме z= r(cos + i·sin ), можно воспользоваться формулой Муавра
z n
= rn
·(cos( n· ) + i·sin( n· )) .
Формула для извлечения корня n-й степени из комплексного числа z= r·(cos +
i ·sin ) имеет вид
n

z
= n
√ z
(cos
+2 · ·k n +
i·sin
+2 · ·k n )
,
где n > 1, k = 0 ,1 , . . . , n −1.
Далее приведён текст программы, реализующий алгоритм решен ия зада-
чи 9.2. В программе описаны две структуры для работы с компле ксными числа-
ми: структура complex1для представления комплексных чисел в алгебраической
форме ( Re действительная часть комплексного числа, Im его мнимая часть)
и структура complex2для представления комплексных чисел в показательной
Программирование на языке С++ в среде Qt Creator

9.1. Общие сведения о структурах253
или тригонометрической форме (Modul модуль комплексного числа, Argum
его аргумент). Кроме того в программе созданы функции, реал изующие основ-
ные действия над комплексными числами, переход между разли чными формами
представления комплексных чисел, а также ввод-вывод компл ексных чисел.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
s t r u c t c o m p l e x 1
{
f l o a t Re ;
f l o a t Im ;
} ;
s t r u c t c o m p l e x 2
{ f l o a t Modul ;
f l o a t Argum ;
} ;
/ / Ввод числа в алгебраической форме
c o m p l e x 1 v v o d 1 ( )
{
c o m p l e x 1 temp ;c o u t << " Введите действительную часть числа \ n " ;
c i n >>temp . Re ;
c o u t << " Введите мнимую часть комплексного числа \ n " ;
c i n >>temp . Im ;
r e t u r n temp ;
}
/ / Ввод числа в тригонометрической или показательной форме
c o m p l e x 2 v v o d 2 ( )
{
c o m p l e x 2 temp ;c o u t << " Введите модуль комплексного числа \ n " ;
c i n >>temp . Modul ;
c o u t << " Введите аргумент комплексного числа \ n " ;
c i n >>temp . Argum ;
r e t u r n temp ;
}
/ / Вывод числа в алгебраической форме
v o i d v i v o d ( c o m p l e x 1 c h i s l o )
{ c o u t << c h i s l o . Re ;
i f ( c h i s l o . Im>=0)
c o u t << " + "<< c h i s l o . Im<< " i "<< e n d l ;
e l s e
c o u t << " "<< c h i s l o . Im<< " i "<< e n d l ;
}
/ / Вывод числа в тригонометрической форме
v o i d v i v o d ( c o m p l e x 2 c h i s l o )
{ c o u t << c h i s l o . Modul<< " ( c o s ( "<< c h i s l o . Argum<< " ) + i s i n ( "<< c h i s l o . Argum<<
" ) ) " << e n d l ;
}
/ / Перевод числа из тригонометрической формы в алгебраическую ,
/ / pr определяет, выводить или нет полученное число на экран.
c o m p l e x 1 p e r e v o d ( c o m p l e x 2 c h i s l o , b o o lp r=f a l s e )
{ c o m p l e x 1 temp ;
temp . Re= c h i s l o . Modul ∗c o s ( c h i s l o . Argum ) ;
temp . Im= c h i s l o . Modul ∗s i n ( c h i s l o . Argum ) ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Перевод числа из алгебраической формы в тригонометрическую ,
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

254Глава 9. Структуры в языкеC++
/ /pr определяет, выводить или нет полученное число на экран.
c o m p l e x 2 p e r e v o d ( c o m p l e x 1 c h i s l o , b o o lp r=f a l s e )
{ c o m p l e x 2 temp ;
temp . Modul= s q r t ( c h i s l o . Re ∗c h i s l o . Re+
c h i s l o . Im ∗c h i s l o . Im ) ;
temp . Argum=a t a n ( c h i s l o . Im / c h i s l o . Re ) ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Функция сложения двух чисел в алгебраической форме,
/ / pr определяет, выводить или нет число на экран.
c o m p l e x 1 p l u s 1 ( c o m p l e x 1 c h i s l o 1 , c o m p l e x 1 c h i s l o 2 , b o o lp r=t r u e )
{
c o m p l e x 1 temp ;
temp . Re= c h i s l o 1 . Re+ c h i s l o 2 . Re ;
temp . Im= c h i s l o 1 . Im+ c h i s l o 2 . Im ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Функция вычитания двух чисел в алгебраической форме,
/ / pr определяет, выводить или нет число на экран.
c o m p l e x 1 m i n u s 1 ( c o m p l e x 1 c h i s l o 1 , c o m p l e x 1 c h i s l o 2 , b o o lp r=t r u e )
{ c o m p l e x 1 temp ;
temp . Re= c h i s l o 1 . Re −c h i s l o 2 . Re ;
temp . Im= c h i s l o 1 . Im −c h i s l o 2 . Im ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Функция умножения двух чисел в алгебраической форме,
/ / pr определяет, выводить или нет число на экран.
c o m p l e x 1 m u l t 1 ( c o m p l e x 1 c h i s l o 1 , c o m p l e x 1 c h i s l o 2 , b o o lp r=t r u e )
{
c o m p l e x 1 temp ;
temp . Re= c h i s l o 1 . Re ∗c h i s l o 2 . Re −c h i s l o 1 . Im ∗c h i s l o 2 . Im ;
temp . Im= c h i s l o 1 . Im ∗c h i s l o 2 . Re+ c h i s l o 1 . Re ∗c h i s l o 2 . Im ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Функция деления двух чисел в алгебраической форме,
/ / pr определяет, выводить или нет число на экран.
c o m p l e x 1 d i v i d e 1 ( c o m p l e x 1 c h i s l o 1 , c o m p l e x 1 c h i s l o 2 , b o o lp r=t r u e )
{
c o m p l e x 1 temp ;
temp . Re=( c h i s l o 1 . Re ∗c h i s l o 2 . Re+ c h i s l o 1 . Im ∗c h i s l o 2 . Im ) / ( c h i s l o 2 . Re ∗c h i s l o 2 .
Re+ c h i s l o 2 . Im ∗c h i s l o 2 . Im ) ;
temp . Im=( c h i s l o 1 . Im ∗c h i s l o 2 . Re −c h i s l o 1 . Re ∗c h i s l o 2 . Im ) / ( c h i s l o 2 . Re ∗c h i s l o 2 .
Re+ c h i s l o 2 . Im ∗c h i s l o 2 . Im ) ;
i f ( p r ) v i v o d ( temp ) ;
r e t u r n temp ;
}
/ / Функция возведения комплексного числа в алгебраической форм е
/ / в целую степень n, pr определяет, выводить или нет полученное ч исло на экран.
c o m p l e x 1 pow1 ( c o m p l e x 1 c h i s l o 1 , i n tn ,b o o l p r=t r u e )
{ c o m p l e x 1 temp ;
c o m p l e x 2 t e m p 2 ;f l o a t p = 1 ;
i n t i = 1 ;
t e m p 2=p e r e v o d ( c h i s l o 1 , t r u e) ;/ / Перевод числа в тригонометрическую форму.
f o r ( ; i <=n ; p ∗=t e m p 2 . Modul , i ++) ;
temp . Re=p ∗c o s ( n ∗t e m p 2 . Argum ) ;
temp . Im=p ∗s i n ( n ∗t e m p 2 . Argum ) ;
i f ( p r ) v i v o d ( temp ) ;
Программирование на языке С++ в среде Qt Creator

9.1. Общие сведения о структурах255
r e t u r ntemp ;
}
/ / Функция извлечения корня степени n из комплексного числа
/ / в алгебраической форме, pr определяет, выводить или нет
/ / полученные значения на экран. Функция возвращает ro и fi.
v o i d s q r t n 1 ( c o m p l e x 1 c h i s l o 1 , i n tn ,f l o a t ∗r o , f l o a t ∗f i , b o o l p r=t r u e )
{
c o m p l e x 1 temp ;
c o m p l e x 2 t e m p 2 ;i n t i = 0 ;
t e m p 2=p e r e v o d ( c h i s l o 1 , t r u e) ;/ / Перевод числа в тригонометрическую форму.
∗ r o=pow ( t e m p 2 . Modul , ( f l o a t) 1 / n ) ;
∗ f i =t e m p 2 . Argum ;
i f ( p r )
{ f o r ( i = 0 ; i { c o u t < temp . Re= ∗r o ∗c o s ( ( ∗f i +2 ∗M_PI ∗i ) / n ) ;
temp . Im= ∗r o ∗s i n ( ( ∗f i +2 ∗M_PI ∗i ) / n ) ;
v i v o d ( temp ) ;
}
}
} i n t m a i n ( )
{ c o m p l e x 1 c h i s l o 1 , c h i s l o 2 ; / /Описание комплексных
c o m p l e x 1 c h i s l o 5 ; / /чисел в алгебраической форме.
c o m p l e x 2 c h i s l o 3 , c h i s l o 4 ; / /Описание комплексных чисел в тригонометрической форме.
f l o a t r o 1 , f i 1 ;
c h i s l o 1 =v v o d 1 ( ) ; / /Ввод исходных данных
c h i s l o 2 =v v o d 1 ( ) ; / /в алгебраической форме.
v i v o d ( c h i s l o 1 ) ; / /Вывод исходных данных
v i v o d ( c h i s l o 2 ) ; / /в алгебраической форме.
c h i s l o 3 =p e r e v o d ( c h i s l o 1 , t r u e) ;/ /Перевод чисел
c h i s l o 4 =p e r e v o d ( c h i s l o 2 , t r u e) ;/ / в тригонометрическую форму и вывод их на экран.
c o u t << " Сумма чисел " ;
c h i s l o 5 =p l u s 1 ( c h i s l o 1 , c h i s l o 2 , t r u e) ;
c o u t << " Разность чисел " ;
c h i s l o 5 =m i n u s 1 ( c h i s l o 1 , c h i s l o 2 , t r u e) ;
c o u t << " Произведение чисел " ;
c h i s l o 5 =m u l t 1 ( c h i s l o 1 , c h i s l o 2 , t r u e) ;
c o u t << " Частное чисел " ;
c h i s l o 5 = d i v i d e 1 ( c h i s l o 1 , c h i s l o 2 , t r u e) ;
c h i s l o 5 =pow1 ( c h i s l o 1 , 5 , t r u e) ;/ /Возведение числа в пятую степень.
s q r t n 1 ( c h i s l o 1 , 5 , &r o 1 , & f i 1 , t r u e) ;/ /Извлечение корня пятой степени.
r e t u r n 0 ;
}
Результаты работы программы к задаче 9.2.
Введите действительную часть числа
5
Введите мнимую часть комплексного числа
-7
Введите действительную часть числа
11
Введите мнимую часть комплексного числа
1.85
5 -7 i
11 +1.85 i
8.60233 ( cos (-0.950547) + i sin (-0.950547))
11.1545 ( cos (0.166623) + i sin (0.166623))
Сумма чисел 16 -5.15 i
Разность чисел -6 -8.85 i
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

256Глава 9. Структуры в языкеC++
Произведение чисел 67.95 -67.75 i
Частное чисел 0.337961 -0.693203 i
8.60233 ( cos (-0.950547) + i sin (-0.950547))
1900 +47068 i
8.60233 ( cos (-0.950547) + i sin (-0.950547))
0-е значение корня
1.51018 -0.290608 i
1-е значение корня
0.743054 +1.34646 i
2-е значение корня
-1.05094 +1.12277 i
3-е значение корня
-1.39257 -0.652552 i
4-е значение корня
0.190285 -1.52606 i
9.2 Библиотеки для работы с комплексными числами
Работа с комплексными числами в C++реализована с помощью библиотеки
complex . Подключение этой библиотеки даёт возможность применять оп ерации
+ ,− ,*, / для работы не только с вещественными, но и с комплексными чис лами.
Перед подключением библиотеки complexобязательно необходимо подклю-
чить библиотеку math.h.
Для определения переменной типа комплексное число используется оператор.
complex <тип_переменной> имя_переменной;
Здесь тип_переменной  это любой допустимый в C++числовой тип данных
( int ,long int ,double ,float и т. д.), описывающий действительную и мнимую
части комплексного числа. Например, c o m p l e x < f l o a t> x , y , z [ 5 ] , ∗r ;
c o m p l e x < double> a ;
c o m p l e x < i n t> a , b , c ;
Для организации ввода-вывода комплексных чисел можно использовать библио-
теку iostream и стандартные конструкции cin,cout . Например,
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ c o m p l e x < double> b , c ; / /Описание комплексных чисел.
c o u t << " b = "; c i n >>b ; / /Ввод комплексного числа b.
c o u t << " c = "; c i n >>c ; / /Ввод комплексного числа c.
c o u t << " b / c = "< r e t u r n 0 ;
}
В результате получим:
b=(1.24,-6.12)
c=(9.01,-11.22)
b/c=(0.385567,-0.199105)
Обратите внимание, что при вводе комплексных чисел с клавиатуры действи-
тельная и мнимая части вводятся в скобках через запятую:
(действительная_часть, мнимая_часть)
Программирование на языке С++ в среде Qt Creator

9.2. Библиотеки для работы с комплексными числами257
Далее приведён примерприсваивания комплексным переменным реальных
значений при их описании:
c o m p l e x < double> z ( 4 . 0 , 1 . 0 ) ;
c o m p l e x < i n t> r ( 4 , −7) ;
Следующий пример демонстрирует, как из двух числовых значен ий можно
составить комплексное число :
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( i n ta r g c , c h a r∗ ∗a r g v )
{ double x1 , y 1 ;
x 1 = −2 . 3 ;
y 1 = 8 . 1 ;
c o m p l e x < double> b ( x1 , y 1 ) ; / /Формирование комплексного числа b
/ / с действительной частью x1 и мнимой y1.
c o u t << " b ^ 2 = "< r e t u r n 0 ;
}
В табл. 9.1 представлены основные математические функции для работы с
комплексными числами.
Таблица 9.1: Основные функции комплексного аргумента
Прототип функции Описание функции
double abs(complex z) Возвращает модуль комплексного числа z.
double arg(complex z) Возвращает значение аргумента комплексного числа z.
complex conj(complex z) Возвращает число комплексно сопряжённое числу z
complex cos(complex z) Возвращает косинус комплексного числаz.
complex cosh(complex z) Возвращает гиперболический косинус комплексного чис-
ла z.
complex exp(complex z) Возвращает экспоненту комплексного числа z.
double imag(complex z) Возвращает мнимую часть комплексного числа z.
complex log(complex z) Возвращает натуральный логарифм комплексного чис-
ла z.
complex log10(complex z) Возвращает десятичный логарифм комплексного чис-
ла z.
double norm(complex z) Возвращает квадрат модуля комплексного числа z.
complex pow(complex x,
complex y) Возвращает степень комплексного числа z.
complex polar(double
mag, double angle) Формирует комплексное число с модулем magи аргумен-
том angle .
double real(complex z) Возвращает действительную часть комплексного чис-
лаz.
complex sin(complex z) Возвращает синус комплексного числа z.
complex sinh(complex z) Возвращает гиперболический синус комплексного чис-
ла z.
complex sqrt(complex z) Возвращает квадратный корень комплексного числа z.
complex tan(complex z) Возвращает тангенс комплексного числа z.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

258Глава 9. Структуры в языкеC++
Таблица 9.1  продолжение
Прототип функции Описание функции
complex tanh(complex z) Возвращает гиперболический тангенс комплексного чис-
лаz.
Далее приведён текст программы, демонстрирующий работу с не которыми
функциями из табл. 9.1.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
c o m p l e x < double> x ( 4 , −6) ;
c o m p l e x < double> y (−7 , 2 ) ;
c o u t << " x * y = "< c o u t << " s i n ( x ) * c o s ( y ) = " << s i n ( x )∗c o s ( y )< c o u t << " c o n j ( x ) * l n ( y ) = " << c o n j ( x )∗l o g ( y )<< e n d l ;
c o u t << " s h ( y ) = " << s i n h ( y )<< e n d l ;
r e t u r n 0 ;
}
Результаты работы программы с некоторыми функциями компле ксного ар-
гумента:
x*y=(-16,50)
sin(x)*cos(y)=(-747.159,10.2102)
conj(x)*ln(y)=(-9.23917,23.364)
sh(y)=(228.18,498.583)
Задача 9.3. Вычислитьy= ( √
3
− i) 20
,z =
1+ i·√ 3 1
− i
40
.
Если провести аналитические преобразования, то получим сл едующее:
y = 2 19
·(− 1 + i·√
3)
,z = −219
·(1 + i·√ 3)
.
Проверим эти вычисления с помощью программы на C++. Результаты работы
программы подтверждают аналитические вычисления.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{
c o m p l e x < double> b ( s q r t ( 3 ) , −1 ) , y ;
y=pow ( b , 2 0 ) ;
c o u t << " y = "< c o u t << r e a l ( y ) / pow ( 2 , 1 9 )<< " \ t ";
c o u t < c o m p l e x < double> a ( 1 , s q r t ( 3 ) ) , c ( 1 , −1 ) , z ;
z=pow ( a / c , 4 0 ) ;
c o u t << " z = "< c o u t << r e a l ( z ) / pow ( 2 , 1 9 )<< " \ t ";
c o u t < r e t u r n 0 ;
}
Результаты работы программы к задаче 9.3:
b=(1.73205,-1)y=(-524288,908093)
-1 1.73205
Программирование на языке С++ в среде Qt Creator

9.2. Библиотеки для работы с комплексными числами259
z=(-524288,-908093)
-1 -1.73205
Операции с массивами , элементами которых являются комплексные числа,
осуществляются так же, как и с обычными переменными. В качест ве примера
рассмотрим следующие задачи.
Задача 9.4. Написать программу умножения матриц комплексных чисел. Ма т-
рицы AиB имеют вид:
A = 0
@
1 + 2
·i 2 + 3·i 3 + 1.54 ·i 4− 7.2 ·i
2 + 5 ·i 3 + 7·i 4 + 10·i 5 + 14·i
1 .5 + 3 .25 ·i 1.7 − 3.94 ·i 6.23 + 11 .17 ·i −4.12 + 3 .62 ·i 1
A
,
B =0
B
@
6
.23 −1.97 ·i 0.19 + 0 .22 ·i 0.16 + 0 .28 ·i 3.4 + 1 .95 ·i 2.20 −0.18 ·i
0 .22 + 0 .29 ·i 11 + 12 ·i 6.72 −1.13 ·i 16 + 18 ·i 34 + 66 ·i
5 + 1 ·i 1.4 − 1.76 ·i 4.5 + 2 .3 ·i 296 + 700 ·i 4.2 + 1 .03 ·i
− 3.4 − 2.61 ·i 1 + 11·i 2 + 23·i 3− 35 ·i 4 + 47·i 1
C
A
.
Пусть исходные данные хранятся в файле abc.txt. Данные к задаче 9.4, со-
держимое файла abc.txt:
3 4 5
(1,2) (2,3) (3,1.54) (4,-7.2)
(2,5) (3,7) (4,10) (5,14)
(1.5,3.25) (1.7,-3.94) (6.23,11.17) (-4.12,3.62)
(6.23,-1.97) (0.19,0.22) (0.16,0.28) (3.4,1.95) (2.20,- 0.18)
(0.22,0.29) (11,12) (6.72,-1.13) (16,18) (34,66)
(5,1) (1.4,-1.76) (4.5,2.3) (296,700) (4.2,1.03)
(-3.14,-2.61) (1,11) (2,23) (3,-35) (4,47)
Далее приведён текст программы, реализующий алгоритм решен ия зада-
чи 9.4.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
i n t m a i n ( )
{ i n t i , j , p , N , M, K ;
c o m p l e x < f l o a t>∗ ∗A, ∗ ∗ B ,∗ ∗ C ;
i f s t r e a m f ;
o f s t r e a m g ;
f . o p e n ( " a b c . t x t " ) ;
f >>N>>M>>K ;
c o u t << " N = "< A= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i [M] , i ++) ;
B= new c o m p l e x < f l o a t>∗[M ] ;
f o r ( i = 0 ; i [ K ] , i ++) ;
C= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i [ K ] , i ++) ;
f o r ( i = 0 ; i f o r ( j = 0 ; j >A [ i ] [ j ] , j ++) ;
c o u t << " Матрица A \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j f o r ( i = 0 ; i f o r ( j = 0 ; j >B [ i ] [ j ] , j ++) ;
c o u t << " Матрица B \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j © 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

260Глава 9. Структуры в языкеC++
f o r( i = 0 ; i f o r ( j = 0 ; j f o r ( C [ i ] [ j ] = p = 0 ; p C [ i ] [ j ]+=A [ i ] [ p ] ∗B [ p ] [ j ] ;
f . c l o s e ( ) ;
c o u t << " Матрица C \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j g . o p e n ( " r e s u l t . t x t " ) ;
g<< " Матрица C=A*B \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j g . c l o s e ( ) ; r e t u r n 0 ;
}
Результат умножения матриц из задачи 9.4 (файл result.txt):
Матрица C=A*B
(-8.152,34.598) (75.8604,91.276) (199.988,109.93) (-45 2.5,2486.99) (237.974,406.978)
(51.78,26.61) (-177.52,190.35) (-290.01,242.21) (-5391 .95,5813.9) (-986.2,783.76)
(59.6291,78.3851) (49.9912,-59.0193) (-82.8542,-50.38 38) (-5763.7,7803.92) (149.766,-140.709)
Задача 9.5. Заданы матрицы AиB. Необходимо вычислить матрицу A−
1
, об-
ратную к матрице A, найти определитель |A |матрицы Aи решить матричное
уравнение A·X =B, где X=A−
1
·B . Матрицы AиB имеют вид:
A = 

1 + 2
·i 2 + 3·i 3 + 1.54 ·i
2 + 5 ·i 3 + 7·i 4 + 10·i
1 .5 + 3 .25 ·i 1.7 − 3.94 ·i 6.23 + 11 .17 ·i 

,
B =

1
.5 + 3 .25 ·i 1.7 − 9.34 ·i 6.23 + 11 .17 ·i
0 .11 + 8 .22 ·i 0.34 −18.21 ·i 1− 7·i
1 + 5 ·i 7− 13 ·i 12 + 89 ·i 

.
Для хранения исходных данных создадим текстовый файл abc2.txtследую-
щего содержания:
3
(1,2) (2,3) (3,1.54)
(2,5) (3,7) (4,10)
(1.5,3.25) (1.7,-9.34) (6.23,11.17)
(1.5,3.25) (1.7,-9.34) (6.23,11.17)
(0.11,8.22) (0.34,-18.21) (1,-7)
(1,5) (7,-13) (12,89)
Текст программы, реализующий поставленную задачу, предста влен ниже.
#i n c l u d e < i o s t r e a m >
#i n c l u d e < f s t r e a m >
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
/ / Решение СЛАУ с комплексными коэффициентами
i n t SLAU ( c o m p l e x < f l o a t>∗ ∗m a t r i c a _ a , i n tn , c o m p l e x < f l o a t>∗m a s s i v _ b ,
c o m p l e x < f l o a t>∗x )
{ i n t i , j , k , r ;
c o m p l e x < f l o a t> c , M, s ;
f l o a t max ;
c o m p l e x < f l o a t>∗ ∗a , ∗b ;
Программирование на языке С++ в среде Qt Creator

9.2. Библиотеки для работы с комплексными числами261
a=new c o m p l e x < f l o a t>∗[ n ] ;
f o r ( i = 0 ; i a [ i ] = newc o m p l e x < f l o a t> [ n ] ;
b= new c o m p l e x < f l o a t> [ n ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j a [ i ] [ j ] = m a t r i c a _ a [ i ] [ j ] ;
f o r ( i = 0 ; i b [ i ] = m a s s i v _ b [ i ] ;
f o r ( k = 0 ; k {
max= a b s ( a [ k ] [ k ] ) ;
r=k ;
f o r ( i =k + 1 ; i i f ( a b s ( a [ i ] [ k ] ) >max )
{
max=a b s ( a [ i ] [ k ] ) ;r= i ;
}
f o r ( j = 0 ; j {
c=a [ k ] [ j ] ;
a [ k ] [ j ] = a [ r ] [ j ] ;
a [ r ] [ j ] = c ;
}
c=b [ k ] ;
b [ k ] = b [ r ] ;
b [ r ] = c ;
f o r ( i =k + 1 ; i {
f o r (M=a [ i ] [ k ] / a [ k ] [ k ] , j =k ; j a [ i ] [ j ] −=M ∗a [ k ] [ j ] ;
b [ i ] −=M ∗b [ k ] ;
}
} i f ( a b s ( a [ n −1 ] [ n −1 ] ) ==0)
i f ( a b s ( b [ n −1 ] ) ==0)
r e t u r n −1 ;
e l s e r e t u r n −2 ;
e l s e
{
f o r ( i =n −1 ; i >=0; i −−)
{ f o r ( s = 0 , j = i + 1 ; j s+=a [ i ] [ j ] ∗x [ j ] ;
x [ i ] = ( b [ i ] −s ) / a [ i ] [ i ] ;
}
r e t u r n 0 ;
} f o r ( i = 0 ; i d e l e t e [ ] a [ i ] ;
d e l e t e [ ] a ;
d e l e t e [ ] b ;
}
/ / Вычисление обратной матрицы с комплексными коэффициентам и
i n t INVERSE ( c o m p l e x < f l o a t>∗ ∗a , i n t n , c o m p l e x < f l o a t>∗ ∗y )
{ i n t i , j , r e s ;
c o m p l e x < f l o a t>∗b , ∗x ;
b= new c o m p l e x < f l o a t> [ n ] ;
x= new c o m p l e x < f l o a t> [ n ] ;
f o r ( i = 0 ; i { f o r ( j = 0 ; j i f ( j== i )
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

262Глава 9. Структуры в языкеC++
b [ j ] = 1 ;
e l s e b [ j ] = 0 ;
r e s =SLAU ( a , n , b , x ) ;
i f ( r e s ! = 0 )
break ;
e l s e f o r ( j = 0 ; j y [ j ] [ i ] = x [ j ] ;
}
d e l e t e [ ] x ;
d e l e t e [ ] b ;
i f ( r e s ! = 0 )
r e t u r n −1 ;
e l s e
r e t u r n 0 ;
}
/ / Вычисление определителя матрицы с комплексными коэффицие нтами
c o m p l e x < f l o a t> d e t e r m i n a n t ( c o m p l e x < f l o a t>∗ ∗m a t r i c a _ a , i n tn )
{
i n t i , j , k , r ;
c o m p l e x < f l o a t> c , M, s , d e t = 1 ;
c o m p l e x < f l o a t>∗ ∗a ;
f l o a t max ;
a= new c o m p l e x < f l o a t>∗[ n ] ;
f o r ( i = 0 ; i a [ i ] = newc o m p l e x < f l o a t> [ n ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j a [ i ] [ j ] = m a t r i c a _ a [ i ] [ j ] ;
f o r ( k = 0 ; k { max=a b s ( a [ k ] [ k ] ) ;
r=k ;
f o r ( i =k + 1 ; i i f ( a b s ( a [ i ] [ k ] ) >max )
{ max=a b s ( a [ i ] [ k ] ) ;
r= i ;
}
i f ( r ! = k ) d e t= −d e t ;
f o r ( j = 0 ; j { c=a [ k ] [ j ] ;
a [ k ] [ j ] = a [ r ] [ j ] ;
a [ r ] [ j ] = c ;
}
f o r ( i =k + 1 ; i f o r (M=a [ i ] [ k ] / a [ k ] [ k ] , j =k ; j a [ i ] [ j ] −=M ∗a [ k ] [ j ] ;
} f o r ( i = 0 ; i d e t ∗=a [ i ] [ i ] ;
r e t u r n d e t ;
f o r ( i = 0 ; i d e l e t e [ ] a [ i ] ;
d e l e t e [ ] a ;
}
/ / Умножение матриц с комплексными коэффициентами
v o i d umn ( c o m p l e x < f l o a t>∗ ∗a , c o m p l e x < f l o a t>∗ ∗b , c o m p l e x < f l o a t>∗ ∗c , i n t
n , i n t m,i n t k )
{ i n t i , j , p ;
f o r ( i = 0 ; i f o r ( j = 0 ; j f o r ( c [ i ] [ j ] = p = 0 ; p Программирование на языке С++ в среде Qt Creator

9.2. Библиотеки для работы с комплексными числами263
c [ i ] [ j ]+=a [ i ] [ p ]∗b [ p ] [ j ] ;
}
i n t m a i n ( )
{
i n t i , j , N ;
c o m p l e x < f l o a t>∗ ∗A, ∗ ∗ B ,∗ ∗ X , ∗ ∗Y ;
i f s t r e a m f ;
o f s t r e a m g ; f . o p e n ( " a b c 2 . t x t " ) ;
f >>N ;
c o u t << " N = "< A= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i A [ i ] = newc o m p l e x < f l o a t> [ N ] ;
B= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i B [ i ] = newc o m p l e x < f l o a t> [ N ] ;
X= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i X [ i ] = newc o m p l e x < f l o a t> [ N ] ;
Y= new c o m p l e x < f l o a t>∗[ N ] ;
f o r ( i = 0 ; i Y [ i ] = newc o m p l e x < f l o a t> [ N ] ;
f o r ( i = 0 ; i f o r ( j = 0 ; j f >>A [ i ] [ j ] ;
c o u t << " Матрица A \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t <
f o r ( i = 0 ; i f o r ( j = 0 ; j f >>B [ i ] [ j ] ;
c o u t << " Матрица B \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t < i f ( ! INVERSE ( A , N , X) )
{
c o u t << " Обратная матрица \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t < umn ( X , B , Y , N , N , N) ;
c o u t << " \ n Решение матричного уравнения \ n " ;
f o r ( i = 0 ; i f o r ( j = 0 ; j c o u t < } e l s e c o u t << " Не существует обратной матрицы \ n " ;
c o u t << " Определитель = " < r e t u r n 0 ;
}
Результат работы программы к задаче 9.5:
N=3
Матрица A
(1,2) (2,3) (3,1.54)
(2,5) (3,7) (4,10)
(1.5,3.25) (1.7,-9.34) (6.23,11.17)
Матрица B
(1.5,3.25) (1.7,-9.34) (6.23,11.17)
(0.11,8.22) (0.34,-18.21) (1,-7)
(1,5) (7,-13) (12,89)
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

264Глава 9. Структуры в языкеC++
Обратная матрица
(-0.495047,-0.748993) (0.325573,0.182901) (-0.0340879 ,-0.0958618)
(0.125154,0.0765918) (-0.058179,-0.0728342) (0.002086 64,0.0685887)
(0.157733,0.322512) (-0.0859214,-0.127174) (0.0143863 ,-0.000518244)
Определитель=(7.50219,-208.261)
Решение матричного уравнения
(0.669246,-0.302366) (-5.88068,-2.74393) (15.0106,-16 .4762)
(0.190248,0.114415) (0.488295,0.448942) (-6.72319,3.2 1833)
(0.241332,0.347549) (1.02932,0.405788) (-3.37716,5.51 956)
9.3 Задачи для самостоятельного решения
9.3.1 Структуры. Операции над комплексными числами Разработать программу на языке C++для решения следующей задачи. Даны
комплексные числа a= + ·i, b = + ·i и c= + µ·i. Найти комплесное
число d= + ·i по формуле, представленной в табл. 9.2.
Таблица 9.2: Задания для решения задачи о комплексных чис-
лах
Вариант Формула для вычислений
1 d = a2
· a
+ b a− b·c
2 d = a2
·(
a + b− c) b
3 d = a
3
·b b + c · |
a− b|
4 d = ( a− c)2
·(
a + b) a
5 d = a
2
·b a + c ·
(a − b)
6 d = ( a+ c)2
·(
a − b) (a − c)
7 d = a
·b 2
+ c a− b 8 d = ( a+ b− c)2
·b a
9 d
= a
·b 3
− c a+ b
10 d = ( a+ b− c) · b
2 c
11 d
= a
3
·b + c a− b
12 d = (
a 2
+ b− c3
) a
13 d = a
+ b2
− c a+ b+ c
14 d = (
a + b2
− c) (a + b2
)
15 d =
a+ b+ c a− b+ c
2
16 d = ( a− b− c) · (
b + c) (b − c)
17 d =
a+ b3
+ c a− b2
− c
18 d
= ( a+ b+ c) · (
b − a) (b − c)
19 d =
a− b− c a− b2
+ c3
Программирование на языке С++ в среде Qt Creator

9.3. Задачи для самостоятельного решения265
Таблица 9.2  продолжение
Вариант Формула для вычислений
20 d= (
a 2
− b+ c) (b − c3
)
21 d = (
a + b+ c)2 a
− b− c
22 d = ( a+ b+ c) · (
b + c)2 (
b − c)3
23 d
= (
a 2
+ b− c
) ·
a b
24 d = (
b c
+
b·c )(a − c)
25 d = ( a2
− b c
)
· (
a + c) (a − c)
9.3.2 Работа с библиотекой комплексных чисел
Разработать программу на языке C++для решения следующей задачи:
1. Для заданной матрицы комплексных чисел A(n × n) найти B= 3 ·A 2
+ AT
.
2. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
(2 −3·i) ·A ·B +BT
.
3. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
·A − A2
, где =|B |.
4. Для заданной матрицы комплексных чисел A(n × n) найти C= (3 .2 + 1 .8 ·
i ) ·A T
− A2
.
5. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
(3 .5 ·i) ·A ·B T
− B.
6. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=

2 ·
A T
+ A2
, где =|B |.
7. Для заданной матрицы комплексных чисел D(k × k) найти C= (3 .2 + 1 .8 ·
i ) ·D 2
− (5.2 ·i) ·D T
.
8. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
A ·B T
+ A·B .
9. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
( ·A − AT
)·A , где =|B |.
10. Для заданной матрицы комплексных чисел F(m ×m)найти C= 2 .3 ·(F 2
+
F )T
.
11. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
( − 2 + 3 .5 ·i) ·(A − BT
)2
.
12. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
·(A 2
+ AT
), где =|B |.
13. Для заданной матрицы комплексных чисел D(k × k) найти C= (8 .1 ·i) ·
( D 2
− (1.2 ·i) ·D T
).
14. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
( − 1.5 ·i) ·(A T
+ BT
)2
.
15. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
·(A T
+ A)2
, где =|B |.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

266Глава 9. Структуры в языкеC++
16. Для заданной матрицы комплексных чисел D(k × k) найти C= ( DT
− (1.2 ·
i )) ·D .
17. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
( A 2
+ B2
)T
.
18. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
·(A T
+ A)·A , где =|B |.
19. Для заданной матрицы комплексных чисел F(m ×m)найти C=−3.3 ·
( F T
− (2 ·i) ·F )2
.
20. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
( A ·B +B ·A )T
.
21. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
A − ·A ·A T
, где =|B |.
22. Для заданной матрицы комплексных чисел F(m ×m)найти C=FT
+ (3 ·
i ) ·F 2
.
23. Для заданных матриц комплексных чисел A(n × n) и B(n × n) найти C=
(( A + B)2
)T
.
24. Для заданных матриц комплексных чисел A(n × n) и B(m ×m)найти C=
·(A 2
− AT
), где =|B |.
25. Для заданной матрицы комплексных чисел D(k × k) найти C= ( DT
+ (5 −
1 .3 ·i) ·D )2
.
Программирование на языке С++ в среде Qt Creator

Глава 10
Объектно-ориентированное
программирование
10.1 Возникновение объектного подхода впрограммировании
Первые программы, создававшиеся в те времена, когда значен ия битов в реги-
страх переключались тумблерами на системной консоли и тут же отображались
загорающимися индикаторами  эти первые программы были чрез вычайно про-
сты. Писали их непосредственно в машинных кодах, или, в лучш ем случае, на
ассемблере  языке, заменяющем коды машинных команд буквенн ыми мнемони-
ками. В последствии, по мере усложнения компьютеров и увелич ения размеров
программ, отслеживать возникающие ошибки становилось всё т руднее. Поэтому
стала возрастать популярность языков программирования вы сокого уровня, а
число программ, написанных целиком на языке машинных коман д, наоборот, на-
чало сокращаться. Языки высокого уровня обеспечивали боле е высокий уровень
абстракции, приближая конструкции и операторы языка к поня тиям, которыми
оперирует человек.
Исторически одним из первых языков высокого уровня был Форт ран, завое-
вавший огромную популярность и до сих пор используемый иног да в научных и
инженерных расчётах. Подход к программированию, на котором был основан и
он, и многие другие ранние языки, получил название процедурного программи-
рования . В рамках этого подхода в программе отдельно хранятся процедуры
блоки кода, каждый из которых выполняет какое-то самостоят ельное действие,
и переменные  блоки данных (см. рис. 10.1), к которым обращаются процеду-
ры для получения исходных значений и для сохранения результ ата. Такая чёт-
ко структурированная программа создавала меньше возможно стей не заметить
ошибку. Поэтому производительность труда программистов, освоивших проце-
дурную парадигму, ощутимо вырастала, а вместе с производит ельностью труда
вырастали размеры программ и их функциональные возможност и. Код серьёз-

268Глава 10. Объектно-ориентированное программирование
ных программных продуктов всё чаще писался коллективно, и с коро процедур-
ный подход перестал казаться таким уж защищённым от ошибок. Например,
нередко возникали ситуации, когда несколько программисто в одинаково назы-
вали свои переменные, т. е. фактически использовали одну и т у же глобальную
переменную в разных целях, в результате чего её значение хао тично менялось
при вызове разных процедур.
Процедура Процедура Процедура 
Глобальные переменные
Рис. 10.1: Процедурный подход к программированию
Процедурный подход претерпел ряд модернизаций, более совр еменные язы-
ки высокого уровня заимствовали некоторые принципы функционального про-
граммирования (одним из удачных примеров такого симбиоза является язык C),
большие программы делились на модули, а фирмы вводили собст венные строгие
политики в области оформления программного кода. Но в больш ой программе
по-прежнему было слишком трудно разобраться и слишком прос то запутаться,
поэтому проблема всё равно оставалась.
Объектный подход родился как следующий важный шаг на пути качествен-
ного написания больших программ. В нём предлагается раздел ять программу на
самостоятельные части  объекты, наделённые собственными свойствами, теку-
щим состоянием, и умеющие взаимодействовать друг с другом и с окружающей
средой  примерно так, как это происходит у объектов реально го мира.
В упрощённом виде такая парадигма получила название объект но-
ориентированного программирования (ООП)  подхода, котор ый позволяет
использовать в программе объекты и даже поощряет эту практи ку, но не требу-
ет, чтобы программа состояла из одних только объектов .
Классическое определение объекта звучит следующим образом :
Объект  это осязаемая сущность, которая чётко проявляет своё поведе-
ние. Читателю, для которого объектный подход к программированию внове, такое
определение наверняка покажется слишком туманным. Позже к онкретные при-
меры прояснят ситуацию, а пока поговорим о внутреннем устрой стве объекта.
Объект состоит из следующих трёх частей:
• имя объекта;
• состояние (переменные состояния);
• методы (операции).
На рисунке 10.2 изображены два объекта с именами Объект 1 и Объект
2. Первый объект имеет две переменные состояния и три метод а, в то время
Программирование на языке С++ в среде Qt Creator

10.1. Возникновение объектного подхода в программировании269
как второй объект обходится одной единственной переменнойсостояния и двумя
методами.
Объект 
Объект 
Сообщения
Переменная 
Состояние Интерфейс
Метод

Метод 
Метод 3 Метод
1
Метод 2
Переменная 1
Интерфейс
Состояние
Переменная 2
Рис. 10.2: Объектный подход к программированию
Интерфейс объекта с окружающей средой (пользователем, оста льной частью
программы, операционной системой и т. д.) полностью осущес твляется метода-
ми: к состоянию объекта нет другого доступа извне, кроме как через его методы.
Например, если объект должен передавать окружающей среде ин формацию о
значении одной из своих переменных состояния  для этого соз дают специаль-
ный метод.
Закрытость внутреннего состояния объекта от окружающей сре ды известна
также как свойство инкапсуляции. Инкапсуляция означает, что объект содержит
внутри себя данные и методы, оперирующие этими данными. Факт ически, для
окружающей среды объект представляет собой аналог чёрного ящика: прини-
мает входные воздействия и выдаёт в качестве реакции на них в ыходные, но при
этом никак не проявляет свою внутреннюю структуру.
Для взаимодействия друг с другом объекты обмениваются сообщениями, при-
чём объект, получивший сообщение, может либо проигнориров ать сообщение,
либо выполнить содержащуюся в нём команду (с помощью какого- либо из своих
методов).
Однотипные объекты образуют класс. Под однотипными объектами мы пони-
маем такие объекты, у которых одинаковы наборы методов и пер еменных состо-
яния. При этом объекты, принадлежащие одному классу, имеют р азные имена и,
вероятно, разные значения переменных состояния. Например , можно придумать
класс студент, объектами которого будут конкретные студ енты вуза. Объект
класса студент должен иметь переменные состояния, в кото рых содержится
информация о конкретном студенте: Ф.И.О., номер студенчес кой группы, домаш-
ний адрес, список изучаемых дисциплин и т. д. Конкретный спи сок переменных
зависит от задачи, для решения которой создаётся программа . Так, если постав-
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

270Глава 10. Объектно-ориентированное программирование
лена задача автоматизировать работу университетской библ иотеки, то объекты
класса студент определённо должны содержать информацию о книгах, взятых
на абонемент конкретным студентом. Если автоматизируется учёт успеваемости,
то в списке книг нет необходимости, но зато в состояние объек та обязательно
должны быть включены оценки по изучаемым дисциплинам.
Более того, когда мы рассматриваем сущности реального мира , с которыми
должна иметь дело создаваемая программа, мы можем назначит ь некую сущ-
ность на роль объекта или на роль класса объектов, также в зав исимости от кон-
кретной задачи. Представим себе, что одна из подзадач прогр аммы  система-
тизировать социальные роли, такие как домохозяйка, пен сионер, студент
(например, для учёта доходов и льгот). Вполне вероятно, что в такой программе
социальная роль будет объявлена классом, а сущность сту дент будет всего
лишь одним из объектов.
Иными словами, нет одинакового для всех ситуаций правила, п о которому
сущность делают объектом или классом объектов. Всегда необх одимо исходить
из большей целесообразности.
В реальном мире из родственных по смыслу сущностей часто мож но со-
ставить иерархию от общего к частному. Такие отношения в о бъектно-
ориентированном подходе называются наследованием. Из двух классов, находя-
щихся в отношении наследования, более общий класс называет сябазовым или
родительским классом, а класс, представляющий собой более частный случай ,
называется дочернимилипроизводным классом. Производный класс может за-
имствовать атрибуты (свойства и методы) базового класса. Э то означает, что
если в программе используются родственные по смыслу классы, обладающие
некоторыми одинаковыми свойствами и методами  лучше опред елить один ба-
зовый класс, находящийся в вершине иерархии, и разместить д ублирующиеся
свойства и методы в нём. В этом случае производные классы смо гут автомати-
чески унаследовать эти атрибуты от базового класса, и поэто му их не придётся
описывать снова и снова. Например, если программа оперируе т классами сту-
дент, преподаватель и инженер, логично ввести дополн ительный базовый
класс человек, переместив в него атрибуты, содержащие им я, адрес, другие
личные данные, а также методы, манипулирующие этими данными .
Помимо двух уже рассмотренных качеств  инкапсуляции и насл едования
 у объектов есть ещё третье основополагающее качество: полиморфизм. Это
означает, что объекты могут вести себя по-разному в зависим ости от ситуации.
Одно из основных проявлений полиморфного поведения  перег рузка функций.
Объект может содержать в себе несколько методов с одинаковы ми именами, при-
нимающих разные наборы параметров. В результате, передавая объекту данные,
можно обращаться к одному и тому же имени метода, не заботясь о типе, в ко-
тором представлены данные. Правильно сконструированный о бъект автомати-
чески выполнит наиболее подходящий метод из группы.
Инкапсуляция, наследование и полиморфизм являются тремя ос новополага-
ющими принципами объектно-ориентированного программиров ания и в том или
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 271
ином виде реализуются во всех объектно-ориентированных язы ках. В следующих
разделах мы увидим, как конкретно эти принципы применены в C++.
10.2 Классы и объекты в C++
Хотя C++и не первая попытка создать объектно-ориентированную верс ию
языка С, среди попыток такого рода он оказался наиболее успешным. О чевидно,
одна из причин успешности  то, каким образом объектная пара дигма была
встроена в синтаксис языка.
Ранние версии C++были созданы в начале 1980-х Бьёрном Страуструпом для
собственных нужд (в качестве универсального языка програм мирования, удоб-
ного для компьютерного моделирования). В создаваемый язык б ыли заложены
следующие основные принципы:
• поддержка различных стилей программирования, включая про цедурный и
объектно-ориентированный подходы;
• предоставление программисту полной свободы выбора  в т. ч . реализовать
программные решения, которые могут казаться концептуальн о неверными;
• сохранение обратной совместимости с языком С, чтобы прогр аммист мог
использовать только те дополнительные возможности C++, которые он со-
чтёт нужным, или не использовать их вовсе;
• сохранение переносимости и высокой производительности, характерных
для языка С.
Эти принципы заслужили высокую оценку программистов-прак тиков. В резуль-
тате на текущий момент C++является одним из наиболее распространённых язы-
ков программирования  как системного, так и прикладного.
10.2.1 Реализация ООП в C++. Классы и структуры
Синтаксис описания класса во многом копирует синтаксис опи сания структу-
ры. В простейшем случае класс описывается так: c l a s s имя_класса
{ закрытые члены класса
p u b l i c :
открытые члены класса
} ;
Как и при объявлении структуры, имя_классастановится новым именем ти-
па данных, которое можно использовать для объявления перем енных (объектов
класса) [5, 6]. Членами класса будут переменные и функции, о бъявленные внутри
класса. Функции-члены класса называют методамиэтого класса, а переменные-
члены класса называют свойствамикласса.
В C++ понятия ООП используются следующим образом [5, 6]:
• класс : пользовательский тип данных, во многом аналогичный стру ктуре;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

272Глава 10. Объектно-ориентированное программирование
• объект класса или переменная-экземпляр класса : переменная, в опи-
сании которой какой-то класс указан в качестве типа данных;
• свойство или переменная-член класса : переменная, объявленная внут-
ри класса (как поле внутри структуры); на практике чаще гово рят не о
свойстве класса, а о свойстве объекта, так как для конкретных объектов
переменные  члены класса обладают конкретными значениями и потому
имеют конкретный смысл.
• метод : функция, объявленная внутри класса.
По умолчанию все функции и переменные, объявленные в классе , являютсяза-
крытыми , т. е. принадлежат закрытой секции класса. Это значит, что они до-
ступны для обращения только изнутри членов этого класса и не доступны извне.
Для объявления открытыхчленов класса используется ключевое слово public
с двоеточием, обозначающее начало открытой секции класса. Все члены класса,
объявленные после слова public, доступны для обращения как изнутри этого же
класса, и для любой другой части программы, в которой доступе н класс.
Открытых и закрытых секций в классе может быть несколько, и о ни могут
произвольно чередоваться. При необходимости обозначить о чередную закрытую
секцию, её начало обозначается ключевым словом private.
Более того, структуры в C++были существенно доработаны (по сравнению
с классическим вариантом структур языка С). В C++структура может иметь
помимо переменных-членов (т. е. полей структуры) также и фу нкции-члены, а
ещё в структурах можно вводить открытые и закрытые секции. В сущности,
структуры отличаются от классов двумя вещами:
• в структурах вместо ключевого слова classпишется ключевое слово
struct ;
• в структурах по умолчанию все члены являются отрытыми (инач е переста-
ли бы работать программы, написанные на С).
Рассмотрим в качестве примера объект, представляющий собой геометрический
вектор в трехмерном пространстве. Для простоты ограничимс я хранением в объ-
екте трёх координат и функции, вычисляющей модуль вектора. С учётом разли-
чий между структурами и классами, приведённые ниже вариант ы аналогичны.
c l a s ss p a t i a l _ v e c t o r
{
p u b l i c :
double a b s ( ) ;
p r i v a t e :
double x , y , z ;
} ; s t r u c t s p a t i a l _ v e c t o r
{
double a b s ( ) ;
p r i v a t e :
double x , y , z ;
} ;
Добавив в структуру или в класс какой-нибудь метод, програм мист может
потом вызвать этот метод для конкретного объекта. Обращени е к содержимому
объекта выполняется так же, как к содержимому структурной п еременной: с
использованием операции . (либо операции ->, если нужн о обратиться по
указателю на объект).
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 273
m a i n ( )
{
s p a t i a l _ v e c t o r a , b ;
double d ;
. . . . . . .
d = a . a b s ( ) ;
}
Очевидно, что функция abs(), объявленная в классе spatial_vector, воз-
вращает абсолютное значение вектора. Однако для того, чтобы программа ском-
пилировалась, после объявления функцию abs()нужно ещё определить (т. е.
написать тело этой функции). Определение метода выполняет ся так же, как
обычной функции, только в имени метода нужно указать, что он принадлежит
конкретному классу. Для этого используется оператор расширения области види-
мости :: . Имя класса записывается перед именем функции, отделённо е двой-
ным двоеточием. Например, в следующем примере мы объявим всё тот же класс
spatial_vector с двумя методами (установить значения координат вектора и
посчитать его модуль) и опишем эти методы:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{ double x , y , z ;
p u b l i c :
v o i d s e t (double a ,double b ,double c ) ;
double a b s ( ) ;
} ;
v o i d s p a t i a l _ v e c t o r : : s e t ( doublea ,double b ,double c )
{ x=a ; y=b ; z=c ;
}
double s p a t i a l _ v e c t o r : : a b s ( )
{ r e t u r n s q r t ( x∗x + y ∗y + z ∗z ) ;
}
m a i n ( ) {
s p a t i a l _ v e c t o r a ;
a . s e t ( 1 , 2 , 3 ) ;
c o u t << a . a b s ( ) << e n d l ;
}
10.2.2 Создание и удаление объекта: конструкторы и деструктор ы
Как читатель безусловно помнит, принципы ООП гласят, что св ойства, описы-
вающие состояние объекта, должны находиться в закрытой секц ии, чтобы доступ
к ним осуществлялся через вызов методов объекта. Из-за этог о в приведённом
выше примере для класса spatial_vectorмы использовали метод set, устанав-
ливающий значения его переменных. Вообще, традиционным спо собом доступа
к закрытым переменным класса будет добавление пар методов с именами, состо-
ящих из имени переменной и префиксов get для чтения и set для записи
(т. н. геттеры и сеттеры ):
c l a s s s p a t i a l _ v e c t o r
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

274Глава 10. Объектно-ориентированное программирование
{
double x , y , z ;
p u b l i c :
double g e t _ x ( ) ;
v o i d s e t _ x ( double x ) ;
. . . .
double s p a t i a l _ v e c t o r : : g e t _ x ( ) { r e t u r nx ; }
. . . .
}
Этот способ является неудобным, т. к. при большом количеств е переменных
требует множества тривиальных описаний. Его следует приме нять только для
тех свойств класса, внешний доступ к которым действительно необходим.
Однако есть особая ситуация, когда требуется за один раз при своить значе-
ния переменным-членам класса (всем или большинству): это м омент создания
объекта, т. е. переменной-экземпляра класса. C++ позволяет создать специальный метод, который будет автома тически вы-
зываться для инициализации переменных-членов объекта при его создании. Та-
кой метод называется конструктором. Программист, написавший класс, может
по своему усмотрению включить в конструктор код для присваив ания элементам
начальных значений, динамического выделения памяти и т. д. Если программист
не определил конструктор класса, компилятор самостоятель но сгенерирует кон-
структор по умолчанию (пустой и без входных параметров). Конструктор может вызываться явно или неявно. Компилятор с ам вызывает
конструктор в том месте программы, где создаётся объект кла сса.
У описания конструкторов в C++есть следующие особенности:
• имя конструктора в C++совпадает с именем класса;
• конструктор не возвращает никакое значение, но при описан ии конструк-
тора не используется и ключевое слово void.
Поскольку конструктор удобно использовать для динамическ ого выделения па-
мяти, должен быть также и способ освобождать эту память при у ничтожении
объекта (напомним, что локальные объекты удаляются тогда, к огда они выходят
из области видимости, а глобальные объекты удаляются при зав ершении про-
граммы). Действительно, функцией, обратной конструктору , являетсядеструк-
тор . Эта функция вызывается при удалении объекта.
В C++ деструкторы имеют имена, состоящие из имени класса с префикс ом-
тильдой: ˜имя_класса . Как и конструктор, деструктор не возвращает никакое
значение, но в отличие от конструктора он не может быть вызва н явно. Причины
такого ограничения очевидны: код, предположительно освоб ождающий динами-
ческую память, будет обязательно вызван при выходе из облас ти видимости. Его
явный вызов привёл бы к тому, что память уже освободилась зар анее, а при уни-
чтожении объекта программа попыталась бы сделать это снова и сгенерировала
бы ошибку.
Конструктор не может быть описан в закрытой части класса. В о бщем слу-
чае то же ограничение накладывают и на деструктор. В следующем примере
мы создаём объект, вызываем его метод, а затем разрушаем при завершении
программы:
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 275
#i n c l u d e< i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{
double x , y , z ;
p u b l i c :
s p a t i a l _ v e c t o r ( ) ;
~ s p a t i a l _ v e c t o r ( ) { c o u t << " Работа деструктора \ n "; }
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y + z ∗z ) ; }
} ;
s p a t i a l _ v e c t o r : : s p a t i a l _ v e c t o r ( )
{ / /конструктор класса v e c t o r
x=y=z = 0 ; c o u t << " Работа конструктора \ n " ;
}
m a i n ( )
{
s p a t i a l _ v e c t o r a ; / /создаётся объект a с нулевыми значениями
c o u t << a . a b s ( ) << e n d l ;
}
Будучи выполнена, программа выводит следующие сообщения:
Работа конструктора
0
Работа деструктора
Обратите внимание на то, что тела функции abs()и деструктора были опи-
саны непосредственно при объявлении, внутри описания клас са. Такой подход
обычно применяют для очень простых и коротких методов с триви альным со-
держимым. В соответствии с традицией, унаследованной от яз ыка С, описания
классов в больших программах на C++обычно выносятся в заголовочные файлы,
в отличие от описания методов. Однако помещение описания пр остых методов
внутрь описания класса имеет дополнительный практический смысл. Компиля-
тор пытается сделать код таких методов встроенным(англ. inline). Это означа-
ет, что при обращении к методу вызов соответствующей функции будет заменён
непосредственно на её код. Благодаря такому трюку массовое о бращение к свой-
ствам класса через его методы (геттеры или сеттеры) не обяза тельно снижает
производительность в сравнении с тем, если бы свойства нахо дились в открытой
секции.
10.2.3 Передача параметров в конструкторы
В рассмотренном примере мы использовали конструктор по умо лчанию, т. е.
без параметров. Однако, как любая другая функция, конструкт оры могут иметь
параметры. Значения параметров можно передать конструкто ру при создании
объекта, в качестве аргументов:
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{
double x , y , z ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

276Глава 10. Объектно-ориентированное программирование
p u b l i c:
s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) ;
~ s p a t i a l _ v e c t o r ( ) { c o u t << " Работа деструктора \ n "; }
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y + z ∗z ) ; }
} ;
s p a t i a l _ v e c t o r : : s p a t i a l _ v e c t o r ( doublex1 ,double y1 ,double z 1 )
{
x = x 1 ;
y = y 1 ;z = z 1 ;c o u t << " Работа конструктора \ n " ;
}
m a i n ( ) {
s p a t i a l _ v e c t o r a ( 3 , 4 , 0 ) ;
}
В отличие от конструктора, деструктор не может иметь параме тров. Это не
удивительно: поскольку деструктор не вызывается явно, пер едавать ему пара-
метры некому.
10.2.4 Указатель this
Понятно, что свойства занимают место в памяти для каждого объ екта(соб-
ственно, значениями свойств объекты и отличаются друг от друга). Однако
нет никакой причины создавать для каждого нового объекта ко пии всех методов
класса. Поэтому методы класса хранятся в единственном экзе мпляре.
Вместо бессмысленного расхода памяти на идентичные дублик аты методов,
мы обращаемся к коду метода, передавая ему контекст вызова указание на
то, для какого объекта этот метод в данный момент вызван. Кон текст передаётся
с помощью дополнительного скрытого параметра, который фун кция-член класса
получает в момент вызова: это указатель на переменную-экзем пляр класса, для
которого функция вызвана. Этот указатель имеет имя this. Если в теле метода
используется переменная, которая не описана в нём и не являе тся глобальной,
автоматически считается, что она является членом класса и п ринадлежит пере-
менной this.
При желании программист может явно использовать этот указа тель  на-
пример, если имена аргументов метода совпадают с именами пер еменных-членов
класса. Посмотрим как это выглядит на примере конструктора для некоторого
класса point, содержащего координаты двумерной точки:
. . . .
c l a s s p o i n t
{
i n t x , y ;
p u b l i c :
p o i n t ( i n tx ,i n t y )
{
t h i s −>x=x ; t h i s−>y=y ;
}
. . . .
}
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 277
10.2.5 Дружественные функции
Иногда использование методов для доступа к защищённым элем ентам класса
из внешней среды может оказаться неудобным. На такой случай предусмотрен
специальный обходной путь.
Чтобы класс мог предоставлять внешним функциям доступ к сво ей закры-
той части, используется механизм объявления дружественны х функций (friend)
класса. Внутрь описания класса помещается прототип функци и, перед которым
ставится ключевое слово friend. В качестве примера, рассмотрим всё тот же
класс point. Объявим дружественную этому классу функцию find_point, вы-
полняющую поиск точки с заданными координатами в массиве объ ектов. Пусть
функция принимает три аргумента: указатели на первый и посл едний элементы
массива, среди которых нужно выполнять поиск, а также собст венно аргумент
поиска, т. е. точку с искомыми координатами. c l a s s p o i n t
{ p r i v a t e :
i n t x , y ;
. . . . . .
f r i e n d v o i d f i n d _ p o i n t ( p o i n t ∗f i r s t , p o i n t ∗l a s t , p o i n t a r g ) ;
} ;
v o i d f i n d _ p o i n t ( p o i n t ∗f i r s t , p o i n t ∗l a s t , p o i n t a r g )
{ f o r ( p o i n t ∗p= f i r s t ; p<= l a s t ; p++)
i f ( ( p−>x == a r g . x ) && ( p −>y == a r g . y ) )
c o u t << " Точка с координатами " << p−>x << " , "<< p−>y << " найдена \ n " ;
}
Важно понимать, что функция find_point()не является членом класса
point , хотя и имеет доступ к его закрытой части.
Одна и та же функция может быть другом двух и более классов. Ин капсу-
ляция при этом не страдает, т. к. исключительные права для вне шней функции
предусмотрены в самом классе.
Функция-элемент одного класса может быть дружественной др угому классу.
Например: c l a s s x
{
. . . . . .
p u b l i c :
v o i d f ( ) { } ;
} ;
c l a s s y
{ . . . . . .
f r i e n d v o i d x : : f ( ) ;
} ;
Если все функции одного класса дружественны другому классу , можно ис-
пользовать сокращённую запись: c l a s s y
{
/ / . . .f r i e n d c l a s s x ;
} ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

278Глава 10. Объектно-ориентированное программирование
10.2.6 Статические свойства и методы класса
ВC++ предусмотрен дополнительный способ совместного использо вания эле-
мента данных несколькими объектами  статические члены кла сса.
Одно из типичных применений этого механизма  быстрый и эффе ктивный
обмен информацией между однотипными объектами за счёт обще й переменной.
Другой причиной применения может оказаться желание уменьш ить расход па-
мяти в случае, если какое-то свойство класса может менять св оё значение только
одновременно для всех объектов, и таких объектов в программ е много.
Чтобы объявить статический элемент класса, перед ним необх одимо указать
ключевое слово static. Для примера добавим в класс pointстатическое свойство
count  счётчик, указывающий, сколько экземпляров данного класса существует
в памяти в настоящий момент. Очевидно, что управлять содерж имым счётчика
будут конструктор и деструктор класса.
#i n c l u d e
u s i n g namespace s t d ;
c l a s s p o i n t
{
i n t x , y ;
/ / . . . s t a t i c i n t c o u n t ;
p u b l i c :
p o i n t ( ) { c o u t << " Создаётся точка с номером " << ++c o u n t << e n d l ; }
~ p o i n t ( ) { c o u t << " Разрушается точка с номером " << c o u n t−−<< e n d l ; }
} ;
i n t p o i n t : : c o u n t ;
m a i n ( ) { p o i n t a , b , c ;
}
Помимо соответствующего описания в классе, статическая пер еменная-член
класса должна быть дополнительно объявлена в программе в ка честве глобаль-
ной переменной с указанием её принадлежности классу (см. в п римере строку
перед описанием функции main). В сущности, статические свойства и являются
глобальными переменными, с ограниченной областью видимос ти. В результате
выполнения программа сначала создаст, а потом разрушит три объекта класса
point , выведя об этом соответствующие сообщения:
Создаётся точка с номером 1
Создаётся точка с номером 2
Создаётся точка с номером 3
Разрушается точка с номером 3
Разрушается точка с номером 2
Разрушается точка с номером 1
Метод класса также можно объявить статическим. Такой метод будет вести
себя одинаково для всех объектов, т. е. не будет различать, д ля какого именно
объекта он вызван. По этой причине статическим методам не пе редаётся скры-
тый указатель this. Однако взамен статические методы получают преимуще-
ство: их можно вызвать, не создавая объект класса. Например , статическими
могут быть содержащиеся в классе сервисные функции, если он и не используют
никаких данных объекта, т. е. сам контекст вызоваим по сути не нужен.
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 279
На этот раз примером будет классalarm, предназначенный для рабо-
ты с будильником и среди прочего содержащий в себе служебный метод
current_time() , выводящий на экран текущее время. Поскольку этот метод ис-
пользует служебную функцию операционной системы и не нужда ется в свой-
ствах объекта, мы можем сделать его статическим. Остальные методы класса
для простоты опустим.
#i n c l u d e
#i n c l u d e
u s i n g namespace s t d ;
c l a s s a l a r m
{
t i m e _ t a l a r m _ t ;
p u b l i c :
s t a t i c v o i d c u r r e n t _ t i m e ( ) ;
/ / . . . .
} ;
v o i d a l a r m : : c u r r e n t _ t i m e ( )
{
t i m e _ t t = t i m e (NULL) ; / /получаем текущее время в нотации Unix, в виде числа секунд,
/ / прошедших с 1 января 1970 г.
s t r u c t tm tm = ∗l o c a l t i m e (& t ) ; / /переводим в местное текущее время
c o u t << tm . tm_hour << ’ : ’<< tm . tm_min << ’ : ’<< tm . t m _ s e c << e n d l ;
}
m a i n ( ) {
a l a r m : : c u r r e n t _ t i m e ( ) ;
}
Как видно из примера, для доступа к статическому методу клас са без указа-
ния объекта достаточно всего лишь написать перед именем мет ода имя класса и
поставить оператор разрешения области видимости.
10.2.7 Перегрузка операторов
Как уже упоминалось, перегрузка, т. е. возможность создава ть функции (на-
пример, методы класса) с одинаковыми именами и разными набо рами парамет-
ров, вызываемые в разных ситуациях для решения однотипных з адач  это одно
из ключевых проявлений полиморфизма в C++. Однако кроме перегрузки функ-
ций C++позволяет проделывать то же самое с большинством стандартн ых опе-
раторов.
На самом деле, можно считать, что перегрузка операторов для стандартных
типов данных в неявном виде присутствовала ещё в языке С. Нап ример, опе-
ратор деления может выполнять разные действия в зависимост и от того, какой
тип имеют его аргументы: для целочисленных аргументов будет выполнено деле-
ние нацело, а для вещественных  деление чисел с плавающей точ кой. С точки
зрения процессора деление чисел с плавающей точкой кардинал ьно отличается
от деления нацело: задействована другая машинная команда, операнды должны
быть загружены в совсем другие регистры (ячейки памяти проц ессора), после
чего выполняется совсем другая микропрограмма. На более вы соком уровне аб-
стракции операции целочисленного и вещественного деления могут казаться оди-
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

280Глава 10. Объектно-ориентированное программирование
наковыми; однако использование для них одного и того же опер атора допускают
далеко не все языки. ВC++ это явление довели до логического завершения, и теперь мног ие встро-
енные операторы можно перегрузить для работы с новыми типам и данных. Что-
бы перегрузить оператор, программист объявляет новую функ цию, имя которой
состоит из ключевого слова operatorи знака операции. Например, перегрузим
оператор + для сложения двух объектов класса spatial_vector. Объявление
функции будет выглядеть следующим образом: s p a t i a l _ v e c t o r o p e r a t o r+ ( s p a t i a l _ v e c t o r a , s p a t i a l _ v e c t o r b )
{
. . . . . . . . . .
}
Нам понадобится предусмотреть в классе spatial_vectorгеттеры и сеттеры
для всех трёх координат, чтобы внешняя функция могла выполн ить покоорди-
натное сложение двух векторов (либо мы могли бы объявить фун кцию друже-
ственной классу). Также мы предусмотрим в классе конструкт ор, инициализиру-
ющий координаты заданными значениями, и метод info, выводящий координаты
вектора на экран.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{
double x , y , z ;
p u b l i c :
s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) {t h i s −>x=x ; t h i s−>y=y ; t h i s−>z=z ; }
double g e t _ x ( ) { r e t u r nx ; }
double g e t _ y ( ) { r e t u r ny ; }
double g e t _ z ( ) { r e t u r nz ; }
v o i d s e t _ x ( double x ) {t h i s−>x=x ; }
v o i d s e t _ y ( double y ) {t h i s−>y=y ; }
v o i d s e t _ z ( double z ) {t h i s−>z=z ; }
v o i d i n f o ( ) { c o u t << " Координаты вектора : " < } ;
s p a t i a l _ v e c t o r o p e r a t o r+ ( s p a t i a l _ v e c t o r a , s p a t i a l _ v e c t o r b )
{ s p a t i a l _ v e c t o r c ( 0 , 0 , 0 ) ;
c . s e t _ x ( a . g e t _ x ( ) + b . g e t _ x ( ) ) ;
c . s e t _ y ( a . g e t _ y ( ) + b . g e t _ y ( ) ) ;
c . s e t _ z ( a . g e t _ z ( ) + b . g e t _ z ( ) ) ;
r e t u r n c ;
}
m a i n ( ) {
s p a t i a l _ v e c t o r a ( 1 , 2 , 3 ) , b ( 1 0 , 2 0 , 3 0 ) , c ( 0 , 0 , 0 ) ;
c=a+b ;
c . i n f o ( ) ;
}
• оператор должен уже существовать в языке (нельзя добавить в программу
новые, не существовавшие ранее операторы);
• нельзя изменить количество операндов, которое принимает перегружаемый
оператор;
• нельзя переопределять действия встроенных в C++операторов при работе
со встроенными типами данных: например, нельзя перегрузит ь оператор
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 281
+ для работы с целыми числами типа int(а если вдруг это зачем-то по-
надобится, можно создать класс-обёртку, например integer, и перегружать
для него все что угодно);
• нельзя перегружать операторы ., .*, ?:, ::;
• по вполне очевидной причине нельзя перегружать знак дирек тивы препро-
цессора #.
10.2.8 Перегрузка членов класса Члены класса можно перегружать так же, как любые другие функц ии. Осо-
бенно часто перегрузку используют для объявления нескольки х конструкторов.
Главный смысл перегрузки конструкторов состоит в том, чтоб ы предоставить
программисту наиболее удобный для каждой конкретной ситуа ции способ ини-
циализации объекта. Например, мы можем объявить два констр уктора в классе
spatial_vector : один конструктор по умолчанию, создающий вектор с нулевы-
ми значениями, а другой  принимающий конкретные параметры:
c l a s s s p a t i a l _ v e c t o r
{ double x , y , z ;
p u b l i c :
s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) ;
s p a t i a l _ v e c t o r ( ) ;
. . . .
} ;
Однако заметим, что если код двух конструкторов практическ и идентичен и
различается лишь использованием переданных значений в одн ом конструкторе
и констант  в другом, то запись можно упростить. В такой ситу ации можно
оставить только конструктор с параметрами и задать для этих параметров (для
всех или для нескольких, идущих последними в списке) значен ия по умолчанию:
s p a t i a l _ v e c t o r ( doublex = 0 ,double y = 0 ,double z =0) ;
Параметры, имеющие значение по умолчанию, можно не указывать при вы-
зове.
Операторы тоже можно перегружать как члены класса, но с неко торыми ин-
тересными особенностями. Если мы вызываем в программе мето д класса  его
вызов будет указан после имени конкретного объекта. Как чит атель безусловно
помнит, при этом методу передаётся скрытый указатель на объ ект. Если пере-
груженный оператор объявлен как член класса, то компилятор , встретив его
вызов, должен определить, для какого объекта вызвана перег ружающая опера-
тор функция, и тоже передать ей скрытый указатель на объект. Таким объектом
всегда является левый операнд. По этой причине в объявлении перегруженного
оператора внутри класса нет необходимости упоминать собст венный объект 
ведь он передаётся скрытым указателем this. Поэтому описание бинарного опе-
ратора, перегруженного как член класса, имеет всего один оп еранд (правый), а
описание унарного оператора не имеет ни одного операнда.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

282Глава 10. Объектно-ориентированное программирование
Следует отметить, что нельзя объявить оператор как статиче ский метод (по-
скольку статическим методам указатель thisпри вызове не передаётся) или
использовать с оператором аргументы по умолчанию
Для одного и того же оператора можно объявить несколько пере груженных
операторов-функций. Но, как и в случае перегрузки обычных ф ункций, компи-
лятор должен различать их по типу и количеству аргументов. К огда компилятор
сталкивается с перегруженным оператором для класса X, он ищет подходящую
функцию-оператор для класса Х, используя обычные для перегруженных функ-
ций правила сопоставления аргументов. Если поиск завершил ся неудачей, ком-
пилятор не пытается самостоятельно применить к аргументам перегруженных
операторов преобразования типов.
Механизм дружественных функций часто используется при пер егрузке опе-
раторов для работы с объектами, когда по какой-то причине пе регруженный
оператор невозможно или нецелесообразно объявлять членом класса. Для срав-
нения изменим фрагмент примера из п. 10.2.7, переопределив оператор + как
функцию-член класса (слева) и как дружественную функцию (сп рава):
c l a s ss p a t i a l _ v e c t o r
{ . . . . .
s p a t i a l _ v e c t o r o p e r a t o r+(
s p a t i a l _ v e c t o r b ) ;
} ;
s p a t i a l _ v e c t o r s p a t i a l _ v e c t o r : : o p e r a t o r +( s p a t i a l _ v e c t o r b )
{ s p a t i a l _ v e c t o r c ;
c . x = x + b . x ;
c . y = y + b . y ;
c . z = z + b . z ;
r e t u r n c ;
} c l a s s s p a t i a l _ v e c t o r
{ . . . . .
f r i e n d s p a t i a l _ v e c t o r o p e r a t o r+(
s p a t i a l _ v e c t o r a , s p a t i a l _ v e c t o r b ) ;
} ;
s p a t i a l _ v e c t o r o p e r a t o r+(
s p a t i a l _ v e c t o r a , s p a t i a l _ v e c t o r b )
{ s p a t i a l _ v e c t o r c ;
c . x = a . x + b . x ;
c . y = a . y + b . y ;
c . z = a . z + b . z ;
r e t u r n c ;
}
Классический пример перегрузки оператора как дружественн ой функции 
средства стандартного ввода-вывода в C++. Как известно, операции <<и>> вы-
полняют ввод и вывод, если левым аргументом указан один из ста ндартных объ-
ектов ввода-вывода. Предопределённые объекты cin(клавиатура) и cout(дис-
плей)  экземпляры классов istreamиostream . Этим способом можно вывести
любой базовый тип данных C++. Однако, на самом деле при выводе вызывается
функция, перегружающая оператор. В частности, для объекта coutбудет вы-
звана функция, имеющая приблизительно следующий вид: o s t r e a m o p e r a t o r<<( o s t r e a m , i n t)
В результате, выражение
c o u t << " Значение переменной i равно " << i <<’ \ n ’;
благодаря такой подстановке будет заменено на o p e r a t o r <<(o p e r a t o r <<(o p e r a t o r <<( c o u t , " Значение переменной i равно " ) , i ) ,’ \ n ’) ;
Программирование на языке С++ в среде Qt Creator

10.2. Классы и объекты вC++ 283
Понятно, что библиотекаiostreamсодержит функции только для встроен-
ных типов. Если требуется перегрузить операторы стандартн ого ввода-вывода
для нового класса, чтобы программист мог вводить с консоли е го информаци-
онное содержимое или выполнять его вывод на экран, необходи мо перегрузить
оператор для нового типа.
Использовать перегрузку оператора как члена класса невозм ожно, т. к. ле-
вым аргументом должен быть не объект нового класса, а уже сущ ествующие
объекты cinиcout . Таким образом, перегружать оператор приходится как внеш-
нюю функцию. Однако поскольку эту функцию создаёт автор новог о класса, он
вполне может объявить её в структуре класса как дружественн ую, упростив ей
доступ к закрытой части класса.
В общем виде операция вывода имеет следующую форму
o s t r e a m& o p e r a t o r<< ( o s t r e a m& s t r e a m , имя_класса& o b j )
{ s t r e a m << . . . / /вывод элементов объекта ob j в поток stream
r e t u r n s t r e a m ;
}
Аналогичным образом может быть определена функция ввода: i s t r e a m& o p e r a t o r>> ( i s t r e a m& s t r e a m , имя_класса& o b j )
{ s t r e a m >> . . . / /ввод элементов объекта ob j из потока stream
r e t u r n s t r e a m ;
}
Знак & в списке формальных параметров означает, что компилятор о бес-
печивает скрытую передачу параметра не по значению, а по ссыл ке (передача
объектов по ссылке детально рассмотрена далее, в п. 10.3.2. Первый аргумент
функций ввода и вывода определён как ссылка на поток, второй аргумент 
ссылка на объект, выводящий или получающий информацию, а возв ращаемое
значение  тот же самый объект потока, который был передан в к ачестве пер-
вого аргумента.
Приведём пример с перегрузкой операторов стандартного вво да и вывода для
уже знакомого нам класса spatial_vector.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{
double x , y , z ;
p u b l i c :
s p a t i a l _ v e c t o r ( ) { x=y=z = 0 ; }
f r i e n d o s t r e a m& o p e r a t o r<< ( o s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b ) ;
f r i e n d i s t r e a m& o p e r a t o r>> ( i s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b ) ;
} ;
o s t r e a m& o p e r a t o r<< ( o s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b )
{ s t r e a m << " x = "<< b . x << " ; y = "<< b . y << " ; z = "<< b . z << e n d l ;
r e t u r n s t r e a m ;
}
i s t r e a m& o p e r a t o r>> ( i s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b )
{ s t r e a m >> b . x >> b . y >> b . z ;
r e t u r n s t r e a m ;
}
m a i n ( )
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

284Глава 10. Объектно-ориентированное программирование
{
s p a t i a l _ v e c t o r a ;
c i n >> a ;
c o u t << " Был введён вектор: " << a << e n d l ;
}
10.2.9 Перегрузка постфиксных операторов Большинство операций, поддерживаемых C++, являются префиксными, т. е.
оператор применяется до вычисления выражения. Исключение с оставляют опе-
раторы инкремента и декремента ++и-- , которые могут быть как префиксными,
так и постфиксными. При перегрузке постфиксных операций во зникают опреде-
лённые неудобства: например, программист должен иметь воз можность как-то
показать компилятору, что перегружает именно постфиксный оператор .
Объявление члена класса с именем operator++без аргументов перегружа-
ет префиксный оператор инкремента. Чтобы перегрузить функ цию-член класса
как постфиксный оператор, его нужно объявить с одним аргуме нтом типаint.
Этот аргумент не несёт никакой полезной нагрузки и нужен тол ько, чтобы мож-
но было различить префиксные и постфиксные операторы. При в ыполнении этот
аргумент будет иметь нулевое значение. Следующий пример пок азывает разницу
в описаниях, и дополнительно выводит в консоль информацию о том, префикс-
ный или постфиксный оператор был использован. В примере исп ользован класс
integer , являющийся обёрткой над переменной типа int, т. е. просто хранящий
целое число:
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
c l a s s i n t e g e r
{
i n t v a l u e ;
p u b l i c :
i n t e g e r ( ) { v a l u e = 0 ; }
i n t e g e r & o p e r a t o r++() ; / /префиксный оператор
i n t e g e r & o p e r a t o r++(i n t) ;/ /постфиксный оператор
} ; i n t e g e r & i n t e g e r : : o p e r a t o r++()
{ v a l u e +=1;
c o u t << " Использован префиксный оператор \ n " ;
r e t u r n ∗t h i s ;
} i n t e g e r & i n t e g e r : : o p e r a t o r++(i n t)
{
v a l u e +=1;
c o u t << " Использован постфиксный оператор \ n " ;
r e t u r n ∗t h i s ;
}
m a i n ( ) { i n t e g e r i ;
i ++; / /используется постфиксный оператор
++ i ; / /используется префиксный оператор
}
Заметим, что в приведённом примере оператор постфиксного и нкремента реа-
лизован не совсем корректно и по действию не отличается от пр ефиксной формы.
Программирование на языке С++ в среде Qt Creator

10.3. Создание и удаление объектов285
Если требуется реализовать в программе его полноценный функционал, т. е. из-
менение аргумента после возврата его исходного значения, д ля этого в теле опе-
ратора создаётся и потом возвращается временный объект  ко пия исходного
аргумента. Подробнее особенности передачи временной копи и объекта рассмат-
риваются в следующих подразделах, а пример с полнофункционал ьной формой
постфиксных операторов с дополнительными пояснениями мож но найти в конце
п. 10.3.3.
10.3 Создание и удаление объектов
10.3.1 Присваивание объектов, передача в функцию и возвращ ение
объекта
Можно заметить, что в ряде случаев (например, при перегрузк е операторов)
мы использовали передачу объекта в функцию и возвращение не по значению,
а с использованием ссылки. Для этого существует достаточно веская причина:
передача объектов по значению, равно как и их присваивание, м ожет приводить
к нежелательным последствиям.
Один объект можно присвоить другому, если оба объекта имеют о динако-
вый тип (если объекты имеют разные типы, то компилятор выдаст сообщение
об ошибке). По умолчанию, когда объект Aприсваивается объекту B, то осу-
ществляется побитовое копирование всех элементов-данных Aв соответствую-
щие элементы-данные B. Именно это копирование и является потенциальным
источником проблем. Особенно внимательным нужно быть при п рисваивании
объектов, имеющих свойства-указатели.
Рассмотрим в качестве примера класс matrix, хранящий в себе прямоуголь-
ную матрицу из элементов типа double. Размерность матрицы будет передавать-
ся конструктору класса, после чего будет выполняться динам ическое выделение
памяти под нужное количество элементов. В классе будут такж е предусмотре-
ны методы get_val()чтобы получить элемент матрицы с индексами (i,j)и
set_val() чтобы установить в заданный элемент новое значение.
Однако присвоив просто так одну переменную типа matrixдругой, мы не
сможем избежать побочных эффектов.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
c l a s s m a t r i x
{
double ∗m ; / /элементы матрицы
s i z e _ t w i d t h , h e i g h t ; / /число строк и столбцов в матрице
p u b l i c :
m a t r i x ( s i z e _ t w , s i z e _ t h ) ;
double g e t _ v a l ( s i z e _ t i , s i z e _ t j ) ;
v o i d s e t _ v a l ( s i z e _ t i , s i z e _ t j , doublev a l ) ;
~ m a t r i x ( ) ;
} ;
m a t r i x : : m a t r i x ( s i z e _ t w , s i z e _ t h )
{ m = new double [ w∗h ] ;
w i d t h = w ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

286Глава 10. Объектно-ориентированное программирование
h e i g h t = h ;
}
m a t r i x : : ~ m a t r i x ( )
{
d e l e t e [ ] m ;
}
double m a t r i x : : g e t _ v a l ( s i z e _ t i , s i z e _ t j )
{ r e t u r n m [ i∗w i d t h+ j ] ; / /получить значение элемента матрицы в позиции [i,j]
} v o i d m a t r i x : : s e t _ v a l ( s i z e _ t i , s i z e _ t j , doublev a l )
{
/ /устанавливаем значение элемента матрицы в позиции [i,j]
/ / если координаты не превышают размер матрицы
i f ( ( i }
m a i n ( ) {
m a t r i x a ( 2 , 2 ) ; / /объявляем матрицу размерности 2 х 2
a . s e t _ v a l ( 0 , 0 , 1 0 0 ) ; / /устанавливаем a[0,0] = 100
m a t r i x b=a ; / /присваиваем матрицу
b . s e t _ v a l ( 0 , 0 , 2 0 0 ) ; / /устанавливаем b[0,0] = 200
c o u t << " a [ 0 , 0 ] = " << a . g e t _ v a l ( 0 , 0 ) << " ; "<<" b [ 0 , 0 ] = " << a . g e t _ v a l
( 0 , 0 ) << e n d l ;
}
При запуске программа выдаёт сообщение a[0,0] = 200; b[0,0] = 200
вместо ожидаемого a[0,0]=100, после чего и вовсе аварийно завершается с
сообщением о попытке дважды освободить память. На самом дел е это проис-
ходит по вполне очевидной причине. При побитовом копирован ии скопировался
адрес указателя m, а не содержимое блока памяти, динамически выделенного по
этому адресу. В результате оба объекта получают указатель на одну и ту же
последовательность вещественных чисел.
Аналогично присваиванию, объекты можно передавать в функции в каче-
стве аргументов, в точности так, как передаются данные други х типов. Однако
следует помнить, что в C++по-умолчанию параметры передаются по значению.
Это означает, что внутри функции (а точнее, в стеке) создаёт ся копия объекта-
аргумента, и эта копия, а не сам объект, будет далее использо ваться функцией.
Благодаря этому функции могут произвольно изменять переда нные значения,
не влияя на оригинал.
Итак, при передаче объекта в функцию создаётся новый объект , а когда рабо-
та функции завершается, копия переданного объекта будет ра зрушена. Как все-
гда при разрушении объектов, при этом будет вызван деструкт ор копии. И здесь
может наблюдаться очередной побочный эффект: если передан ный в качестве па-
раметра объект содержит в себе указатель на динамически выд еленную область
памяти, деструктор копии её освободит. Но так как копия созд авалась побито-
вым копированием, деструктор копии высвободит область пам яти, на которую
указывал объект-оригинал. Исходный объект будет по-прежн ему видеть свои
данные по указанному адресу, однако для системы эта память б удет считаться
свободной. Рано или поздно она будет выделена какому-то дру гому объекту, и
данные окажутся затёрты.
Программирование на языке С++ в среде Qt Creator

10.3. Создание и удаление объектов287
Кроме возможности преждевременного разрушения объекта-оригинала, к
аварийной ситуации приведёт вызов его деструктора (в конце работы программы
или при выходе из соответствующей области видимости), котор ый попытается
освободить уже свободную память. Та же проблема возникает п ри использова-
нии объекта в качестве возвращаемого значения.
Во всех трёх случаях (при присваивании объекта, при использ овании его как
параметра и при передаче в качестве возвращаемого значения ) если деструк-
тор высвобождает динамически выделенную память, то разруш ение временного
объекта приведёт к преждевременному разрушению данных ори гинала.
Частично проблема может быть решена перегрузкой оператора присваивания
для данного класса. Кроме того, для объектов, которым проти вопоказано поби-
товое копирование, рекомендуется создавать особую разнов идность конструк-
тора  т. н. конструктор копирования (в некоторых источниках также можно
встретить название конструктор копии). Конструктор коп ирования выполняет
именно то действие, которое заложено в его названии: позвол яет программисту
лично проконтролировать процесс создания копии.
Любой конструктор копирования имеет следующую форму:
имя_класса (c o n s t имя_класса & o b j )
{ . . . / /тело конструктора
}
Читатель должен помнить, что в таком описании & obj это ссылка на объ-
ект, известная ещё как скрытый указатель.
Оператор присваивания, перегруженный как член класса, свя зан со своим
классом настолько же тесно, как конструктор и деструктор. Э ту связь подчёрки-
вает то, что оператор копирования разрешено перегружать то лько как функцию-
член класса, и запрещено  как дружественную функцию. Привед ём в качестве
иллюстрации две почти одинаковые записи: p o i n t p1 , p 2 ; / /объявляем два объекта класса point
p o i n t p 3 = p 2 ; / /используем конструктор копирования
p 1 = p 2 ; / /используем оператор присваивания
Во второй строке примера переменная p3и объявляется и определяется, а в
третьей строке переменной p1всего лишь присваивается значение. Иными слова-
ми, конструктор копирования вызывается для конкретной пер еменной за время
её жизни только один раз, а присваивать значения ей можно мно гократно. В
логике работы конструктора копирования и оператора присва ивания настоль-
ко много общего, что часто рекомендуют описывать одну операц ию в терминах
другой. Фактически операция присваивания неявно использу ется в конструкторе
копирования. Однако конструктор копирования может добавл ять дополнитель-
ные действия по инициализации переменных в довесок к тем дей ствиям, которые
должен выполнять оператор присваивания.
Если оператор присваивания для класса не был определён, то в случае необ-
ходимости (если для объектов этого класса в тексте программ ы выполняется
присваивание) компилятор автоматически генерирует оператор присваивания по
умолчанию , выполняющий то самое побитовое копирование объекта.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

288Глава 10. Объектно-ориентированное программирование
10.3.2 Подробнее об указателях и ссылках на объекты
Передача объектов по указателю имеет ряд преимуществ. В сте к копирует-
ся только ячейка памяти, содержащая адрес объекта, и автома тически исчезает
проблема корректного создания копии. Конечно в результате функция взаимо-
действует с оригиналом объекта, что требует осторожного из менения его данных
(а с копией можно делать всё что угодно). Ещё одно дополнител ьное преиму-
щество передачи по адресу в сравнении с передачей по значени ю  экономия
ресурсов на копирование. Если объект занимает достаточно б ольшой объём па-
мяти, его передача в функцию и возвращение из неё, даже будуч и выполнены
корректно, приведут к неоправданным расходам ресурсов.
Недостаток передачи по указателю  худшая читаемость прогр аммы, когда
приходится часто взаимодействовать с адресами объектов. М ногочисленные опе-
рации адресации и разадресации (взятия адреса объекта и взя тия содержимого
по адресу) могут ухудшать визуальное восприятие текста про граммы, особенно
в сочетании со скобками.
По этой причине в C++был введён специальный тип данных  ссылкаили
скрытый указатель . На понятийном уровне ссылку можно воспринимать как
другое имя (псевдоним) переменной. Фактически же это указа тель на перемен-
ную, который выглядит так, как будто к переменной обращаются п о значению:
программист объявляет такую ссылку, присваивает ей какую-л ибо переменную
и далее пользуется ссылкой как ещё одной переменной. Компил ятор же сам ав-
томатически подставляет ко всем обращениям к ссылке операц ии адресации и
разадресации.
Удобнее всего использовать ссылки для передачи параметров и возвращаемых
значений.
Напомним: ссылка объявляется так же как указатель, только с использова-
нием знака & вместо звёздочки. Сравним, как выглядит код при передач е
аргумента по указателю и по ссылке, на примере функции zero(), устанавлива-
ющей в ноль координаты переданного ей объекта класса point:
/ /использование указателей
v o i d z e r o ( p o i n t ∗p )
{
p− > s e t ( 0 , 0 ) ;
/ / мы использовали "− >"
}
m a i n ( ) {
p o i n t a ( 3 , 4 ) ;z e r o (& a ) ;
} / / использование ссылки
v o i d z e r o ( p o i n t &p )
{
p . s e t ( 0 , 0 ) ;
/ / мы использовали " . "
}
m a i n ( ) {
p o i n t a ( 3 , 4 ) ;z e r o ( a ) ;
}
В приведённом примере при применении параметра-ссылки ком пилятор пе-
редаёт адрес переменной, но везде кроме объявления функции код выглядит так,
как будто переменная передана по значению. Аналогично ссылки могут исполь-
зоваться в качестве возвращаемого значения функции. Однак о нельзя забывать,
Программирование на языке С++ в среде Qt Creator

10.3. Создание и удаление объектов289
что функция, в которую передан параметр по ссылке, будет манипулироватьне
копией , а самим оригинальным объектом.
Часто ссылки применяют в сочетании с указателем this. Рассмотрим в каче-
стве примера переопределение оператора присваивания для к лассаpoint:
p o i n t& p o i n t : : o p e r a t o r= ( p o i n t& p )
{ x = p . x ;
y = p . y ;
r e t u r n ∗t h i s ;
}
В объявлении функции мы указали ссылочный тип в качестве как аргумен-
та, так и возвращаемого значения. Оператор присваивания до лжен возвращать
результат операции, чтобы стало возможным каскадное присв аивание наподобие
a=b=c=0 . В качестве возвращаемого значения мы указываем разадресо ванный
указатель this, однако возвращён в качестве результата будет тот объект, к ото-
рый вызывал операцию =, а не его копия.
Приведём модифицированный вариант класса matrix, имеющий как кон-
структор копирования, так и оператор присваивания, и выдающ ий на экран пра-
вильный результат.
#i n c l u d e < i o s t r e a m >
u s i n g namespace s t d ;
c l a s s m a t r i x
{ double ∗m ; / /элементы матрицы
s i z e _ t w i d t h , h e i g h t ; / /число строк и столбцов в матрице
p u b l i c :
m a t r i x ( s i z e _ t w , s i z e _ t h ) ;
m a t r i x ( c o n s tm a t r i x& m1 ) ; / /конструктор копирования
m a t r i x& o p e r a t o r=( m a t r i x & m1 ) ; / /оператор присваивания
double g e t _ v a l ( s i z e _ t i , s i z e _ t j ) ;
v o i d s e t _ v a l ( s i z e _ t i , s i z e _ t j , doublev a l ) ;
~ m a t r i x ( ) ;
} ;
m a t r i x : : m a t r i x ( s i z e _ t w , s i z e _ t h )
{ m = new double [ w∗h ] ;
w i d t h = w ; h e i g h t = h ;
}
m a t r i x : : m a t r i x ( c o n s tm a t r i x& m1 )
{
/ /устанавливаем размер матрицы и выделяем под неё память:
w i d t h = m1 . w i d t h ;
h e i g h t = m1 . h e i g h t ;
i n t s i z e =w i d t h ∗h e i g h t ;
m = new double [ s i z e ] ;
/ / копируем элементы матрицы:
f o r (i n t i = 0 ; i < s i z e ; i ++)
m [ i ] =m1 . m [ i ] ;
}
m a t r i x& m a t r i x : : o p e r a t o r=( m a t r i x& m1 )
{
i n t s i z e =m1 . w i d t h ∗m1 . h e i g h t ;
i f ( s i z e > w i d t h ∗h e i g h t )
/ / защищаемся от переполнения буфера
s i z e =w i d t h ∗h e i g h t ;
m = new double [ s i z e ] ;
/ / копируем элементы матрицы:
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

290Глава 10. Объектно-ориентированное программирование
f o r(i n t i = 0 ; i < s i z e ; i ++)
m [ i ] =m1 . m [ i ] ;
r e t u r n ∗t h i s ;
}
m a t r i x : : ~ m a t r i x ( )
{ d e l e t e [ ] m ;
}
double m a t r i x : : g e t _ v a l ( s i z e _ t i , s i z e _ t j )
{ / /получить значение элемента матрицы в позиции [i,j]
r e t u r n m [ i∗w i d t h+ j ] ;
} v o i d m a t r i x : : s e t _ v a l ( s i z e _ t i , s i z e _ t j , doublev a l )
{ / /устанавливаем значение элемента матрицы в позиции [i,j].. .
/ / ...если координаты не превышают размер матрицы
i f ( ( i }
m a i n ( ) {
m a t r i x a ( 2 , 2 ) ; / /объявляем матрицу размерности 2 х 2
a . s e t _ v a l ( 0 , 0 , 1 0 0 ) ; / /устанавливаем a[0,0] = 100
m a t r i x b=a ; / /присваиваем матрицу
b . s e t _ v a l ( 0 , 0 , 2 0 0 ) ; / /устанавливаем b[0,0] = 200
c o u t << " a [ 0 , 0 ] = " << a . g e t _ v a l ( 0 , 0 ) << " ; "<<" b [ 0 , 0 ] = " << a . g e t _ v a l
( 0 , 0 ) << e n d l ;
}
Внимательный читатель может заметить в коде примера необыч ную особен-
ность. И конструктор копирования, и оператор присваивания получают доступ
к закрытой части переданного объекта m1. На самом деле это вполне естествен-
но. Вспомним: переменные, объявленные в закрытой секции кл асса, доступны
только для методов этого же класса (а не этого же объекта). Иными словами,
объекты одного класса могут получать доступ к закрытым член ам друг друга,
хотя используется это не так часто.
10.3.3 Пример: класс spatial_vector в сборе
Прежде чем закончить разговор о перегрузке операторов и пер едаче объек-
тов, приведём ещё один пример, наглядно иллюстрирующий, что и ногда передача
объекта по значению может нести практическую пользу. Рассм отрим финаль-
ный вид класса spatial_vector с перегруженными операторами ввода-вывода,
инкремента и декремента обеих форм, а также операторами сло жения и вычи-
тания.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s s p a t i a l _ v e c t o r
{
double x , y , z ;
p u b l i c :
s p a t i a l _ v e c t o r ( doublex = 0 ,double y = 0 ,double z =0) ;
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y + z ∗z ) ; }
double g e t _ x ( ) { r e t u r nx ; }
double g e t _ y ( ) { r e t u r ny ; }
double g e t _ z ( ) { r e t u r nz ; }
v o i d s e t _ x ( double x ) {t h i s−>x=x ; }
Программирование на языке С++ в среде Qt Creator

10.3. Создание и удаление объектов291
v o i ds e t _ y ( double y ) {t h i s−>y=y ; }
v o i d s e t _ z ( double z ) {t h i s−>z=z ; }
v o i d i n f o ( ) ;
s p a t i a l _ v e c t o r& o p e r a t o r++() ; / /префиксная форма
s p a t i a l _ v e c t o r& o p e r a t o r−−() ;
s p a t i a l _ v e c t o r o p e r a t o r++(i n t) ;/ /постфиксная форма
s p a t i a l _ v e c t o r o p e r a t o r−−(i n t ) ;
f r i e n d s p a t i a l _ v e c t o r o p e r a t o r+( s p a t i a l _ v e c t o r a , c o n s ts p a t i a l _ v e c t o r& b ) ;
f r i e n d s p a t i a l _ v e c t o r o p e r a t o r−( s p a t i a l _ v e c t o r a , c o n s ts p a t i a l _ v e c t o r& b ) ;
f r i e n d o s t r e a m& o p e r a t o r<<( o s t r e a m& s t r e a m , c o n s ts p a t i a l _ v e c t o r& b ) ;
f r i e n d i s t r e a m& o p e r a t o r>>( i s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b ) ;
} ;
s p a t i a l _ v e c t o r : : s p a t i a l _ v e c t o r ( doublex1 ,double y1 ,double z 1 )
{
x = x 1 ;
y = y 1 ;z = z 1 ;
}
v o i d s p a t i a l _ v e c t o r : : i n f o ( )
{ c o u t << " Координаты вектора : x = " << x <<" ; y = "<< y << " ; z = "<< z << e n d l ;
c o u t << " Модуль вектора равен " << a b s ( ) << e n d l ;
}
s p a t i a l _ v e c t o r& s p a t i a l _ v e c t o r : : o p e r a t o r++()
{
x++; y++; z ++;r e t u r n ∗t h i s ;
} s p a t i a l _ v e c t o r& s p a t i a l _ v e c t o r : : o p e r a t o r−−()
{
x−− ; y−− ; z−− ;
r e t u r n ∗t h i s ;
} s p a t i a l _ v e c t o r s p a t i a l _ v e c t o r : : o p e r a t o r++(i n t)
{ s p a t i a l _ v e c t o r temp= ∗t h i s ;
++( ∗t h i s ) ;
r e t u r n temp ;
}
s p a t i a l _ v e c t o r s p a t i a l _ v e c t o r : : o p e r a t o r−−(i n t )
{
s p a t i a l _ v e c t o r temp= ∗t h i s ;
−− (∗ t h i s ) ;
r e t u r n temp ;
} s p a t i a l _ v e c t o r o p e r a t o r+ ( s p a t i a l _ v e c t o r a , c o n s ts p a t i a l _ v e c t o r& b )
{ / /передаём первый аргумент по значению,
/ / поэтому можем изменять его, не влияя на исходный объект:
a . x += b . x ;
a . y += b . y ;
a . z += b . z ;
/ / возвращаем изменённую копию первого аргумента:
r e t u r n a ;
}
s p a t i a l _ v e c t o r o p e r a t o r−( s p a t i a l _ v e c t o r a , c o n s ts p a t i a l _ v e c t o r& b )
{ a . x −= b . x ;
a . y −= b . y ;
a . z −= b . z ;
r e t u r n a ;
}
o s t r e a m& o p e r a t o r<<( o s t r e a m& s t r e a m , c o n s ts p a t i a l _ v e c t o r& b )
{
s t r e a m << " x = "<< b . x << " ; y = "<< b . y << " ; z = "<< b . z << e n d l ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

292Глава 10. Объектно-ориентированное программирование
r e t u r ns t r e a m ;
}
i s t r e a m& o p e r a t o r>>( i s t r e a m& s t r e a m , s p a t i a l _ v e c t o r& b )
{
s t r e a m >> b . x >> b . y >> b . z ;
r e t u r n s t r e a m ;
}
m a i n ( ) {
s p a t i a l _ v e c t o r a , b ( 1 , 2 , 3 ) ;
c o u t << " \ n 1. Заполнение вектора через стандартный ввод \ n " ;
c o u t << " Введите координаты вектора: " ;
c i n >> a ;
a . i n f o ( ) ;
c o u t << " \ n 2. Вычитание векторов \ n " ;
s p a t i a l _ v e c t o r c = a −b ;
c o u t << " Координаты вектора с=a-b(1,2,3): " << c ;
c o u t << " \ n 3. Изменение координаты вектора с помощью геттеров и сет теров \ n ";
c . s e t _ x ( c . g e t _ x ( ) +1) ;
c o u t << " После инкремента координаты x, координаты вектора c: " << c ;
c o u t << " \ n 4. Инкремент: \ n вывод с++: " << c ++;
c o u t << " Вывод ++с: " << ++c ;
}
Функция main()просит пользователя ввести с клавиатуры три координаты
вектора, а затем выполняет несколько тестов, демонстрирующ их работу методов
класса. Например, при вводе значений 1 2 3 выводится следу ющий результат:
1. Заполнение вектора через стандартный ввод
Введите координаты вектора: 1 2 3
Координаты вектора: x=1; y=2; z=3
Модуль вектора равен 3.74166
2. Вычитание векторов
Координаты вектора с=a-b(1,2,3): x=0; y=0; z=0
3. Изменение координаты вектора с помощью геттеров и сеттер ов
После инкремента координаты x, координаты вектора c: x=1; y =0; z=0
4. Инкремент:
вывод с++: x=1; y=0; z=0
Вывод ++с: x=3; y=2; z=2
Как можно заметить, в программе не перегружен оператор прис ваивания, а
в классе spatial_vector не задан конструктор копирования. В данном случае
класс не работает с динамической памятью и не нуждается в как ой-то особой
предварительной инициализации и деинициализации, поэтом у выполняемое по
умолчанию побитовое копирование объектов оказывается пол ностью приемле-
мым. Более того, передача параметра по значению активно исп ользуется в пе-
регруженных операторах сложения и вычитания, а также в пост фиксной форме
инкремента и декремента. В первых двух случаях первый парам етр (левый опе-
ранд) передаётся по значению, чтобы можно было изменить его и вернуть, не
затронув исходный объект. В перегруженных постфиксных опе раторах исполь-
зуется возврат исходной побитовой копии объекта, снятой до того, как ориги-
нальный объект был изменён.
Комбинирование в выражениях перегруженных операторов, не которые из ко-
торых используют передачу по ссылке, а некоторые  по значени ю, требует тща-
Программирование на языке С++ в среде Qt Creator

10.4. Наследование293
тельности в оформлении списка параметров. Если возвращённый по значению
результат работы одного оператора может быть принят другим по ссылке, во
избежание конфликтов соответствующий аргумент следует явн о объявить кон-
стантным (см., например, второй параметр оператора потоко вого вывода). На
самом деле использование модификатора constв подобных случаях боле чем
логично, поскольку оператор не изменяет принятый аргумент , а передача по
ссылке используется исключительно для уменьшения накладны х расходов на
копирование объекта.
10.4 Наследование
Наследование классов позволяет строить иерархию, наверху к оторой нахо-
дятся более общие классы, а внизу  более специализированны е. Попробуем
привести наглядный пример иерархии наследования. Предпол ожим, мы создаём
объектно-ориентированную систему работы с графикой, и пре дусмотрели класс
point , описывающий отдельную двумерную точку на экране. В этом кла ссе хра-
нятся координаты точки, её цвет, а также методы для управлен ия этими дан-
ными. При необходимости можно легко создать на базе класса pointпроизвод-
ный класс, хранящий трехмерную вершину (например, vertex): добавить в нём
третью координату, соответствующие конструкторы, модифиц ировать некото-
рые методы. Однако не следует путать отношение наследовани я с отношением
включения. Например, будет нелогичным строить на базе класс аpoint или клас-
са vertex классregion , описывающий объекты с произвольным количеством
вершин: скорее, это должен быть класс-контейнер, содержащ ий в себе массив
объектов pointилиvertex .
Таким образом, есть смысл создавать на базе существующего кл асса произ-
водный, если мы хотим получить частный случай с модифициров анной функци-
ональностью. ВC++ новый класс строится на базе уже существующего с помощью конс трук-
ции следующего вида: c l a s s p a r e n t { . . . . . } ;
c l a s s c h i l d : [ модификатор наследования ] p a r e n t { . . . . . } ;
При определении класса-потомка, за его именем следует разд елитель-
двоеточие :, затем необязательный модификатор наследования и имя роди-
тельского класса. Модификатор наследования определяет ви димость наследу-
емых переменных и методов для класса-потомка и его возможны х потомков.
Таким способом определяется, какие права доступа к перемен ным и методам
класса-родителя будут делегированы классу-потомку. При реализации наследования область видимости принадлежа щих классу
данных и методов можно определять выбором одного из следующи хмодифи-
каторов доступа :
• private (закрытый);
• public (общедоступный);
• protected (защищённый).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

294Глава 10. Объектно-ориентированное программирование
Модификаторы наследования :
• public
• protected
• private Модификаторы доступа :
• public
• protected
• private
c l a s s p o i n t { . . . } ;
c l a s s v e r t e x : p u b l i cp o i n t
{ . . . } ; c l a s s p o i n t
{
p u b l i c :
i n t c o l o r ;
. . .
} ;
Таблица 10.1: Разница между модификаторами наследования и доступа
Модификатор наследования:
Модификатор
доступа: public protected private
public public protected private
protected protected protected private
private нет доступа нет доступа нет доступа
Таблица 10.2: Сочетание модификаторов наследования и доступа
Эти модификаторы могут произвольно чередоваться внутри оп исания класса и
уже использовались нами для обозначения открытых и закрыты х секций класса.
Модификатор privateописывает закрытые члены класса, доступ к которым
имеют только методы-члены этого класса. Модификатор publicпредназначен
для описания общедоступных элементов, доступ к которым воз можен из любого
места в программе, где доступен объект данного класса. Моди фикаторprotected
используется тогда, когда необходимо, чтобы некоторые чле ны базового класса
оставались закрытыми, но были бы доступны из класса-потомк а.
Иными словами, одни и те же ключевые слова могут использовать ся и в
качестве модификаторов наследования, и в качестве модифик аторов доступа:
То, как изменяется доступ к элементам базового класса из мет одов производ-
ного класса в зависимости от значения модификаторов наслед ования, показано
в таблице 10.2.
Из таблицы видно, в производном классе доступ к элементам ба зового класса
может быть сделан более ограниченным, но никогда нельзя сде лать его менее
ограниченным.
Программирование на языке С++ в среде Qt Creator

10.4. Наследование295
10.4.1 Конструкторы и деструкторы при наследовании
Базовый класс, производный класс или оба могут иметь констр укторы и де-
структоры. Если и у базового и у производного классов есть ко нструкторы и
деструкторы, то они срабатывают по очереди: конструкторы вы полняются в по-
рядке наследования, а деструкторы  в обратном порядке.
#i n c l u d e
u s i n g namespace s t d ;
c l a s s p a r e n t
{ p u b l i c :
p a r e n t ( ) { c o u t << " Работа конструктора базового класса \ n " ; }
~ p a r e n t ( ) { c o u t << " Работа деструктора базового класса \ n " ; }
} ;
c l a s s c h i l d : p u b l i c p a r e n t
{
p u b l i c :
c h i l d ( ) { c o u t << " Работа конструктора производного класса \ n " ; }
~ c h i l d ( ) { c o u t << " Работа деструктора производного класса \ n " ; }
} ;
m a i n ( )
{ c h i l d c 1 ;
}
Выполнение этой предельно простой программы иллюстрирует п орядок сра-
батывания конструкторов и деструкторов. Результат её рабо ты следующим об-
разом отображается на экране:
Работа конструктора базового класса
Работа конструктора производного класса
Работа деструктора производного класса
Работа деструктора базового класса
При реализации наследования может возникнуть ситуация, ко гда конструк-
тор базового или производного класса требует параметры. Ес ли параметры нуж-
но передать только конструктору производного класса, они п ередаются обыч-
ным способом. Если требуется передать какие-либо аргумент ы родительскому
конструктору, для этого используется расширенная запись к онструктора произ-
водного класса:
конструктор_производного_класса (список формальных пар аметров)
: конструктор_базового_класса (список фактических параме тров)
{
. . . / /тело конструктора производного класса
}
Списки параметров родительского и дочернего конструкторо в могут совпа-
дать, а могут и различаться. Например, конструктор произво дного класса часто
принимает некоторые аргументы только для того, чтобы перед ать их конструк-
тору базового класса. Приведём пример с уже обсуждавшимися классамиpoint
и vertex .
#i n c l u d e
u s i n g namespace s t d ;
c l a s s p o i n t
{ p r o t e c t e d :
i n t x , y , c o l o r ;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

296Глава 10. Объектно-ориентированное программирование
p u b l i c:
p o i n t ( i n tp1 , i n tp2 , i n tc ) ;
} ;
p o i n t : : p o i n t ( i n tp1 , i n tp2 , i n tc )
{
x=p 1 ;
y=p 2 ;c o l o r =c ;
}
c l a s s v e r t e x : p u b l i cp o i n t
{
i n t z ;
p u b l i c :
v e r t e x ( i n tp1 , i n tp2 , i n tp3 , i n tc ) ;
} ;
v e r t e x : : v e r t e x ( i n tp1 , i n tp2 , i n tp3 , i n tc ) : p o i n t ( p1 , p2 , c )
{ z=p 3 ;
}
m a i n ( ) {
v e r t e x c 1 ( 2 , 3 , 4 , 0 ) ;
}
Допускается также использовать эту краткую запись передач и параметров
родительскому конструктору, чтобы компактно проинициали зировать перемен-
ные дочернего класса. Например, мы могли бы написать в преды дущем примере:
v e r t e x : : v e r t e x ( i n tp1 , i n tp2 , i n tp 3 )
: p o i n t ( p1 , p 2 ) , z ( p 3 )
{
/ / z=p 3 ;
}
С наследованием конструкторов класса связана ещё одна спец ифическая осо-
бенность: если в базовом классе есть перегруженный операто р присваивания, он
не наследуется производными классами. Если оператор присв аивания был пере-
гружен в родительском классе, а в производном  нет, то присв аивание объектов
производного класса не будет вызывать ошибку, однако выпол няться при этом
будет не перегруженный оператор, а присваивание по умолчан ию, т. е. побитовое
копирование свойств объекта.
10.4.2 Раннее и позднее связывание
Обрабатывая вызов метода какого-либо класса, компилятор с начала ищет
метод с указанным именем внутри данного класса. Если метод с таким именем
не определён внутри класса, то компилятор обращается к базо вому классу и ищет
его там. Если найдёт, то подставит в точки вызова адрес метод а из родительского
класса. Если не найдёт, то поднимается всё выше по иерархии н аследования.
Методы, которые вызываются так, являются статическими  в том смысле,
что компилятор разбирает ссылки на них во время компиляции. Этот подход
экономит ресурсы в момент выполнения программы, однако ино гда приводит к
нежелательным результатам. Рассмотрим для примера иерарх ию из двух клас-
сов: класса vector, представляющего собой двумерный вектор, и производный
от него класс spatial_vector , уже знакомый нам по прежним примерам. Нам
Программирование на языке С++ в среде Qt Creator

10.4. Наследование297
будут нужны два метода у каждого из классов: методinfo(), выводящий тек-
стовое сообщение и сообщающий, чему равен модуль вектора, и м етодabs() ,
собственно вычисляющий значение модуля. Наследование одно го класса от дру-
гого в данном случае представляется вполне логичным: в прои зводном классе
достаточно будет добавить ещё одну переменную, модифициров ать конструктор
и функцию вычисления модуля.
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s v e c t o r
{ p r o t e c t e d :
double x , y ;
p u b l i c :
v e c t o r ( double x ,double y ) {t h i s−>x=x ; t h i s−>y=y ; }
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y ) ; }
v o i d i n f o ( ) { c o u t << " Модуль вектора равен " << a b s ( ) << e n d l ; }
} ;
c l a s s s p a t i a l _ v e c t o r : p u b l i cv e c t o r
{ p r o t e c t e d :
double z ;
p u b l i c :
s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) ;
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y + z ∗z ) ; }
} ;
s p a t i a l _ v e c t o r : : s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) : v e c t o r ( x , y )
{
t h i s −>z=z ;
}
m a i n ( )
{ c o u t << " Создаём вектор на плоскости с координатами 1,2 \ n " ;
v e c t o r a ( 1 , 2 ) ;
a . i n f o ( ) ;
c o u t << " Создаём пространственный вектор с координатами 1,2,3 \ n " ;
s p a t i a l _ v e c t o r b ( 1 , 2 , 3 ) ;
b . i n f o ( ) ;
}
В действительности же данный код генерирует весьма странны й результат:
Создаём вектор на плоскости с координатами 1,2
Модуль вектора равен 2.23607
Создаём пространственный вектор с координатами 1,2,3
Модуль вектора равен 2.23607
Мы корректно переопределили метод abs()в производном классе (можно легко
в этом убедиться, вызвав его непосредственно), однако для п роизводного класса
функция info()выдала явно неверное значение, не посчитав в модуле третью
координату. Проблема в том, что родительский метод info()не знает, что
функция abs()переопределена в классе-потомке.
Для того чтобы это стало возможным нужен специальный механи зм, и в язы-
ке C++ это  позднее связывание , реализующее механизм виртуальных методов.
Виртуальные методы реализуют полиморфизм. Виртуальный метод  это метод, который, будучи описан в потомках,
замещает собой соответствующий метод везде, даже в методах, описанных
для предка, если он вызывается для потомка.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

298Глава 10. Объектно-ориентированное программирование
Адрес виртуального метода известен только в момент выполнен ия програм-
мы. Когда происходит вызов виртуального метода, его адрес б ерётся из таблицы
виртуальных методов своего класса. Таким образом, вызывае тся то, что нужно.
Виртуальные методы описываются с помощью ключевого слова virtualв
базовом классе. Это означает, что в производном классе этот метод может быть
замещён методом, более подходящим для этого производного к ласса. Объявлен-
ный виртуальным в базовом классе, метод остаётся виртуальн ым для всех про-
изводных классов. Если в производном классе виртуальный ме тод не будет пере-
определён, то при вызове будет найден метод с таким именем вв ерх по иерархии
классов (т. е. в базовом классе).
#i n c l u d e < i o s t r e a m >
#i n c l u d e
u s i n g namespace s t d ;
c l a s s v e c t o r
{ p r o t e c t e d :
double x , y ;
p u b l i c :
v e c t o r ( double x ,double y ) {t h i s−>x=x ; t h i s−>y=y ; }
v i r t u a l double a b s ( ) {r e t u r ns q r t ( x∗x + y ∗y ) ; }
v o i d i n f o ( ) { c o u t << " Модуль вектора равен " << a b s ( ) << e n d l ; }
} ;
c l a s s s p a t i a l _ v e c t o r : p u b l i cv e c t o r
{ p r o t e c t e d :
double z ;
p u b l i c :
s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) ;
double a b s ( ) { r e t u r ns q r t ( x∗x + y ∗y + z ∗z ) ; }
} ;
s p a t i a l _ v e c t o r : : s p a t i a l _ v e c t o r ( doublex ,double y ,double z ) : v e c t o r ( x , y )
{
t h i s −>z=z ;
}
m a i n ( )
{ c o u t << " Создаём вектор на плоскости с координатами 1,2 \ n " ;
v e c t o r a ( 1 , 2 ) ;
a . i n f o ( ) ;
c o u t << " Создаём пространственный вектор с координатами 1,2,3 \ n " ;
s p a t i a l _ v e c t o r b ( 1 , 2 , 3 ) ;
b . i n f o ( ) ;
}
Будучи выполнен, пример наконец выдаёт ожидаемый ответ:
Создаём вектор на плоскости с координатами 1,2
Модуль вектора равен 2.23607
Создаём пространственный вектор с координатами 1,2,3
Модуль вектора равен 3.74166
10.4.3 Множественное наследование
В списке базовых классов можно указывать несколько классов -родителей,
через запятую, каждого со своим модификатором наследования :
c l a s s A { . . . } ;
c l a s s B { . . . } ;
c l a s s C :p u b l i c A ,p u b l i c B { . . . } ;
Программирование на языке С++ в среде Qt Creator

10.4. Наследование299
При этом классCунаследует как содержимое класса А, так и класса B. При
вызове конструктора будут сначала вызваны конструкторы ба зовых классов (в
порядке следования). Деструкторы, как всегда, имеют против оположный поря-
док вызова. При множественном наследовании автоматически включается п озднее связы-
вание.
10.4.4 Указатели на базовые классы
Другая сфера приложения виртуальных функций связана с испо льзованием
указателей на объекты. Указатель, объявленный в качестве ук азателя на базо-
вый класс, также может использоваться как указатель на любой класс, произ-
водный от этого базового: point * p = new vertex();
По указателю на объект базового класса можно вполне коррект но вызвать те
методы класса-потомка, которые уже существовали в описани и базового класса.
Вызвать по такому указателю метод, присутствующий лишь в про изводном
классе напрямую нельзя, но можно косвенно, с использование м приведения ти-
пов: c l a s s p a r e n t
{ p u b l i c :
v o i d p a r e n t _ m e t h o d ( ) { }
} ;
c l a s s c h i l d : p u b l i cp a r e n t
{ p u b l i c :
v o i d c h i l d _ m e t h o d ( ) { }
} ;
m a i n ( )
{ p a r e n t ∗p = new c h i l d ( ) ;
p − >p a r e n t _ m e t h o d ( ) ;
( ( c h i l d ∗) p ) −>c h i l d _ m e t h o d ( ) ;
}
Типичное использование указателя на базовый класс, которо му присвоен ад-
рес объекта производного класса  хранение либо передача не скольких разно-
типных объектов, имеющих общий класс-предок. Например, во м ногих библио-
теках виджетов (графических элементов управления) инстру ментальная панель,
которая может содержать в себе кнопки, надписи, выпадающие с писки и т. д.,
является универсальным контейнером, хранящим указатели н а объект базового
класса (например, класса widget), от которого унаследованы конкретные эле-
менты управления (классы button,text ,list и т. д.). Благодаря возможности
использовать указатель на базовый класс, панель реализует один единственный
набор методов для добавления и удаления разнотипных элемен тов, а также для
обращения к ним. Однако при использовании указателей на базовый класс требу ется соблюдать
осторожность в отношении разрушения объектов. Если объект -потомок выйдет
из области видимости и будет разрушен по указателю на базовы й класс, то без
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

300Глава 10. Объектно-ориентированное программирование
дополнительных мер вызовется деструктор базового класса. Если деструкторы
базового и производного классов имеют важные различия в своё м поведении
(например, когда деструктор-потомок должен освободить до полнительные блоки
памяти)  такое поведение является недопустимым. В этом слу чае деструктор
родительского класса необходимо объявлять виртуальным  т ак же, как это
делается с любым другим методом.
10.4.5 Абстрактные классы
Иногда, когда функция объявляется в базовом классе, она не в ыполняет ни-
каких значимых действий, поскольку часто базовый класс не о пределяет закон-
ченный тип, а нужен чтобы построить иерархию. Например, мето дpaint() , объ-
явленный в классе widgetи выполняющий отрисовку виджета на экране, должен
переопределяться в классах-потомках, с тем, чтобы выводит ь на экран изображе-
ние кнопки в классе buttonили текстовую надпись в классе text. Изображение
же абстрактного виджета тоже абстрактно, и метод в базовом к лассе не несёт
практической нагрузки.
Методы, которые нужны только для того, чтобы их обязательно переопреде-
лили в производных классах, называются чисто виртуальнымиметодами.
Чисто виртуальные методы не определяются в базовом классе. У них нет
тела, а есть только декларации об их существовании.
Чисто виртуальная функция выглядит в описании класса следу ющим обра-
зом:
virtual тип имя_функции (список параметров) = 0;
Как можно заметить, функцию делает чисто виртуальной прира внивание её
описания к нулю.
Класс, содержащий хотя бы один чисто виртуальный метод, наз ывается аб-
страктным классом. Поскольку у чисто виртуального метода н ет тела, то создать
объект абстрактного класса невозможно.
10.4.6 Пример иерархии классов  библиотека потокового
ввода-вывода
В заключение рассмотрим, как используется наследование для решения ре-
альных задач программирования.
Технологии наследования классов, входящие в стандарт C++, предсказуемо
были использованы и при разработке библиотек, входящих в ст андарт этого
языка. Включённая в стандарт реализация сама по себе являетс я прекрасным
примером, т. к. в данном случае не приходится сомневаться в г рамотном и це-
лесообразном проектировании как иерархии классов, так и их внутренней ре-
ализации. По этой причине рассмотрим в качестве примера сло жной структу-
ры классов, созданных для решения конкретных практических задач, объектно-
ориентированную библиотеку потокового ввода-вывода.
Программирование на языке С++ в среде Qt Creator

10.4. Наследование301
В предыдущих разделах мы касались использования операторов<< и>> вме-
сте с объектами cinиcout , а также отметили, что эти объекты на самом деле
являются экземплярами классов istreamиostream . Однако прежде чем рас-
сматривать внутреннее устройство этих и других классов, во влечённых в ре-
ализацию ввода-вывода, необходимо разобраться в самой пре дметной области.
Поэтому рассмотрим подробнее, какие стадии включает в себя п ринятая вC++
кросс-платформенная реализация ввода-вывода.
При разработке средств потокового ввода-вывода в C++была использована
следующая двухуровневая модель (см. рис. 10.3), предназнач енная для передачи
символьных данных между программой и каким-либо внешним ус тройством.
Рис. 10.3: Модель потокового ввода-вывода вС++
При этом представление данных в программе и на внешнем устро йстве мо-
жет отличаться: по необходимости данные могут отображатьс я в форме, удобной
для восприятия человеком, либо преобразовываться в какой- либо формат обме-
на данными. Как видно из рисунка, собственно обработка текс товых данных вы-
полняется на двух уровнях: форматированияитранспортном . Под форматиро-
ванием понимается преобразование внутренних данных прогр аммы в человеко-
читаемую последовательность символов. Например, значени е целочисленной или
вещественной переменной на этом этапе должно быть преобраз овано в последова-
тельность цифр, а управляющие символы в строковых данных дол жны быть за-
менены соответствующими им символьными последовательност ями (например,
код табуляции \t превращается в заданное число пробелов). Под кодировани-
ем понимается трансляция из одной кодировки символов в друг ую. Например,
транспортный уровень может выполнять преобразование симв олов в кодировку
Unicode для их использования за пределами программы (данная кодировка яв-
ляется стандартом де-факто, но неудобна для непосредствен ного использования
в программе, т. к. символы разных языков имеют в ней различное количество
байт).
В рамках двухуровневой модели ввода-вывода, принятой в C++, уровень фор-
матирования делает возможным выполнение следующих процеду р:
• преобразование вещественных значений в последовательно сть цифр с за-
данной точностью и формой представления;
• преобразование целочисленных значений в последовательн ость цифр в
шестнадцатеричной, восьмеричной либо десятичной системе счисления;
• исключение лишних пробелов из входных данных;
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

302Глава 10. Объектно-ориентированное программирование
• задание ширины поля (т. е. максимального количества знако в) для выво-
димых данных;
• адаптация представления чисел к конкретной локали (т. е. у чёт националь-
ной специфики их отображения).
Транспортный уровень отвечает непосредственно за получен ие и выдачу симво-
лов. На этом уровне инкапсулируется специфика конкретных в нешних устройств.
К числу таковых помимо возможности преобразования в многоб айтные коди-
ровки относится также блочный вывод в файлы с использование м системных
вызовов операционной системы, под которую компилируется п рограмма.
Для уменьшения числа обращений к внешнему устройству испол ьзуется пото-
ковый буфер. При выводе последовательность символов после форматирования
попадает в потоковый буфер, а реальная передача данных внеш нему устройству
выполняется когда буфер оказывается заполнен, или когда пр инудительно вы-
звана операция опустошения буфера. При вводе данных трансп ортный уровень
считывает последовательность символов из внешнего устрой ства в буфер, после
чего уровень форматирования извлекает данные из буфера. Ко гда буфер оказы-
вается пуст, задачей транспортного уровня является его пов торное наполнение
данными.
Реализованный в C++форматированный потоковый ввод-вывод можно раз-
делить на две группы: файловый ввод-выводиввод-вывод в памяти . Файло-
вый ввод-вывод предполагает передачу данных между програм мой и внешним
устройством. При этом внешнее устройство только представл ено файлом; поми-
мо обычного файла на диске оно может в действительности быть каналом обмена
данными или любым реальным устройством, файловая абстракци я которого ре-
ализована в операционной системе.
Ввод-вывод в памяти в действительности не задействует ника кого внешнего
устройства. Благодаря этому отпадает необходимость в уров не кодирования и
передачи, а уровень форматирования просто формирует строк у символов.
Расширяемость библиотеки потокового ввода-вывода позвол яет программи-
сту добавлять свои элементы на любом из её уровней. Например, операторы
ввода-вывода могут быть перегружены для новых типов данных , программист
может создавать собственные элементы, управляющие формати рованием (т. н.
манипуляторы). Можно создавать собственные локали для спе цифического пред-
ставления чисел и т. д.
Теперь мы можем рассмотреть, как выглядит иерархия классов потокового
ввода-вывода с точки зрения программиста.
Мы будем рассматривать упрощённое представление для случа я, когда симво-
лы представлены в программе в однобайтной кодировке с испол ьзованием типа
char . В реальности библиотека iostreamреализует более универсальное пред-
ставление данных на основе шаблонов, позволяющее не указывать заранее при
описании классов тип данных, используемый для хранения сим вола. Благода-
ря этому подходу тот же самый код может применяться, наприме р, для много-
байтных кодировок, представленных специальным типом wchar_t. Также мы на
Программирование на языке С++ в среде Qt Creator

10.4. Наследование303
данном этапе опустим специальные средства обработки ошибок и других исклю-
чительных ситуаций, применённые в данной библиотеке. Подр обнее о шаблонах
и обработке исключительных ситуаций можно будет узнать в сле дующих разде-
лах; там же будут пояснены опущенные на данном этапе элемент ы, и в т. ч. то,
как на самом деле объявлены типы библиотеки iostream.
Пока достаточно знать, что иерархия классов iostreamвыглядит для про-
граммиста, использующего обычные символы типа char, следующим образом
(см. рис. 10.4).
Из приведённой иерархии можно заметить, что структура клас сов уровня
форматирования заметно более разветвлённая, хотя основны е отличия между
файловыми потоками и потоками в памяти кроются на транспортн ом уровне.
Кажущийся дисбаланс легко объясним, если вспомнить, что пр ограммист, поль-
зующийся библиотекой iostream, непосредственно взаимодействует в основном
с уровнем форматирования. Использование универсальных кл ассов, которые по-
сле существенной предварительной настройки выполняли бы в вод-вывод с лю-
быми объектами транспортного уровня, менее удобно, чем спе циализированные
классы для каждого типа ввода-вывода, не требующие или почти не требующие
настройки для выполнения требуемых операций.
Будучи базовым для всех потоковых классов уровня форматиро вания, класс
ios содержит информацию, присущую любым потокам: управляющую инф ор-
мацию для разбора и форматирования, возможности для расшир ения иерархии
собственными потоками пользователя, а также локали. Здесь же объявляются
некоторые типы, используемые остальными классами: флаги ф орматирования,
биты состояния, режим открытия и т. д. Здесь же содержится ук азатель на пото-
ковый буфер (который в свою очередь включает собственно симв ольный буфер
и служебную информацию, отражающую состояние буфера и обеспе чивающую
целостность информации).
Как читатель успел заметить из собственной практики програ ммирования на
C++ , активнее всего потоки используются для стандартного ввода -вывода (т. е.
ввода с клавиатуры и вывода на дисплей). Для обработки станд артного ввода
предусмотрен класс istream, а для обработки стандартного вывода  ostream;
оба класса наследуются от ios, приобретая благодаря этому всю специфику, свя-
занную с форматированием, и указатель на потоковый буфер. Д ля взаимодей-
ствия с потоковым буфером в классе istreamобъявлен перегруженный оператор
потокового ввода >>, а в классе ostream перегруженный оператор потокового
вывода <<. Для возможности неформатированного ввода и вывода в этих к лас-
сах объявлен также ряд методов  таких как read()иwrite() . Наконец, для
случаев, когда необходим двунаправленный ввод-вывод (по а налогии с тем, как
файл может открываться одновременно для чтения и записи) с п омощью мно-
жественного наследования от этих двух классов порождён кла ссiostream , ав-
томатически приобретающий свойства как входных, так и выход ных потоков и
используемый как базовый для классов, в которых двунаправл енный ввод-вывод
действительно востребован.
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В. , Чмыхало А. С.

304Глава 10. Объектно-ориентированное программирование
Рис. 10.4: Иерархия классов потокового ввода-вывода
Строковые потоки, осуществляющие ввод-вывод в памяти, пред ставлены
классами istringstream иostringtstream , порождёнными соответственно от
istream иostream , а также универсальным классом двунаправленного ввода-
вывода stringtream , порождённым от iostream. Эти классы включают функции
(геттеры и сеттеры) для использования строки в качестве буф ера.
Файловый ввод-вывод осуществляют классы ifstreamиoftstream , порож-
дённые соответственно от istreamиostream , а также универсальный класс
fstream , порождённый от iostream. Эти классы содержат методы для открытия
и закрытия файлов, аналогичные функциям fopen()иfclose() языкаС.
Очевидно, что значительная часть различий между стандартн ым вводом-
выводом, файловыми и строковыми потоками скрыта на транспо ртном уровне.
Базовый класс streambufferолицетворяет собой универсальный потоковый
буфер. Будучи абстрактным классом, он не содержит в себе спе цифики кон-
кретных оконечных устройств; однако в нём объявлены две чис то виртуальные
функции: overflow() иunderflow() , которые должны быть перегружены в про-
изводных классах, чтобы выполнять действительную передач у символов между
символьным буфером и конкретными оконечными устройствами .
Класс потокового буфера поддерживает две символьные после довательности:
область получения ( get), представляющую последовательность символов, полу-
чаемых из оконечного устройства, и область выдачи ( put), т. е. выходную после-
довательность для записи на устройство. Также в классе пред усмотрены функ-
ции, извлекающие очередной символ из буфера ( sgetc()и т. д.) и помещающие
очередной символ в буфер ( sputc()и т. д.), которые обычно используются уров-
нем форматирования. Дополнительно потоковый буфер содерж ит также объект
локали.
Производный от streambufклассfilebuf используется для работы с файла-
ми и содержит для этого ряд функций, таких как open()иclose() . Он также на-
следует объект локали от базового класса для перекодирован ия между внешней
и внутренней кодировками (например, как уже упоминалось, м ежду кодировкой
Программирование на языке С++ в среде Qt Creator

10.5. Обработка исключений305
Unicode и внутренним представлением мультиязычных символов значениями ти-
па wchar_t ).
Класс stringbuf также является производным от streambuf. Поскольку он
предназначен для работы со строками, внутренний буфер одно временно являет-
ся и оконечным устройством. По мере необходимости внутренн ий буфер может
динамически изменять свой размер, чтобы принять все записа нные в него симво-
лы. Класс позволяет получить копию внутреннего буфера, а та кже скопировать
в него строку.
Взаимодействие между уровнем форматирования и транспортн ым уровнем
осуществляется следующим образом. Класс ios, как мы уже упоминали, содер-
жит в себе указатель на потоковый буфер. В производных от нег о классах (таких
как fstream илиstringstream ) содержатся указатели на объекты соответствую-
щих классов транспортного уровня ( filebufилиstringbuf ). Классы транспорт-
ного уровня можно также использовать и непосредственно, дл я неформатирован-
ного ввода-вывода  точно так же, как их использует уровень ф орматирования.
Представленная на рисунке иерархия могла бы быть описана сл едующим об-
разом: c l a s s i o s { . . . } ;
c l a s s o s t r e a m : p u b l i ci o s { . . . } ;
c l a s s i s t r e a m : p u b l i ci o s { . . . } ;
c l a s s o f s t r e a m : p u b l i co s t r e a m { . . . } ;
c l a s s i f s t r e a m : p u b l i ci s t r e a m { . . . } ;
c l a s s o s t r i n g s t r e a m : p u b l i co s t r e a m { . . . } ;
c l a s s i s t r i n g s t r e a m : p u b l i ci s t r e a m { . . . } ;
c l a s s i o s t r e a m : p u b l i co s t r e a m , p u b l i ci s t r e a m { . . . } ;
c l a s s f s t r e a m : p u b l i ci o s t r e a m { . . . } ;
c l a s s s t r i n g s t r e a m : p u b l i ci o s t r e a m { . . . } ;
10.5 Обработка исключений
10.5.1 Общие понятия Классический подход к обработке ошибок в программе, разраб отанной в рам-
ках процедурного подхода, предполагает анализ значений, в озвращаемых функ-
циями. Например, многие библиотечные функции в случае возн икновения ошиб-
ки или какой-либо непредвиденной ситуации возвращают нулев ое значение, ин-
терпретируемое как ложно, а в случае успешной работы  нен улевое, т. е.
истина. При необходимости передачи более детальной инфо рмации об ошибке,
код ошибки может сохраняться в некую глобальную переменную (биб