06 - arrays y matrices en lenguaje c

62
1 06 - Arrays y matrices Diego Andrés Alvarez Marín Profesor Asociado Universidad Nacional de Colombia Sede Manizales

Upload: diego-andres-alvarez-marin

Post on 13-Jun-2015

272 views

Category:

Software


5 download

DESCRIPTION

Si quiere descargar la presentación y los códigos fuente, dirijase a: http://programaciondecomputadoresunalmzl.wikispaces.com/codigos_y_diapositivas Le agradecería si me reporta los errores que encuentre en la diapositiva (daalvarez arroba unal punto edu punto co)

TRANSCRIPT

Page 1: 06 - Arrays y matrices en lenguaje C

1

06 - Arrays y matrices

Diego Andrés Alvarez MarínProfesor Asociado

Universidad Nacional de ColombiaSede Manizales

Page 2: 06 - Arrays y matrices en lenguaje C

2

Temario

Declaración de arrays

Inicialización de arrays

Acceso a los elementos del array

Arrays multidimensionales

Cadenas de texto

Arrays de cadenas

Arrays de uniones

Arrays de estructuras

Ordenamiento de arrays (burbuja, quicksort)

Agotando la memoria de pila

Arrays como parámetros de funciones

Page 3: 06 - Arrays y matrices en lenguaje C

3

Declaración de arrays

Se debe especificar el tipo y el número de elementos del array.

int mi_array[10];

El C99 permite declarar el tamaño de un array con una variable, no con una constante. Dicho array solo existe en el bloque en el que se definió (variable local):

int n = 10;

int mi_array[n];

Page 4: 06 - Arrays y matrices en lenguaje C

4

Declaración de arrays globales

Tenga en cuenta que una declaración como:

const int N = 5;int a[N];

tratando de crear a[] como una variable global no funciona. Esto sucede ya que “const” significa “solo lectura”. El valor de un objeto “const” no es necesariamente constante (si lo es en C++). En este caso:

#define N 5 int a[N];

Esto no funciona, produce error de compilación

Esta es la forma correcta dedeclarar el array global

Page 5: 06 - Arrays y matrices en lenguaje C

5

Inicialización de arraysint x[5] = { 0, 1, 2, 3, 4 };

int x[5] = { 0, 1, 2 }; /* esto es x[0]=x[3]=x[4]=0, x[1]=1, x[2]=2 */

int x[5] = { 0 }; /* inicializa todo el array a 0 */

El C99 permite:

int x[5] = { [2] 5, [4] 9 };

int x[5] = { [2] = 5, [4] = 9 };

lo cual es equivalente a:

int x[5] = { 0, 0, 5, 0, 9 };

Page 6: 06 - Arrays y matrices en lenguaje C

6

Inicialización de arrays

Existe una GNU extension que permite hacer lo siguiente:int x[100] = { [0 ... 9] = 1, [10 ... 98] = 2, 3 };

En este caso los elementos x[0] a x[9] valen 1, x[10] a x[98] valen 2 y x[99] vale 3. Note que debe existir un espacio antes y después de los "..."

Si usted inicializa cada elemento del array, no es necesario especificar su tamaño:int x[] = { 0, 1, 2, 3, 4 }; // tamaño 5 int x[] = { 0, 1, 2, [99] = 99 }; // tamaño 100

Page 7: 06 - Arrays y matrices en lenguaje C

7

Acceso a los elementos del array

A[i] designa al elemento i+1 del array A

Se especifica el nombre y el número del elemento:x[1] = 5; // asigna al segundo elemento un 5

Con estructuras:struct arraypunto{ int x, y;};struct arraypunto punto[2] = { {4, 5}, {8, 9} };punto[0].x = 3;

Page 8: 06 - Arrays y matrices en lenguaje C

8

Verificación de límites(array bound checking)

C no provee un método para verificar los límites de los arreglos durante su uso.

La bandera de compilación -O2 (menos o mayúscula 2) puede ayudar en algo, aunque no capturaría errores en tiempo de ejecución.

Page 9: 06 - Arrays y matrices en lenguaje C

9

Compound literals (GNU C extension)http://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

