Está en la página 1de 18

Arreglos y Matrices

22 23 25 24 26 27 26

26/03/2023 Programación I 1
Arreglos: Introducción
En el caso que se deba trabajar con un conjunto de
elementos, sería bastante desprolijo la creación de varias
variables. Para esto se utiliza la herramienta arreglos.

Un arreglo se define como colección ordenada de


elementos del mismo tipo.

22 23 25 24 26 27 26

2
Arreglos: Definición
En C una variable tipo arreglo se define de la siguiente
manera:

tipo nombre_arreglo [ CANT_ELEMS ];

El tipo especifica el tipo de dato de cada elemento (double,


char, int, etc.) mientras que CANT_ELEMS especifica la
cantidad de elementos, la cual debe ser constante.

Ejemplo:
• int legajos [10]; /* arreglo de 10 enteros */
• char alfabeto [26]; /* arreglo de 26 caracteres */
• double temperaturas [5]; /* arreglo de 5 doubles */

3
Arreglos: Inicialización
Un arreglo, igual que cualquier variable, se puede definir e
inicializar simultáneamente, colocando en una lista los valores
iniciales entre llaves «{}» separados por coma «,».
tipo nombre_arreglo [N] = { VAL1, VAL2, … ,VALN };

En este caso se puede dejar los corchetes vacíos, ya que el


compilador obtiene la cantidad de elementos de la lista.
tipo nombre_arreglo [ ] = { VAL1, VAL2, … ,VALN };

Ejemplo:
• int legajos [3] = {40033, 40120, 40055};
• double temp [] = {20.3, 25.2, 26.0, 24.8, 22.3};
• char msg1[] = { 'H', 'O', 'L', 'A' };
• char msg2[] = "HOLA";

Forma simplificada,
sólo sirve para strings.
4
Arreglos: Acceso
Para acceder a los elementos de un arreglo se utiliza un
índice.
En lenguaje C, el índice del primer elemento es el 0.

Para hacer referencia al primer elemento del arreglo se usa


el índice 0, al segundo elemento el índice 1 y así
sucesivamente. Si el arreglo tiene N elementos el índice
puede tomar valores desde 0 hasta N-1.

Para hacer referencia a cualquier elemento del arreglo


usamos la notación arreglo[i], donde i es el índice.

22 23 25 24 26 27 26

0 1 2 3 4 5 6 ¡No confundir
elemento con
índice índice!

5
Arreglos: Acceso
Ejercicio 1: Predecir cómo quedan las variables al finalizar el programa.
int main(void)
{
int arr[5];
int ind = 1;

arr[0] = 5;
arr[ind+1] = -6;
arr[4] = 7;
arr[ind++] = 1;
arr[++ind] = -3;
++arr[2];

return 0;
}

6
Arreglos: Acceso
En assembler el acceso a los elementos del arreglo se
realizaba manualmente, considerando la dirección inicial de
arreglo, el tamaño de los elementos y el elemento en
cuestión.

dirección de legajo[i] = legajo + i * EL_SIZE donde i = 0…N-1.

Ejemplo: Acceso a legajo[2]


legajo[0]
ldaa #2 indice=2
ldx #legajo
legajo[1]
ldab #EL_SIZE
mul
legajo[2] abx

Read ldd 0,x Lectura


legajo[3] Write std 0,x Escritura

7
Arreglos: Precauciones
A fin de hacer un código eficiente, el lenguaje no nos protege
en ciertos casos, por lo que se debe ser precavido.

• El lenguaje C no verifica que el valor del índice se


encuentre en dentro de los límites del arreglo, ni durante
la compilación ni en la ejecución.
• No se pueden realizar operaciones a todo el conjunto de
elementos, se debe hacer elemento por elemento.
• Los elementos de un arreglo son Lvalue, el arreglo NO es
un Lvalue.
• El tamaño de un arreglo es fijo. No es posible agregar
ni quitar elementos.

Modificar el programa anterior y probar estos puntos…

8
Arreglos: Funciones
¿Cómo podemos hacer llegar el contenido de un arreglo a una
función para que lo procese?

Ejemplo: Tenemos un arreglo con las temperaturas de todos


los días de la semana y deseamos hacer una función que
devuelva el promedio de todas las temperaturas de la semana.

Una posibilidad sería el pasaje por valor, pero eso no es muy


práctico pues para eso la función tendría que hacer una copia
de todo el arreglo en memoria, lo que puede ser muy grande.

A fin de lograr código eficiente, el lenguaje C pasa la


dirección del primer elemento del arreglo, en otras
palabras, un puntero al primer elemento del arreglo.

Por lo tanto, si la función realiza alguna modificación, lo hace


