Revistas en papel
Anterior
Menú
Logotipo
Sí puedes leer esta frase, la página ha sido actualizada.

Año II - Nº 5 - Junio 1996
NOTA: Pulsando sobre las fotos con borde azul ampliarás la imagen.

PROGRAMACION

Curso de ANSI C (III) por Javier G.Lete

ARRAYS (MATRICES)

Tranquilos, tranquilos, no voy a daros una clase de Matemáticas. :-)

Simplemente comentaré el tema lo suficiente para entrar de lleno en su uso en C, que va más allá de la mera matemática.

Un array es un conjunto de datos del mismo tipo agrupados en un cierto número de dimensiones.

Se define dando el tipo de datos que va a almacenar, nombre del array y a continuación el tamaño de cada dimensión.

Ejemplos:

/* Array de una dimensión de chars */

char unidim[80];

Lo podemos utilizar para almacenar texto, como ya hemos hecho anteriormente.

/* Array de dos dimensiones */

char 2D[5][3];

Se puede utilizar para guardar datos en una especie de rectángulo. Por ejemplo puede representar un hotel, en el que hay 5 habitaciones por cada piso, y tiene tres pisos, y el dato guardado en cada habitación puede ser una 'o' si está ocupada dicha habitación, 'l' si está libre y lo que se os ocurra.

/* Array de tres dimensiones */

int 3D[5][3][2];

Podía servir para otro hotel, que tenga 5 habitaciones por pasillo, 3 pasillos por planta y 2 plantas. :-). Ya que el tipo que he puesto a los datos de la array son int lo que se almacena por cada habitación podría ser perfectamente el precio de cada una, o el número de ocupantes o camas... Lo que queráis almacenar.

Se puede añadir más dimensiones (para almacenar las reservas del hotel según el día en concreto, por ejemplo) e incluso algunas que para la realidad cotidiana no tienen mucho sentido, pero que a veces en un programa pueden llegar a ser interesantes. De todas formas, mejoraremos este hotel cuando lleguemos a las estructuras. ;-)

ERROR COMUN: Pensar que los indices de los arrays van de 1 a x en lugar de 0 a (x - 1)

RESULTADO:Datos confusos y posible corrupción de memoria (cuelgue)

"¡Buff...! ¡Cuánto rollo! ¿Y los ejemplos?" :-o

Tranquilos, ahora, después de esta introducción, ya vais a tener ejemplos, como el ejemplo 13. ;-)

char matrix[80];

Definimos el array matrix de 80 caracteres.

gets(matrix);

Como se puede entender ahora, gets almacena los caracteres en realidad en la matriz, casilla por casilla, añadiendo al final un '\0' al final.

for (indice = 0; matrix[indice] != '\0'; indice++) putchar(matrix[indice]);

Hacemos un bucle, para mostrar cada casilla (en este caso, letra) por separado, de forma equivalente a como lo haría un printf.

Como se puede comprobar, la forma de acceder a cada dato del array es por medio de matrix[indice] con lo cual obtenemos el dato guardado en el array matrix en la posición [indice].

Un detalle importante a destacar es que al definir los arrays se especifica el número de elementos (en este caso 80), pero el índice comienza DESDE CERO, y no desde uno, y va (en este caso también) al 79 y no al 80.

putchar('|');

Ponemos este carácter a modo de espejo, para que la presentación quede mejor. :-)

for (--indice; indice >= 0; indice--) putchar(matrix[indice]);

Ahora mostramos la cadena al revés.

putchar('\n');

Terminamos con un ENTER para tener una buena presentación.

Otro ejemplo bastante ilustrativo (ejemplo 14a).

CADENAS DE CARACTERES VS
ARRAYS DE CARACTERES

Es una diferencia que se establece para distinguir un array de caracteres que contenga el carácter '\0' al final de la serie de caracteres de otro que no lo tenga.

Esta diferencia es importante ya que hay que tenerla bien clara para no caer en el fallo de intentar imprimir un array de caracteres (sin '\0') con funciones que sirven para imprimir cadenas, ya que es muy posible que muestren una buena parte de la memoria hasta que encuentren dicho carácter por casualidad.

