PRG122804 2019 1 AULA11

De MediaWiki do Campus São José
Ir para: navegação, pesquisa

Objetivos

  • Definição de estruturas;
  • Estruturas como parâmetros;
  • Inicialização de estruturas;
  • Cópia de estruturas;

Estruturas

No C é possível criar tipos de dados que representam uma estrutura. Veja o exemplo seguinte

#include <stdio.h>

struct TUsuario /* struct TUsuario é o nome do tipo que está sendo criado */
{ 
  char userID[20];
  char senha[20];
} Usuario; /* aqui é definida uma variável do  tipo struct TUsuario */

struct TUsuario TabelaUsuario[20];

main()
{
  scanf("%s", Usuario.userID);
  scanf("%s", Usuario.senha);
  scanf("%s", TabelaUsuario[10].userID);
  scanf("%s", TabelaUsuario[10].senha);
}

Neste exemplo, foi definido um tipo (modelo) para o registro (struct TUsuario) e foi criada uma variável chamada Usuario a partir deste tipo. Na sequência foi criada mais uma variável (um vetor de estruturas) chamada TabelaUsuario. Note que basta usar as palavras chave struct Usuario para criar novas variáveis. O tipo completo é definido uma única vez no início.

Exercícios
  1. Criar um programa que define uma struct para armazenamento do nome e das notas bimestrais de um aluno. Atualizar a estrutura usando o scanf.
  2. Alterar o programa para que ele calcule e imprima a média de cada aluno.
Resposta
#include <stdio.h>

#define NUM_MAX 3

struct TAluno {
  char nome[30];
  char matricula[11];
  float b1,b2,b3,b4;
} Turma[NUM_MAX];

void print_aluno(struct TAluno aux)
{
  printf("Nome -> %s\n", aux.nome);
  printf("Matrícula -> %s\n", aux.matricula);
  printf("Bimestre 1 -> %f\n", aux.b1);
  printf("Bimestre 2 -> %f\n", aux.b2);
  printf("Bimestre 3 -> %f\n", aux.b3);
  printf("Bimestre 4 -> %f\n", aux.b4);          
}

main()
{
  int i;
  
  for(i=0;i<NUM_MAX;i++) {
  	printf("Entre com o nome do aluno\n");
  	scanf("%s", Turma[i].nome);
  	printf("Entre com a matrícula do aluno\n");
  	scanf("%s", Turma[i].matricula);
  	printf("Entre com a nota do bimestre 1\n");
  	scanf("%f", &Turma[i].b1);
  	printf("Entre com a nota do bimestre 2\n");
  	scanf("%f", &Turma[i].b2);
  	printf("Entre com a nota do bimestre 3\n");
  	scanf("%f", &Turma[i].b3);
  	printf("Entre com a nota do bimestre 4\n");
  	scanf("%f", &Turma[i].b4);
  }
  for(i=0;i<NUM_MAX;i++) {
    printf("=========== Aluno %d ============\n", i);  
  	print_aluno(Turma[i]); 
  }      
}

Copiando structs

O exemplo a seguir demonstra como se pode copiar uma variável struct para outra do mesmo tipo.

#include <stdio.h>
  
struct THoras{
   int hora;
   int minuto;
   int segundo;
};

struct THoras Ontem = {2,10,57};

void main()
{
     struct THoras Hoje;
     Hoje = Ontem;

     printf("Hora hoje = %d, Minuto hoje = %d e Segundo hoje %d\n", Hoje.hora, Hoje.minuto, Hoje.segundo);
}

Estruturas dentro de estruturas

Vamos ver um exemplo com estruturas definidas dentro de estruturas:

#include <stdio.h>
  
struct TEndereco{
     char rua[50];
     char numero[10];
};

struct TCidadao{
  char nome[50];
  char cpf[20];
  struct TEndereco endereco;
  int num_filhos;
};

