Arrays
Un array es un indicador que puede almacenar varios valores
simultáneamente. Cada uno de estos valores se identifica mediante un número al
cual se llama índice. Así, para acceder al primer elemento del array habría que
usar el índice cero, para el segundo el índice uno, para el tercero el índice
dos, y así sucesivamente. A continuación se muestra cómo se declara un array:
tipo[] variable;
Es muy parecido a como se declara una variable, sólo que hay que poner
corchetes detrás del tipo. 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, aún no se habrá creado, no se habrá reservado aún memoria
para él. En consecuencia, los arrays de C# son todos dinámicos, por lo que es
necesario instanciarlos antes de poder utilizarlos. Un ejemplo:
string[] nombres; // Declaración del array
nombres = new
string[3]; // Instanciación del array
El array nombres será utilizable únicamente a partir de su instanciación.
En este ejemplo, el número 3 que está dentro de los corchetes indica el número
total de elementos de que constará el array. Todos los arrays de C# están
basados en cero, esto es, el primer elemento del array es cero. Por lo tanto,
en este caso, el último elemento
sería 2 y no 3, ya que son tres los elementos que lo componen (0, 1 y
2). Un ejemplo:
class Arrays
{
static void Main()
{
string[] nombres; // Declaración del array
ushort num=0;
do
{
try
{
Console.Write("¿Cantidad
de nombres a introducir? ");
num=UInt16.Parse(Console.ReadLine());
}
catch
{
continue;
}
} while (num==0);
nombres=new string[num]; // Instanciación del array
for (int i=0;
i<num; i++)
{
Console.Write("Introduzca
el nombre para cada elemento {0}: ", i);
nombres[i]=Console.ReadLine();
}
Console.WriteLine("Introducidos
los {0} nombres", num);
Console.WriteLine("Pulse
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 la salida en la consola:
¿Cantidad de nombres a introducir? 3
Escriba el
nombre para el elemento 0: Antonio
Escriba el
nombre para el elemento 1: Ana
Escriba el
nombre para el elemento 2: Raquel
Introducidos los 3 nombres
Pulse INTRO para listarlos
Elemento 0: Antonio
Elemento 1: Ana
Elemento 2: Raquel
Este programa declara un array y lo instancia después de haber preguntado
al usuario cuántos elementos va a tener. Utiliza un bucle for para recoger los
valores a introducir en el array. Dichos nombres se han introducido en la línea
"nombres[i] = Console.ReadLine()" lo que hace es que al
elemento "i" del array le asigna lo que devuelva el método ReadLine.
Como "i" tomará valores entre 0 y el número total de elementos menos
uno, rellena el array completo (la condición del bucle, es i<num, si i es
igual a num el bucle ya no se itera). Después tiene otro bucle for para
recorrer todo el array y escribir sus valores en la consola. Para acceder a un
elemento del array se utiliza la sintaxis "array[índice]".
También es posible inicializar un array en la propia declaración, ya sea
instanciándolo o bien asignándole los valores directamente. Reescribimos el
ejemplo anterior para instanciar el array en la declaración del mismo:
class Arrays2
{
static void Main()
{
ushort num=3;
do
{
try
{
Console.Write("¿Cantidad
de nombres a introducir? ");
num=UInt16.Parse(Console.ReadLine());
}
catch
{
continue;
}
} while (num==0);
string[] nombres=new string[num]; // Declaración e
instanciación del array
for (int i=0;
i<num; i++)
{
Console.Write("Escriba
el nombre del elemento {0}: ", i);
nombres[i]=Console.ReadLine();
}
Console.WriteLine("Introducidos
los {0} nombres", num);
Console.WriteLine("Pulse
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();
}
}
Se puede observar, que el array se instancia en la misma línea en la que se
declara. El funcionamiento sería el mismo que el del ejemplo anterior. En el
ejemplo siguiente de inicialización del array, le asigna los valores en la
declaración:
class Arrays3
{
static void Main()
{
// Declaración e
inicialización del array
string[] nombres={"Antonio",
"Ana", "Raquel"};
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 se inicializa en la propia declaración del
mismo, asignándole los tres valores que va a contener. Dichos valores están
entre llaves y separados por comas. Las comillas son necesarias, ya que el
array es de tipo string. ¿Dónde se encuentra en este caso la instanciación del
array? la instanciación la hace por debajo el compilador, de forma implícita. Ahora
se utiliza la propiedad Length del array nombres en lugar de una variable. Esta
propiedad devuelve el número de elementos de un array. De este modo, la salida
en consola de este programa sería esta:
Elemento 0: Antonio
Elemento 1: Ana
Elemento 2: Raquel
El hecho de que un array haya sido inicializado no quiere decir que sea
inamovible. En el caso de que un array que ya contienga datos se vuelva a
instanciar, el array volverá a estar vacío, y obtendrá las dimensiones de la
nueva instanciación.
Arrays multidimensionales
Los arrays multidimensionales constan de dos o más dimensiones, cada
elemento del array viene definido por dos o más índices. En este caso vamos a
definir un array de tres dimensiones):
tipo[,,] variable;
Hay dos comas dentro de los corchetes, esto indica que el array es
tridimensional, los tres índices del mismo se separan uno de otro por comas. Un
pequeño ejemplo:
string[,] nombres = new string[2,4];
Este array es bidimensional y sirve para almacenar una lista de nombres por
habitación, de este modo, si tenemos dos salones y cuatro personas en cada una,
podemos representarlo en una tabla para hacernos una idea:
nombres[0,0]="Manuel";
nombres[0,1]="Ana";
nombres[0,2]="Juan";
nombres[0,3]="Raquel";
nombres[1,0]="Lola";
nombres[1,1]="Antonio";
nombres[1,2]="Juana";
nombres[1,3]="Vicente";
Esto sería como almacenar los datos en
esta tabla:
Sala 0
|
Sala 1
|
|
NOMBRE 0
|
Manuel
|
Lola
|
NOMBRE 1
|
Ana
|
Antonio
|
NOMBRE 2
|
Juan
|
Juana
|
NOMBRE 3
|
Raquel
|
Vicente
|
Un array multidimensional se reccorre con bucles anidados. A continuación
un programa pregunta al usuario por el número de columnas que quiere generar de
una quiniela de fútbol, y después las rellena al azar y las muestra en
pantalla:
class Quinielas
{
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
{
try
{
Console.WriteLine("Mínimo
una columna y máximo ocho");
Console.Write("¿Cuántas
columnas quiere 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. Pulse INTRO para mostrarla");
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();
}
}
La clase Random utilizada en este programa, es para generar números
aleatorios. En la instanciación de la clase, se ha puesto algo que puede
resultar algo confuso:
Random rnd=new Random(unchecked((int)
DateTime.Now.Ticks));
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 se utiliza
en este ejemplo. De no ser así, siempre generaría los mismos números en cada
ejecución del programa. El número lo generamos al ejecutar el método
NextDouble, el cual retorna un número mayor o igual a 0 y menor que 1. Esta es
la línea:
azar=(byte) (rnd.NextDouble()*3D);
Se multiplica por 3D? pues como se necesitan números enteros entre 0 y será
suficiente con multiplicar este número por 3. La D es un sufijo literal, para
indicar si se debe considerar si el número es de un tipo o de otro. Dado que el
método NextDouble retorna un valor double, tenemos que multiplicarlo por otro
valor double. Por eso se pone el sufijo "D" al número tres. Posteriormente
todo ese resultado se convierte a byte y se asigna a la variable azar, que es
la que se comprueba en el switch y le asigna el carácter necesario según su
valor a cada elemento del array.
También hay un par de bucles anidados para asignar los valores al array y
después otros dos bucles anidados para recorrer dicho array y mostrar su
contenido en la consola.
El número de dimensiones de un array se llama rango. Para conocer el rango
de un array a través de código, se invoca la propiedad Rank del mismo (heredada
de la clase System.Array). Un ejemplo:
class Rangos
{
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
de array1: {0}", array1.Rank);
Console.WriteLine("Rango
de array2: {0}", array2.Rank);
Console.WriteLine("Rango
de array3: {0}", array3.Rank);
Console.WriteLine("Rango
de array4: {0}", array4.Rank);
string a=Console.ReadLine();
}
}
La salida en la consola sería la siguiente:
Rango de
array1: 1
Rango de array2: 2
Rango de array3: 3
Rango de array4: 4
Arrays de Arrays
Son arrays que pueden contener otros arrays. Un programa en el que el
usuario tiene que manejar simultáneamente múltiples objetos de distintas clases
derivadas de una clase base, por ejemplo, triángulos y cuadrados derivados de
la clase figura. Si solamente estuviera permitido utilizar arrays
unidimensionales o multidimensionales declararíamos un array distinto para cada
tipo de objeto (uno para triángulos y otro para cuadrados). Pero en el caso de
que haya que redibujar todos los objetos, ya sean cuadrados o triángulos,
habría que escribir un bucle para cada uno de los arrays para poder invocar los
métodos Redibujar de cada uno de los elementos. Sin embargo, introduciendo
todos los arrays dentro de un array de arrays bastaría con escribir un par de
bucles anidados para recorrer todos los objetos y dejar el resto en manos del
polimorfismo. A continuación un ejemplo.
class ArraysDeArrays
{
static void Main()
{
object[][] numeros; // Declaración del array
de arrays
numeros=new object[2][]; // Instanciación del
array de arrays
numeros[0]=new object[3]; // Instanciación del
primer array
numeros[1]=new object[4]; // Instanciación 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 se utiliza un array que incluye dos arrays: uno para
números de tipo double y otro para números de tipo ulong. Como estos dos tipos
están derivados de la clase System.Object, se declara un array de este tipo en
la primera línea del método Main, y después se instancia para que contendrá dos arrays (en la segunda
línea). Después se instancian los dos arrays como tipo object, y se les asignan
los valores: al array numeros[0] se le asignan valores de tipo double, y al
array numeros[1] se le asignan valores de tipo ulong. Posteriormente se utiliza un par de bucles anidados que recorren
todos los elementos del array de arrays con objeto de invocar el método
ToString() de todos ellos (heredado de la clase System.Object). El bucle
"i" recorre el array de arrays (la condición, i<numeros.Length), y
el bucle "j" recorre cada uno de los elementos del array numeros[i],
según sea el valor de i en cada iteración.
No hay comentarios:
Publicar un comentario