funcion como argumento a otra funcion

Iniciado por Dark Invader, 29 Junio 2011, 00:15 AM

0 Miembros y 1 Visitante están viendo este tema.

Dark Invader

Hola a todos,

Tenía una duda sobre este codigo:

#include <stdio.h>
double inversos(int k);
double cuadrados(int k);
double funcsuma(int n,double (*f)(int k));

int main(){
printf("Suma de cinco inversos: %.3f \n",funcsuma(5,inversos));
printf("Suma de tres cuadrados: %.3f \n",funcsuma(3,cuadrados));
}
double funcsuma(int n,double(*f)(int k)){
double s= 0;
int i;
for (i=1;i<=n;i++)
s+=f(i);
return s;
}
double inversos(int k){
return 1.0/k;}
double cuadrados(int k){
return (double) k* k;
}


Resulta que no tengo ni idea de que realiza funcsuma(osea,lo de dentro del codigo si,lo que no entiendo es como luego se puede unir a las otras dos funciones) y porque luego se pone:

printf("Suma de cinco inversos: %.3f \n",funcsuma(5,inversos));
printf("Suma de tres cuadrados: %.3f \n",funcsuma(3,cuadrados));


Si alguien me lo pudiera explicar me haría un gran favor.

Gracias por adelantado.

Un saludo

Littlehorse

Esta usando un puntero a función.

#include <stdio.h>
double inversos(int k);
double cuadrados(int k);
double funcsuma(int n,double (*f)(int k)); //f es un puntero a funcion

int main(){
printf("Suma de cinco inversos: %.3f \n",funcsuma(5,inversos)); //Pasa la direccion de inversos
printf("Suma de tres cuadrados: %.3f \n",funcsuma(3,cuadrados)); //Pasa la direccion de cuadrados
}
double funcsuma(int n,double(*f)(int k)){ //f recibe la dirección de la función
double s= 0;
int i;
for (i=1;i<=n;i++)
s+=f(i); //Llamada a la función correspondiente pasandole el valor de i
return s;
}
double inversos(int k){
return 1.0/k;}
double cuadrados(int k){
return (double) k* k;
}


En este caso el valor de retorno y los parámetros son exactamente los mismos por lo que es sencillo hacer una especie de puntero a función "genérico".
Busca sobre punteros a función.

Saludos!
An expert is a man who has made all the mistakes which can be made, in a very narrow field.

leogtz

#2
Si se te complica entender un poco, personalmente me gusta más manejar las cosas así, aunque basicamente es la misma, pero bueno, me ayuda a entender.

#include <stdio.h>
double inversos (int k);
double cuadrados (int k);
double funcsuma (int n, double (*f) (int k)); //f es un puntero a funcion

int main ()
{
    double (*pf)(int, double (*)(int)) = &funcsuma;
    printf ("Suma de cinco inversos: %.3f \n", pf(5, inversos)); //Pasa la direccion de inversos
    printf ("Suma de tres cuadrados: %.3f \n", pf(3, cuadrados)); //Pasa la direccion de cuadrados
    return 0;
}

double funcsuma (int n, double (*f) (int k))
{ //f recibe la dirección de la función
  double s = 0;
  int i;
  for (i = 1; i <= n; i++)
    s += f (i); //Llamada a la función correspondiente pasandole el valor de i
  return s;
}

double inversos (int k)
{
  return 1.0 / k;
}

double cuadrados (int k)
{
  return (double) k *k;
}
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Dark Invader

Gracias a ambos por contestar,he estado buscando y buscando y nada,que no me entra,he encontrado un ejemplo en este mismo foro:

int (*punt) (int,int);

  int suma(int a , int b){
     return a+b;
  }

  int resta(int a , int b){
     return a-b;
  }

  *punt=suma;
   punt(2,3);

  *punt=resta;
   punt(5,1);


Este lo entiendo bien pero el que puse....Se me hace un poco complicado y eso que he buscado,incluso por youtube para ver si habia algun tutorial pero sin resultados...

Mis dudas principalmente son estas:

Dentro de la funcion double funcsuma (int n, double (*f) (int k))

No se que pinta ahi el f(i),deduzco que f es el puntero pero no se...

Y luego esto:

printf ("Suma de cinco inversos: %.3f \n", pf(5, inversos)); //Pasa la direccion de inversos
    printf ("Suma de tres cuadrados: %.3f \n", pf(3, cuadrados)); //Pasa la direccion de cuadrados


Aunque Leo me ha pasado otro pero sigo sin entenderlo...

    printf ("Suma de cinco inversos: %.3f \n", pf(5, inversos)); //Pasa la direccion de inversos
    printf ("Suma de tres cuadrados: %.3f \n", pf(3, cuadrados)); //Pasa la direccion de cuadrados


Gracias a ambos.

Un saludo

leogtz

Te dejo el código que use comentado para que se entienda un poco mejor:

#include <stdio.h>
double inversos (int k);
double cuadrados (int k);
double funcsuma (int n, double (*f)(int k));
/* f es un puntero a función que acepta como argumento un int y que devuelve un double */
/* Es la manera correcta de describir ese parámetro en la función funcsuma */

int main(void)
{
    double (*pf)(int, double (*)(int)) = &funcsuma;

    /* pf es un puntero a función */
    /* pf acepta como argumentos :

    {
        un int
        un puntero a función que acepta un int y que devuelve un double
    }

    Al puntero a función pf le asignamos la dirección de memoria de la función funcsuma
    De ahí que usemos el operador &, aunque se puede omitir.

    */

    /* Invocamos a la función funcsuma a través del puntero que acabamos de declarar que apunta hacia ella */
    /* Como puedes ver, utilizamos los mismos argumentos que la función necesita
         int     double (*)(int)
    pf(   5,         &inversos )

    Pasamos por referencia la función inversos

    */

    printf ("Suma de cinco inversos: %.3f \n", pf(5, &inversos)); //Pasa la direccion de inversos

    printf ("Suma de tres cuadrados: %.3f \n", pf(3, &cuadrados)); //Pasa la direccion de cuadrados
    return 0;
}

double funcsuma (int n, double (*f) (int k))
{ //f recibe la dirección de la función
  double s = 0;
  int i;
  for (i = 1; i <= n; i++)
    s += f (i); //Llamada a la función correspondiente pasandole el valor de i

    /*

    s += f(i);

    Se llama a la función correspondiente, según hallamos invocado.
    pf(5, &inversos) -> s += inversos(i);
    pf(3, &cuadrados) -> s += cuadrados(i)

    */


  return s;
}

double inversos (int k)
{
  return 1.0 / k;
}

double cuadrados (int k)
{
  return (double) k *k;
}
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Dark Invader

Osea,que inversos es un puntero a una funcion que acepta un int y devuelve un double¿no?

Y pf guarda la direccion de memoria de funcsuma¿no?

La verdad es que me esta costando aprenderlo,el otro ejemplo que puse que vi por el foro no era tan complicado  >:(

Un saludo y gracias