П№18 Шаблоны

18.1. Примеры решения задач

18.1.1. Пример решения простой задачи

Задача

Написать функцию, сортирующую массивы произвольного типа.

Решение (проект Simple)

//main. cpp

#include "sort. h"

#include <stdlib. h>

#include <iostream>

using namespace std; //Пространство имён по умолчанию std

//Функция, инициализирующая массив случайным образом

template <class Type>

void InitArray(Type *mas, int size)

{

for(int i=0; i<size; ++i)

mas[i] = (Type)rand();

}

//Функция, выводящая массив на экран

template <class Type>

void PrintArray(Type *mas, int size)

{

for(int i=0; i<size; ++i)

cout << " ["<< i <<"]=" << mas[i] << endl;

}

//Функция, проверяющая сортировку для заданного типа

template <class Type>

void CheckSort(int size)

{

Type *mas = new Type[size]; //Создание массива

InitArray(mas, size);

cout << "Check type: " << typeid(Type).name() << endl;

cout << "Initial array:\n";

PrintArray(mas, size);

sort(mas, size);

cout << "Sorted array:\n";

PrintArray(mas, size);

cout << endl;

delete[] mas; //Удаление массива

}

int main()

{

CheckSort<short int>(10);

CheckSort<int>(10);

CheckSort<char>(10);

CheckSort<float>(10);

CheckSort<double>(10);

return 0;

}

//sort. h

#pragma once //Только для Microsoft compiler

//Include guard

#ifndef __SORT_H__

#define __SORT_H__

НЕ нашли? Не то? Что вы ищете?

//Сортировка выбором

template <class Type>

void sort(Type* mas, int size)

{

for(int i=0; i<size-1; ++i)

{

int min = i; //Индекс минимального элемента в неотсортированной части

for(int j=i+1; j<size; ++j)

if(mas[min] > mas[j]) //Сравнение должно быть реализовано для типа Type

min = j;

if(min!= i)

{

Type tmp = mas[i]; //Присваивание должно быть реализовано для типа Type

mas[i] = mas[min];

mas[min]=tmp;

}

}

}

#endif

18.1.2. Пример решения задачи средней сложности

Задача

Написать функцию, сортирующую массивы произвольного типа. Реализовать класс комплексных чисел с произвольным типом действительной и мнимой частей. Привести пример использования разработанной функции как для встроенных типов (int, char, short, float, double), так и для класса комплексных чисел.

Решение (проект Average)

//main. cpp

#include "sort. h"

#include "Complex. h"

#include <stdlib. h>

#include <iostream>

using namespace std; //Пространство имён по умолчанию std

//Генерация элемента случайным образом

template <class Type>

void InitElement(Type &el)

{

el = Type(rand());

}

//Специализация для типа double

template<>

void InitElement<double>(double &el)

{

el = (rand()/2.-RAND_MAX) / (rand() + 1.);

}

//Специализация для типа float

template<>

void InitElement<float>(float &el)

{

el = (rand()/2.f-RAND_MAX) / (rand() + 1.f);

}

//Специализация для типа char

//Только заглавные английские буквы

template<>

void InitElement<char>(char &el)

{

el = rand() % 26 + 65;

}

//Генерация элемента случайным образом типа Complex

template <class Type>

void InitElement(Complex<Type> &el)

{

Type re, im;

InitElement(re);

InitElement(im);

el = Complex<Type>(re, im);

}

//Функция, инициализирующая массив случайным образом

template <class Type>

void InitArray(Type *mas, int size)

{

for(int i=0; i<size; ++i)

InitElement(mas[i]);

}

//Функция, выводящая массив на экран

template <class Type>

void PrintArray(Type *mas, int size)

{

for(int i=0; i<size; ++i)

cout << " ["<< i <<"]=" << mas[i] << endl;

}

//Функция, проверяющая сортировку для заданного типа

template <class Type>

void CheckSort(int size)

{

Type *mas = new Type[size]; //Создание массива

InitArray(mas, size);

cout << "Check type: " << typeid(Type).name() << endl;

cout << "Initial array:\n";

PrintArray(mas, size);

sort(mas, size);

cout << "Sorted array:\n";

PrintArray(mas, size);

cout << endl;

delete[] mas; //Удаление массива

}

int main()

{

CheckSort<short int>(10);

CheckSort<int>(10);

CheckSort<char>(10);

CheckSort<float>(10);

CheckSort<double>(10);

CheckSort<Complex<float>>(10);

CheckSort<Complex<int>>(10);

CheckSort<Complex<Complex<float>>>(10);

return 0;

}

//sort. h

#pragma once //Только для Microsoft compiler

//Include guard

#ifndef __SORT_H__

#define __SORT_H__