sobre el arreglo original, no sobre una copia.
9
Arreglos: Funciones
La definición de la función seria la siguiente:
double prom_temp (double temp[], unsigned int cantidad)
{
unsigned int i;
double prom=0;

for (i=0 ; i<cantidad ; i++)


prom += temp[i];

return prom / cantidad;


}

10
Arreglos: Funciones
El uso de dicha función sería:
#include <stdio.h>

double prom_temp (double temp[], unsigned int cantidad);

int main(void)
¿Porqué se pasa la cantidad de elementos?
{
¿No se puede calcular dentro de la función?
int n;
double prom;

double temperaturas[]={10.5,15.3,12,16.3,20,16,17};
n = sizeof(temperaturas) / sizeof(temperaturas[0]);
prom = prom_temp(temperaturas, n);
printf("El promedio es: %f\n", prom);

return(0);
}

11
Matrices: Introducción
En varias situaciones es conveniente trabajar con matrices,
tanto bidimensionales (2D) como multidimensionales (3D,
4D, etc.).

Esto es posible en el lenguaje C mediante un arreglo de


arreglos. Todos los conceptos y reglas previamente
presentadas se respetan.

A continuación se explicará con matrices 2D, pero aplica


para matrices de cualquier dimensión.

12
Matrices: Definición
La definición de una matriz (o arreglo bidimensional) es
entonces:

tipo nombre_matriz [ CANT_FILS ] [ CANT_COLS ];

Ejemplo:
• int mat [4][10]; /* matriz de enteros de
4 filas y 10 columnas */

Esta definición podría pensarse como un


arreglo de 4 elementos, donde cada
elemento es un arreglo de 10 enteros.

El tamaño en bytes de este arreglo


bidimensional es: 4*(10*sizeof(int)).

13
Matrices: Inicialización
La inicialización se realiza de manera similar a la de un
arreglo. Si una matriz es un arreglo de arreglos, y estos
últimos se inicializan con una lista, la matriz se inicializará
¡como una lista de listas!

Ejemplo:
• int mat [2][4] = { {1, 2, 3, 4}, {11, 12, 13, 14} };

El compilador obtiene la cantidad de elementos de la lista,


pero el tipo de datos de los elementos debe estar definido.

¿Cuáles de las siguientes definiciones son válidas?


• int mat [ ][ ] = { {1, 2, 3, 4}, {11, 12, 13, 14} };
• int mat [ ][4] = { {1, 2, 3, 4}, {11, 12, 13, 14} };
• int mat [2][ ] = { {1, 2, 3, 4}, {11, 12, 13, 14} };
• int mat [2][4] = { {1, 2, 3, 4}, {11, 12, 13, 14, 9} };
• int mat [2][4] = { {1, 2, 3, 4}, {11, 12} };
14
Matrices: Inicialización
A igual que arreglos unidimensionales, es posible definir e
inicializar una matriz de strings de forma simplificada.

Ejemplo:
• char texto [ ][9] = { "hola", "mundo" };

¿Qué tamaño tendrá la matriz anterior?

15
Matrices: Acceso
Para acceder a los elementos de una matriz, basta con
pensarla como un arreglo de arreglos.

Ejemplo:
• value = mat[1][2];

• mat[0][2] = 7;
¿Qué realiza cada una de estas expresiones?
• mat[i+1][j-1]++;

Interpretación gráfica:
mat [0] mat [1][2]
mat [1]

El cálculo que realiza el compilador para acceder al elemento (i, j)


de una matriz es:
direccion_base + ( CANT_COLUMNAS * i + j ) * sizeof(tipo)
16
Matrices: Funciones
A igual que con arreglos, se pueden escribir funciones que
reciban una matriz. En dicho caso, lo que realmente recibirá
es un puntero al primer elemento (primera columna de la
primera fila).

Ejemplo:
Función que calcula la sumatoria de los elementos de una
matriz de rows filas por 10 columnas.
Su prototipo es: int sum(int matrix[][10], int row);
Se invoca: rta = sum(mat, 5);

Es necesario especificar la cantidad de


columnas en el prototipo. Analizar porqué.

Pensar e implementar dicha función.

17
Ejercicios
• Escribir una función que busque el mayor elemento del
arreglo de enteros y lo devuelva. Luego escribir un
programa que lo pruebe con distintos vectores.

• Idem ejercicio anterior con una matriz.

• Completar una matriz con números consecutivos en forma


de espiral.

• Escribir una función que reciba un string con texto válido


(con signos de puntuación y varios renglones) y luego
determine cuantas palabras contiene.

• Escribir una función que realice la multiplicación de dos


matrices de 3x3, utilizando ciclos, y devuelva su resultado.
Pensar el prototipo de la función y cómo devolver el
resultado.
18

También podría gustarte