Upload
phungnhan
View
220
Download
0
Embed Size (px)
Citation preview
Aula 9 Agregado Heterogêneo
Ponteiro
prof Leticia Winkler
1
Prof. Leticia Winkler 2
Agregado Heterogêneo Também conhecido como registro;
É uma coleção de campos que podem ser referenciados pelo mesmo nome.
Permite que informações relacionadas mantenham-se juntas.
A declaração de um registro define um tipo de dado
Informa ao computador o número de bytes que será necessário reservar para uma variável que venha a ser declarada como sendo desse tipo.
Prof. Leticia Winkler 3
Exemplo Suponha-se que se deseja manipular num programa os
seguintes dados do candidato para uma vaga numa empresa:
Inscrição: inteiro
Idade: inteiro
Sexo: caractere (F ou M)
Conceito: caractere (A, B, C, D ou e)
Poderia se criar o agregado heterogêneo Candidato que irá manter estas informações, que são relacionadas (de um candidato).
Prof. Leticia Winkler 4
Definição A forma de declaração de uma estrutura em C é:
struct (nome_da_estrutura) {
tipo nomeVar1;
tipo nomeVar2;
...
} variável_tipo_nomedaestrutura;
nome_da_estrutura e variável_tipo_nomedaestrutura são opcionais, porém uma delas deve ser declarada obrigatoriamente;
Cada elemento de uma struct é chamada de campo ou membro da struct ou ainda elementos.
Prof. Leticia Winkler 5
Exemplo struct Candidato {
int inscr;
int idade;
char sexo;
char conceito;
} cand;
Candidato é o nome do novo tipo de dado;
inscr, idade, sexo e conceito são membros (ou campos ou elementos) da struct Candidato.
cand é a variável que irá conter os valores dos dados de um candidato.
Prof. Leticia Winkler 6
Exemplo struct Data {
int dia;
int mes;
int ano;
};
Criado um novo tipo de dado chamado Data, cujos campos (ou membros) são dia, mes e ano
struct Produto {
int codigo;
char descricao[20];
float preco;
};
Criado um novo tipo de dado chamado Produto, cujos campos são codigo, descricao e preco
Prof. Leticia Winkler 7
• Após a declaração das structs, pode-se declarar variáveis do tipo Produto e do tipo Data
Declaração de Variáveis struct Produto varProd;
Alocado o espaço para armazenar dados de um produto e de uma data.
struct Data vData;
Alocado o espaço para armazenar dados de uma data.
Prof. Leticia Winkler 8
varProd
vData
typedef type definition.
Permite redefinir um tipo de dado dando-lhe um novo nome.
Sintaxe: typedef nomeTipo novoNomeTipo;
Exemplo: Deseja-se redefinir o tipo int para inteiro e também o tipo float para
decimal.
typedef int inteiro;
typedef float decimal;
O antigo tipo continua funcionando: int x;
inteiro y;
Prof. Leticia Winkler 9
typedef com struct Declarando a struct:
struct data {
int dia;
int mes;
int ano;
};
Declarando a variável:
struct data vData;
Declarando a struct:
struct data {
int dia;
int mes;
int ano;
} ;
Dando o nome ao tipo:
typedef struct data tipoData;
Declarando a variável:
tipoData vData;
Prof. Leticia Winkler 10
typedef com struct Declarando a struct e dando novo ao tipo definido:
typedef struct data {
int dia;
int mes;
int ano;
} tipoData;
Declarando a variável:
tipoData vData;
ou
struct data vData;
Prof. Leticia Winkler 11
Declaração de Variável na Definição
struct aluno {
int matricula;
char nome[40];
float media;
} alu1, alu2;
struct {
int matricula;
char nome[40];
float media;
} alu1, alu2;
Prof. Leticia Winkler 12
• Pode-se declarar variáveis na definição de uma struct, neste caso não é obrigatório dar nome a struct:
alu1 alu2
Observação struct data {
int dia;
int mes;
int ano;
} X;
X é uma variável do tipo struct data
typedef struct data {
int dia;
int mes;
int ano;
} X;
X é o nome do tipo struct data
Prof. Leticia Winkler 13
Acesso aos Membros da Struct Utiliza o operador ponto:
variável_tipo_nomedaestrutura.campo
Exemplo:
varProd.codigo = 123;
cout << varProd.preco;
Prof. Leticia Winkler 14
varProd
codigo descricao preco
Exemplo de Programa #include <iostream>
#include<cstdlib>
using namespace std;
struct aluno {
int matricula;
char nome[40];
float media;
};
int main() {
aluno x, y;
cout << "Digite os dados dos 2 alunos : " << endl << endl;
cout << "\nAluno 1 : " << endl;
cout << "Matricula ? "; cin >> x.matricula;
cout << "Media ? "; cin >> x.media;
cout << "Nome ? "; cin.get(); cin.getline(x.nome,40);
cout << "\nAluno 2 : " << endl;
cout << "Matricula ? "; cin >> y.matricula;
cout << "Media ? "; cin >> y.media;
cout << "Nome ? "; cin.get(); cin.getline(y.nome,40);
cout << "\n\nDados fornecidos : " << endl;
cout << "\nAluno 1 : " << endl;
cout << "Matricula = " << x.matricula << endl;
cout << "Media = " << x.media << endl;
cout << "Nome = " << x.nome << endl;
cout << "\nAluno 2 : " << endl;
cout << "Matricula = " << y.matricula << endl;
cout << "Media = " << y.media << endl;
cout << "Nome = " << y.nome << endl;
return 0;
}
Prof. Leticia Winkler 15
Manipulação entre Variáveis struct Supondo que foram declaradas 2 variáveis do tipo struct:
struct Produto prod1, prod2;
prod1.codigo = 123;
prod1.preco = 3.99;
É possível a atribuição de uma variável de um tipo struct em outra
do mesmo tipo struct:
prod2 = prod1;
Prof. Leticia Winkler 16
123 3.99
prod1
codigo descricao preco
prod2
codigo descricao preco
123 3.99
prod1
codigo descricao preco
123 3.99
prod2
codigo descricao preco
Manipulação entre Variáveis struct É possivel a comparação de variável do tipo struct
através dos operadores relacionais de igualdade e desigualdade apenas:
O uso dos demais operadores só é possível aplicado a um campo da struct:
Prof. Leticia Winkler 17
if (prod1 == prod2) { ... }
if (prod1 != prod2) { ... }
if (prod1 > prod2) { ... }
if (prod1.preco > prod2.preco) { ... } OK
Exemplo de Programa #include <iostream>
using namespace std;
struct Pessoa {
int idade;
char nome[51]; // string, ou seja vector de 51 caracteres para o nome:
};
int main () {
struct Pessoa pes1={15,"Paulo Silva"}, pes2={51,"Ana Silva"};
if (pes1.idade > pes2.idade)
cout << pes1.nome << " é mais velho(a) que " << pes2.nome << endl;
else
cout << pes2.nome << " é mais velho(a) que " << pes1.nome << endl;
return 0;
} Prof. Leticia Winkler 18
Vetor de struct Para manipular vários elementos de um tipo struct, pode-se declarar
um vetor.
Exemplo:
struct Produto vetProd[100];
Para acessar um membro de um elemento do vetor de struct:
vetProd[1].preco = 1.30; // o índice pertence ao vetor
Prof. Leticia Winkler 19
vetProd[0] vetProd[99]
...
vetProd[1]
vetProd[0] vetProd[99]
...
vetProd[1]
1.30
Exemplo de Programa #include <iostream>
#include<cstdlib>
using namespace std;
struct aluno {
int matricula;
char nome[40];
float media;
};
int const TAM=30;
int main() {
aluno v[TAM]; // declara vetor v de alunos
int i; // índice do vetor
cout << "Montando uma lista de alunos : " << endl;
for (int i = 0; i < TAM; i++) {
cout << "\nAluno " << i + 1 << " : " << endl;
cout << "Matricula ? "; cin >> v[i].matricula;
cout << "Media ? "; cin >>v[i].media;
cout << "Nome ? "; cin.get(); cin.getline(v[i].nome,40);
}
cout << "\n\nListando os alunos da lista criada : " << endl;
for (int i = 0; i < TAM; i++) {
cout << "\nAluno " << i + 1 << " : " << endl;
cout << "Matricula = " <<v[i].matricula << endl;
cout << "Media = " << v[i].media << endl;
cout << "Nome = " <<v[i].nome << endl;
}
cout << endl;
return 0;
}
Prof. Leticia Winkler 20
Exercício Faça um programa que leia os dados (matrícula e salário bruto) de 100
empregados de uma empresa e calcule e apresente a matricula e salário líquido, sabendo-se que: O salário líquido é calculado a partir do salário base, descontando-se o imposto de renda, de acordo com a tabela a seguir:
O salário base é obtido aplicando-se um desconto no salário bruto para o INSS, de acordo com a tabela a seguir, até o limite de R$ 406,09
Prof. Leticia Winkler 21
Base de cálculo mensal em R$ Alíquota % Parcela a deduzir do imposto em R$
Até 1.499,15 - -
De 1.499,16 até 2.246,75 7,5 112,43
De 2.246,76 até 2.995,70 15,0 280,94
De 2.995,71 até 3.743,19 22,5 505,62
Acima de 3.743,19 27,5 692,78
SALÁRIO-DE-CONTRIBUIÇÃO (R$) ALÍQUOTA PARA FINS DE RECOLHIMENTO AO INSS
até 1.107,52 8,00%
de 1.107,53 até 1.845,87 9,00%
de 1.845,88 até 3.691,74 11,00 %
Prof. Leticia Winkler 22
Ponteiro É uma variável que armazena o endereço de memória
de outra variável.
o valor contido num ponteiro indica onde uma informação está armazenada e não o que está armazenado.
Diz-se que o ponteiro “aponta” para a variável cujo endereço ele armazena.
Prof. Leticia Winkler 23
1002 ... D
ponteiro variável 1001 endereços: 1002 1003
Razões para uso de ponteiros Receber argumentos em funções que necessitem modificar
o argumento original; Manipular elementos de matrizes (vetor é um caso especial
de matriz); Passar strings (vetor de caracteres) de uma função para
outra; Criar estruturas de dados complexas, como listas
encadeadas e árvores binárias, onde um item deve conter referências à outro;
Alocar e liberar memória dinamicamente. O uso de ponteiro também dá uma maior velocidade no
processamento, já que o acesso à informação é feito diretamente à posição de memória.
Prof. Leticia Winkler 24
Declaração tipo_de dado *nome_do_ponteiro;
Exemplos:
int *pt;
char *temp,*pt2;
O asterisco indica que a variável é um ponteiro.
Após a declaração um ponteiro deve ser inicializado.
Prof. Leticia Winkler 25
Inicialização do Ponteiro – Operador & O ponteiro deve ser inicializado (apontado para algum
lugar conhecido) antes de ser usado.
Exemplo:
int num = 10;
int *pt;
pt = #
O & antes do nome de uma variável, dentro de um expressão indica endereço da variável
Não confundir com & antes do nome de uma variável numa declaração que indica referência (apelido) de uma variável.
Prof. Leticia Winkler 26
Operador Indireção ou Deferência Asterisco (*) Fornece o conteúdo da área apontada pelo ponteiro.
Exemplo:
int num = 10;
int *pt;
pt = #
cout << *pt; /* mostra o valor 10
mostra o valor da variável apontada por
pt – valor de num */
Prof. Leticia Winkler 27
Observações - Operador Asterisco (*) Supondo:
int x, y, z;
Produto:
z = x * y; // multiplicação entre as variáveis x e y
Declaração de um ponteiro:
int *p; // declaração de um ponteiro, chamado p, para um inteiro.
Conteúdo da variável apontada pelo ponteiro:
p = &x;
*p= 10; // a variável apontada por p recebe o valor 10 - x recebe 10
Prof. Leticia Winkler 28
Exemplo de Programa #include <iostream>
using namespace std;
int main (){
int num,val;
int *p;
num=50;
p = # // O endereço de num é atribuído a p – p aponta para num
val = *p; // Variável val recebe o valor da variável num
cout << val << endl;
cout << "Endereco para onde o ponteiro aponta: " << p << endl;
cout << "Valor da variavel num: " << num << endl;
cout << "Valor da variavel apontada por p (que é num): " << *p << endl;
*p=100; // Alterando o valor de num através do ponteiro p
cout << "Novo valor de num: " << num << endl;
return 0;
}
Prof. Leticia Winkler 29
Saída do programa: 50 Endereco para onde o ponteiro aponta: 0xbfc2e414 Valor da variavel num: 50 Valor da variavel apontada por p (que é num): 50 Novo valor de num: 100
num
0xbfc2e414 ...
ponteiro
endereços: 0xbfc2e414 0xbfc2e413
Operações com Ponteiros Atribuição ... int *p, *q, x, y; ... x = 10; p = &x; // p aponta para x q = p; /* q aponta p/ o mesmo endereço que q ou seja, q aponta p/ x */ Observe que o comando q = p faz com que q aponte para o
mesmo lugar que p, o que é diferente de: *q=*p;
faz com que o conteúdo da posição apontada por p seja atribuído ao conteúdo da posição apontada por q.
Prof. Leticia Winkler 30
x
endereços
1001 1001
1005
... ... ...
q y p
1006 a 1009 1001 a 1004
Operações com Ponteiros Incremento e Decremento Quando um ponteiro é incrementado, ele passa a apontar para a
próxima posição de memória,
Quando é decrementado passa a apontar para posição anterior.
Suponha que um ponteiro aponta para um vetor e é incrementado:
int vet[5], *p;
p = &vet[0]; // p aponta para o primeiro elemento do vetor
Prof. Leticia Winkler 31
p
2344 a 2347 2348 a 234b 234c a 234f 2350 a 2353 2354 a 2357
p
2344 a 2347 2348 a 234b 234c a 234f 2350 a 2353 2354 a 2357
p++;
Operações com Ponteiros Incremento e Decremento
p=p+2;
p--;
Observe que operações aritméticas com ponteiros mudam a posição de memória para onde o ponteiro aponta, ou seja, não são operações com o conteúdo das variáveis para as quais eles apontam.
Prof. Leticia Winkler 32
20 15 5 40 10
p
20 15 5 40 10
p
20 15 5 40 10
p
Operações com Ponteiros Adição e Subtração Tem resultado semelhante ao incremento e
decremento – movem o ponteiro.
Exemplo:
...
int vet[5], *p;
...
p = &vet[0]; // p aponta para o primeiro elemento do vetor
Prof. Leticia Winkler 33
20 15 5 40 10
p
Operações com Ponteiros Adição e Subtração
p = p + 3;
p = p - 2;
Prof. Leticia Winkler 34
20 15 5 40 10
p
20 15 5 40 10
p
20 15 5 40 10
p
Operações com Ponteiros Comparação Operadores == e !=
Informam se dois ponteiros apontam para mesma posição de memória
p == q true
p = &y
p != q true
Prof. Leticia Winkler 35
x
endereços
1001 1001
1005
... ... ...
q y p
2006 a 2009 1001 a 1004
x
endereços
1001 2006
1005
... ... ...
q y p
2006 a 2009 1001 a 1004
Operações com Ponteiros Comparação Operadores >, >=, < e <=
Informam se um ponteiro aponta para uma posição de memória mais alta do que a do outro
p=q;
p > q false
p=&y
q < p true
Prof. Leticia Winkler 36
x
endereços
1001 1001
1005
... ... ...
q y p
2006 a 2009 1001 a 1004
x
endereços
1001 206
1005
... ... ...
q y p
2006 a 2009 1001 a 1004
Porque definir tipo de dado para um ponteiro?
Devido às operações aritméticas com ponteiro
O ponteiro precisa saber quantos bytes se mover quando da execução de uma operação aritmética se um ponteiro do tipo int é incrementado, isto significa
que ele irá apontar para 4 bytes após a posição atual que ele aponta (já que um inteiro ocupa 4 bytes),
se o ponteiro é do tipo char, irá apontar para o byte seguinte (tamanho de um char é 1 byte) e assim por diante.
Operações aritméticas com ponteiros não alteram conteúdo da variável apontada pelo ponteiro.
Prof. Leticia Winkler 37
Operações Aritméticas em Variáveis através de seus Ponteiros Para realizar operações aritméticas em variáveis através
de seus ponteiros deve ser usado * (asterisco).
Exemplo: Para incrementar o conteúdo da variável apontada pelo
ponteiro p: ...
int x, *p;
x = 5;
p = &x;
(*p)++; // incrementando x
cout << x << endl; // será apresentado o valor 6
Prof. Leticia Winkler 38
5
p x
6
p x
Ponteiro e Vetor Um ponteiro pode se utilizado para manipular um vetor.
O primeiro passo é fazer o ponteiro apontar para o vetor:
...
int vet[5], *p;
...
p = &vet[0]; // p aponta para o primeiro elemento do vetor
ou
p = vet; // p aponta para o primeiro elemento do vetor
Prof. Leticia Winkler 39
50 40 30 20 10
50 40 30 20 10
p
Ponteiro e Vetor Acesso aos Elementos do Vetor O acesso a elementos de um vetor através de um
ponteiro pode ser feito usando o operador *.
int *p, vet[5]={10, 20, 30, 40, 50};
p = vet; // p aponta para o primeiro elemento do vetor
cout << *p << endl; // será apresentado o valor 10
...
Prof. Leticia Winkler 40
50 40 30 20 10
p
Ponteiro e Vetor Acesso aos Elementos do Vetor Um índices também pode ser usado juntamente com o
ponteiro, produzindo o mesmo resultado semelharte ao índice do vetor.
Exemplo: ...
cout << p[0]<< endl; // será apresentado o valor 10
cout << p[1]<< endl; // será apresentado o valor 20
cout << p[2]<< endl; // será apresentado o valor 30
cout << p[3]<< endl; // será apresentado o valor 40
cout << p[4]<< endl; // será apresentado o valor 50
cout << *p<< endl; // será apresentado o valor 10
Prof. Leticia Winkler 41
50 40 30 20 10
p
Ponteiro e Vetor Acesso aos Elementos do Vetor Quando o índice é usado com o ponteiro, o operador *
deixa de ser usado;
Observe que o ponteiro não é movido. Na realidade uma operação aritmética entre a posição do ponteiro e o índice é realizada. Assim: p[0] significa a posição do ponteiro + 0 elementos – posição com o
valor 10
p[2] significa a posição do ponteiro + 2 elementos – posição com o valor 30
Prof. Leticia Winkler 42
50 40 30 20 10
p
Ponteiro e Vetor Acesso aos Elementos do Vetor Deve-se ter cuidado quando se move o ponteiro e utiliza-se índice, pois
se o ponteiro não estiver apontando para o primeiro elemento do vetor, o índice com ponteiro não corresponderá ao elemento de mesmo índice com o vetor.
p = p + 2; // o ponteiro p é movido 2 elementos
// aponta para o terceiro elemento do vetor
Neste caso:
...
cout << *p << endl; // será apresentado o valor 30
cout << p[0] << endl; // será apresentado o valor 30
cout << p[1] << endl; // será apresentado o valor 40
cout << p[2] << endl; // será apresentado o valor 50
cout << p[3] << endl; // ERRO - for a do vetor
Prof. Leticia Winkler 43
50 40 30 20 10
Usando o Ponteiro para Manipular o Vetor #include <iostream> #include <stdlib.h> using namespace std; int main(void){ float vet[10], *p; p = vet; /* p aponta p/ o primeiro elemento do vetor */
// solicita digitacao de cada elemento do vetor cout << "Digite os elementos do vetor:\n" ; for (int i=0; i<10; i++) { cout << "Elemento " << i << "? "; cin >> *p; p++; // p aponta para o próximo elemento do vetor } p = vet; // voltando com p p/ o primeiro elem. do vetor // mostrando o conteudo do vetor cout << "\nConteudo do vetor\n"; for (int i=0; i<10; i++){ cout << *p << endl; p++; } cout << endl; return 0; }
Prof. Leticia Winkler 44
Usando o Ponteiro com Índice para Manipular o Vetor #include <iostream> #include <stdlib.h> using namespace std; int main(void){ float vet[10], *p; p = vet; /* p aponta p/ o primeiro elemento do vetor */
// solicita digitacao de cada elemento do vetor cout << "Digite os elementos do vetor:\n" ; for (int i=0; i<10; i++) { cout << "Elemento " << i << "? "; cin >> p[i]; } // mostrando o conteúdo do vetor cout << "\nConteudo do vetor\n"; for (int i=0; i<10; i++){ cout << p[i] << endl; } cout << endl; return 0; }
Prof. Leticia Winkler 45
Ponteiro e struct Supondo a struct Produto:
struct Produto{
int cod;
float preco;
};
Supondo a declaração:
struct Produto prod, *pProd;
Inicializando o ponteiro:
pProd = ∏
Prof. Leticia Winkler 46
Acesso a struct através de um Ponteiro Utiliza-se o operador seta
nomePonteiroStruct -> membro;
Exemplo:
cout << pProd -> preco; // mostra o membro preco da posição
de memória apontada por pProd
Prof. Leticia Winkler 47
... ... ... ...
cod preco
prod
pProd
Vetor de struct com Ponteiro Um também ponteiro pode se utilizado para manipular um vetor de
struct.
struct Produto vetProd[3], *pProd;
Fazendo o ponteiro apontar para o vetor:
pProd = vetProd;
Ou
pProd = &vetProd[0];
Prof. Leticia Winkler 48
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
pProd
Vetor de struct com Ponteiro
As operações aritméticas com ponteiro para um vetor de struct também movimentam o ponteiro sobre os elementos do vetor: pProd = pProd + 2;
Prof. Leticia Winkler 49
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
pProd
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
pProd
Vetor de struct com Ponteiro
pProd-=2;
Prof. Leticia Winkler 50
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
pProd
... ... ...
vetProd
cod preco cod preco cod preco
0 1 2
pProd
Acesso ao Vetor de struct através de Ponteiro
Usando o operador -> (seta): cout << pProd ->cod; // mostra o valor 10
Usando índice: cout << pProd[2].preco; // mostra o valor 0.75 O índice pertence ao vetor Para o índice com ponteiro coincidir com o índice do vetor, o ponteiro deve estar
apontando para o primeiro elemento do vetor Com índice o operador volta a ser o . (ponto).
Prof. Leticia Winkler 51
... ... ...
vetProd
0.50 10
cod preco
1.23 20
cod preco
0.75 18
cod preco
0 1 2
pProd
Exemplo Vetor de struct com ponteiro #include <iostream> using namespace std; int const tam=3; struct Produto{ int cod; float preco; }; int main(){ struct Produto vetProd[tam], *pProd, *pIni; pIni = pProd = vetProd;
cout << "Digite os dados dos " << tam << " produtos:\n"; for (int i=0; i<tam; i++){ cout << "Código? "; cin >> pProd->cod; cout << "Preço? "; cin >> pProd->preco; // reajustando o preço em 4,3% pProd->preco *= 1.043; pProd++; } pProd = pIni; cout << "\n\n\n*** Produtos ***\n\n"; for (int i=0; i<tam; i++){ cout << "Código: " << pProd->cod << endl; cout << "Preço..: " << pProd->preco << "\n\n"; pProd++; } return 0; }// fim da main
Prof. Leticia Winkler 52
Exemplo Vetor de struct com ponteiro (usando índice) #include <iostream> using namespace std; int const tam=3; struct Produto{ int cod; float preco; }; int main(){ struct Produto vetProd[tam], *pProd; pProd = vetProd;
cout << "Digite os dados dos "<<tam<<" produtos:\n"; for (int i=0; i<tam; i++){ cout << "Código? "; cin >> pProd[i].cod; cout << "Preço? "; cin >> pProd[i].preco; // reajustando o preço em 4,3% pProd[i]. preco *= 1.043; } cout << "\n\n\n*** Produtos ***\n\n"; for (int i=0; i<tam; i++){ cout << "Código: " << pProd[i].cod << endl; cout << "Preço..: " << pProd[i].preco << "\n\n"; } return 0; }// fim da main
Prof. Leticia Winkler 53
Exercício Altere o exemplo do exercício anterior e crie um
ponteiro para manipular o vetor de struct Empregado
Prof. Leticia Winkler 54