PUNTEROS A FUNCIONES. Apunte teórico.

Anuncio
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);
}
Descargar