VARIABLES DE PUNTERO A FUNCIONES Las variables de puntero a funciones son variables que almacenan la dirección de memoria donde comienza una función o un procedimiento. Para declararlas se debe indicar además del nombre antecedido por el símbolo asterisco el tipo de valor de retorno y el tipo de parámetros. Por ejemplo. double (* fa)( double ) significa que fa puede almacenar la dirección de memoria de cualquier función que devuelve un valor de tipo double y a la que hay que pasarle un valor de tipo double. Por ejemplo la función de librería sin puede almacenarse en dicha variable de puntero. void(*px)(char *, char *, int ) significa que px puede almacenar la dirección de memoria de cualquier procedimiento al que hay que pasarle dos cadenas de caracteres y un valor entero. Por ejemplo la función de librería sin puede almacenarse en dicha variable de puntero. El siguiente código ilustra la utilización de las variables de puntero. #include <math.h> #include <stdio.h> double secante( double x ) { return ( 1.0 / cos(x); } main() { double x, y; double(*trig)(double); //declaración de trig como variable de puntero a una función /* observar aquí como se utilizan las variables de puntero a función. Primero asignamos a la variable de puntero trig el nombre de una función existente ya sea de librería o creada por el usuario. Luego la variable de puntero se utiliza como si fuera la función misma. */ trig = sin; x = trig( 1.35 ); trig = secante; y = trig( 1.35 ); printx(“%lf\n”, x ); //mostramos el seno de 1.35 radianes printx(“%lf\n”, y ); //mostramos la secante de 1.35 radianes } Ejercicio de ejemplo El siguiente ejercicio va a crear un procedimiento que ordene un vector de n términos de cualquier tipo de datos por el método de la burbuja. El procedimiento será de la forma: burbuja( void * a, int tam, int terms, int (*funcmp)(void *, void * ) ); siendo: a un vector de cualquier tipo. tam el tamaño en bytes que tiene cada término del vector. terms el número de términos del vector. funcmp es una variable de puntero a una función que indicará el criterio de comparación. Devolverá un entero mayor que cero si el bloque de memoria que corresponde al parámetro de la izquierda es mayor que el de la derecha, menor que cero si es menor y cero si los dos bloques son iguales de acuerdo con un criterio definido por una función creada por el usuario. #include <mem.h> #include <alloc.h> void cambiarbloque( void * a, void * b, int tam ); void burbuja( void * a, int tam, int terms, int (*funcmp)( void *, void * ) ) { int i, j; //variables de conteo unsigned char * ai, *aj; //para que al sumar se me desplace un byte /* las variables de puntero a char ai y aj se utilizan porque a las variables de tipo void no se les puede aplicar la suma puesto que no tienen tamaño conocido. Se selecciona el tipo unsigned char por tener una longitud de un byte. */ for( i = 0, ai = (unsigned char *)a; i < (terms-1); i++, ai+= tam ) {//metodo del método de burbuja for( j = i , aj = ai; j < terms; j++, aj+= tam ) { /* observar que con i y j llevamos la cuenta de los términos y con ai y aj apuntamos a la dirección de memoria de los distintos términos del vector. */ if( funcmp( ai, aj ) > 0 ) //llamamos a la función que pasamos como parámetro { cambiarbloque( ai, aj, tam ); //Ver el desarrollo de la función que intercambia bloques } } } } //------------------------------------------------------------------------------------------------------------------------------------------void cambiarbloque( void * a, void * b, int tam ) { /* Utilizamos esta función para intercambiar bloques de memoria. Equivale a intercambiar valores de variables. Los parámetros son: a apunta a un bloque de memoria b apunta a un segundo bloque de memoria tam es el tamaño en bytes de cada bloque. */ void * aux = malloc( tam ); //alocamos memoria para búfer auxiliar de tam bytes /* Los llamados sucesivos a la función memcpy efectúa el intercambio de valores de los bloques de memoria. */ memcpy(aux, a, tam ); memcpy(a, b, tam ); memcpy(b, aux, tam ); free( aux );//liberamos aux } Programas de Ejemplo. Utilizaremos la función desarrollada anteriormente, primero para hacer un ordenamiento de un vector con números enteros y luego un vector de estructuras de tipo punto. Ejemplo 1. Ordenamiento de un vector de números enteros. int intcomp( void * a, void * b ) { /* función que vamos a pasar como parámetro para comparar dos números enteros. Definimos dos variables x e y de tipo entero donde se indirecciona como números enteros los punteros a y b pasados como parámetros. Las comparamos y devolvemos un valor diferente ya sea que x sea mayor, menor o igual a y */ int x = *( (int *)a );//indireccionamos lo apuntado como entero int y = *( (int *)b ); if( x > y ) { return 1; } if( x < y ) { return -1; } return 0; } int main(int argc, char* argv[]) { int i, j, cant; int *a; printf ( "entre terminos "); scanf( "%d", &cant ); a = (int *)malloc( cant * sizeof(int) ); for( i = 0; i < cant; i++ ) { a[i] = random( 500 ); printf( "%d\t", a[i] ); } burbuja( a, sizeof(int), cant, intcomp ); //llamado a la función burbuja printf( "\n\n" ); for( i = 0; i < cant; i++ ) { printf( "%d\t", a[i] ); } free( a ); } Ejemplo 2. Ordenamiento de un vector de estructuras punto en sentido creciente de los valores de y. struct punto { double x, y; }; int pcomp ( void * a, void * b ) { /* función que vamos a pasar como parámetro para comparar dos estructuras punto. Definimos dos variables p1 y p2 de tipo estructura punto donde se indirecciona como punto los punteros a y b pasados como parámetros. Las comparamos y devolvemos un valor diferente ya sea que p1.y sea mayor, menor o igual a p2.y */ punto p1 = *((punto*)a); punto p2 = *((punto*)b); if( p1.y > p2.y ) { return 1; } if( p1.y < p2.y ) { return -1; } return 0; } int main(int argc, char* argv[]) { int i, cant; punto * p; printf ( "Cuantos puntos "); scanf( "%d", &cant ); p = (punto *) malloc ( cant * sizeof(punto) ); for( i = 0; i < cant; i++ ) { p[i].x = random(500); //para dar valores decimales p[i].y = random(500); printf( "Punto %d x=%lf\ty=%lf\n", i, p[i].x, p[i].y ); } //ordenamos por burbuja burbuja( p, sizeof( punto ), cant, pcomp ); printf( "\n\n" );//separa los dos listados for( i = 0; i < cant; i++ ) { printf( "Punto %d x=%lf\ty=%lf\n", i, p[i].x, p[i].y ); } free(p); }