Note que p2 no se inicializó; en la línea 10 se está separando y a la vez asignando el espacio de memoria para p2. Esta asignación sólo es válida en el bloque { } en el cual se utilizó el compound literal.

sizeof(p2) = 4 bytes ya que se ejecutó el programa en un sistema operativo de 32 bits; si hubiera sido un sistema operativo de 64 bits sizeof(p2) = 8 bytes

Tiene que ser (int []) ya que si usted pone (int *) el código falla.

Page 10: 06 - Arrays y matrices en lenguaje C

10

Ejemplo de compound literals

para arrays

Page 11: 06 - Arrays y matrices en lenguaje C

11

Arrays multidimensionales

int m[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10} };

Se usa así:m[1][3] = 12; // asignaciónprintf("%d", m[1][3]); // referencia

En la memoria m[0][2] está seguido por m[0][3], no por m[1][2].

Los elementos en un array multidimensional se guardan fila a fila no columna a columna como lo hace FORTRAN o MATLAB.

Page 12: 06 - Arrays y matrices en lenguaje C

12

Disposición de los elementos de una matriz en la memoria

Lenguaje C/C++

Fortran/MATLAB

Page 13: 06 - Arrays y matrices en lenguaje C

13

Arrays multidimensionales: arrays de dos o más dimensiones

int tabla[5][5][20];float array[5][6][5][6][5];

tabla es un array 3D, que puede almacenar 5*5*20=500 ints es decir 2000 bytes.

array es un array 5D, que puede almacenar 5*6*5*6*5=4500 floats, es decir 18000 bytes.

Page 14: 06 - Arrays y matrices en lenguaje C

14

Salida:

Page 15: 06 - Arrays y matrices en lenguaje C

15

Accediendo a las filas de una matriz

M[k] es un puntero que apunta al elemento M[k][0] de la matriz

Page 16: 06 - Arrays y matrices en lenguaje C

16

Compound literals para matrices

Page 17: 06 - Arrays y matrices en lenguaje C

17

Memoria cachéLa memoria caché es una memoria utilizada por la CPU para reducir el tiempo promedio de acceso a la memoria RAM. Es una memoria más pequeña, más rápida y más costosa que almacena copias de los datos a los que se acceden más frecuentemente. Cuando el procesador necesita leer o escribir en un lugar de memoria, primero verifica si una copia de los datos está en el caché. Si esto sucede, el procesador inmediatamente lee o escribe al cache, lo cual es mucho más rápido que escribir directamente a la memoria principal. Si estos datos no están, el caché trae los datos de la memoria principal, generalmente reescribiendo aquella información presente en el caché que poco se ha utilizado recientemente.

Mientras el procesador ejecuta otras tareas, el caché transfiere los datos entre la memoria principal y el caché en bloques de tamaño constante llamados "líneas del caché" (cache lines). Estas líneas tienen un tamaño de 32, 64 o 128 bytes (lo cual depende de la arquitectura donde se está ejecutando el programa).

Page 18: 06 - Arrays y matrices en lenguaje C

18

Array caching

Ciclo CON array caching

Ciclo SINarray caching

Este comportamiento se debe a la cercanía de las referencias.

Ver:http://en.wikipedia.org/wiki/Locality_of_reference

Page 19: 06 - Arrays y matrices en lenguaje C

19

Inicialización de cadenas de texto

char color1[26];char color2[26] = {'r', 'o', 'j', 'o', '\0'};char color3[26] = "naranja";char color4[] = {'g', 'r', 'i', 's', '\0'};char color5[] = "verde";

En cada uno de estos casos se incluye el carácter nulo '\0' al final de la cadena, incluso cuando no se especifica explícitamente.

Page 20: 06 - Arrays y matrices en lenguaje C

20

Inicialización de cadenas de texto

Cuando se crea un matriz de enteros y se declara:int matriz[5][5]={10};

solamente en la posición [0][0] se inicializa con un 10 el resto de posiciones toman el valor de 0. Del mismo modo, al hacer:char color[8] = "AZUL";

en la memoria se asigna:

Page 21: 06 - Arrays y matrices en lenguaje C

Pregunta

Con respecto a las cadena de texto, cual es la diferencia entre 'A' y “A” ?

