Home > Tecnologia > Informática > Programação > C++ > Arrays dinâmicos com structs em C++

Arrays dinâmicos com structs em C++

Em artigos anteriores (“Como usar apontadores em C / C++” e “Funções malloc e realloc em C / C++“) abordei a questão dos apontadores e de arrays dinâmicos em C/C++. Neste artigo vou continuar a falar sobre esta matéria abordando agora a estruturas do tipo “struct”.

Em C++, uma “struct” funciona como uma classe mas sem métodos, apenas propriedades (variáveis). Outra diferença, é que numa “struct”, as propriedades são públicas por omissão. Imagine que se pretende criar uma agenda em que cada entrada irá conter um nome, um número de telefone e um endereço de e-mail. Podemos definir a nossa “struct” da seguinte forma:

struct Agenda {
    char nome[60];
    char telefone[15];
    char email[32];
};

Queremos que a nossa agenda possa ter uma capacidade dinâmica e que não esteja limitada a um determinado número fixo de entradas. Vimos no artigo “Funções malloc e realloc em C / C++” como usar as funções “malloc” e “realloc” para construir um array dinâmico de números inteiros. Vimos ainda várias soluções para ir incrementando a capacidade do nosso array e usei a solução 2, onde alocámos 10 elementos iniciais e fazíamos crescer a capacidade do array de 10 em 10, sempre que atingíssemos o limite deste. Neste artigo, vou optar pela solução 3 e, no exemplo que se segue, vamos iniciar a capacidade a 5 elementos e vamos duplicando esta capacidade sempre que atingirmos o limite do array.

O seguinte código mostra a iniciação dos nossos dados:

    int indice = 0;
    int capacidade = 5;
    Agenda *agenda = NULL;
    
    agenda = (Agenda *) malloc(sizeof(Agenda)*capacidade);

Repare que o código é muito semelhante ao exemplo que vimos no artigo anterior. É importante ter em mente que, ao usarmos a função “sizeof”, a nossa estrutura tenha um tamanho fixo! Por isso, usei arrays de chars de dimensão fixa para os campos da agenda. De outra forma, não seria possível a aceder directamente a um elemento “agenda[i]” pois o compilador não conseguia calcular a sua posição exacta, como expliquei no mesmo artigo anterior.



Para inserir elementos e gerir a capacidade do array, teremos o seguinte código:

    Agenda a;
    cout << "Nome: ";
    cin >> a.nome;
    cout << "Telefone: ";
    cin >> a.telefone;
    cout << "E-Mail: ";
    cin >> a.email;
    agenda[indice] = a;
    indice++;
    if (indice>=capacidade) {
        capacidade*=2;
        agenda = (Agenda *) realloc(agenda, sizeof(Agenda)*capacidade);
    }

Repare que, neste caso, estamos a duplicar a capacidade do array sempre que chegamos ao seu limite (linha 11). Gostaria de chamar à atenção também que podemos usar sempre a função “realloc”.  Quando iniciámos a array “agenda” com a função “malloc”, podíamos tê-lo feito da seguinte forma:

    agenda = (Agenda *) realloc(agenda, sizeof(Agenda)*capacidade);

Repare que o array é iniciado a “NULL”. Quando a função “realloc” recebe um apontador existente a “NULL”, vai criar uma nova alocação.

Vejamos agora o código completo:

#include <iostream>
#include <stdlib.h>

using namespace std;

struct Agenda {
    char nome[60];
    char telefone[15];
    char email[32];
};

int main() {
    
    char menu = ' ';
    int indice = 0;
    int capacidade = 5;
    Agenda *agenda = NULL;
    
    agenda = (Agenda *) malloc(sizeof(Agenda)*capacidade);
    
    while (menu!='0') {
        
        cout << "1 - Inserir contacto" << endl;
        cout << "2 - Listar contactos" << endl;
        cout << "3 - Estado do array" << endl;
        cout << "0 - Sair do programa" << endl;
        cin >> menu;
        
        switch (menu) {
            case '0':
                break;
            case '1':
                Agenda a;
                cout << "Nome: ";
                cin >> a.nome;
                cout << "Telefone: ";
                cin >> a.telefone;
                cout << "E-Mail: ";
                cin >> a.email;
                agenda[indice] = a;
                indice++;
                if (indice>=capacidade) {
                    capacidade*=2;
                    agenda = (Agenda *) realloc(agenda, sizeof(Agenda)*capacidade);
                }
                break;
            case '2':
                for (int i=0; i<indice; i++) {
                    cout << "Entrada " << i << ":" << endl;
                    cout << "  Nome: " << agenda[i].nome << endl;
                    cout << "  Telefone: " << agenda[i].telefone << endl;
                    cout << "  E-Mail: " << agenda[i].email << endl;
                }
                break;
            case '3':
                cout << "Elementos inseridos: " << indice << endl;
                cout << "Capacidade do array: " << capacidade << endl;
                break;
            default:
                printf("Opção inválida!");
                break;
        }
        
    }
    
    free(agenda);
    
    return 0;
    
}



Algumas considerações e diferenças neste código, face ao do artigo anterior:

  • Esta implementação está focada em C++ e foi usada a biblioteca “iostream” em vez da “stdio.h” (linha 1) e para facilitar o acesso aos comandos “cout” e “cin” foi declarado o uso do “namespace std” (linha 4)
  • O comando “cin” tem um comportamento pouco simpático com números inteiros (linha 27), por isso a variável menu foi declarada como “char” (linha 14). É óbvio que se pode dar a volta ou usar funções como o “fgets”, mas o objectivo aqui é simplificar o código e focar o essencial.
  • Na linha 33, declarou-se uma instância da “Agenda” para carregar os dados. Estes podem ser inseridos directamente no array, mas não considero boa prática proceder desta forma (especialmente no caso de se pretender validar dados antes de copiar a informação para o array).

Siga-nos nas redes sociais e esteja a par das nossas novidades no nosso blogue multi-temático Out4Mind!

Este artigo foi escrito de acordo com a antiga grafia.

About Carlos Santos

Frequência em mestrado de Engenharia Electrotécnica e de Computadores. Programador freelancer: Websites, Aplicações Web (JAVA e PHP), J2SE/J2EE, C/C++ e Android. Explicador e formador em informática, matemática e electrotecnia. Formação presencial ou remota através de Skype e Team Viewer. Interesses: Música, áudio, vídeo, ciência, astronomia e mitologia.

Leave a Reply

Your email address will not be published and it is optional.