Pergunta

Quero criar uma função que execute uma função passada por parâmetro em um conjunto de dados.Como você passa uma função como parâmetro em C?

Foi útil?

Solução

Declaração

Um protótipo para uma função que recebe um parâmetro de função se parece com o seguinte:

void func ( void (*f)(int) );

Isso afirma que o parâmetro f será um ponteiro para uma função que possui um void tipo de retorno e que leva um único int parâmetro.A seguinte função (print) é um exemplo de função que pode ser passada para func como parâmetro porque é o tipo adequado:

void print ( int x ) {
  printf("%d\n", x);
}

Chamada de Função

Ao chamar uma função com um parâmetro de função, o valor passado deve ser um ponteiro para uma função.Use o nome da função (sem parênteses) para isso:

func(print);

ligaria func, passando a função de impressão para ele.

Corpo funcional

Como acontece com qualquer parâmetro, func agora pode usar o nome do parâmetro no corpo da função para acessar o valor do parâmetro.Digamos que func aplicará a função passada para os números de 0 a 4.Considere, primeiro, como seria o loop para chamar print diretamente:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

Desde funca declaração do parâmetro diz que f é o nome de um ponteiro para a função desejada, lembramos primeiro que se f é um ponteiro então *f é a coisa que f aponta para (ou seja,a função print nesse caso).Como resultado, basta substituir todas as ocorrências de print no loop acima por *f:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

De http://math.hws.edu/bridgeman/courses/331/f05/handouts/c-c++-notes.html

Outras dicas

Esta pergunta já tem a resposta para definir ponteiros de função, porém eles podem ficar muito confusos, especialmente se você for repassá-los em seu aplicativo.Para evitar esse desconforto eu recomendo que você digite o ponteiro da função em algo mais legível.Por exemplo.

typedef void (*functiontype)();

Declara uma função que retorna nula e não aceita argumentos.Para criar um ponteiro de função para este tipo agora você pode fazer:

void dosomething() { }

functiontype func = &dosomething;
func();

Para uma função que retorna um int e recebe um char você faria

typedef int (*functiontype2)(char);

e para usá-lo

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

Existem bibliotecas que podem ajudar a transformar ponteiros de função em tipos legíveis.O função de impulso a biblioteca é ótima e vale a pena o esforço!

boost::function<int (char a)> functiontype2;

é muito melhor do que o acima.

Desde C++ 11 você pode usar o biblioteca funcional fazer isso de forma sucinta e genérica.A sintaxe é, por exemplo,

std::function<bool (int)>

onde bool é o tipo de retorno aqui de uma função de um argumento cujo primeiro argumento é do tipo int.

Incluí um programa de exemplo abaixo:

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

Às vezes, porém, é mais conveniente usar uma função de modelo:

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

Passar endereço de uma função como parâmetro para outra função como mostrado abaixo

#include <stdio.h>

void print();
void execute(void());

int main()
{
    execute(print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f()) // receive address of print
{
    f();
}

Também podemos passar a função como parâmetro usando ponteiro de função

#include <stdio.h>

void print();
void execute(void (*f)());

int main()
{
    execute(&print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)()) // receive address of print
{
    f();
}

Você precisa passar um ponteiro de função.A sintaxe é um pouco complicada, mas é realmente poderosa quando você se familiariza com ela.

As funções podem ser "passadas" como ponteiros de função, conforme 6.7.6.3p8:"Uma declaração de um parâmetro como ‘‘tipo de retorno de função’’ deve ser ajustada para ‘‘ponteiro para tipo de retorno de função’’, como em 6.3.2.1. ".Por exemplo, isto:

void foo(int bar(int, int));

é equivalente a isto:

void foo(int (*bar)(int, int));

Não é realmente uma função, mas é um trecho de código localizado.Claro que não passa o código apenas o resultado.Não funcionará se for passado para um despachante de eventos para ser executado posteriormente (já que o resultado é calculado agora e não quando o evento ocorre).Mas ele localiza seu código em um só lugar, se isso é tudo que você está tentando fazer.

#include <stdio.h>

int IncMultInt(int a, int b)
{
    a++;
    return a * b;
}

int main(int argc, char *argv[])

{
    int a = 5;
    int b = 7;

    printf("%d * %d = %d\n", a, b, IncMultInt(a, b));

    b = 9;

    // Create some local code with it's own local variable
    printf("%d * %d = %d\n", a, b,  ( { int _a = a+1; _a * b; } ) );

    return 0;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top