- Unidad 3 Tipos de Datos Estructurados 1
Tipos de Datos Compuestos en C 2
Arreglos (1) Un arreglo (array) una colección homogénea de datos simples ó compuestos, que se referencian con un nombre comú, y cuyos elementos son accedidos mediante un índice. Se utilizan los corchetes ([]) para declarar el arreglo y para acceder a sus elementos. La sintaxis es: <tipo> <variable>[<dimensión>]; Por ejemplo: int V[100]; 3
Arreglos (2) Los índices de un arreglo comienzan siempre en 0 (cero). Para acceder a los elementos de un array: V[6] = 9; Para recorrer un array: for (i = 0; i<5; i++){ V[i] = i; printf("v[ %d ] = %d \n", i, V[i]); } 4
En C todos los arreglos son unidimensionales. Si queremos tener arreglos multidimensionales (de más de una dimensión), necesitamos un conjunto de corchetes por cada una de ellas. Por ejemplo: Arreglos (3) int X[10]; int Y[10][20]; int Z[10][50][100]; // 1 dimensión // 2 dimensiones // 3 dimensiones 5
Estructuras (1) Un registro ó estructura es una colección heterogénea de datos simples ó compuestos, cuyos elementos son denominados campos ó miembros. Por ejemplo, un alumno contiene una colección de datos diversos, como por ejemplo, entre otros: Número de Libreta: Un tipo entero largo. Carrera: Un tipo enumerado con los valores (TUP, TIG, TEU, etc.). Fecha de Nacimiento: Una fecha también es del tipo estructura: DD/MM/AAAA. 6
Estructuras (2) 7
Estructuras (3) Es decir que el esquema de una estructura es la siguiente: 8
Siendo la sintaxis en el lenguaje C, para definir una estructura la siguiente: struct <nombre>{ } <variables>; Estructuras (4) <tipo_1> <miembro_1>; <tipo_2> <miembro_2>;... <tipo_n> <miembro_n>; 9
Por ejemplo: struct nrocomplejo{ } z; Estructuras (5) int ptereal; int pteimag; Y para acceder a cada uno de los miembros de la estructura anterior, hacemos: z.ptereal = 1; z.pteim = 0; 10
Uniones (1) Una unión es una posición de memoria que es compartida por varias variables, que pueden ser de tipos diferentes. Por ejemplo, en la siguiente declaración x es una variable, que podrá alojar tanto un entero como un carácter: union IntChar{ int num; char car; } x; 11
Uniones (2) En la variable x, tanto el entero num como el carácter car comparten la misma posición de memoria. Y el compilador asigna el suficiente espacio de memoria, para que se pueda almacenar al más grande de los miembros especificados. Y si escribimos la siguiente porción de código: x.num = 4427; printf("int = %d Char = %c \n", x.num, x.car); x.car = M ; printf("int = %d Char = %c \n", x.num, x.car); 12
Uniones (3) Produciéndose como salida: Int = 4427 ; Char = K Int = 114d ; Char = M Recordemos que el tipo int ocupa dos bytes, y el char un byte; por lo tanto: int = B0 B1 char = B0 13
Uniones (4) Primeramente tenemos: B1 = 0 0 0 1 0 0 0 1 B0 = 0 1 0 0 1 0 1 1 = 75 Y a continuación: B1 = 0 0 0 1 0 0 0 1 B0 = 0 1 0 0 1 1 0 1 = 77 14
Uniones (5) Podemos usar las uniones con los campos de bits para poder modificar una variable, tanto a nivel de los bytes como a nivel de los bits. Por ejemplo: union puerto{ unsigned char valor; struct{ unsigned bit_0: 1;... unsigned bit_7: 1; }; }byte; 15
Uniones (6) Hemos declarado una unión, que internamente contiene una estructura anónima, porque no posee nombre. Entonces si queremos escribir un valor en byte, utilizamos la variable de la siguiente forma: byte.valor = 0xFE; Y si queremos acceder a los bits de esa variable, escribiremos: byte.bit_0 = 1; byte.bit_4 = byte.bit_7; 16
Cadena de Caracteres (1) Una cadena de caracteres es un conjunto de caracteres que se almacena en localidades contiguas de memoria. En C se representa como un vector de caracteres, en donde cada elemento del vector representa un carácter de la cadena. Por ejemplo: char nombre[7] = "Pepito"; P e p i t o \0 Toda cadena termina con el carácter nulo ( \0 ). 17
Cadena de Caracteres (2) Leer una cadena del teclado: gets(nombre); scanf("%s", nombre); Mostrar una cadena en pantalla: puts(nombre); printf("nombre: %s \n", nombre); Asignar un valor a una cadena: strcpy(nombre, "Pepito"); 18
Cadena de Caracteres (3) Arreglo de cadenas: #define LON_MAX 80 #define CAN_MAX 100 main(){ typedef char Cadena[LON_MAX]; typedef Cadena VectorCadenas[NRO_ELEMS]; VectorCadenas V; int i; for(i = 0; i < NRO_ELEMS; i++){ printf("cadena Nro %i", i); scanf("%s",v[i]);} } 19
Punteros (1) Una variable del tipo puntero es aquella que almacena una dirección de memoria en donde se almacena un valor de un determinado tipo. Los punteros se definen mediante la siguiente sintaxis: <tipo> * <puntero>; Por ejemplo, int *p declara que p es una variable que almacena una dirección de memoria, en donde se puede almacenar un entero. Por lo tanto se dice que p "apunta" a una variable de tipo entero. 20
Punteros (2) Los operadores asociados a punteros: &: Devuelve la dirección que una variable tiene en memoria (operador de dirección). Por ejemplo: & variable; *: Devuelve el contenido que tiene una dirección de memoria (operador de indirección). Por ejemplo: * puntero; 21
Punteros (3) La aritmética de punteros consiste básicamente en tratar a los punteros como variables numéricas (que contienen direcciones), é incrementar ó disminuir estas variables para acceder a las direcciones de memoria contiguas a la dirección original. Por ejemplo, si tenemos la declaración del siguiente puntero a una variable entera: char *p; Entonces la siguiente sentencia hace que el puntero p apunte a la dirección de memoria contigua (posterior) : p = p + 1; Cuando sumamos 1 a un puntero, el incremento se adecúa al tamaño en memoria de la variable apuntada. 22
Relación entre Arrays y Punteros (1) Existe una estrecha relación entre punteros y arreglos, tanto que pueden ser usados en forma casi indistinta. Esto es, una variable de tipo arreglo puede considerarse como un puntero al tipo del arreglo. Por ejemplo, sean las siguientes declaraciones: int V[N],*p; Entonces podemos hacer las siguientes asignaciones: p = V ó p = &V[0] *(p + i) = valor ó V[i] = valor 23
Relación entre Arrays y Punteros (2) Por ejemplo, sea el siguiente ciclo: for (i = 0; i < N; i++) s = s + V[i]; El mismo podría ser escrito también como: Que es equivalente a: for (i = 0; i < N; i++) s = s + *(V + i); for (p = V; p < &V[N]; p++) s = s + *p; 24
Relación entre Cadenas y Punteros (1) Así también, como una cadena de caracteres es un arreglo, podemos definir un puntero a una cadena de caracteres de la forma: char *cadena; Por ejemplo, podemos escribir: char *nombre = "Pepito", *p; p = nombre; while (*p!= '\0') p++; printf("largo: %d", p - nombre); 25
Relación entre Cadenas y Punteros (2) En el ejemplo, asignamos a la variable nombre la dirección de comienzo de la cadena de caracteres (Pepito). El compilador añade al final de ella el carácter nulo, para poder detectar el final de la misma. Luego copiamos la dirección de inicio de la cadena en el puntero p, y al incrementarlo en uno, vamos tomando carácter por carácter, hasta llegar al carácter nulo. Siendo la diferencia p nombre la longitud de la cadena. 26
Relación entre Cadenas y Punteros (2) Puesto que la sentencia while sólo comprueba si la expresión: *p!= '\0' es distinta de cero, en lugar de hacer la comparación explícita se puede hacer ímplicitamente de la siguiente manera: while (*p) p++; Y como ahora la expresión está formada únicamente por *p, podemos por lo tanto escribir finalmente: while (*p++); printf("largo: %d", p nombre - 1); 27
Declaración de Nuevos Tipos de Datos Podemos dar un nombre nuevo a cualquier tipo de datos mediante typedef. La sintaxis es: typedef declaración; En donde declaración tiene la forma de una declaración de variable, sólo que estamos definiendo un nuevo tipo de datos. Por ejemplo: typedef enum {Lu, Ma, Mi, Ju, Vi} dias; Y luego podemos declarar variables de este tipo: dias x, y, z; 28
Conversión de Tipos La conversión de tipos se denomina "moldeo" (casting) y se realiza anteponiendo a la expresión a moldear, el nombre del tipo requerido entre paréntesis: (<tipo>) <expresión> El conjunto de paréntesis y tipo recibe el nombre de "operador de moldeo" (cast). Por ejemplo, si n es un int, entonces: (double)n forzará al valor de n para que la expresión tenga el tipo double, permaneciendo inalterable el valor que tiene en la memoria. 29