Aula 9 Agregado Heterogêneo Ponteiro prof Leticia Winklerlncc.br/~rogerio/ed/09 - Agregado...

Preview:

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 = &num;

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 = &num;

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 = &num; // 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 = &prod;

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

Recommended