Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ESTRUCTURAS DE DATOS
OBJETIVOS
Definir un nuevo TDA utilizando las técnicas ya revisadas
Generico g; 72
5
g = Generico_CrearInt(5); G
Generico_SetInt(g,Generico_GetInt(g)+67);
2056
printf(“%d\n”, Generico_GetInt(g));
“Mama
“Mama”
y Papa”
Generico_Eliminar(g);
g = Generico_CrearString(“Mama”);
strcpy(cad,Generico_GetString(g)); 1343
strcat(cad,” y Papa”); “Mama
“Mama”
y Papa”
Generico_SetString(g, cad);
printf(“%d\n”, Generico_GetString(g));
Generico_Eliminar(g);
GENERICO: NIVEL DE
APLICACION
Bien utilizado
El tipo de dato Generico puede ser sumamente útil
A lo largo de todo el curso
Para usarlo hay que considerar
Nunca olvidar que las conversiones serán necesarias
Si las dejamos a un lado, el resultado será no esperado ni
deseado
REDEFINICION DE ARRAYU
Necesitamos redeclarar el TDA ArrayU
Para definirlo como un arreglo de cualquier tipo de dato
OJO: la definición en el nivel lógico sigue igual
Solo cambiara el nivel de implementación
typedef struct{
Generico *Arreglo;
int nreal;
int inicial;
}ArrayU;
ARRAYU GENERICO: NIVEL DE
APLICACION
Tratemos ahora de usar el ArrayU Generico
Apliquémoslo en el mismo ejemplo anterior:
Pedir n elementos por teclado, almacenarlos en un
arreglo y luego mostrar la mitad de cada valor ingresado
main(){
ArrayU *Datos;
int n, valor;
Generico g;
printf(¿Cuántos datos maximo desea ingresar?);
n = GetInteger();
Datos = ArrayU_Crear(n,1);
for(i = ArrayU_GetInicio(Datos); i <=ArrayU_GetFinal(Datos);i++){
//Inicio i en el for desde 1, no desde 0
printf(“Ingrese el dato No.”, i);
valor = GetInteger();
g = Generico_CrearEntero(valor);
ArrayU_SetElemento(Datos,i, g); //Pido el elemento i
}
for(i = 1; i <= Datos.n ; i++){
g = ArrayU_GetElemento(Datos,i);
valor= Generico_GetEntero(g)/2;
Generico_SetEntero(g, valor);
printf(“Mitad del elemento %d: “,
Generico_GetEntero(g));
}
ArrayU_Eliminar(&Datos);
}
VENTAJAS Y DESVENTAJAS
Ventajas
Logramos definir un arreglo mas funcional
Siempre tiene consigo su tamaño, su índice inicial y
Sirve para cualquier tipo de dato
Estudiante_Imprimir(E);
break;
case QUEBRADO:
Q = A->Elementos[i];
Quebrado_Imprimir(Q);
DESVENTAJAS
Son obvias:
Esta función no sirve para cualquier tipo de dato
Para que ArrayU soporte un nuevo tipo de dato hay que
modificar la función
Buscar al creador del TDA
Pedirle que añada un case para el nuevo tipo de dato
Pedirle que recompile la librería
Pedirle el nuevo .h y el nuevo .lib
MUCHO TRABAJO!!
Esta solución no favorece la expandibilidad del TDA
SEGUNDA SOLUCIÓN
Implementar la función igual que si conociera el tipo
de dato
Enfocarnos en el algoritmo, no en el tipo de dato
Pero.. Aquello que no sepamos como hacer
Porque desconocemos el tipo de dato
Lo debemos recibir como parametro
Y no seria un valor
Sería una acción una función, como parametro
void ArrayU_Imprimir(ArrayU *A, procfn Imprimir){
for(i = 0; i< A->tmax; i++){
//Imprimir A->Elementos[i], NO SE COMO
HACERLO
//Llamo a la funcion Imprimir recibida
como parametro
Imprimir(A->Elementos[i]);
}
}
void ImprimirEntero(int *valor);
void ImprimirCadena(char *cadena);
void Estudiante_Imprimir(Estudiante *E);
void Quebrado_Imprimir(Quebrado *Q);
main(){
ArrayU *A;
A = ArrayU_Crear(10);
//Se piden 10 Estudiante por teclado
//y se almacenan en A
ArrayU_Imprimir(A, Estudiante_Imprimir);
}
FUNCIONES CALLBACKS
Es una herramientas de programación que nos ofrece
lenguaje C
Permite crear un tipo de dato que describa una función
En forma muy genérica
Se indica tipo de dato de retorno
Se indica los tipos de datos de entrada
Ejemplo:
typedef TipoRetorno (*Nombre_Nuevo_Tipo)(<valores de entrada>);
Cualquier función que coincida con este prototipo
Puede decirse que pertenece al nuevo tipo de dato declarado
EJEMPLO: LA GRAPHAPP
El prototipo de la función que crea un nuevo botón es:
button newbutton(char *text, rect r, actionfn fn);
Recibe un texto, un rectángulo y al parecer una variable de tipo
actionfn
Actionfn debe ser un nuevo tipo de dato, su declaración es:
typedef void (*actionfn)(button b);
Esto indica que cualquier función que coincida con el prototipo declarado para
actionfn será de tipo actionfn
Ejemplo:
void CalcularSalarios(button b);
//….
button b;
b = newbutton(“Aceptar”, rect(10,10,10,10), CalcularSalarios);
SU UTILIDAD
Ese mecanismo nos va a permitir
Crear funciones que necesiten llamar a otras funciones
Volviendo a nuestro caso,
La función callback que necesitamos cumplirá la tarea de
imprimir un dato Generico:
typedef void (*Generico_Imprimir)(Generico);
Cualquier función que tenga este prototipo caerá en este tipo.
Ejemplo:
void Imprimir_Entero(int *a); o
void Imprimir_String(char *s);
USANDO UNA FUNCION
COMO PARAMETRO
Nuestra función para imprimir un ArrayU quedaría entonces
void ArrayU_Imprimir(ArrayU *A, Generico_Imprimir fn);