Respuesta: ●'A' es el carácter A (ocupa 1 byte)●“A” es la cadena de texto A que se representa en memoria como A \0 y ocupa 2 bytes

Page 22: 06 - Arrays y matrices en lenguaje C

22

Cadenas de textoDespués de la inicialización, no se puede asignar una nueva cadena al array utilizando el operador de asignación. Por lo tanto, lo siguiente es inválido:char fruta1[20];char fruta2[26] = "naranja"; // OKfruta1 = fruta2; // Error!fruta1 = "naranja"; // Error!

Esta asignación se puede hacer utilizandostrcpy(fruta1,fruta2); // Esta en string.hstrcpy(fruta1,"naranja");

Page 23: 06 - Arrays y matrices en lenguaje C

23

Un error frecuente tratando de copiar cadenas

Page 24: 06 - Arrays y matrices en lenguaje C

24

La forma correcta de copiar cadenas

strlen(s) retorna la longitud de la cadena s, sin incluir el caracter final '\0'. Se encuentra en string.h

Page 25: 06 - Arrays y matrices en lenguaje C

25

Arrays de

cadenas

Estas expresiones funcionan porque son constantes cadena; si fueran variables cadena, habría un error.

El puntero apunta a la dirección de memoria de las constantes cadena, las cuales residen en el segmento de código.

sizeof(cad2) = 12 bytes (32 bits)sizeof(cad2) = 24 bytes (64 bits)

Page 26: 06 - Arrays y matrices en lenguaje C

26

Page 27: 06 - Arrays y matrices en lenguaje C

27

Arrays de unionesunion u{ int i; float f;};union u x[3];

Los tres primeros miembros de x se pueden inicializar como:

union u x[3] = { {3}, {4}, {5} };

(los brackets internos son opcionales)

Los elementos se acceden así:x[0].i = 2;

Page 28: 06 - Arrays y matrices en lenguaje C

28

Arrays de estructuras

struct punto{ int x, y;};struct punto p[3];

Los elementos se pueden inicializar así:struct punto p[3] = { {2, 3}, {4, 5}, {6, 7} };

Para acceder a los elementos se hace lo siguiente:struct punto p[3];p[0].x = 2;p[0].y = 3;

Page 29: 06 - Arrays y matrices en lenguaje C

29

Copiando arrays: memcpy() vs for()

memcpy() es un poco más veloz (pero no se justifica usarlo, ya que el código con el for es mucho más fácil de leer y menos propenso a equivoca-ciones)

memcpy() está en string.h

Page 30: 06 - Arrays y matrices en lenguaje C

30

Algoritmos de ordenamientoSon algoritmos que pone elementos de un array en una secuencia dada por una relación de orden. Las relaciones de orden más usadas son el orden numérico y el orden lexicográfico (orden alfabético). Ordenamientos eficientes son importantes para optimizar el uso de otros algoritmos (como los de búsqueda y fusión) que requieren listas ordenadas para una ejecución rápida. También es útil para poner datos en forma canónica y para generar resultados legibles por humanos.

https://en.wikipedia.org/wiki/Sorting_algorithm

Page 31: 06 - Arrays y matrices en lenguaje C

31

Algoritmo burbuja (bubblesort)

Funciona revisando cada elemento de la lista que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado. Es necesario revisar varias veces toda la lista hasta que no se necesiten más intercambios, lo cual significa que la lista está ordenada. Este algoritmo obtiene su nombre de la forma con la que suben por la lista los elementos durante los intercambios, como si fueran pequeñas "burbujas".

Es muy ineficiente, por lo que es recomendable utilizar otros algoritmos de ordenamiento.

http://en.wikipedia.org/wiki/Bubble_sort

Page 32: 06 - Arrays y matrices en lenguaje C

32

Algoritmoburbuja

Page 33: 06 - Arrays y matrices en lenguaje C

33

Algoritmo quicksortCreado por Charles Hoare, basado en la técnica de divide y vencerás. Permite en promedio ordenar n elementos en un tiempo proporcional a n log

2 n.

El algoritmo trabaja de la siguiente forma:● Elegir un elemento de la lista de elementos a ordenar, al que

llamaremos pivote.● Resituar los demás elementos de la lista a cada lado del pivote,