Por ello hay que tener claro lo siguiente: siempre que se indique un texto entre comillas, va a incluir un '\0' en el ordenador; y por lo tanto será una cadena de caracteres, utilizable por cualquier función que las utilice.

Los usuarios del DCC 2.06.21 o similares, recibirán un mensaje de error al compilar que dirá que esta versión del DCC no maneja este tipo de asignación. Por suerte, la versión 2.06.37 ya lo maneja, y está disponible en AmiNet. :-)

int digitos[] = { 00, 11, 22, 33, 44, 55, 66, 77, 88, 99 };

Con esta línea definimos un array unidimensional, con unos elementos pre-establecidos.

Como se puede comprobar, no se ha introducido el número concreto de elementos, sino que se ha omitido. Esto es posible ya que hemos dado los datos directamente en la declaración, con lo que el propio compilador se encargará de que el tamaño del array sea exactamente el del número de elementos decididos. Una vez declarado tiene un tamaño fijo, que no puede ser cambiado, al igual que el resto de declaraciones de arrays.

char arraycar[] = {'R','G','B'};

Hacemos lo mismo con un array de caracteres.

char cadena[] = "RGB";

Ahora definimos una cadena de caracteres. Ver recuadro para diferenciación entre cadena de caracteres y array de caracteres.

for (indice = 0; indice < sizeof(digitos)/sizeof(int); indice++)
printf ("digitos[%d] = %2d\n", indice, digitos[indice]);

Aquí mostramos el array digitos elemento por elemento.

Como se puede haber comprobado, el listado está preparado para manejar cualquier tamaño de array, ya que se comprueba dicho tamaño con la palabra clave sizeof(tipo de dato o variable) que da el tamaño en bytes de la variable o tipo de dato en cuestión.

Para "curarnos en salud", después de saber el tamaño en bytes gracias a sizeof(digitos), lo dividimos entre el tamaño de cada elemento, calculado también gracias a sizeof: sizeof(int). con esto obtenemos el número de elementos.

for (indice = 0; indice < sizeof(arraycar)/sizeof(char);indice++)
printf ("arraycar[%d] = '%c' (%3d)\n", indice, arraycar[indice], arraycar[indice]);

ERROR COMUN: Salirse de las dimensiones del array.

RESULTADO: Se escriben los datos sobrantes en memoria de forma que es muy posible que se produzca un cuelgue al llegar a la zona de algunos programas.

Aquí hacemos lo mismo para arraycar, aunque realmente el tamaño de char salvo casos muy excepcionales, suele ser siempre de un byte, con lo que no es necesario dividir de ninguna manera.

puts(arraycar);

Mostramos arraycar.

Esto no es muy correcto, y puede dar fallos, ya que si el último carácter de la cadena no es \0 puede pasar perfectamente que salga una cadena mucho más larga, pasando por toda la memoria, hasta que se encuentre el siguiente \0.

Por ello es más correcto utilizar lo que tenemos a continuación:

for (indice = 0; indice < strlen(cadena); indice++)
printf ("cadena[%d] = '%c' (%3d)\n", indice, cadena[indice], cadena[indice]);

Mostramos el texto de la cadena como un array normal, para demostrar que no tiene ningún problema para utilizarlo como tal, con la salvedad de que además de las tres letras, incluye un \0.

puts(cadena);

Esto ya sí es correcto, ya que cadena estamos completamente seguros de que termina en \0.

printf("Tamaño de long es %d y de digito es %d\n\n", sizeof(long), sizeof(digitos));

Esto es meramente informativo, pero viene bien como ejemplo de sizeof, y para comprobar el tamaño del array y del tipo de datos long.

Podéis cambiarlo para comprobar el tamaño de lo que deseéis, y es la mejor referencia para saber con seguridad el tamaño de cada tipo de dato y/o variable, ya que pueden variar según el compilador.

De todas formas la forma más habitual de rellenar un array es también con un bucle for. Para saber cómo hacerlo estudiar el ejemplo 14b. Observar que en este ejemplo, cuando se pide la cadena de caracteres, se pueden introducir más caracteres de los declarados. El resultado puede ser un maravilloso cuelgue con soga incluida. :-)

Por ello se debe andar con cuidado, ya que el C no se preocupa de comprobar que los datos tienen el tamaño necesario, sino que debe ser el programador el que lo haga.

