Mudanças entre as edições de "AULA 19 - Programação 1 - Engenharia"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 99: Linha 99:
  
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
+
int main(void)
main()
 
 
{
 
{
 
   float a, *p;
 
   float a, *p;
Linha 107: Linha 106:
  
 
   *p= 5.5;
 
   *p= 5.5;
+
  return 0;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
EXERCÍCIO 3
+
EXERCÍCIO 3: Implementar um programa chamado "calculador" que recebe 3 parâmetros na linha de comando: dois números reais e um operador (char). O operador pode ser "+" ou "-". O programa deve mostrar o resultado da operação. Exemplo:
 
 
Implementar um programa chamado "calculador" que recebe 3 parâmetros na linha de comando: dois números reais e um operador (char). O operador pode ser "+" ou "-". O programa deve mostrar o resultado da operação. Exemplo:
 
 
    
 
    
  calculador 3.5 + 2.6
+
calculador 3.5 + 2.6
 
 
OBS: usar a função ''atof'' para converter string em double.
 
  
Solução: Contribuição do aluno Vinícius Luz
+
OBS: usar a função ''atof'' para converter string em double.
  
 +
{{collapse top | solução Ex. 3}}
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdio.h>
Linha 164: Linha 160:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
{{collapse bottom}}
  
 
===Apontando para estruturas===
 
===Apontando para estruturas===

Edição das 10h45min de 29 de maio de 2019

Objetivos

Ao final da aula o aluno deverá ser capaz de utilizar:

  • vetor de ponteiros;
  • argc e argv
  • ponteiros para qualquer coisa
  • ponteiros para estruturas

Links Sugeridos Pelo Aluno Jean

Este link possui um material muito interessante.

Vetor de ponteiros

Como visto em aulas anteriores, variáveis ponteiros possuem como conteúdo um endereço. É perfeitamente possível construir vetores e matrizes de ponteiros. Por exemplo:


#include <stdio.h>

int main()
{
  int i;

  char *vp[4];
  char alfa[5]="IFSC";
  char beta[5]="TELE";
  char delta[5]="RAC";
  char gamma[5]="CGER";

  vp[0] = alfa;
  vp[1] = beta;
  vp[2] = delta;
  vp[3] = gamma;  

  for(i=0;i<4;i++)
	printf("%s\n", vp[i]);
}

Fig1Aula24PrgITele.jpg

Observe que vp é um vetor de ponteiros para char e cada elemento aponta para uma cadeia de caracteres.

Argumentos de linha de comando

Um bom exemplo de vetor de ponteiros é a passagem de parâmetros na linha de comando. Cada parâmetro é tratado como uma cadeia de caracteres apontada por um elemento do vetor argv. O número de parâmetros é passado em argc. Note que argv[0] aponta para uma string que inidica o nome do programa.

Exemplo: Considere o programa abaixo:

#include <stdio.h>

main(int argc, char *argv[])
{
  int i;

  for (i=0;i<argc;i++) {
       printf("%s\n", argv[i]);
  }
  printf("Numero de parametros passados = %d\n", argc-1); /* o primeiro é o nome do arquivo executavél" */
}

EXERCÍCIO 1: Implementar um programa chamado cmpcadeia que testa se duas strings passadas na linha de comando são iguais. O programa deve imprimir uma mensagem indicando se são iguais ou diferentes. Usar a função strcmp da biblioteca. Caso sejam passados mais ou menos que dois parâmetros o programa deve se encerrar mostrando uma indicação do tipo:

cmpcadeia: dois parametros devem ser passados

Solução Ex.1

EXERCÍCIO 2: Renomeie o executável e veja seja a mensagem de erro mostra o nome correto do programa.

Ponteiros para qualquer "coisa"...

Podemos criar ponteiros para apontar para qualquer objeto na memória. Por exemplo, podemos apontar para variáveis do tipo float, double etc.

int main(void)
{
  float a, *p;
  
  p=&a;

  *p= 5.5;
   return 0;
}

EXERCÍCIO 3: Implementar um programa chamado "calculador" que recebe 3 parâmetros na linha de comando: dois números reais e um operador (char). O operador pode ser "+" ou "-". O programa deve mostrar o resultado da operação. Exemplo:

calculador 3.5 + 2.6

OBS: usar a função atof para converter string em double.

solução Ex. 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main(int quant, char *argv[])
{
  float num1, num2, result;
  char oper;

  oper = *argv[2];

  num1 = atof (argv[1]);
  num2 = atof (argv[3]);

  switch (oper) {
    case '+':
        result = num1 + num2;
        printf("Resultado: %0.2f\n", result);
        break;
    case '-':
        result = num1 - num2;
        printf("Resultado: %0.2f\n", result);
        break;
    case '*':
        result = num1 * num2;
        printf("Resultado: %0.2f\n", result);
        break;
    case '/':
        if ( num2 != 0 ){
            result = num1 / num2;
            printf("Resultado: %0.2f\n", result);
        }
        else
            printf("Denominador inválido\n");

        break;
    default:
        printf("Operacao invalida\n");
    }
 
}

Apontando para estruturas

Ponteiros podem apontar para qualquer "objeto" de qualquer tipo. Vamos verificar como é possível apontar para uma estrutura:

#include <stdio.h>

struct TRegistro {
   char nome[20];
   int idade;
} pessoa ={"Maria", 10}; 


main()
{
  struct TRegistro *p;
  p = &pessoa; /*p aponta para o registro pessoa */
  printf("O nome da pessoa é %s e idade = %d\n", p->nome,p->idade);
}
NOTE a forma como a partir de um ponteiro, pode-se acessar uma campo da estrutura!
O uso de p->nome é uma alternativa ao uso de (*p).nome

Agora vamos ver um exemplo acessando estruturas armazenadas em tabelas (vetor de estruturas):

#include <stdio.h>
#include <stdio.h>
struct TRegistro {
   char nome[20];
   int idade;
} Tabela[4] = {
          {"joao",18,},
          {"maria",18,},
          {"jose",19,},
          {"lara",17,},
}
;

struct TRegistro *p;

main()
{
  p = &Tabela[3]; /*p aponta para o registro 3 da tabela */
  printf("O nome na posição 3 é %s e idade = %d\n", p->nome,p->idade);
}


No primeiro caso pode-se ler: o campo nome do objeto que é apontado por p.

Retornando uma estrutura em uma função

No exemplo a abaixo a função RetornarStruct() retorna um ponteiro para uma estrutura. O cuidadado que se deve ter é que a função não deveria apontar para uma estrutura que foi criada localmente na função!

#include <stdio.h>
struct TRegistro {
   char nome[20];
   int idade;
} Tabela[4] = {
          {"joao",18,},
          {"maria",18,},
          {"jose",19,},
          {"lara",17,},
}
;

struct TRegistro *p;

struct TRegistro * RetornarStruct(int indice)
{
  return &Tabela[indice];
}

main()
{
  p = RetornarStruct(2); /*p aponta para o registro 3 da tabela */
  printf("O nome na posição 2 é %s e idade = %d\n", p->nome,p->idade);
}

Passando uma estrutura como parâmetro

#include <stdio.h>
struct TRegistro {
   char nome[20];
   int idade;
} Tabela[4] = {
          {"joao",18,},
          {"maria",18,},
          {"jose",19,},
          {"lara",17,},
};

struct TRegistro *p;

void MudarStruct(struct TRegistro *p1, int indice)
{
  Tabela[indice] = *p1;
}

main()
{
  struct TRegistro aux = {"luisa",16};

  MudarStruct(&aux,2);
  p = &Tabela[2];
  printf("O nome na posição 2 é %s e idade = %d\n", p->nome,p->idade);
}

Exercício 4:

No programa acima construir uma função que imprime a Tabela usando ponteiros. A função deve receber como parâmetro um ponteiro para o início da tabela e o tamanho da tabela.

Exercício 5

Implementar um programa que implementa um relógio através de uma estrutura. Ao ser chamado, o programa deve mostrar as horas, minutos e segundos, iniciando de 00:00:00. Trata-se de uma variação do programa mostrado em (ver https://www.youtube.com/watch?v=cnqIhFsFSFU). Utilize a função da biblioteca sleep para aguardar 1s. O corpo do programa é dado a seguir:

struct tempo {
 char horas;
 char minutos;
 char segundos;
};

void atualizar_relogio(struct tempo *p)
{
}

void mostrar_relogio(struct tempo *p)
{
}

main ()
{
  struct tempo meu_relogio;

  meu_relogio.horas=0;
  meu_relogio.minutos=0;
  meu_relogio.segundos=0;

  while(1){
     atualizar_relogio(&meu_relogio);
     mostrar_relogio(&meu_relogio);
  }
}


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

struct tempo {
 char horas;
 char minutos;
 char segundos;
};
 
void atualizar_relogio(struct tempo *p)
{
  sleep(1);
  p->segundos++;
  if(p->segundos==60) {
     p->minutos++;
     p->segundos=0;
     if(p->minutos==60) {
        p->horas++;
        p->minutos=0;
        if(p->horas==24)
           p->horas=0;
     }
  }
}
 
void mostrar_relogio(struct tempo *p)
{
  printf("%02d:%02d:%02d\n", p->horas,p->minutos,p->segundos);
}
 
main ()
{
  struct tempo meu_relogio;
 
  meu_relogio.horas=0;
  meu_relogio.minutos=0;
  meu_relogio.segundos=0;
 
  while(1){
     atualizar_relogio(&meu_relogio);
     mostrar_relogio(&meu_relogio);
  }
}

Múltiplas indireções

Observe que é tecnicamente possível várias indireções. Um ponteiro pode apontar para um ponteiro (ponteiro para ponteiro). Veja o exemplo seguinte.

#include  <stdio.h>

void main()
{
  int a, *b, **c, ***d;

  a =  3;
  b = &a;
  c = &b;
  d = &c;

  printf("Valor de a = %d\n",***d);
}
Soluções

Exercício 3

Implementação feita pela monitora de programação
#include <stdio.h>

main () {

  char opcao;
  int opr1;
  int opr2;
  int result;
  printf("Entre com a operação desejada\n");
  opcao=getchar();

  printf("Entre com o operando\n");
  scanf("%d",&opr1);

  printf("Entre com outro operando\n");
  scanf("%d",&opr2);

  switch(opcao) {
  case '+':

	  	  result=opr1+opr2;
          printf("Soma: %d\n",result);
          break; /* o break força o encerramento da instrução*/
  case '-':
	  	  result=opr1-opr2;
	      printf("Subtração: %d\n",result);
          break;
  case '*':
	  	  result=opr1*opr2;
	  	  printf("Multiplicação: %d\n",result);
          break;
  case '/':
	  	  result=opr1/opr2;
	  	  printf("Divisão: %d\n",result);
          break;

  default:
          printf("Nenhuma das operações é válida!\n");
          break;    
  }
}