Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 24 Septiembre 2016, 21:41 pm



Título: [Solucionado] Pasar una función como parámetro en C.
Publicado por: 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. -

Código
  1. #include <stdio.h>
  2.  
  3. void uno( );
  4. void dos( );
  5.  
  6.  
  7. int main(void){
  8.  
  9. uno( dos() );
  10.  
  11. return 0;
  12. }
  13.  
  14. void uno(  ){
  15. printf( "\n Uno " );
  16. }
  17.  
  18. void dos(  ){
  19. printf( "\n dos" );
  20. }
  21.  

Saludos y desde ya muchas gracias. -


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: Arturo400 en 24 Septiembre 2016, 21:45 pm
En la linea 9 cuando llamas a la funcion 2 es sin parentesis
Quedaria uno(dos);
Tene en cuenta que a la funcion uno le estas pasando como parametro algo, y ese parametro va sin corchetes ni parentesis en el llamado.


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 24 Septiembre 2016, 22:31 pm
Hola, Arturo400. -
Si bien no me da error sólo imprime Uno y no Uno y dos.



Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: MCKSys Argentina en 24 Septiembre 2016, 22:42 pm
Hola!

No sé mucho de C++, pero creo que estás confundiendo las cosas:

Tu primer post dice que quieres pasar una función como parámetro. Para hacerlo, debes seguir lo que te dijo Arturo400.

Ahora, tu último post dice que la función que pasas como parámetro, no se ejecuta. Lo cual es lógico pues cuando la pasas como parámetro, lo que haces es pasar la dirección de memoria de donde está dicha función, no ejecutarla.

En tu ejemplo, si quieres ejecutar la función dos (que pasas como parametro), deberás modificar el codigo de uno, para que se llame la funcion pasada.