void main()
{
  struct TCidadao Cidadao;

  printf("Entre com o nome\n");
  scanf ("%s",Cidadao.nome); // substitua por gets()

  printf("Entre com o cpf\n");
  scanf ("%s",Cidadao.cpf);

  printf("Entre a rua\n");
  scanf ("%s",Cidadao.endereco.rua); // substitua por gets()

  printf("Entre a numero\n");   
  scanf ("%s",Cidadao.endereco.numero);

  printf("Entre com o número de filhos\n");
  scanf ("%d",&Cidadao.num_filhos);
  
}

Exercício 1: Faça um código adicional para imprimir o conteúdo lido na estrutura.


Resposta
#include <stdio.h>
 
struct TEndereco{
     char rua[50];
     char numero[10];
};
 
struct TCidadao{
  char nome[50];
  char cpf[20];
  struct TEndereco endereco;
  int num_filhos;
};

void print_endereco(struct TEndereco aux)
{
  printf ("Rua %s Número %s\n", aux.rua, aux.numero); 
}

void print_cidadao(struct TCidadao aux)
{
  printf("Nome: %s CPF: %s ", aux.nome, aux.cpf);
  print_endereco(aux.endereco);
  printf("Numero de filhos %d\n", aux.num_filhos);
}

void main()
{
  struct TCidadao Cidadao;
 
  printf("Entre com o nome\n");
  scanf ("%s",Cidadao.nome);
 
  printf("Entre com o cpf\n");
  scanf ("%s",Cidadao.cpf);
 
  printf("Entre a rua\n");
  scanf ("%s",Cidadao.endereco.rua);
 
  printf("Entre a numero\n");   
  scanf ("%s",Cidadao.endereco.numero);
 
  printf("Entre com o número de filhos\n");
  scanf ("%d",&Cidadao.num_filhos);
 
}

Iniciando structs na definição

Como toda variável, é possível dar valores para uma variável do tipo struct definida no programa:

#include <stdio.h>
 
struct TEndereco{
     char rua[50];
     char numero[10];
};
 
struct TCidadao{
  char nome[50];
  char cpf[20];
  struct TEndereco endereco;
  int num_filhos;
};
 
void main()
{
  struct TCidadao Cidadao = {"Maria",
                             "42342342234",
                             {"Rua AlfaBeta","145"},
                             5
                            };
 
  printf("Rua do cidadao = %s\n", Cidadao.endereco.rua);
 
}

Passando estruturas como parâmetro e retornando estruturas

Se não for usado o operador "&" , um parâmetro que é estrutura será passado por cópia. Não apresentaremos agora a passagem por endereço pois necessita do conceito de ponteiro. Observe o exercício abaixo.

#include <stdio.h>
  
struct TEndereco{
     char rua[50];
     char numero[10];
};

struct TCidadao{
  char nome[50];
  char cpf[20];
  struct TEndereco endereco;
  int num_filhos;
};

void print_struct (struct TCidadao aux)
{
  printf("nome=%s cpf=%s\n", aux.nome, aux.cpf);
  printf("endereço inicial do aux %p\n", &aux);
}

void main()
{
  struct TCidadao Cidadao;

  printf("Entre com o nome\n");
  scanf ("%s",Cidadao.nome);

  printf("Entre com o cpf\n");
  scanf ("%s",Cidadao.cpf);

  printf("Entre a rua\n");
  scanf ("%s",Cidadao.endereco.rua);

  printf("Entre a numero\n");   
  scanf ("%s",Cidadao.endereco.numero);

  printf("Entre com o número de filhos\n");
  scanf ("%d",&Cidadao.num_filhos);
  
  print_struct(Cidadao);

  printf("endereço inicial do Cidadao %p\n", &Cidadao);
}
O que podemos concluir com os endereços que foram mostrados??? Vamos a mais um exemplo.
#include <stdio.h>
  
struct TEndereco{
     char rua[50];
     char numero[10];
};

struct TCidadao{
  char nome[50];
  char cpf[20];
  struct TEndereco endereco;
  int num_filhos;
};

struct TCidadao ler_struct()
{
  struct TCidadao aux;

