AULA 19 - Programação 1 - Engenharia
Objetivos
- vetor de ponteiros;
- argc e argv
- ponteiros para qualquer coisa
- ponteiros para estruturas
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]);
}
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 indicão do tipo:
cmpcadeia: dois parametros devem ser passados
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.
main()
{
float a, *p;
p=&a;
*p= 5.5;
}
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: Contribuição do aluno Vinícus Luz
#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>
#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);
}
Note que o uso de p->nome é uma alternativa ao uso de (*p).nome
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;
}
}
|