Question

Je souhaite créer une fonction qui exécute une fonction passée en paramètre sur un ensemble de données.Comment passer une fonction en paramètre en C ?

Était-ce utile?

La solution

Déclaration

Un prototype de fonction qui prend un paramètre de fonction ressemble à ceci :

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

Cela indique que le paramètre f sera un pointeur vers une fonction qui a un void type de retour et qui prend un seul int paramètre.La fonction suivante (print) est un exemple de fonction qui pourrait être transmise à func comme paramètre car c'est le bon type :

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

Appel de fonction

Lors de l'appel d'une fonction avec un paramètre de fonction, la valeur transmise doit être un pointeur vers une fonction.Utilisez pour cela le nom de la fonction (sans parenthèses) :

func(print);

j'appellerais func, en lui passant la fonction d'impression.

Corps de fonction

Comme pour tout paramètre, func peut désormais utiliser le nom du paramètre dans le corps de la fonction pour accéder à la valeur du paramètre.Disons que func appliquera la fonction à laquelle elle est transmise aux nombres 0-4.Considérons d’abord à quoi ressemblerait la boucle pour appeler directement print :

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

Depuis funcLa déclaration des paramètres de dit que f est le nom d'un pointeur vers la fonction recherchée, on rappelle d'abord que si f est un pointeur alors *f est la chose que f pointe vers (c.-à-d.la fonction print dans ce cas).En conséquence, remplacez simplement chaque occurrence de print dans la boucle ci-dessus par *f:

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

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

Autres conseils

Cette question a déjà la réponse pour définir des pointeurs de fonction, mais ils peuvent devenir très compliqués, surtout si vous comptez les transmettre dans votre application.Pour éviter ce désagrément, je vous recommande de saisir le pointeur de fonction en quelque chose de plus lisible.Par exemple.

typedef void (*functiontype)();

Déclare une fonction qui renvoie void et ne prend aucun argument.Pour créer un pointeur de fonction vers ce type vous pouvez maintenant faire :

void dosomething() { }

functiontype func = &dosomething;
func();

Pour une fonction qui renvoie un int et prend un caractère, vous feriez

typedef int (*functiontype2)(char);

et pour l'utiliser

int dosomethingwithchar(char a) { return 1; }

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

Il existe des bibliothèques qui peuvent aider à transformer les pointeurs de fonction en types lisibles.Le fonction boost la bibliothèque est géniale et en vaut la peine !

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

est tellement plus agréable que ce qui précède.

Depuis C++11, vous pouvez utiliser le bibliothèque fonctionnelle de le faire de manière succincte et générique.La syntaxe est, par exemple,

std::function<bool (int)>

bool est ici le type de retour d'une fonction à un argument dont le premier argument est de type int.

J'ai inclus un exemple de programme ci-dessous :

// 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);
}

Parfois, cependant, il est plus pratique d’utiliser une fonction de modèle :

// 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);
}

Passer adresse d'une fonction en paramètre d'une autre fonction comme indiqué ci-dessous

#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();
}

Nous pouvons également passer une fonction comme paramètre en utilisant pointeur de fonction

#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();
}

Vous devez passer un pointeur de fonction.La syntaxe est un peu lourde, mais elle est vraiment puissante une fois qu'on s'y est familiarisé.

Les fonctions peuvent être « transmises » en tant que pointeurs de fonction, conformément à 6.7.6.3p8 :"Une déclaration d’un paramètre comme « type de retour de fonction » doit être ajustée en « pointeur vers le type de retour de fonction », comme au § 6.3.2.1. ".Par exemple, ceci :

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

est équivalent à ceci :

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

Ce n'est pas vraiment une fonction, mais c'est un morceau de code localisé.Bien sûr, il ne transmet pas le code uniquement le résultat.Cela ne fonctionnera pas s'il est transmis à un répartiteur d'événements pour être exécuté ultérieurement (car le résultat est calculé maintenant et non lorsque l'événement se produit).Mais il localise votre code en un seul endroit si c'est tout ce que vous essayez de faire.

#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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top