de manera que a un lado queden todos los menores o iguales que él, y al otro los mayores. En este momento, el pivote ocupa exactamente el lugar que le corresponderá en la lista ordenada.

● La lista queda separada en dos sublistas, una formada por los elementos a la izquierda del pivote, y otra por los elementos a su derecha.

● Repetir este proceso de forma recursiva para cada sublista mientras éstas contengan más de un elemento.

● Una vez terminado este proceso todos los elementos estarán ordenados.

Page 34: 06 - Arrays y matrices en lenguaje C

34

Algoritmo quicksortSelección del pivote:

La selección del pivote es la parte más crítica para un funcionamiento óptimo del algoritmo.

Existen varios métodos para seleccionar el pivote. Uno de los aconsejados es tomar tres elementos de la lista - por ejemplo, el primero, el segundo, y el último - y compararlos, eligiendo el valor de la mediana (el del centro).

http://en.wikipedia.org/wiki/Quicksorthttp://youtu.be/ywWBy6J5gz8 (apréndalo bailando)

Page 35: 06 - Arrays y matrices en lenguaje C

35

Algoritmo quicksort

El programa:http://programaciondecomputadoresunalmzl.wikispaces.com/file/detail/06_alg_ordenamiento.c

Page 36: 06 - Arrays y matrices en lenguaje C

36

Page 37: 06 - Arrays y matrices en lenguaje C

37

La función qsort (stdlib.h)

#include <stdlib.h>

void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));

Ver: http://www.cplusplus.com/reference/cstdlib/qsort/

Page 38: 06 - Arrays y matrices en lenguaje C

38

Algoritmo de búsqueda binaria

El programa:http://programaciondecomputadoresunalmzl.wikispaces.com/file/detail/06_alg_busqueda.c

Page 39: 06 - Arrays y matrices en lenguaje C

39

La función bsearch() (stdlib.h)

#include <stdlib.h>

void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

Ver: http://www.cplusplus.com/reference/cstdlib/bsearch/

Page 40: 06 - Arrays y matrices en lenguaje C

40

Definiendo arrays dinámicos con malloc() y free()

x existe en lamemoria de pila

x existe en lamemoria del montón

Page 41: 06 - Arrays y matrices en lenguaje C

41

Separando memoria del montón con malloc() y free()

Si no se usa free( ), el espacio reservado anteriormente por malloc( ) no será re-utilizable hasta que el programa termine, momento en el cual el sistema libera el espacio automáticamente.

Entonces la consecuencia es que el programa ocuparía más espacio en memoria de la que se necesita. Por eso lo más recomendable es siempre liberar el espacio con free( ) cuando ya no se requiera dicha memoria.

Page 42: 06 - Arrays y matrices en lenguaje C

42

Tenga en cuenta que con las direcciones de memoria de los elementos del array:&x[0] == x+0 == x&x[1] == x+1&x[2] == x+2&x[N-1] == x+N-1

Por lo tanto:x[0] == *(x+0)x[1] == *(x+1)x[2] == *(x+2)x[N-1] == *(x+N-1)

x

El poner o no (double *) comocasting aquí es opcional

Page 43: 06 - Arrays y matrices en lenguaje C

43

Acceso a los elementos de la matriz A por medio de aritmética de punteros

Page 44: 06 - Arrays y matrices en lenguaje C

44

Error!!!

Lo correcto es:*((int *)A + i)El casting se debe hacer porque A es un puntero a un array de punteros, es decir cada elemento de A es del tipo int [4]. La aritmética de punteros solo funciona si A es un puntero int *

Page 45: 06 - Arrays y matrices en lenguaje C

45

Tamaño de aquello a loque apunta el puntero A

Page 46: 06 - Arrays y matrices en lenguaje C

46

Agotando la memoria de pilahttp://compgroups.net/comp.lang.c/problem-with-big-matrices/713823

Page 47: 06 - Arrays y matrices en lenguaje C

47

Agotando la memoria de pila

El problema con la matriz anterior es que a pesar que solo ocupa 30.5 Mb y tenemos 4 Gb de RAM, el programa falla por falta de memoria en la pila.

