
- •СОДЕРЖАНИЕ
- •ПРЕДИСЛОВИЕ
- •ГЛАВА 1. Введение в алгоритмы
- •1.1. Этапы решения задач на ЭВМ
- •1.2. Понятие алгоритма
- •1.3. Свойства алгоритмов
- •1.4. Сложность алгоритма
- •1.7. Пример простейшего линейного процесса
- •1.7. Пример циклического процесса
- •ГЛАВА 2. Базовые средства языка Си
- •2.1. Алфавит языка Си
- •2.2. Лексемы
- •2.3. Идентификаторы и ключевые слова
- •2.4. Комментарии
- •2.5. Простейшая программа
- •2.7. Декларация объектов
- •2.8. Данные целого типа (integer)
- •2.9. Данные символьного типа (char)
- •2.10. Данные вещественного типа (float, double)
- •ГЛАВА 3. Константы в программах
- •3.2. Константы вещественного типа
- •3.4. Строковые константы
- •ГЛАВА 4. Обзор операций
- •4.1. Операции, выражения
- •4.3. Операция присваивания
- •4.4. Сокращенная запись операции присваивания
- •4.7. Операции сравнения
- •4.8. Логические операции
- •4.10. Операция «,» (запятая)
- •ГЛАВА 5. Обзор базовых инструкций языка Си
- •5.2. Стандартные математические функции
- •5.3. Функции вывода данных на дисплей
- •5.4. Функции ввода информации
- •ГЛАВА 6. Составление разветвляющихся алгоритмов
- •6.1. Краткая характеристика операторов языка Си
- •ГЛАВА 7. Составление циклических алгоритмов
- •7.1. Понятие циклического кода
- •7.2. Оператор с предусловием while
- •7.4. Оператор цикла с предусловием и коррекцией for
- •ГЛАВА 8. Операторы и функции передачи управления
- •8.1. Оператор безусловного перехода goto
- •8.2. Операторы continue, break и return
- •8.3. Функции exit и abort
- •Советы по программированию
- •ГЛАВА 9. Указатели
- •9.1. Определение указателей
- •9.2. Операция sizeof
- •9.3. Инициализация указателей
- •9.4. Операции над указателями
- •ГЛАВА 10. Массивы
- •10.1. Понятие массива
- •10.2. Одномерные массивы
- •10.4. Строки как одномерные массивы данных типа char
- •10.5. Указатели на указатели
- •10.8. Работа с динамической памятью
- •10.9. Библиотечные функции
- •10.10. Пример создания одномерного динамического массива
- •ГЛАВА 11. Функции пользователя
- •11.1. Декларация функции
- •11.2. Вызов функции
- •11.3. Передача аргументов в функцию
- •11.4. Операция typedef
- •11.5. Указатели на функции
- •ГЛАВА 12. Классы памяти и область действия объектов
- •ЗАДАНИЕ 4. Обработка массивов
- •Первый уровень сложности
- •Второй уровень сложности
- •ЗАДАНИЕ 5. Функции пользователя
- •Первый уровень сложности
- •Второй уровень сложности
- •12.3. Статические и внешние переменные
- •12.4. Область действия переменных
- •Советы по программированию
- •13.1. Структуры
- •13.5. Вложенные структуры
- •13.6. Массивы структур
- •13.7. Размещение структурных переменных в памяти
- •13.8. Объединения
- •13.9. Перечисления
- •13.10. Битовые поля
- •ГЛАВА 14. Файлы в языке Си
- •14.1. Открытие файла
- •14.2. Закрытие файла
- •14.3. Запись-чтение информации
- •14.5. Дополнительные файловые функции
- •Советы по программированию
- •ЗАДАНИЕ 7. Создание и обработка файлов
- •Первый уровень сложности
- •Второй уровень сложности
- •ГЛАВА 15. Динамические структуры данных
- •15.1. Линейные списки
- •15.2.1. Алгоритм формирования стека
- •15.2.2. Алгоритм извлечения элемента из стека
- •15.2.3. Просмотр стека
- •15.2.4. Алгоритм освобождения памяти, занятой стеком
- •15.2.5. Алгоритм проверки правильности расстановки скобок
- •15.3.1. Формирование очереди
- •15.3.2. Алгоритм удаления первого элемента из очереди
- •15.4. Двунаправленный линейный список
- •15.4.1. Формирование первого элемента
- •15.4.3. Алгоритм просмотра списка
- •15.4.5. Алгоритм удаления элемента в списке по ключу
- •15.5. Нелинейные структуры данных
- •15.5.1. Бинарные деревья
- •15.5.2. Основные алгоритмы работы с бинарным деревом
- •15.5.4. Вставка нового элемента
- •15.6. Построение обратной польской записи
- •15.6.1. Алгоритм, использующий дерево
- •15.6.2. Алгоритм, использующий стек
- •15.6.3. Пример реализации
- •15.7. Понятие хеширования
- •15.7.2. Примеры хеш-функций
- •15.7.3. Схемы хеширования
- •15.7.4. Примеры реализации схем хеширования
- •Вариант 2. Двунаправленные списки
- •ГЛАВА 16. Переход к ООП
- •16.1. Потоковый ввод-вывод
- •16.3. Проблема ввода-вывода кириллицы в среде Visual C++
- •16.4. Операции new и delete
- •16.6. Шаблоны функций
- •Первый уровень сложности
- •Второй уровень сложности
- •6.1. Основные понятия
- •6.3. Примитивы GDI
- •6.5. Получение описателя контекста устройства
- •6.6. Основные инструменты графической подсистемы
- •6.7. Закрашивание пустот
- •6.8. Рисование линий и кривых
- •6.9. Пример изображения графика функции sin
- •6.10. Рисование замкнутых фигур
- •6.11. Функция Polygon и режим закрашивания многоугольника
- •6.13. Управление областями вывода и отсечением
- •ЗАДАНИЕ 11. Создание графических изображений
- •ЛИТЕРАТУРА
16.6. Шаблоны функций
Понятие шаблона функции
Параметризация определений функций позволяет сократить трудоемкость программирования и повысить лаконичность текста.
Механизм шаблонов – средство построения обобщенных определений функций, независимых от используемых типов данных. Их использование избавляет от необходимости дублировать код функции для различных типов
данных, составляющих их параметры и возвращаемые результаты. Это позволяет снять достаточно жесткие ограничения, накладываемые механизмом взаимосвязи между формальными параметрами и фактическими
данных на основе определения шаблона автоматическиИпорождает соответствующие экземпляры или «представители» функций.
аргументами при вызове функции. |
Р |
|
|
Компилятор по заданному в качестве аргумента конкретному типу |
Рассмотрим необходимость создания шаблона функции на конкретном |
|||
примере. |
|
У |
|
Г |
|||
|
|||
|
Б |
|
Пусть нужно написать код для определения максимального из пар значений х и у для разных типов зн чений для этой пары: например,
целочисленные данные и пара вещественных д нных.
Существуют следующие варианты решения данной задачи. |
|||||
|
|
|
|
е |
|
1. Для ускорения работы программы воспользоваться перегрузкой |
|||||
функций: |
|
т |
к |
||
int Max(int x, int y) { |
|
|
|||
|
|
return (x>y) ? x : y; |
|||
} |
|
о |
|
|
|
|
|
и |
|
|
|
double Max(double x, double y) { |
|||||
} |
|
return(x>y)? x : y; |
|
||
|
. . . |
|
|
|
|
|
б |
|
|
|
|
int i, j, k; |
|
|
|
|
|
и |
|
|
|
|
|
k = Max(i,лj); |
|
|
// Первая функция |
||
double a, b, d; |
|
|
|
||
Б |
|
|
|
|
// Вторая функция |
d = Max(a, b); |
|
|
. . .
Идентификаторы функций и их код дублируются, различие только в типах параметров и возвращаемого результата.
2. Вторая возможность – воспользоваться макросом: #define Max(x, y) ((x>y) ? x : y )
В этом случае недостатки:
– снижается надежность, т.к. при использовании макросов не работает проверка типов аргументов;
178
– данная подстановка будет выполнена во всех местах, где встретится
Max;
– в данной ситуации лучше воспользоваться механизмом шаблонов, основанном на параметризации. Данная параметризация осуществляется при помощи обобщенного определения этой функции шаблоном (template), в котором тип параметров определяют символическим идентификатором (например буквой).
Компилятор, проанализировав передаваемые в функцию аргументы, а именно – их типы, сгенерирует код нужной функции, заменив символическое имя типа параметров на конкретный тип.
Формат шаблона функции: |
|
|
|
|
|
|
Р |
|||||
|
template список параметров шаблона |
|
||||||||||
|
|
декларация функции; |
|
|
|
|
||||||
Набор параметризуемых |
типов |
определяется |
списком параметров |
|||||||||
|
|
|
|
|
|
|
|
|
|
И |
|
|
шаблона. Каждый тип определяется ключевым словом class и локальным в |
||||||||||||
|
|
|
|
|
|
|
|
|
|
У |
|
|
рамках функции идентификатором типа. Список параметров не может быть |
||||||||||||
пустым, а его элементы разделяются запятыми. |
|
|
|
|
||||||||
Элемент декларация функции – обычное определениеГ(или описание – |
||||||||||||
|
|
|
|
|
|
|
лона |
|
|
|
||
прототип) функции. В списке ее параметров необходимо упомянуть хотя бы |
||||||||||||
один раз типы параметров из списка шаб |
|
. |
Б |
|
|
|
||||||
|
|
|
|
|
|
к |
|
|
|
|
|
|
Примеры отношений между параметр ми ш блона и функции: |
|
|||||||||||
1. Шаблон может иметь единств нный параметр: |
|
|
|
|||||||||
|
|
|
|
т |
|
|
|
|
|
|
|
|
|
template <class T> |
е |
|
|
|
|
|
|||||
|
void f1(T par) { |
|
|
|
|
|
|
|||||
|
|
|
о |
|
|
|
|
|
|
|
|
|
|
} |
код функции f1 |
|
|
|
|
|
|
|
|
||
|
и |
|
|
|
|
|
|
|
|
|
||
При этом с мв л т па T можно использовать и для спецификации |
||||||||||||
|
л |
|
|
|
|
|
|
|
|
|
|
|
возвращаемого значен я, а также для любых других объектов в коде |
||||||||||||
|
б |
|
|
|
|
|
|
|
|
|
|
|
функции. О язате ьный пункт – использование T в списке параметров |
||||||||||||
функции выпо нен. |
|
|
|
|
|
|
|
|
|
|
||
ри |
может |
иметь |
любые |
типы |
параметров |
как |
||||||
Функция |
||||||||||||
парамет зованные, так и стандартно декларированные. |
|
|
||||||||||
Б |
|
|
|
|
|
|
|
|
|
|
|
|
2. Шаблон функции с частично параметризованными параметрами: |
|
template <class T>
void f2(T par, int x, int y) {
код функции f2
}
3. Шаблон может иметь несколько параметризованных параметров с разными символическими идентификаторами:
template <class T2, class T1> void f3(T1 par1, T2 par2) {
179
код функции f3
}
Порядок следования ID параметров в заголовке функции может отличаться от их декларации в шаблоне.
Использование шаблона функций не требует специальных действий от программиста, т.к. компилятор автоматически формирует требуемый операцией вызова экземпляр кода по набору типов аргументов, которые передаются в функцию. То есть шаблон функции не является ее экземпляром. Только при обращении к функции с аргументами конкретного типа происходит генерация конкретной функции.
Пример нахождения максимума для разных типов аргументов:
#include <iostream.h> |
|
|
|
|
|
|
|
Р |
||||
template <class T> |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
И |
||||||
T max(T x, T y) { |
|
|
|
|
|
|
||||||
|
|
return(x>y)? x : y; |
|
|
|
|
|
|||||
|
} |
|
|
|
|
У |
|
|||||
|
|
|
|
|
|
|
|
|
|
|||
|
void main() |
|
|
|
|
|
Г |
|
|
|||
|
{ |
|
|
|
|
|
|
|
|
|
||
|
int i = 2, j = 3; |
|
|
|
|
Б |
|
|
|
|||
|
|
|
|
|
|
|
|
|
||||
|
|
double x = 1.5, y = 2.5; |
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|||||
|
|
cout <<” I = ”<<i<<” J = ”<<j<< “ Max = ”<<max(i, j)<<endl; |
||||||||||
|
|
|
|
|
|
|
|
а |
|
|
|
|
|
|
cout <<” X = ”<<x<<” Y = ”<<y<<” Max = ”<<max(x,y)<<endl; |
||||||||||
|
} |
|
|
|
|
|
к |
|
|
|
|
|
|
|
|
|
|
|
е |
|
|
|
|
|
|
Результат выполнения программы: |
|
|
|
|
||||||||
|
|
i = 2 j = 3 Max = 3 |
|
|
|
|
|
|
||||
|
|
X = 1.5 y = 2.5 Max = 2.5 |
|
|
|
|
|
|||||
|
|
|
|
|
т |
|
|
|
|
|
|
|
Таким образом, шаблон функции избавил копирование ее определения |
||||||||||||
|
|
|
|
о |
|
|
|
|
|
|
|
|
для различных т пов данных. |
|
|
|
|
|
|
|
|||||
|
|
|
и |
|
|
|
|
|
|
|
|
|
Перегрузка шаблонов функций |
|
|
|
|
|
|||||||
|
|
л |
|
|
|
|
|
|
|
|
|
|
Можно перегружать функции-шаблоны для неподходящих под |
||||||||||||
|
б |
|
|
|
|
|
|
|
|
|
|
|
данный код шаблона данных, т.к. их использование базируется, как и у |
||||||||||||
и |
|
|
|
|
|
|
|
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
|
|
обычных функций, на распознавании компилятором различий в списках их параметров.
Кроме того, т.к. код шаблона не меняется, лучше его оформлять отдельным заголовочным файлом, а в функции, которая его использует, подключать его на этапе препроцессорной обработки.
Приведем пример перегрузки шаблонов, состоящей из ограничения использования функции mах для некоторых типов аргументов.
Перегрузка шаблона создается путем явного его определения (специализированная функция) для конкретного типа данных.
180
Например, для строк шаблон-функция mах не подходит, так как все операции над строками производятся только при помощи библиотечных функций, декларированных в заголовочном файле string.h.
Шаблон функции поиска максимума будет иметь следующий вид:
|
template <class T> |
|
|
|
|
|
|
|
|
||||
T max(T x, T y) { |
|
|
|
|
|
|
|
|
|
|
|||
} |
|
return (x>y)? x : y; |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
Р |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
Специализированная функция выбора максимальной из двух строк: |
|||||||||||||
char* max(char* x, char* y) { |
|
|
|
|
И |
||||||||
|
|
return (strcmp(x, y)>0) ? x : y; |
|
|
|||||||||
|
|
|
У |
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
||
Осуществляется следующая последовательность этапов выбора |
|||||||||||||
«экземпляра» перегруженных функций: |
|
Г |
|
|
|||||||||
|
|
|
|
|
|||||||||
1) |
поиск специализированной (не шаблон) функции с совпадающим |
||||||||||||
списком параметров, и в случае неудачи: |
|
Б |
|
|
|
||||||||
|
|
|
|
|
|||||||||
– поиск шаблона функции с точным соответствием списка параметров; |
|||||||||||||
– поиск специальной функции по условию совпадения списка |
|||||||||||||
параметров после возможных преобразов ний типов; |
|
|
|
||||||||||
2) |
поиск завершается |
|
|
к |
|
|
|
|
|||||
выбором нужной функции при совпадении |
|||||||||||||
|
|
|
|
|
|
|
е |
аом передаваемых аргументов. |
|||||
параметров экземпляра функции со спис |
|||||||||||||
Программа, использующая пр образования шаблонов и специализи- |
|||||||||||||
|
|
|
|
|
ть |
|
|
|
|
|
|
||
рованных функций, будет име |
сл дующий вид: |
|
|
|
|||||||||
#include <stdio.h> |
|
|
о |
|
|
|
|
|
|
|
|
||
#include <string.h> |
|
|
|
|
|
|
|
|
|
||||
и |
|
|
|
|
|
|
|
|
|
||||
template <class T> |
|
|
|
|
|
|
|
|
|
||||
T max(T x, T y) { |
|
|
|
|
|
|
|
|
|
|
|||
|
л |
|
|
|
|
|
|
|
|
|
|
||
|
return (x>y)? x : y; |
|
|
|
|
|
|
|
|
||||
} |
б |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char* max(char* x, char* y) { |
|
|
|
|
|
|
|||||||
и{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
return (strcmp(x, y)>0) ? x : y; |
|
|
|
|
|
|||||||
void main() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int a=7, b=5; |
|
|
|
|
|
|
|
|
|
|||
Б char c1=’a’, c2=’z’; |
|
|
|
|
|
|
|
char s1[]=”one”, s2[]=”two”;
printf(“\n a=%d, b=%d, max=%d \n”, a, b, max(a, b)); printf(“\n c1=%c, c2=%c, max=%c \n”, c1, c2, max(c1, c2)); printf(“\n s1=%s, s2=%s, max=%s \n”, s1, s2, max(s1, s2));
}
181
При построении шаблонов функций, они, как правило, декларируются прототипами, а в программе определяются в произвольном порядке.
Рассмотрим пример нахождения максимального значения в массивах с
данными различных типов. |
|
|
|
|
|
|
|
|
|
||||
|
|
. . . |
|
|
|
|
|
|
|
|
|
|
|
template <class T> Maxa(T *z, int n); |
|
|
// прототип шаблона |
||||||||||
void main(void) { |
|
|
|
|
|
|
|
|
|
|
|||
|
|
int a[100], n; |
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("\n Input n < 100 : "); |
|
|
|
|
|
|
Р |
||||
|
|
scanf("%d", &n); |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
for( int i=0; i<n; i++) { |
|
|
|
|
|
|
И |
||||
|
|
|
printf("\n a[%d] = ", i+1); |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||||
|
|
} |
scanf("%d", &a[i]); |
|
|
|
|
У |
|
||||
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("\n Max int = %d ", Maxa(a, n)); |
Г |
|
|
||||||||
// Вызывается функция Maxa для типа int |
|
|
|
||||||||||
Б |
|
|
|
||||||||||
|
|
double b[ ] = {0.22, 1.5, 0.88}; |
|
|
|
||||||||
|
|
|
|
|
|
|
|
||||||
|
|
printf("\n Max double = %lf ", Maxa(b,3)); |
|
|
|
|
|||||||
// Вызывается функция Maxa для типа double |
|
|
|
|
|
|
|||||||
} |
|
char Str[ ] = "ABC123abc"; |
а |
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
к |
|
|
|
|
|
|
|
|
|
printf("\n Max char = %c ", Maxa(Str, (int)strlen(Str))); |
|
||||||||||
// Вызывается Maxa для типа char |
|
|
|
|
|
|
|
|
|||||
// Код шаблона |
|
т |
|
|
|
|
|
|
|
|
|||
template <class T> |
|
е |
|
|
|
|
|
|
|
||||
T Maxa(T *z, int n) { |
|
|
|
|
|
|
|
||||||
|
|
int imax = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
и |
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=1; i<n; i++) |
|
|
|
|
|
|
|
|
|||
|
|
|
if(z[i]>z[imax]) imax = i; |
|
|
|
|
|
|
||||
} |
|
return (z[imax]);о |
|
|
|
|
|
|
|
|
|
||
б |
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
||
ри |
|
|
|
|
|
|
|
|
|
|
|
||
Советылпо программированию |
|
|
|
|
|
|
|
||||||
П |
выполнении вариантов заданий |
придерживайтесь следующих |
|||||||||||
Б |
|
|
|
|
|
|
|
|
|
|
|
|
|
ключевых моментов. |
|
|
|
|
|
|
|
|
|
|
|||
1. Шаблоны функций применяются для записи идентичных действий |
|||||||||||||
над данными различных типов. |
|
|
|
|
|
|
|
|
|||||
2. |
Вызов шаблона – |
это создание шаблоном конкретного варианта |
|||||||||||
функции. |
|
|
|
|
|
|
|
|
|
|
|
|
|
3. |
Шаблоны можно перегружать как обычными функциями, так и |
другими шаблонами.
4. Перегрузкой функций называется использование нескольких функций с одним именем и различными типами параметров.
182