Buscar

[INF1007] ResumoStruct

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Programação II 
Monitor: André Vicente Pessanha 
Resumo Struct: 
 
*************************************************************************************************** 
 
OBS:​ Essa matéria cai "somente" na P1, P2 e P3! :D 
 
************************************************************************************************** 
 
- Definição: 
 
 
Struct é uma nova forma de armazenar um conjunto de dados (variáveis) de modo muito 
mais organizado e prático. 
 
A grande vantagem é que em struct podemos armazenar variáveis de tipos diferentes! 
 
OBS:​ Lembrando que vetor e matrizes também permitem armazenar um conjunto de dados, 
mas somente de >> um único << tipo! (int, float, etc) 
 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
- Como se cria uma struct? (Parte 1: Protótipo) 
 
 
Antes de tudo precisamos criar um protótipo para a struct que é onde definimos o nome da 
struct e suas variáveis. 
 
São sempre informações (variáveis) compatíveis com o que queremos representar! Por 
exemplo, um ponto no plano cartesiano é representado pela coordenada x e y. Um aluno 
pode ser representado pelo seu nome e matrícula, etc. 
 
OBS:​ Não precisa se preocupar em criar o protótipo do zero! O próprio enunciado já te dá o 
protótipo pronto ou no mínimo do que se trata a struct(Aluno, ponto, pombo, etc) assim 
como uma breve descrição do que precisa ser armazenado.(Variáveis) 
 
OBS2: ​Risque "pombo" dos exemplos de struct. Pois é, eles invadem quando você menos 
espera. Haha 
 
 
 
 
 
 
 
 
Exemplo: Protótipo da struct ponto: 
 
 
struct ponto{ 
 float x; 
 float y; 
}; 
 
 
ponto é o nome da struct e float x, y são as variáveis que pertencem a essa struct. 
 
OBS:​ Notou o >> ; << no fim né? :) 
 
Coloque todos os protótipos de struct >> SEMPRE << no início do programa! Logo abaixo 
dos #include, pois dessa forma, todas as funções do seu programa vão poder usar a struct! 
 
OBS:​ Lembra que uma função só pode chamar outra função, se ela estiver definida acima 
da que chamou? 
 
Na dúvida é só lembrar da main, ela fica sempre lá embaixo, no final do programa, por isso 
ela pode chamar qualquer função do programa e com struct é o mesmo esquema! As 
funções só podem usar uma struct que esteja definida acima dela! 
 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
- Como se cria uma struct? (Parte 2: Variável da struct) 
 
Após criar o protótipo da struct: 
 
struct ponto{ 
 float x; 
 float y; 
}; 
 
int main (void){ 
 struct ponto p1; 
 
 p1.x = 5.0; 
 p1.y = 2.0; 
 
} 
 
 
 
Na main, "struct ponto" é o >>Tipo<< (Como se fosse int, float, etc) 
"p1" é o nome da variável da struct! (Como se fosse "float p1") 
Muito cuidado pra não confundir! 
 
struct ponto p1; 
 
Então sempre que precisamos criar uma variável de qualquer struct temos que escrever 
"struct >>nome da struct<< >>nome da variável<<" (Pelo menos por enquanto, já vou falar 
sobre typedef!) 
 
 
p1.x = 5.0; 
 
Pra alterar ou acessar o conteúdo da variável x temos que usar o conector > . < pra fazer 
a ligação entre a variável p1 e a variável x da struct. 
 
OBS:​ Essa parte é mais fácil de entender no Visual Studio, pois assim que você digita > p1. 
< aparece uma lista com as variáveis que pertencem a struct ponto, no caso, x e y! 
 
Então se você planeja usar o Visual Studio só uma vez no semestre...Aproveite e pelo 
menos veja esse detalhe! :D 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
 
- Como se cria uma struct? (Parte 3: Typedef) 
 
Typedef é como se fosse um atalho, um nome que é usado pra representar alguma struct. 
 
