3. Una de las construcciones más interesantes que puede crear es un
array de punteros a funciones. Para elegir una función, sólo indexe el
array y dereferencie el puntero. Esto permite implementar el
concepto de código dirigido por tabla(table-driven code); en lugar
de usar estructuras condicionales o sentencias case, se elige la
función a ejecutar en base a una variable (o una combinación de
variables). Este tipo de diseño puede ser útil si añade y elimina
funciones de la tabla con frecuencia (o si quiere crear o cambiar una
tabla dinámicamente).
El siguiente ejemplo crea algunas funciones falsas usando una macro
de preprocesador, después crea un array de punteros a esas funciones
usando inicialización automática. Como puede ver, es fácil añadir y
eliminar funciones de la table (y por tanto, la funcionalidad del
programa) cambiando una pequeña porción de código.
4. Supongamos que queremos pasar un array a una función. La solución es pasar punteros. El nombre de un
array es un puntero al primer elemento del array. Así, si hemos definido int taco[10]como un array de diez
enteros, taco será un puntero al array. Por ejemplo, sea guacamole un array de 6 enteros: 6, 63, 112, 18, -52,
16. guacamole es simplemente un puntero al primer elemento. Entonces, *guacamole equivale al valor 6. Si
tratamos de acceder al elemento guacamole[6], estamos accediendo a lo que haya después del último
elemento del array. Los resultados son inesperados.
Veamos un ejemplo de cómo pasar un array a una función:
# include <iostream.h>
void eat_at_joes(int guacamole[])
{
guacamole[0] = 1;
guacamole[1] = 2;
guacamole[2] = 3;
}
main()
{
int taco[3];
int nacho[2];
eat_at_joes(taco);
eat_at_joes(nacho);
}
5. Al definir la función, no hemos puesto ningún número entre los corchetes. Esto significa que estamos
permitiendo que un array de cualquier tamaño pueda ser pasado a la función. En la función main, hemos
declarado dos arrays de enteros, taco y nacho. Primero pasamos taco a la función, que en realidad es la
direccion del array taco. Ahora bien, el segundo array, nacho, tiene sólo dos elementos. Cuando la función
trate de acceder al tercer elemento del array, que realmente no existe. Ya que los arrays son muchas variables
almacenadas una detrás de otra en la memoria del ordenador, tratará y accederá a la variable almacenada
despueés del segundo elemento del array, que no existe.
Además, el programa compilará y correrá sin mensajes de error. Esto sucedía ya en C, que permite leer y
escribir en la memoria del ordenador sin saber si realmente hay variables allí. Se deben evitar casos como el
del ejemplo, porque, o bien el programa correrá sin mensajes de error, o bien casca.
Una forma de evitarlo es añadiendo un segundo parámetro que indique el tamaño del array:
# include <iostream.h>
void eat_at_joes(int guacamole[], int size)
{
if (size > 0)
guacamole[0] = 1;
if (size > 1)
guacamole[1] = 2;
if (size > 2)
guacamole[2] = 3;
}
main()
{
int taco[3];
int nacho[2];
eat_at_joes(taco,3);
eat_at_joes(nacho,2);
}
6. Por default, los arrreglos en C se pasan a una función como referencia y no como valor. Esto significa que todas
las modificaciones que hagamos dentro de la función en C al arreglo que recibimos como parámetro, realmente
se realizan en el arreglo original que se utilizó como argumento al momento de llamar a la función.
Al escribir una función en C, la forma de indicar que uno de los parámetros que se va a recibir es un arreglo de
una dimensión, es decir de que tipo va a ser el arreglo y el nombre con el cual vamos a manipular dicho arreglo
dentro de nuestra función seguido de corchetes que abren y cierran; nuestra función también debe recibir un
segundo parámetro que nos indique el tamaño del arreglo, o dicho de otra forma, el número de elementos de los
que consta nuestro arreglo, recordemos que como el arreglo se pasa a la función como referencia, lo que esta
recibiendo la función en realidad es un apuntador al primer elemento del arreglo, pero no sabe en donde termina
el arreglo, por eso es necesario que la función también reciba como parámetro el número de elementos del
arreglo.
Por ejemplo, el prototipo de una función en C que va a regresar un entero y va a recibir un arreglo de 10
elementos de tipo entero sería algo asi:
int Mi Función(int mi_arreglo[], int num_elemetos);
Para llamar a la función anterior, se pone como primer argumento el nombre del arreglo (sin corcehetes) y como
segundo argumento el número de elementos del arreglo. Supongamos que tenemos un arreglo de 10 elementos
de tipo entero llamado números y queremos guardar en una variable llamada “x” el valor que nos regresa la
función “Mi Función” al llamarla pasándole como argumentos el arreglo “números”, haríamos algo como esto
x = Mi Función(numeros, 10);
El siguiente programa solicita al usuario que ingrese 10 números de tipo entero y los almacena en un arreglo;
después le pide que introduzca un número para que busque su posición dentro del arreglo..
El programa utiliza una función llamada Busca Numero que recibe como parámetros el arreglo con los 10
números capturados, el número de elementos del arreglo (en este caso 10) y el número del cual se desea saber su
posición dentro del arreglo.. La función regresa -1 si el número que se busca no se encuentra en el arreglo y en
caso contrario, regresa la primera posición del arreglo que contiene dicho número.
El programa también utiliza una función llamada Muestra Arreglo que no regresa valor alguno, sólo recibe como
parámetros el arreglo y el número de elementos. Esta función imprime en pantalla los elementos del arreglo
separados por un tabulador.
7. //: C03:FunctionTable.cpp
// Using an array of pointers to functions
#include <iostream>
using namespace std;
// A macro to define dummy functions:
#define DF(N) void N() { cout << "function “
#N " called..." << endl; } DF(a); DF(b); DF(c); DF(d); DF(e); DF(f);
DF(g);
void (*func_table[])() = { a, b, c, d, e, f, g };
int main() { while(1) { cout << "press a key from 'a' to 'g' " "or q to
quit" << endl;
char c, cr;
cin.get(c);
cin.get(cr);
// second one for CR
if ( c == 'q' ) break; // ... out of while(1)
if ( c < 'a' || c > 'g' )
continue; (*func_table[c - 'a'])();
}
} ///:~