Aprenda C++

  • Página Inicial
  • Contato!
  • Tudo sobre C++ Parte 1!
  • Tudo sobre C++ Parte 2!
  • Tudo sobre C++ Parte 3!
  • Tudo sobre C++ Parte 4!
  • Tudo sobre C++ Parte 5!
  • Tudo sobre C++ Parte 6!
  • Tudo sobre C++ Parte 7!
  • Tudo sobre C++ Parte 8!
  • Tudo sobre C++ Parte 9!
  • Tudo sobre C++ Parte 10!
  • Tudo sobre C++ Parte 11!
  • Tudo sobre C++ Parte 12!
  • Tudo sobre C++ Parte 13!
  • Tudo sobre C++ Parte 14!
  • Tudo sobre C++ Parte 15!
  • Tudo sobre C++ Parte 16!
  • Tudo sobre C++ Parte 12

    Iterator

    Basicamente, um iterator serve para navegar dentro de uma coleção de dados, ou seja, vai apontar para determinado item de um conteiner (como o vector).

    Primeiro, crie um vector básico assim:

    
    int main() {
        vector<string> produtos; // Importe vector
    
        produtos.push_back("mouse");
        produtos.push_back("teclado");
        produtos.push_back("monitor");
        produtos.push_back("gabinete");
        produtos.push_back("caixa");
        
        cout << produtos[0] << endl;
    
        return 0;
    }
    
    

    Para navegarmos pelos elementos do vector, usaremos o iterator assim:

    
    int main() {
        vector<string> produtos; // Importe vector
    
        produtos.push_back("mouse");
        produtos.push_back("teclado");
        produtos.push_back("monitor");
        produtos.push_back("gabinete");
        produtos.push_back("caixa");
    
        vector<string>::iterator it; // Iterator
    
        cout << produtos[0] << endl;
    
        return 0;
    }
    
    

    Para retornar o primeiro elemento, usamos o método begin(), e para exibir, a variável com ponteiro, assim:

    
    int main() {
        vector<string> produtos; // Importe vector
    
        produtos.push_back("mouse");
        produtos.push_back("teclado");
        produtos.push_back("monitor");
        produtos.push_back("gabinete");
        produtos.push_back("caixa");
    
        vector<string>::iterator it; // Iterator
        
        it = produtos.begin(); // Retorna o primeiro elemento do vector
    
        cout << *it << endl; // Não esqueça do ponteiro
    
        return 0;
    }
    
    

    Também podemos usar o end(), para retornar a quantidade de elementos do vector, para exibir o último elemento em si, subtraia um, assim:

    
    it = produtos.end() - 1;
    
    

    Para navegar entre todos os elementos, podemos usar as opções advance(), next() e prev() (não exclusivo de vector e iteradores, também muito usados em listas), por exemplo:

    
    it = produtos.begin();
    advance(it, 3); // Imprime o índice 3
    
    cout << *it << endl; // Não esqueça do ponteiro
    
    

    Ou o next diretamente como ponteiro, indicando quantos elementos avançaremos:

    
    it = produtos.begin();
    
    cout << *next(it, 2) << endl; // Não esqueça do ponteiro
    
    

    O mesmo vale pro prev, usando end() ao invés de begin():

    
    it = produtos.end();
    
    cout << *prev(it, 1) << endl; // Não esqueça do ponteiro
    
    

    E para exibir todos os elementos, podemos fazer assim:

    
    int main() {
        vector<string> produtos; // Importe vector
    
        produtos.push_back("mouse");
        produtos.push_back("teclado");
        produtos.push_back("monitor");
        produtos.push_back("gabinete");
        produtos.push_back("caixa");
    
        vector<string>::iterator it; // Iterator
    
        for(it = produtos.begin(); it != produtos.end(); it++) {
            cout << *it << endl;
        }
    
        return 0;
    }
    
    

    PS: Podemos declarar o iterator diretamente nos parâmetros do for também.

    Tratamento de Erros com Try Catch

    Quando criamos um código que pode gerar um erro, podemos tratá-lo colocando ele dentro de um bloco try catch. Quando o que está sendo executado dentro do try dá erro, ele pula para o bloco catch, onde podemos tratar o erro, por exemplo fechando o programa para evitar travamentos ou exibindo uma mensagem personalizada.

    Vamos primeiramente, criar um vector dentro de um try catch, assim (não esqueça de importar vector pro vector e stdexcept para o try catch):

    
    int main() {
        vector<int> num(5); // Importe vector
    
        num.at(7) = 10; // Teste posições existentes e inexistentes.
        
        cout << num[0] << endl;
        
        try {// Importe stdexcept
            
        }
        catch(exception &ex) { // Aqui teremos o & indicando endereço
    
        }
    
        return 0;
    }
    
    

    Nosso vector tem 5 posições, ao colocarmos uma posição inexistente no at() (por exemplo, 7), ele dará erro, como não estamos usando o try catch, disparará um aviso de erro padrão do C++ e travará o programa. Mas até o momento, nosso código não foi tratado.

    Ao colocar o código errado dentro do try, ele não gerará mais esse erro, veja como fazer:

    
    int main() {
        vector<int> num(5); // Importe vector
    
        try {// Importe stdexcept
            num.at(7) = 10;
    
            cout << num[0] << endl;
        }
        catch(exception &ex) {
    
        }
    
        return 0;
    }
    
    

    Note que na forma acima, o erro foi tratado, ele não foi executado por ter dado erro, mas não travou por isso. Podemos exibir uma mensagem usando o método what() do exception, por exemplo, dessa forma:

    
    int main() {
        vector<int> num(5); // Importe vector
    
        try {// Importe stdexcept
            num.at(7) = 10;
    
            cout << num[0] << endl;
        }
        catch(exception &ex) {
            cerr << "ERRO: " << ex.what() << endl; // cerr é usado para exibir erros, nesse caso import fstream
        }
    
        return 0;
    }
    
    

    Veja que ele não trava dessa forma.

    Lembrando que num vector, quando adicionamos 5 posições, elas são numeradas de 0 a 4, se adicionar ou exibir uma posição inexistente (no caso, o 5), ele dará erro). Quando o código não dá erros, ele executa normalmente.

    Temos ocasiões que é necessário gerarmos uma exceção de erro, para testar isso, faremos uma função nova para divisões, assim:

    
    double dividir(double num, double dem); // Não esqueça do protótipo da função
    
    int main() {
        double n1, n2;
    
        cout << "Digite o numerador: ";
        cin >> n1;
        cout << "Digite o denominador: ";
        cin >> n2;
    
        cout << dividir(n1, n2) << endl;
    
        return 0;
    }
    
    double dividir(double num, double dem) {
        return num / dem;
    }
    
    

    Mas como sabemos, é impossível dividir por zero, e em C++ costuma retornar o valor inf, nesse caso, vamos tratar o erro assim:

    
    int main() {
        double n1, n2;
    
        cout << "Digite o numerador: ";
        cin >> n1;
        cout << "Digite o denominador: ";
        cin >> n2;
    
        cout << endl;
    
        try {
            cout << dividir(n1, n2) << endl;
        }
        catch(exception &ex) {
            cerr << "ERRO: " << ex.what() << endl;
        }
    
        return 0;
    }
    
    

    Só que tem um detalhe, mesmo se dividirmos algum número por zero, ele não será passado o erro pro catch, então devemos ir na função dividir() e criar nosso próprio aviso de erro usando o throw, assim:

    
    double dividir(double num, double dem) {
        if(dem == 0) {
            throw "Tentativa de divisão por ZERO";
        }
        
        return num / dem;
    }
    
    

    E na função principal, mudaremos o catch assim:

    
    try {
        cout << dividir(n1, n2) << endl;
    }
    catch(const char* msg) {
        cerr << "ERRO: " << msg << endl;
    }
    
    

    Dessa forma, podemos criar outras exceções sem fazer mais alterações no try catch, por exemplo:

    
    double dividir(double num, double dem) {
        if(dem == 0) {
            throw "Impossível a divisão por ZERO";
        }
        
        // Outra condição
        
        if(num < dem) {
            throw "Numerador Tem que Ser Maior que o Denominador!";
        }
    
        return num / dem;
    }
    
    

    PS: Essa condição com o throw pode ser colocada no bloco try diretamente. E também podemos ter mais de uma cláusula catch no mesmo try.