Imagina ter que escrever "Struct ponto" sempre que quiser criar alguma variável struct 
desse tipo? 
 
É nisso que o typedef salva! Pois criamos uma palavra pra substituir e representar o "struct 
ponto"! 
Tem várias formas de se usar o typedef, mas eu vou escrever aqui a forma que eu acho a 
ideal e é a mais curta também: 
 
typedef struct ponto{ 
 float x; 
 float y; 
}Ponto; 
 
Em outras palavras: typedef (substitua ou represente) o tipo "struct ponto" pela palavra > 
Ponto < ! Agora no resto do programa, vc pode usar sempre Ponto ao invés de struct ponto! 
 
OBS:​ >>SEMPRE<< coloque a primeira letra maiúscula em todos os typedef! Isso é 
justamente pra facilitar a visualização e diferenciar de uma variável comum! 
 
Ex: typedef struct aluno Aluno; typedef struct ponto Ponto; typedef struct notas Notas; 
 
OBS: ​Assim como nas macros (#define) que o recomendado é > sempre < usar palavras 
em maiúsculo! Isso é justamente pra diferenciar Macro de variável comum e de typedef de 
structs! 
 
Ex: #define MAX 10 #define NOTAS 3 
 
Dessa forma o programa fica mais organizado e se alguém de fora olhar o seu código, 
assim que ver uma variável começando com letra maiúscula, já vai sacar que se trata de 
uma struct! :) 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
- Leitura e impressão de struct: 
 
typedef struct ponto{ 
 float x; 
 float y; 
}Ponto; 
 
int main (void){ 
 Ponto p1, p2; 
 
 puts("Digite as coordendas do primeiro ponto:"); 
 scanf("%f%f", &p1.x, &p1.y); 
 puts("Digite as coordendas do segundo ponto:"); 
 scanf("%f%f", &p2.x, &p2.y); 
 
Se p1 e p2 são structs, então temos que usar o > . < pra acessar o conteúdo das variáveis x 
e y de cada uma delas. 
E como precisamos armazenar um valor, usamos o ' & ' . (Assim como em qualquer variável 
comum!) 
 
OBS:​ Apesar de ter o mesmo nome (x e y), são variáveis completamente diferentes para p1 
e p2! E não precisa se preocupar, o compilador sabe qual é a variável x e y de cada uma! 
 
 printf("Coordenadas de p1: (%.1f;%.1f)\n", p1.x, p1.y); 
 printf("Coordenadas de p2: (%.1f;%.1f)\n", p2.x, p2.y); 
 return 0; 
} 
 
A impressão é o mesmo esquema da leitura, mas sem o &! Sem mistério nenhum né? :) 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
- Enviar/ Receber struct como parâmetro: (Sem usar ponteiro!) 
 
 
typedef struct ponto{ 
 float x, y; 
}Ponto; 
 
Ponto lePonto (){ 
 Ponto novo; 
 
 puts("Digite as coordendas do ponto:"); 
 scanf("%f%f", &p1.x, &p1.y); 
 return novo; 
} 
 
void imprimePonto (Ponto p1){ 
 
 printf("Coordenadas do ponto: (%.1f;%.1f)\n", p1.x, p1.y); 
} 
 
int main (void){ 
 Ponto p1; 
 
 p1 = lePonto(); 
 imprimePonto(p1); 
 return 0; 
} 
 
 
OBS: ​Essa forma de solução é a mais básica de todas, usada >>Somente<< nos casos em 
que o enunciado disser que uma função retorna uma >>Estrutura<< ou uma função envia 
como parâmetro uma >>Estrutura<< (Observe que não estamos lidando com ponteiro 
ainda!) 
 
Vamos analisar por partes: 
 
Ponto lePonto (); 
 
Essa função retorna uma struct ponto, mas como já definimos o typedef lá em cima, 
podemos só escrever > Ponto < no tipo de retorno da função! Essa função lê as 
coordenadas de um novo ponto e o retorna. 
 
