[Solucionado] Pasar una función como parámetro en C.

Iniciado por NOB2014, 24 Septiembre 2016, 21:41 PM

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

xiruko

#10
Cita de: NOB2014 en 24 Septiembre 2016, 21:41 PM
Hola, que tengan un muy buen día.
En mi post anterior utilice este tipo de llamada a función y todo correcto, pero ahora no logro que funcione, reconozco que si leyera en inglés tal vez podría saber el porqué del error pero recién estoy comenzando con el idioma. -

Hola, creo que lo que quieres conseguir se hace con punteros a funciones. Deberías buscar en google ya que hay bastante información. Igualmente te paso un ejemplo tonto:

#include <stdio.h>

int sumar(int a, int b);
int restar(int a, int b);
int calculadora(int (*pfunc)(int, int), int a, int b);

int main()
{
printf("Suma = %d\n", calculadora(sumar, 7, 4));
printf("Resta = %d\n", calculadora(restar, 7, 4));
return 0;
}

int calculadora(int (*pfunc)(int, int), int a, int b) {
return ((*pfunc)(a, b));
}
int sumar(int a, int b) {
return a+b;
}
int restar(int a, int b) {
return a-b;
}


Como ves a la función calculadora le debes pasar como parámetro la función a utilizar. Para pasar la función se usa un puntero, y éste tiene la siguiente forma:

tipo return (nombre_puntero*)(tipo parametro1, tipo parametro2, ...)

De ahí lo de (int)(pfunc*)(int, int), ya que ambas funciones sumar y restar reciben dos enteros y devuelven un entero.

EDIT: Se me olvidaba, implementando esto en tu código quedaría así:

#include <stdio.h>

void uno(void (*pfunc)(void));
void dos();

int main(void)
{
uno(dos);
return 0;
}

void uno(void (*pfunc)(void)) {
printf("Uno\n");
(*pfunc)();
}
void dos(){
printf("Dos\n");
}


Saludos!

dato000

Ahi estas llamando una función dentro otra.

Daria lo mismo:

void uno(void (*pfunc)(void)) {
printf("Uno\n");
(*pfunc)();
}


que usar una función:


void uno() {
printf("Uno\n");
printf("Dos\n");
}