Encontré éste post (http://stackoverflow.com/questions/9410/how-do-you-pass-a-function-as-a-parameter-in-c) que puede ayudarte (si, está en inglés.)

Saludos!


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: dato000 en 25 Septiembre 2016, 02:08 am
Esta mal declarada la función uno, la cuál debe declararse con una estructura que reciba una función vacia como parametro ( dos() ) y así ejecutar ese metodo que se necesita.

Código
  1. #include <stdio.h>
  2.  
  3. void uno( void ()  );
  4. void dos( );
  5.  
  6.  
  7. int main(void){
  8.  
  9. uno( dos );
  10.  
  11. return 0;
  12. }
  13.  
  14. void uno( void funcionDos() ){
  15. printf( "\n Uno " );
  16. }
  17.  
  18. void dos(  ){
  19. printf( "\n dos" );
  20. }
  21.  

En lo personal este tipo de declaraciones en C son horrendas, pues al ser programación estructurada no es lo ideal en la forma de escribir código, es mejor usar funciones directas o virtuales para ejecutar este tipo de funciones, luego en C++ ya existe el encapsulamiento y declaraciones para ejecutar nuevas instancias de objetos, que facilitan mucho el desarrollo.

Supongo que será más un tema de aprendizaje, lo cuál viene bien.


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: MAFUS en 25 Septiembre 2016, 02:13 am
Uno es una función sin argumentos pero cuando la llamas le pasas la función dos, lo que C no se lo espera.

Esta técnica sirve cuándo una función pide un argumento, por ejemplo un entero, ahí puedes llamar una función que devuelva un entero. Ésta última se evalúa y el valor que retorna es el que usará la primera función.

Por ejemplo
Código
  1. int a() {
  2.    return 3;
  3. }
  4.  
  5. void b(int num) {
  6.    printf("num = %d", num);
  7. }
  8.  
  9. // ...
  10. // Llamada a b pasando a como argumento
  11. b(a());
  12.  


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 02:41 am
Hola a todos.
MCKSys Argentina, gracias por la página que me apuntaste, pero todavía no si es lo que busco. -
dato000 me resulta lo mismo que antes, compila perfecto, pero me imprime solamente Uno. -

Saludos.


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: dato000 en 25 Septiembre 2016, 02:49 am
Hola a todos.
MCKSys Argentina, gracias por la página que me apuntaste, pero todavía no si es lo que busco. -
dato000 me resulta lo mismo que antes, compila perfecto, pero me imprime solamente Uno. -

Saludos.

Pues eso es exactamente lo que hace, que querias que hiciera???


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 02:53 am
Que me imprima "Uno" y en la línea siguiente "dos"


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: dato000 en 25 Septiembre 2016, 03:00 am
Que me imprima "Uno" y en la línea siguiente "dos"

No se puede hacer de esa manera, lo mejor en ese caso seria:

Código
  1. #include <stdio.h>
  2.  
  3. void uno( void ()  );
  4. void dos( void () );
  5.  
  6.  
  7. int main(void){
  8.  
  9. uno( dos );
  10. dos( uno );
  11.  
  12. return 0;
  13. }
  14.  
  15. void uno( void funcionDos() ){
  16. printf( "\n Uno " );
  17. }
  18.  
  19. void dos( void funcionUno() ){
  20. printf( "\n dos" );
  21. }
  22.  

Eso es debido a que esas funciones no retornan ni toman argumentos, por lo que deben ser invocadas linealmente una y luego la otra para que se ejecuten.

En este caso, es lo mismo llamar a void uno() que void uno( void Dos), pues son funciones que solo imprimen un texto diseñado en tiempo de compilación y se muestra directamente al usuario sin tener ninguna clase de persistencia.


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: xiruko en 25 Septiembre 2016, 03:50 am
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:

Código
  1. #include <stdio.h>
  2.  
  3. int sumar(int a, int b);
  4. int restar(int a, int b);
  5. int calculadora(int (*pfunc)(int, int), int a, int b);
  6.  
  7. int main()
  8. {
  9. printf("Suma = %d\n", calculadora(sumar, 7, 4));
  10. printf("Resta = %d\n", calculadora(restar, 7, 4));
  11. return 0;
  12. }
  13.  
  14. int calculadora(int (*pfunc)(int, int), int a, int b) {
  15. return ((*pfunc)(a, b));
  16. }
  17. int sumar(int a, int b) {
  18. return a+b;
  19. }
  20. int restar(int a, int b) {
  21. return a-b;
  22. }

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í:

Código
  1. #include <stdio.h>
  2.  
  3. void uno(void (*pfunc)(void));
  4. void dos();
  5.  
  6. int main(void)
  7. {
  8. uno(dos);
  9. return 0;
  10. }
  11.  
  12. void uno(void (*pfunc)(void)) {
  13. printf("Uno\n");
  14. (*pfunc)();
  15. }
  16. void dos(){
  17. printf("Dos\n");
  18. }

Saludos!


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: dato000 en 25 Septiembre 2016, 04:25 am
Ahi estas llamando una función dentro otra.

Daria lo mismo:
Código
  1. void uno(void (*pfunc)(void)) {
  2. printf("Uno\n");
  3. (*pfunc)();
  4. }

que usar una función:

Código
  1. void uno() {
  2. printf("Uno\n");
  3. printf("Dos\n");
  4. }

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


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: xiruko en 25 Septiembre 2016, 06:23 am
Ahi estas llamando una función dentro otra.

Daria lo mismo:
Código
  1. void uno(void (*pfunc)(void)) {
  2. printf("Uno\n");
  3. (*pfunc)();
  4. }

que usar una función:

Código
  1. void uno() {
  2. printf("Uno\n");
  3. printf("Dos\n");
  4. }

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!


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 15:00 pm
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. -

Código
  1. #include <stdio.h>
  2.  
  3. int a();
  4. void b(int num);
  5.  
  6. int main(void){
  7.  
  8. b(a());
  9.  
  10. return 0;
  11. }
  12.  
  13. int a() {
  14. printf("num = %d\n\n", 1);
  15. return 2;
  16. }
  17.  
  18. void b(int num) {
  19.    printf("num = %d\n\n", num);
  20. }
   


desde ya muchas gracias, si es mucho pedir, disculpas. -
Saludos.


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: ivancea96 en 25 Septiembre 2016, 15:51 pm
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:

Código
  1. #include <stdio.h>
  2.  
  3. int a();
  4. void b(int num);
  5.  
  6. int main(void){
  7. int t = a();
  8. b(t);
  9.  
  10. return 0;
  11. }
  12.  
  13. int a() {
  14. printf("num = %d\n\n", 1);
  15. return 2;
  16. }
  17.  
  18. void b(int num) {
  19. printf("num = %d\n\n", num);
  20. }



La otra interpretación, era la que te comentaron por ahí, que es pasar como parámetro una función en sí.
Código
  1. #include <stdio.h>
  2.  
  3. void call(void (*func)());
  4. void a();
  5. void b();
  6.  
  7. int main(void){
  8.  
  9. call(&a);
  10. call(&b);
  11.  
  12. return 0;
  13. }
  14.  
  15. void call(void (*func)()){
  16. func();
  17. }
  18.  
  19. void a() {
  20. printf("num = %d\n\n", 1);
  21. }
  22.  
  23. void b() {
  24. printf("num = %d\n\n", 2);
  25. }

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


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 16:03 pm
Código
  1. #include <stdio.h>
  2.  
  3. char a();
  4. void b( char dos );
  5.  
  6. int main(void){
  7.  
  8. b(a());
  9.  
  10. return 0;
  11. }
  12.  
  13. char a() {
  14. char dos[] = "dos";
  15. printf("frase uno = %s\n\n", "uno");
  16. return dos;
  17. }
  18.  
  19. void b(char dos) {
  20.    printf("\n frase dos = = %s\n\n", dos);
  21. }

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

Citar
repaso.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. -


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: ivancea96 en 25 Septiembre 2016, 16:32 pm
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:
Código
  1. 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:
Código
  1. #include <stdio.h>
  2.  
  3. char* a();
  4. void b( char* dos );
  5.  
  6. int main(void){
  7.  
  8. b(a());
  9.  
  10. return 0;
  11. }
  12.  
  13. char* a() {
  14. char* dos = "dos";
  15. printf("frase uno = %s\n\n", "uno");
  16. return dos;
  17. }
  18.  
  19. void b(char* dos) {
  20. printf("frase dos = %s\n\n", dos);
  21. }

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 (http://stackoverflow.com/questions/31060404/how-can-i-return-a-character-array-from-a-function-in-c)


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 16:57 pm
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());



Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: MAFUS en 25 Septiembre 2016, 17:26 pm
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())


Título: Re: Llamas a función y pasar como argumento otra llamada a función [C]
Publicado por: NOB2014 en 25 Septiembre 2016, 17:54 pm
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. -

Código
  1. #include <stdio.h>
  2.  
  3. char* a();
  4. void b( char* dos, int x );
  5.  
  6. int main(void){
  7. int x = 5;
  8. b(a(), x);
  9.  
  10. return 0;
  11. }
  12.  
  13. char* a() {
  14. char* dos = "dos";
  15. printf(" frase uno = %s\n", "uno");
  16. return dos;
  17. }
  18.  
  19. void b(char* dos, int x) {
  20. printf(" frase dos = %s", dos);
  21. printf("\n numero = %d\n", x);
  22. }
   

Saludos y muchas gracias a todos.