Cuando se amplía el número de dimensiones no suelen haber muchos problemas. (Ejemplo 15).

#define MAXX 3
#define MAXY 2

Vamos preparando el tamaño en constantes para mayor flexibilidad.

int matriz1[][] = {{0, 1},{2, 3},{4, 5} };

Definimos matriz 1 que contendrá los elementos 0, 1, 2, 3, 4, y 5, ordenados dos a dos.

int matriz2(MAXX][MAXY] = {
{ 0, 1 },
{ 2, 3 },
{ 4, 5 }
};

Esta declaración es equivalente a la anterior. como habréis comprobado ya, aquí utilizamos las constantes definidas anteriormente (MAXX y MAXY). No es necesario cuando se define un array con sus elementos, pero suele ser recomendable.

También es interesante ver que la sintaxis del C nos permite colocar los elementos de una forma bastante más intuitiva que la anterior. Aquí se ve directamente la "forma" de nuestro array.

for (x = 0; x < MAXX; x++)
for (y = 0; y < MAXY; y++)
printf("matriz1[%d][%d] = %d\nmatriz2[%d][%d] = %d\n\n", x, y, matriz1[x][y], x, y, matriz2[x][y]);

Como se puede comprobar, la forma de mostrar los datos necesita de dos bucles, uno para el "largo" por llamarlo de alguna manera, y otro para el "nacho. Por supuesto en el famoso hotel de marras, podría ser x el piso e y la puerta.

No incluyo el listado para pedir los datos al usuario y rellenar el array, ya que es equivalente al ejemplo 15, pero con la salvedad de cambiar el printf por un scanf.

Ahora vamos a mirar un ejemplo de array bidimensional bastante utilizado: podríamos llamarlo el array de cadenas de caracteres. Observemos el ejemplo 16:

char nombre[5][80] = { "Cero", "Uno", "Dos", "Tres", "Cuatro"};

Definimos el array de cadenas.

for (indice = 0 ; indice < 5 ; indice++) puts(nombres[indice]);

Y las mostramos de esta manera. Como se puede comprobar no hay mayor complicación. Como mucho tomar nota de las dimensiones y no pasarse del tamaño como ya he comentado.

No trato ya los arrays tridimensionales en adelante, ya que sirve con extrapolar lo visto en las 2D.

Por último vamos a dar un listado en el que se pasa de parámetro un array. En este ejemplo desarrollamos nuestra propio función para imprimir en pantalla, casi idéntica a puts(). El nombre, para mayor originalidad será imprimir(). :-)

void imprimir(char texto[]);

Declaramos la función. Como se puede comprobar, ya indicamos el tipo de datos que va a recibir.

char x[80];

Array en la que almacenaremos el texto en el programa principal.

gets(x);

Tomamos el texto de teclado y...

imprimir(x);

... lo mostramos con nuestra maravillosa función. ;-)

void imprimir(char texto[])

Ahora vamos a describir la función:

int indice;

Necesitaremos un índice para poder desplazarnos por los caracteres.

for (indice = 0; texto[indice] != '\0'; indice++)

putchar(texto[indice]);

Escribimos los caracteres hasta que llegue el final de la cadena...

putchar ('\n');

... y redondeamos el resultado con el '\n' correspondiente para hacer que el resultado sea lo más parecido a puts.

Por esta vez, no doy otro capítulo debido a que ando muy ocupado y esta edición de Amiga Agora va a ser bastante extensa ya de por sí.

Como siempre, espero vuestras sugerencias, consulta, etc, por varios medios: carta a la redacción de Amiga Agora, e-mail a Amiga Agora por la dirección de internet [email protected], a través de mi dirección de e-mail de infovía [email protected] (apuntaros en Axis, que es gratuito) o por net a la dirección 39:11/1.4 de AmigaNet.

En la próxima edición de Amiga Agora si el espacio lo permite es posible que incluya algún ejemplo más entretenido de arrays, aparte de incluir el capítulo de estructuras de datos.

os espero en la próxima Amiga Agora, y ánimo con el curso, porque aunque ahora parezca un poco duro, luego podremos manejar el Amiga a tope.

