Saltar para o conteúdo

Programar em C/Estruturas

Origem: Wikilivros, livros abertos por um mundo aberto.
Esta página precisa ser reciclada (discuta).
Ao melhorá-la, você estará ajudando o Wikilivros.

As estruturas (structs) permitem com que possamos ter variáveis de vários tipos aglomerados sob o mesmo nome. E esse mesmo nome vai passar a ser um novo tipo de dados tal como o int ou float.

Mas o uso disto é que podemos ter valores que tenham alguma relação lógica, por exemplo guardar um int de idade e um string de nome. Isto pode ser atributos de uma pessoa. Ou seja podemos empacotar várias variáveis de vários tipos com o objetivo de representar o mundo real e dar um nome a essas variáveis todas.

Ao fazer isto criamos um tipo de dados da mesma forma como fazemos em relação ao int ou ao float.

Declarar uma estrutura

[editar | editar código-fonte]

A sintaxe é:


 struct <identificador> {
   <tipo>  campo_um   ; 
   <tipo>  campo_dois ;
 };

Aqui o tipo struct indica que vamos criar uma estrutura. O nome ou identificador pode ser alunos, família, etc . (têm de ser válidos identifiers) Não esquecer o ponto e vírgula “;” no fim da declaração. Campo_um e Campo_dois são variáveis membro – member variables – ou campo da estrutura.

Assim criamos novos tipos de dados.

Primeiro método:

 struct minha_estrutura
 {
   int  variavel_um;
   int  campo_dois;
   char  fruta[40];
 } ;

Aqui o identificador do tipo "struct" é "minha_estrutura" dentro dessa estrutura temos três campos o ultimo é "fruta"

Agora podemos usar esse tipo "struct" para definir variáveis.

struct minha_estrutura nova_estructura;

Para ter acesso aos membros definidos dentro da estrutura utilizamos um operador de seleçao de membro "."(um ponto).

  nova_estrutura.fruta[0];

Nos dá o primeiro caracter da palavra contida dentro do membro "fruta".

Para inicializar um campo da estrutura o processo é o mesmo que usamos com as variáveis.

 nova_estrutura.campo_dois = 100;

Matrizes de estruturas

[editar | editar código-fonte]

Uma estrutura é como qualquer outro tipo de dado no C. Podemos, portanto, criar matrizes de estruturas. Vamos ver como ficaria a declaração de um vetor de 100 fichas pessoais:

struct minha_estrutura fichas [100];

Poderíamos então acessar um campo dando um índice do vetor fichas:

fichas[12].variavel_um;

Declarar instâncias (objetos) da estrutura

[editar | editar código-fonte]

Podemos declarar os objetos de duas formas:

  • Ao mesmo tempo que declaramos a estrutura
 struct product {
  int weight;
  float price;
 } apple, banana, melon;
  • Ou como uma variável normal
 struct product
 {
 ..
 }
 int main()
 {
 struct product apple, banana, melon;
 }

E até podemos declarar um array delas

 Person p[20];

Pergunta: como é que é feito exatamente os objetos?

Para cada objeto vão ser feito uma cópia dos elementos da estrutura.

Agora isso significa que os objetos são distintos entre si em termos de reserva de memória? ie, à medida que enumero os objetos vão ser reservado para cada objeto o tamanho x de bytes? ou somam-se todos os objetos e reserva-se para todos os objetos de uma forma seguida? Penso que deve ser a 1ª opção.

Se tivermos apenas um objeto (ou variável da estrutura) não é necessário darmos o nome da estrutura

 struct {
 char item[40]; // name of item
 double cost; // cost
 double retail; // retail price
 int on_hand; // amount on hand
 int lead_time; // number of days before resupply
 } temp;

Acessar as variáveis membro das estruturas

[editar | editar código-fonte]

Agora queremos dar valores a cada uma das pessoas, queremos dar o nome e a altura, para isso faríamos;

 strcpy(p1.name, "Tiago");
 p1.altura =1.9;

A forma genérica é:

 structure-varname.member-name

ou seja

 [objecto_estrutura][member_estrutura]

Exemplo

 #include <stdio.h>
 const int MAX = 3;
 
 struct Person 
 {
    char name[100];
    int height;
 };
 
 int main ()
 {
   Person p[MAX];
   for (int x = 0; x < MAX; x++)
   {
      printf("Enter person's name: ");
      getline(cin, p[x].name);
      printf("Enter height in meters: ");
      scanf("%d\n", &p[x].height);
   }
   printf("Outputting person data\n");
   printf("======================\n");
   for (int x = 0; x < MAX; x++){
       printf("Person #%d's name is %s and height is %d.\n", x + 1, p[x].name, p[x].height);
   }
   return 0;
 }

