Capítulo 8. Arrays. 1. Introducción. 2. Definición de array.

Anuncio
Capítulo 8.
Arrays.
1. Introducción.
2. Definición de array.
3. Arrays unidimensionales.
4. Arrays multidimensionales.
4.1. Arrays bidimensionales.
5. Cadenas.
5.1. Funciones habituales con cadenas.
5.2. Array de cadenas.
6. Inicialización de arrays.
6.1. Inicialización de arrays sin tamaño.
7. Introducción a los arrays como parámetros de funciones.
1
1. Introducción.
Hasta ahora hemos tenido una limitación importante al almacenar datos
en las variables declaradas en un programa. Cuando queremos introducir una
serie de datos relacionados, por ejemplo las 10 notas de un alumno, si lo
hacemos con un bucle, cada dato se guarda donde está guardado el dato
anterior, con lo que al final del bucle no tendremos en memoria todos los datos,
sino sólo el último dato introducido. Para mantener simultáneamente todos los
datos en memoria necesitamos declarar una variable independiente para cada
dato, pero en ese caso no podremos usar un bucle para introducirlos.
El uso de arrays soluciona esas limitaciones citadas y permite una
organización más lógica en memoria de datos relacionados. Veamos en qué
consisten los arrays.
2. Definición de array.
Un array es una colección de variables del mismo tipo que se
referencian por un nombre común. El número de variables del array es fijo y
finito.
Para acceder a un elemento específico del array se usa el nombre del
array más un índice (o varios) que indica la posición que ocupa el elemento
dentro del array.
Cada elemento del array se denomina componente. El tamaño del array
es el número de componentes que tiene. El tipo del array es el tipo de las
componentes que lo forman. La dimensión del array es el número de índices
necesarios para hacer referencia o acceder a una componente del array.
Ej.
Nombre del array: NOTAS
Tamaño: 8 componentes
Dimensión: 1 (con un sólo índice se accede a cada componente)
Indice: de 0 a 7
0
9
1
8
2
7
Valor de cada componente:
NOTAS[0] = 9
NOTAS[1] = 8
NOTAS[2] = 7
NOTAS[3] = 3
3
3
4
7
5
3
6
6
7
5
NOTAS[4] = 7
NOTAS[5] = 3
NOTAS[6] = 6
NOTAS[7] = 5
Un inconveniente del array es que debe indicarse el tamaño al
declararse el array, en tiempo de programación, no en tiempo de ejecución del
programa.
2
El compilador de C reserva espacio en memoria para cada array
declarado y le asigna posiciones contiguas de memoria a las componentes del
array. La dirección más baja corresponde el primer elemento y la más alta al
último.
Los arrays pueden tener una o varias dimensiones, dependiendo del
número de índices necesarios para hacer referencia a una componente del
array.
Vamos a referenciar los arrays del mismo modo en pseudocódigo que en
lenguaje C, como se va a explicar a continuación.
3. Arrays unidimensionales.
Un array unidimensional es el que tiene una dimensión, es decir que con
un sólo índice se puede referenciar o acceder a cada componente del array. Se
denominan vectores y se pueden representar como una lista de elementos.
En C se declaran de la forma:
tipo nombre_array[tamaño];
donde el tipo indica el tipo de datos que se almacenarán en el array y
tamaño indica el número de componentes.
Ej.
float notas[8];
En ese array, el índice podrá valer desde 0 a 7 para acceder a cada
componente:
notas[0] notas[1] notas[2] notas[3] notas[4] notas[5] notas[6] notas[7]
Para acceder a una componente se usa la sintaxis:
nombre_array[indice]
(donde índice estará entre 0 y tamaño–1)
Cada componente del array será una variable del tipo del array (float en
el ejemplo anterior), y se usará como cualquier otra variable de ese tipo que no
fuera parte de un array.
Ej.
notas[2]=6.5; //asignación de 6.5 a la componente 2
scanf(“%f”, &notas[6]); //Teclear un valor y guardarlo
//en la componente 6 del array.
Una operación muy usada con arrays es recorrerlo, es decir acceder a
cada una de sus componentes. Veámoslo con el siguiente ejemplo, que carga
en el array valores tecleados:
3
Ej.
En pseudocódigo:
para I de 0 a 7 con Inc. 1
Escribir “Teclee nota ”, I
Leer notas[I]
finpara
En C:
void main(void)
{
int i;
float notas[8];
for (i=0; i < 8; i++)
{
printf(“Teclee nota %d:”, i);
scanf(“%f”, &notas[i]); fflush(stdin);
}
}
Un inconveniente de lenguaje C es que ni al compilar ni al ejecutar se
comprueban los límites del array, por lo que es responsabilidad del
programador asegurar que no se sobrepasen esos límites, ya que se puede
acceder a otras posiciones de memoria contiguas al array y escribir encima de
alguna otra variable o incluso encima de código de programa.
El número de bytes que ocupa un array en memoria es:
nº de componentes
*
nº de bytes del tipo del array
Ej.
int codigo[9]; // int=2 bytes; 9*2=18 bytes
char nombre[25]; // char=1 byte; 25*1=25 bytes
Veamos un último ejemplo:
Ej. Calcular la media de los valores guardados en el array notas:
En pseudocódigo:
media = 0
para I de 0 a 7 con Inc. 1
media = media + notas[I]
finpara
Escribir “Nota media:”, media/8
En C:
media = 0;
for (i = 0; i < 8; i++)
media += notas[i];
printf(“Nota media: %5.2f”, media/8);
4
4. Arrays multidimensionales.
En un array multidimensional se necesitan más de un índice para
referenciar a una de sus componentes. El número máximo de dimensiones
permitido viene determinado por el compilador usado.
Un array de dimensión N se declara en C de la forma siguiente:
tipo nombre_array[tamaño1][tamaño2]...[tamañoN];
Se necesitarán N índices donde:
- índice1 tomará valores entre 0 y tamaño1 – 1.
- índice2 tomará valores entre 0 y tamaño2 – 1.
...
- índiceN tomará valores entre 0 y tamañoN – 1.
El número de bytes que ocupa un array multidimensional será el
producto del número de bytes del tipo del array por el número de componentes.
El número de componentes será el producto de cada uno de los tamaños de
las distintas dimensiones.
Ej.
int codigo[4][3][5]; //nºcomponentes: 4*3*5=60
//int=2bytes; 60*2=120 bytes de memoria.
Este tipo de arrays se usa poco con más de 2 dimensiones, debido a la
complejidad de la programación, a la gran cantidad de memoria que ocupan y
al elevado tiempo de acceso requerido.
4.1. Arrays bidimensionales.
En un array bidimensional se necesitan 2 índices para acceder a cada
componente. Se llaman matrices y se pueden representar como una tabla con
filas y columnas.
Se declaran indicando el número de filas y columnas:
tipo nombre_array[filas][columnas];
Ej.
int dato[3][4]; //3 filas (0,1,2); 4 columnas(0,1,2,3)
fila 0
fila 1
fila 2
Col. 0
Col. 1
Col. 2
Col. 3
dato[0][0] dato[0][1] dato[0][2] dato[0][3]
dato[1][0] dato[1][1] dato[1][2] dato[1][3]
dato[2][0] dato[2][1] dato[2][2] dato[2][3]
Para acceder a cada componente se hará de la forma:
5
nombre_array[indice1][indice2]
donde indice1 indicará la fila variando entre 0 y filas-1 e índice2 indicará
la columna y variará entre 0 y columnas-1.
El C almacena en memoria el array por filas, es decir primero las
componentes de la fila 0, después las de la fila 1 y así sucesivamente. El
números de bytes que ocupa en memoria será el producto del número de bytes
del tipo del array por el número de componentes. El número de componentes
será el producto del número de filas por el número de columnas.
El recorrido de un array bidimensional se hace a través de dos bucles,
uno para las filas y otro para las columnas, como se indica en el siguiente
ejemplo:
Ej. Cargar valores tecleados en el array numeros de 3 filas y 5 columnas.
En pseudocódigo:
para I de 0 a 2 con Inc. 1
para J de 0 a 4 con Inc. 1
Escribir “Teclee valor”, I,J
Leer numeros[I][J]
finpara
finpara
En C:
void main(void)
{
int numeros[3][5], i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 5; j++)
{
printf(“Teclee valor %d, %d:”, i,j);
scanf (“%d”, &numeros[i][j]);fflush(stdin);
}
}
Veamos un último ejemplo.
Ej. Calcular el producto de los valores del array anterior:
En pseudocódigo:
producto = 1
para I de 0 a 2 con Inc. 1
para J de 0 a 4 con Inc. 1
producto = producto * numeros[I][J]
finpara
finpara
Escribir “El producto es:”, producto
En C:
6
producto = 1;
for (i = 0; i < 3; i++)
for (j = 0; j < 5; j++)
producto *= numeros[i][j];
printf(“El producto es: %ld”, producto);
5. Cadenas.
Una cadena es un caso particular de array unidimensional, cuyo tipo es
char, o sea que una cadena es una array unidimensional de caracteres.
En C se declaran del modo:
char nombre_cadena[tamaño];
Cuando se guarda una cadena de caracteres en un array del tipo char,
siempre se almacena al final el carácter nulo ‘\0’, para conocerse hasta donde
está lleno el array. Por tanto el número máximo de caracteres utilizables que
pueden almacenarse en ese array será de tamaño-1.
Ej.
char codigo[10];
scanf(“%9[^\n]”, codigo);fflush(stdin);
Por ejemplo si se teclea el código “JAB32”, se almacena:
0
J
1
A
2
B
3
3
4
2
5 6
\0
7
8
9
Después del 2 se guarda \0. Por tanto el máximo número de caracteres
que pueden guardarse en ese array será de 9, aunque tenga tamaño 10.
Cuando se encuentra el \0 en el array, se sabe que de ahí hasta el final los
caracteres no se van a usar.
Este tipo de array es un tanto especial ya que existen funciones del C
que son capaces de manejar el array completo. Un ejemplo de esas funciones
la vemos en el ejemplo anterior, scanf permite teclear una cadena, sin tener
que usar un bucle para ir tecleando letra a letra. En el caso de arrays
numéricos siempre se accede a cada componente por separado, no se puede
manejar el array completo.
5.1. Funciones habituales con cadenas.
El lenguaje C es famoso por la gran cantidad de funciones que se
incluyen en sus librerías. Vamos a ver unas pocas muy usadas sobre arrays de
caracteres o cadenas, las cuales suelen incluirse en el fichero string.h:
strcpy(CadenaDestino, CadenaOrigen)
Copia el contenido de una cadena (CadenaOrigen) en otra
(CadenaDestino). En C, la asignación de cadenas no es correcta
(CadenaDestino = CadenaOrigen daría error), debe usarse la función strcpy.
7
La CadenaOrigen debe contener el carácter \0 como fin de cadena.
Dicho carácter será grabado automáticamente en CadenaDestino. Además el
programador debe controlar que la CadenaDestino tenga el tamaño suficiente
para almacenar la CadenaOrigen completa, ya que en caso contrario se
sobreescribirán posiciones de memoria que no pertenecen a la cadena.
Ej.
char nombre[25];
strcpy(nombre,"Juan Manuel"); //Al final añade el \0.
char nombre1[25], nombre2[25];
gets(nombre2); //La cadena tecleada en nombre2 se
strcpy(nombre1, nombre2); //copia en nombre1.
strcat(CadenaDestino, CadenaOrigen)
Concatena CadenaOrigen en CadenaDestino y añade un carácter nulo,
es decir el \0 o fin de cadena. En CadenaDestino queda lo que ya tenía y a
continuación se coloca CadenaOrigen. Hay que tener cuidado ya que no se
comprueban los límites o tamaños, por lo que se debe estar seguro que en
CadenaDestino cabe la cadena completa concatenada.
Ej.
char cad1[30], cad2[10];
strcpy(cad1, “JUAN”);
strcpy(cad2, “MANUEL”);
strcat(cad1, cad2); //En cad1 queda “JUANMANUEL”.
strlen(Cadena)
Devuelve la longitud de Cadena, es decir el número de caracteres que
tiene almacenados, que no debe confundirse con el tamaño máximo de la
cadena. No cuenta el carácter nulo ‘\0’.
Ej.
char cad1[10]; //Tamaño máximo de cad1 es 10.
strcpy(cad1, “RAM”); //3 caracteres guardados en cad1.
longitud = strlen(cad1); //En Longitud se guarda un 3.
strcmp(Cadena1, Cadena2)
Compara lexicográficamente las dos cadenas. Esta función devuelve un
número entero que se interpreta de la siguiente forma:
< 0 (menor que 0)
= 0 (igual a 0)
> 0 (mayor que 0)
Cadena1
Cadena1
Cadena1
es menor (<) que
es igual (=) que
es mayor (>) que
Cadena2.
Cadena2.
Cadena2.
Ej.
char codigo[10];
printf("Teclee código de acceso: ");
scanf(“%9[^\n]”, codigo); fflush(stdin);
if (strcmp(codigo, "azul")!=0) //Si devuelve algo !=0
8
printf( "Acceso Denegado \n");
else //strcmp devuelve 0 cuando codigo es “azul”.
printf( "Acceso Autorizado \n");
Ej.
char nombre1[30], nombre2[30];
strcpy(nombre1, “JUAN”);
strcpy(nombre2, “JOSE”);
if (strcmp(nombre1,nombre2)< 0)
printf(“%s \n %s”, nombre1, nombre2);
else
printf(“%s \n %s”, nombre2, nombre1);
//Se visualizan los 2 nombres ordenados
//alfabéticamente de menor a mayor.
5.2. Arrays de cadenas.
Un array de cadenas es un array bidimensional de caracteres, en el que
cada fila será una cadena.
Se declara de la forma:
char nombre_array[filas][columnas];
Por ejemplo si se desean almacenar 10 nombres en un array se podría
declarar:
char nombres[10][25];
//Cada nombre tendrá como máximo 24 letras.
El acceso a una componente del array se realiza a través de dos índices,
con lo cual se accederá a un carácter del array. Sin embargo, como se ha
mencionado anteriormente, hay funciones que pueden manejar una cadena
completa, por lo que en el caso de arrays de cadenas pueden manejar una fila
completa del array. Veamos un ejemplo.
Ej. Teclear 10 nombres en el array anterior.
char nombres[10][25];
int i;
for (i = 0; i < 10; i++) //la fila va de 0 a 9
{
printf(“\n Nombre %d:”, i);
scanf(“%24[^\n]”, nombres[i]); fflush(stdin);
//También podría hacerse con gets(nombres[i]);
}
Como vemos, en ese scanf no se usan dos índices, sino sólo 1 (índice i)
para hacer referencia a la fila donde va a almacenarse el nombre tecleado. La
columna la maneja el scanf automáticamente. Debe recordarse también que el
scanf, para teclear cadenas, no lleva el carácter & delante del nombre de la
9
variable. También la función printf puede manejar una cadena completa, por
ejemplo:
printf(“Nombre 3 del array: %s”, nombres[3]);
Si se desea acceder a un único carácter del array de cadenas, puede
hacerse como se explicado para arrays bidimensionales, es decir utilizando los
2 índices. El primer índice indicará a qué nombre de los 10 se va a acceder, es
decir la fila. El segundo índice indicará a qué carácter, dentro de ese nombre,
se va a acceder, es decir la columna.
Ej.
nombres[2][5] = ‘A’; //En el nombre de la fila 2,
//almacena una A en la columna 5.
Ej. Contar cuántas veces aparece la letra ‘A’ en los 10 nombres.
char nombres[10][25];
int i, j, VecesA = 0;
for (i = 0; i < 10; i++) //la fila va de 0 a 9
for (j = 0; j < strlen(nombres[i]); j++)
if (nombres[i][j] == ‘A’) //Usa 2 índices, i,j.
VecesA ++;
printf(“La letra A aparece %d veces.”, VecesA);
Como vemos en el ejemplo anterior, el índice j recorre cada nombre
(nombres[i]) hasta que se encuentre el ‘\0’, no hasta 25, que es su tamaño
máximo. Para ello puede usarse la función strlen como aparece en ese
ejemplo.
6. Inicialización de arrays.
Los arrays se puede inicializar de dos formas:
-en tiempo de ejecución del programa: recorriéndolos y colocando un
valor de inicio en cada componente.
-en tiempo de programación, al declararlo, de la forma:
tipo nombre_array[indice_1]...[índice_n]={lista valores};
donde lista valores tiene la forma:
{dato_0, dato_1, ..., dato_n}
Ej.
int cuadrados[4][2] =
{ 1,1,
2,4,
3,9,
10
4,8 };
En el caso de cadenas se hace usando comillas dobles en lugar de
llaves; el compilador de C se encarga de introducir el carácter nulo.
Ej.
char cadena[6] = "Error";
6.1. Inicialización de arrays sin tamaño.
El C nos permite inicializar arrays sin indicar el tamaño, para no tener
que contar los elementos que lo componen.
El tamaño del array será el necesario para guardar los datos de
inicialización. Ese tamaño queda fijado y no se puede alterar durante el tiempo
de ejecución. No debe confundirse con la asignación dinámica que veremos
más adelante.
Ej.
char cadena[] = "Error";
//cadena tendrá longitud 6, ya que Error son 5 letras,
//y hay que añadir el \0.
Si se usa esta inicialización en arrays multidimensionales, deben
especificarse todas las dimensiones excepto la de más a la izquierda (el primer
índice) en la declaración.
Ej.
char parejas[][2] =
{ 1,1,
//Tendrá 4 filas, aunque no se
2,2,
//haya indicado en [].
3,3,
4,4 };
7. Introducción a los arrays como parámetros de funciones.
Una componente de un array puede ser pasada como parámetro por
valor a una función, del mismo modo que cualquier otra variable, según se ha
explicado en un tema anterior. La función no podrá modificar esa componente
del array. El paso por referencia lo veremos más adelante.
Ej.
void FUNCION(int X); //Función que recibe un
//parámetro de tipo int.
void main(void)
{
int Edad[4] = {22,31,25,19}; //Array de 4 datos.
FUNCION(arr[2]); //Pasa la componente 2 por valor
//como parámetro, vale 25.
11
}
void FUNCION(int X) //X es una
{
//el valor
...;
//local de
}
//finaliza
copia de arr[2], toma
25. Es una variable
FUNCION, cuando
FUNCION se destruye X.
En ese ejemplo, la función trabaja con X y puede modificar su valor, pero
en ningún momento será modificado arr[2].
Por otra parte, también se puede pasar un array completo como
parámetro de una función. Para ello en la llamada a la función se usará el
nombre del array, sin indicar ninguna componente entre corchetes.
Debe destacarse que un array completo siempre se pasa por referencia,
no por valor. La función trabaja con el array original, no se crea una copia, por
lo que la función podrá modificar el contenido del array. Esto ocurre también
con arrays bidimensionales.
Ej.
void FUNCION(int arr[4]); //arr es array de tamaño 4.
void main(void)
{
int i;
int arr[4];
FUNCION( arr ); //Pasa el array completo, no se
//especifica índice ni corchetes.
for (i=0; i < 4; i++)
printf(“\nValor tecleado: %d”, arr[i]);
}
//Visualiza los valores tecleados en FUNCION.
void FUNCION(int arr[4]) //La FUNCION recibe el array
{
//completo como parámetro.
int i;
for (i=0; i < 4; i++)
{
scanf(“%d”, &arr[i]);fflush(stdin);
}
//Se carga el arr de main. La función puede
}
//hacerlo ya que trabaja con el original.
Ej. Con array bimensional:
void FUNCION(char nombres[10][25]); //Array de 10x25.
void main(void)
{
int i;
char nombres[10][25];
FUNCION(nombres); //Pasa el array completo.
for (i=0; i < 10; i++)
printf(“Nombre %d :, %25s”, i+1, nombres[i]);
12
}
//Visualiza los 10 nombres tecleados en FUNCION.
void FUNCION(nombres[10][25]) //La FUNCION recibe el
{
//array completo.
int i;
for (i=0; i < 10; i++)
{
scanf(“%24[^\n]”, nombres[i]);fflush(stdin);
}
//Se cargan 10 nombres en el array de main.
}
13
EJERCICIOS - CAPITULO 8:
Realizar los siguientes algoritmos en pseudocódigo y en C.
1. Introducir desde teclado las edades de alumnos en un array de 50
componentes. El programa finalizará al responder ‘N’ a la pregunta
“Introducir edad (S/N)?”. Calcular al final la edad media de las edades
tecleadas.
2. Teclear 20 números guardándolos en un array y visualizarlos en orden
inverso al de entrada.
3. Teclear las notas de alumnos en un array de 100 componentes. El
programa finalizará cuando la nota tecleada sea –1. Visualizar los
porcentajes de suspendidos y aprobados, y dentro de los aprobados el
porcentaje de sobresalientes.
4. Guardar 30 valores en un array. A continuación deben teclearse valores y
para cada valor se visualizará cuántas veces está en el array. El programa
finalizará cuando se responda ‘N’ a “Contar otro valor (S/N)?”.
5. Usando el array anterior, visualizar cuál es el mayor valor guardado en el
array y cuántas veces aparece.
6. Introducir en un array las 11 notas enteras de los 30 alumnos de una clase.
Después debe visualizarse la nota media de cada uno de los alumnos y al
final visualizar cuántos alumnos hay aprobados y suspendidos y la nota
media de toda la clase.
7. Usando el array anterior y teniendo en cuenta que las notas guardadas
están entre 0 y 10, contar cuántas veces aparecen cada una de las notas,
guardando los resultados en un array de 11 componentes.
8. Cargar en un array de 10x20 valores positivos distintos. A continuación
teclear valores hasta que se teclee un –1. Para cada valor tecleado debe
indicarse si existe en el array y en qué celda se encuentra.
9. Usando el array anterior, visualizar el número de la fila cuya suma de sus
componentes es mayor.
10. Teclear nombres en una cadena, hasta que el nombre tecleado se deje en
blanco. El formato será “apellido1 apellido2, nombre”. Para cada nombre
tecleado debe visualizarse si el nombre es simple o compuesto.
11. Introducir un nombre y apellidos en una cadena y transfórmalo en
mayúsculas inversas (primera letra en minúscula y resto en mayúscula para
cada palabra). Usar las funciones tolower y toupper.
14
12. Introducir frases en una cadena hasta responder ‘N’ a “Introducir frase
(S/N)?”. Cada frase tecleada debe guardarse en otra cadena dejando sólo
las letras y números, sin blancos ni signos de puntuación.
13. Teclear 10 nombres en una cadena. El formato del nombre será “Nombre
Apellido1 Apellido2”. Para cada nombre deberán visualizarse sus iniciales
en el formato “N. A. A.”.
14. Teclear una frase en una cadena formada por letras y blancos. Después
teclear una palabra e indicar si esa palabra está en la frase y en qué
posición comienza.
15. Introducir dos grupos de 5 palabras en dos arrays. Ambos grupos de
palabras deben coincidir y en caso contrario deben visualizarse las
posiciones de las que no coinciden.
16. Introducir frases en un array de 30x100, hasta que la frase se deje en
blanco. Para cada frase tecleada se visualizará si es capicúa.
17. Guardar en un array 10 nombres encriptados. Para encriptar se usará el
siguiente código: cada carácter tecleado se guardará como el carácter que
ocupa 3 posiciones más adelante en el código ASCII. Visualizar el array
encriptado y sin encriptar.
18. Teclear nombres y sus dni en dos arrays hasta que se responda ‘N’ a
“Teclear datos (S/N)?”. Después el programa permitirá buscar el dni que
corresponda el nombre que se vaya tecleando, hasta que se teclee uno en
blanco.
19. Introducir nombres de alumnos (pasándolos a mayúsculas) y sus edades en
dos arrays de 50 componentes, hasta que el nombre tecleado se deje en
blanco. Visualizar el nombre y la edad del alumno de mayor edad.
20. Usando los arrays anteriores, rotarlos el número de posiciones que se
teclee. Los elementos que salgan un lado entrarán por el contrario.
21. Cargar en un array 30 nombres de personas y en otro las 30 puntuaciones
de esas personas. El programa debe calcular y guardar en un tercer array la
posición que ocupa cada persona según su puntuación, de mayor a menor.
Al final visualizar los nombres y las puntuaciones ordenadas de mayor a
menor.
22. Cargar en un array los nombres de 10 asignaturas. Después cargar en otro
array los 10 notas (una de cada asignatura) de alumnos, hasta responder
‘N’ a la pregunta “Otro alumno (S/N)?”. Finalmente el programa solicitará
número de alumno y nombre de asignatura y visualizará la nota de ese
alumno en esa asignatura. Cuando el número de alumno tecleado sea –1
finalizará el programa.
15
Documentos relacionados
Descargar