LAB_9 Wprowadzenie w STL
Na przykładzie klasy kontenera vector rozważymy kilka elementarnych zadań.
1. Wprowadzimy klasę danych
współrzędne punktu na płaszczyźnie
class coord
{
double *cr; //wpółrzędne punktu na płaszczyźnie cr[0] = x; cr[1] = y
public:
coord() : cr(NULL) {}
coord(double x, double y);
~coord() { if(cr) delete [] cr;}
void set(double x, double y);
double * get() { return cr;}
private:
void alloc();
};
void coord::alloc()
{
try
{
cr = new double [2];
memset((void *)cr, 0, 2*sizeof(double));
}
catch(bad_alloc xx)
{
}
}
coord::coord(double x, double y)
{
alloc();
cr[0] = x;
cr[1] = y;
}
void coord::set(double x, double y)
{
cr[0] = x;
cr[1] = y;
}
2. Stworzymy tablicę dynamiczną vector
int _tmain(int argc, _TCHAR* argv[])
{
//numb - ilość punktów
size_t numb = 20, ind, it;
const double PI = 3.14159236;
double x, y, ro, fi, dfi = 2.0*PI/numb;
coord tmp(0, 0); //obiekt pomocniczy
vector<coord> vec; //tablica dynamiczna dla typu danych coord
vector<coord>::iterator It_end; //wprowadzamy iterator do klasy kontenera
//vector , typ danych - coord
//przygotowanie tablicy obiektów coord
for(it=0; it<numb; it++)
{
//promień zmieniamy w sposób losowy
ind = rand()%5;
fi = dfi*it;
ro = static_cast<double>(ind+1);
x = ro*cos(fi);
y = ro*sin(fi);
//tworzymy obiekt typu coord ze współrzędnymi x, y
tmp.set(x, y);
//umieszczamy w koniec tablicy vec
vec.push_back(tmp);
}
//wyświetlamy zbiór punktów na monitorze za pomocą funkcji-szablonu disp
disp(vec, "initial vec");
//sortowanie tablicy obiektow coord
//w porządku malejacym (dlugosc wektora)
// ob.ro[i] > ob.ro[i+1]
//algorytm sort, funkcje-predykat SortDescending
sort(vec.begin(), vec.end(), SortDescending);
disp(vec, "sorted in descending order vec");
//usunięcie wektorów z taką samą długością
//algorytm unique, funkcja-predykat CoordCompare)
It_end = unique(vec.begin(), vec.end(), CoordCompare);
//obcinamy vec po unique
vec.erase(It_end, vec.end());
disp(vec, "after unique vec");
vec.clear();
system("pause");
return 0;
}
3. Funkcja szablon disp()
template<class T>
void disp(vector<T> &v, char *str)
{
vector<T>::iterator It;
cout << str << endl;
//przeglądamy tablicę dynamiczną za pomocą iteratorów
for(It=v.begin(); It!=v.end(); It++)
{
cout << *(It); //pobieramy wartość obiektu przez iterator
}
cout << "-------------------\n";
}
4. Dla wykonania sformułowanego powyżej zadania trzeba przygotować klasę danych:
Dla poprawnego działania algorytmów sort, unique trzeba wprowadzić funkcje-predykat SortDescending i funkcje porównawczą CoordCompare.
bool SortDescending(coord elem1, coord elem2)
//funkcja-predykat SortDescending jest predykatem binarnym:
//zwraca bool i ma dwa argumenty
//dla sortowania w porządku malejacym według dlugości wektora funkcja //SortDescending powinna zwrócić true, jeśli długość ro1 elementu elem1 jest //większy od długości ro2 elementu elem2, gdzie elem1 i elem2 to dwa kolejne //elementy tablicy dynamicznej, reprezentowanej klasą-kontenerem vector
{
double ro1 = elem1, ro2 = elem2;
//Wyrażenie double ro1 = elem1 ma sens tylko wtedy, kiedy wprowadzimy funkcje konwertującą operator double() { return (liczymy dlugość wektora))
return ro1 > ro2;
}
Funkcja konwertująca w klasie danych:
dołożyć prototyp tej funkcji w deklaracji klasy (public)
operator double();
Definicja:
coord::operator double ()
{
double ro = cr[0]*cr[0]+cr[1]*cr[1];
return sqrt(ro);
}
Porównywanie == typów danych double może powodować problemy. Ten kod jest niepoprawny.
bool CoordCompare(coord elem1, coord elem2)
{
double ro1 = elem1, ro2 = elem2;
return(ro1 == ro2);
}
W skutek błędów zaokrąglenia pewne elementy tablicy mogą być potraktowane jako != .
Na przykład: 2.0000000000000 i 2. 0000000000001 .
Oto jest poprawny wariant kodu:
bool CoordCompare(coord elem1, coord elem2)
{
double ro1 = elem1, ro2 = elem2;
double dif = fabs(ro1-ro2);
if(dif < 1.0e-8)
return true;
else
return false;
}
Spróbuj użyć pierwszy wariant kodu i przeanalizuj wyniki. Później zmień na poprawny wariant kodu.
Funkcja-predykat SortDescending i funkcja porównawcza CoordCompare nie są metodami klasy coord.
Żeby kompilator był w stanie rozpoznać prototypy kontenera vector i algorytmów sort, unique,
trzeba dołożyć nagłówki
#include<vector>
#include<algorithm>
Dla rozpoznania prototypów sqrt, fabs, sin, cos - dołożyć nagłówek
#include<cmath>