Soluciones:● Declarar la matriz A como static● Definir la matriz A en la memoria del montón

(heap memory)● Incrementar la memoria de pila

Page 48: 06 - Arrays y matrices en lenguaje C

48

Verificando el tamaño de la memoria de pila en Linux

Se tienen 8 Mb de pila

Page 49: 06 - Arrays y matrices en lenguaje C

49

Verificando el tamaño de la memoria de pila en Windows

Se deben utilizar programas como VMMap de Sysinternals para mirar el tamaño de la pila.

Ver:http://en.wikipedia.org/wiki/Winternals http://technet.microsoft.com/en-us/sysinternals/bb842062http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx

Page 50: 06 - Arrays y matrices en lenguaje C

50

Solución 1:Declarar la matriz A como static:

Al ser A una variable estática esta se crea en el segmento de datos, no el la pila

Page 51: 06 - Arrays y matrices en lenguaje C

51

Solución 2: Definir la matriz A en la memoria del montón

Esta es mi solución preferida.malloc() siempre separa la memoria de la memoria del montón

Page 52: 06 - Arrays y matrices en lenguaje C

52

Solución 3:Incrementar la memoria de pila

Es una solución dependiente del sistema operativo, y por lo tanto es mejor evitarla.

Page 53: 06 - Arrays y matrices en lenguaje C

53

Cambiando el tamaño de la memoria de pila (GNU/Linux)

$ ulimit -a # muestra el tamaño actual de la pila$ ulimit -s 32768 # cambia el tamaño de la pila a 32 Mb

Page 54: 06 - Arrays y matrices en lenguaje C

54

Cambiando el tamaño de la memoria de pila (Windows)

No existe un comando que haga esto

Page 55: 06 - Arrays y matrices en lenguaje C

55

Arrays como parámetros de funciones

Estos dos códigos son equivalentes:

Aquí se está pasando un puntero al primer elemento en x. Tenga en cuenta que dentro de la función no se puede usar sizeof para determinar el tamaño del array. El sizeof dará el tamaño del puntero a. El dar el tamaño del array en la declaración de la función tampoco sirve.

Para pasar un array "por valor", toca meterlo dentro de una estructura. Aunque es mejor pasar un const array para indicar que uno no debe modificar el array.

Page 56: 06 - Arrays y matrices en lenguaje C

56

Arrays multidimensionales como parámetros de funciones: standard C89

Modo utilizado con el standard C89: Las siguientes formas de pasar una matriz como parámetro a una función son válidas y equivalentes:

la primera

Page 57: 06 - Arrays y matrices en lenguaje C

57

Como no hay una forma general óptima de escribir una sola función que acepte ambas matrices la mejor forma de pasar la matriz es pasar un puntero al elemento [0][0], junto con el número de filas y de columnas y hacer la referencia a los elementos "manualmente":

Observe que no se necesita para nada el parámetro nfil.

Esta función se llamaría usando:

Page 58: 06 - Arrays y matrices en lenguaje C

58

Cuando se tiene un array de más de tres dimensiones, únicamente la primera dimensión es opcional. Las otras dimensiones son obligatorias:

void mifun(int miarray[][3][4]){

}

Page 59: 06 - Arrays y matrices en lenguaje C

59

Arrays multidimensionales como parámetros de funciones: standard C99

En C99 se pueden pasar las dimensiones del array antes de pasarlo.

Recuerde que el for(int i=0; ...se activa con el -std=c99

Prototipo de n

Page 60: 06 - Arrays y matrices en lenguaje C

Funciones que retornan arrays

No es posible utilizar return para devolver un array que fue creado dentro de la función. Los arrays se tratan como punteros, de modo que al salir de la función, una copia del puntero se transfiere. Al salir de la función, la variable local x es destruida, por lo que el puntero apunta a un pedazo de memoria ilegal.

Si se quiere retornar dicho array, este se debe crear utilizando malloc().

No es la salidaesperada

Page 61: 06 - Arrays y matrices en lenguaje C

Casting de array a matriz

Page 62: 06 - Arrays y matrices en lenguaje C

Material basado en:

Wikipediahttp://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

http://rajkishor09.hubpages.com/hub/How-to-work-with-Multidimensional-Array-in-C-Programming