2007-04-24

Apontadores Exercícios

  1. Escreva a função com o protótipo void mult(int *v1, int *v2, int *v3, int n) que multiplica os vectores v1 e v2 elemento a elemento e coloca o resultado no vector v3. Os vectores têm comprimento n .(Ex (1,2,3)X(4,5,6)=(4,10,18)).

  2. Escreva a função com o protótipo int comp_vec(int *v1, int *v2, int n) que retorna 1 se os vectores v1 e v2 forem iguais e 0 se forem diferentes. Os vectores têm comprimento n.

  3. Escreva a função com o protótipo int is_ident(int *mat, int n) onde mat é uma matriz nxn. A função deverá retornar 1 se mat for a matriz identidade e 0 caso contrário. (Definição de Matriz Identidade)

  4. Escreva a função com o protótipo void comuns(int a[], int m, int b[], int n) onde a[] e b[] contêm respectivamente m e n elementos distintos ordenados por ordem crescente e sem repetição. A função deve imprimir por ordem crescente os elementos comuns aos 2 vectores. Por exemplo, para os vectores [1,3,4,7,8] e [2,3,4,6,8,9] deverá ser impresso 3 4 8.

  5. Escreva a função com o protótipo void sort_vec(int *vec, int n) que ordena os elementos do vector vec de n elementos por ordem crescente. Note que o vector pode conter elementos repetidos.

  6. Considere 2 vectores globais de strings char *proibidos[] e char *gratis[] que representam respectivamente os prefixos de números de telefone de utilização proibida e grátis. Ambas estas lista usam o valor NULL para indicar o fim da lista. Um exemplo:
    char *proibidos[] = {"23","2677",NULL};
    char *gratis[] = {"0800","11",NULL};
    Implemente uma função com o protótipo int classifica_numero(char *tel) que retorna respectivamente 1,0 ou -1 conforme respectivamente o número de telefone tel é proibido (algum proibidos[i] é prefixo dele), grátis (algum gratis[i] é prefixo dele) ou nem grátis nem proibido. Para o exemplo dado, temos que classifica_numero("234455666") retorna 1.
    Recorde que dadas duas palavras p e s, diz-se que p é prefixo de s, se e só se, existir uma palavra y (que pode ser vazia) tal que s = py.
    A função int classifica_numero(char *tel) deverá utilzar uma função auxiliar com o protótipo int prefixo(char *p, char *s) que retorna 1 se p é prefixo de s e 0 caso contrário.

Apontadores (Revisões)

http://paginas.fe.up.pt/~apm/C_tut/Cap_8.htm

2007-04-18

Apontadores e funções

Quando se passam argumentos para funções em C, estes são passados por valor (excepto os arrays, como veremos); ou seja, é criada uma cópia do argumento no stack do processador e é essa cópia que chega à função; quando a função termina essa cópia desaparece. No entanto há situações em que a passagem de argumentos por valor não é muito conveniente; por exemplo, quando queremos que modificações feitas aos argumentos no interior das funções cheguem a quem as chamou, ou quando necessitamos de passar argumentos de tamanho muito elevado (estruturas com muitos membros). Certas linguagens permitem então a passagem de parâmetros de outra forma - passagem por referência - em que a informação que chega à função é apenas o endereço do local na memória onde se encontra o valor do argumento (p. exemplo, argumentos declarados como var no Pascal). No entanto o C não permite esse mecanismo sendo necessário o uso explícito de apontadores para o implementar. (Nota: o C++ contém já esse mecanismo).

Por exemplo, se quiséssemos escrever uma função para trocar o conteúdo de duas variáveis, a forma habitual não funcionaria:

void swap(int a, int b)
{
int t;

t = a; a = b; b = t;
}

com a chamada
swap(i, j);


Para funcionar teríamos de recorrer a apontadores e ao operador
&
de obtenção do endereço de uma variável:

void swap(int *a, int *b)
{
int t;

t = *a; *a = *b; *b = t;
}

com a chamada
swap(&i, &j);


É possível também retornar apontadores como resultado de uma função, usado geralmente quando se pretende retornar informação que ocupe um grande espaço, como as estruturas:

typedef struct { float x, y, z; } coord;

coord *coor_fn(void);

void main(void)
{
coord p1;

...
p1 = *coord_fn();
...
}

coord *coor_fn(void)
{
coord p;

p = ... ;
return &p;
}


Aqui retorna-se um apontador cujo conteúdo é imediatamente de-referenciado para uma variável do tipo correspondente. Deve fazer-se esta transferência de imediato uma vez que a variável p é local à função e desaparece quando a função retorna, podendo a memória que lhe corresponde ser reutilizada.