Tipo_base * matriz_punteros[DIM_1][DIM_2]...[DIM_N];en donde
Tipo_base
es cualquier tipo válido en C, y
DIM_1
,
DIM_2
,...,
DIM_N
son constantes previamente definidas. Evidentemente, la expresión de acceso a un elemento de una matriz de punteros es de la forma
matriz_punteros[i][j]...[k]y dado que ese elemento es un puntero, la expresión
*matriz_punteros[i][j]...[k]
lista[0] = cadena
pero no
cadena = lista[0]
.char cadena[80];Este método es cómo pero plantea el problema habitual: en muchos caso se va a desperdiciar espacio, y no hay seguridad de que la
cadena
disponga de espacio suficiente para almacenar todos los caracteres necesarios en un determinado momento.
char * cadena; cadena = malloc(ESPACIO_NECESARIO);Este segundo método requiere, desde luego, saber cuánto espacio se necesita, pero esto no es realmente un problema, al disponer de la función
fgetln()
, cuyo prototipo es
char * fgetln(FILE *stream, size_t *num)y que proporciona todo lo necesario (un puntero del lugar en que comienza la cadena y su longitud a través de
*num
). El método es más engorroso pero siempre funciona y siempre es seguro.
fgetln()
y
malloc()
; los punteros de las líneas se almacenan en una lista (posiblemente
no lineal
) de punteros de
char
y quedan a disposición del programa.
Listas de punteros de funciones. Según se ha indicado, los punteros pueden señalar distintos tipos de objetos. Uno de los posibles objetos señalables son precisamente las funciones. Esto va a resultar muy útil porque permitirá indicar a una función la dirección de otra función. Esto tiene aplicación, por ejemplo, en la función de biblioteca qsort(). Esta función, para su correcto funcionamiento requieren
otra
función que la relación de orden de los tipos de datos que se quieren ordenar. De este modo,
qsort()
permite ordenar enteros, reales, cadenas, o cualquier otro tipo de datos para el cual seamos capaces de definir una función de comparación. Un ejemplo sencillo de uso de
qsort()
es el que puede verse a continuación:
#include < stdlib.h > #include < stdio.h > long a[1000]; int comparar(const void *x, const void *y) { if (*(int *)x < *(int *)y) return -1; else if (*(int *)x > *(int *)y) return 1; else return 0; } int main(int argc, char * argv) { int i; for (i=0; i<1000 ; i++) a[i]=(long)rand(); qsort(a, 1000, sizeof(int), comparar); for (i=0 ; i < 1000 ; i++) printf("%ld\n",a[i]); }
int
(llamada a) de valores aleatorios. Esta lista se pasa a la función
qsort()
, junto con el nombre (el puntero) de una función llamada
comparar()
, que admite como argumentos dos punteros de
void
y proporciona como resultado un
int
. Internamente, la función refunde los punteros de
void
a punteros de
int
y deshace la indirección; los dos números resultantes se comparan entre sí y se proporciona un resultado negativo, nulo positivo según el primer número sea menor, igual o mayor que el segundo. Esta convención es análoga, por cierto, a la empleada en la función de comparación de cadenas,
strcmp()
. /* Este programa muestra la utilización de matrices de punteros */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define DIM_1 5 /* Esto se admite y funciona! */ char * lista[DIM_1] = {"uno", "dos", "tres", "cuatro", "cinco"}; char cadena[80]; /* La razón es que el compilador de C reserva una zona para variables alfanuméricas, y asigna a los elementos de lista la dirección de esas variables. El compilador se encarga de reservar espacio para las constantes consideradas. Esto es muy cómodo! RECORDATORIO Está prohibida la asignación de variables matriciales. */ int i; int main(void) { for(i=0;i<DIM_1;i++) printf("lista[%d] = %10s, direccion = %d\n",i,lista[i],lista[i]); lista[0] = "OOO"; printf("\nUna nueva asignación de cadenas:\n\n"); for(i=0;i<DIM_1;i++) printf("lista[%d] = %10s, direccion = %d\n",i,lista[i],lista[i]); /* Explicación: el compilador ha creado una nueva entrada en la tabla de constantes alfanuméricas, y hemos asignado a lista[0] la dirección de esa nueva entrada. El lenguaje "conoce" este mecanismo, y strcpy() funciona correctamente: */ strcpy(lista[0],"aaaa"); printf("\nTodo va bien:\n\n"); for(i=0;i<DIM_1;i++) printf("lista[%d] = %10s, direccion = %d\n",i,lista[i],lista[i]); /* ¿Qué sucede si se emplea memcpy() en lugar de strcpy()? */ memcpy(lista[2],"bbbbbbbb",strlen("bbbbbbbb")); printf("\nUn resultado inesperado:\n\n"); for(i=0;i<DIM_1;i++) printf("lista[%d] = %10s, direccion = %d\n",i,lista[i],lista[i]); /* MORALEJA El lenguaje conoce las cadenas: en el tratamiento de cadenas, convienen utilizar funciones de cadenas (string.h) siempre que sea posible. */ printf("\n\nTerminación normal del programa.\n\n"); return 0; } /* RESULTADO lista[0] = uno, direccion = 97159628 lista[1] = dos, direccion = 97159632 lista[2] = tres, direccion = 97159880 lista[3] = cuatro, direccion = 97159885 lista[4] = cinco, direccion = 97159892 Una nueva asignación de cadenas: lista[0] = OOO, direccion = 97159636 lista[1] = dos, direccion = 97159632 lista[2] = tres, direccion = 97159880 lista[3] = cuatro, direccion = 97159885 lista[4] = cinco, direccion = 97159892 Todo va bien: lista[0] = aaaa, direccion = 97159636 lista[1] = dos, direccion = 97159632 lista[2] = tres, direccion = 97159880 lista[3] = cuatro, direccion = 97159885 lista[4] = cinco, direccion = 97159892 Un resultado inesperado: lista[0] = aaaa, direccion = 97159636 lista[1] = dos, direccion = 97159632 lista[2] = bbbbbbbbtro, direccion = 97159880 lista[3] = bbbtro, direccion = 97159885 lista[4] = cinco, direccion = 97159892 Terminación normal del programa. */
char * tabla[][20]
o
char (*tabla)[20]
), asignándole valores iniciales que sean cadenas de distintas longitudes. Mostrar en pantalla la tabla e indicar la cantidad de espacio desperdiciado en cada una. Permitir que el usuario modifique el contenido de las líneas. ¿Qué ocurre si el usuario aporta más caracteres que los esperados?
strcmp()
sirve para determinar la relación de orden de dos cadenas. Se pide construir un programa que haga uso de alguna de las funciones de ordenación conocidas (
qsort()
,
heapsort()
,
mergesort()
) para ordenar una lista de cadenas introducidas a través del teclado.
qsort()
,
heapsort()
o
mergesort()
a voluntad del usuario. Emplear una lista de punteros de función. struct Ficha { char nombre[80]; int edad; float peso; };Se pide construir un programa dotado de una lista de estructuras de este tipo. El programa debe ser capaz de ordenar la lista de estructuras por cualquier campo, para luego mostrar todos los registros en pantalla, con formato encolumnado.
struct Ficha
, según se ha definido en ejercicios anteriores. Se pide construir una pila estática basada en esa lista de punteros.
char
. Construir una función que permita mostrar el mensaje de error correspondiente a un cierto número de error, que actuará como índice dentro de la lista. Seguir el modelo de
perror()
.
malloc()
y crear dinámicamente las estructuras necesarias para utilizar una lista de punteros de estructura. ¿Hay alguna diferencia significativa respecto al uso de una tabla de estructuras estáticas?