Registros

Até o presente momento só foi possível a manipulação de coleção de dados do mesmo tipo, como os vetores e as matrizes, pois quando se declara um vetor de inteiros, por exemplo, todos os seus elementos são do tipo inteiro.

Já com registros, também chamados de estruturas, é possível agregar informações de tipos diferentes, criando-se um novo tipo de dado. Um registro é, portanto, uma coleção de campos, em que cada campo pode ser de um tipo diferente.

Definição Formal: O conceito de registro visa facilitar o agrupamento de variáveis que não são do mesmo tipo, mas que guardam estreita relação lógica. O registro é um caso mais geral de variável composta na qual os elementos do conjunto não precisam ser, necessariamente, homogêneos ou do mesmo tipo (FARRER ET AL, 2008).

Por exemplo, os seguintes dados de um funcionário - código, nome, salário e sexo - são informações de tipos diferentes, mas possuem uma estreita relação lógica, que é a de compor as características de um funcionário.

funcionarioRegistro.jpg

1 - Definição de um registro: criação de um novo tipo de dados

Através da palavra-chave struct define-se um novo tipo de dado. Definir um tipo de dado significa informar ao compilador seu nome, tamanho em bytes e a maneira como deve ser lido e recuperado da memória.

A definição de um registro informa como ele está organizado e quais são os seus membros. A definição de um registro não cria variável, somente informa ao compilador as características de um novo tipo de dado. Não há nenhuma reserva de memória.

registro1.jpg

A forma geral para se criar um novo tipo de dados como registro é apresentada a seguir.

struct tipoDoRegistro{ // primeiro cria-se o tipo de dado Registro
   tipoDoCampo1  nomeDoCampo1;
   tipoDoCampo2  nomeDoCampo2;
   ...
   tipoDoCampoN  nomeDoCampoN;
};

Exemplo 1: Criação de um registro que agrupa características de um funcionário.

struct Funcionario{ // tipo de dado Funcionario sendo criado
   int codigo;
   char nome[30];
   float salario;
   char sexo;
};

Exemplo 2: Criação de um registro que agrupa características de uma conta bancária.

struct Conta{ // tipo de dado Conta sendo criado
   int numero;
   char tipo;
   char titular[30];
   float saldo;
};

2 - Declaração de variáveis do tipo de dado registro

Depois de definir um novo tipo de dado, este pode ser usado para declarar variáveis de modo análogo a qualquer tipo simples.

Segue a sintaxe de declaração de uma varíável do tipo de dado registro:

tipoDeDadoRegistro nomeDaVariável;

Exemplo 1: Declaração de uma variável simples do tipo Funcionário

Funcionario funcionario; // Declara-se a variável funcionario do tipo Funcionario

A variável funcionario gasta os seguintes espaços de memória para armazenar todos os membros do registro: 4 bytes para codigo, 30 bytes para nome, 4 bytes para salario e 1 byte para sexo. Total: 39 bytes.

Exemplo 2: Declaração de um vetor do tipo Funcionario

Funcionario funcionarios[10]; /* Declara-se um vetor chamado funcionarios em que cada elemento é do tipo Funcionario */

O vetor funcionarios gasta os seguintes espaços de memória para armazenar todos os membros do registro: 10 vezes a quantidade para 1 funcionário (10 * 39). Total: 390 bytes.

3 - Acesso aos membros de um registro

Pelo fato de o registro conter várias informações, para acessar um campo individualmente é necessário indicar o nome da variável e o nome do campo desejado, separados pelo operador ponto.

Segue a sintaxe para acessar membros de um registro:

sintaxeAcessoCampoRegistro.jpg

Exemplo 1: Variável simples funcionario

Funcionario funcionario;
cout << funcionario.nome; // Imprime o nome do funcionário
cout << funcionario.nome[0]; // Imprime o primeiro caracter do nome do funcionário

Exemplo 2: Variável composta funcionarios

Funcionario funcionarios[10];
cout << funcionarios[9].nome; // Imprime o nome do último funcionário
cout << funcionarios[0].nome[0]; // Imprime o primeiro caracter do nome do primeiro funcionário

4 - Passando Variáveis do tipo Registro para Funções

Variáveis do tipo registro podem ser passados como parâmetro de funções da mesma maneira que foi trabalhado com as demais variáveis (simples, vetores ou matrizes).

4.1 - Passando variável simples do tipo de dado registro

