Baixe o app para aproveitar ainda mais
Prévia do material em texto
Estrutura de Dados A.3 Estrutura de dados (structs) Curso Sistemasde Informação Prof. Me. Bruno Siqueira da Silva bruno.siqueira@iffarroupilha.edu.br @B2S – version 2018.1 Definição “Estrutura de dados trata-se de um relacionamento lógico entre tipo de dados”. ● Uma estrutura (struct) ou registro em C é uma coleção de um ou mais valores (os valores podem ser heterogêneos = diferentes), agrupados sob um único nome. ● Estruturas constituem um recurso importante para organizar os dados utilizados por um programa graças à possibilidade de tratar um grupo de valores como uma única variável ● Por exemplo, para representar um aluno são necessáriasas informações nome, matrícula, conceito. Ao invés de criar três variáveis, é possível criar uma única variável contendo três campos. ● • Em C, usa-se a construção struct para representar esse tipo de dado 2 Representação • Exemplo: • Como representar as coordenadas de um Ponto no plano Cartesiano? • A estrutura deve conter dois inteiros, x e y. • Ponto (x, y) • OK! Como declaramos essa estrutura??? 3 Representação • a estrutura contém dois inteiros, int x e int y • p1 e p2 são duas variáveis tipo, como o objetivo de receber/conter duas coordenadas cada. • OK! Como declaramos uma estrutura??? 4 struct { int x; int y; } p1, p2; Declaração 5 struct nome_da_estrutura { tipo_1 dado_1; tipo_2 dado_2; ... tipo_n dado_n; } lista_de_variaveis; • A estrutura pode agrupar um número arbitrário de dados de tipos diferentes • Pode-se nomear a estrutura para referenciá-la rótulo da estrutura dados heterogêneos variáveis do mesmo tipo da estrutura Declaração: nomeando a Struct (não rotulada) 6 Declaração: Estrutura anônima (não rotulada) 7 ● O exemplo abaixo cria uma estrutura chamada de estrutura anônima. ● Esse tipo de estrutura não pode ser referenciada em outras partes do programa. struct { int dia; int mes ; int ano; } hoje; ○ Serve somente para declaração de variáveis do tipo da estrutura ● Não será possível declarar outras variáveis do mesmo tipo da variável hoje, p. ex. ● Para resolver isso deve-se declarar estruturas usando rótulos Declaração: Estrutura rotulada 8 struct ponto { int x; int y; }; struct funcionario { int registro; char nome[30]; char depto[5]; float salario; }; O rótulo dessas estruturas são ponto e funcionario e usa- se eles para declaração de variáveis Declaração: Estrutura rotulada 9 struct ponto { int x; int y; }; struct funcionario { int registro; char nome[30]; char depto[5]; float salario; }; O rótulo dessas estruturas são ponto e funcionario e usa- se eles para declaração de variáveis Declaração: Estrutura rotulada 10 struct ponto { int x; int y; }; struct funcionario { int registro; char nome[30]; char depto[5]; float salario; }; O rótulo dessas estruturas são ponto e funcionario e usa- se eles para declaração de variáveis ● As variáveis que fazem parte de uma estrutura são denominadas membros e são identificadas por nomes ● As declarações de ponto e funcionario, definem os respectivos tipos de dados, que podem ser utilizados em declarações de variáveis. Exemplos: struct ponto p1, p2, p3; struct funcionario Joao; ● Na primeira declaração, estão sendo declaradas as variáveis p1, p2 e p3 do tipo ponto. Na segunda declaração, é declarada a variável Joao do tipo funcionário. Declaração: Acesso aos dados da Struct 11 struct ponto { int x; int y; }; /*Exemplo de acesso */ p1.x = 10; /*atribuição */ p1.y = 20; /*atribuição */ p2.x = p1.x + 5; p2.y = p2.y + 5; ● Para uma variável do tipo ponto, dizemos que x e y são seus campos ou membros. Os campos de uma variável podem ser acessados individualmente como variáveis usando-se o nome da variável seguido de "." e o nome do campo. Declaração: Atribuição de Estruturas 12 • Inicialização de uma estrutura: struct ponto p1 = { 220, 110 }; • Atribuição entre estruturas do mesmo tipo: struct ponto p1 = { 220, 110 }; struct ponto p2; p2 = p1; /* p2.x = p1.x e p2.x = p1.y */ • Os campos correspondentes das estruturas são automaticamente copiados do destino para a fonte Declaração: Atribuição/Acesso às Estruturas 13 • Atenção para estruturas que contenham ponteiros: struct aluno { char *nome; int idade; } a1, a2; a1.nome = “Afranio”; a1.idade = 32; a2 = a1; • Agora a1 e a2 apontam para o mesmo string nome: a1.nome == a2.nome == “Afranio” Declaração: Composição das Estruturas 14 Os campos de uma estrutura podem ser de qualquer tipo? Declaração: Composição das Estruturas 15 Tipos suportados: Tipos simples/primitivos (int, char, float, etc.), vetores, ou até mesmo estruturas. struct retangulo { struct ponto inicio; struct ponto fim; }; struct retangulo r = { { 10, 20 }, { 30 , 40 } }; • Acesso aos dados: r.inicio.x += 10; r.inicio.y -= 10; Declaração: Composição das Estruturas 16 struct retangulo { struct ponto inicio; struct ponto fim; }; struct retangulo r = { { 10, 20 }, { 30 , 40 } }; • Acesso aos dados: r.inicio.x += 10; r.inicio.y -= 10; struct ponto { int x; int y; }; STRUCT ponto Declaração de valores iniciais 17 Ao declararmos uma estrutura, podemos também definir o seu valor inicial, de forma análoga a aquela utilizada para vetores. Exemplos: struct ponto origem = {0,0}; ... struct ponto trapezio[] = { { 5,5}, {5, 10}, {10,5}, {10,13} }; ... Exemplo de programa utilizando Struct 18 #include <conio.h> #include <stdio.h> // uma estrutura Pessoa struct Pessoa{ char *nome; int idade; }; int main() { // declara uma variável do tipo struct struct Pessoa cliente; cliente.nome = "Osmar J. Silva“; cliente.idade = 36; // obtém os dados printf("O nome do cliente e: %s\n", cliente.nome); printf("A idade do cliente e: %d\n", cliente.idade); return 0; } Pratique! 19 #include <conio.h> #include <stdio.h> // uma estrutura Pessoa struct Pessoa{ char *nome; int idade; }; int main() { // declara uma variável do tipo struct struct Pessoa cliente; cliente.nome = "Osmar J. Silva“; cliente.idade = 36; // obtém os dados printf("O nome do cliente e: %s\n", cliente.nome); printf("A idade do cliente e: %d\n", cliente.idade); return 0; } Agora é com vocês!!! Acrescente 3 tipos de dados para esta estrutura. Utilize: um vetor, um float e um ponteiro Crie 3 Pessoas e exiba na ordem em que foram criadas Copiando string 20 Como copiar uma string em C strcpy(destino, origem); Como Comparar uma string em C strcmp(s1, s2); http://www.cplusplus.com/reference/cstring/strcpy/ Estruturas rotuladas e nomeadas: typedef 21 ● É possível criar um tipo baseado em uma estrutura ■ Para isso utiliza-se typedef na declaração ● Para criar uma estrutura rotulada e nomeada pode-se usar Assim, DATA é um tipo. Podendo ser declarada uma variável: DATA d; Não há necessidade de uma struct tipo_data d; Forma mais comum de declarar struct tipo_data{ int dia, mes, ano; }; typedef struct tipo_data DATA; typedef struct tipo_data{ int dia, mes, ano; } DATA; Exemplo: 22 #include <stdio.h> int main(void){ typedef struct Data{ int dia, mes, ano; }; Data date; /* antes era assim struct Data date*/ date.ano = 2018; date.mes = 12; date.dia = 1; printf("Minha data: %d - %d - %d", date.dia, date.mes, date.ano); return 0;} Estruturas rotuladas e nomeadas: typedef 23 Estruturas auto-referenciadas ● Passagem de uma struct como parâmetro para função, i.e., o tipo de dado passado para a função é do tipo struct ● Recebe um registro como parâmetro e devolve o registro como resultado Exemplo 1: struct data{ int dia; int mes; int ano; }; void imprime(struct data d) { printf(“%d - %d - %d”, d.dia, d.mes, d.ano); } int main(){ struct data d; d.dia =10; d.mes = 12; d.ano = 1500; imprime(d); } Regra simples: struct <nome> é, para o C, um tipo tal qual int e float, e pode ser usado como os primitivos nas funções. 24 Estruturas auto-referenciadas Exemplo 2: struct pessoa{ char nome[100];int idade; pessoa *pai; }; typedef struct pessoa pessoa; main(){ pessoa joao, pedro; pessoa *p =&joao; strcpy(joao.nome, "joao da silva"); joao.idade = 20; strcpy(pedro.nome, "pedro da silva"); pedro.idade = 45; joao.pai = &pedro; printf("%s, %d\n", joao.pai->nome, joao.pai->idade); printf("%s, %d\n", p->pai->nome, p->pai->idade); } 25 Estruturas auto-referenciadas Exemplo 2: struct pessoa{ char nome[100]; int idade; pessoa *pai; }; typedef struct pessoa pessoa; main(){ pessoa joao, pedro; pessoa *p =&joao; strcpy(joao.nome, "joao da silva"); joao.idade = 20; strcpy(pedro.nome, "pedro da silva"); pedro.idade = 45; joao.pai = &pedro; printf("%s, %d\n", joao.pai->nome, joao.pai->idade); printf("%s, %d\n", p->pai->nome, p->pai->idade); } Se não fosse o operador -> ... printf("%s, %d\n", (*(*p).pai).nome, (*(*p).pai).idade); // no lugar de printf("%s, %d\n", p->pai->nome, p->pai->idade); 26 Estruturas e funções Exemplo 3: 27 Estruturas e funções: com retorno ● Retorno de uma struct a partir de uma função: struct tamanho{ int t; }; struct tamanho define(int valor){ struct tamanho a; a.t = valor; return a; } int main(){ struct tamanho a; a = define( 10 ); /* a recebe a struct resultante da função*/ printf(“%d”, a.t); /* vai imprimir 10 */ .... 28 Estruturas e funções: usando ponteiros struct data{ int dia; int mês; int ano; }; ● Definindo uma variável do tipo data struct data dt; ● Definindo um ponteiro para dt struct data *pdt=&dt; ● Fazendo referência a um elemento da estrutura dt.dia ou (*pdt).dia ou pdt->dia dt.mes ou (*pdt).mes ou pdt->mês dt.ano ou (*pdt).ano ou pdt->ano 29 Estruturas e funções: Passando structs por referência para funções - O operador -> Uma estrutura pode ser passada como parâmetro por referência numa função. Quando se usa uma referência (ponteiro), o acesso aos campos da mesma é feito através do operador “->” (seta) ao invés de “.” (ponto). Exemplo 1: void moveP(struct ponto* p, int dx, int dy){ p -> x += dx; p -> y += dy; } Observe o uso de -> ao invés de . Algumas implementações Pratique para não ter dúvidas 30 31 Passando structs por referência para funções - O operador -> #include<stdio.h> Typedef struct{ char modelo[30]; float potenciaMotor; int anoFabricacao, numPortas; }CARRO; void Exibe(CARRO car){ printf("\n\tExibindo carro\n"); printf("Modelo: %s\n",car.modelo); printf("Motor: %.1f\n",car.potenciaMotor); printf("Ano: %dn",car.anoFabricacao); printf("%d portas\n",car.numPortas); } void Preenche(CARRO* car){ printf("Modelo do carro: "); gets(car->modelo); printf("Motor: "); scanf("%f",&car->potenciaMotor); printf("Ano: "); scanf("%d",&car->anoFabricacao); printf("Numero de portas: "); scanf("%d",&car->numPortas); } int main(void){ CARRO fusca; Preenche(&fusca); Exibe(fusca); return 0; } 32 Apontando ponteiro para uma struct typedef struct{ char nome[100]; int idade; } pessoa; main(){ pessoa joao; pessoa *p =&joao; strcpy(joao.nome, "joao da silva"); joao.idade = 20; printf("%s, %d\n", (*p).nome, (*p).idade); (*p).idade = 18; printf("%s, %d\n", joao.nome, joao.idade); } Operador -> substitui (*p).Ponteiro para estrutura typedef struct{ char nome[100]; int idade; } pessoa; main(){ pessoa joao; pessoa *p =&joao; strcpy(joao.nome, "joao da silva"); joao.idade = 20; printf("%s, %d\n", p->.nome, p->.idade); p->.idade = 18; printf("%s, %d\n", joao.nome, joao.idade); } 33 Como escrever e ler elementos de uma struct em C Exemplo: Struct Aluno que armazena o nome e exibe média #include<stdio.h> Int main(void){ struct Alunos{ char nome[30]; float matematica, fisica, media; }; Struct Alunos alunos[5]; Int count; for(count = 0 ; count<5 ; count++){ fflush(stdin); printf("\nNome do aluno%d:", count+1); gets(alunos[count].nome); printf("Nota de matematica:"); scanf("%f",&alunos[count].matematica); printf("Nota de fisica:"); scanf("%f",&alunos[count].fisica); alunos[count].media = (alunos[count].matematica + alunos[count].fisica)/2; } printf("\nExibindo nomes e medias:\n"); for(count = 0 ; count<5 ; count++){ printf("\nAluno%d\n", count+1); printf("Nome:%s\n",alunos[count].nome); printf("Media:%.2f\n", alunos[count].media); } return 0; } Alocação dinâmica em C 34 35 Alocação dinâmica em C ● Permite solicitar memória em tempo de execução ● Função para alocar memória (stdlib.h): malloc(num_bytes) – Retorna o endereço de memória da região alocada – Retorna zero se não for possível alocar ● Função para liberar a memória (stdlib.h): free(endereco_regiao_alocada) – A região fica disponível para outras variáveis/alocações ● A alocação dinâmica de uma struct é feita exatamente igual ao demais tipos ● Única diferença é usar o sizeof adequando-o para o tipo struct ● E fazer o casting para um ponteiro para o tipo struct 36 Alocação dinâmica em C: exemplo main(){ // alocando um inteiro int *p = (int*) malloc(sizeof(int)); if (p){ *p = 3; printf("%d\n", *p); free(p); } } Casting p/ inteiro 37 Alocação dinâmica em C: exemplo main(){ // alocando um inteiro int *p = (int*) malloc(sizeof(int)); if (p){ *p = 3; printf("%d\n", *p); free(p); } } Casting p/ inteiro malloc (sizeof()) 38 Alocação dinâmica em C: exemplo main(){ // alocando um vetor com 3 inteiros int *v = (int*) malloc( 3 * sizeof(int) ); if (v){ v[0] = 10; v[1] = 20; v[2] = 30; printf("%d %d %d\n", v[0], v[1], v[2]); free(v); } } 39 #include <stdio.h> /*declaracao da estrutura*/ typedef struct tipo_data{ int dia, mes, ano; } DATA; int main (void) { DATA *d; d = (DATA *) malloc (sizeof (DATA)); d->dia = 31; d->mes = 12; d->ano = 2008; /* ou scanf("%d%d%d", &d->dia, &d->mes, &d->ano); */ printf("Data: %d / %d / %d \n", d->dia, d->mes, d->ano); free(d); return 0; } Alocação dinâmica: exemplo [1] com estrutura de dados (struct) 40 casting #include <stdio.h> /*declaracao da estrutura*/ typedef struct tipo_data{ int dia, mes, ano; } DATA; int main (void) { DATA *d; d = (DATA *) malloc (sizeof (DATA)); d->dia = 31; d->mes = 12; d->ano = 2008; /* ou scanf("%d%d%d", &d->dia, &d->mes, &d->ano); */ printf("Data: %d / %d / %d \n", d->dia, d->mes, d->ano); free(d); return 0; } Alocação dinâmica: exemplo [1] com estrutura de dados (struct) 41 casting sizeof Struct DATA #include <stdio.h> /*declaracao da estrutura*/ typedef struct tipo_data{ int dia, mes, ano; } DATA; int main (void) { DATA *d; d = (DATA *) malloc (sizeof (DATA)); d->dia = 31; d->mes = 12; d->ano = 2008; /* ou scanf("%d%d%d", &d->dia, &d->mes, &d->ano); */ printf("Data: %d / %d / %d \n", d->dia, d->mes, d->ano); free(d); return 0; } Alocação dinâmica: exemplo [1] com estrutura de dados (struct) 42 #include <stdio.h> /*declaracao da estrutura*/ typedef struct{ char nome[100]; int idade; } pessoa; main(){ // alocando uma estrutura pessoa *p = (pessoa*) malloc(sizeof(pessoa)); if (p){// verifica se p foi alocado em memória... p->idade = 3; printf("%d\n", p->idade); free(p); } } Alocação dinâmica: exemplo [2] com estrutura de dados (struct) 43 • A função realloc (stdlib.h) permite modificar o tamanho de uma região alocada, conservando os dados previamente armazenados • No caso de uma aumento de tamanho, realloc tenta utilizar bytes adjacentes à região já alocada • Caso não seja possível, uma nova região é alocada, e os dados armazenados na antiga região são copiados Modificando o tamanho da região alocada 44 main(){ int *v = (int*) malloc( 3 * sizeof(int) ); if (v){ v[0] = 10; v[1] = 20; v[2] = 30; printf("%d %d %d\n", v[0], v[1], v[2]); v = (int*) realloc(v, 4 * sizeof(int) ); if (v){ v[3] = 40; printf("%d %d %d %d\n", v[0], v[1], v[2], v[3]); free(v); } } } Modificando o tamanho da região alocada 45 ● Para implementar um Tipo Abstrato de Dados em C, usa-se a definição de tipos juntamente com a implementação de funções que agem sobre aquele tipo. ● Como boa regra de programação, evita-se acessar o dado diretamente, fazendo o acesso sóatravés das funções. ○ Mas, diferentemente de C++ e Java, não há uma forma de proibir o acesso Estruturas: TAD em C 46 ● Uma boa técnica de programação é implementaros TADs em arquivos separados do programa principal - main.c ● Para isso geralmente separa-se a declaração e a implementação do TAD em dois arquivos. ○ NomeDoTAD.h : com a declaração ○ NomeDoTAD.c : com a implementação ● O programa ou outros TADs que utilizam o seu TAD devem dar um #include no arquivo.h Estruturas: TAD em C 47 ● Implemente um TAD ContaBancaria, com os campos número e saldo onde os clientes podem fazer as seguintes operações: I. Iniciar uma conta com um número e saldo inicial II. Depositar um valor III. Sacar um valor IV. Imprimir o saldo ● Adotando as recomendações de boas práticas, vamos criar 3 arquivos ○ ContaBancaria.h - a declaração da nossa TAD e cabeçalho das funções ○ ContaBancaria.c - a implementação da TAD e as funções ○ Main.c - programa principal Estruturas: Exemplo de TAD 48 // definição do tipo typedef struct { int numero; double saldo; } ContaBancaria; // cabeçalho das funções Inicializa (ContaBancaria *, int, double); void Deposito (ContaBancaria *, double); void Saque (ContaBancaria *, double); void Imprime (ContaBancaria); Estruturas: Exemplo de TAD – ContaBancaria.h 49 Estruturas: Exemplo de TAD – ContaBancaria.c #include <stdio.h> #include "Contabancaria.h" void Inicializa(ContaBancaria *conta, int numero, double saldo) { conta->numero = numero; conta->saldo = saldo; } void Deposito (ContaBancaria *conta, double valor) { conta->saldo += valor; } void Saque (ContaBancaria *conta, double valor) { conta->saldo -= valor; } void Imprime (ContaBancaria conta) { printf("Numero: %d\n", conta.numero); printf("Saldo: %f\n", conta.saldo); } 50 Estruturas: Exemplo de TAD – main.c #include <stdio.h> #include <stdlib.h> #include "ContaBancaria.h" int main (void){ ContaBancaria conta1; Inicializa(&conta1, 918556, 300.00); printf("\nAntes da movimentacao:\n"); Imprime(conta1); Deposito(&conta1, 50.00); Saque(&conta1, 70.00); printf("\nDepois da movimentacao:\n "); Imprime (conta1); system("PAUSE"); return(0); } 51 LISTA 1 – Exercício 1 Definir e declarar o registro cuja representação gráfica é dada a seguir 52 LISTA 1 – Exercício 2 Uma indústria faz a folha mensal de pagamentos de seus empregados/funcionários baseada no seguinte tabela: Construa um algoritmo que processe e emita para cada funcionário seu contracheque cujo o formato é dado a seguir: O salário de referência deverá ser lido previamente. O salário referente às horas extras é calculado acrescentando 30% ao salário-hora normal. O desconto do INSS é de 11% do salário bruto (salário correspondente às horas normais trabalhadas + salário correspondente às horas extras). Para o cálculo do salário, considerar que existem duas classes de funcionários, a classe 1, cujo salário é 1,3 vezes o salário de referência, e a classe 2, cujo salário é 1,9 vezes o salário de referência. 53 LISTA 1 – Exercício 3 Implemente uma TAD que cadastre o nome, a matrícula e duas notas de vários alunos. Em seguida imprima as informações de cada um deles. Saída desejada 54 LISTA 1 – Exercício 4 Implemente um novo TAD Banco que faça uso do TAD Conta Bancária para criar um conjunto de contas bancárias. O tipo do conjunto deve se chamar Contas e deve conter o número de contas existentes e um vetor de contas. As operações devem ser: – InicializaContas(Contas *cnt) /* Define o número de contas existentes como sendo 0.*/ – CriarNovasContas(Contas *cnt, int n); /* Cria n novas contas no conjunto de contas, solicitando ao usuário o saldo e definindo automaticamente o número da conta. */ – ImprimirContas(Contas *cnt); /* Imprime todas as contas existentes. */ – ZerarSaldoConta(Contas *cnt, int num); /* Dado o número num de uma conta, zera seu saldo. */ Observe que para criar o ZerarSaldoConta você deverá buscar a conta que tem um determinado número e retirar todo seu saldo. Para isso você deverá criar no TAD ContaBancarias duas novas funções: – VerificaNum (ContaBancaria cont, int num) /* Retorna 1 se a conta tiver o número num, e 0 se não tiver */ – ConsultaSaldo (ContaBancaria conta) /* Retorna o saldo da ContaBancaria Conta */ Explique por que estas funções devem estar no TAD Conta Bancária e não no TADBanco. 55 LISTA 1 – Exercício 5 Implemente um TAD Número Complexo – cada número possui os campos real e imaginário – Implemente as operações: • Atribui: atribui valores para os campos • Imprime: imprime o número da forma “R + Ci” • Copia: Copia o valor de um número para outro • Soma: Soma dois números complexos • EhReal: testa se um número é real Faça um pequeno programa para testar o seuTAD 56 Defina uma estrutura que irá representar grupos musicais (bandas). Essa estrutura deve conter o nome, que tipo de música ela toca, o número de integrantes e em que posição do ranking em que essa banda está dentre as suas 5 bandas favoritas. Crie um looping para preencher as 5 estruturas de bandas criadas no exemplo passado. Após criar e preencher, exiba todas as informações das bandas. Não se esqueça de usar o operador -> para preencher os membros das structs. Crie uma função que peça ao usuário um número de 1 até 5. Em seguida, seu programa deve exibir informações da banda cuja posição no seu ranking é a que foi solicitada pelo usuário. LISTA 1 – Exercício 6 Bibliografia • Estrutura de Dados, Nina Edelweiss e Renata Galante. • Estrutura de Dados e Algoritmos: Padrões de Projetos Orientados a Objetos com Java, Bruno R. Preiss. • Algoritmos: Teoria e Prática, Thomas H. Cormen. 57 My Bookmarks Página 48
Compartilhar