P.D: Perdonad el no haber utilizado estilos de letra diferentes, pero debido a un error en el PageStream3.0i no ha sido posible utilizarlos, para distinguir los distintos tipos de texto. Espero que en la próxima edición el PageStream3.0i arregle estos errores, y el curso pueda volver a su aspecto normal.

/* Listado 13 */

#include <stdio.h>

main()
{
int indice;

char matrix[80];

gets(matrix);

for (indice = 0; matrix[indice] != '\0'; indice++) putchar(matrix[indice]);

putchar('|');

for (--indice; indice >= 0; indice--) putchar(matrix[indice]);

putchar('\n');
}


/* Listado 14a */

#include <stdio.h>
#include <string.h>

main()
{
int indice;

int digitos[] = { 00, 11, 22, 33, 44, 55, 66, 77, 88, 99 };

char arraycar[] = { 'R' , 'G', 'B' };

char cadena[] = "RGB";

putchar('\n');

for (indice = 0; indice < sizeof(digitos)/sizeof(int); indice++)
printf ("digitos[%d] = %2d\n", indice, digitos[indice]);

putchar('\n');

for (indice = 0; indice < sizeof(arraycar)/sizeof(char); indice++)
printf ("arraycar[%d] = '%c' (%3d)\n", indice, arraycar[indice], arraycar[indice]);

putchar('\n');

puts(arraycar);

putchar('\n');

for (indice = 0; indice < strlen(cadena); indice++)
printf ("cadena[%d] = '%c' (%3d)\n", indice, cadena[indice], cadena[indice]);

putchar('\n');

puts(cadena);

putchar('\n');

printf("Tamaño de long es %d y de digitos es %d\n\n", sizeof(long), sizeof(digitos));
}


/* Listado 14b */

#include <stdio.h>
#include <string.h>

#define NUMELEM 3

main()
{
int indice;

int digitos[NUMELEM];

char arraycar[NUMELEM];

char cadena[NUMELEM];

printf("\nIntroduzca los datos para digitos:\n\n");

for (indice = 0; indice < NUMELEM; indice++)
{
printf ("digitos[%d] = ", indice);
scanf ("%d", &digitos[indice]);
}

for (indice = 0; indice < NUMELEM; indice++)
printf ("digitos[%d] = %2d\n", indice, digitos[indice]);

putchar('\n');

for (indice = 0; indice < sizeof(arraycar)/sizeof(char); indice++)
{
printf ("arraycar[%d] = ", indice);
scanf("%c",&arraycar[indice]);
}

for (indice = 0; indice < sizeof(arraycar)/sizeof(char); indice++)
printf ("arraycar[%d] = '%c' (%3d)\n", indice, arraycar[indice], arraycar[indice]);

putchar('\n');

puts(arraycar);

putchar('\n');

scanf("%s",cadena);

for (indice = 0; indice < strlen(cadena); indice++)
printf ("cadena[%d] = '%c' (%3d)\n", indice, cadena[indice], cadena[indice]);

putchar('\n');

puts(cadena);

putchar('\n');
}


/* Listado 15 */

#include <stdio.h>

#define MAXX 3
#define MAXY 2

main()
{
int x, y;

int matriz1[][] = { 0, 1 }, { 2, 3 }, { 4, 5 } };
int matriz2[MAXX][MAXY] = {
{ 0, 1 },
{ 2, 3 },
{ 4, 5 }
};

for (x = 0; x < MAXX; x++)
for (y = 0; y < MAXY; y++)
printf("matriz1[%d][%d] = %d\nmatriz2[%d][%d] = %d\n\n", x, y, matriz1[x][y], x, y, matriz2[x][y]);
}


/* Listado 16 */

#include <stdio.h>

main()
{
int indice;

char nombres[5][80] = { "Cero", "Uno", "Dos", "Tres", "Cuatro" };

for (indice = 0; indice < 5; indice++) puts(nombres[indice]);
}


/* Listado 17 */

#include <stdio.h>

void imprimir(char texto[]);

main()
{
int indice;
char x[80);

gets(x);

imprimir(x);
}

void imprimir(char texto[])
{
int indice;

for (indice = 0; texto[indice] != '\0'; indice++) putchar(texto[indice]);

putchar ('\n');
}


Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal