You are on page 1of 12

ARRAYS

Antes de comenzar a explicaros con mayor claridad qu es un array quiero advertir nuevamente a
los programadores de C/C++: En C#, aunque parecidos, los arrays son diferentes tanto semntica
como sintcticamente, de modo que te recomiendo que no pases por alto esta entrega.
Bien, una vez hechas todas las aclaraciones previas, creo que podemos comenzar. Un array es un
indicador que puede almacenar varios valores simultneamente. Cada uno de estos valores se
identifica mediante un nmero al cual se llama ndice. As, para acceder al primer elemento del
array habra que usar el ndice cero, para el segundo el ndice uno, para el tercero el ndice dos, y
as sucesivamente. Que nadie se preocupe si de momento todo esto es un poco confuso, ya que lo
voy a ir desmenuzando poco a poco. Vamos a ver cmo se declara un array:
tipo[] variable;
Bien, como veis es muy parecido a como se declara una variable normal, slo que hay que poner
corchetes detrs del tipo. Los programadores de C/C++ habrn observado inmediatamente la
diferencia sintctica. En efecto, en la declaracin de un array en C# los corchetes se colocan
detrs del tipo y no detrs de la variable. Esta pequea diferencia sintctica se debe a una
importante diferencia semntica: aqu los arrays son objetos derivados de la clase System.Array.
Por lo tanto, y esto es muy importante, cuando declaramos un array en C# este an no se habr
creado, es decir, no se habr reservado an memoria para l. En consecuencia, los arrays de C#
son todos dinmicos, y antes de poder usarlos habr que instanciarlos, como si fuera cualquier otro
objeto. Veamos un breve ejemplo de lo que quiero decir:
string[] nombres; // Declaracin del array
nombres = new string[3]; // Instanciacin del array
En efecto, tal como podis apreciar, el array nombres ser utilizable nicamente a partir de su
instanciacin. En este ejemplo, el nmero 3 que est dentro de los corchetes indica el nmero total
de elementos de que constar el array. No os equivoquis, puesto que todos los arrays de C#
estn basados en cero, esto es, el primer elemento del array es cero. Por lo tanto, en este caso, el
ltimo elemento sera 2 y no 3, ya que son tres los elementos que lo componen (0, 1 y 2).
Veamos un ejemplo algo ms completo y despus lo comentamos:

