Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2vcTnguyvU

.pdf
Скачиваний:
6
Добавлен:
15.04.2023
Размер:
955.27 Кб
Скачать

По умолчанию сортировка ассоциативных контейнеров производится с помощью операции “меньше”. Однако можно указать и другой оператор сравнения (объекты-функции).

1.Используя обобщенный алгоритм generate, заполнить значениями вектор целых чисел. Причем, при заполнении сгенерированное значение получить с помощью определенной функции, которая выбирает только простые числа. Затем, используя алгоритм random_shuffle расположить элементы в случайном порядке. Затем, заполнить другой вектор целых чисел, используя алгоритм random_shuffle случайными числами. После этого, используя алгоритм transform заполнить третий вектор значениями, полученными сложением элемента первого вектора с удвоенным значением 2-вектора. Удвоение значения элемента второго вектора производить, если этот элемент нечетный. Все результаты выводить на экран. Использовать STL.

2.Применить алгоритмы accumulate и inner_product для нахождения уравнения линии регрессии у = а + bx для данных находящихся в файле в виде (x, y)

20.5118.1

20.6118.25

20.65 118.2

20.75 118.4

20.8118.4

20.85118.5

20.9118. 45

21.0118.5

Используйте метод наименьших квадратов. Алгоритм accumulate вычисляет

значение ∑xI и значение ∑y I ;

 

Алгоритм inner_product вычисляет ∑x2

I и ∑xI * y I . Результаты расчетов

поместить в третий столбец, результат на экран, вывод данных представляет уравнение регрессии и три столбца данных: два столбца входных данных и третий столбец - результат расчета.

a*n+b*∑xI =∑y I

a*∑xI +b*∑x2 I = ∑xI * y I .

3. Создайте приложение, использующее контейнер map. Специализируйте этот контейнер так: ключом является тип string -фамилия , а значением – вектор с названиями стран, которые посетил данный гражданин. Поместите в отображение(map) как минимум пять элементов. Реализуйте возможность делать запрос по фамилии, добавлять новые страны, распечатывать содержимое.

120

4. Перепишите программу текстового поиска с использованием multimap для хранения позиций слов.

Контрольные вопросы

1.Объясните разницу между размером и емкостью контейнера. Почему понятие емкости необходимо для контейнера, содержащего элементы в непрерывной области памяти, и не нужно для списка?

2.Почему большие сложные объекты удобнее хранить в контейнере в виде указателей на них, а для коллекции целых чисел применение указателей снижает эффективность? Докажите программным путем.

3.Какие ошибки допущены при использовании итераторов:

const vector<int> ivec; vector<string> svec; list<int> ilist;

(a)vector<int>::iterator it=ivec.begin();

(b)list<int>::iterator it=ilist.begin()+2;

(c)vector<string>::iterator it=&svec[0];

(d)for(vector<string>::iterator it=svec.begin();it!=0; ++it)

4.Приведите по два примера когда нужно использовать шаблонные классы set и map.

5.Напишите определение объектов map и set.

Задание для самостоятельной работы

1. Разработайте тестирующую программу, которая выполняет простую проверку наличия функций-членов и типов и их правильного поведения для одной специализации шаблонного класса map

#include <assert.h> #include <iostream> #include <functional> #include <map> using namespace std; void test_map()