  printf("Entre com o nome\n");
  scanf ("%s",aux.nome);

  printf("Entre com o cpf\n");
  scanf ("%s",aux.cpf);

  printf("Entre a rua\n");
  scanf ("%s",aux.endereco.rua);

  printf("Entre a numero\n");   
  scanf ("%s",aux.endereco.numero);

  printf("Entre com o número de filhos\n");
  scanf ("%d",&aux.num_filhos);

  return aux;
}

void print_struct (struct TCidadao aux)
{
  printf("nome=%s cpf=%s\n", aux.nome, aux.cpf);
  printf("endereço inicial do aux %p\n", &aux);
}

void main()
{
  struct TCidadao Cidadao;

  Cidadao = ler_struct();

  print_struct(Cidadao);

  printf("endereço inicial do Cidadao %p\n", &Cidadao);
}

Aplicação no Controle de Acesso

O exemplo a seguir implementa uma parte do programa de controle de acesso usando estruturas. Neste exemplo a tabela de usuários já vem inicializada nos campos UserID e Senha.

#include <stdio.h>
#include <string.h>
 
/**********************************************/
/*** PROGRAMA DE CONTROLE DE ACESSO  **/
/** Autor: TurmaENG.TELECOM - 2012.2 */
/**********************************************/
 
/** VARIÁVEIS GLOBAIS DESTE MÓDULO ****/

struct TRegistroUsuario {
	char UserId[10];
	char Senha[10];
};

/* Tabela de Usuários */
struct TRegistroUsuario TabelaUsuarios[4] = {
         {"joao","abcd"},
         {"maria","xxxx"},
         {"jose","yyyy"},
         {"lara","zzzz"},
};

 
char userID[20];
 
 
/** FUNÇÔES DESTE MÓDULO ****/
 
void mostrar_menu_entrada_usuario()
{
  printf("*******************************\n");
  printf("Entre com o seu USERID para ter acesso\n"); 
  printf("*******************************\n");
}
 
/** Função que implementa as tarefas do administrador **/
 
void  administrar()
{
}
 
/** Função que valida um usuário e abre a porta **/
 
void tratar_usuario()
{
  char senha[10];
  int userEncontrado=1;
  int i;
 
 
 /* 
     Loop para encontrar o usuário na tabela. 
     Ao final do loop a variavel i conterá o índice do usuário (se ele estiver
     na tabela
  */
  for (i=0;i<4 && userEncontrado; i++) {
       if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
             userEncontrado=0;
  }
 
  /* se usuário encontrado abre a porta */
  if (userEncontrado==0) {
	printf("Bom dia %s! Entre com a senha\n", userID);
  	scanf("%s",senha);
	i--; /* o indice do sujeito é i-1 */
	if(strcmp(senha,TabelaUsuarios[i].Senha)==0) 
	       printf("Abrir porta!!!\n");
	else
		printf("Senha Inválida\n");
  }
}
 
void main()
{
 for(;;) {
     mostrar_menu_entrada_usuario();
     scanf("%s",userID);
     if (strcmp(userID, "admin")==0) {
          administrar();
     } else {
         tratar_usuario();
     }
 }   
}

Exercício:

  1. Implementar um contador de acesso que permita bloquear o usuário após 3 tentativas seguidas. Note que caso o usuário acerte a senha, este contador deverá ser zerado.
  2. Implementar uma funcionalidade do administrador para desbloquear o usuário bloqueado.
  3. No programa de controle de senha inserir um campo na estrutura do usuário de forma a acomodar uma mensagem de boas vindas particularizada para cada usuário. A mensagem "DEFAULT" é Bom dia!
  4. Implementar na função administrar a inserção da mensagem no exercício anterior.
  5. Na solução acima criar uma função que procura usuário na tabela (já que este código é utilizado em mais do que um luga). A função deve receber o UserID a ser procurado e deve retornar um inteiro correspondente ao índice do usuário encontrado ou -1 se não for encontrado.
Solução 1
#include <stdio.h>
#include <string.h>
 
