Linguagem de Programação I Carlos Eduardo Batista Centro de Informática - UFPB bidu@ci.ufpb.br
Exemplo: Explorar Templates e Exceções Incrementar com o uso de STL 2
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. STL 3
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 STL 4
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. STL 5
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> <set> Array associativo do tipo T (red-black tree) Conjunto do tipo T <bitset> Array de booleanos
Organização da STL <utility> <funcional> <memory> <ctime> <iterator> <algorithm> <cstdlib> General Utilities Operadores Funções Funções para manipulação de memória Funções de C para manipulação de data e hora Iterators Definição e suporte para Iterators Algorithms Algoritmos gerais bsearch() e qsort()
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
<cstdlib> Language Suport 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 Organização da STL
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. STL - Iteradores 14
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. STL - Iteradores 15
#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; STL - Iteradores 16
É um tipo utilizado para percorrer os containers da STL Objetos deste tipo são ponteiros Cada container possui uma classe com este nome; Para percorrer um container podemos utilizar os métodos: begin() - Ponteiro para o início do container end() - Ponteiro para o fim do container As classes const_iterator
int main() { typedef vector<int> IntVector; IntVector v; v.push_back(10); v.push_back(14); v.push_back(0); v.push_back(-8); v.push_back(30); // declara um iterator para um vetor IntVector::const_iterator iter; // percorre o vetor através de um iterator for (iter = v.begin(); iter!= v.end(); iter++) { } cout << *iter << " "; cout << endl; cin.get(); } return 0; As classes const_iterator 18
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 19
#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 20
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; } STL - Vector 21
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 22
#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 23
#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; } STL - List 24
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 25
#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 26
} 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; STL - Set 27
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 28
#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 29
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; STL - Map 30
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; } 31
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. STL - Hash Map 32
#include <ext/hash_map> #include <string> #include <iostream> using namespace std; using gnu_cxx::hash_map; using gun_cxx::hash; #define table_size 11 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"; Map.insert(ValuePair("BERNI", "Xaviera")); 33
} 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; STL Hash Map 34
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; } 35
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. STL - String 36
#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; } 37
int main() { string s; // também é uma string basic_string<char> bs; // lê uma linha getline(cin, bs); cout << "bs = \"" << bs << "\"" << endl; // lê uma string cin >> s; cout << "s = \"" << s << "\"" << endl; // troca os conteúdos s.swap(bs); cout << "Apos a inversao: " << endl << "bs = \"" << bs << "\"" << endl << "s = \"" << s << "\"" << endl; int a = s.find('a'); cout << "Primeiro indice da letra 'a' em s: " << a << endl; s[a] = 'A'; cout << "Apos a modificacao s = \"" << s << "\"" << endl; // converte s para uma strig de c const char *p = s.data(); // s.c_str(); cout << "p = \"" << p << "\""<< endl; cout << "Tamanho de bs: " << bs.length() << endl; // limpa bs bs = ""; cout << "bs foi limpa? " << (bs.empty()? "Sim" : "Nao") << endl; return 0; } Strings 38
Crie uma função verificarpalindromo() que recebe um vetor como parâmetro. Ela deve retornar true se ele contém 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. A classe Pessoa deve ser feita usando templates, armazenando uma variável de tipo arbitrário. Crie um programa que leia entradas e armazene utilizando a classe map. Caso o usuário tente cadastrar uma chave duplicada, uma exceção deve ser lançada. Exercícios 39
2ª. Prova 20/03 Reposição 25/03 Final 27/03 2º. Trabalho Deadline 22/03 23h59 GMT-3 40
Notas de aula Claudio Esperança e Paulo Cavalcanti (UFRJ) Notas de aula Allan Lima (citi/ufpe) Referências 41
Marcação 2ª. Prova e trabalho 42
STL Programação Orientada a Eventos Programação concorrente (Threads) (3ª. Prova) Próximas aulas 43
Linguagem de Programação I Carlos Eduardo Batista Centro de Informática - UFPB bidu@ci.ufpb.br