using System;
namespace Arrays
{
class ArraysApp
{
static void Main()
{
string[] nombres; // Declaracin del array
ushort num=0;
do
{
try
{
Console.Write("Cuntos nombres vas a introducir? ");
num=UInt16.Parse(Console.ReadLine());
}
catch
{
continue;
}
} while (num==0);
nombres=new string[num]; // Instanciacin del array
for (int i=0; i<num; i++)
{
Console.Write("Escribe el nombre para elemento {0}: ",
i);

nombres[i]=Console.ReadLine();
}
Console.WriteLine("Introducidos los {0} nombres", num);
Console.WriteLine("Pulsa INTRO para listarlos");
string a=Console.ReadLine();
for (int i=0; i<num; i++)
{
Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
}
}

a=Console.ReadLine();

Veamos ahora la salida en la consola (en rojo, como siempre, lo que se ha escrito durante la
ejecucin del programa):
Cuntos nombres vas a introducir? 3
Escribe el nombre para el elemento 0: Juanito
Escribe el nombre para el elemento 1: Jaimito

Escribe el nombre para el elemento 2: Joselito


Introducidos los 3 nombres
Pulsa INTRO para listarlos
Elemento 0: Juanito
Elemento 1: Jaimito
Elemento 2: Joselito
En este pequeo programa hemos declarado un array y lo hemos instanciado despus de haber
preguntado al usuario cuntos elementos iba a tener. Como veis, hemos utilizado un bucle for para
recoger todos los valores que hay que meter en el array. Quiero que prestis especial atencin a
cmo hemos introducido los valores en el array: en la lnea "nombres[i] = Console.ReadLine()" lo
que hacemos es que al elemento "i" del array le asignamos lo que devuelva el mtodo ReadLine.
Como "i" tomar valores entre 0 y el nmero total de elementos menos uno rellenaremos el array
completo (fijaos en la condicin del bucle, que es i<num, es decir, que si i es igual a num el bucle
ya no se itera). Despus tenemos otro bucle for para recorrer todo el array y escribir sus valores en
la consola. En definitiva, para acceder a un elemento del array se usa la sintaxis "array[ndice]".
Un array tambin puede inicializarse en la propia declaracin, bien instancindolo (como cualquier
otro objeto) o bien asignndole los valores directamente. Vamos a reescribir el ejemplo anterior
instanciando el array en la declaracin del mismo:
using System;
namespace Arrays2
{
class Arrays2App
{
static void Main()
{
ushort num=3;
do
{

try
{

Console.Write("Cuntos nombres vas a introducir? ");


num=UInt16.Parse(Console.ReadLine());

}
catch
{
continue;
}
} while (num==0);

string[] nombres=new string[num]; // Declaracin e


instanciacin del array
for (int i=0; i<num; i++)

{
Console.Write("Escribe el nombre para elemento {0}: ",

i);
}

nombres[i]=Console.ReadLine();

Console.WriteLine("Introducidos los {0} nombres", num);


Console.WriteLine("Pulsa INTRO para listarlos");
string a=Console.ReadLine();
for (int i=0; i<num; i++)
{
Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
}
a=Console.ReadLine();
}

}
Bien, ahora, como puedes observar, el array ha sido instanciado en la misma lnea en la que fue
declarado. El funcionamiento de este ejemplo, por lo tanto, sera el mismo que el del ejemplo
anterior. Veamos ahora otro ejemplo de inicializacin del array asignndole los valores en la
declaracin:
using System;
namespace Arrays3
{
class Arrays3App
{
static void Main()
{
// Declaracin e inicializacin del array
string[] nombres={"Juanito", "Jaimito", "Joselito"};
for (int i=0; i<nombres.Length; i++)
{
Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
}
string a=Console.ReadLine();
}

}
En este caso, el array nombres ha sido inicializado en la propia declaracin del mismo, asignndole
los tres valores que va a contener. Como ves, dichos valores estn entre llaves y separados por
comas. Las comillas son necesarias en este caso, ya que el array es de tipo string. Que dnde

est la instanciacin del array? Bueno, cuando hacemos esto, la instanciacin la hace por debajo el
compilador, es decir, de forma implcita. Presta atencin tambin a la condicin del bucle: ahora
hemos usado la propiedad Length del array nombres en lugar de una variable. En efecto, esta
propiedad nos devuelve el nmero de elementos de un array. Por lo tanto, la salida en consola de
este programa sera esta:
Elemento 0: Juanito
Elemento 1: Jaimito
Elemento 2: Joselito
Por otro lado, el hecho de que un array haya sido inicializado no quiere decir que sea inamovible.
Si un array que ya contiene datos se vuelve a instanciar, el array volver a estar vaco, y obtendr
las dimensiones de la nueva instanciacin.
Bien, todos estos arrays que hemos explicado hasta el momento son arrays unidimensionales, es
decir, que tienen una sola dimensin (un solo ndice). Sin embargo esto no soluciona an todas las
necesidades del programador. Pongamos, por ejemplo, que queremos almacenar las
combinaciones de las ocho columnas de una quiniela de ftbol en un array.Cmo lo hacemos?
Pues bien, el mejor modo es utilizar un array multidimensional.

ARRAYS MULTIDIMENSIONALES
Los arrays multidimensionales son aquellos que constan de dos o ms dimensiones, es decir, que
cada elemento del array viene definido por dos o ms ndices. Vamos a echar un vistazo a la
declaracin de un array multidimensional (en este caso, ser tridiensional, es decir, con tres
dimensiones):
tipo[,,] variable;
Como ves, hay dos comas dentro de los corchetes, lo cual indica que el array es tridimensional,
puesto que los tres ndices del mismo se separan uno de otro por comas. Veamos un pequeo
ejemplo que lo clarifique un poco ms:
string[,] alumnos = new string[2,4];

Este array es bidimensional y servira para almacenar una lista de alumnos por aula, esto es,
tenemos dos aulas (el primer ndice del array es 2) y cuatro alumnos en cada una (el segundo
ndice es 4). Veamos un poco de cdigo y una tabla para que os hagis una idea de cmo se
almacena esto:
alumnos[0,0]="Lolo";
alumnos[0,1]="Mario";
alumnos[0,2]="Juan";
alumnos[0,3]="Pepe";
alumnos[1,0]="Lola";
alumnos[1,1]="Mara";
alumnos[1,2]="Juana";
alumnos[1,3]="Pepa";
Esto sera como almacenar los datos en esta tabla:

NOMBRE 0
NOMBRE 1
NOMBRE 2
NOMBRE 3

AULA 0

AULA 1

Lolo
Mario
Juan
Pepe

Lola
Mara
Juana
Pepa

Que quieres saber por qu he separado a los chicos de las chicas? Bueno, no es que sea un
retrgrado, es para que se vea mejor todo esto. Mira que sois detallistas... Bueno, creo que va
quedando bastante claro. Y cmo recorremos un array multidimensional? Pues con bucles
anidados. Vamos ya con un ejemplo ms completito de todo esto. Este pequeo programa
pregunta al usuario por el nmero de columnas que quiere generar de una quiniela de ftbol, y
despus las rellena al azar y las muestra en pantalla:
using System;
namespace Quinielas
{
class QuinielasApp
{
static void Main()
{
const char local='1';
const char empate='X';
const char visitante='2';
const byte numFilas=14;
byte numColumnas=0;
char[,] quiniela;
byte azar;
Random rnd=new Random(unchecked((int) DateTime.Now.Ticks));

do
{

ocho");

try
{

Console.WriteLine("Mnimo una columna y mximo


Console.Write("Cuntas columnas quieres generar? ");
numColumnas=Byte.Parse(Console.ReadLine());

}
catch
{
continue;
}
} while (numColumnas<1 || numColumnas>8);
quiniela=new char[numColumnas, numFilas];

for (byte i=0; i<numColumnas; i++)


{
for (byte j=0; j<numFilas; j++)
{
azar=(byte) (rnd.NextDouble()*3D);
switch (azar)
{
case 0:
quiniela[i,j]=local;
break;
case 1:
quiniela[i,j]=empate;
break;
case 2:
quiniela[i,j]=visitante;
break;
}
}
}
Console.WriteLine("Quiniela generada. Pulsa INTRO para
verla");

string a=Console.ReadLine();
for (byte i=0; i<numColumnas; i++)
{
Console.Write("Columna {0}: ", i+1);
for (byte j=0; j<numFilas; j++)
{
Console.Write("{0} ", quiniela[i,j]);
}
Console.WriteLine();
Console.WriteLine();
}
}

a=Console.ReadLine();

Como veis, esto se va poniendo cada vez ms interesante. De este programa, aparte de la clase
Random, hemos visto todo excepto los bloques try y catch, de modo que si hay algo que no
entiendes te recomiendo que revises las entregas anteriores. La clase Random es para generar
nmeros aleatorios (al azar). En la instanciacin de dicha clase hemos puesto algo que puede
resultarte algo confuso. Es esta lnea:
Random rnd=new Random(unchecked((int) DateTime.Now.Ticks));
Bien, el constructor de esta clase tiene dos sobrecargas: una de ellas es sin argumentos, y la otra
acepta un argumento de tipo int, que es la que hemos usado. Por qu? Porque de lo contrario
siempre generara los mismos nmeros en cada ejecucin del programa, lo cual no sera muy til
en este caso. Como necesitamos que se generen nmeros distintos tenemos que pasarle nmeros
diferentes en el argumento int del constructor de la clase Random, y el modo ms eficaz de
conseguirlo es hacer que ese nmero dependa del tiempo que lleve encendido el ordenador. Por
otro lado, el nmero lo generamos al ejecutar el mtodo NextDouble, el cual nos retorna un nmero
mayor o igual a 0 y menor que 1. Esta es la lnea:
azar=(byte) (rnd.NextDouble()*3D);
Por qu lo hemos multiplicado por 3D? Pues bien, como queremos nmeros enteros entre 0 y 2
(o sea, 0, 1 o 2) bastar con multiplicar este nmero (recuerda que est entre cero y uno) por 3. Y
la D? Ahora voy, hombre. Os acordis de los sufijos en los literales, para indicar si se deba
considerar si el nmero era de un tipo o de otro? Pues aqu est la explicacin. Dado que el
mtodo NextDouble retorna un valor double, tenemos que multiplicarlo por otro valor double. Por
eso le ponemos el sufijo "D" al nmero tres. Despus todo ese resultado se convierte a byte y se
asigna a la variable azar, que es la que se comprueba en el switch para asignar el carcter
necesario segn su valor a cada elemento del array.
Por lo dems creo que a estas alturas no debera tener que explicaros gran cosa: tenemos un par
de bucles anidados para asignar los valores al array y despus otros dos bucles anidados para
recorrer dicho array y mostrar su contenido en la consola.
Otra cuestin importante en la que quiero que te fijes es en que ya estoy empezando a dejar de
usar "literales y nmeros mgicos", usando constantes en su lugar. Efectivamente, podra haberme

ahorrado las cuatro constantes: local, empate, visitante y numFilas, poniendo sus valores
directamente en el cdigo, algo as:
...

...

for (byte i=0; i<numColumnas; i++)


{
for (byte j=0; j<14; j++)
{
azar=(byte) (rnd.NextDouble()*3D);
switch (azar)
{
case 0:
quiniela[i,j]='1';
break;
case 1:
quiniela[i,j]='X';
break;
case 2:
quiniela[i,j]='2';
break;
}
}
}

En efecto, funcionara exactamente igual, pero qu ocurrira si otra persona que no sabe qu es
una quiniela, o por qu tiene que ser el nmero 14, o qu significan el 1, la X o el 2? Pues que el
cdigo sera menos claro. Las constantes, sin embargo, hacen la lectura del cdigo ms fcil. Por
otro lado, si algn da cambiaran los signos, por ejemplo, si hubiese que poner una "a" en lugar del
"1", una "b" en lugar de la "x" y una "c" en lugar del "2" y no hubisemos usado constantes habra
que buscar todos estos literales por todo el cdigo y sustituirlos uno por uno, mientras que usando
constantes (que estn declaradas al principio) basta con modificar sus valores, haciendo as el
cambio efectivo ya para todo el programa. As que ya lo sabis: a partir de ahora vamos a evitar en
lo posible los "literales y los nmeros mgicos".
Para terminar con esto, el nmero de dimensiones de un array se llama rango. Para conocer el
rango de un array mediante cdigo basta con invocar la propiedad Rank del mismo (heredada de la
clase System.Array). Veamos un ejemplo de esto:
using System;
namespace Rangos
{
class RangosApp
{
static void Main()

{
int[] array1=new int[2];
int[,] array2=new int[2,2];
int[,,] array3=new int[2,2,2];
int[,,,] array4=new int[2,2,2,2];
Console.WriteLine("Rango
Console.WriteLine("Rango
Console.WriteLine("Rango
Console.WriteLine("Rango

array1:
array2:
array3:
array4:

{0}",
{0}",
{0}",
{0}",

array1.Rank);
array2.Rank);
array3.Rank);
array4.Rank);

string a=Console.ReadLine();

}
}

de
de
de
de

La salida en la consola de todo esto sera la siguiente:


Rango
Rango
Rango
Rango

de
de
de
de

array1:
array2:
array3:
array4:

1
2
3
4

ARRAYS DE ARRAYS
En efecto, para liar un poco ms la madeja, tenemos tambin los arrays de arrays. Estos son
arrays que pueden contener otros arrays. Y para qu diablos queremos meter un array dentro de
otro? No nos basta con los arrays multidimensionales? Pues realmente podra bastarnos, en
efecto, pero habra ocasiones en las que tendramos que hacer bastantes cabriolas con el cdigo
por no usar los arrays de arrays. Pensad en un programa en el que el usuario tiene que manejar
simultneamente mltiples objetos de distintas clases derivadas de una clase base, por ejemplo,
tringulos y cuadrados derivados de la clase figura. Si solamente pudiramos usar arrays
unidimensionales o multidimensionales tendramos que declarar un array distinto para cada tipo de
objeto (uno para tringulos y otro para cuadrados). La dificultad viene ahora: Qu ocurre si hay
que redibujar todos los objetos, ya sean cuadrados o tringulos? Evidentemente, habra que
escribir un bucle para cada uno de los arrays para poder invocar los mtodos Redibujar de cada
uno de los elementos. Sin embargo, si metemos todos los arrays dentro de un array de arrays nos
bastara con escribir un par de bucles anidados para recorrer todos los objetos y dejar el resto en
manos del polimorfismo. Ciertamente, an no hemos estudiado a fondo ninguno de los
mecanismos de la herencia. No obstante, con lo que sabemos hasta ahora, podemos poner un
ejemplo sobre los arrays de arrays, aunque probablemente no se aprecie realmente la ventaja.

Veamos el ejemplo, y luego lo comentamos. Eso s, presta especial atencin a la sintaxis, tanto en
la declaracin como en las instanciaciones:
using System;
namespace ArraysdeArrays
{
class ArraysDeArraysApp
{
static void Main()
{
object[][] numeros; // Declaracin del array de arrays
numeros=new object[2][]; // Instanciacin del array de arrays
numeros[0]=new object[3]; // Instanciacin del primer array
numeros[1]=new object[4]; // Instanciacin del segundo array
numeros[0][0]=3.325D;
numeros[0][1]=6.25D;
numeros[0][2]=3D;
numeros[1][0]=3u;
numeros[1][1]=7u;
numeros[1][2]=4u;
numeros[1][3]=87u;
for (int i=0;i<numeros.Length;i++)
{
for (int j=0;j<numeros[i].Length;j++)
{
Console.WriteLine(numeros[i][j].ToString());
}
}
}
}

string a=Console.ReadLine();

En este ejemplo vamos a usar un array en el que incluiremos dos arrays: uno para nmeros de tipo
double y otro para nmeros de tipo ulong. Como estos dos tipos estn derivados de la clase
System.Object, lo que hacemos es declarar el array de este tipo en la primera lnea del mtodo
Main, y despus lo instanciamos dicindole que contendr dos arrays (en la segunda lnea).
Despus instanciamos tambin como tipo object los dos arrays que contendr el primero, y le
asignamos valores: al array numeros[0] le asignamos valores de tipo double, y al array numeros[1]
le asignamos valores de tipo ulong. Despus usamos un par de bucles anidados para recorrer
todos los elementos del array de arrays con el objeto de invocar el mtodo ToString() de todos ellos
(heredado de la clase System.Object). Como ves, el bucle "i" recorre el array de arrays (fjate en la
condicin, i<numeros.Length), y el bucle "j" recorre cada uno de los elementos del array

numeros[i], segn sea el valor de i en cada iteracin. Con los ejemplos de esta entrega se incluye
tambin el de los cuadrados y los tringulos que te mencion antes (en la carpeta Figuras), pero no
lo reproduzco aqu porque an no hemos visto la herencia. Sin embargo, cuando lo ejecutes, vers
mejor la utilidad de los arrays de arrays.
Bien, creo que ya es suficiente para esta entrega. No te pondr ejercicios sobre los arrays todava,
pues prefiero esperar a que hayamos vistos los indizadores y los bucles foreach. Por cierto...
espero que la prxima entrega no se haga esperar tanto como esta. A ver si hay algo de suerte...

You might also like