Некоммерческое акционерное общество
«Алматинский институт энергетики и связи»
Кафедра компьютерных технологий
ОБЪЕКТНО – ОРИЕНТИРОВАННОЕ
ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ С++
Методические указания к выполнению лабораторных работ
для студентов всех форм обучения специальности 5В0703 – Информационные системы
Алматы 2010
СОСТАВИТЕЛЬ: Т.С. Бимагамбетов. Объектно – ориентированное программирование на языке С++. Методические указания к выполнению лабораторных работ для студентов всех форм обучения специальности 580703 – Информационные системы. – Алматы: АИЭС, 2010. – 15 с.
Представленная работа является продолжением методического указания «Объектно – ориентированное программирование на языке С++», вышедшего в 2006 г. В лабораторных работах излагаются основы стандартной библиотеки шаблонов (Standard Template Library, STL), в которую входят контейнерные классы, алгоритмы и итераторы. С точки зрения программиста, STL содержит набор классов коллекцией для различных применений, а также поддерживает ряд эффективных алгоритмов для работы с этими коллекциями. Благодаря STL программисты могут пользоваться новыми разработками в области структур данных и алгоритмов, не разбираясь в принципах их работы.
Введение
Часть стандартной библиотеки, в которую входят контейнерные классы, алгоритмы и итераторы, называют стандартная библиотека шаблонов (Standard Template Library, STL). Контейнерные классы реализует наиболее распространенные структуры для хранения данных: списки, вектора, множества и др. Алгоритмы снабжает операциями контейнера, итераторы обеспечивает доступ к элементам контейнерных классов. Таким образом, STL содержит унифицированный средства для работы с наборами объектов с применением современных и эффективных алгоритмов.
Все компоненты STL оформлены в виде шаблонов и могут использоваться с произвольными типами элементов, более того, они позволяют включить другие, новые классы объектов и алгоритмов в уже существующие. Это позволяет отказаться от самостоятельного программирования динамических массивов, связанных списков, двоичных деревьев, разных алгоритмов поиска, сортировки и т.п. Для применения коллекции (объектов) нужного типа программист просто определяет соответствующий контейнер, а затем вызывает для него нужные методы и алгоритмы для обработки данных.
Для использования средства STL в программу с помощью директивы #include следует подключить соответствующие стандартные заголовочные файлы.
В каждой лабораторной работе указываются цель и краткая теория изучаемых вопросов, порядок выполняемых работ, а также контрольные вопросы.
8 Лабораторная работа. Контейнеры. Последовательные контейнеры
Цель работы: познакомиться со стандартной библиотеки шаблонов. Работа с контейнерами.
8.1 Теоретические сведение
8.1.1 Стандартная библиотека шаблонов (STL)
В языке С++ входит собственная встроенная библиотека классов-контейнеров. Она называется стандартной библиотекой шаблонов (Standard Template Library, STL). В STL содержится контейнеры, алгоритмы и итераторы.
Контейнеры – это способ организации хранения данных. Для каждого типа контейнера в соответствующем контейнерном классе определены методы для работы с его элементами (объектами), не зависящие от конкретного типа объектов, которые хранятся в контейнере. По этой причине один и тот же вид контейнера можно использовать для хранения и работы с объектами различных типов. Это реализуется с помощью шаблонов классов.
Таблица 8.1.1
Контейнер |
Характеристики |
Плюсы и минусы |
|
|
|
Массив |
Фиксированный размер |
Скоростной случайный доступ по индексу. Медленная вставка (изъятие) данных из середины. Размеры не могут изменены во время работы программ. |
Вектор |
Перераспределяемый, расширяемый массив |
Скоростной случайный доступ по индексу. Скоростная вставка (изъятие) данных из хвоста. Медленная вставка (изъятие) данных из середины. |
Список |
Аналогичен связанному списку |
Скоростная вставка (изъятие) данных из любого места. Быстрый доступ к обоим концам. Медленный случайный доступ. |
Очередь с двусторонним доступом |
Как вектор, но доступ с обоих концов |
Скоростной случайный доступ. Скоростная вставка (изъятие) данных из середины. Медленная вставка (изъятие) данных из хвоста или головы. |
Использование контейнеров позволяет значительно повысить надежность
программ, их переносимость и универсальность. Однако отметим, что снижение быстродействия, в зависимости от реализации компилятора языка С++, может оказаться весьма значительным.
Контейнеры разделяется на последовательные и ассоциативные. В этом работе мы рассмотрим только основные последовательные контейнеры.
Последовательные контейнеры обеспечивают хранения конечного количества однотипных объектов в виде непрерывной последовательности и имеют следующие разновидности: векторы, списки, очереди с двусторонним доступом, стеки, очередь и приоритетная очередь. Первые три являются основными, а остальные вспомогательными. В таблице 8.1 даны характеристики последовательных контейнеров, для сравнения приводится и обычный массив.
Каждый из перечисленных контейнеров обеспечивает свой набор действий над содержащимися в нем объектами. Выбор контейнера зависит от того, что требуется делать с объектами в программе. Например, если требуется часто вставлять и удалять элементы из середины последовательности, то следует использовать список. Если же включение или удаление объектов выполняется чаще конец или начало последовательности, то лучше использовать двустороннюю очередь.
Стандартная библиотека классов определена в следующих заголовочных файлах: <vector>, <list>, <deque>. Эти заголовочных файлы нужно включить в программу. Передача информации о том, какие типы объектов будут храниться, производится в виде передачи параметра в шаблон. Например: vector<int>fvec // создать вектор целых чисел (типа int). А также не нужно специфицировать размеры контейнеров, они сами заботятся о размещении своих данных в память.
Последовательные контейнеры поддерживают разные наборы операций, среди которых имеются совпадающие операции (см. таблицу 8.1.1) с различной эффективностью выполнения.
Таблица 8.1.2
Операция |
Метод |
Вид последовательного контейнера |
||
vector |
deque |
list |
||
|
|
|
||
Вставка в начало |
push_front() |
Отсутствует + + |
||
Удаление из начала |
pop_front(0 |
Отсутствует + + |
||
Вставка в конец |
push_back() |
+ + + |
||
Удаление из конца |
pop_back() |
+ + + |
||
Вставка в произвольное место |
insert() |
(+) (+) + |
Удаление из произвольного места |
erase() |
(+) (+) + |
Произвольный доступ к элементу |
[] или at () |
+ + Отсутствует |
Знак «+» означает, что соответствующая операция реализуется за постоянное время, не зависящее от количества n объектов, помещенных в контейнер. Знак (+) означает, что соответствующая операция реализуется за время, пропорциональное n (линейная сложность). Из таблицы видно, что вектор эффективно реализует произвольный доступ к элементам, добавление в конец и удаление элемента из конца. Двусторонняя очередь (дек) эффективно реализует произвольный доступ к элементам, добавление в оба конца и удаление элементов из обоих концов. Список эффективно реализуется вставку и удаление элементов в произвольное место, но не имеет произвольного доступа к своим элементам.
8.1.2 Векторы
Векторы – это умные массивы. Они занимается автоматическим размещением себя в памяти, расширением и сужением своего размера по мере вставки или удаления данных. Случайный доступ выполняется очень быстро, также довольно быстро осуществляются добавлением новых данных в конец вектора.
Рассмотрим пример.
#include<iostream>
#include<vector>
void main() { vector<int>v // создать вектор типа int
v.push_back(10); v.push_back(11); v.push_back(12); v.push_back(13); // внести данные в конец вектора
v[0]=20; v[3]=23; // заменить новыми значениями
for(int i=0; i<v.size(); i++) cout<<v[i]<<”\t”; // 20 11 12 23
}
В данном примере использована методы push_back(),size() и оператор [].
Тип переменных, которые будут храниться в векторе, используется шаблонный формат тип int. Мы не определяем размер контейнера, поэтому в начале он равен 0. Метод push_back() вставляет значения своего аргумента в конец вектора, начало вектора , в отличие от списков и очередей, не может использоваться для вставки новых элементов. Проталкиваем значения 10, 11, 12, 13 и заменяем 10 на 20 и 13 на 23 с помощью оператора []. Метод size() возвращает текущее число элементов, содержащихся в контейнере.
Другие методы (конструкторы): swap() – обменивает данные одного вектора на другого, при этом порядок следования элементов не изменяется, empty() – содержание вектора, back() – возвращает значение последнего элемента вектора.
8.1.3 Списки
Списки представляет собой дважды связанный список, в котором каждый элемент хранит указатель на соседа слева и справа. Контейнер содержит адрес первого и последнего элементов, поэтому доступ к обоим
концам списка осуществляется быстро.
Рассмотрим пример.
#include<iostream>
#include<list>
void main() { list<int>ilist // создать списки типа int
ilist.push_back(10); ilist.push_back(11); // внести данные в конец
ilist.push_front(12); ilist.push_back(13); // вставка элементов в начало
int size=ilist.size(); // число элементов
for(int i=0; i<v.size; i++) { cout<<ilist.front()<<”\t”; // читать данные из начало
ilist.pop_front(); // извлечение данных из начала
}
} Результат программы 13 12 10 11.
Другие методы (конструкторы): reverse() – перевернуть значения элементов, merge() – объединяет элементы, unique() – удаляет повторяющиеся элементы. Отметим, что некоторые методы используются только списками.
Списки целесообразно использовать при частых операциях вставки и удаления где-либо в середине списка. При этих действиях использовать векторы и очереди нелогично, потому что все элементы над точкой вставки и удаления должны при этом сдвинуты. Что касается списков, изменяются лишь значения нескольких указателей.
8.1.4 Очереди с двусторонним доступом
Очередь с двусторонним доступом (deque) представляет собой нечто похожее и на вектор, и на связанный список. Как вектор поддерживает произвольный доступ, как списки доступ может быть получен к началу и концу очереди. В целом это вектор с двумя концами.
Отметим, что вектор и очереди с двусторонним доступом память резервируется по -разному. Вектор всегда занимает смежные ячейки памяти, очередь может размещаться в нескольких сегментах памяти, поэтому очередь практически всегда будет гарантированно размещена в памяти, но доступ к сегментированным объектам всегда осуществляется с более медленной скоростью.
Рассмотрим пример.
#include<iostream>
#include<deque>
void main() { deque<int>deq // создать очередь типа int
deq.push_back(10); deq.push_back(11); // внести данные в конец
deq.push_front(12); deq.push_front(13); // вставка элементов в начало
deq[2]=33; // изменение произвольного элемента
for(int i=0; i<deq.size(); i++) cout<<deq[i]<<”\t”; // читать данные из начало ilist.pop_front(); // извлечение данных из начала
} Результат программы 13 12 33 11.
8.2 Порядок выполнения лабораторной работы
8.2.1 Напишите законченную программу, в которой с помощью подходящего конструктора создайте вектор v с элементами целого типа, размером 5 и одинаковыми значениями 1. Выведите на экран размер вектора и значения его элементов. С помощью операции «[]» второй элемент вектора увеличьте на 3, а с помощью метода at() четвертый элемент вектора уменьшите на 1. Вновь выведите на экран размер вектора и значения его элементов. С помощью методов front() и back() первый элемент вектора уменьшите на 5, а последний – увеличьте на 2.
8.2.2 Напишите законченную программу, в которой с помощью подходящего конструктора создайте векторы v1, v2 с элементами целого типа и размером 5 и одинаковыми значениями элементов соответственно 1 и -2. Выведите на экран размеры и значения элементов созданных векторов. С помощью метода push_back() добавьте элемент со значением 21 в конец вектора v1 и выведите на экран размер и значения элементов вектора v1. С помощью метода pop_back() удалите последней элемент вектора v1 и выведите на экран размер и значения элементов вектора v1.
8.2.3 Напишите законченную программу, в которой с помощью конструктора умолчания создайте три пустых списка L1, L2, L3 из элементов целого типа. В начало первого списка занесите значения 0, 1, 2, 3, 4, в конец второго списка – значения 10, 11, 12 и выполните присваивание L3=L2. С помощью итераторов выведите на экран размеры и значения элементов созданных списков.
8.2.4 Аналогично 8.2.3 создайте и инициализируйте списки L1, L2, и выведите информацию о них на экран. С помощью метода remove() удалите из списка L2 элемент со значением 12 и выведите на экран информацию о списке L2. С помощью метода merge() выполните слияние в список L1 списков L1, L2 и выведите на экран информацию о списке L1. С помощью методов sort() и reverse() последовательно вначале отсортируйте список L1 по возрастанию, а затем измените порядок следования элементов на противоположный. После каждой операции выведите на экран информацию о списке L1.
8.2.5 Напишите законченную программу, в которой создайте на базе последовательного контейнера deque q1, q2, q3 для хранения целых значений. С помощью методов empty(), front() и pop выведите содержимое адаптера q1 на экран.
8.3 Контрольные вопросы
8.3.1 Что собой представляет контейнеры, зачем они нужны?
8.3.2 Виды контейнеров.
8.3.3 Последовательные контейнеры: векторы, списки и двусторонняя
очередь.
8.3.4 Адаптеры последовательного контейнера.
8.3.5 Ассоциативные контейнеры.
8.3.6 Специальный контейнер: битовое множество.
9 Лабораторная работа. Алгоритмы. Функциональные объекты.
Цель работы: познакомиться со стандартной библиотеки шаблонов. Работа с алгоритмами и функциональным объектами.
9.1 Теоретические сведение
Алгоритмы в STL выполняют различные операции, которые требуется пользователю контейнера. Общее число таких алгоритмов около шестидесяти. Каждый алгоритм реализован в виде шаблонов функции или в виде наборов шаблонов функций. Для настройки алгоритма на конкретные требования пользователя применяются функциональные объекты.
Использование стандартных алгоритмов, как и других средств стандартной библиотеки, избавляет программиста от написания, отладки циклов обработки последовательностей. Это способствует уменьшению ошибок в программе, сокращает время ее разработки и делает ее более читаемой и компактной. Объявления стандартных алгоритмов находятся в заголовочном файле <algorithm>, а стандартных функциональных объектов - файле <functional>. Все алгоритмы можно разделить на пять категорий.
1. Немодифицирующие операции с последовательностями (не меняют значения элементов последовательности или последовательность в целом, извлекают информацию из последовательности или определяют положение элемента в последовательности).
2. Модифицирующие операции с последовательностями (могут изменять последовательность или значения ее элементов).
Таблица 9.1
Алгоритмы |
Значение |
|
|
find() |
Ищет первый элемент в контейнере, значение которого равно указанному. |
count() |
Подсчитывает, сколько элементов в контейнере имеют данное значение. |
sort() |
Сортирует элементов контейнера. |
search() |
Ищет последовательность, заданную одним контейнером, в другом контейнере. |
merge() |
Объединяет элементы двух в третий контейнер |
for_each() |
Выполняет некое действие над каждым элементом в контейнере. |
transform() |
Трансформирует элемент контейнера и помещает в другой. |
3. Алгоритмы сортировки последовательностей.
4. Алгоритмы работы с множествами и пирамидами.
5. Обобщенные численные алгоритмы, объявления которых помещены в заголовочный файл <numeric>.
Отметим, что в качестве параметров алгоритму передаются итераторы, определяющие начало и конец обрабатываемой последовательности. Вид итераторов определяет типы контейнеров, для которых может использоваться данный алгоритмы. Например, алгоритм сортировки sort() требует использования итераторов произвольного доступа. Поэтому он не может работать с контейнером list. Алгоритмы не проверяют выход за пределы последовательности. В таблице 8.1 даны некоторые алгоритмы и ее значения.
Рассмотрим примеры.
Алгоритм find().
#include<iostream>
#include<algorithm>
int arr[]={11,22,33,44,55};
void main() { int*ptr; ptr=find(arr,arr+5,33); // найти первое значения 33
cout<<”Первый объект со значением 33 найден в позиции”<< (ptr-arr);
}
Результат: первый объект со значением 33 найден в позиции 2.
Функциональные объект greater<>().
#include<iostream>
#include<algorithm>
#include<functional>
int arr[]={11,22,33,44,55};
void main() { sort(arr,arr+5, greater<>()); // сортировка значений int
for(int i=0; i<6;i++ )
cout<<arr[i]<<”\t”;
}
Результат 55 44 33 22 11
Обычно алгоритм сортирует по возрастанию, но использование
функциональные объект greater<>() изменяет режим сортировки.
9.2 Порядок выполнения лабораторной работы
При решении задачи применяйте только средства стандартной библиотеки языка С++ (потоковый ввод-вывод, стандартный класс vector и объявления стандартных алгоритмов из файла <algorithm> и <functional>).
9.2.1 Алгоритм search () – ищет целую последовательность значений, заданную одним контейнером, в другом контейнере.
Даны массивы arr1[]={5, 2, 1, 2, 3, 0, 3} и arr2[]={ 1, 2, 3}. Найти с какого элемента встречается последовательность 1, 2, 3, заданную массивом arr2.
9.2.2 Напишите законченную программу, в которой создайте и инициализируйте целочисленный вектор. Выедите значения его элементов на экран. С помощью метода find() выполните поиск в векторе элемента с заданным значением и выведите результаты поиск на экран. С помощью метода count() подсчитайте в векторе количество элементов с заданным значением, выведите результаты поиск на экран.
9.2.3 Напишите законченную программу, в которой создайте и инициализируйте два целочисленных вектора размерами соответственно 4 и 2 элемента. С помощью метода for_search() и функции (функция, вызываемая для каждого элемента вектора) выведите значения его элементов на экран.
9.2.4 Напишите законченную программу, в которой с помощью подходящих конструкторов создайте три вектора вещественного типа v, v1 и v2. Инициализируйте первые два вектора случайными значениями, а вектор v2 так, чтобы он содержал две отсортированных последовательности. Выведите значения элементов этих векторов на экран. С помощью алгоритмов sort() и stable_sort() выполните соответственно обычную и устойчивую сортировку векторов v, v1 и выведите на экран значения элементов этих векторов. С помощью алгоритма binary_search() выполните поиск в векторе v заданного значения и выведите результаты поиска на экран. С помощью алгоритма implace_merge() выполните слияние двух отсортированных последовательностей в векторе v2 и выведите значения элементов этого вектора экран.
9.3 Контрольные вопросы
9.3.1 В каких файлах объявления стандартных алгоритмов и функциональных объектов?
9.3.2 Перечислите основные категории алгоритмов..
9.3.3 Как реализуется алгоритмы?
9.3.4 Какие алгоритмы работает с множествами и пирамидами?
9.3.5 Модифицирующие и немодифицирующие операции с последовательностями.
9.3.6 Специальный контейнер: битовое множество.
10 Лабораторная работа. Итераторы. Потоковые итераторы.
Цель работы: познакомиться со стандартной библиотеки шаблонов. Работа с итераторами.
10.1 Теоретические сведение
10.1.1 Итераторы
Итераторы – это сущности, напоминающие указатели. В STL итераторы представляет собой объект класса iterator. Они используются для работы контейнерами классами, потоками и буферами потоков. При работе с итераторами используются понятия «текущий указываемой элемент» и указатель на следующий элемент. Доступ к текущему элементу последовательности выполняется, как и при использовании указателей, с помощью операции «*» и «->». Переход к следующему элементу выполняется с помощью операции инкремента «++»(«--»). Для всех итераторов определены также операции присваивания, проверки на равенство и неравенство. Тем не менее, разные итераторы обладают разными свойствами. Для разных типов итераторов используются свои итераторы. Всего существует три основных класса итераторов: прямые, двунаправленные и со случайным доступом. Прямой итератор может проходить по контейнеру только в прямом правлении. Такой оператор не может двигаться в обратном направлении и не может быть поставлен в произвольном месте контейнера. Двунаправленный итератор, соответственно, может передвигаться в обеих направлениях, а итератор со случайным доступом может двигаться в обеих направлениях и перескакивать на произвольное место контейнера. Есть два специализированных вида итераторов. Это входной итератор, который может «указывать» на устройство ввода (cin или просто входной файл), также выходной итератор – вывода ( cout). В таблице 10.1 показаны характеристики различных типов итераторов
Таблица 10.1
Типы итераторов |
Запись/ Чтение |
Хранение значения |
Направление |
Доступ |
|
|
|
|
|
Со случайным доступом |
Запись и чтение |
Возможно |
Оба направления |
Случайный |
Двунаправленный |
Запись и чтение |
Возможно |
Оба направления |
Линейный |
Прямой |
Запись и чтение |
Возможно |
Только прямое |
Линейный |
Выходной |
Запись |
Невозможно |
Только прямое |
Линейный |
Входной |
Чтение |
Невозможно |
Только прямое |
Линейный |
10.1.2 Адаптеры итераторов
Адаптеры итераторов – это специализированные итераторы, позволяющие выполнить алгоритмы, которые поддерживают:
1) перебор элементов в обратном порядке (обратные итераторы);
2) режим вставки (итераторы вставки);
3) работы с потоками данных (потоковые итераторы).
Обратные итераторы обозначается reverse_iterator, при ее использовании применяются методы rbegin() и rend(). Приведем пример.
#include<iostream>
#include<list>
void main() {int arr[]={2,4,6,8,10};
list<int>thelist;
for(int i=0; i<5; i++)
thelist.hush_back(arr[i]) // перенести содержимое массива в список
list<int>:: reverse_iterator revit; // обратный итератор
revit = thelist. rbegin(); // реверсная итерация
while(revit!=thelist. rend()) // по списку с выводом на экран
cout<< *revit++<<”\t”;
}
Результат 10 8 6 4 2.
Прохождения контейнера начинается с конца, при этом вызывается метод rbegin().
Итераторы вставки предназначены для добавления новых элементов в начало, конец и произвольное место контейнера. Они front_inserter, back_inserter, inserter.
Потоковые итераторы обеспечивает при использовании стандартных алгоритмов возможность работы с потоками ввода-вывода. Существует два потоковых итератора: ostream_iterator и istream_iterator. Приведем пример.
#include<iostream>
#include<list>
#include<algoritm>
void main() {int arr[]={2,4,6,8,10}; list<int>thelist;
for(int i=0; i<5; i++)
ostream_iterator<int>ositer(cout, “, ”);
copy(thelist.begin(), thelist.end(),ositer);
}
Результат: 2, 4, 6, 8, 10. Итератор ostream_iterator для чтения типа int. Двумя параметрами конструктора является поток, в которой будут записываться значения и строка, которая будет выводиться вслед за каждым из них. Значением потока является имя файла или cout.
Итератор istream_iterator может использоваться в качестве параметра любого алгоритма, работающего с входным потоком.
10.1.3 Итераторы как интеллектуальные указатели
Как нам известно, для получения данных массива можно использовать указатели float*ptr= start_address; for(int i=0;i<size;i++) cout<<*ptr++;
Однако отметим, что использовать указатели с более сложными контейнерами довольно затруднительно. Например , если элементы контейнера хранятся непоследовательно (списки) в памяти, а сегментировано, то методы доступа к ним значительно усложняется. Одним из решений проблем такого рода является создание класса «интеллектуальных указателей». Объекта такого класса обычно является оболочкой для методов, работающих с обычными указателями. Операторы ++ и * перегружается и поэтому в курсе того, как нужно работать с элементами контейнера, даже если они расположены не последовательно или изменяют свое местоположения (вставим или удалим из середины контейнера). Перепишем предыдущую программу.
class sum {private: float*ptr ; public: float operator*() {}
float operator++() {}};
void main() {sum sptr=start_address; }
for(int i=0;i<size;i++) cout<<*ptr++;}
10.2 Порядок выполнения лабораторной работы
10.2.1 Даны массив arr[]={5, 2, 1, 2, 3}. Заполните список элементами массива, создайте итератор для целочисленного списка, выведите данного списка на экран.
10.2.2 Даны массивы arr1[]={5, 2, 1, 2, 3, 0, 3} и arr2[]={2, 4, 6}. Создайте два (d1 и d2) двусторонним доступ с типам int. Перенесите данные из массивов в очереди с двусторонним доступом. Копируйте d1 в конец d2, используя итератора back_inserter, и выведите данные d2.
10.2.3 Создайте неинициализированный список типа float, используя итератор istream_iterator, введите значения элементов списка, где cin - аргумент конструктора и укажите конец потока. Копируйте из cin в список. Выведите значения списка на экран.
10.2.4 В 8.2.3 примере вместо потока cin используйте входной файл (см.лаб.№8), из которого берутся данные для программы.
10.3 Контрольные вопросы
10.3.1 Для чего предназначены итераторы?
10.3.2 Одинакова ли семантика итератора и указателя?
10.3.3 Какие операции допустимы для любого типа итератора?
10.3.4 Перечислите категории итераторов, разрешенные для каждой категории операции и области их применения.
10.3.5 В каких случаях итератор может быть недействительным?
10.3.6 Перечислите итераторные адаптеры и укажите их назначение.
Список литературы
1. Подбельский В.В., Фомин С.С. Программирование на языке С++. Учебное пособие. –М.: Финансы и статистика, 2000.
2. Фридман А.Л. Язык программирования С++. Курс лекций. –М.: Интернет – Университет информационных технологий, 2003.
3. Лафоре Р. Объектно- ориентированное программирование в С++. Санкт- Петербург, 2003.
4. Шиманович Е.Л. С/С++ в примерах и задачах. -Мн.: Новое знание, 2004.
5. Давыдов В.Г. Технология программирования С++. Санкт- Петербург, 2005.
6. Бимагамбетов Т.С. Объектно- ориентированное программирование на языке С++. Методическое указание к выполнению лабораторных работ. Алматы. -АИЭС, 2006.
7. Бимагамбетов Т.С. Программирование на языке Си++. Учебное пособие. Алматы. -АИЭС, 2007.
Содержание
Введение 3
Лабораторная работа №8. Контейнеры. Последовательные контейнеры. 4
Лабораторная работа №9. Алгоритмы. Функциональные объекты. 9
Лабораторная работа №10. Итераторы. Потоковые итераторы 12
Список литературы 15