{

typedef allocator<int> Myal; typedef less<char> Mypred; typedef pair<const char, int> Myval;

typedef map<char, int, Mypred, Myal> Mycont; Myval x, xarr[3], xarr2[3];

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

{new (&xarr[i]) Myval('a'+i, 1+i); 121

new (&xarr2[i]) Myval('d'+i, 4+i);

}

Mycont::key_type *p_key=(char *)0; Mycont::mapped_type *p_mapped=(int *)0; Mycont::key_compare *p_kcomp=(Mypred *)0; Mycont::allocator_type *p_alloc=(Myal *)0; Mycont::value_type *p_val=(Myval *)0; Mycont::value_compare *p_vcomp=0; Mycont::pointer p_ptr=(Myval *)0; Mycont::const_pointer p_cptr=(const Myval *)0; Mycont::reference p_ref=x; Mycont::const_reference p_cref=(const Myval&)x; Mycont::size_type *p_size=(size_t *)0; Mycont::difference_type *p_diff=(ptrdiff_t *)0; Mycont v0;

Myal al=v0.get_allocator(); Mypred pred;

Mycont v0a(pred), v0b(pred, al); assert(v0.empty() && v0.size()==0); assert(v0a.size()==0 && v0a.get_allocator()==al); assert(v0b.size()==0 && v0b.get_allocator()==al); Mycont v1(xarr, xarr+3);

assert(v1.size()==3 && (*v1.begin()).first=='a'); Mycont v2(xarr, xarr+3, pred); assert(v2.size()==3 && (*v2.begin()).first=='a'); Mycont v3(xarr, xarr+3, pred, al); assert(v3.size()==3 && (*v3.begin()).first=='a'); const Mycont v4(xarr, xarr+3); assert(v4.size()==3 && (*v4.begin()).first=='a'); v0=v4;

assert(v0.size()==3 && (*v0.begin()).first=='a'); assert(v0.size() <=v0.max_size()); Mycont::iterator p_it=v1.begin(); Mycont::const_iterator p_cit=v4.begin(); Mycont::reverse_iterator p_rit=v1.rbegin(); Mycont::const_reverse_iterator p_crit=v4.rbegin(); assert((*p_it).first=='a' && (*p_it).second==1

&& (*--(p_it=v1.end())).first=='c'); assert((*p_cit).first=='a' && (*--(p_cit=v4.end())).first=='c'); assert((*p_rit).first=='c' && (*p_rit).second==3

122

&& (*--(p_rit=v1.rend())).first=='a'); assert((*p_crit).first=='c' && (*--(p_crit=v4.rend())).first=='a'); v0.clear();

pair<Mycont::iterator, bool> pib=v0.insert(Myval('d', 4)); assert((* pib.first).first=='d' && pib.second); assert((*--v0.end()).first=='d'); pib=v0.insert(Myval('d',5));

assert((*pib.first).first=='d' && (*pib.first).second==4 && !pib.second); assert((*v0.insert(v0.begin(), Myval('e',5))).first=='e');

v0.insert(xarr, xarr+3);

assert(v0.size()==5 && (*v0.begin()).first=='a'); v0.insert(xarr2, xarr2+3);

assert(v0.size()==6 && (*--v0.end()).first=='f'); assert(v0['c']==3);

v0.erase(v0.begin()); assert((*v0.begin()).first=='b' && v0.size()==5); v0.erase (v0.begin(), ++v0.begin()) ;

assert( v0.size()==4);

assert(v0.erase ('x')==0 && v0.erase('e')==1); v0.clear();

assert(v0.empty());

v0.swap(v1);

assert(!v0.empty() && !v1.empty()); swap(v0,v1);

assert(v1==v1 && v0<v1);

assert(v0.key_comp()('a','c') && !v0.key_comp()('a','a')); assert(v0.value_comp() (Myval('a',0), Myval('e', 1))

&& !v0.value_comp() (Myval('a', 0), Myval('a',1))); assert((*v4.find('b')).first=='b');

assert(v4.count('x')==0 && v4.count('b')==1); assert((*v4.lower_bound('a')).first=='a'); assert((*v4.upper_bound('a')).first=='b'); pair<Mycont::const_iterator, Mycont::const_iterator> pcc=v4.equal_range('a');

assert((*pcc.first).first=='a' && (*pcc.second).first=='b');

}

#pragma argsused int main()

{

test_map();

123

cout<<"success testing";

cout << "Press key 1 !! Good by!!"<< endl; while (m!='1')

cin>>m; return 0;

}

Тестовое задание

Шаблоны классов

1.Выберите наиболее подходящий из указанных шаблонов:

template

<class T1, class T2, int J> class A { };

//(1)

template

<class T, int J> class A<T, T*, J> { };

//(2)

template

<class T1, class T2, int J> class A<T1*, T2, J> { };//(3)

template <class T> class A<int, T*, 5> {};

//(4)

template

<class T1, Class T2, int J> class A<T1, T2*, J> { }; //(5)

(т.е. укажите какой шаблон используется в следующих вызовах, укажите неоднозначность, если она имеется))

A<int, int, 1> a1; A<int, int*, 1> a2; A<int, char*, 5> a3; A<int, char*, 1> a4; A < int*, int*, 2> a5;

