Capítulo VII – Tipos Enumerativos e Estruturas 7.1 – Tipos enumerativos 7.2 – A necessidade de estruturas 7.3 – Manipulação dos campos de uma estrutura 7.4 – Campos alternativos 7.4 – Campos Alternativos 7.4.1 – Utilidade de campos alternativos Seja o cadastramento dos moradores de um prédio Para todo morador são registrados: o nome, o andar, o número do apartamento e a idade Conforme a idade, outras informações são registradas Morador: nome, andar, número do apartamento, idade Zero a 3 anos: número de mamadeiras tomadas por dia 4 a 11 anos: escolaridade, número de brinquedos que possui; 12 a 17 anos: escolaridade, número de livros que já leu, passatempo predileto 18 anos ou mais: escolaridade, profissão, se é ou não casado(a), caso seja casado(a), o nome do cônjuge e o número de filhos A seguinte struct poderia ser usada: struct morador { char Nome[30], Escolaridade[10], Passatempo[15], Profissao[15], NomeConjuge[30]; int andar, numapartamento, idade, numeromamadeiras, numbrinquedos, numlivros, numfilhos; logic casado; }; Nenhum morador usaria todos os campos: desperdício de memória Solução: Campos Alternativos Campos Alternativos: campos de uma variável que compartilham um mesmo espaço de memória A variável não será do tipo struct, mas sim do tipo union No exemplo dos moradores do prédio, o mesmo espaço de memória pode ser compartilhado por: nummamadeiras Escolaridade, numbrinquedos Escolaridade, numlivros, Passatempo Escolaridade, Profissao, casado, NomeConjuge, numfilhos nummamadeiras Escolaridade, numbrinquedos Escolaridade, numlivros, Passatempo Escolaridade, Profissao, casado, NomeConjuge, numfilhos Os campos desse espaço a serem utilizados dependem da idade do morador O tamanho total desse espaço é o maior dentre aqueles ocupados pelas quatro alternativas 7.4.2 – A declaração union Sejam as seguintes declarações: union valor { int valint; double valreal; char valchar; }; union valor val; Val A variável val é do tipo union valor Os campos valint, valreal e valchar compartilham o mesmo espaço de memória Então, essa variável pode guardar alternativamente, num dado momento, um inteiro, um real ou um caractere valint/valreal/valchar union valor { int valint; double valreal; char valchar; Val }; union valor val; valint/valreal/valchar O espaço por ela ocupado é o de um double, pois dentre os tipos dos três campos, double é o que ocupa maior espaço Tal como nas declarações enum e struct, a variável val poderia ser declarada das seguintes formas alternativas: union valor { int valint; double valreal; char valchar; } val; ou typedef union valor valor; union valor { int valint; double valreal; char valchar; }; valor val; typedef union valor valor; Val union valor {int valint; double valreal; char valchar;}; Exemplo: seja o trecho valor val; de programa à val.valint = 4455; esquerda valint/valreal/valchar printf ("1) valint = %d, valreal = %lf, valchar = %c", Os mesmos 8 bytes val.valint, val.valreal, val.valchar); (64 bits) estão val.valreal = 4455.68; sendo vistos de printf ("\n\n2) valint = %d, valreal = %lf, valchar = %c", formas diferentes val.valint, val.valreal, val.valchar); val.valchar = '*'; printf ("\n\n3) valint = %d, valreal = %lf, valchar = %c", val.valint, val.valreal, val.valchar); No vídeo 1) valint = 4455, valreal = 0.000000, valchar = g 2) valint = 343597384, valreal = 4455.680000, valchar = H 3) valint = 343597354, valreal = 4455.680000, valchar = * 7.4.3 – Estruturas com campos alternativos Campos alternativos são muitíssimo usados dentro de estruturas São frequentes os casos em que o valor de algum campo de uma estrutura determina quais os outros campos da mesma serem preenchidos em seguida Seja a seguir o exemplo visto dos moradores de um prédio Declarações dos tipos utilizados: cadastro Cad; // Cad é do tipo cadastro onde struct cadastro { int nmor; morador Moradores[10]; }; typedef struct cadastro cadastro; Moradores nmor morador morador morador morador morador morador morador morador morador morador Cad typedef struct morador morador; struct morador { char Nome[30]; int andar, nap, idade; infoadicionais InfoAdic; }; Moradores nmor morador morador morador morador morador morador morador morador morador morador Cad O tipo morador char - [30] int int int infoadicionais Nome andar nap idade InfoAdic O tipo morador char - [30] int int int infoadicionais Nome andar nap idade InfoAdic typedef union infoadicionais infoadicionais; union infoadicionais { infozeroa3 Info03; info4a11 Info411; info12a17 Info1217; info18oumais Info18; }; O tipo infoadicionais infozeroa3 / info4a11 / info12a17 / info18oumais Info03 / Info411 / Info1217 / Info18 O tipo infoadicionais infozeroa3 / info4a11 / info12a17 / info18oumais Info03 / Info411 / Info1217 / Info18 typedef struct infozeroa3 infozeroa3; struct infozeroa3 {int nmamads;}; O tipo infozeroa3 int nmamads typedef struct info4a11 info4a11; struct info4a11 {escolaridade esc; int nbrinq;}; O tipo info4a11 escolaridade int esc nbrinq O tipo infoadicionais infozeroa3 / info4a11 / info12a17 / info18oumais Info03 / Info411 / Info1217 / Info18 O tipo info12a17 escolaridade int char - [20] esc nlivros Passatempo typedef struct info12a17 info12a17; struct info12a17 { escolaridade esc; int nlivros; char Passatempo[20]; }; O tipo infoadicionais infozeroa3 / info4a11 / info12a17 / info18oumais Info03 / Info411 / Info1217 / Info18 O tipo info18oumais escolaridade char - [20] char - [30] esc Profissao Conjuge char int ehcasado nfilhos typedef struct info18oumais info18oumais; struct info18oumais { escolaridade esc; char Profissao[20], Conjuge[30]; char ehcasado; int nfilhos; }; A seguir, um programa completo #include <stdio.h> #include <stdlib.h> /* Declaracoes dos diversos tipos */ typedef enum escolaridade escolaridade; enum escolaridade {nenhuma, basica, media, superior}; typedef struct infozeroa3 infozeroa3; struct infozeroa3 {int nmamads;}; typedef struct info4a11 info4a11; struct info4a11 {escolaridade esc; int nbrinq;}; typedef struct info12a17 info12a17; struct info12a17 { escolaridade esc; int nlivros; char Passatempo[20]; }; typedef struct info18oumais info18oumais; struct info18oumais { escolaridade esc; char Profissao[20], Conjuge[30]; char ehcasado; int nfilhos; }; typedef union infoadicionais infoadicionais; union infoadicionais { infozeroa3 Info03; info4a11 Info411; info12a17 Info1217; info18oumais Info18; }; typedef struct morador morador; struct morador { char Nome[30]; int andar, nap, idade; infoadicionais InfoAdic; }; typedef struct cadastro cadastro; struct cadastro { int nmor; morador Moradores[10]; }; /* Cabecalho e declaracoes das variaveis */ int main () { cadastro Cad; int i; char c; /* Inicio da entrada de dados */ printf ("CADASTRO DE MORADORES DE UM PREDIO"); printf ("\n\nNumero de moradores: "); scanf ("%d", &Cad.nmor); for (i = 0; i < Cad.nmor; i++) { /* Leitura das informacoes comuns a cada morador */ printf ("\n\nMorador n.o %d:", i+1); printf ("\n\tNome: "); setbuf (stdin, NULL); gets (Cad.Moradores[i].Nome); printf ("\tAndar: "); scanf ("%d", &Cad.Moradores[i].andar); printf ("\tApto: "); scanf ("%d", &Cad.Moradores[i].nap); printf ("\tIdade: "); scanf ("%d", &Cad.Moradores[i].idade); /* Leitura das informacoes dos moradores com idade de zero a 3 anos */ if (Cad.Moradores[i].idade >= 0 && Cad.Moradores[i].idade <= 3) { printf ("\tNumero de Mamadeiras: "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info03.nmamads); } /* Leitura das informacoes dos moradores com idade de 4 a 11 anos */ else if (Cad.Moradores[i].idade >= 4 && Cad.Moradores[i].idade <= 11) { printf ("\tEscolaridade "); printf ("(0 - Nenhuma, 1 - Basica, 2 - Media, 3 - Superior): "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info411.esc); printf ("\tNumero de Brinquedos: "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info411.nbrinq); } /* Leitura das informacoes dos moradores com idade de 12 a 17 anos */ else if (Cad.Moradores[i].idade>=12 && Cad.Moradores[i].idade<=17) { printf ("\tEscolaridade "); printf ("(0 - Nenhuma, 1 - Basica, 2 - Media, 3 - Superior): "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info1217.esc); printf ("\tNumero de Livros Lidos: "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info1217.nlivros); printf ("\tPassatempo Predileto: "); setbuf (stdin, NULL); gets (Cad.Moradores[i].InfoAdic.Info1217.Passatempo); } /* Leitura das informacoes dos moradores com idade de 18 anos ou mais */ else { printf ("\tEscolaridade "); printf ("(0 - Nenhuma, 1 - Basica, 2 - Media, 3 - Superior): "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info18.esc); printf ("\tProfissao: "); setbuf (stdin, NULL); gets (Cad.Moradores[i].InfoAdic.Info18.Profissao); printf ("\tEh casado? (s/n): "); c = Cad.Moradores[i].InfoAdic.Info18.ehcasado = getche (); if (c == 's' || c == 'S') { printf ("\n\tNome do conjuge: "); setbuf (stdin, NULL); gets (Cad.Moradores[i].InfoAdic.Info18.Conjuge); printf ("\tNumero de Filhos: "); scanf ("%d", &Cad.Moradores[i].InfoAdic.Info18.nfilhos); } else printf ("\n"); } } /* Listagem das informacoes digitadas */ printf ("\nListagem dos Moradores:\n"); for(i = 0; i < Cad.nmor; i++) { /* Informacoes comuns */ printf("\n%d) Nome: %-21s; Andar: %4d; Apto: %5d; Idade: %4d", i+1, Cad.Moradores[i].Nome, Cad.Moradores[i].andar, Cad.Moradores[i].nap, Cad.Moradores[i].idade); /* Moradores de zero a 3 anos */ if (Cad.Moradores[i].idade >= 0 && Cad.Moradores[i].idade <= 3) { printf ("\n\tMamadeiras: %d;", Cad.Moradores[i].InfoAdic.Info03.nmamads); } /* Moradores de 4 a 11 anos */ else if (Cad.Moradores[i].idade >= 4 && Cad.Moradores[i].idade <= 11) { printf ("\n\tEscolaridade: %d; Brinquedos: %d", Cad.Moradores[i].InfoAdic.Info411.esc, Cad.Moradores[i].InfoAdic.Info411.nbrinq); } /* Moradores de 12 a 17 anos */ else if (Cad.Moradores[i].idade>=12 && Cad.Moradores[i].idade<=17) { printf ("\n\tEscolaridade: %d; Livros: %d; Passatempo: %s", Cad.Moradores[i].InfoAdic.Info1217.esc, Cad.Moradores[i].InfoAdic.Info1217.nlivros, Cad.Moradores[i].InfoAdic.Info1217.Passatempo); } /* Moradores de 18 anos ou mais */ else { printf ("\n\tEscolaridade %d; Profissao %s; Casado: %c;", Cad.Moradores[i].InfoAdic.Info18.esc, Cad.Moradores[i].InfoAdic.Info18.Profissao, Cad.Moradores[i].InfoAdic.Info18.ehcasado); c = Cad.Moradores[i].InfoAdic.Info18.ehcasado; if (c == 's' || c == 'S') { printf ("\n\tConjuge: %s, Filhos: %d", Cad.Moradores[i].InfoAdic.Info18.Conjuge, Cad.Moradores[i].InfoAdic.Info18.nfilhos); } } } /* Fechamento da tela */ printf ("\n\n"); system ("pause"); return 0; } Exercícios 7.4: 1) Seja o programa ao lado contendo estruturas e campos alternativos. Mostrar o que será escrito no vídeo pela sua execução. #include <stdio.h> #include <stdlib.h> typedef char str2[2]; typedef char str4[4]; struct ss {str2 x[4]; str4 y[2];}; typedef struct ss ss; typedef char str16[16]; typedef char str8[8]; union uu {ss a; str16 b; str8 c;} uniao; int main () { str16 palavra = "ABCDEFGHIJKLMNOP"; str8 numero = "12345678"; int i, j; for (i=0; i<16; i++) uniao.b[i] = palavra[i]; for (i=0; i<8; i++) uniao.c[i] = numero[i]; for (i=0; i<4; i++) { for (j=0; j<2; j++) printf ("%c%c", uniao.a.x[i][j], uniao.a.y[j][i]); printf ("\n"); } printf ("\n\n"); system ("pause"); return 0; }