- •Издано в рамках Инновационной образовательной программы ннгу: Образовательно-научный центр «Информационно-телекоммуникационные системы: физические основы и математическое обеспечение»
- •Глава 1. Основные понятия 13
- •Глава 3. Работа с числовыми данными 42
- •Глава 4. Операторы. Ключевые слова 52
- •Глава 5. Управление и циклы 64
- •Глава 6. Массивы 77
- •Глава 7. Функции 84
- •Глава 8. Символы и строки 102
- •Глава 9. Препроцессор 113
- •Глава 10. Указатели и ссылки 119
- •Глава 11. О файлах и командной строке 133
- •Глава 12. Работа с экраном дисплея 145
- •Глава 13. Внутреннее представление чисел 157
- •Глава 14. Структуры, перечисления, объединения 179
- •Глава 15. Классы 204
- •Глава 16. Программы из нескольких файлов 233
- •Глава 21. Шаблоны, исключения 321
- •Предисловие
- •Глава 1.Основные понятия
- •1.1.Элементы языка программирования
- •Алфавит
- •Лексемы
- •Выражения
- •Функции
- •Комментарии
- •1.2.Процесс создания программы
- •1.3.Первая программа Программа 1. Приветствие
- •1.4.Состав программы
- •Загрузка
- •Работа с окнами
- •Настройка среды
- •Указание каталогов библиотек
- •Подключение графической библиотеки
- •Назначение текущего каталога
- •Работа с блоками текста в редакторе
- •Выполнение программы
- •Отладка программ
- •Программа 2. Деление чисел
- •Синтаксические ошибки
- •Ошибки в процессе работы программы
- •Трассировка программ
- •Просмотр текущих значений выражений
- •Разработка консольных приложений
- •Программа 3. Hello
- •Выполнение и отладка программы
- •Файлы проекта
- •Автоматическая генерация кода
- •Особенности ввода и вывода
- •Глава 3.Работа с числовыми данными
- •3.1.Целые типы
- •Целые константы
- •Программа 4. Операции над целыми
- •3.2.Числа с плавающей точкой
- •Плавающие константы
- •3.3.Ввод и вывод чисел
- •Программа 5. Точность плавающих чисел
- •3.4.Логический тип и логические операции
- •3.5.Математические функции
- •Глава 4.Операторы. Ключевые слова
- •4.1.Операторы
- •Унарные операторы
- •Бинарные операторы
- •Оператор запятая
- •Условное выражение
- •Операторы присваивания
- •4.2.Приоритеты операторов
- •4.3.Ключевые слова
- •Продолжение таблицы 23. Ключевые слова стандарта языка Cи
- •4.4.Структура программы
- •Объявления переменных
- •Объявления и определения
- •Инструкции и блоки
- •4.5.Константы
- •Задачи 1-17 . Простейшие вычисления
- •Глава 5.Управление и циклы
- •5.1.Условный оператор
- •Программа 6. Максимальное из двух чисел
- •5.2.Операторы цикла
- •Цикл с предусловием while
- •Программа 7. Суммирование цифр целого
- •Цикл for
- •Программа 8. Поиск максимума и минимума
- •Цикл do-while
- •Программа 9. Вычисление квадратного корня
- •5.3.Переключатель
- •Программа 10. День недели
- •5.4.Операторы break и continue
- •Программа 11. Сумма положительных чисел
- •Задачи 18-52. Выбор и циклы
- •Глава 6.Массивы
- •6.1.Одномерные массивы
- •Программа 12. Проверка упорядоченности массива
- •6.2.Двумерные массивы
- •Программа 13. Подсчет выручки
- •Задачи 53-69. Одно- и двумерные массивы
- •Глава 7.Функции
- •7.1.Определение функции
- •7.2.Формальные параметры и фактические аргументы
- •Пpограмма.14. Степени целых чисел
- •7.3.Автоматические и статические переменные
- •Программа 15. Автоматические и статические переменные
- •7.4.Прототипы функций
- •7.5.Массивы как аргументы функций
- •7.6.Внешние переменные
- •Программа 16. Сортировка массива
- •7.7.Рекурсия
- •Программа 17. Рекурсивная печать целого
- •7.8.Перегруженные имена функций
- •Программа 18. Перегрузка функций
- •7.9.Аргументы функций по умолчанию
- •Программа 19. Аргументы по умолчанию
- •Задачи 70-96. Функции
- •Глава 8.Символы и строки
- •8.1.Символы
- •Символьные константы
- •Программа 20. Представления символов
- •Ввод и вывод символов
- •Программа 22. Печать текста по словам
- •8.2.Строки символов
- •Строковые константы
- •Ввод и вывод строк
- •Средства работы со строками
- •Программа 23. Реверсирование строк
- •Задачи 97-121. Символы и строки
- •Глава 9.Препроцессор
- •9.1.Директивы препроцессора
- •9.2.Макросы
- •Программа 24. Возможности препроцессора
- •Задачи 122-124. Макросы
- •Глава 10.Указатели и ссылки
- •10.1.Указатели и адреса
- •Программа 25. Расчет треугольника
- •10.2.Указатели и массивы
- •10.3.Адресная арифметика
- •10.4.Символьные указатели
- •10.5.Массивы указателей
- •Программа 26. Названия месяцев
- •10.6.Указатели на функции
- •Программа 27. Поиск максимума функции
- •10.7.Ссылки
- •Программа 28. Использование ссылок
- •10.8.Операторы new и delete
- •Программа 29. Выделение и освобождение памяти
- •Задачи 125-134. Указатели и ссылки
- •Глава 11.О файлах и командной строке
- •11.1.Знакомство с файлами
- •Программа 30. Копирование файлов
- •11.2.Командная строка
- •11.3.Перенаправление стандартного ввода и вывода на файл
- •11.4.Аргументы командной строки
- •Программа 31. Эхо аргументов командной строки
- •Программа 32. Печать строк, содержащих образец
- •Задачи 135-147. Файлы и командная строка
- •Глава 12.Работа с экраном дисплея
- •12.1.Текстовый режим
- •Программа 33. Российский флаг
- •12.2.Графический режим
- •Графические драйверы и режимы
- •Инициализация графики
- •Функции рисования
- •Программа 34. Звезда
- •Задачи 148-158. Работа с экраном
- •Глава 13.Внутреннее представление чисел
- •13.1.Двоичная система счисления
- •13.2.Беззнаковые целые
- •13.3.Двоичный дополнительный код
- •13.4.Двоичный код с избытком
- •13.5.Побитовые операторы
- •Программа 35. Побитовые операторы
- •13.6.Дробные числа в двоичной системе
- •13.7. Внутреннее представление плавающих типов
- •13.8.Преобразование типов
- •Значения логических выражений
- •Арифметические преобразования
- •Преобразование при присваивании
- •Явное приведение типа
- •Задачи 159-166. Побитовые операторы
- •Глава 14.Структуры, перечисления, объединения
- •14.1.Объявление структур
- •14.2.Структуры и функции
- •14.3.Указатели на структуры
- •Программа 36. Точки и прямоугольники на экране
- •14.4.Массивы структур
- •Программа 37. Подсчет ключевых слов
- •14.5.Перечисления
- •Программа 38. Использование перечислений
- •14.6. Объединения
- •Программа 39. Внутреннее представление float
- •14.7.Битовые поля
- •14.8.О бинарных файлах
- •Программа 40. Анализ успеваемости
- •Задачи 167-174. Структуры
- •Глава 15.Классы
- •Программа 41. Время как структура
- •15.2.Встроенные функции
- •15.3.Классы. Скрытие данных
- •Программа 42. Класс дат
- •15.4.Конструкторы
- •Программа 43. Конструкторы в классе дат
- •15.5.Статические члены класса
- •Программа 44. Размер класса и объектов класса
- •15.6.Друзья класса
- •Программа 45. Статические члены и друзья класса
- •15.7.Копирование объектов класса
- •Программа 46. Копирование объектов
- •15.8.Управление доступом
- •Структуры и классы
- •Правила доступа
- •15.9.Ссылка на себя
- •Программа 47. Модификация дат
- •15.10.Деструкторы
- •Программа 48. Деструктор в классе дат
- •Программа 49. Многоугольники
- •Задачи 175-185. Работа с классами
- •Глава 16.Программы из нескольких файлов
- •16.1.Работа с проектами
- •16.2.Область действия имен
- •Программа 50. Глобальные и локальные имена
- •Статические имена
- •Программа 51. Сумматор чисел
- •16.3.Заголовочные файлы
- •Страж включения
- •Понятие стека
- •Программа 52. Реализация стека в виде массива
- •16.4.Пространства имен
- •Стандартные пространства имен
- •Задачи 186-189. Работа со стеком
- •Глава 17.Перегрузка операторов
- •Программа 53. Обыкновенные дроби
- •17.1.Правила перегрузки операторов
- •Программа 54. Комплексные числа
- •Задачи 190-196. Перегрузка операторов
- •Глава 18.Конструктор копирования и оператор присваивания
- •18.1.Проблемы при копировании
- •Программа 55. Вектора на плоскости
- •Задачи 197-198. Конструктор копирования
- •Глава 19.Ввод и вывод
- •19.1.Вывод
- •19.2.Ввод
- •19.3.Ввод и вывод определяемых пользователем типов
- •Программа 56. Перегрузка операторов ввода/вывода
- •19.4.Работа с файлами
- •Программа 57. Сравнение текстового и бинарного файлов
- •Задачи 199-202. Ввод и вывод
- •Глава 20.Взаимоотношения классов
- •20.1.Объекты как члены класса
- •20.2.Конструкторы встроенных типов
- •Программа 58. Личные данные
- •20.3.Наследование
- •Пример наследования
- •Программа 59. Наследование
- •Управление доступом при наследовании
- •Наследование и конструкторы
- •Программа 60. Производный класс личных данных
- •20.4. Виртуальные функции
- •Программа 61. Невиртуальные функции
- •Программа 62. Виртуальные функции
- •20.5.Абстрактные классы
- •Программа 63. Абстрактный класс фигур
- •Вызов виртуальных функций
- •20.6. Совместимость типов
- •20.7.Множественное наследование
- •Программа 64. Системы уравнений Класс алгебраических векторов Vector
- •Класс прямоугольных матриц
- •Объявление класса Matrix
- •Реализация класса Matrix
- •Класс систем линейных уравнений
- •Пример использования классов
- •Задачи 203-212. Наследование классов
- •Глава 21.Шаблоны, исключения
- •21.1.Шаблоны
- •21.2.Шаблоны функций
- •Программа 65. Объявление и определение шаблона функции
- •21.3.Классы и шаблоны
- •Программа 66. Шаблон классов векторов
- •Программа 67. Шаблон классов динамических массивов
- •21.4.Обработка исключений
- •Программа 68. Расчет нод
- •21.5.Стандартная библиотека шаблонов
- •Программа 69. Использование шаблона векторов
- •Литература
- •Предметный указатель
- •603950, Н. Новгород, пр. Гагарина, 23
- •603000, Н. Новгород, ул. Б. Покровская, 37.
Задачи 199-202. Ввод и вывод
Для комплексных чисел (программа 54) перегрузите операторы ввода и вывода. Используйте эти операторы для ввода коэффициентов уравнения из файла и записи решения уравнения в файл.
Перегрузите операторы ввода и вывода для структуры Time (программа 41).
Для класса Date (программы 42-48) перегрузите операторы ввода и вывода.
В классе Polinom (задача 198) перегрузите операторы ввода и вывода. Используйте их для ввода коэффициентов полинома из файла и записи результатов действий над полиномами в файл.
Глава 20.Взаимоотношения классов
На базе ранее разработанных классов можно создавать новые классы. Это можно делать, включая объекты одного класса в состав другого, например, так как прямоугольник rect включает две точки point в программе 36, или делая новый класс производным от другого.
20.1.Объекты как члены класса
Пусть есть класс:
class Member {
int a;
public:
Member (int i) // Конструктор класса Member
{a = i;}
};
Объявим новый класс, который будет включать в качестве своего члена объект класса Member:
сlass Container{ // Класс, содержащий объект другого класса
Member aa; // Объект aa класса Member – член класса Container
double x;
public:
Container(int i, double xx); // Конструктор
};
При создании объекта класса Container должен создаваться и объект aa класса Member, для чего должен вызываться соответствующий конструктор. Это реализуется с помощью специальной синтаксической конструкции:
Container :: Container(int i, double xx): aa(i) //Конструктор Container
{ x = xx; }
После заголовка конструктора ставится двоеточие, за которым идет имя объекта и в скобках аргументы конструктора объекта. Далее идет реализация остальной части конструктора класса, содержащего объект.
20.2.Конструкторы встроенных типов
Встроенные типы можно рассматривать как классы, имеющие конструкторы, поэтому конструктор для Member можно реализовать в виде:
Member(int i): a(i) {}
Здесь запись a(i) означает вызов конструктора встроенного типа int. Аналогично, конструктор класса Container можно записать в виде:
Container :: Container(int i, double xx): aa(i), x(xx) { }
Запись x(xx) означает вызов конструктора для типа double.
Программа 58. Личные данные
Напишем программу, для работы с массивами персональных сведений о людях. Эти сведения должны включать фамилию человека и его дату рождения.
Создадим модуль DateCls для класса моделирования календарных дат, внеся в этот класс конструктор копирования и оператор сравнения дат.
// Файл DateCls.H
#ifndef DateClsH
#define DateClsH
class Date // Класс для работы с датами
{
int d, m, y; // День, месяц, год
static int d0, m0, y0; // Начальная дата
static int dw0; // День недели начальной даты.
public:
Date(int = 0, int = 0, int = 0); // Конструктор
Date(Date&); // Конструктор копирования
static void SetInitDate(int di, int mi, int yi, int dwi)
{ d0 = di; m0 = mi; y0 = yi; dw0 = dwi; }
int DayOfYear(); // Номер дня в году
long Diapason(Date dt); // Диапазон между двумя датами
void PrintDate(); // Печать даты
char* WeekDay(); // Название дня недели
bool operator<=(Date&); // Сравнение двух дат
};
bool Leap(int year); // Проверка високосный или нет год year
#endif
Реализацию класса Date поместим в файле DateCls.CPP. Ниже приводится только та часть этого файла, которая отличается от рассмотренных ранее реализаций класса дат (см. программы 42-48).
// Файл DateCls.cpp
#include ”DateCls.h”
Date :: Date(Date& D) // Конструктор копирования
{ d = D.d; m = D.m; y = D.y; } // создает копию даты D
bool Date :: operator<=(Date& D) // Сравнение двух дат
{
return (y < D.y) || (y == D.y && m < D.m)
|| (y == D.y && m == D.m && d <= D.d);
}
Создадим модуль Persons, в котором разместим классы для работы со сведениями об отдельной личности и о группе лиц. Далее приводится заголовочный файл этого модуля:
// Файл Persons.h
#ifndef PersonsH
#define PersonsH
#include "DateCls.h" // Подключение класса Date
#include <iostream.h>
#include <fstream.h>
#include <string.h>
class Pers // Класс со сведениями о человеке
{
char* name; // Строка с фамилией и инициалами
Date bd; // Дата рождения
public:
Pers(char*, Date); // Конструктор
Pers(); // Конструктор по умолчанию
Pers(Pers&); // Конструктор копирования
~Pers() // Деструктор
{ delete[] name;} // Удаление строки с именем
Pers& operator = (Pers &); // Оператор присваивания
void Print(); // Вывод сведений о человеке
// CmpDate: возвращает true, если дата объекта ps1
// более ранняя или та же, что и у объекта ps2
friend bool CmpDate(Pers& ps1, Pers& ps2) // Используется
{ return ps1.bd <= ps2.bd; } // функция-оператор сравнения дат
};
class Persons // Класс для моделирования группы лиц
{
Pers* G; // Массив сведений о людях
int size; // Размер массива
int n; // Текущее число людей в группе
public:
Persons(int size = 25); // Конструктор. По умолчанию 25 человек
void Add(Pers&); // Добавление человека в группу
void Print(); // Печать группы
~Persons(); // Деструктор
friend void ReadFromFile(ifstream& inf, Persons&); // Чтение данных
// о группе из файла
void SortPersons(bool (*Compare)(Pers& ps1, Pers& ps2)); // Сортировка
// массива по критерию, задаваемому функцией сравнения Compare
void Swap(int i, int j); // Поменять местами элементы i и j массива G
};
#endif
Теперь приведем файл реализации модуля Persons.cpp.
// Файл Persons.cpp
#include "Persons.h"
Конструктор класса Pers пишем по изложенному выше правилу:
Pers :: Pers(char *s, Date D): bd(D) // Конструктор
{ // Сначала вызывается конструктор для объекта bd
name = new char [strlen(s)+1]; // Выделение памяти под имя
strcpy(name, s); // Копирование имени
}
Так как у класса Date есть конструктор по умолчанию, он будет вызываться в следующем конструкторе по умолчанию для класса Pers:
Pers :: Pers() // Конструктор по умолчанию
{ // Текущая дата как дата рождения
name = NULL; // Пустое имя
}
Pers::Pers(Pers& ps) // Конструктор копирования
{
name = new char [strlen(ps.name) + 1]; // Выделение памяти под имя
strcpy(name, ps.name); // Копирование имени
bd = ps.bd; // Копирование даты
}
Pers& Pers :: operator = (Pers& ps) // Перегрузка оператора присваивания
{
if (this != &ps){ // Если присваивание не самому себе,
delete[] name; // удаление старого имени,
name = new char [strlen(ps.name) + 1]; // память под новое имя,
strcpy(name, ps.name); // копирование имени,
bd = ps.bd; // копирование даты
}
return *this; // Возвращение ссылки на объект
}
void Pers :: Print() // Вывод сведений о человеке
{
cout << name << " \t"; // Вывод имени
bd.PrintDate(); // Вывод даты
}
Здесь после вывода имени печатается несколько пробелов и символ табуляции, чтобы даты выравнивались по вертикали. Число пробелов определяется подбором.
Далее идет реализация класса Persons, моделирующего группу.
Persons :: Persons(int sz) // Конструктор
{
G = new Pers[size = sz]; // Выделение памяти под массив
n = 0; // Вначале группа пуста
}
Создание массива объектов класса Pers возможно потому, что в этом классе есть конструктор по умолчанию, который создает объекты с пустыми фамилиями и текущими датами.
Без наличия в классе конструктора по умолчанию создание массива объектов класса невозможно.
Persons :: ~Persons() // Деструктор
{ delete[] G; } // Освобождение памяти
При удалении каждого объекта из массива для него будет автоматически вызван деструктор, так как при создании каждого объекта использовался конструктор.
void Persons :: Add(Pers& st) // Добавление в группу
{ // нового человека
if (n == size){ // Если в группе нет
cout << "Мест нет\n"; // мест, то выход
return;
}
G[n++] = st; // Добавление сведений о новом члене группы
}
В инструкции G[n++] = st; используется перегруженный оператор присваивания класса Pers.
void Persons :: Print() // Печать группы
{
for(int i = 0; i < n; i++) // Печать данных
G[i].Print(); // о каждом человеке
}
void ReadFromFile(ifstream& inf, Persons& grp) // Чтение данных
{ // о группе из файла
const int N = 200;
int ng; // Число людей в группе
char s[N]; // Массив для фамилии
int d, m, y;
inf >> ng; // Чтение размера группы
inf.getline(s, N); // Чтение '\n' из первой строки и переход к следующей
for(int i = 0; i < ng; i++){
inf.getline(s, N); // Чтение из файла строки с фамилией и инициалами
inf >> d >> m >> y; //Чтение компонентов даты
grp.Add(Pers(s, Date(d, m, y))); // Добавление сведений в группу
inf.getline(s, N); // Чтение '\n' для перехода на следующую строку
}
}
// Сортировка массива методом пузырька по критерию,
// задаваемому функцией сравнения Compare
void Persons :: SortPersons(bool (*Compare)(Pers& ps1, Pers& ps2))
{
for(int i = n - 1; i > 0; i--)
for(int j = 0; j < i; j++)
if(!Compare(G[j], G[j + 1])) //Если не тот порядок элементов,
Swap(j, j + 1); //переставить их
}
Аргументом функции сортировки является указатель Compare на функцию, которая сравнивает личные сведения двух людей.
void Persons :: Swap(int i, int j) //Переставить элементы i и j массива G
{
Pers tmp = G[i];
G[i] = G[j];
G[j] = tmp;
}
В главной программе создадим один объект класса Persons (одну группу). Заполним объект сведениями, прочитанными из файла PersData.txt, распечатаем, отсортируем по возрастанию даты рождения и снова распечатаем. Все это – в файле MainPers.cpp:
// Файл MainPers.cpp
#include "Persons.h"
int main()
{
Persons Writers; // Writers – объект класса Persons
ifstream inf("PersData.txt"); // Создаем файловый поток для чтения
if(!inf){ // Если файл не удалось открыть,
cerr << "Не удалось открыть файл PersData.txt ";
exit(1); // завершаем программу
}
ReadFromFile(inf, Writers); // Чтение сведений из файла
cout << "Состав группы: \n";
Writers.Print(); // Вывод состава группы
// Сортировка по возрастанию даты рождения
Writers.SortPersons(CmpDate);
cout << "\nСостав группы по возрастанию даты: \n";
Writers.Print(); // Вывод состава группы
cin.get(); // Ждем нажатия Enter
return 0;
}
Текстовый файл исходных данных можно создать любым редактором, в частности редактором среды разработки, с помощью которого создаются исходные тексты программ. Подготовим в файле PersData.txt следующие исходные данные:
9
Толстой Л.Н.
9 9 1828
Пушкин А.С.
6 6 1799
Лермонтов М.Ю.
15 10 1814
Крылов И.А.
13 2 1769
Тургенев И.С.
28 10 1818
Ломоносов М.В.
19 11 1711
Горький А.М.
28 3 1868
Достоевский Ф.М.
11 11 1821
Шолохов М.А.
24 5 1905
Здесь 9 – количество записей в файле. Далее в отдельных строках располагаются имена и компоненты даты рождения. На такую структуру файла исходных данных настроена функция ReadFromFile.
Программа выдает следующее:
Состав группы:
Толстой Л.Н. 9.9.1828
Пушкин А.С. 6.6.1799
Лермонтов М.Ю. 15.10.1814
Крылов И.А. 13.2.1769
Тургенев И.С. 28.10.1818
Ломоносов М.В. 19.11.1711
Горький А.М. 28.3.1868
Достоевский Ф.М. 11.11.1821
Шолохов М.А. 24.5.1905
Состав группы по возрастанию даты:
Ломоносов М.В. 19.11.1711
Крылов И.А. 13.2.1769
Пушкин А.С. 6.6.1799
Лермонтов М.Ю. 15.10.1814
Тургенев И.С. 28.10.1818
Достоевский Ф.М. 11.11.1821
Толстой Л.Н. 9.9.1828
Горький А.М. 28.3.1868
Шолохов М.А. 24.5.1905
