- •Предисловие
- •Глава 1. Основные понятия
- •1.1. Элементы языка программирования
- •1.2. Процесс создания программы
- •1.3. Первая программа
- •1.4. Состав программы
- •Глава 2. Средства разработки на C++
- •2.1. Системы Turbo C++ 3.0/Borland C++ 3.1
- •2.2. Система C++ Builder
- •Глава 3. Работа с числовыми данными
- •3.1. Целые типы
- •3.2. Числа с плавающей точкой
- •3.3. Ввод и вывод чисел
- •3.4. Логический тип и логические операции
- •3.5. Математические функции
- •Глава 4. Операторы. Ключевые слова
- •4.1. Операторы
- •4.2. Приоритеты операторов
- •4.3. Ключевые слова
- •4.4. Структура программы
- •4.5. Константы
- •Задачи - . Простейшие вычисления
- •Глава 5. Управление и циклы
- •5.1. Условный оператор
- •5.2. Операторы цикла
- •5.3. Переключатель
- •5.4. Операторы break и continue
- •Задачи -. Выбор и циклы
- •Глава 6. Массивы
- •6.1. Одномерные массивы
- •6.2. Двумерные массивы
- •Задачи -. Одно- и двумерные массивы
- •Глава 7. Функции
- •7.1. Определение функции
- •7.2. Формальные параметры и фактические аргументы
- •7.3. Автоматические и статические переменные
- •7.4. Прототипы функций
- •7.5. Массивы как аргументы функций
- •7.6. Внешние переменные
- •7.7. Рекурсия
- •7.8. Перегруженные имена функций
- •7.9. Аргументы функций по умолчанию
- •Задачи -. Функции
- •Глава 8. Символы и строки
- •8.1. Символы
- •8.2. Строки символов
- •Задачи -. Символы и строки
- •Глава 9. Препроцессор
- •9.1. Директивы препроцессора
- •9.2. Макросы
- •Задачи -. Макросы
- •Глава 10. Указатели и ссылки
- •10.1. Указатели и адреса
- •10.2. Указатели и массивы
- •10.3. Адресная арифметика
- •10.4. Символьные указатели
- •10.5. Массивы указателей
- •10.6. Указатели на функции
- •10.7. Ссылки
- •10.8. Операторы new и delete
- •Задачи -. Указатели и ссылки
- •Глава 11. О файлах и командной строке
- •11.1. Знакомство с файлами
- •11.2. Командная строка
- •11.3. Перенаправление стандартного ввода и вывода на файл
- •11.4. Аргументы командной строки
- •Задачи -. Файлы и командная строка
- •Глава 12. Работа с экраном дисплея
- •12.1. Текстовый режим
- •12.2. Графический режим
- •Задачи -. Работа с экраном
- •Глава 13. Внутреннее представление чисел
- •13.1. Двоичная система счисления
- •13.2. Беззнаковые целые
- •13.3. Двоичный дополнительный код
- •13.4. Двоичный код с избытком
- •13.5. Побитовые операторы
- •13.6. Дробные числа в двоичной системе
- •13.7. Внутреннее представление плавающих типов
- •13.8. Преобразование типов
- •Задачи -. Побитовые операторы
- •Глава 14. Структуры, перечисления, объединения
- •14.1. Объявление структур
- •14.2. Структуры и функции
- •14.3. Указатели на структуры
- •14.4. Массивы структур
- •14.5. Перечисления
- •14.6. Объединения
- •14.7. Битовые поля
- •14.8. О бинарных файлах
- •Задачи -. Структуры
- •Глава 15. Классы
- •15.1. Структуры в C++. Инкапсуляция
- •15.2. Встроенные функции
- •15.3. Классы. Скрытие данных
- •15.4. Конструкторы
- •15.5. Статические члены класса
- •15.6. Друзья класса
- •15.7. Копирование объектов класса
- •15.8. Управление доступом
- •15.9. Ссылка на себя
- •15.10. Деструкторы
- •Задачи -. Работа с классами
- •Глава 16. Программы из нескольких файлов
- •16.1. Работа с проектами
- •16.2. Область действия имен
- •16.3. Заголовочные файлы
- •16.4. Пространства имен
- •Задачи -. Работа со стеком
- •Глава 17. Перегрузка операторов
- •17.1. Правила перегрузки операторов
- •Задачи -. Перегрузка операторов
- •Глава 18. Конструктор копирования и оператор присваивания
- •18.1. Проблемы при копировании
- •Задачи -. Конструктор копирования
- •Глава 19. Ввод и вывод
- •19.1. Вывод
- •19.2. Ввод
- •19.3. Ввод и вывод определяемых пользователем типов
- •19.4. Работа с файлами
- •Глава 20. Взаимоотношения классов
- •20.1. Объекты как члены класса
- •20.2. Конструкторы встроенных типов
- •20.3. Наследование
- •20.4. Виртуальные функции
- •20.5. Абстрактные классы
- •20.6. Совместимость типов
- •20.7. Множественное наследование
- •Задачи -. Наследование классов
- •Глава 21. Шаблоны, исключения
- •21.1. Шаблоны
- •21.2. Шаблоны функций
- •21.3. Классы и шаблоны
- •21.4. Обработка исключений
- •21.5. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
94 |
7 |
|
const int SIZEARR = 100; |
// Размер массива |
|
int x[SIZEARR]; |
// Массив |
Далее приведен пример работы программы.
Введите размер массива < 100: 10 Исходный массив:
346, 130, 10982, 1090, 11656, 7117, 17595, 6415, 22948, 31126 Отсортированный массив:
130, 346, 1090, 6415, 7117, 10982, 11656, 17595, 22948, 31126
Обратим внимание на то, как меняются значения двух элементов массива. Для этого используется специальная промежуточная переменная tmp.
7.7.Рекурсия
Вязыке C++ функции могут быть рекурсивными, то есть вызывать сами себя.
Рассмотрим печать целого числа как последовательности цифр. Цифры числа легко получать, начиная с конца числа как остатки от деления на 10, но печатать их нужно в правильной последовательности. Напишем рекурсивную функцию printd, которая будет вызывать сама себя, чтобы напечатать все старшие цифры, а затем печатает последнюю младшую цифру.
Программа 17. Рекурсивная печать целого
//Файл Recurs.cpp #include <iostream.h> #include <conio.h>
//printd: печатает n как целое десятичное число void printd(int n)
{
if(n < 0){ |
// Если число отрицательное, |
cout.put('-'); |
// печатаем знак числа, |
n = -n; |
// делаем число положительным |
} |
|
if(n / 10) |
// Если в n более одной цифры, |
printd(n / 10); |
// печатаем старшие цифры, иначе |
cout.put('0' + n % 10); |
// выводим последнюю цифру |
}
void main()
{
int number;
cout << "\nВведите число: "; cin >> number;
Функции 95
printd(number);
}
Символы цифр ’0’, ’1’, …, ’9’ занимают в кодовой таблице непрерывный участок и расположены в порядке возрастания их значения. Код цифры ’0’ равен 48, у цифры ’1’ код 49 и т.д., поэтому выражение
n % 10 + ’0’ дает правильный код последней десятичной цифры числа n. Например, если n = 321, то n % 10 + '0' = 1 + 48 = 49, что равно коду цифры ’1’, и эту цифру изобразит на экране функция put в соответствии со значением своего аргумента.
При каждом вызове рекурсивной функции создается свой собственный набор локальных переменных, в том числе и формальных параметров. Сам же код рекурсивной функции существует в единственном экземпляре. Таким образом, рекурсивная функция, не закончив обработку одного набора данных, переключается на обработку другого, но затем возвращается и завершает прерванную обработку.
Полезно выполнить данную программу в пошаговом режиме, наблюдая за работой рекурсивной функции, за значениями формального параметра n и состоянием экрана. Разберем работу функции printd. Пусть для number введено значение 123, то есть первый вызов функции имеет вид printd(123). Работу функции поясняет табл. 27. Углубление в рекурсию, когда функция вызывает сама себя, происходит, пока обрабатываемое число остается многозначным. Последний вызов printd происходит для однозначного числа 1, на экран выводится цифра ’1’ и работа 3-го вызова завершается, после чего управление передается во 2- й вызов на инструкцию:
cout.put(n % 10 + '0');
которая выводит предпоследнюю цифру, затем происходит возврат в 1-й вызов, печатается последняя цифра исходного числа и работа printd завершается.
Таблица 27. Работа рекурсивной функции
967
7.8.Перегруженные имена функций
Если функции делают примерно одинаковую работу над объектами разных типов, целесообразно давать им одинаковые имена. Использование одного имени для операции, выполняемой над различными типами, называется перегрузкой. Например, одно имя + используется для сложения целых чисел и чисел с плавающей точкой, хотя им соответствуют совершенно разные машинные команды.
Пусть в программе требуется вычислять абсолютную величину переменных типа int и типа double. Для этого можно написать две функции с одинаковыми именами, что и сделано в следующей программе.
Программа 18. Перегрузка функций
//Файл Module.cpp #include <iostream.h> #include <conio.h>
//module: возвращает абсолютную величину целого n int module(int n)
{
if(n < 0) return -n;
return n;
}
//module: возвращает абсолютную величину плавающего x double module(double x)
{
if(x < 0) return -x;
return x;
}
int main()
{
cout << "module(-3.14) = " << module(-3.14f) << "\n"; cout << "module(-3) = " << module(-3) << "\n"; getch();
return 0;
}
Компилятор различает функции с одним именем по количеству и типам аргументов, а также по типу возвращаемого значения. При выборе подходящей функции из многих перегруженных компилятор
Функции 97
ищет такую, которая имеет наилучшее соответствие типов формальных и фактических параметров. Программа печатает:
module(-3.14) = 3.14 module(-3) = 3
Это показывает, что для числа с плавающей точкой -3.14f, имеющего тип float, вызывается функция
double module(double x);
а для целого -3 функция int module(int n);
7.9.Аргументы функций по умолчанию
Уфункций общего назначения часто больше аргументов, чем требуется в простых случаях. В программе 19 рассмотрена функция печати целого val. В качестве аргумента функции передается основание системы счисления base, в которой следует печатать целое, но предполагается, что в большинстве случаев целые будут печататься в виде десятичных чисел, поэтому значением по умолчанию для base указано 10.
Программа 19. Аргументы по умолчанию
Функция печати целого print рекурсивная. Если основание системы счисления base <= 10, используются обычные цифры 0, 1, …, 9. Если base > 10, то в качестве цифр используются заглавные латинские буквы
A, B, C, D, E, F, G, H,… со значениями: 10, 11, 12, 13, 14, 15, 16, 17,… // Файл ArgDeflt.cpp
#include <iostream.h> #include <conio.h>
// print: печать val в системе счисления с основанием base
void print(int val, int base = 10) // 10 – значение для base по умолчанию
{
if(val < 0){ cout.put('-'); print(-val, base);
}
if(val / base > 0) print(val / base, base);
int r = val % base; if(r < 10)
cout.put('0' + r);
//Если число многозначное,
//печатать старшие цифры
//Остаток от деления