Na função cadastra() do exemplo a seguir, o parâmetro deve ser passado por referência, pois deverá ocorrer atualização dos membros do registro após a sua chamada.

Já na função exibe(), o parâmetro pode ser passado por valor, pois não ocorrerá quaisquer modificações nos membros do registro. Entretanto, é importante frisar que no caso de registros que ocupam grande quantidade de memória, não é aconselhável utilizar a passagem de parâmetros por valor, pois ocorrerá cópias de todos seus membros na memória.

Observa-se que a criação do novo tipo de dado Funcionario foi global, ou seja, é visível por qualquer função definida no programa.

#include <iostream>
#include <cstdio>
using namespace std;
 
struct Funcionario
{
    int codigo;
    char nome[30];
    float salario;
    char sexo;
};
 
void cadastra(Funcionario &f);
void exibe(Funcionario f);
 
int main()
{
    Funcionario funcionario;
 
    cadastra(funcionario);
    exibe(funcionario);
 
    return 0;
}
 
void cadastra(Funcionario &f)
{
    cout << "Entre com o código: ";
    cin >> f.codigo;
    cout << "Entre com o nome: ";
    fflush(stdin);
    gets(f.nome);
    cout << "Entre com o salário: ";
    cin >> f.salario;
    cout << "Entre com o sexo: ";
    cin >> f.sexo;
 
}
void exibe(Funcionario f)
{
    cout << "\nCódigo: " << f.codigo;
    cout << "\nNome: " << f.nome;
    cout << "\nSalário: " << f.salario;
    cout << "\nSexo: " << f.sexo;
}

4.2 - Passando variável composta (vetor) do tipo de dado registro

A sintaxe de passar um vetor ou matriz de registros é semelhante a de passar vetor ou matriz de variáveis simples. Na chamada a uma função deve-se escrever apenas o nome do vetor ou matriz. No cabeçalho de definição da função declaram-se normalmente os vetores/matrizes de registros.

#include <iostream>
#include <cstdio>
using namespace std;
 
struct Funcionario
{
    int codigo;
    char nome[30];
    float salario;
    char sexo;
};
 
void cadastra(Funcionario f[]);
void exibe(Funcionario f[]);
 
int main()
{
    Funcionario funcionarios[10];
 
    cadastra(funcionarios);
    exibe(funcionarios);
 
    return 0;
}
 
void cadastra(Funcionario f[10])
{
    for(int i=0; i<10; i++)
    {
        cout << i+1 << "o. FUNCIONARIO\n";
        cout << "Entre com o código: ";
        cin >> f[i].codigo;
        cout << "Entre com o nome: ";
        fflush(stdin);
        gets(f[i].nome);
        cout << "Entre com o salário: ";
        cin >> f[i].salario;
        cout << "Entre com o sexo: ";
        cin >> f[i].sexo;
    }
}
void exibe(Funcionario f[10])
{
    for(int i=0; i<10; i++)
    {
        cout << i+1 << "o. FUNCIONARIO\n";
        cout << "\nCódigo: " << f[i].codigo;
        cout << "\nNome: " << f[i].nome;
        cout << "\nSalário: " << f[i].salario;
        cout << "\nSexo: " << f[i].sexo;
    }
}

4.3 - Funções que retornam um registro

Pode-se retornar um registro completo para outra função, como pode ser observado na função novaVenda() no exemplo a seguir.

#include <iostream>
using namespace std;
 
struct Venda{
   int quantPecas;
   float preco;
};
 
Venda novaVenda()
{
   Venda v;
   cout << "\nNova Venda\n";
   cout << "\nInsira o numero de peças: ";
   cin >> v.quantPecas;
   cout << "\nInsira o preço: ";
   cin >> v.preco;
   return v;
}
 
void listaTotalVendas(Venda &v1, Venda &v2)
{
   cout << "\nVenda Total\n";
   cout << "\nTotal de peças: " << (v1.quantPecas + v2.quantPecas);
   cout << "\nPreço Total: " << (v1.preco + v2.preco);
}
 
int main()
{
   Venda venda1, venda2;
   venda1 = novaVenda();
   venda2 = novaVenda();
   listaTotalVendas(venda1, venda2);
   return 0;
}

5 - Inicialização de variáveis do tipo registro

É possível inicializar uma variável do tipo registro de forma semelhante a uma matriz. Os valores a serem atribuídos a seus membros devem ser colocados na ordem em que foram definidos, separados por vírgulas e entre chaves.