/**********************************************/
/*** PROGRAMA DE CONTROLE DE ACESSO  **/
/** Autor: Turma ENG.TELECOM - 2013.1 */
/**********************************************/
 
/** VARIÁVEIS GLOBAIS DESTE MÓDULO ****/
 
struct TRegistroUsuario {
	char UserId[10];
	char Senha[10];
	int contador;
};
 
/* Tabela de Usuários */
struct TRegistroUsuario TabelaUsuarios[4] = {
         {"joao","abcd",0},
         {"maria","xxxx",0},
         {"jose","yyyy",0},
         {"lara","zzzz",0},
};
 
 
char userID[20];
 
 
/** FUNÇÔES DESTE MÓDULO ****/
 
void mostrar_menu_entrada_usuario()
{
  printf("*******************************\n");
  printf("Entre com o seu USERID para ter acesso\n"); 
  printf("*******************************\n");
}

/** Função que implementa as tarefas do administrador **/
 
void  administrar()
{
  char aux_senha[10];
  int userEncontrado=1;
  int i;
    
  printf("Entre com a senha do admin \n");
  scanf ("%s", aux_senha);
  
  if(strcmp(aux_senha,"123456")==0) {
      /* senha valida do admin - agora entre com userid a ser desbloqueado */
      printf("Entre com userdID a ser desbloqueado\n");
      scanf("%s",userID);
      for (i=0;i<4 && userEncontrado; i++) {
         if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
             userEncontrado=0;
      } 
      if (userEncontrado==0) {
         i--;
         TabelaUsuarios[i].contador=0;
      }           
  }
}
 
/** Função que valida um usuário e abre a porta **/
 
void tratar_usuario()
{
  char senha[10];
  int userEncontrado=1;
  int i;
 
 
 /* 
     Loop para encontrar o usuário na tabela. 
     Ao final do loop a variavel i conterá o índice do usuário (se ele estiver
     na tabela
  */
  for (i=0;i<4 && userEncontrado; i++) {
       if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
             userEncontrado=0;
  }
 
  /* se usuário encontrado abre a porta */
  if (userEncontrado==0) {
  	 i--; /* o indice do sujeito é i-1 */
    if (TabelaUsuarios[i].contador<3){
    
	   printf("Bom dia %s! Entre com a senha\n", userID);
  	   scanf("%s",senha);

	   if(strcmp(senha,TabelaUsuarios[i].Senha)==0) {
	       printf("Abrir porta!!!\n");
	       TabelaUsuarios[i].contador=0;
	   }
	   else {
		   TabelaUsuarios[i].contador++;
		   printf("Senha Inválida\n");
		   printf("Tentativas restantes %d\n", 3-TabelaUsuarios[i].contador);
		}
    } else {
      printf("Usuário bloqueado\n");
    }
  } else {
    printf("Usuário não encontrado\n");
  }
}
 
void main()
{
 for(;;) {
     mostrar_menu_entrada_usuario();
     scanf("%s",userID);
     if (strcmp(userID, "admin")==0) {
          administrar();
     } else {
         tratar_usuario();
     }
 }   
}
|}
Solução 2
#include <stdio.h>
#include <string.h>
 
/**********************************************/
/*** PROGRAMA DE CONTROLE DE ACESSO           */
/** Autores: Daniel Trevisan Tatsch           */
/**          Ricardo Amorim                   */
/**********************************************/
 
/** VARIÁVEIS GLOBAIS DESTE MÓDULO ****/
 
struct TRegistroUsuario {
    char UserId[10];
    char Senha[10];
    int ativo;
};
 
/* Tabela de Usuários */
struct TRegistroUsuario TabelaUsuarios[4] = {
         {"joao","abcd",1},
         {"maria","xxxx",1},
         {"jose","yyyy",1},
         {"lara","zzzz",1},
};
 
char userID[20];
 
/** FUNÇÔES DESTE MÓDULO ****/
 