2. В следующей функции используются необязательные временные объекты как минимум в трех местах. Сколько таких мест найдете вы? string FindAddr( list<Employee> emps, string name) {

for(list<Employee>::iterator

i=emps.begin(); i!=emps.end(); i++) {

if(*i==name)

{

return i ->addr; }

} return “”; }

 

 

Как должен быть сконструирован класс Employee, чтобы этот код работал? Доработайте программу. Примените соответствующую функцию из стандартной библиотеки. Почему не рекомендуется использовать временные объекты, а что использовать тогда ?

3. Имеется шаблон класса Stack: template <class T> class Stack {

public:

 

 

Stack();

~Stack():

Stack & operator=(const Stack&);

size_t

Count() const;

void Push(const T & ); T Pop();

private:

 

T*

v_;

//указатель на область памяти, достаточную для

 

 

124

size_t vsize_; // размещения vsize_ объектов типа T

size_t vused_; //количество реально используемых объектов };

При реализации конструктора копирования и оператора копирующего присваивания для управления распределением памяти была разработана вспомогательная функция:

template <class T> T* NewCopy ( const T* src, size_t srcsize, size_t destsize )

{assert (destsize>=srcsize); T* dest= new T[destsize]; try {

copy( src, src+srcsize, dest );

}catch (...)

{delete [] dest;

throw; } return dest; }

Приведите реализацию конструкторов, оператора копирования с помощью этой вспомогательной функции.

Наследование

1. Какие ошибки (если таковые есть) имеются в приведенном ниже коде? template <typename T> class X_base {

public:

typedef T instantiated_type; }; template<typename A, typename B> class X: public X_base<B> { public:

bool operator() const instantiated_type & i) const { return i!= instantiated_type(); }

// прочий код };

2. Приведенный шаблон предоставляет функции управления списком, включая возможность работы с элементами списка в определенных позициях.

template <class T> class MyList { public:

bool Insert (const T&, size_t index ); T Access (size_t index ) const; size_t Size() const;

private: T* buf;

125

size_t bufsize_; };

Рассмотрите следующий код, демонстрирующий два способа написания класса MySet с использованием MyList.

(a) template <class T> class MySet1: private MyList<T> { public:

bool Add ( const T & );

//вызывает Insert()

T Get (size_t index ) const;

//вызывает Access()

using MyList<T>::Size;

 

// ....

 

};

 

(b) template <class T> class MySet2 {

public:

 

bool Add (const T & );

//вызывает impl_.insert()

T Get (size_t index const );

 

// вызывает impl_.Access()

 

size_t Size () const;

//вызывает impl_.Size ()

// ...

 

private:

 

MyList<T> impl_;

 

};

 

Ответьте на следующие вопросы:

a.Имеется ли различие между MySet1 и MySet2?

b.В чем заключается различие между закрытым наследованием и включением? Приведите по возможности более полный список причин, по которым могло бы потребоваться использовать наследование, а не включение.

c.Приведите по возможности более полный список причин, по которым могло бы потребоваться открытое наследование.

d.Создайте программу с использованием классов MySet1 и MySet2.

3. Предположим, что класс Derv является частным производным класса Base. Был определен объект класса Derv, расположенный в функции main(). Через него можно получить доступ к:

членам класса Derv, объявленным как public; членам класса Derv, объявленным как protected; членам класса Derv, объявленным как private; членам класса Base, объявленным как public; членам класса Base, объявленным как protected; членам класса Base, объявленным как private.

126

4. Предположим, что класс Derv является производным класса Base. Оба класса содержат метод func() без аргументов. Напишите выражение, входящее в метод класса Derv, которое вызывает метод func() базового класса.

Абстрактные классы, динамическая информация о типе

1. Рассмотрите следующий пример.

class A {

public:

 

 

virtual

~A();

 

 

 

string Name();

 

 

 

private:

 

 

 

 

virtual string DoName();

};

 

class B1 : virtual public A

{

 

string DoName();

};

 

 

class B2 : virtual public A

 

 

{

string DoName(); };

 

A::~A() { }

 

 

 

string A::Name()

{ return DoName(); }

string A::DoName() { return “A”;

}

string B1::DoName() { return “B1”; }

string

B2::DoName () { return “B2”; }

class D : public B1, public

B2 {

 

string

DoName()

{ return “D”; }

};

Покажите по возможности наилучший способ избежать множественное

наследование, написав эквивалентный

(или максимально приближенный к

оригиналу)

class D без использования

множественного наследования. Каким

образом можно достичь той же функциональности и применимости класса D при минимальном изменении синтаксиса вызывающего кода?

Классы и динамическая память

1.Какой вариант конструктора по умолчанию предпочтительней:

(a)template <class T> Stack<T>::Stack() : v_(0), vsize_(10), vused_(0)

{v_=new T[vsize_]; //начальное распределение памяти

 

 

}

(b)

template <class T> Stack<t>::Stack()

 

: v_(new T[10]), vsize_(10), vused_(0) { }

2.

Рассмотрите следующий код. Найдите ошибку в этом фрагменте,

 

связанную с управлением памятью.

 

class B

 

{

public:

 

virtual ~B();

 

 

127

void operator delete (void *, size_t ) throw (); void operator delete [] (void *, size_t ) throw (); void f (void*, size_t ) throw (); };

class D: public B {

void operator delete (void *) throw (); void operator delete [](void * ) throw (); };

Почему операторы delete в классе B имеют вторые параметры, а в классе D - нет?

3.Приведенный далее фрагмент кода является продолжением предыдущего. Какой из операторов delete() вызывается в каждом из выражений? Почему, и с какими параметрами?

D* pd1= new D; delete pd1;

B* pb1 = new D; delete pb1;

D* pd2 = new D[10]; delete [] pd2;

B* pb2 = new D[10]; delete [] pb2;

4.Корректны ли два следующих присваивания?

 

B b;

 

 

 

 

typedef void (B::*PMF)(void* , size_t );

 

PMF p1 = &B::f;

 

 

 

PMF p2=& B::operator delete;

 

5.

Имеются

ли в следующем коде

ошибки, связанные с управлением

памятью?

 

 

 

 

class X

{

 

 

 

public:

 

 

 

 

void * operator new (size_t s, int ) throw (bad_alloc)

 

{ return ::operator new(s);

} };

 

 

 

 

Исключения

1.

Рассмотрите следующий класс:

 

 

class C : private A {

B b_;

};

Как в конструкторе класса С можно перехватить исключение , сгенерированное в конструкторе базового подъекта (такого, как А) или объекта-члена (такого, как b_) ?

2. Какие из приведенных инструкций throw ошибочны? Почему? Для правильных инструкций укажите тип возбужденного исключения:

(a) class exceptionType { }; throw exceptionType();

128

(b)int excpObj; throw excpObj;

(c)enum mathErr ( overflow, underflow, zeroDivide }; throw mathErr zeroDivide();

(d)int *pi=excpObj;

throw pi;

Потоковый ввод-вывод

1.Какие классы используются в потоках ввода-вывода?

2.Что из себя представляют манипуляторы? Приведите примеры использования.

3.Определите для вывода манипулятор based с двумя параметрами: система счисления и целое значение, и печатайте целое в представлении, определяемом системой счисления. Например, based(2,9) напечатает 1001.

4.Разработать несколько функций для запроса и чтения данных разных типов. Предложения: целое, вещественное число, имя файла, почтовый адрес, дата, личная информация, и т.п. Попытайтесь сделать их устойчивыми к ошибкам.

Стандартная библиотека шаблонов

1.В приведенном коде имеется, как минимум, четыре ошибки, связанные с использованием итераторов. Укажите найденные ошибки.

int main() { vector<Date> vec;

copy(istream_iterator<Date>(cin), istream_iterator<Date(), back_inserter(vec) );

vector<date.::iterator first =find(vec.begin (), vec.end(), “01/01/10”); vector<Date>::iterator last =find(vec.begin(), vec.end(), “12/31/10”); *last=”12/30/10”;

copy(first, last, ostream_iterator<Date>(cout, “\n”) ); vec.insert (--vec.end(), TodayDate() );

copy(first, last, ostream_iterator<Date>cout, “\n”) ); }

2.Какие ошибки допущены при использовании итераторов:

const vector<int> ivec; vector<string> svec; list<int> ilist;

(a)vector<int>::iterator it=ivec.begin();

(b)list<int>::iterator it=ilist.begin()+2;

(c)vector<string>::iterator it=&svec[0];

(d)for(vector<string>::iterator it=svec.begin();it!=0; ++it)

129

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]