Curso completo de linguagem C++
Gameprog - Escola de programação de jogos digitais
Contato: gameprog.br@gmail.com
track18.html

index << >>

18. STL 1/5 <vector>

18.1 Visão geral A linguagem c++ possui uma biblioteca padrão de classes que implementa diversas estruturas de dados bastante utilizadas em programação como arrays dinâmicas, filas, pilhas, mapas e algoritmos muito utilizados como organização e pesquisa de dados. Estas classes são implementadas utilizando a sintaxe genérica de programação desta forma garantindo que estas estruturas sejam utilizadas com qualquer tipo de dado. Esse conjunto de bibliotecas da linguagem c++ é conhecido como STL - Standard Template Library que pode ser traduzido como Biblioteca de modelos padrões. Em STL é comum pensar das estruturas de dados como se fossem containers ou recipientes para qualquer outro tipo de dado. Na manipulação dos recipientes aparece a figura do iterator que é um objeto que funciona semelhante a um ponteiro pelo qual você acessa e transita pelos dados armazenados. 18.1.1 #include <vector> // arrays dinâmicas Nossa primeira abordagem é a biblioteca <vector> que implementa vector que consiste em uma array dinâmica. O vetor permite o crescimento dinâmico da array, permite a inserção e a deleção de itens e todo o processo de alocação e liberação da memória é feito de maneira automática por essa estrutura. Nosso programa abaixo 'imagina' um inventário de itens muito típico de muitos jogos de videogame. É comum do personagem caminhar pelo cenário, localizar itens, pegar, gastar itens, trocar itens. Os vetores se prestam muito bem a essas necessidades.
// vetores_01.cpp // Ilustra o uso de vetores #include <iostream> #include <string> #include <vector> using namespace std; void inicio(); void fim(); // -------------------- início da função principal --------------------------- int main() { inicio(); vector<string> inventario(5); vector<string>::iterator ncx_iter; int ntam; int nitem = 0; int ncapacidade = 0; bool lvazio; // Assinalando os itens nas posições reservadas inventario[0] = "faca"; inventario[1] = "canivete"; inventario[2] = "botas"; // Anexando dados no final do vetor inventario.push_back("espada"); inventario.push_back("escudo"); inventario.push_back("capa"); inventario.resize(10); ntam = inventario.size(); inventario.reserve(100); ncapacidade = inventario.capacity(); lvazio = inventario.empty(); cout << "\t vetor.tamanho: " << ntam << "\n"; cout << "\t vetor.capacidade: " << ncapacidade << "\n"; cout << "\t vetor.vazio? " << boolalpha << lvazio << "\n"; cout << "------------------------------------------ \n"; // Acessando os itens via iterator for (ncx_iter = inventario.begin(); ncx_iter != inventario.end(); ncx_iter++) { cout << "\t item: " << nitem << "\t"; cout << *ncx_iter << "\n"; nitem++; } // Acessando os itens via indice cout << "------------------------------------------ \n \t"; cout << inventario[1].c_str() << " tem " ; cout << inventario[1].size() << " letras \n\n"; fim(); } // endmain // ------------------ funções básicas ---------------------------------------- void inicio() { system("color f0"); system ("title vetores_01.cpp"); cout << "\n"; } // endfunction: inicio() void fim() { cout << endl; system("pause"); } // endfunction: inicio()
#include <vector> Inclua a linha acima para utilizar arrays dinâmicas. vector<string> inventario(5); Na declaração acima foi criado um vetor para armazenar 5 strings. Então para criar um vetor pode ser utilizado esta sintaxe: vector<tipo_de_dado> nome_do_vetor (nTamanho do vetor); vector<string>::iterator ncx_iter; Na maioria dos programas exemplos do nosso curso nós utilizamos em uma estrutura for(;;) uma variável inteira nomeada ncx para acessar e transitar pelos elementos de uma array ou para repetir um bloco de código um certo número de vezes. Cada ciclo de repetição do código é chamado de iteração e dizemos que nossa variável ncx é um iterador (iterator em inglês). De maneira semelhante precisamos definir um iterador para acessar os elementos dos vetores e para transitar por estes elementos. Na linha acima declaramos que ncx_iter é um iterador de um vetor de strings. int ntam; int ncapacidade = 0; bool lvazio; Declaramos estas variáveis para guardar os valores das propriedades retornados por alguns métodos como tamanho do vetor, capacidade e um valor lógico para guardar se o vetor estiver vazio. // Assinalando os itens nas posições reservadas inventario[0] = "faca"; inventario[1] = "canivete"; inventario[2] = "botas"; Nos vetores você pode assinalar conteúdo às posições utilizando a sintaxe normal de arrays, isto é possível desta forma porque esta classe implementa o método operator[](). // Anexando dados no final do vetor inventario.push_back("espada"); inventario.push_back("escudo"); inventario.push_back("capa"); O método .push_back() expande o tamanho do vetor e anexa o conteúdo em seu final. inventario.resize(10); ntam = inventario.size(); inventario.reserve(100); ncapacidade = inventario.capacity(); lvazio = inventario.empty(); O método .resize() redimensiona o tamanho do vetor. O método .reserve() aloca antecipadamente memória para o vetor. O método .capacity() retorna a capacidade de memória para itens do vetor. O método .empty() verifica se o vetor está vazio. A questão do redimensionamento de arrays trazida pelo método .resize() é um processo complexo e que toma certo tempo de processamento porque o algoritmo de aumento do tamanho da array implica na alocação de um espaço maior e depois cópia dos elementos originais para o espaço recém-alocado. Devido a isso é importante utilizar .reserve() para deixar pré-reservado o espaço que você acredita que tua array pode alcançar para assim evitar dispêndio de tempo em repetições de redimensionamento da array. for (ncx_iter = inventario.begin(); ncx_iter != inventario.end(); ncx_iter++) { cout << "\t item: " << nitem << "\t"; cout << *ncx_iter << "\n"; nitem++; } Este bloco permite o acesso e a iteração pelos elementos do vetor de strings. O método .begin() retorna um iterator que aponta para o começo do vetor, e o método .end() retorna um iterator apontando para o final do vetor. Veja que é utilizado sintaxe de ponteiros para adiantar (ncx_iter++) e acessar os elementos apontados (*ncx_iter). Essa forma somente é possível porque esta classe implementa o operator*(). // Acessando os itens via indice: cout << "------------------------------------------ \n \t"; cout << inventario[1].c_str() << " tem " ; cout << inventario[1].size() << " letras \n\n"; Este bloco produz este resultado: canivete tem 8 letras. O operator[]() retorna uma referência ao objeto armazenado no vetor. Como este objeto é da classe string nós utilizamos os métodos dessa classe para obter a string propriamente dita através de .c_str() e acessamos o tamanho dela pelo método .size().
index << >>


Produzido por Gameprog: Jair Pereira - Fev/2006 - Junho/2013 © gameprog.br@gmail.com http://www.gameprog.com.br