Se a função retorna uma struct ponto, precisamos armazenar numa variável de um tipo que 
seja compatível! p1 = lePonto(); 
 
OBS:​ Eu sempre recomendo nomear qualquer nova struct como "novo", justamente pra 
facilitar o entendimento que você tá criando uma nova variável de struct. Mas isso é 
completamente opcional. 
 
imprimePonto(p1); 
 
A função imprimePonto recebe uma struct ponto como parâmetro e você envia como se 
fosse uma variável comum! 
 
OBS:​ Assim como em Prog 1, se eu declarei uma variável chamada p1, enviei como 
parâmetro, o nome dela na função >>NÃO<<precisa ser o mesmo, pois se tratam de 
variáveis diferentes! 
 
void imprimePonto (Ponto p1) 
 
Ponto p1 é uma variável local da função imprimePonto (Nesse caso foi feito uma cópia do 
seu conteúdo e enviado para essa função), mas podíamos ter chamado de Ponto t1 por 
exemplo pra deixar claro que são variáveis diferentes! 
 
Mas pra não confundir, eu recomendo sempre usar sempre o mesmo nome! E isso vale pra 
passagem por referência também! (Ponteiro) 
 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
 
- Enviar/ Receber struct como parâmetro: (Usando ponteiro e alocação dinâmica!) 
 
 
typedef struct ponto{ 
 float x, y; 
}Ponto; 
 
Ponto * lePonto (){ 
 Ponto * novo; 
 
 novo = (Ponto *) malloc (sizeof(Ponto)); 
 if(!novo){ 
 puts("Erro! Sem memoria!"); 
 return NULL; 
 } 
 
 puts("Digite as coordendas do ponto:"); 
 scanf("%f%f", &p1->x, &p1->y); 
 return novo; 
} 
 
void imprimePonto (Ponto * p1){ 
 
 printf("Coordenadas do ponto: (%.1f;%.1f)\n", p1->x, p1->y); 
} 
 
int main (void){ 
 Ponto * p1; 
 
 p1 = lePonto(); 
 if(!p1) exit(1); 
 imprimePonto(p1); 
 free(p1); 
 return 0; 
} 
 
Analisando por partes: 
 
Ponto * lePonto () 
 
Dessa vez a função lePonto retorna um ponteiro para Ponto! Então o primeiro passo é 
alocar dinamicamente um novo Ponto. Lembrando que se caso não conseguir alocar, 
retornamos NULL pra representar um ponteiro Nulo! 
É na main (A função que fez a chamada) que verificamos se o ponteiro é Nulo ou não. Se 
for Nulo, não faz sentido continuar o programa e podemos encerrar com a função exit. 
 
if(!p1) exit(1); 
 
OBS:​ if(!p1) é o mesmo que if(p1 == NULL) 
 
E >>Nunca<< esqueça de devolver a memória alocada através da função free! 
 
free(p1); 
 
Percebe que enviamos o parâmetro da função imprimePonto como se fosse uma variável 
comum também? 
 
imprimePonto(p1); 
 
OBS:​ Agora em Prog 2, a partir daqui, vamos sempre criar variáveis que são ponteiros para 
algo! Lembra que em Prog 1 o único ponteiro que era criado dessa forma era o FILE *in de 
arquivo? Tirando essa exceção, a única forma de manipular ponteiro era declarando uma 
variável comum e enviando como parâmetro seu endereço para alguma função. 
 
Ex: (Ponteiro em Prog 1) Declaração: int lidos; 
Chamada de função: leArquivo(&lidos); 
 
OBS:​ Em alguns exercícios é necessário resolver dessa forma (Enviando o endereço de 
uma variável), mas no geral, principalmente em provas o que será cobrado é a nova forma 
de manipular ponteiros. 
 
Como declaramos Ponto *p1 que já é um ponteiro (Endereço de uma variável), basta enviar 
como parâmetro como se fosse uma variável comum também! Não precisa do '&'! 
 