Iniciar uma estrutura

[editar | editar código-fonte]

Podemos iniciar uma estrutura usando uma lista de iniciação, que seria algo como:

 Person p1 = {"Jeff Kent", 72};

isto basicamente é igual a arrays, apenas com a diferença de termos tipos diferentes. Logo a ordem vai interessar, por exemplo se escrevêssemos

 Person p1 = {72, "Jeff Kent"};  //não iria funcionar- erro de compilação

Ponteiros para estruturas

[editar | editar código-fonte]
 struct movies_t 
 {
  string title;
  int year;
 };
 
 movies_t amovie;
 movies_t * pmovie;

Nós criámos algo

 movies_t	title	year
 amovie		
 * pmovie

Vejamos que temos um ponteiro como instância.

 // pointers to structures
 #include <stdio.h>
 
 struct movies_t 
 {
  char title[100];
  int year;
 };
 
 int main ()
 {
  string mystr;
  movies_t amovie;
  movies_t *pmovie;
  pmovie = &amovie;            //atribuímos valor ao ponteiro 
 
  printf("Enter title: ");
  fgets(pmovie->title, 100, stdin);            //operador ->
  printf("Enter year: ";
  scanf("%d", &pmovie->year);
  
  printf("\nYou have entered:\n");
  printf("%s (%d)\n", pmovie->title, pmovie->year); //operador ->
  return 0;
 }

Como já devem ter deduzido o operador -> será muito similar a pmovie->title é equivalente a (*pmovie).title

Mas olhem que é diferente a:

*pmovie.title	 	que  equivalente a  	*(pmovie.title)

Passando estruturas como argumento de funções

[editar | editar código-fonte]

A estrutura é passada como ponteiro.

 #include <stdio.h>
 #include <string.h>

 
 struct Person 
 {
   string name; 
   int height;
 };
 
 void setValues(Person*);
 void getValues(const Person*);
 
 int main ()
 {
   Person p1;
   setValues(&p1);  
   printf("Outputting person data\n");
   printf("======================\n");
   getValues(&p1);
   return 0;
 }
 
 void setValues(Person* pers)
 {
   printf("Enter person's name: ");
   fgets(pers.name, 100, stdin);
   printf("Enter height in inches: ");
   scanf("%d", &pers.height);
 }
 
 void getValues(const Person* pers)
 {
    printf("Person's name is %s and height is %d.", pers.name, pers.height);
 }

Estruturas aninhadas

[editar | editar código-fonte]

A ideia é ter uma estrutura dentro de outra estrutura.

 #include <stdio.h>
 
 struct Date    //estrutura chamada de date
 {
   int day;
   int month;
   int year;
 };
 struct Person 
 {
   char name[100]; 
   int height;
   Date bDay;    //temos uma nova variável, mas notem o tipo
 };
 
 void setValues(Person*);
 void getValues(const Person*);
 
 int main ()
 {
   Person p1;
   setValues(&p1);  
   printf("Outputting person data\n");
   printf("======================\n");
   getValues(&p1);
   return 0;
 }
 
 void setValues(Person* pers)
 {
   printf("Enter person's name: ");
   fgets(pers.name, 100, stdin);
   printf("Enter height in inches: ");
   scanf("%d", &pers.height);
   printf("Enter day, month and year of birthday separated by spaces: ");
   scanf("%d %d %d\n", &pers.bDay.day, &pers.bDay.month, &pers.bDay.year );
 }
 
 void getValues(const Person* pers)
 {
   printf("Person's name: %s\n", pers.name);
   printf("Person's height in inches is: %d\n", pers.height);
   printf("Person's birthday in dd/mm/yyyy format is: %d/%d/%d\n", pers.bDay.day, pers.bDay.month, pers.bDay.year );
 }

Reparem que a estrutura Date tem de ser declarada antes da estrutura Person, pois caso contrário o compilador não entenderia o tipo declarado na estrutura Person.



Pergunta: Por que não podemos acrescentar mais membros (campos) nas estruturas?

Porque elas são compiladas estaticamente com posição de memória já alocada e tipo já conhecido em tempo de compilação

Pergunta: Ao invés de termos apenas variáveis nas estruturas, poderíamos ter também funções?

Sim, como ponteiros para funções.