//Сортировка выбором

template <class Type>

void sort(Type* mas, int size)

{

for(int i=0; i<size-1; ++i)

{

int min = i; //Индекс минимального элемента в неотсортированной части

for(int j=i+1; j<size; ++j)

if(mas[min] > mas[j]) //Сравнение должно быть реализовано для типа Type

min = j;

if(min!= i)

{

Type tmp = mas[i]; //Присваивание должно быть реализовано для типа Type

mas[i] = mas[min];

mas[min]=tmp;

}

}

}

#endif

//Complex. h

#pragma once //Только для Microsoft compiler

//Include guard

#ifndef __COMPLEX_H__

#define __COMPLEX_H__

#include <iostream>

template <class Type>

class Complex

{

private:

Type re, im;

public:

Complex(Type re_t = 0, Type im_t = 0): re(re_t), im(im_t)

{}

bool operator==(Complex& right) const

{

if(re == right. re && im == right. im)

return true;

else

return false;

}

bool operator>(Complex& right) const

{

if(re > right. re)

return true;

else

if(re == right. re && im > right. im)

return true;

else

return false;

}

std::ostream& Print(std::ostream& o) const

{

o << "<"<< re << ", " << im << ">";

return o;

}

};

template <class Type>

std::ostream& operator<<(std::ostream& o, const Complex<Type>& instance)

{

return instance. Print(o);

}

#endif

18.2. Задачи для самостоятельного решения

18.2.1.  Простые задачи

Функции с шаблоном

Написать функцию, для поиска минимального элемента массива (элементы массива могут быть произвольного типа). Написать функцию, для поиска максимального элемента массива (элементы массива могут быть произвольного типа). Написать функцию, для поиска позиции первого максимального элемента массива (элементы массива могут быть произвольного типа). Написать функцию, для поиска позиции последнего минимального элемента массива (элементы массива могут быть произвольного типа). Написать функцию, реализующую сумму векторов (элементы вектора могут быть произвольного типа). Размеры векторов не обязаны совпадать. Написать функцию, реализующую скалярное умножение векторов (элементы вектора могут быть произвольного типа). Написать функцию умножения вектора на скаляр (элементы вектора могут быть произвольного типа, тип скаляра и элементов вектора могут не совпадать). Написать функция вычисления модуля двух чисел.

Классы с шаблоном

Реализовать класс для хранения массива произвольной длины (элементы массива могут быть произвольного типа). Реализовать следующие операции: доступ к элементу через [], сортировка элементов, вывод в поток. Реализовать класс для хранения массива произвольной длины (элементы массива могут быть произвольного типа). Реализовать следующие операции: доступ к элементу через [], вставка элемента в конец массива, удаление элемента из начала массива (порядок остальных элементов не должен меняться). Реализовать класс для представления комплексного числа (действительная и мнимая части могут быть произвольного типа). Реализовать методы: сложения/вычитания комплексных чисел, вывод на экран в различных форматах, задание/чтение действительной и мнимой частей. Реализовать класс для представления комплексного числа (действительная и мнимая части могут быть произвольного типа). Реализовать методы: сложения/вычитания комплексного числа и произвольного типа данных, задание/чтение действительной и мнимой частей, вычисление нормы.

18.2.2.  Задачи средней сложности

Функции с шаблоном

Для каждой задачи из раздела простых дополнительно реализовать класс комплексных чисел с произвольным типом действительной и мнимой частей. Привести пример использования разработанных функций как для встроенных типов (int, char, short, float, double), так и для класса комплексных чисел.

Классы с шаблоном

Для задач 1, 2 из раздела простых дополнительно реализовать класс комплексных чисел. Привести пример использования разработанного класса хранения элементов массива как для встроенных типов (int, char, short, float, double), так и для класса комплексных чисел.

Для задач 3, 4 из раздела простых дополнительно реализовать класс рациональных чисел. Привести пример использования разработанного класса комплексных чисел как для встроенных типов (int, char, short, float, double), так и для класса рациональных чисел.

18.2.3.  Задачи повышенной сложности

Буферизованная работа с фалами

Реализовать класс, выполняющий буферизованную работу с файлом. Класс должен предоставлять две основные функции: записать элемента произвольного типа в файла, чтение очередного элемента произвольного типа из фала. Запись должна осуществляться в конец фала. Чтение осуществляется сначала файла. Все операции с файлом должны быть буферизованы, т. е. любая операция записи выполняется в буфер памяти, а при заполнении буфера он записывает на жесткий диск. Любая операция чтения должна осуществляться из буфера памяти, который содержит данные заранее считанные из файла. Если все данные из буфера считаны, то с жесткого диска загружается следующая порция данных. Размер буфера памяти должен задаваться через шаблон.