Revisão de C: Ponteiros e Estruturas

De Aulas

Links Relacionados: DAS5102 Fundamentos da Estrutura da Informação

Ponteiros e Estruturas de Dados

Este tópico visa apresentar a utilização de estruturas em conjunto com ponteiros. Inicialmente apresentamos a diretiva struct e seguimos descrevendo como se pode referenciar estruturas usando ponteiros.

  • Coleção de variáveis referenciada por um único nome
  • Maneira conveniente de se ter informações relacionadas agrupadas
  • A definição de uma estrutura forma um modelo para criação de várias estruturas com a forma definida
1struct <nome_estrutura>
2{ 
3   <tipo> nome_variavel; 
4   <tipo> nome_variavel; 
5   //... 
6  //... 
7} <var1>, ..., <varn>;

Exemplo 1 – sintaxe para definição de estruturas

Toda declaração de estruturas deve começar com a palavra reservada struct seguida por um identificador, um nome que identifique a estrutura sendo declarada. Todas as variáveis que comporão os elementos da estrutura devem estar declaradas entre os operadores de escopo “{” e “}”. Opcionalmente, após o delimitador de escopo, uma ou mais variáveis do tipo definido pela estrutura podem ser declaradas. É importante notar que a sintaxe de estruturas requer que um delimitador de comandos “;” seja colocado ao final da declaração.

1struct endereco
2{ 
3    char nome[30]; 
4    char rua[40]; 
5    char cidade[20]; 
6    char estado[2]; 
7    unsigned int numero; 
8    char CEP[8]; 
9};

Exemplo 2 – definição de uma estrutura.

O exemplo acima demonstra a declaração de uma estrutura que acomoda as informações requeridas por uma entrada num banco de endereços.

Adicionalmente, podemos declarar quantas variáveis quisermos utilizando a estrutura definida.

1struct endereco end_info;

Exemplo 3 – declaração de variáveis do tipo estrutura

Referenciando Elementos de Estruturas

Podemos acessar os elementos de uma estrutura via o operador de referência ".".

1end_info.nome = "Misato Katsuragi"; 
2printf(%s\n, end_info.cidade);

Exemplo 4 – acesso a elementos de uma estrutura usando o operador ".".

Atribuição de Estruturas

Similarmente ao que ocorre com relação a variáveis atômicas, podemos atribuir uma variável tipo estrutura a outra.

1struct endereco end1, end2; 
2
3end1 = end2;

Exemplo 5 – atribuição de estruturas.

Ao atribuirmos uma estrutura a outra, todos os valores dos elementos da estrutura serão copiados.

 1#include <stdio.h> 
 2
 3void main( void )
 4{ 
 5    struct
 6    { 
 7        int a,b; 
 8    } x, y; 
 9  
10    x.a = 10; 
11    y = x; 
12    printf(%d\n,y.a); 
13}

Exemplo 6 – atribuição de estruturas

Arrays e Estruturas

Podemos criar arrays de estruturas.

1struct endereco end_info[1000]; 
2
3printf(%d, end_info[979].numero); 
4printf(%s, end_info[178].nome);

Exemplo 7

Passando Estruturas para Funções

Estruturas podem ser passadas como argumentos para funções tal como qualquer outro tipo de variável. Elas podem ser tanto passadas por valor ou por referência.

 1struct stc
 2{ 
 3    int a,b; 
 4    char ch; 
 5};
 6 
 7void f1(struct stc stc1); 
 8
 9void main(void)
10{ 
11    struct stc s1; 
12    s1.a = 1979; 
13    f1(s1);  
14} 
15
16void f1(struct stc stc1)
17{ 
18    printf(%d, stc1.a); 
19}

Exemplo 8 – passagem de estruturas por valor para funções.

A passagem de estruturas por referência segue as mesmas regras de passagem de parâmetros por referências vistas anteriormente. Exemplos serão apresentados a seguir.

Ponteiros para Estruturas

Em geral, ponteiros para estruturas funcionam exatamente como para variáveis comuns. Com algumas exceções.

1struct stc *pstc;