Simplemente para un caso de este tipo es absurdo este tipo de procedimientos. Es complicarse la vida  >:(



xiruko

#12
Cita de: dato000 en 25 Septiembre 2016, 04:25 AM
Ahi estas llamando una función dentro otra.

Daria lo mismo:

void uno(void (*pfunc)(void)) {
printf("Uno\n");
(*pfunc)();
}


que usar una función:


void uno() {
printf("Uno\n");
printf("Dos\n");
}


Simplemente para un caso de este tipo es absurdo este tipo de procedimientos. Es complicarse la vida  >:(

No es lo mismo una cosa y otra. Usando punteros a funciones dejas al usuario que elija qué procedimiento usar, y también le das opción para que él defina uno y se lo pase a la función (aka callbacks).

Y sí, para este caso es absurdo pero entiendo que NOB2014 publicó un código simple de ejemplo para este problema.

Saludos!

NOB2014

Hola. -
Tanto practicar llegue a la conclusión que lo que me funciona como lo que yo esperaba es el código de MAFUS, (no deseo con esto ofender ni menospreciar al resto que deseo ayudarme) pero igual desearía que alguien me pase el código que muestro a continuación a cadena, o sea, que en vez de mostrar 1 y 2 muestre uno y dos. -
Estuve practicando un rato largo y me da demasiados errores, hasta utilice malloc y nada. -

#include <stdio.h>
     
int a();
void b(int num);
     
int main(void){
     
b(a());
   
return 0;
}

int a() {
printf("num = %d\n\n", 1);
return 2;
}

void b(int num) {
    printf("num = %d\n\n", num);
}
   


desde ya muchas gracias, si es mucho pedir, disculpas. -
Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

Ese código es correcto.

Pasar como argumento una "llamada a función", intuyo que te refieres a pasar como argumento el retorno de una función.

Tu código es igual a este:

#include <stdio.h>

int a();
void b(int num);

int main(void){
int t = a();
b(t);

return 0;
}

int a() {
printf("num = %d\n\n", 1);
return 2;
}

void b(int num) {
printf("num = %d\n\n", num);
}




La otra interpretación, era la que te comentaron por ahí, que es pasar como parámetro una función en sí.
#include <stdio.h>

void call(void (*func)());
void a();
void b();

int main(void){

call(&a);
call(&b);

return 0;
}

void call(void (*func)()){
func();
}

void a() {
printf("num = %d\n\n", 1);
}

void b() {
printf("num = %d\n\n", 2);
}


Si dices que un código te da errores, copia también esos errores aquí.

NOB2014

#include <stdio.h>
     
char a();
void b( char dos );
     
int main(void){
     
b(a());
   
return 0;
}

char a() {
char dos[] = "dos";
printf("frase uno = %s\n\n", "uno");
return dos;
}

void b(char dos) {
    printf("\n frase dos = = %s\n\n", dos);
}


Citarrepaso.c: In function 'a':
repaso.c:16:2: warning: return makes integer from pointer without a cast [enabled by default]
  return dos;
  ^

Citarrepaso.c:16:2: warning: function returns address of local variable [-Wreturn-local-addr]
repaso.c: In function 'b':
repaso.c:20:5: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat=]
     printf("\n frase dos = = %s\n\n", dos);
     ^

Esto es exactamente como quiero que quede el código, sin errores claro. -

Un abrazo amigo y gracias por ocuparte. -
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

#16
Vale. No confundas char con char[] o char*.
char es 1 caracter, que en C es un entero de 8 bits.
char[] y char* son punteros, que apuntan a un (o varios) char.

De ahí el error: return makes integer from pointer without a cast
Es decir, en el retorno, estás convirtiendo un puntero (char[]) a un entero (char) sin un cast explícito, que sería:
return (char)dos;

El segundo error es lo mismo prácticamente. printf espera una cadena (%s, char*), y le estás pasando un entero (char).


Aquí la solución es colocar los tipos correctos:
#include <stdio.h>

char* a();
void b( char* dos );

int main(void){

b(a());

return 0;
}

char* a() {
char* dos = "dos";
printf("frase uno = %s\n\n", "uno");
return dos;
}

void b(char* dos) {
printf("frase dos = %s\n\n", dos);
}


Ahora b coge un parámetro char*. Por tanto, a retorna un parámetro char*.


Edito: Por si acaso, aclarar una cosa: no debes retornar un array de tipo char[]. En vez de eso, deberías utilizar malloc, llenar ese array, y retornarlo.
Una explicación más larga con ejemplos la tienes aquí. Está en inglés, pero los ejuemplos son auto-explicativos: http://stackoverflow.com/questions/31060404/how-can-i-return-a-character-array-from-a-function-in-c

NOB2014

Siiiiiiiiiiiiiiiiiiiiiiiiiiii, sublime, maravilloso, eso es lo que quería. -
No teneos una idea como me aclararte las cosas, ahora algo más que quiero que me digas si es posible:
En esta llamada a función, puedo pasar parámetros.

b(a());

abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

MAFUS

Si b está declatada como b() o b(void) no puedes porque no espera argumento alguno.
Pero, lo dicho, si b espera almenos un argumento b(int n) sí puede recibir una función que devuelva ese argumento esperado int a(), quedando de la forma que hemos dicho: b(a())

NOB2014

Bueno todo solucionado, pido mil disculpas a todos los que participaron por utilizar demasiado su tiempo, realmente creí que algo más sencillo, pero evidentemente y como muchas veces me ocurre me cuesta hacer que me entiendan, hubo por ahí un comentario pre juicioso que me pareció que estuvo de más, pero todo bien. -
Dejo el código para demostrar del todo lo que quería lograr, por último, por lo que pedí ayuda no fue algo caprichoso, lo que ocurre es que en casi todas mis practicas suelo llamar a una función dentro del cuerpo de otra y me parece que de esta forma queda más legible. -

#include <stdio.h>

char* a();
void b( char* dos, int x );

int main(void){
int x = 5;
b(a(), x);

return 0;
}

char* a() {
char* dos = "dos";
printf(" frase uno = %s\n", "uno");
return dos;
}

void b(char* dos, int x) {
printf(" frase dos = %s", dos);
printf("\n numero = %d\n", x);
}
   

Saludos y muchas gracias a todos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-