Você está na página 1de 13

Cap.

9:
Estruturas (Structs)

Tipos de dados compostos III

Sumário
 Revisitação à taxonomia de tipos de dados
 Características gerais de tipos de dados compostos
 Estruturas: motivação ou a razão de ser
 Definição de estrutura (struct)
 Declaração de estruturas
 Diagrama de sintaxe de estruturas
 Inicialização de estruturas
 Características específicas de estruturas
 Operadores de acesso a estruturas
 Operador de atribuição de estruturas
 Passagem de estruturas para funções
 Comparação entre a passagem de alinhamentos e passagem de estruturas
para funções
 Retorno de estruturas a partir de funções
 A categoria static de armazenamento de variáveis. 2

1
Revisitação à taxonomia
de tipos de dados
Tipos de Dados

void Tipos Simples Tipos Compostos

Tipos Tipos Tipos


Numéricos Apontadores Enumerados

* enum

array struct FILE


char int float double
3

Características gerais
dos tipos de dados compostos
 Definição pelo utilizador
Não pertencem ao léxico da linguagem
Requerem a utilização dum mecanismo sintáctico ou duma palavra
reservada ([ ], struct, FILE, ...)
 Composição
Têm valores compostos
Exemplo (clientes dum empresa):
CLIENTE x = {“Josefa Boavida”, “Rua do Vau, nº 2, 3500-089 Viseu”, 232456719};
CLIENTE y = {“Rui Silva”, “Rua da Pescada, nº 5, 1100-115 Lisboa”, 213445232};

 Não têm ordem


Um conjunto não tem ordem ou escala
Exemplo:
x < y
?
4

2
Estruturas (structs):
motivação
Quando há necessidade de guardar informação de vários tipos numa só
entidade (ou struct).

Exemplo:
No dia-a-dia das empresas e organizações há necessidade de introduzir,
alterar, eliminar e consultar dados em formulários (p.ex.: segurança social,
banca, finança, bolsa, arquivo de identificação, etc). Em geral, há três
dados comuns a todos estes sistemas de organização de informação:
 nome
 morada
 telefone
Em C (novo tipo de dados: CLIENTE):

typedef struct
{
char *nome;
char *morada;
long telefone;
} CLIENTE; 5

Estruturas (structs):
definição
 Definição
É uma colecção ou conjunto de elementos (ou variáveis) numa zona
contígua de memória.
Os elementos são variáveis usuais identificadas por nome.
Os elementos são também designados por campos, membros ou
componentes.
Ao contrário dos arrays:
os elementos não são necessariamente do mesmo tipo.
os elementos não são indexados.

struct CLIENTE
{ x.nome
char *nome; x.morada x
char *morada;
x.telefone
long telefone;
} x;

3
Estruturas (structs):
diagrama de sintaxe
 Diagrama de sintaxe

struct nome { tipo elemento1 } ;


tipo elemento1

tipo elementon

Estruturas (structs):
declaração de variáveis
☞ Definição de tipo de dados + ☞ Definição de tipo de dados +
declaração de variável (variáveis) declaração de variável (variáveis)
em instruções diferentes na mesma instrução

struct CLIENTE struct CLIENTE


{ {
char *nome; char *nome;
char *morada; char *morada;
long telefone; long telefone;
}; } x;

struct CLIENTE x;

4
Estruturas (structs):
declaração de variáveis (cont.)
☞ Definição de tipo de dados sem ☞ Definição de tipo de dados c/
nome+ declaração de variável typedef + declaração de variável
(variáveis) na mesma instrução (variáveis) em instruções
diferentes

struct typedef struct


{ {
char *nome; char *nome;
char *morada; char *morada;
long telefone; long telefone;
} x; } CLIENTE;

CLIENTE x;

Estruturas (structs):
inicialização de variáveis
 Inicialização
É feita da mesma forma que a dos arrays.

typedef struct
{
char *nome;
char *morada;
long telefone;
} CLIENTE;

Exemplo (declaração dum cliente c/ inicialização):


CLIENTE x = {“José Boavida”, “Rua do Vau, nº 2, 3500-089 Viseu”, 232456719};

10

5
Estruturas (structs):
características específicas
 Contiguidade
Ocupa uma zona contígua de memória

 Não são homogeneamente tipadas


