Linguagem de Programação I -...
Transcript of Linguagem de Programação I -...
Templates
Sobrecarga de funções ◦ Mesmo nome
◦ Mesma semântica
◦ Diferentes tipos de dados
As vezes a mesma sintaxe...
2
int soma(int x, int y) {
return x + y;
}
Ponto soma(Ponto x, Ponto y) {
return x + y; //supondo operador + sobrecarregado
}
Templates em C++
Templates = modelos, padrões
Genericidade: a partir do momento em que o tipo parâmetro fornece tudo o que é usado no símbolo template, é possível passar qualquer tipo.
Simplicidade: só é possível codificar um símbolo, independentemente dos tipos passados em parâmetro, o que torna o código mais fácil de manter.
3
Templates em C++
Templates para funções
T representa um tipo de dados qualquer ◦ Tipos primitivos (int, float, char ...)
◦ Classes definidas pelo usuário
4
template <class T>
T fun(T parametros, ...)
{
//faça coisas usando um tipo T
}
template <class T>
T soma(T x, T y) {
return x + y;
}
Templates C++ 5
int sumVector(int *array, int n)
{
int sum(0);
// mais eficiente que: int sum=0;
for (int idx = 0; idx < n; ++idx)
sum += array[idx];
return (sum);
} template <typename T>
T sumVector(T *array, int n)
{
T sum=0;
for (int idx = 0; idx < n; ++idx)
sum += array[idx];
return (sum);
}
Templates em C++
Tipos a serem usados podem ser restringidos ◦ Otimiza a compilação (são geradas “versões” do código que usa o template para os tipos definidos)
6
template <typename T> // um tipo genérico
T sumVector(T *array, int n)
{ ... }
template int sumVector<int>(int *, int);
template double sumVector<double>(double *, int);
int main() { ... }
Templates em C++ - Classes 7
template <class T>
class Camaleao {
public:
Camaleao();
Camaleao(T novaVariavel);
~Camaleao();
T getVariavel();
void setVariavel(T novaVariavel);
private:
T variavel;
};
Templates em C++ - Classes 8
template <typename T>
class Vector
{
int d_size; T *d_v;
public:
Vector(int size):d_size(size){d_v=new T[d_size];}
~Vector(){delete d_v;}
T operator[](int index) const{return d_v[index];}
int size() const { return d_size;}
T &operator[](int index){ return d_v[index];}
void enlarge(int newsize)
{
T *aux=new T[newsize];
for(int i=0;i<d_size;i++) aux[i]=d_v[i];
delete []d_v; d_v=aux; d_size=newsize;
}
friend ostream &operator<<(ostream &o, Vector<T> const &t)
{
for(int i=0;i<t.d_size;i++) o << t.d_v[i] << " ";
return o << "\n";
}
};
Templates em C++ - Herança 9
template<typename T>
class Base
{
T d_t;
public:
Base(T const &t):d_t(t);
};
template<typename T>
class Derived: public Base<T>
{
public:
Derived(T const &t) : Base(t){}
};
class Ordinary: public Base<int> //
{
public:
Ordinary(int x) : Base(x) {}
};
Exceções
Tratamento de erros hierarquizado Erros que:
◦ Comprometem dados do usuário.
◦ Impedem a boa execução do programa.
◦ Erros que devem ser evitados e avisados aos usuários
Palavras chave try, throw e catch. try
◦ Inicia um bloco passível de lançar exceção
throw ◦ Arremessa uma exceção
catch ◦ Captura uma exceção
10
Exceções em C++ 11
void fun() { throw 1337; }
int main() {
try {
fun();
}
catch (...){
//faça algo com a exceção
}
}
Exceções em C++ 12
class DivideByZeroException {
public:
string message;
DivideByZeroException() {
message = “DIVISION BY ZERO”;
}
}
int divide(int a, int b)
{
if (b==0)
throw DivideByZeroException();
return a/b;
}
Exceções em C++ 13
int main()
{
try {
divide(3,0);
}
catch (DivideByZeroException e) {
cout << “Erro: ” << e.message << endl;
}
}
Exceções em C++
catch(...) ◦ Qualquer tipo
◦ catch(X var)
Objetos da classe X e de suas derivadas
14
STL
STL é uma biblioteca padrão com as estruturas de dados mais usadas ◦ Criada para evitar a implementação e teste das mesmas estruturas de dados
◦ Economiza tempo e evita retrabalho
É a biblioteca padrão de C++ Padronizada pelo ANSI em 1997 Por que templates?
◦ Poupam da tarefa de reimplementar o código para cada novo tipo de dado da sua aplicação.
16
STL
Quando usados apropriadamente, templates são bastante eficazes. ◦ Porém, mensagens de erro STL costumam ser pouco elucidativas.
Uma boa fonte sobre a STL é o guia de programação da SGI
17
STL
A STL oferece: ◦ Containers (recipientes). ◦ Iterators (iteradores). ◦ Algorithms (algoritmos).
Recipientes servem para armazenar dados e podem ser classificados como: ◦ Seqüências de dados ◦ Recipientes associativos para pares de objetos
(chave, dado). ◦ Adaptadores que provêem um subconjunto da
funcionalidade de um recipiente. Pilhas, filas, filas de prioridade.
18
Organização da STL
Containers
<vector> Array unidimensional do tipo T
<list> Lista duplamente ligada do tipo T
<deque> Lista ligada ‘double-ended’ do tipo T
<queue> Lista ligada do tipo T
<stack> Pilha do tipo T
<map> Array associativo do tipo T (red-black tree)
<set> Conjunto do tipo T
<bitset> Array de booleanos
Organização da STL
General Utilities
<utility> Operadores
<funcional> Funções
<memory> Funções para manipulação de memória
<ctime> Funções de C para manipulação de data e hora
Iterators
<iterator> Definição e suporte para Iterators
Algorithms
<algorithm> Algoritmos gerais
<cstdlib> bsearch() e qsort()
Organização da STL
Diagnostics
<exception> Definição da classe exception
<stdexception> Exceções da biblioteca padrão
<cassert> Diagnóstico de Erros
<cerrno> Tratamento de erro com as funções de C
Organização da STL
Strings
<string> string do tipo T
<cctype> Classificação de caracteres
<cwctype> Classificação de wide-caracters
<cstring> Funções de C para manipulação de strings
<cwchar> Funções de C para classificação de wide-caracters
<cstdlib> Mais funções de C para manipulação de strings
Organização da STL
Input/Output
<iosfwd> Declarações forward de facilidades de E/S.
<iostream> Objetos e operações padrões de E/S.
<ios> Classes bases de E/S.
<streambuf> Stream buffers.
<istream> Templates de stream de entrada.
<ostream> Templates de stream de saída.
<iomanip> Manipuladores.
<sstream> Stream para E/S com strings.
Organização da STL
Input/Output
<cstdlib> Classificação de caracteres e funções
<fstream> Streams para E/S com arquivos
<cstdio> printf() e scanf()
<cwchar> printf() e scanf() para wide characters
Language Suport
<locale> Representa diferenças culturais
<clocale> Funções de C para representar diferenças culturais
Organização da STL
Language Suport
<limits> Limites numéricos
<climits> Macros de C com os limites numéricos
<cfloat> Macros de C com os limites de ponto flutuante
<new> Gerenciamento de memória dinâmico
<typeinfo> Suporte para identificação de tipos em tempo de execução
<exception> Suporte para o tratamento de exceções
<cstddef> Suporte para a biblioteca da linguagem C
<cstdargs> Criação de funções com lista de argumentos variável
<csetjmp> Funções de C para manipulação de Pilhas
Organização da STL
Language Suport
<cstdlib> Finalização do programa
<ctime> Relógio (Clock) do sistema
<csignal> Manipulação de sinais em C
Numéricos
<complex> Números complexos e seus operadores
<valarray> Vetores numéricos e operações
<numeric> Operações numéricas generalizadas
<cmath> Funções matemáticas de C
<cstdlib> Geração de números aleatórios em C
STL - Iteradores
Criados para permitir uma maneira unificada de percorrer ou recuperar dados de recipientes. ◦ Escondem detalhes de implementação das
aplicações. Diminui o uso de ponteiros
◦ É possível trocar o tipo de recipiente e ainda assim usar o mesmo código.
A STL adota a filosofia de manter os algoritmos fora das classes dos recipientes. ◦ Permitir que o mesmo algoritmo possa agir sobre
recipientes diferentes.
27
STL - Iteradores
Algoritmos são implementados usando iteradores apenas. ◦ Ordenação, busca, contagem, substituição, etc...
◦ Iteradores tem operadores de incremento “++” definidos.
◦ Ponteiros podem ser usados como iteradores.
28
STL - Iteradores 29
#include <vector>
#include <iostream>
using namespace std;
template <class T>
struct print : public unary_function <T, void>
{
print(ostream& out) : os(out), count(0) {}
void operator() (T x) { os << x << ' ';
++count; }
ostream& os;
int count;
};
int main()
{
int A[] = {1, 4, 2, 8, 5, 7};
const int N = sizeof(A) / sizeof(int);
print<int> P = for_each(A, A + N,
print<int>(cout));
cout << endl << P.count << " objects
printed." << endl;
return 1;
}
30
STL - Vector
vector é o recipiente mais simples da STL. ◦ Seqüência que suporta acesso aleatório aos seus elementos.
◦ Inserção e remoção de elementos no final em O(1).
◦ Inserção e remoção de elementos no meio em O(n).
◦ Busca em O(n). ◦ Gerenciamento automático de memória. ◦ Iteradores estão invalidados após realocação de memória, inserção e remoção no meio.
◦ Descrição e implementação
STL - Vector 31
#include <vector>
#include <iostream>
#include <iterator>
#include <ext/algorithm>
using namespace std;
using __gnu_cxx::is_sorted;
int main()
{
vector<int> V;
V.push_back(20);
V.push_back(30);
V.push_back(-1);
V.push_back(-1);
V.push_back(-1);
cout << "V: \n";
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
stable_sort (V.begin(), V.end());
cout << "\nV: sorted\n";
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
cout << "\nV: is sorted? ";
cout << is_sorted ( V.begin(), V.end() ) << "\n";
}
STL - Vector 32
template<class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result) {
for( InputIterator itr = first; itr != last; ++itr, ++result ) {
*result = *itr;
}
return result;
}
33
STL - List
list é de fato uma lista duplamente encadeada. ◦ É uma seqüência que suporta percurso para frente e para trás.
◦ Busca em O(n).
◦ Inserção e remoção de elementos na frente, no meio e no final em O(1).
◦ Iteradores ainda estão válidos após inserção, splicing ou remoção.
STL - List 34
#include <list>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
list<int> L;
L.push_back(0);
L.push_front(1);
L.insert(++L.begin(), 2);
copy(L.begin(), L.end(), ostream_iterator<int>(cout, " "));
cout << "\n";
list<int> M ( L );
L.splice ( ++++L.begin(), M );
copy(L.begin(), L.end(), ostream_iterator<int>(cout, " "));
cout << “\n”;
copy(M.begin(), M.end(), ostream_iterator<int>(cout, " "));
}
STL - List 35
#include <iostream>
#include <list>
using namespace std;
int main() {
list<string> l;
l.push_back("Hello, ");
l.push_back(“Bro! ");
l.push_back("Fine? ");
for (list<string>::const_iterator i = l.begin(); i != l.end(); ++i) cout << *i;
}
36
STL - Set
set é uma coleção ordenada de objetos do tipo “key” sem duplicatas. ◦ Operações de conjunto como interseção, união e diferença são eficientes.
◦ Implementado por uma árvore balanceada de busca (Red Black, Splay).
◦ Busca em O(log n).
multiset é a versão que permite duplicatas.
STL - Set 37
#include <set>
#include <iostream>
using namespace std;
struct ltstr // função objeto. Compara duas seqüências de caracteres.
{
bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) < 0;
}
};
int main()
{
const int N = 6;
const char* a[N] = {"isomer", "ephemeral", "prosaic",
"nugatory", "artichoke", "serif"};
const char* b[N] = {"flat", "this", "artichoke",
"frigate", "prosaic", "isomer"};
set<const char*,ltstr> A(a, a + N);
set<const char*,ltstr> B(b, b + N);
set<const char*,ltstr> C;
STL - Set 38
cout << "Set A: ";
copy(A.begin(), A.end(), ostream_iterator <const char*>(cout, " "));
cout << endl;
cout << "Set B: ";
copy(B.begin(), B.end(), ostream_iterator <const char*>(cout, " "));
cout << endl;
cout << "Union: ";
set_union(A.begin(), A.end(), B.begin(), B.end(),
ostream_iterator<const char*>(cout, " "), ltstr());
cout << endl;
cout << "Intersection: ";
set_intersection(A.begin(), A.end(), B.begin(), B.end(),
ostream_iterator<const char*>(cout, " "), ltstr());
cout << endl;
set_difference(A.begin(), A.end(), B.begin(), B.end(),
inserter(C, C.begin()), ltstr());
cout << "Set C (difference of A and B): ";
copy(C.begin(), C.end(), ostream_iterator <const char*>(cout, " "));
cout << endl;
}
39
STL - Map
map associa objetos do tipo “key” a objetos do tipo “data”. ◦ Nenhum par de elementos possui a mesma chave.
◦ Percurso é ordenado. ◦ Indicada para implementação de dicionários. ◦ Implementada por uma árvore balanceada de busca (Red Black, Splay).
◦ Busca em O(log n). multimap é a versão que permite
duplicatas.
STL - Map 40
#include <map> #include <string> #include <iostream> using namespace std; typedef map < long, string > mapType; typedef mapType::value_type ValuePair; int main() { mapType Map; Map[836361136] = "Andrew"; Map[274635328] = "Berni"; Map[974635328] = "Ulisses"; Map[277735328] = "Paulo"; Map[277825328] = "Pedro"; Map[266735328] = "Peter"; Map[275734328] = "Paula"; Map[275839328] = "Paulos"; Map.insert(ValuePair(260736622, "John")); Map.insert(ValuePair(720002287, "Karen")); Map.insert(ValuePair(138373498, "Thomas")); Map.insert(ValuePair(135353630, "William")); // insertion of Xaviera is not executed, because // the key already exists. Map.insert(ValuePair(720002287, "Xaviera")); mapType Map2 ( Map.begin(), Map.end() ); cout << "equality operator " << (Map2 == Map) << endl;
STL - Map 41
cout << "Output:\n";
Map.erase ( 720002287 );
Map2.swap ( Map );
mapType::const_reverse_iterator iter = Map.rbegin();
while( iter != (mapType::const_reverse_iterator)Map.rend() ) {
cout << (*iter).first << ':'
<< (*iter).second
<< endl;
++iter;
}
cout << "Output of the name after entering the number\n"
<< "Number: ";
long Number;
cin >> Number;
mapType::const_iterator it = Map.find(Number);
if(it != Map.end()) {
cout << (*it).second << ' ' // O(1)
<< endl;
} else
cout << "Not found!" << endl;
}
42
class cool
{
private: int serial;
private: string longname;
public: cool() {} // try to comment this out to see the error
public: cool(int i, string s)
{
serial = i;
longname = s;
}
public: int get_serial() { return serial; }
public: string get_name() { return longname; }
public: void set_name(string n) { longname = n; }
};
int main()
{
cool c(5,"Five Young Canibals");
cool d(8,"Eighteen");
map<string,cool> m; // This container stores pair of objects string and cool
// I mean: copies of the objects I give to it
map<string,cool*> m2; // One could store pointers to objects in a container
m["Five"]=c;
m["Eight"]=d;
m["new"] = cool(78,"New object"); // short for m.insert(m.begin,make_pair(const string("Eight"),d));
map<string,cool>::iterator i;
for (i=m.begin(); i!= m.end(); ++i)
cout << (*i).second.get_serial() << " " << (*i).second.get_name() << endl;
// elements in the map are pairs, whose fields are first and second
cout << “One of the elements: " << m["new"].get_name() << endl;
}
43
STL - Hash Map
hash_map associa objetos do tipo “key” a objetos do tipo “data”. ◦ Nenhum par de elementos possui a mesma chave.
◦ Não há ordem de percurso. ◦ Implementada por uma hash table. Há uma função de hash que gera endereços a partir de chaves.
◦ Busca em O(1).
hash_multimap é a versão que permite duplicatas.
44
#include <ext/hash_map> #include <string> #include <iostream> using namespace std; using __gnu_cxx::hash_map; using __gun_cxx::hash; // initial hash table size #define table_size 11 // define your own hash function template <class T> class my_hash: public hash<T> { public: my_hash() {} size_t operator()(const string& p) const { hash<const char*> h; return h(p.c_str()); } }; typedef hash_map<string, string, my_hash<string> > mapType; typedef mapType::value_type ValuePair; int main() { mapType Map ( table_size, my_hash <string>() ); Map["ANDREW"]="Andrew"; Map["BERNI"]="Berni"; Map["JOHN"]="John"; Map.insert(ValuePair("KAREN", "Karen")); Map.insert(ValuePair("THOMAS", "Thomas")); Map["WILLIAM"]="William"; // insertion of Xaviera is not executed, because // the key already exists. Map.insert(ValuePair("BERNI", "Xaviera"));
STL – Hash Map 45
cout << "Output:\n";
mapType::iterator iter = Map.begin();
while(iter != Map.end()) {
cout << (*iter).first << ':'
<< (*iter).second
<< endl;
++iter;
}
cout << "Output of the name after entering the key\n"
<< "Key: ";
char buf[256]; buf[0] = '\0';
fgets ( buf, 256, stdin );
if ( buf[strlen(buf)-1]=='\n' ) buf[strlen(buf)-1] = '\0';
string key ( buf );
iter = Map.find(key);
if(iter != Map.end()) {
cout << (*iter).second << ' '
<< Map[key]
<< endl;
} else
cout << "Not found!" << endl;
}
46
class cool
{
private: int serial;
private: string longname;
public: cool() {} // try to comment this out to see the error
public: cool(int i, string s)
{
serial = i;
longname = s;
}
public: int get_serial() { return serial; }
public: string get_name() { return longname; }
public: void set_name(string n) { longname = n; }
};
int main()
{
char *five="Five";
cool c(5,"Five Young Canibals");
cool d(8,"Eighteen");
hash_map<char*,cool> m;
m[five]=c;
m["Eight"]=d;
// short for m.insert(m.begin,make_pair(const string("Eight"),d));
hash_map<char*,cool>::iterator i;
cool x = m["Five"];
cout << x.get_serial() << " " << x.get_name() << endl;
// elements in the map are pairs, whose fields are first and second
char a;
cout << "Ok?";
cin >> a;
}
47
STL - String
string toma o lugar de um “array of char” (char *) ◦ Não é mais necessário se preocupar com o tamanho do arranjo.
◦ Oferece todas as funções de C pertinentes a strings como membros da classe.
◦ Evita erros relacionados com ponteiros, na chamada de funções que recebem ou retornam strings.
48
#include <string>
#include <iostream>
using namespace std;
int main () {
string str0;
cout << "empty constructor: " << str0 << endl;
cout << "str0 size = " << str0.size() << endl;
string str1("hellow world!");
cout << "const char constructor: " << str1 << endl;
cout << "data = " << str1.data() << endl;
cout << "size = " << str1.size() << endl;
cout << "length = " << str1.length() << endl;
cout << "capacity = " << str1.capacity() << endl;
cout << "max_size = " << str1.max_size() << endl;
cout << "str0 empty = " << str0.empty() << endl;
cout << "str1 empty = " << str1.empty() << endl;
string str2(str1);
cout << “copy constructor: " << str2 << endl;
string str3(str1, 4, 6);
cout << "string&, pos, npos, str3 constructor: "
<< str3 << endl;
string str4("hellow word!", 6);
cout << "char[], npos, str4 constructor: " << str4 << endl;
string str5(12, 'h');
cout << “n, char str5 constructor: " << str5 << endl;
cout << "str5 size = " << str5.size() << endl;
// swap
str5.swap(str1);
cout << "swap str1 and str5" << endl;
cout << "str1 = " << str1 << endl;
cout << "str5 = " << str5 << endl;
}
Exercícios
Crie uma função isPalindromo() que recebe um vetor como parâmetro. Ela deve retornar true se ele é um palíndromo e false caso contrário. ◦ Exemplo: Um vetor contendo 1, 2, 3, 2, 1 é um
palíndromo. E um vetor contendo 1, 4, 3, 2, 1 não é um palíndromo.
Crie uma mapa que associa o nome de uma pessoa a um objeto do tipo Pessoa. Utilize classe map.
Use templates e exceções
49
Referências
Notas de aula – Claudio Esperança e Paulo Cavalcanti (UFRJ)
Notas de aula – Allan Lima (citi/UFPE)
50
Próximas aulas
STL
Programação Orientada a Eventos
Programação concorrente (Threads) ◦ (3ª. Prova)
52