imprimePonto(p1); 
 
 
OBS:​ Arquivo >>NÃO<< será cobrado em Prog 2! Sim, pois é! Muito triste né? D: 
 
 
novo = (Ponto *) malloc (sizeof(Ponto)); 
 
Queremos converter o retorno da função malloc para o tipo que precisamos, no caso, 
Ponteiro para Ponto. (Ponto *) 
E qual será o tamanho recebido como parâmetro pela malloc? Justamente o tamanho da 
própria struct! (sizeof (Ponto)) 
 
OBS: ​Se quiser uma explicação mais detalhada sobre como se usa a função malloc, assim 
como a sua prevenção de erro, é só dar uma lida no bloco "Resumo_AlocaçãoDinâmica". :) 
 
A grande diferença com ponteiro é o uso do conector setinha ( -> ) que será explicado logo 
adiante! 
 
 
 
*************************************************************************************************** 
 
Detalhe importantíssimo: (Recomendo nem piscar nessa parte! =D ) 
 
 
A partir de agora (Sim, exatamente agora!), antes de acessar o conteúdo de qualquer 
variável de qualquer struct, primeiro você vai se perguntar: 
 
"Isso é uma Estrutura ou um Ponteiro para Estrutura!?" 
 
Ponto p1 é uma Estrutura, então para acessar o conteúdo de x ou y, basta usar o conector 
> . < ! 
 
EX: p1.x ou p1.y 
 
Ponto *p1 é um Ponteiro para uma Estrutura!!! Então após alocar dinamicamente, 
acessamos o conteúdo de x ou y através do conector -> (Setinha!) 
 
EX: p1->x ou p1->y 
 
 
*************************************************************************************************** 
 
OBS: ​Esse tipo de solução será usado e cobrado em 99,57% das provas! >>SOMENTE<< 
nos casos em que o enunciado disser que uma função retorna ou envia como parâmetro um 
>> Ponteiro para uma Estrutura << (Nesse caso, um Ponteiro para Ponto!) 
No mesmo segundo que vc ler a palavra >>Ponteiro<< você já vai sacar que é pra usar a 
setinha, né? :) 
 
 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
 
- Struct definida a partir de outra struct: 
 
 
************************************************************************************************* 
 
OBS:​ Essa parte é importantíssima e com certeza será cobrado na P1! :O 
 
************************************************************************************************ 
 
É basicamente uma struct que em seu protótipo, possui variáveis de outras structs! 
 
Por exemplo: Vamor criar o protótipo de uma struct círculo que é composta pela coordenada 
do seu centro (Struct Ponto), um raio e os valores RGB que representam a cor do círculo 
(Struct Cor). 
 
typedef struct ponto{ 
 float x, y; 
}Ponto; 
 
typedef struct cor{ 
 int r, g, b; 
}Cor; 
 
typedef struct circulo{ 
 Ponto * centro; 
 float raio; 
 Cor * cor; 
}Circulo; 
 
OBS:​ Percebe que é >> obrigatório << definir o protótipo da struct ponto e cor antes da 
struct círculo? Pois ela depende da definição das outras! 
Lembra que só podemos chamar uma função que está definida acima da que fez a 
chamada? É exatamente a mesma ideia! 
 
