- •Экзамен 374 Предварительные рассуждения Вступительное слово
- •Исторические факты
- •Начнем!
- •Проба пера
- •Открытие сохраненного проекта
- •Вывод данных
- •Типы данных
- •Хороший стиль программирования
- •Переменные и константы
- •Практический пример
- •Ввод данных
- •Например:
- •Пример:
- •Арифметические операции с числами
- •Литералы
- •Некоторые примеры
- •Домашнее задание
- •Напишите программу, которая вводит число из трех цифр, разделяет число на отдельные цифры и печатает их отдельно друг от друга с тремя пробелами между ними. Преобразование типов
- •Перечисляемые типы
- •Типичная ошибка
- •Хороший стиль программирования
- •Типичная ошибка
- •Выражения
- •Оператор if
- •Структура программы
- •Логические операции
- •Структура множественного выбора switch
- •Практический пример
- •Цикл for
- •Практический пример
- •Цикл do-while
- •Домашнее задание
- •Вызов функции
- •Прототипы функций
- •Разбор программы
- •Область видимости
- •Аргументы по умолчанию
- •Встраивание
- •Перегрузка функций
- •Учебный пример перегруженных функций. Иллюстрация перегрузки
- •Результат работы программы
- •Практические примеры
- •Домашнее задание
- •Примеры домашней работы урока 1 Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Примеры домашних работ на создание функций Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Массивы
- •Объявление массивов
- •Примеры использования массивов
- •Программа 1
- •Программа 2
- •Обратите внимание!
- •Типичная ошибка программирования
- •Типичная ошибка программирования
- •Программа 3
- •Типичная ошибка программирования
- •Замечание по технике программирования
- •Программа 4
- •Программа 5
- •Программа нахождения минимального и максимального элементов массива
- •Сортировка массивов
- •Домашнее задание
- •Что такое указатели?
- •За кулисами...
- •Как работать с указателями?..
- •Зачем нужны указатели?
- •Указатели и Массивы.
- •Примеры задач
- •Пример 1
- •Пример 2
- •Пример 3
- •Указатели - аргументы функций.
- •Ссылочные параметры
- •Примеры решения задач
- •Домашнее задание
- •Операторы свободной памяти new и delete
- •Функции работы со строками из библиотеки обработки строк
- •Пример 1.
- •Пример2
- •Пример 3
- •Пример задачи на новый материал
- •Домашнее задание
- •Двухмерные массивы, как частный случай многомерных массивов
- •Программа.
- •Результаты работы программы.
- •Многомерные динамические массивы
- •Пример на многомерные динамические массивы
- •Домашнее задание
- •Рекурсия
- •Рекурсии или итерации
- •Указатели на функции
- •Пример №1
- •Результат выполнения программы:
- •Пример №2
- •Результат выполнения программы
- •Пример №3
- •Результаты выполнения программы
- •Определения структур
- •Пример #1 на использование структур
- •Пример #2 на использование структур
- •Оператор указателя на структуру
- •Домашнее задание
- •Тест по c Группа ___________________ф. И. О. ______________________
- •Объектно-ориентированное программирование.
- •Наследование (Inheritance).
- •Инкапсуляция (Encapsulation).
- •Определение класса
- •Конструкторы и деструкторы Инициализация объектов класса: конструкторы
- •Основное назначение конструкторов - инициализация объектов.
- •Использование конструкторов с аргументами по умолчанию
- •Если параметры не передаются конструктору, в определении объекта не нужно включать пустые круглые скобки.
- •Использование деструкторов
- •Когда вызываются конструкторы и деструкторы.
- •Домашнее задание
- •Конструктор копирования
- •Синтаксис конструктора копирования
- •Памятка
- •Пример использования конструктора копирования.
- •Перегруженные конструкторы
- •Экскурс в историю
- •Послесловие к примеру
- •Маленькое замечание
- •Домашнее задание
- •Создание класса ''строка''
- •Перегрузка операций.
- •Общие принципы перегрузки операторов.
- •Преобразования, определяемые классом
- •Пример строкового класса с перегруженными операторами
- •Домашнее задание
- •Дружественные функции (Friend Functions)
- •Пример строкового класса с перегруженными операторами и дружественными функциями
- •Перегрузка операторов new и delete
- •Перегрузка оператора индексирования
- •Класс вектор. Часть1.
- •Класс вектор. Часть 2.
- •Класс вектор. Часть 3.
- •Домашнее задание
- •Наследование (Inheritance). Часть 1.
- •Наследование (Inheritance). Часть 2.
- •Множественное наследование (multiple inheritance)
- •Пример множественного наследования
- •Домашнее задание
- •Статические члены данных
- •Раннее и позднее связывание
- •Виртуальные функции
- •Пример.
- •Абстрактные классы
- •Виртуальный базовый класс
- •Практический пример
- •Домашнее задание
- •Потоки ввода-вывода.
- •Iostream.H: stream - поток, "I" - сокр. Input - ввод, "o" - сокр. Output - вывод.
- •Предопределенные потоки.
- •Операции помещения в поток и извлечения из потока.
- •Файловый ввод-вывод с применением потоков.
- •Конструкторы файловых потоков.
- •Функции для открытия и закрытия файлов.
- •Функции для обмена с потоками.
- •Часто применяемые функции потока.
- •Ввод/вывод массива в/из файл(-а).
- •Практический пример: перекодировка файла.
- •Домашнее задание
- •Немного о файлах...
- •И снова файлы...
- •Пример "Телефонная книга"
- •Файл abonent.H
- •Форматирование данных при обменах с потоками.
- •Состояние потока.
- •Использование аргументов командной строки.
- •Ввод/вывод в с.
- •Домашнее задание
- •Определение шаблонов функций
- •Переопределение шаблонов функций
- •Шаблоны классов
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Введение
- •Обработка исключительных ситуаций
- •Практический пример
- •Программа
- •Домашнее задание
- •Экзамен
Домашнее задание
Написать функцию, которая осуществляет поиск заданного слова в файлах по указанному пути и выводит на экран имена всех файлов, содержащих искомый элемент. Регистр букв не учитывать.
Даны два входных файла с числовыми данными file1 и file2. Сформируйте выходной файл, содержащий все элементы из файла file1 и те элементы файла file2, которые отсутсвуют в первом файле.
а) используйте потоковый ввод/вывод
б) используйте функции языка Си.
Определение шаблонов функций
С помощью шаблонов функций языка С++ можно создать единственное общее определение функции, использующееся с различными типами данных.
Давайте вспомним тему "Перегруженные функции". Для использования одной и той же функции с различными типами данных нужно определить отдельную перегруженную версию этой функции для каждого типа. Если требуется функция, возвращающая абсолютную величину значения как типа int, так и типа double, то нужно написать две перегруженные функции. Например:
int Abs(int N)
{
return N < 0 ? -N : N;
}
double Abs(double N)
{
return N < 0. ? -N : N;
}
Используя шаблон языка С++, можно создать единственное определение, которое будет автоматически обрабатывать значения типа int, double или любого подходящего другого типа. Такой шаблон выглядит следующим образом:
template <class T> T Abs (T N)
{
return N < 0 ? -N : N;
}
В этом определении идентификатор T является параметром типа. Он определяет тип переменной или константы, передаваемой при вызове функции. Если программа вызывает функцию Abs и передает ей значения типа int, например,
cout << "Абсолютное значение для -5 = " << Abs(-5);
то компилятор автоматически создаст версию функции, в которой идентификатор T имеет тип int, и добавит в программу вызов данной версии функции.
Созданная компилятором функция будет эквивалентна функции, определенной явно:
int Abs (int N)
{
return N < 0 ? -N : N;
}
Аналогично, если программа вызывает функцию Abs и передает ей значение типа double, например,
double D = -5.12;
cout << "Абсолютное значение для D = " << Abs(D);
то компилятор автоматически сгенерирует версию функции, в которой заменит параметр типа T на double, и добавит в программу вызов данной версии функции. Эта версия функции эквивалентна следующей:
double Abs(double N)
{
return N < 0. ? -N : N;
}
Таким же образом компилятор создает дополнительные версии функции для каждого вызова, в котором указывается новый числовой тип данных, например, short или float. Генерация новой версии функции называется созданием экземпляра шаблона функции.
|
При определении шаблона нужно использовать спецификаторы template и class вместе с угловыми скобками, как показано в приведенном выше примере. Для параметра типа Т можно использовать любой корректный идентификатор имени, а в угловые скобки можно включать несколько параметров типа.
|
При определении шаблона функции не путатйте понятия параметр функции и параметр типа. Параметр функции - это значение, передаваемое в функцию при выполнении программы. Параметр типа, напротив, задает тип аргумента, передаваемого в функцию, и полностью обрабатывается при компиляции. Обратите внимание: в определении шаблона спецификатор class в угловых скобках ссылается на любой тип данных, фактически передаваемых при вызове (как встроенный, так и определенный программистом).
Само по себе определение шаблона не вызывает генерацию кода компилятором. Компилятор создает код функции только при ее фактическом вызове. Первый же вызов с определенным типом данных приводит к генерации компилятором кода соответствующей версии функции. Последующие вызовы с указанием тех же типов данных не сгенерируют дополнительные копии функции, а только вызовут ее первоначальную копию. Но компилятор создаст новую версию функции, если тип параметра не совпадает в точности с типом в предыдущем вызове. Например, рассмотрим случай, когда программа передает в шаблон функции параметр типа long, а компилятор генерирует соответствующую версию функции. Если затем программа передаст параметр типа int, компилятор создаст полностью новую версию функции для обработки типа int. Он не будет выполнять стандартное преобразование int в long для использования кода первой версии функции.
Еще один пример шаблона функции:
template <class T> T Max (T A, T B)
{
return A > B ? A : B;
}
Этот шаблон генерирует функции, возвращающие большее из двух значений одинакового типа. Так как оба параметра определены как имеющие тип идентификатора T, в вызове функции оба передаваемых переметра должны быть только одного типа. Иначе компилятор не определит, какой тип соответствует параметру T - тип первого или второго параметра. Таким образом допустимы такие вызовы функции:
cout << "Большее из 10 и 5 = " << Max(10, 5) << endl;
cout << "Большее из 'A' и 'B' = " << Max('A', 'B') << endl;
cout << "Большее из 3.5 и 5.1 = " << Max(3.5, 5.1) << endl;
А следующий вызов является недопустимым:
cout << "Большее из 10 и 5.55 = " << Max(10, 5.55); // ОШИБКА!
Компилятор не преобразует второй параметр int в double для приведения типов, хотя это преобразование является стандартным.
Чтобы передавать параметры различных типов, нужно определить шаблон функции.
template <class T1, class T2> T1 Max(T1 A , T2 B)
{
return T2 (A > B ? A : B);
}
В этом шаблоне Т1 обозначает тип значения, передаваемого в качестве первого параметра, а Т2 - второго.
Для такой версии шаблона следующий оператор допустим и печатает значение 5.55
cout << "Большее из 10 и 5.55 = " << Max(10, 5.55);
В С++ параметр типа можно использовать в любом месте кода, в котором используется имя типа.
Так как возвращаемое значение преобразуется к типу второго параметра, то при изменении порядка параметров предыдущего примера
cout << "Большее из 5.55 и 10 = " << Max(5.55, 10);
результат сравнения будет округлен и равняться 5.
Каждый параметр типа, встречающийся внутри символов "<" и ">", должен также появляться в списке параметров функции. Т.е. следующее определение шаблона функции недопустимо:
template <class T1, class T2> T1 Max(T1 A , T1 B)
{
return A > B ? A : B;
}
// ОШИБКА! список параметров должен включать T2 как параметр типа.
При таком определении компилятор, встретив вызов функции, не сможет определить значение идентификатора T2. Это - ошибка, даже если идентификатор T2 не использован.