As componentes podem ter tipos diferentes de dados
Exemplo (clientes):
CLIENTE x = {“Josefa Boavida”, “Rua do Vau, nº 2, 3500-089 Viseu”, 232456719};
CLIENTE w;

 Acesso por identificador


Cada componente tem um identificador
Exemplo:
w.nome = “Carlos Ribeiro”;
w.telefone = x.telefone;
Acesso para Acesso para
escrita leitura

11

struct CLIENTE
{
Estruturas (structs): char *nome;
char *morada;

operadores de acesso
long telefone;
};

Operador . Operador →

(Ponteiro para uma struct)


struct CLIENTE x; struct CLIENTE *x;

x.nome = “Joaquim Mira”; x→nome = “Joaquim Mira”;


x.morada = “R. Ag.Cima, 2, x→morada = “R. Ag.Cima, 2,
2456-001 Águeda”; 2456-001 Águeda”;
x.telefone = 239675413; x→telefone = 239675413;

struct CLIENTE *x;

(*x).nome = “Joaquim Mira”;


(*x).morada = “R. Ag.Cima, 2,
2456-001 Águeda”;
(*x).telefone = 239675413;
12

6
struct CLIENTE
{
Estruturas (structs): char *nome;
char *morada;
operador de atribuição };
long telefone;

struct CLIENTE x, y;

// a atribuição pode ser feita campo a campo

x.nome = “Joaquim Mira”;


x.morada = “R. Ag. Cima, 2,
2456-001 Águeda”;
x.telefone = 239675413;

y.morada = x.morada;

// mas, ao contrário dos arrays,


// também pode ser feita entre estruturas

y = x;
x = *(&y);
13

Exemplo:
#include<stdio.h>
main(){
struct CLIENTE {
char *nome;
char *morada;
long telefone;
};
struct CLIENTE x, y;
x.nome = "Joaquim Mira";
x.morada = "R. Ag.Cima, 2, 2456-001 Agueda";
x.telefone = 239675413;
y=x;
printf("Nome: %s\n",y.nome);
printf("Morada: %s\n",y.morada);
printf("Tel.: %d\n", y.telefone);
}

OUTPUT: Nome: Joaquim Mira


(ecrã) Morada: R. Ag.Cima, 2, 2456-001 Agueda
Tel.: 239675413 14

7
Passagem de estruturas para
funções
O método escolhido determina que operador (. ou →) deve
ser usado no corpo da função para aceder aos membros
da estrutura:

Passagem por cópia de valor da estrutura

Passagem por cópia de valor de endereço da estrutura

15

Exemplo: passagem por cópia


de valor de estrutura
#include <stdio.h>
typedef struct {
float x;
float y;
} VECTOR;

float produtoInterno(VECTOR, VECTOR);

main(){
VECTOR p = {5.0,10.0};
VECTOR q = {6.0,9.0}; main
float p_q; p_q p q
p_q = produtoInterno(p,q);
printf(“Poduto interno = %f”,p_q);
} float a b
produtoInterno
float produtoInterno(VECTOR a, VECTOR b){
return (a.x * b.x + a.y * b.y);
} 16

8
Exemplo: passagem por cópia
de valor de endereço de estrutura
#include <stdio.h>
typedef struct {
float x;
float y;
} VECTOR;

float produtoInterno(VECTOR*, VECTOR*);

main(){
VECTOR p = {5.0,10.0};
VECTOR q = {6.0,9.0}; main
float p_q;
p_q = produtoInterno(&p,&q); p_q &p &q
printf(“Poduto interno = %f”,p_q);
}
float a b
float produtoInterno(VECTOR *a, VECTOR *b) produtoInterno
{
return (a->x * b->x + a->y * b->y);
17
}

Comparação entre passagem de


arrays e passagem de estruturas
para funções
Passagem de estruturas
alternativa 1: passa-se o nome da estrutura, o que implica a cópia do
conteúdo da estrutura para uma estrutura local da função.
alternativa 2: passa-se o endereço da estrutura para uma variável
apontadora que é local à função.

