C++ Standard Template Library
-
Upload
duda-dornelles -
Category
Technology
-
view
954 -
download
3
description
Transcript of C++ Standard Template Library
Introdução à STL(Standard Template Library)
Felipe Sampaio, Robson Dornelles, Gerson Geraldo H. Cavalheiro
Templates
• É uma ferramenta da linguagem C++ para a geração de código genérico
template<class tipo>tipo soma(tipo a, tipo b) {return a + b;
}printf(“%d”, soma<int> (1,2));printf(“%f”, soma<float> (1.4,2.6));
• O código acima funciona para qualquer tipo que tenha o operador “+” sobrecarregado
Templatestypedef struct minha_string {
char *str;
minha_string(char* s) {
str = (char*) malloc(sizeof(strlen(s)));
strcpy(str,s);
}
minha_string operator+(minha_string b) {
minha_string n(strcat(str,b.str));
return n;
}
}MINHA_STR;
int main() {
MINHA_STR a("abc");
MINHA_STR b("def");
printf("%s\n", soma<MINHA_STR> (a,b).str);
return 0;
}
Afinal, o que é?
• Parte do ISO Standard C++ Library
• STL = Standard Template Library
• A STL implementa várias estruturas de dados, no formato de classes, utilizando templates
• Assim, é possível guardar qualquer tipo nessas estruturas
• Documentação oficial:
www.sgi.com/tech/stl
Por que usar?
• Redução do tempo de desenvolvimento.– Código pronto e depurado.
• Legibilidade de código– Além de utilizar código padrão, o programa desenvolvido fica
mais enxuto.
• Robustez– As estruturas de dados de STL crescem automaticamente.
• Código portável– Usa um padrão.
• Facilita a manutenção– As estruturas de dados são, até certo ponto, intercambiáveis
• É fácil!
Componentes básicos
• Trata-se de uma biblioteca que define:
• Containers– Estruturas de dados
• Iterators– Iteradores para percorrer as estruturas de dados
• Algoritmos– Oferecem serviços (funcões) para as estruturas de dados (busca, ordenação...)
Containers “top of mind”
• map – Possui dois campos, uma chave e um valor, ambos
campos podem ser de qualquer tipo e de qualquer valor
– O conteúdo é mantido ordenado
• vector – Semelhante a um vetor em C/C++, mas cresce
automáticamente.
• list – Semelhante ao vetor, mas implementada como uma
lista encadeada
Uso do vector
• Métodos– unsigned int size();
• Retorna o número de elementos de um vetor
– push_back(type element);• Insere, no fim, um novo elemento
– bool empty();• Retorna true se o vetor esta vazio
– void clear();• Remove todos os elementos do vetor
– type at(int n);• Retorna o elemento que está na posição indicada, fazendo o teste de limites
Uso do vector
• Operadores– =
• Substitui o conteúdo do vetor destino com o conteúdo do vetor informado
– ==• Compara o conteúdo (elemento a elemento) do vetor
– []• Acesso à uma posição do vetor – sem teste de limites!
Uso do vector
• Alocação prévia da área de dadosvector<int> v(100);
v[80] = 1; // Funciona!
v[200]= 1; // Ups...
• Crescimento automáticovector<int> v2;
int i;
while( std::cin >> I )
v.push_back(i);
Uso do vector#include <iostream>#include <vector>
using namespace std;int main() { int i; vector <int> example; example.push_back(3); example.push_back(10); example.push_back(33); for( i = 0 ; i < example.size() ; i++) cout << example[i] << " "; ...}
Uso do vector#include <iostream>#include <vector>
using namespace std;int main() { vector <int> example; vector <int> another_vector;
another_vector.push_back(10); example.push_back(10); if( example == another_vector ) example.push_back(20); for( i = 0 ; i < example.size() ; i++) cout << example[i] << " ";
return 0;}
Uso de list
• Métodos– unsigned int size();
• Retorna o número de elementos de um vetor
– push_back/front(type element);• Insere, no fim/início, um novo elemento
– pop_back/front();• Retira o último/primeiro elemento
– back/front();• Retorna o último/primeiro elemento
– iterator insert(iterator pos, const T& x);• Insere um elemento após a posição indicada
– empty, clear, swap, resize, split, merge, ...
Uso de list
• Operadores– =
•Substitui o conteúdo do vetor destino com o conteúdo do vetor informado
– ==•Compara o conteúdo (elemento a elemento) do vetor
– <•Comparação lexicográfica
Uso de list
int i;
list<int> lst;
for( i = 1 ; i <= 5 ; ++i )
lst.push_back(i);
for( i = 10 ; i > 5 ; ++i )
lst.push_front(i);
...
Uso de map
• Estrutura de dados que faz uma associação entre valores de dois tipos de dados distintos– Chave– Dado
• Não pode haver dois dados com a mesma chave!
Uso de map
• Métodos– size, empty, clear, swap, ...– iterator find(const key_type& k)
•Retorna a posição onde o elemento identificado pela chave se encontra
– size_type count(const key_type& k)•Retorna o número de elementos que possui a chave indicada (que deve ser, no map, 1 ou 0)
Uso de map
• Operadores– []
•Onde é informada a chave
– =•Operação de atribuição
– ==•Compara dois maps
– <•Teste lexicográfico
Uso de maplong aux;map<long,int> raiz;
raiz[4] = 2;raiz[1000000] = 1000;
std::cin >> aux;
if( root.count(aux) != 0 ) std::cout << root[l]else std::cout << "Nao tem raiz perfeita!";
Uso de map#include <map>
double bancaSaoJoao( const caipira& caipa ) {
map<char*,float,ltstr> preco;
char item[20];
double conta = 0.0;
price["carapinha"] = 0.75;
preco["quentao"] = 1.5;
preco["pinhao"] = 1.25;
preco["pipoca"] = 0.75;
while( std::cin >> item ) {
item = caipa.whatYouWantBaby();
conta += price[item];
}
return conta;
}
Uso de map#include <map>
struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }};
double bancaSaoJoao( const caipira& caipa ) {
map<char*,float,ltstr> preco;
char item[20];
double conta = 0.0;
preco["carapinha"] = 0.75;
...
Uso de mapint main() {
map<const char*, int, ltstr> months;
months["january"] = 31; months["february"] = 28;
months["march"] = 31; months["april"] = 30;
months["may"] = 31; months["june"] = 30;
months["july"] = 31; months["august"] = 31;
months["september"] = 30; months["october"] = 31;
months["november"] = 30; months["december"] = 31;
cout << "june -> " << months["june"] << endl;
map<const char*, int, ltstr>::iterator cur = months.find("june");
map<const char*, int, ltstr>::iterator prev = cur;
map<const char*, int, ltstr>::iterator next = cur;
++next;
--prev;
cout << "Previous (in alphabetical order) is " << (*prev).first << endl;
cout << "Next (in alphabetical order) is " << (*next).first << endl;
}
Iterators
• Declaração– Identificação do container.
list<int> lst;
list<int>::iterator li;
• Acesso ao início da lista: li = lst.begin();
• Acesso ao fim da lista: li = lst.end();
• Acesso ao elemento int aux;
aux = *li;
Iterators
• Permite “passear” nos containers
list<int> lst;
list<int>::iterator li;
for( li = lst.begin() ;
lst != lst.end() ;
lst++ )
std::cout << *it << std::endl;
// também pode:
li = lst.begin();
*li = 313;
Algoritmos
• Permitem percorrer containters executando operações pré-definidas
• Existem vários, diversos e variados.– Exemplo
list<int> lst;
vector<int> vet;
copy(lst.begin(), lst.end(), vet.begin());
copy(lst.begin(), lst.end(),
ostream_iterator<int>(cout, ","));
sort(lst.begin(), lst.last() );
Criando classes para serem incluidas em containers
• Obrigatório:– Definir o operador de cópia:
operator=(const T&)
– Implementar o construtor default:T()
– Implementar o construtor de cópia:T(const T&)
• Caso o container desejado seja ordenado, ex: map<>– Deve ser definido o operador “menor-que”:
operator<()
– Alguns tipos primitivos possuem:• int, char, string
– Outros não:• char *
Exemplo de tipo definido pelo usuário
• Agenda de nomes struct Nome {
char* prenome;
char* sobrenome;
bool operator<(const Nome& n) {
return strcmp(prenome, n.prenome) < 0;
}
}
map<Nome,int> agenda;
Cuidados
• Acesso à posição inválida de vector<>.vector<int> v;v[100] = 1; // Ups!
Solução:– Utilizar a interface prevista:
• push_back()• reserve()• capacity()
– Pré-alocar no construtor.
Cuidados
• Cuidar para não criar elementos no map<> de forma inadvertida
if( toto["bob"] == 1 ) ...– Se bob não existia em toto, agora existe!
Evite utilizando count() para verificar se a entrada existe.
if( toto.count("bob") ) ...
Cuidados
• Utilizar a interface de serviços observando o desempenho:– Exemplo:
•empty() em list<> .
– Muito lento
if( lst.count() == 0 ) { ... }– Bem mais rápido
if( lst.empty() ) {...}
• Como saber?–Estudando a STL...
Cuidados
• Utilizar um iterador invalidadolist<int> lst;list<int>::iterator li;li = lst.begin();lst.erase(li);++li; // Ups!• Utilizar o retorno do erase para avançarli = lst.erase(li); // Ok!
Erro de compilação comum!
• Erro de compilação comum! vector<vector<int>> vet;
Falta de espaço!
O analisador léxico entende como right-shift.
Muitos outros containers
• set, multiset, multimap• queue, priority_queue
• stack , deque
• slist, bitset, valarray