Exemplo: Função que cria e retorna um novo círculo alocado dinamicamente e uma função 
que exibe as informações de um círculo: 
 
 
Circulo * criaCirculo (){ 
Circulo *novo; 
Ponto *p; 
Cor *c; 
 
p = (Ponto *) malloc (sizeof(Ponto)); 
if(!p){ 
puts("Erro! Nao conseguiu alocar o Ponto!"); 
return NULL; 
} 
c = (Cor *) malloc (sizeof(Cor)); 
if(!c){ 
puts("Erro! Nao conseguiu alocar a cor!"); 
return NULL; 
} 
novo = (Circulo*) malloc (sizeof(Circulo)); 
if(!novo){ 
puts("Erro! Nao conseguiu alocar o Circulo!"); 
return NULL; 
} 
 
OBS:​ Essa é a forma mais correta de se alocar várias coisas em sequência! 
 
************************************************************************************************* 
 
Mas existe uma forma mais simples: 
 
p = (Ponto *) malloc (sizeof(Ponto)); 
c = (Cor *) malloc (sizeof(Cor)); 
novo = (Circulo*) malloc (sizeof(Circulo)); 
if(!p || !c || !novo){ 
 puts("Erro! Sem memoria!"); 
 return NULL; 
} 
 
OBS:​ Primeiro aloca todos e depois só faz um único teste, se um deles for igual a NULL, 
encerra a função. O problema dessa solução é que imagina se não conseguimos alocar o 
ponto (primeira chamada do malloc), faz sentido tentar alocar os outros? 
 
Pois é, então apesar dessa solução ser bem menor que a outra, é um pouco arriscada. (Vai 
depender do critério de correção de cada professor) 
 
************************************************************************************************ 
 
puts("Coordenadas do Centro: "); 
scanf("%f%f",&p->x, &p->y); 
puts("Cores (RGB):"); 
scanf("%d%d%d", &c->r, &c->g, &c->b); 
puts("Raio: "); 
scanf("%f", &novo->raio); 
novo->centro = p; 
novo->cor = c; 
 
return novo; 
} 
 
OBS:​ Percebe que novo->centro é um ponteiro para Ponto? Por isso podemos atribuir ele a 
variável p que também é um ponteiro para Ponto! Mesmo esquema na atribuição da cor. 
 
void exibeCirculo (Circulo *c){ 
printf("Centro: (%.1f ; %.1f)\n",c->centro->x, c->centro->y); 
printf("Raio: %.1f\n", c->raio);printf("R: %d G: %d B: %d\n",c->cor->r, c->cor->g, c->cor->b); 
} 
 
************************************************************************************************ 
 
OBS:​ Notou que a quantidade de setinhas aumentou? :) 
 
c é um ponteiro para uma estrutura círculo, então a >> única << forma de acessar o 
conteúdo das suas variáveis é através da setinha. Mas centro é um ponteiro para Ponto, 
então como vamos fazer pra acessar as variáveis x e y? 
 
É só parar pra analisar, centro é um ponteiro para Ponto! Então vamos seguir a 
>>MESMA<< lógica e usar uma setinha pra acessar o conteúdo de suas variáveis! Por isso 
são duas setinhas, uma para cada ponteiro, até chegar onde queremos, o conteúdo de x ou 
y! 
 
OBS:​ Ficou em dúvida quando se usa setinha ou conector ponto? 
Sabia! Eu avisei pra não piscar, não foi? :D 
Só dar uma lida na parte "Detalhe importantíssimo!" na metade desse resumo. 
 
*********************************************************************************************** 
 
int main(void) { 
Circulo *c; 
 
c = criaCirculo(); 
if(!c) exit(1); 
exibeCirculo (c); 
free(c->centro); 
free(c->cor); 
free(c); 
return 0; 
} 
 
OBS:​ Muito cuidado pra não esquecer a prevenção de erro! Logo após chamar a função 
que cria e retorna algo alocado dinamicamente! 
 
OBS2:​ Percebe que primeiro dei free no c->centro que é o ponteiro para um ponto, depois 
free na c->cor que é o ponteiro para uma cor e >>SOMENTE NO FIM<< dei free no ponteiro 
do círculo! Lembra que um círculo depende de um ponto e uma cor? 
 
Então se der free no círculo antes, vamos perder as informações do ponto e da cor!!! Ou 
seja, dar free no círculo não significa dar free em tudo! Erro mais que fatal, muito cuidado! 
 
 
------------------------------------------------------- // ------------------------------------------------------------

Outros materiais