33
Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include <iostream> template<classe T> void PRINT_ELEMENTS( const T& col, const char* opcional = “” { typename T::const_iterator pos; std::cout << opcional; for (pos = col.begin(); pos != col.end(); ++pos) std::cout << *pos << ‘ ‘; std::cout << endl; }

Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Embed Size (px)

Citation preview

Page 1: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Funções definidas pelo usuário

STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções

#include <iostream>

template<classe T>void PRINT_ELEMENTS( const T& col, const char* opcional = “”{

typename T::const_iterator pos;

std::cout << opcional; for (pos = col.begin(); pos != col.end(); ++pos)

std::cout << *pos << ‘ ‘;std::cout << endl;

}

Page 2: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Algoritmos definidos pelo usuário

#include <set>typedef sdt::set<int> IntSet;

IntSet col;col.insert(3); col.insert(1); col.insert(4);col.insert(1); col.insert(2); col.insert(5);

PRINT_ALL_ELEMENTS(col, “Set: “);

Page 3: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Funções como argumentos

Vários algoritmos permitem a passagem de funções definidas pelo usuário como parâmetros. Essas serão chamadas pelo algoritmo

void print(int elem) { cout << elem << ‘ ‘ ; }

int main() {

vector<int> col;

for (int i=1; i<=9; ++i) col.push_back(i);

for_each(col.begin(), col.end(), print);

cout << endl;}

Page 4: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Funções como argumentos

Algumas vezes são requeridos, outras opcionais. Podem especificar critérios de busca, de ordenação ou definir uma manipulação enquanto transferindo elementos de um container para outro

int square(int val) { return val * val; }

int main()

{

vector<int> col;

vector<int> col2;

for (int i=1; i<=9; ++i)

col.push_back(i);

transform(col.begin(), col.end(), std::back_inserter(col2), square);

cout << endl;

}

Page 5: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Predicados

São funções que retornam um valor Booleano Usadas em critérios de busca ou ordenação Predicado sempre retorna o mesmo resultado para o mesmo

valor

bool isPrime (int number) { ... }

list<int> col;// ... preenche a lista

list<int>::iterator pos;pos = find_if(col.begin(),col.end(),isPrime);if (pos != col.end())

cout << “Primeiro número primo é: “ << *pos << endl;else

cout << “Nenhum número primo encontrado” << endl;

Page 6: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Predicados Binários

Comparam propriedades específicas de dois argumentos

class Pessoa {public:

string nome(); string sobrenome();

}bool pessoaCriterio(cont Pessoa& p1, const Pessoa& p2){ return ( p1.sobrenome() < p2.sobrenome() || (!p2.sobrenome() < p1.sobrenome()) &&

p1.nome() < p2.nome());}

deque<Pessoa> col;...sort(col.begin(), col.end(), pessoaCriterio);

Page 7: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Objetos Função

Objetos que comportam-se como função são functors O que é uma função? algo que pode ser chamado usando parênteses e

passando argumentos: function(arg1,arg2)

Como criar classes que podem se comportar como função:class X {

public:

valor_retorno operator() (argumentos);

...

};

X fo;

fo(arg1,arg2);

fo.operator() (arg1,arg2);

Page 8: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Objetos Função

class PrintInt{public:

void operator() (int elem) const { cout << elem << ‘ ‘;

}}

void main() {

vector<int> col;// ...

for_each(col.begin(), col.end(), PrintInt);}

Page 9: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Objetos Função

São mais “espertos” que funções pois podem possuir mais habilidades que o operador (). Podem ter outros membros e atributos, ou seja tem um estado próprio

Cada objeto função tem seu próprio tipo, mesmo que sua assinatura seja idêntica a de outro objeto

São usualmente mais rápidos que funções ordinárias

class AddVal() {public: AddVal(int v) : val_(v); void operator(int& elem) { elem += val_; }}

AddVal add3(3);AddVal add4(4);for_each(col.begin(),col.end(),add3);for_each(col.begin(),col.end(),add4);

Page 10: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Elementos de Containers

Um elemento de container devem ser copiável por um construtor de cópia

containers guardam cópias dos elementos nele inseridos

Um elemento de container deve ser associável por um operador de associação

Um elemento de container deve ser destruível por um destrutor

ContType c cria um container vazioContType c1(c2) copia um container do mesmo tipoContType c(beg, end) cria e inicializa com os elem. do intervalo

c.size() retorna o numero de elementos do containerc.empty() retorna se o container esta vazio ou não

c.insert(pos, elem) insere elemento em posiçãoc.erase(beg,end) remove elementos do intervaloc.clear() remove todos os elementos

Page 11: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Iterator Adapters

Iteradores são abstrações: qualquer coisa que se comporte

como um iterador é um iterador.

É possível escrever classes que oferecem interfaces iguais a

dos iteradores mas fazem coisas diferentes

STL fornece alguns iteradores especiais com comportamento

pré-definido: iterator adapters

Acrescentam poder ao conceito de iteradores

Page 12: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Insert Iterators

Algoritmos STL trabalham sobre iteradores e não sobre coleções

Iteradores não conhecem detalhes das coleções que estão

percorrendo

Iteradores tradicionais trabalham no modo sobreposição:

col2.resize(col1.size()); // necessário

copy(col1.begin(), col1.end(), col2.begin(); // pré-alocação

Insert Iterators : permitem que os iteradores trabalhem em modo

inserção . Eliminam o problema de algoritmos que tentam

escrever em destinos sem memória suficiente: destino cresce

automaticamente

Page 13: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Insert Iterators

Back Inserters: inserem novos elementos ao final da coleção

atrravés do método (push_back)

copy(col1.begin(),col2.end(),back_inserter(col2));

Front Inserters: inserem novos elementos no início da coleção

através do método (push_front)

copy(col1.begin(),col2.end(),front_inserter(col2));

Inserters: inserem na posição seguinte à posição passada como

segundo parâmetro na sua construção. Usam o método (insert)

copy(col1.begin(),col2.end(),inserter(col2, col2.begin()));

Page 14: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Stream Iterators

São iteradores que lêem de e escrevem em um objeto que representa um canal de entrada/saída (stream)

Os caracteres lidos de um teclado comportam-se como uma coleção

A saída de um algoritmo pode ser redirecionada para um arquivo ou tela

vector<string> col;

copy(istream_iterator<string>(cin), // começo da fonte

istream_iterator<string>(), // fim da fonte

back_inserter(col)); // destino

sort(col.begin(),col.end());

copy(col.begin(),col.end(), // fonte

ostream_iterator<string>(cout,”\n”); // destino

Page 15: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Invalidação de Iteradores

Operações de inserção e remoção podem invalidar iteradores Invalidação de iteradores depende do container

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

for (int i=0; i <4; i++){

coll.insert(it,i); // Erro! it é invalidado após inserção

it++;}

Page 16: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Invalidação de Iteradores

Operações de inserção e remoção podem invalidar iteradores Invalidação de iteradores depende do container

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

for (int i=0; i <4; i++){

it = coll.insert(it,i); // o.k

it++;}

Page 17: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Objetos Função

Permitem que os algorimos executem um código fornecido pelo usuário

for_each(col.begin(),col.end(),AddValue(10));

Predicados são funções que retornam verdadeiro ou falso

pos = find_if(col.begin(),col.end(),isPrime)

Page 18: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Objetos Função e Predicados pré-definidos

Predicados <funcional>

equal_to (binário) arg1 == arg2greater (binário) arg1 < arg2less (binário) arg1 > arg2...

Objetos Funcionais plus (binário) arg1 + arg2minus (binário) arg1 - arg2multiplies (binário) arg1 * arg2...

Page 19: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Adaptadores de função

Predicados e funções podem ser os pré-definidos ou escritos pelos usuários

Muitas vezes necessita-se de um predicado que é ligeiramente diferente de um predicado pré-definido

Para isso são usados adaptadores

pos = find_if(col.begin(),col.end(),bind2nd(greater<int>(),42))

// retorna primeiro elemento menor que 42

pos = transform(col.begin(),col.end(), col2.begin(),bind1st(minus<int>(),1000))

// copia para coleção 2, 1000 menos os elementos de coleção 1

Page 20: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Adaptadores para funções membro

class Person {

//...

void print () const {

std::cout << name << std::endl;

}

void printWithPrefix (std::string prefix) const {

std::cout << prefix << name << std::endl;

}

};

std::vector<Person>& coll;

//....

for_each (coll.begin(), coll.end(), mem_fun_ref(&Person::print));

for_each (coll.begin(), coll.end(),

bind2nd(mem_fun_ref(&Person::printWithPrefix),

"person: "));

Page 21: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Containeres

Containeres são diferentes tanto em eficiência quanto em

termos de operações e invalidação de iteradores: escolha com

cuidado

Containeres guardam cópias de elementos e retornam cópias:

forneça construtores de cópia e operadores de associação

eficientes

Use if (c.empty()) ao invés de if (c.size() == 0)

Prefira funções e algoritmos que trabalham sobre range ao

invés de manipular elemento a elemento

Page 22: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Exemplo

Dados dois vetores v1 e v2 qual a melhor forma de fazer com que o conteúdo de v1 seja igual a segunda metade do conteúdo de v2?

Usando loopv1.clear();vector<Widget>::const_iterator ci;for (ci=v2.begin() + v2.size()/2; ci != v2.end(); ci++){

v1.push_back(*ci);} Resposta: usar membro assign ao invés de loop nos elementos:v1.assign(v2.begin()+v2.size()/2, v2.end());

v1.clear();copy(v2.begin()+v2.size()/2,back_inserter(v1));

Page 23: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Algoritmos que não modificam estrutura

Servem para encontrar algo sobre a estrutura ou sobre os elementos da estrutura sem escrever loops explícitos

for_each : retorna a função passada como terceiro argumento

class MeanValue { private: long num; // número de elementos long sum; // soma de todos os valores dos elementos public:

MeanValue () : num(0), sum(0) {}void operator() (int elem) {

num++; // incrementa contador sum += elem; // acumula valor } double value ()

{ return static_cast<double>(sum) / static_cast<double>(num); }};

MeanValue mv = for_each (coll.begin(), coll.end(), MeanValue()); cout << "mean value: " << mv.value() << endl;

Page 24: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Família Find

Percorre uma sequência ou um par de sequências a fim de encontrar um valor ou um elemento que atenda o predicado

p = find(col.begin(),col.end(),3)p = find_if (col.begin(),col.end(),isPrime)

vector<int> coll;list<int> searchcoll;

pos = find_first_of (coll.begin(), coll.end(), searchcoll.begin(), searchcoll.end());

pos = adjacent_find (coll.begin(), coll.end());if (pos != coll.end()) { cout << "first two elements with equal value have position " << distance(coll.begin(),pos) + 1

Page 25: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Count

vector<int> coll; // conta o número de elementos com valor 4 num = count (coll.begin(), coll.end(), 4); cout << "number of elements equal to 4: " << num << endl;

// conta o número de elementos pares num = count_if (coll.begin(), coll.end(), isEven); cout << "number of elements with even value: " << num << endl;

// conta número de elementos com valor maior que 4 num = count_if (coll.begin(), coll.end(), bind2nd(greater<int>(),4)); cout << "number of elements greater than 4: " << num << endl;

Page 26: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Algoritmos que modificam estrutura

É melhor aplicar algoritmos do que iterar sobre eles:

for (it = col1.begin(); it!= col1.end(); it++)col2.push_back(*it);

copy(col1.begin(); col1.end(), col2.begin());

transform(col.begin(); col.end(); col2.begin(), square);

pos = unique (col.begin(), col.end());

swap (sentence[1], sentence[3]);

Page 27: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Resumo

Vector Deque List

Estrutura interna array dinâmico array de array lista duplamente linkada

Elementos valor valor valor

Valores duplicados

sim sim sim

Acesso aleatório sim sim não

Iteradores acesso aleatório acesso aleatório bidirecional

Busca elementos lenta lenta muito lenta

Inserção/Remoção é rápida

no fim no fim e no começo

qualquer lugar

Invalida iteradores

qdo realoca sempre nunca

Libera memória remoção

nunca às vezes sempre

Page 28: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Resumo

Set Multiset Map Multimap

Estrutura interna árvore binária árvore binária árvore binária árvore binária

Elementos valor valor (chave,valor) (chave,valor)

Valores duplicados não sim não para chave sim

Acesso aleatório não não com a chave não

Iteradores bidirecional bidirecional bidirecional bidirecional

Busca elementos rápida rápida rápido para chave

rápido para chave

Inserção/Remoção é rápida

--- --- --- ---

Invalida iteradores nunca nunca nunca nunca

Libera memória remoção

sempre sempre sempre sempre

Page 29: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Containeres Especiais

Stack: métodos push(), pop(), top()

#include <stack>stack<int> st;

Queues: métodos push(), front(), back(), pop()

#include <queue>queue<string> q;

Priority Queues: métodos push(), pop(), top()

#include <queue>priority_queue<float,vector<float>,greater<float> > p;

Bitsets: arrays de bits (valores booleanos)enum Color { red, green, blue ... }bitset<numColors> usedColors;usedColors.set(red);usedColors.set(green);

Page 30: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Strings

Podem ser usados como tipos normais

Podem ser copiadas, comparadas, associadas como tipos fundamentais sem

a preocupação sobre a existência de memória suficiente p. ex.

Operadores : = , ==, + (concatenação)#include <string>

string filename, tmpname;

string suffix(“tmp”);

int idx = filename.find(‘.’);

if (idx == string::npos)

tmpname = filename + suffix;

else

{

string basename = filename(0,idx);

tmpname = basename + suffix;

}

Page 31: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

I/O Streams

Em C++ entrada/saída é executada através de streams: canais de entrada

e saída onde fluem sequências de caracteres. Entrada é interpretada como

dados fluindo de um stream e saída como dados fluindo para um stream

Existem duas classes de streams: istream e ostream

A biblioteca IOStream define alguns objetos globais do tipo istream e

ostream . Esses objetos correspondem aos canais padrão de entrada e

saída: cin : canal de entrada padrão, geralmente conectado, pelo sistema operacional,

ao teclado cout: canal de saída padrão, geralmente conectado, pelo sistema operacional, ao

monitor cerr: canal de saída padrão para a saída de erros, geralmente também

conectado ao monitor clog: canal de saída padrão para a saida de log, geralmente também

conectadoao monitor

Page 32: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

I/O Streams

Operadores de deslocamento << e >> são sobrecarregados para

representarem os operadores de entrada e saída

Manipuladores: objetos especiais que manipulam os streams

endl envia um ´\n´ e descarrega o buffer

ends envia um ´\0´

flush descarrega o buffer

ws lê e descarta espaços em branco

Formatação é feita através de flags

cout << std::setw(8) << std::setfill(´_´) << -3.14 << endl;

// ___-3.14

Page 33: Funções definidas pelo usuário STL oferece a possibilidade de que o usuário escreva seus próprios algoritmos para processar os elementos de coleções #include

Acesso a arquivos

Streams podem ser usadas para acessar arquivos: ofstream e ifstream. Permissões são controladas por flags

Exemplo:const string saida = “xxx.txt”;const string entrada = “yyy.txt”;ofstream file(saida.c_str(),std::ios:app);if (!file) // erro na abertura do arquivo{ ... }for (int i=32; i<256; i++)

file << i << “ “;

ifstream file2(entrada.c_str());if (file2) {

char c; while (file.get(c))

cout.put(c)}