Parametros funcionais em C (function pointers)

gryphus1

Membro
Boas.

Tenho uma duvida referente a funções passadas para outras funções como apontadores, isto é, parâmetros funcionais em C.

Por exemplo, tenho uma funçao:

Código:
tDic newDic (int max, tKey(*key)(tElem),
int (*eqKey)(tKey,tKey),int (*eqElemKey)(tElem,tElem),int (*hash)(tKey,int));

tDic é o tipo que a função devolve, tKey é o tipo para a função apontada por *key assim como o tipo de alguns parametros de entrada para o apontador *eqKey e *hash por exemplo, e o mesmo para tElem que é o tipo dos parametros de entrada para o apontador *eqElemKey por ex.


Mas isto é apenas a declaração da função newDic... como posso fazer para a chamar no programa principal?? A minha duvida é o que passar durante o chamamento da função newDic no programa principal para os apontadores às funções *key,*eqKey,*eqElemKey... etc
 
Vou dar um exemplo para as funções:

- Imagina que tens 2 funções para cada tipo que tens de passar para a função newDic

Código:
tKey keyGet(tElem elem);
tKey keyFunc(tElem elem);

int eqKeyComp (tKey key1, tKey key2);
int eqKeyDiff (tKey key1, tKey key2);

int eqElemKeyPrim (tElem elem1, tElem elem2);
int eqElemKeySec (tElem elem1, tElem elem2);

int hashGen (tKey key, int i);
int hashProd (tKey key, int i);

- Agora, para chamares a função newDic podes passar qualquer das duas funções de cada tipo, por exemplo

Código:
int main() {
...
tDic d = newDic(100, keyGet, eqKeyDiff, eqElemKeyPrim, hashGen);
...
}

- E para usares as funções dentro da newDic é só chamar por elas e passar-lhes os argumentos

Código:
tDic newDic (int max, tKey(*key)(tElem), int (*eqKey)(tKey,tKey),int (*eqElemKey)(tElem,tElem),int (*hash)(tKey,int)) {
...
tElem e1;
tElem e2;
...
tKey k1 = key(e1);
tKey k2 = key(e2);
...
if(eqKey(k1, k2)) ...
...
if(eqElemKey(e1,e2)) ...
...
int a = hash(k1, 100);
...
}




EDIT: Já agora, por curiosidade, se quiseres uma função que te devolva outra função podes faze-la do seguinte modo

Código:
(tipo_dados_devolve) (tipo_dados_recebe, tipo_dados_recebe, ...) nome_funcao_devolve(parâmetros ...) {
...
return(nome_funcao_devolvida);
...
}

Mas uma nota importante: se queres andar a passar funções como argumento e funções para devolveres funções, trabalha em LISP que isso é o pão nosso de cada dia :) em C o código torna-se pouco legível e intuitivo, mas funciona na mesma.
 
Última edição:
Obrigado pela explicação Dan!:) Já percebi como se faz, era mesmo isso.

O que é LISP? Alguma linguagem? (não conheço :D)

De todas as formas estou actualmente a trabalhar em C não por escolha própria mas porque estou a dar C na faculdade e vou ter exame de C eheh :P mas de todas as formas nunca é demais aprender, e agora fiquei deveras curioso com essa linguagem LISP... :)
 
O LISP é uma linguagem de programação funcional concebida por John McCarthy em 1958. Num célebre artigo este mostra que é possível usar exclusivamente funções matemáticas como estruturas de dados elementares (o que é possível a partir do momento em que há um mecanismo formal para manipular funções: o Cálculo Lambda de Church). Durante os anos de 1970 e 1980 o LISP se tornou a principal linguagem da comunidade de inteligência artificial, tendo sido pioneiro em aplicações como administração automática de armazenamento, linguagens interpretadas e programação funcional.

O seu nome vem de LISt Processing (a lista é a estrutura de dados fundamental desta linguagem). Tanto os dados como o programa são representados como listas o que permite que a linguagem manipule o código fonte como qualquer outro tipo de dados.

Existem diversos dialetos de Lisp, sendo os mais conhecidos o Common Lisp e o Scheme.

Fonte: Wiki

Na prática é um paradigma completamente diferente do imperativo (usado em C) e a estrutura de dados base, como está dito em cima, é a lista, ao invés do vector (mais usado em C), embora também o tenha.

O que eu chamo "o pão nosso de cada dia" em LISP é a recursão, as funções que recebem funções e as funções que devolvem funções. Em LISP estas operações, ao nível do programador, são extremamente simples, e permitem algo de maravilhoso que são as operações/funções de alto nível, que simplificam o código bastante.

Só tem um senão, que com o hábito o pessoal lá atina, que é a notação prefixa. Uma simples soma também é uma função, logo escreves o "+" e a seguir todos valores que queres somar, e se tens uma subtracção lá no meio idem. Há uns exemplos no link de cima.

Dado que estás na faculdade penso que irás dar alguma linguagem funcional e muito possivelmente será LISP.

Já agora, boa sorte para o exame! :D
 
Ah, então gryphus1 pode ser que não dês LISP na faculdade, é uma questão de veres o programa da tua licenciatura. Não conheço Haskell, por isso não sei se o que disse do LISP se possa dizer do Haskell.
 
aquilo que disseste para Lisp também se mantem no Haskell: é uma linguagem funcional (pura), usa listas em vez de array, usas recursividade em tudo quanto é lado, usas funções de ordem superior q.b., etc.
no entanto, no Haskell não tens o inconveniente das operações serem pre-fixas e tens uma notação mais simples (na minha opinião), mas próxima da linguagem matemática e do lambda calculus.

resumindo, Haskell é muito melhor do que Lisp :x2:
 
no entanto, no Haskell não tens o inconveniente das operações serem pre-fixas e tens uma notação mais simples (na minha opinião), mas próxima da linguagem matemática e do lambda calculus.

Ok, ok, a notação prefixa já tinha admitido que é um pouco chata ao início, mas trabalha um pouco com ela que depois vais ver que não queres outra coisa :D
 
Ok, ok, a notação prefixa já tinha admitido que é um pouco chata ao início, mas trabalha um pouco com ela que depois vais ver que não queres outra coisa :D

em Haskell temos as duas alternativas (para operadores binários): se <op> é infixo, então (<op>) é prefixo (p.e. + / (+)) :D
 
em Haskell temos as duas alternativas (para operadores binários): se <op> é infixo, então (<op>) é prefixo (p.e. + / (+)) :D

huuuummmmm... :D , ok, ganhas-te este round. A ver se dou uma espreitadela a esse Haskell um dia destes. Tem compilador, interpretador ou ambos?
 
GHCi ou Hugs, mas GHCi é melhor!

Vou experimentar então quando acabarem os meus exames :)

Verdade seja dita que o paradigma funcional é o que precebo e uso menos, mas talvez seja esse o fascínio que tenho por ele, principalmente o "mix" do funcional com orientação a objectos, algo que o Common LISP oferece.
 
Back
Topo