Exemplo 9 – declaração de uma variável ponteiro para estruturas.

1struct bal
2{ 
3    float balanco; 
4    char nome[30]; 
5} pessoa; 
6
7struct *ps; //declara um ponteiro para estrutura
8ps = &pessoa;

Exemplo 10 – ponteiros para estruturas.

Quando referenciamos uma estrutura indiretamente via um ponteiro, devemos utilizar um operador diferente -> para referenciar os elementos da estrutura.

1printf("%f", ps->balanco);

Exemplo 11 – acesso a elementos de uma estrutura apontada por um ponteiro.

Exercícios

1. Em que caso devemos usar o operador “.” e o operador “->” para acessar os elementos de uma estrutura? Explique e de exemplos.

2. Escreva um programa que represente pontos tridimensionais. Utilize estruturas para representar os pontos. O programa deve requisitar ao usuário que ele informe 2 pontos. A seguir o programa deve calcular a distância entre os pontos e informar ao usuário. Crie uma função para calcular a distância entre os pontos. Passe as duas estruturas representando os pontos por valor.

3. Crie uma função que mova o ponto passado como referência uma unidade para a esquerda. (incremente a coordenada x em uma unidade)

4. Crie um programa para gerenciar uma agenda de telefones. Inicialmente uma estrutura deve ser composta por nome, e número de telefone. Utilize arrays de estruturas para armazenar a agenda. Crie funções para inserção e alteração de registros da agenda.

Roteiro

Objetivos

  • Revisar a criação e utilização de estruturas;
  • Revisar como ponteiros e estruturas se relacionam;
  • Revisar a criação de bibliotecas de funções;
  • Revisar a passagem de parâmetros para o programa (argc e argv).

Exercícios

Crie um arquivo chamado < str_time.c > utilizando um editor de textos padrão (vi, pico, xemacs, gedit) e digite o seguinte programa:

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <unistd.h>
 4
 5// protótipos de funções
 6void display( unsigned int *ah, unsigned int *am, unsigned int *as );
 7void update( unsigned int *ah, unsigned int *am, unsigned int *as );
 8void delay();
 9
10int main( void )
11{
12    unsigned int h = 0;
13    unsigned int m = 0;
14    unsigned int s = 0;
15    while(1)
16    {
17        system("clear");
18        update( &h, &m, &s );
19        display( &h, &m, &s );
20    }
21    return 0;
22}
23
24void display( unsigned int *ah, unsigned int *am, unsigned int *as )
25{
26    (*as)++;
27    if( (*as) == 60 ) 
28    {
29        (*as) = 0;
30        (*am)++;
31    }
32    if( (*am) == 60 )
33    {
34        (*am) = 0;
35        (*ah)++;
36    }
37    if( (*ah) == 24 )
38    {
39        (*ah) = 0;
40    }
41    delay();
42}
43
44void update ( unsigned int *ah, unsigned int *am, unsigned int *as )
45{
46    printf("%02d:",   (*ah) );
47    printf("%02d:",   (*am) );
48    printf("%02d\n",  (*as) );
49}
50
51void delay()
52{
53    unsigned int mSeconds = 500000;
54    usleep(mSeconds);
55}

Como compilar o programa

gcc str_time.c -o str_time

Atividades

a) Reescreva o programa acima utilizando estruturas (struct) para representar as horas minutos e segundos;

b) Mova as funções delay, update e display para uma biblioteca separada. Crie um arquivo CDtime.h que deve conter os protótipos das funções e um arquivo CDtime.c que contenha a definição das três funções;

c) Estenda o programa para mostrar adicionalmente o tempo decorrido em segundos desde o início do programa; (contagem incremental dos segundos);

d) Estenda o programa de modo que o usuário possa passar um horário (HH:MM:SS) inicial para o programa. A contagem então deve começar a partir do horário especificado. O programa deve testar se o tempo especificado é um horário válido;

e) Estenda o programa para que o usuário possa passar como argumento o número de segundos transcorridos a partir do qual o relógio deve começar a contar. O programa deve calcular qual o horário em termos de horas minutos e segundos e então iniciar a contagem a partir deste horário.