Passagem de arrays:
alternativa 1: não existe!!! Não é possível copiar ou passar o
conteúdo dum array para um array local duma função. De facto, ao
passar o nome do array, não é feita a cópia do conteúdo do array,
mas sim a cópia do endereço do array.
alternativa 2: passa-se o endereço do array (i.e. do primeiro
elemento), mas como o compilador interpreta o nome do array como
apontador para si próprio, basta escrever o nome do array (sem
índice).

18

9
Exemplo: passagem de estruturas
e passagem de arrays
ESTRUTURAS:
// RECEBE CÓPIAS DE 2 ESTRUTURAS
float produtoInterno(VECTOR a, VECTOR b);

// RECEBE CÓPIAS DE 2 ENDEREÇOS PARA ESTRUTURAS


float produtoInterno(VECTOR *a, VECTOR *b);

ARRAYS:
// RECEBE CÓPIAS DE 2 ENDEREÇOS DE ARRAYS
float produtoInterno(float a[], float b[]);

// RECEBE CÓPIAS DE 2 ENDEREÇOS DE ARRAYS


float produtoInterno(float *a, float *b);

19

Exemplo: passagem por cópia


de valor de endereço de array
#include <stdio.h>
float produtoInterno(float a[], float b[]);

main(){
float p[2] = {5.0,10.0};
float q[2] = {6.0,9.0};
float p_q; main
p_q = produtoInterno(p,q); p_q p q
printf(“Produto interno = %f”,p_q);
}
float a b
float produtoInterno(float a[], float b[]) produtoInterno
{
return (a[0] * b[0] + a[1] * b[1]);
}

20

10
Exemplo equivalente: passagem
por cópia de valor de endereço
de array
#include <stdio.h>
float produtoInterno(float *a, float *b);

main(){
float p[2] = {5.0,10.0};
float q[2] = {6.0,9.0};
float p_q; main
p_q = produtoInterno(p,q); p_q p q
printf(“Poduto interno = %f”,p_q);
}
float a b
float produtoInterno(float *a, float *b) produtoInterno
{
return (a[0] * b[0] + a[1] * b[1]);
}

21

Retorno duma estrutura


a partir duma função
O retorno ou saída duma estrutura :
alternativa 1: retorna-se o nome da estrutura, o que implica a
cópia da estrutura local da função para uma estrutura local da
função invocadora (p.ex. main).
alternativa 2: retorna-se o endereço da estrutura local à função
para uma variável apontadora que é local à função invocadora
(p.ex. main).

22

11
Exemplo: retorno por cópia
de valor de estrutura
#include <stdio.h>
typedef struct {
float x;
float y;
} VECTOR;
VECTOR soma(VECTOR, VECTOR);
main
main(){ s p q
VECTOR p = {5.0,10.0};VECTOR q = {6.0,9.0};
VECTOR s;
s = soma(p,q); VECTOR a b
printf(“Vector soma = {%f,%f}”,s.x, s.y); soma
}
VECTOR soma(VECTOR a, VECTOR b){
VECTOR vs;
vs.x = a.x + b.x;
vs.y = a.y + b.y;
return vs;
} 23

Exemplo: retorno por cópia


de valor de endereço de estrutura
#include <stdio.h>
typedef struct {
float x;
float y;
} VECTOR;
VECTOR *soma(VECTOR, VECTOR);
main
main(){ s p q
VECTOR p = {5.0,10.0};VECTOR q = {6.0,9.0};
VECTOR *s;
s = soma(p,q); VECTOR* a b
printf(“Vector soma = {%f,%f}”,s->x, s->y); soma
}
VECTOR *soma(VECTOR a, VECTOR b){
static VECTOR vs;
vs.x = a.x + b.x;
vs.y = a.y + b.y;
return &vs;
} 24

12
Exemplo: array de estruturas
#include <stdio.h>
typedef struct
{
char *nome;
char *morada;
long telefone;
} CLIENTE;

main(){
CLIENTE clientes[1000];
char nome[100];
printf(“Introduza o nome do cliente:\n”);
gets(nome); // fgets(nome, 100, stdin); //Para ler uma string

clientes[0].nome=nome;
printf(“Introduza o telefone do cliente:\n”);
scanf(“%d”, clientes[0].telefone);
...
printf(“Morada do cliente %d = %s\n”, i, clientes[i].morada);
} 25 FIM

13

Você também pode gostar