void mostrar_menu_entrada_usuario()
{
  printf("\n********************************************");
  printf("\nEntre com o seu USERID para ter acesso: "); 
  printf("\n********************************************\n");
}
 
/** Função que implementa as tarefas do administrador **/
 
void administrar()
{
    int i;
    for(i=0;i<4;i++)
	TabelaUsuarios[i].ativo=1;
    printf("\nTodos os usuários foram liberados!\n"); 
}
 
/** Função que valida um usuário e abre a porta **/
 
void tratar_usuario()
{
  char senha[10];
  int userEncontrado=1;
  int i, cont = 0;
 
 /* 
     Loop para encontrar o usuário na tabela. 
     Ao final do loop a variavel i conterá o índice do usuário (se ele estiver
     na tabela
  */
  for (i=0;i<4 && userEncontrado; i++) {
       if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
             userEncontrado=0;    
  }
  
  if (userEncontrado==0) {  // se usuário encontrado...
      for(;;){
	      if(TabelaUsuarios[i-1].ativo){ // se usuário ativo (1)...
		 printf("Bom dia %s! Entre com a senha\n", userID);
		 scanf("%s",senha);
		 if(strcmp(senha,TabelaUsuarios[i-1].Senha)==0){ // se senha confere (0)...
		    printf("Abrir porta!!!\n");
		    cont=0;
		    break;
		 } else {
		    printf("Senha Inválida\n");
		    cont++;
		    if(cont==3){
		       printf("\nUsuário Bloqueado!\n");    
		       TabelaUsuarios[i-1].ativo = 0;
		       break;
		    }
		 }
	      } else {
		 printf("\nUsuário Bloqueado!\n");  // usuario bloqueado ativo (0)    
		 break;
	      }
	} // fim do for(;;)
  } else
        printf("\nUsuário não encontrado!\n"); // se usuario nao encontrado.   
}
 
void main()
{
 for(;;) {
     mostrar_menu_entrada_usuario();
     scanf("%s",userID);
     if (strcmp(userID, "admin")==0) {
          administrar();
     } else {
         tratar_usuario();
     }
 }   
}
|}

Exercícios com Structs

Desafio 1

Implementar uma função converte_para_polar que recebe como parâmetro um número complexo na forma retangular (representado por uma struct). A função deve retornar uma struct contendo o número complexo na forma polar.Usar as funções sqrtf e atanf da [matemáticas biblioteca matemática]. Como converter:

ou

NOTE que as funções atanf e similares retornam em RADIANOS.

Solução
#include <stdio.h>
#include <math.h>

struct tipo_ret {
 	float x;
 	float y;
};

struct tipo_polar {
 	float mod;
 	float ang;
};


/* Função para converter complexo retangular em polar */

struct tipo_polar converter_ret_pol(struct tipo_ret num_ret)
{
  struct tipo_polar num_polar;
  float aux;
  
  aux = num_ret.x*num_ret.x + num_ret.y*num_ret.y;
  
  /* falta a lógica para detectar o quadrante */
  num_polar.mod = sqrtf(aux);
  num_polar.ang = atanf(num_ret.y/num_ret.x);
  return num_polar; 
}

/* Função para imprimir complexo retangular */
void imprimir_complexo_ret(struct tipo_ret num_ret)
{
  printf("Coordenada x = %f", num_ret.x);
  printf("Coordenada y = %f\n", num_ret.y);
}

/* Função para imprimir complexo retangular */
void imprimir_complexto_pol(struct tipo_ret num_ret)
{
  printf("Coordenada x = %f", num_ret.x);
  printf("Coordenada y = %f\n", num_ret.y);
}

main()
{
  struct tipo_ret num1;
  struct tipo_polar num2;
  
  num1.x = 5;
  num1.y = 10;
  num2 = converter_ret_pol (num1);  
}

Desafio 2

Implementar uma função que some dois números complexos no formato retangular e retorne a soma como um complexo retangular.

Desafio 3

Implementar uma função que some dois números complexos no formato polar e retorna a soma no formato polar.




Icone voltar.png Icone menu.png Icone prox.png