struct Data{
   int dia;
   int mes;
   int ano;
};
Data natal = {25,12,2011};
Data aniversario = {12,8,2011};

6 - Atribuições entre registros

Uma variável do tipo registro pode ser atribuída à outra variável do mesmo tipo através de uma atribuição simples. Os valores de todos os membros de um registro são atribuídos aos membros de outro registro. Segue um exemplo.

struct Data{
   int dia;
   int mes;
   int ano;
};
 
Data anoNovo = {1, 1, 2012};
Data aniversarioCris = anoNovo;

Assim, os valores de aniversarioCris.dia, aniversarioCris.mes e aniversarioCris.ano serão, respectivamente: 1, 1 e 2012.

7 - Registros aninhados

Podem-se definir tipos de dados registro cujos membros são outros registros. No exemplo a seguir foi adicionado um membro do tipo Data chamado dtVenda ao registro Venda.

A variável v possui três membros, sendo que um deles é do tipo Data. Portanto, v.dtVenda é o nome de uma variável do tipo Data e, para acessar seus membros, deve-se aplicar o operador ponto.

#include <iostream>
#include <cstdio>
using namespace std;
 
struct Data{
   int dia;
   int mes;
   int ano;
};
struct Venda{
   int quantPecas;
   float preco;
   Data dtVenda;
};
int main()
{
   Venda v = {15, 130.50, {27, 5, 2011}};
 
   cout << "Quantidade de peças: " << v.quantPecas << endl
          << "Preço: " << v.preco << endl
          << "Data da venda: " << v.dtVenda.dia << "/" << v.dtVenda.mes << "/" << v.dtVenda.ano;
   return 0;
}

8 - Exercícios

1. Faça um programa modularizado utilizando registro que leia apenas uma conta bancária com as seguintes informações: número da conta, nome do cliente e saldo. Apresente esses dados na tela.

2. Modifique o programa anterior para realizar o cadastro de 100 contas, não podendo haver mais de uma conta com o mesmo número. Declare uma constante MAX_CONTAS com o valor 100 para facilitar a execução do programa, alterando seu valor para um número menor apenas para testes. Observação: o programa deverá continuar modularizado.

3. Altere o programa anterior criando o menu de opções a seguir e implementando cada uma das opções:
0. Sair
1. Cadastrar uma conta
2. Visualizar todas as contas
3. Mostrar informações da conta com maior saldo (caso haja mais de uma conta com saldo igual ao maior, mostrar todas)
4. Mostrar informações da conta com menor saldo
5. Excluir uma conta

Observação: o programa deverá continuar modularizado.

4. Veja os campos de alguns registros:

Professor (número de registro, nome, cod_título, total h/a semanal)
Título (cod_título, descrição, valor hora/aula)

Faça um programa que:

  • Crie uma função para cadastrar os títulos. Sabe-se que nessa escola existem cinco títulos;
  • Crie uma função para cadastrar os professores. Sabe-se que nessa escola trabalham 10 professores, e cada um deve estar associado a um título previamente cadastrado;
  • Crie uma função para mostrar a relação de professores, conforme a figura a seguir.
tabela.jpg

5. Faça um programa que manipule uma lista contendo informações sobre dez pacientes (nome do paciente, nome do médico, data de nascimento e sexo). Esse programa deverá implementar as seguintes funções:

1. Cadastrar pacientes
2. Mostrar pacientes em ordem de cadastramento
3. Mostrar pacientes em ordem crescente (ordenar pelo nome)
3. Mostrar pacientes em ordem decrescente (ordenar pelo nome)
5. Excluir pacientes individualmente
6. Excluir pacientes por médico

  • Os elementos poderão ser inseridos sem qualquer ordenação (deve ser utilizado um vetor; não poderão ser cadastrados mais de dez pacientes);
  • Quando a lista for mostrada em ordem crescente ou decrescente, deve ser utilizada alguma maneira para não destruir a ordem original de cadastramento;
  • Para realizar a exclusão de pacientes individualmente, deve ser informado o nome do paciente que se deseja excluir;
  • Para realizar a exclusão de pacientes por médico, deve ser informado o nome do médico cujos pacientes serão excluídos da lista.
Bibliography
1. MIZRAHI, V. V. Treinamento em Linguagem C++. 2 ed. São Paulo: Pearson Prentice Hall, 2006.
2. FARRER, Harry et al. Programação estruturada de computadores: algoritmos estruturados. 3 ed. Rio de Janeiro: Guanabara Dois, 2008.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License