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

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 442: Linha 442:
 
     return 1;  //retorna 1 se forem diferentes
 
     return 1;  //retorna 1 se forem diferentes
 
     }else{
 
     }else{
return 0;//se percorrer a string totalmente e nao encontrar nada diferente retorna 0
+
return 0;//se percorrer a string totalmente e nao encontrar nada diferente retorna 0
 
}
 
}
p1++;            //proxima posicao de p1
+
p1++;            //próxima posição de p1
p2++;            //proxima posicao de p2
+
p2++;            //próxima posição de p2
 
   }
 
   }
 
    
 
    
 
}
 
}
+
 
/* exemplo de uso da função */
 
 
int main(void)
 
int main(void)
 
{
 
{

Edição das 13h12min de 29 de maio de 2019

Objetivos

  • iniciação ao uso de ponteiros no C;

Referências

[1]

[2]

[3]

[4]

Site Embarcados

Ponteiros

A memória de um computador pode ser vista como um vetor de bytes.

Cada byte possui um endereço. O tamanho da memória é definido pelo tamanho do barramento de endereços usado para acessá-la.

Uma variável ocupa uma área da memória. Tipicamente uma variável to tipo char se utiliza de um byte. Já uma variável do tipo int pode (dependendo do sistema) usar 4 bytes contíguos.

 Uma variável possui um endereço e um conteúdo (dados).


 Uma variável ponteiro tem como conteúdo um endereço. Portanto a variável ponteiro possui um endereço e contém um endereço como conteúdo.

Ponteiro para inteiro

Observe o programa abaixo. A variável p é um ponteiro para inteiro. Isto significa que ela pode armazenar um endereço de um inteiro. O operador & é usado para capturar o endereço da variável.

#include <stdio.h>

main()
{
  int x;
  int *p;

  x=5;
  printf("Valor de x antes = %d\n", x);
  
  p = &x;
  *p=10;

  printf("Valor de x depois = %d\n", x);
  printf("Valor de p = %p\n", p);
}

Observe que para se referenciar o conteúdo da posição de memória apontada por p deve-se usar o asterisco: *p

EXERCÍCIO 1: Considere o programa:

int main(void)
{
  int x=10;
  int y, *p, *w;

}

Faça um código para copiar o conteúdo de x para y, sem que estas variáveis apareçam no lado esquerdo de um sinal de atribuição.

solução Ex. 1
int main(void)
{
  int x=10;
  int y, *p, *w;
  
  p = &x;
  w = &y;
  *w = *p;  

  printf("valor copiado para y : %d\n",y);
  return 0;
}

EXERCÍCIO 2: Tente inferir qual seria o valor da variável y no final do programa abaixo.

int main(void)
{
  int x,y,w,*p1,*p2;
  x = 20;
  w = 30;
  p1 = &x;
  p2 = &w;
  y = *p1 + *p2;
  return 0;
}
solução Ex. 2
y = 50

EXERCÍCIO 3: Tente inferir qual seria o valor da variável y no final do programa abaixo.

int main(void)
{
  int x,y,w,*p1,*p2, *p3;
  x = 20;
  w = 30;
  p1 = &x;
  p2 = &w;
  y = *p1 + w;
  p3 = &y;
  *p3 = *p3 + 10;
  y = *p1 + *p2 + *p3;
  return 0;
}
solução Ex. 3
y = 110

Ponteiro para char

Os ponteiro para char são muito utilizados pois permitem apontar para strings. A ideia é que ele aponte para o primeiro caracter da string. Veja o exemplo abaixo.

#include <stdio.h>

int main(void)
{
   char x[10]="ifsc";
   char *p;

   p = &x[2];

   printf("x[2] = %c\n", *p);

   p = x;

   printf("string %s\n", p);

   while (*p!=0) {
       printf("Endereco %p conteúdo %c\n", p,*p);
       p++;
   }
   return 0;	
}

Neste foi usado o incremento de um ponteiro, o que implica em adicionar ao endereço armazenado em p uma quantidade relativa ao tamanho do tipo apontado. No caso é 1 (tamanho de um char é um byte).

EXERCÍCIO: Sem executar o programa abaixo, determine o valor de y no final do programa:

int main(void)
{
   char x[10]="ifsc";
   char *p, y;
   
   p = x + 2;
   y = *p;
   return 0;
}
solução
y = 's'

Apontando para um vetor de inteiros

Da mesma forma que usamos um ponteiro para char para apontar uma string, podemos fazer um ponteiro para int apontar para para um elemento de um vetor de inteiros.

#include <stdio.h>

main()
{
   int x[10]= {0,1,2,3,4,5,6,7,8,9};
   int *p;
   int i;
   
   p = x;

   i=0;
   while (i<10) {
       printf(" endereco %p e conteudo %d\n", p, *p);
       p++;
       i++;       
   }	
}


OBSERVE que p++ incrementa em 4 unidades.

Usando ponteiro na passagem de parâmetros

Observe como podemos usar ponteiros na passagem de parâmetros.

#include <stdio.h>

void str_cpy(char *pdest, char *pfonte)
{
   while (*pfonte!=0) {
        *pdest++ = *pfonte++;
   }
   *pdest = 0;
}


int str_len (char *p)
{
   int i=0;
   while (*p++!=0)
		i++;
   return i;
}

int main(void)
{
   char fonte[10]="ifsc";
   char destino[10];

   str_cpy(destino, fonte);
   printf("string destino = %s\n", destino);

   printf("tamanho de dest = %d\n", str_len(destino));
   return 0;
}

Um ponto interessante é que ponteiros permitem, na chamada de uma função, passar valores por referência (de forma "simulada"):

void alfa(int *p)
{
  *p=10;
}

main()
{
  int x;
  x =5;
  printf("Valor de x antes da chamada de alfa = %d\n", x);
  alfa(&x);
  printf("Valor de x depois da chamada de alfa = %d\n", x);
}

Exercícios

  1. Rever a aula da UFMG em Link Aula Ponteiros UFMG e fazer os exercícios de fixação. Obs: Se necessário, ao ler no browser, troque a codificação de UTF8 para Ocidental. Eu tive problemas na leitura da página.
  2. Implemente um programa que realize o swap de suas variáveis inteiras passadas como parâmetro. Use ponteiros.
    solução 1:
  3. Implementar a função str_cat que concatena duas strings usando ponteiros.
    void str_cat(char *p1, char *p2)
    {
    
    }
    
    /* exemplo de uso da função */
    int main()
    {
      char vet1[30]="IFSC";
      char vet2[20]="-SC";
      
      str_cat(vet1,vet2);
      printf("%s",vet1); /* aqui deveria imprimir "IFSC-SJ" */
      return (0);
    }
    
    solução A:
    solução B:
    Solução C:
  4. Implementar um programa para ler dados para dentro das variáveis x e y e somar o conteúdo das mesmas colocando o resultado em x SEM referenciar estas variáveis no scanf ou na expressão de soma.
    solução Ex. 4
  5. Implementar uma função que compara duas strings passadas como parâmetro. A função retorna 0 se as strings forem iguais e 1 se diferentes. Usar ponteiros.
    solução Ex. 5
  6. Implementar uma função que recebe como parâmetro o endereço de duas variáveis float que contêm a parte real e imaginária de um número complexo no formato polar (ângulo em radianos). A função deve converter do formato polar retangular colocando a coordenada x no primeira variável cujo endereço foi fornecido como parâmetro e a coordenada y na segunda variável.
    void converte_polar_retang(float *parte1, float parte2)
    {
    }
    
    int main(void)
    {
      float num1=1.5, num2=10.6;
    
      /*chamar a função aqui */
    
      /* imprimir os valores de num1 e num2 aqui */
    }
    
    solução Ex. 6
  7. Implementar uma função que recebe como parâmetro o endereço de duas variáveis do tipo char e após a chamada da função os valores das variáveis devem estar maiúsculos (caso elas contenham letras minúsculas).
    void capitaliza(char *c1, char *c2)
    {
    }
    
    int main(void)
    {
      char alfa='a', beta='b';
    
      capitaliza(&alfa, &beta);
      
      /* aqui os valores de alfa e beta deverão ser A e B */
    }
    
    solução Ex. 7
  8. Implementar uma função que recebe uma string contendo uma cadeia de caracteres com dígitos numéricos e retorna o valor inteiro da string. Usar ponteiros.
    int a_toi(char *p)
    {
    }
    
    main()
    {
      char *p="123";
      int x;
    
      x = a_toi(p);
      
      /* neste ponto x deve conter 123 */
    }
    
    solução Ex. 8
  9. Construir uma função usando ponteiros que retorna a média de um vetor de inteiros passado como parâmetro. O tamanho do vetor também deve ser fornecido.
    float media_vet(int *vet, int tamanho)
    {
    }
     
    /* exemplo de uso */
     
    main()
    {
       int x[10]= {0,1,29,3,42,5,61,7,82,9};
       float media;
     
       media = media_vet(x,10); /* em media_vet deve ficar a média do vetor */
    }
    
    solução Ex. 9


|}