Introducción La computadora fue diseñada como una herramienta

Anuncio
Nombre
de
la
asignatura
Créditos académicos
de la asignatura
Número y Nombre
del módulo
Autor del contenido
ESTRUCTURAS DE DATOS
3
Módulo 2: ESTRUCTURAS
Carlos Alberto Torres Sastoque
Cel:304 6407052
Introducción
La computadora fue diseñada como una herramienta mediante la cual podemos
realizar operaciones de cálculo complejas en un mínimo lapso de tiempo, también
para almacenar y acceder a grandes cantidades de información. La información
útil para nosotros nunca se encuentra de forma aislada y desorganizada, por el
contrario siempre la encontraremos de forma estructurada y organizada.
Imaginemos un diccionario, o una enciclopedia con la información desordenada o
sin algún tipo de regla determinada para su organización. De este punto parte la
necesidad de organizar la información de forma estructurada y que siga ciertas
reglas que nos facilitan el acceso y el manejo de los datos.
El segundo módulo de este curso está orientado a ofrecerle a los estudiosos
diferentes conceptos relacionados con el manejo y la administración de las
estructuras de programación, así como también el uso de datos de memorias y
variables denominadas punteros.
En la primera parte del módulo se aborda el tema de estructuras desde una visión
amplia en su definición; se acerca a los estudiosos a la iniciación de la declaración
de estructuras, teniendo en cuenta sus tamaños y formas de acceso; para
finalmente puntualizar en la recuperación de información de la estructura y su uso
en la programación.
A continuación se hace un breve recorrido por el tipo de arreglos de estructuras
para luego conocer los parámetros y requisitos necesarios en procesos de
uniones, enumeraciones y la función ‘typedef’. La parte final del módulo se enfoca
en el estudio de los apuntadores o punteros, desde su declaración hasta sus
funciones básicas como variables útiles para la manipulación de las estructuras de
datos.
Estructura temática
5.1 Definición de Estructuras
5.2 Declaración de una estructura
5.3 Declaración variable en Estructuras
5.4 Inicialización de una declaración de Estructuras
5.5 Tamaño de un Estructura
5.6 Acceso a una Estructura
5.7 Lectura de información de una Estructura
5.8 Recuperación de información de una Estructura
6.
Uso de las estructuras en la programación
6.1 Estructuras añadidas
6.2 Arreglos de Estructuras
6.3 Arreglos con miembros
6.4 Uniones
6.5 Enumeraciones
6.6 Typedef
7.
Apuntadores
7.1 Declaración de Punteros
7.2 Inicialización de Punteros
7.3 Indirección de Punteros
7.4 Punteros a Punteros
7.5 Punteros a Arrays
7.6 Arrays de Punteros
7.7 Punteros de cadenas
7.8 Aritmética de Punteros
7.9 Punteros a funciones
5. Estructuras
5.1 Definición de estructuras
Una estructura permite almacenar diferentes tipos de datos con el único fin de
facilitar su manipulación y su acceso. La estructura también agrupa una o más
variables, ya sea de un mismo tipo o de diferentes tipos de datos.
Una estructura de datos, es una colección de datos organizados (lógicamente) de
un modo particular con el objetivo de facilitar su manipulación. Cada estructura
ofrece ventajas y desventajas en relación a la simplicidad y eficiencia para la
realización de cada operación. De esta forma, la elección de la estructura de datos
apropiada para cada problema depende de factores como la frecuencia y el orden
en que se realiza cada operación sobre los datos.
Una estructura de dato simple puede ser de: caracteres, números enteros o
decimales, etc, mientras que una estructura de dato compuesto puede ser de:
vectores, estructuras, listas, etc. Los elementos o componentes de una estructura
se llaman miembros.
Una estructura es una colección de uno o más tipos de elementos llamados
miembros, cada uno de los cuales puede ser un tipo de dato diferente.
Se llamara a un dato de tipo estructurado a una entidad, con un solo identificador,
constituida por datos de otro tipo, de acuerdo con las reglas que definen cada una
de las estructuras de datos.
Ejemplo:
 Una cadena formada por una sucesión de caracteres.
 Una matriz por datos simples organizados en forma de filas y columnas.
 Un archivo, está constituido por registros, estos por campos, que se
componen a su vez, de datos de tipo simple.
Niklaus Wirth, inventor
siguiente ecuación:
del lenguaje de programación
PASCAL, planteo la
Algoritmos + Estructura de Datos = Programas
La anterior ecuación indica que un programa se obtiene tras el diseño correcto de
un algoritmo y la elección adecuada de la estructura de datos.
Una estructura puede ser compuesta por cualquier cantidad de miembros, donde
cada uno de ellos tendrá un único nombre, al que se denomina nombre del
miembro.
Supongamos que deseamos almacenar los datos de un almacén, los datos a
almacenar serán los siguientes:





Nombre
Proveedor
Cantidad
Precio
Fecha de la compra
La estructura de datos almacén contendrá cinco miembros, una vez decididos los
miembros definiremos los tipos de datos a utilizar para cada miembro, a
continuación se muestra en representación gráfica:
Nombre de miembro
Tipo de dato
Nombre
Arreglo de caracteres de tamaño 20
Proveedor
Arreglo de caracteres de tamaño 25
Cantidad
Entero
Precio
Decimal
Fecha de la compra
Arreglo de caracteres de tamaño 8
En la siguiente tabla podemos observar que cada miembro de la estructura de
datos almacén es un tipo de dato diferente:
Nombre de miembro
Tipo de dato
Nombre
Lata de atún
Proveedor
Atunes y Mariscos
Cantidad
1000
Precio
1520.23
Fecha de la compra
12-05-2013
Las estructuras de datos pueden ser de dos tipos: estructuras de datos estáticas y
estructuras de datos dinámicas:
 Estáticas: Son aquellas en las que se asigna una cantidad fija de memoria
cuando se declara la estructura. Es decir, su tamaño en memoria no
pueden aumentar ni disminuir mientras que el programa se encuentra en
ejecución.
 Dinámicas: Son aquellas estructuras cuya operación en memoria puede
aumentar y disminuir en su tiempo de ejecución.
5.2 Declaración de una estructura
La estructura es un tipo de dato definido por el usuario, la cual se deberá declarar
antes de que se pueda utilizar. La sintaxis correcta para declarar una estructura es
la siguiente:
struct<nombre de la estructura>
{
<tipo de dato miembro1><nombre del miembro1>
<tipo de dato miembro2><nombre del miembro2>
<tipo de dato miembro3><nombre del miembro3>
……………….
<tipo de dato miembron><nombre del miembron>
};
struct: es una palabra reservada de C que nos indicara que los
elementos que vienen agrupados a continuación entre llaves
componen una estructura de datos.
nombre de la estructura: es el nombre de la estructura.
tipo de dato miembro: es el tipo de dato que corresponde a cada
miembro.
nombre del miembro:
son los campos que conformaran la
estructura de datos, deben estar precedidos por el tipo de dato al que
pertenecen.
Cabe recordar que la estructura define un tipo de dato, y no una variable, esto
quiere decir que no se reserva un espacio en memoria cuando el compilador este
analizando la estructura. Para que se puedan almacenar y manipular los datos se
deberán declarar las variables del tipo definido por la estructura.
Para nuestra estructura de datos almacén la declaración quedaría de la siguiente
manera:
struct almacen
{
char nombre[20];
char proveedor[25];
int cantidad;
float precio;
charfecha_compra[8];
};
Ejemplo:
struct tarjetas
{
char nombre[20];
int identificacion;
int codigo;
float valor_aprobado;
};
En el anterior ejemplo declaramos la estructura tarjetas en la que almacenaremos
los siguientes datos:
 Nombre: Nombre de la persona a quien pertenece la tarjeta.
 identificación: número de identificación de la persona propietaria de
la tarjeta.
 Código: un código compuesto por números que identificara la tarjeta.
 Valor_aprobado: Valor o cupo aprobado en la tarjeta.
Constantes: Una constante es un dato cuyo valor no puede cambiar durante la
ejecución del programa, recibe un valor en el momento de la compilación y este
permanece inalterado durante todo el programa.
Las constantes se declaran con la palabra reservada const. Después de declarar
una constante ya se podrá utilizar en el cuerpo principal del programa. Tienen
varios usos:
 Ser miembro de una expresión.
 En una comparación.
 Asignar su valor a una variable.
Ejemplo:
const
Min = 0;
Max = 100;
Sep = 10;
var
i = integer;
begin
i = Min;
while i < Max do begin
wirteln(i);
i = i + sep
end
end
En el ejemplo anterior tenemos que se declararon tres constantes:
 Min
 Max
 Sep
En la primera línea del cuerpo del programa se asigna una constante a una
variable.
En la segunda, se usa una constante en una comparación.
En la tercera, la constante Sep se usa en una expresión que se asigna a una
variable.
El resultado de ejecutar este programa sería una impresión en pantalla de los
números: 0, 10, 20, 30, 40, 50, 60, 70, 80, y 90.
Las constantes se puedes dividir en tres grupos:
 Constantes literales (sin nombre).
 Constantes declaradas (con nombre).
 Constantes expresión.
Constantes Literales:
Son valores de cualquier tipo que se utilizan directamente, no se declaran ya que
no tienen nombre.
Ejemplo:
valor_esfera = 4/3 * 3.1416 * radio * radio * radio;
En el ejemplo tenemos un par de constantes literales:
 El 3, y el 4.
 3.1416
Constantes Declaradas:
También son conocidas como constantes con nombre, son las que se declaran en
la sección const asignándoles un valor directamente.
Ejemplo:
const
pi = 3.141592; (* valor real *)
Min = 0 (* entero *)
Max = 99 (* entero *)
Saludo = ‘Hola Mundo’; (* cadena carácter *)
Constantes Expresión:
Están también son declaradas en la sección const, la diferencia es que a estas no
se les asigna un valor directamente, sino que se les asigna una expresión.
Esta expresión se evalúa en tiempo de compilación y el resultado se le asigna a la
constante.
Ejemplo:
const
Min = 0;
Max = 100;
Rango = 10;
N = (Max – Min) div Rango;
Mitad = (Max - Min) div 2;
5.3 Declaración de variables en estructuras
Por más pequeño que sea un programa, casi siempre se hará uso de variables.
Por ejemplo, si se utiliza algún bucle en el programa, se tendrá mínimo una
variable para el avance de este.
Cuando hablamos de bucle nos estamos refiriendo a las estructuras de control
repetitivo.
Para acceder a una estructura lo hacemos por medio de una o varias variables, las
cuales deberán ser definidas después de la declaración de la estructura. De la
misma forma que sucede en otros lenguajes de programación, en C debemos
considerar dos conceptos similares: declaración y definición.
 Declaración: La declaración especifica simplemente el nombre y el formato
de la estructura de dato, pero no reversa un espacio en memoria.
 Definición: Cada definición de variable creara un espacio en memoria en
donde almacenara los datos de acuerdo al formato estructurado dado en la
declaración.
La forma de declarar variables es muy sencilla, Esta sección debe comenzar con
la
palabra
reservada
var,
seguida
de
una
lista
de
parejas
lista_de_variables=tipo_al_que_pertenecen. Cada par debe ir seguido por un
punto y coma. La lista_de_variables es uno o más nombres de variables
separados por comas:
La declaración de variables en una estructura se podrá realizar de dos maneras:
Primera: Las variables que serán utilizadas en el programa se podrán listar
inmediatamente después de la llave de cierre de la declaración de la estructura.
struct almacen
{
char nombre[20];
char proveedor[25];
int cantidad;
float precio;
charfecha_compra[8];
} producto1, producto2, producto 3;
Segunda: Las variables se podrán listar seguidas del nombre de la estructura.
struct almacen producto1, producto2, producto 3;
{
char nombre[20];
char proveedor[25];
int cantidad;
float precio;
charfecha_compra[8];
};
Ejemplo: Supongamos que un programa procesa gestiona los siguientes datos de
un automóvil: concesionario, modelo, color, precio.
 La estructura info_automovil quedaría de la siguiente manera:
struc tinfo_automovil
{
charconcesionario[20];
intmodelo;
char color[10];
float precio;
};
 La definición de la estructura info_automovil quedaría de la siguiente
manera:
Primera forma:
struc tinfo_automovil
{
char concesionario[20];
int modelo;
char color[10];
float precio;
} automovil1, automovil2, automovil3, automovil4;
Segunda forma:
struc tinfo_automovil automovil1, automovil2, automovil3, automovil4;
{
char concesionario[20];
int modelo;
char color[10];
float precio;
};
5.4 Inicialización de una declaración de estructuras
Las estructuras, al igual que las matrices, almacenan sus miembros de forma
contigua, razón por la cual, se les pueden aplicar punteros y una cierta aritmética.
Por la misma razón, se pueden crear matrices de estructuras e incluso estructuras
de matrices (sus miembros son matrices). Estas últimas no se diferencian gran
cosa de las matrices de matrices (a no ser en la notación de acceso a sus
miembros).
También se puede calcular su tamaño en bytes con la expresión sizeof, aunque a
este respecto debe tenerse en cuenta algunas posibles discrepancias respecto a
los valores "teóricos", debidas a las alineaciones internas realizadas por el
compilador, que se comentan
Para inicializar una estructura se puede realizar de dos formas:
 Se podrá realizar dentro de la sección de código de su programa.
 Siendo parte de la definición de la estructura, se deberá especificar
los valores iníciales, entre llaves, después de la definición de variable
estructura.
La sintaxis correcta es:
struct<tipo><nombre variable estructura> =
{
valor miembro,
valor miembro,
valor miembro,
……...
valor miembro
};
Para nuestro ejemplo de automóviles se inicializara durante la declaración:
struct info_automovil
{
char concesionario[20];
int modelo;
char color[10];
float precio;
} automovil1 = {“Renault”,2013,”Azul”,30000000};
Otra forma puede ser:
struct info_automovil
{
char concesionario[20];
int modelo;
char color[10];
float precio;
} automovil2 {
“Renault”,
2013,
”Azul”,
30000000
};
5.5Tamaño de una estructura
La forma más fácil de almacenar el contenido de una variable en memoria en
tiempo de ejecución es en memoria estática o permanente a lo largo de toda la
ejecución del programa. No todas las variables pueden ser almacenadas
estáticamente. Para que un variable pueda ser almacenado en memoria estática
su tamaño (número de bytes necesarios para su almacenamiento) debe ser
conocido en tiempo de compilación, como consecuencia de esta condición no
podrán almacenarse en memoria estática:
 Los objetos correspondientes a procedimientos o funciones
recursivas, ya que en tiempo de compilación no se sabe el número
de variables que serán necesarias.
 Las estructuras dinámicas de datos tales como listas, árboles, etc. ya
que el número de elementos que las forman no es conocido hasta
que el programa se ejecuta.
Las técnicas de asignación de memoria estática son sencillas.
A partir de una posición señalada por un puntero de referencia se aloja la variable
X, y se avanza el puntero tantos bytes como sean necesarios para almacenar la
variable X. La asignación de memoria puede hacerse en tiempo de compilación y
las variables están vigentes desde que comienza la ejecución del programa hasta
que termina. En los lenguajes que permiten la existencia de subprogramas, y
siempre que todas las variables de estos subprogramas puedan almacenarse
estáticamente se aloja en la memoria estática un registro de activación
correspondiente a cada uno de los subprogramas.
Estos registros de activación contendrán las variables locales, parámetros
formales y valor devuelto por la función.
Cuando hablamos del tamaño de una estructura nos estamos refiriendo al espacio
que ocupa en memoria una estructura de datos, para determinar el tamaño
utilizamos el operador sizeof el cual se aplicara sobre una variable o sobre un tipo
de datos.
A continuación veremos un ejemplo de la forma en que se utiliza el operador
sizeof:
#include<stduio.h>
/* declarar una estructura niña */
struc niña
{
char nombre[20];
int edad;
float altura;
float peso;
};
Voidmain()
{
struc niña mar;
printf(“Sizeof (niña): %d \n”,|sizeof(mar));
}
Cuando ejecutemos este programa el resultado de salida será el siguiente:
Sizeof (niña): 30
El 40 representa el tamaño en bytes que ocupa en memoria la estructura.
Niña
Miembros dato
Tamaño (bytes)
char(1)
20
Edad
int(2)
2
Altura
float(4)
4
Peso
Float(4)
4
nombre[20]
Total
Memoria Dinámica
30
Supongamos que nuestro programa debe manipular estructuras de datos de
longitud desconocida. Un ejemplo simple podría ser el de un programa que lee las
líneas de un archivo y las ordena. Por tanto, deberemos leer un número
indeterminado de líneas, y tras leer la última, ordenarlas. Una manera de manejar
ese número indeterminado, sería declarar una constante MAX_LINEAS, darle un
valor grande, y declarar un array de tamaño MAX_LINEAS. Esto, obviamente, es
muy ineficiente (y feo). Nuestro programa no sólo quedaría limitado por ese valor
máximo, sino que además gastaría esa enorme cantidad de memoria para
procesar hasta el más pequeño de los ficheros.
La solución consiste en utilizar memoria dinámica. La memoria dinámica es un
espacio de almacenamiento que se solicita en tiempo de ejecución. De esa
manera, a medida que el proceso va necesitando espacio para más líneas, va
solicitando más memoria al sistema operativo para guardarlas. El medio para
manejar la memoria que otorga el sistema operativo, es el puntero, puesto que no
podemos saber en tiempo de compilación dónde nos dará huecos el sistema
operativo (en la memoria de nuestro PC).
5.6 Acceso a estructuras
Debido a que los miembros de una estructura de datos se procesan generalmente
de modo individual, se deberá poder acceder a cada uno de los miembros
individuales de una variable estructura. Cuando tenemos almacenada información
dentro de una estructura podremos acceder a los miembros de ella de dos
maneras:
 Utilizando el operador punto (.).
 Utilizando el operador puntero ().
Acceso a una estructura de datos mediante el operador punto:
La asignación de datos a los miembros de una variable estructura se hace
mediante el operador punto.
Su sintaxis es:
<nombre de la variable estructura> . <nombre miembro> = datos;
Ejemplos:
cancion1.artista = “Andres Cepeda”;
cancion1.duracion = 350;
cancion2.titulo = “celos”;
cancion2.fecha = {8,12,1983};
cancion2.fecha.anho = 1990;
El operador punto nos brinda el camino directo al miembro correspondiente.
Debemos tener en cuenta que los datos que se almacenan en un miembro dato
deberán ser del mismo tipo declarado para ese miembro.
A continuación veremos un ejemplo en el que se lee del teclado los datos de una
variable estructura ciclista:
struct ciclista cl;
printf (“nombre: ”);
gets(cl.nombre);
printf(“edad: “);
scanf(“%d”,&cl.edad);
printf(“sexo: “);
scanf(“%c”,&cl.sexo);
printf(“club: “);
gets(cl.club);
if (cl.edad<= 18)
cl.categoria = “Juvenil”;
elseif(cl.edad<= 40)
cl.categoria = “Senior”;
else
cl.categoria = “Veterano”;
Acceso a una estructura de datos mediante el operador flecha o puntero:
El operador puntero sirve para acceder a los datos de la estructura a partir de un
puntero, para poder utilizar este operador se deberá primero definir una variable
puntero que apunte a la estructura.
Su sintaxis es:
<puntero estructura> -><nombre miembro> = datos;
Ejemplos:
struc trabajador;
{
char nombre[30];
intnum_trabajador;
intanyo_de_ingreso;
float sueldo;
};
Ahora vamos a definir un puntero ptr_trab a la estructura trabajador.
struct trabajador *ptr_trab;
struct trabajador mejor_pago;
Una vez la estructura tenga su espacio asignado en memoria, a los miembros de
la estructura trabajador se les podrá asignar datos de la siguiente forma:
ptr_trab = &mejor_pago; /*
mejor_pago */
ptr_trab tiene la dirección (apunta a)
strcpy(ptr_trab -> Nombre , “Juan Perez”);
ptr_trab ->Num_trabajador = 4876;
ptr_trab ->mejor_pago = 5.000.000;
En el ejemplo anterior debimos previamente crear un espacio de almacenamiento
en memoria; por ejemplo, con la función malloc().
5.7 Lectura de información de una estructura
Con el operador punto o flecha (puntero) podemos acceder a los miembros de la
estructura, de esta forma introducimos la información en la estructura de datos,
esta información se puede obtener desde el teclado o ya sea desde un archivo, o
asignar valores calculados.
Ejemplo:
struct complejo
{
float pr;
float pi;
float modulo;
};
struct complejo z;
printf(“\nParte real: “)
scanf(“%f”,&z.pr);
printf(“\nParte imaginaria: “);
scanf(“%f”,&z.pi);
/* cálculo del modulo */
z.modulo = sqrt(z.pr*z.pr + z.pi*z.pi);
En el anterior ejemplo, tenemos la variable z de tipo estructura complejo, se lee
parte real, parte imaginaria y se calcula el modulo.
5.8 Recuperación de información de una estructura
Para recuperar la información de una estructura podemos utilizar




Operador de asignación.
Sentencia de salida (printf(), puts(),…..).
Operador punto.
Operador flecha (puntero).
La sintaxis de estos operadores es la siguiente:

<nombre variable> =
<nombre variable estructura>.<nombre miembro>;

<nombre variable> =
<puntero de estructura> -><nombre miembro>;

Para salida:
o printf(“ “,<nombre variable estructura>.<nombre miembro>);
o printf(“ “,<nombre variable estructura> -><nombre miembro>);
Ejemplos:
Algunos ejemplos de las estructura complejo:
floatx,y;
struct complejo z;
struct complejo *pz;
pz = &z;
x = z.pr;
y = z.pi;
….
printf(“\número complejo (%.1f,%.1f), modulo: %.2f”, pz->pr,pz->pi,pz
->modulo);
6. Uso de estructuras en programación
6.1 Estructuras añadidas
Una estructura puede anidar otras estructuras, previamente definidas, como se
demuestra en el siguiente ejemplo en el que las estructuras se definen a nivel
global.
Las estructuras anidadas ahorran tiempo en la escritura de programas que utilizan
estructuras similares, se definen los miembros comunes solo una vez en su propia
estructura y a continuación utilizar esa estructura como un miembro de otra
estructura.
Para mencionar un miembro de una estructura se indican, ordenadamente, el
nombre de la estructura principal, el nombre de la estructura anidada y el nombre
del miembro de la estructura, todos ellos separados por el operador punto.
struct autor
/*Declara globalmente autor */
{
char nombre [30];
char apellido[30];
};
struct tema
/*Declara globalmente tema */
{
char modulo[5];
chararea[8];
};
/*Estructura “Libros” que anida las estructuras “autor” y “tema”.
La declaración también es global.*/
structlibros
{
charnom_lib[40];
struct autoraut;
struct tema tem;
};
void main()
{
struct libros li;
/*Declara li del tipo libros*/
clrscr();
/*Borra la pantalla*/
puts(“Titulo del libro”);
/*Imprime en pantalla*/
gets(li.nom_lib);
/*Lee datos del teclado*/
puts(“Apellidos del autor”);
gets(li.aut.ape);
puts(“Nombre del autor”);
gets(li.aut.nomb);
puts(“Modulo: “);
gets(li.tem.modulo);
puts(“Area de conocimiento”);
gets(li.tem.area);
}
Gráficamente el anidamiento de estructuras se vera de la siguiente manera:
nom_lib
nomb
ape
aut
Revisemos la definición de dos estructuras:
struct trabajador
{
Char nombre_trabajador[40];
char ciudad[25];
char localidad[25];
longint código_postal;
double salario;
};
area
tem
li
char dirección[20];
modulo
struct clientes
{
char nombre_cliente[40];
char dirección[20];
char ciudad[25];
char localidad[25];
longint código_postal;
double saldo;
};
Estas dos estructuras contienen varios datos comunes, de esta forma podría
disponerse de una estructura, info_direccion, que contenga estos miembros
comunes.
struct info_direccion
{
char dirección[20];
char ciudad[25];
char localidad[25];
longint código_postal;
};
Esta estructura se podrá anidar a las demás estructuras.
struct trabajador
{
char nombre_trabajador[40];
struct info_direccion direccion_trabajador;
double salario;
};
struct clientes
{
char nombre_cliente[40];
struc tinfo_direccion direccion_cliente;
double saldo;
};
EL acceso a los miembros dato de estructuras anidadas requiere el uso de
múltiples operadores punto.
Las estructuras se pueden anidar a cualquier grado, y se podrán inicializar
estructuras anidadas en la definición.
6.2 Arreglos de estructuras
Así como las variables las estructuras también pueden formar parte de un arreglo,
tendremos que definir primero la estructura y luego declarar una variable arreglo
de dicho tipo.
Para crear arreglos de estructuras se puede hacer de la misma forma en que se
hace un arreglo de cualquier tipo, son muy útiles para almacenar gran cantidad de
información que se adapte a un formato de estructura (inventarios, empleados).
La sintaxis general es:
struct Nombre_estructura
{
Tipo_Variable1 Nombre_Variable1;
……
Tipo_VariableN Nombre_VariableN;
};
struct Nombre_EstructuraVariable_Arreglo[Numero_Elementos];
Se utilizara el operador punto para citar elementos individuales de la variable
estructura y elementos individuales del arreglo utilizando el subíndice
correspondiente.
Los arreglos de estructuras permiten almacenar en un mismo lugar valores de
diferentes tipos agrupados como estructuras, mientras que los arreglos
convencionales agrupan valores de un mismo tipo.
En algunas ocasiones se pueden utilizar los arreglos de estructura como método
para almacenar datos en un archivo de disco, una vez allí se podrán calcular sus
datos de disco y posteriormente almacenarlos en memoria. Estos arreglos de
estructura se podrán utilizar también como medio para guardar datos que se leen
del disco.
La declaración de arreglos de estructuras se podrá hacer de forma similar a
cualquier arreglo:
Ejemplo: arreglo info_empleados
struc tinfo_empleados empleados[80];
Se define un arreglo empleados de 80, si queremos acceder a los miembros de
cada uno de los elementos de la estructura se utilizara una notación de arreglo, y
para la inicialización del primer elemento del arreglo estructura lo haremos e la
siguiente manera:
strcpy(empleados[0] .nombre, “Juan”);
strcpy(empleados[0] .apellido, “Perez”);
strcpy(empleados[0] .cargo, “asesor contable”);
empleados[0] .edad = 25;
Vamos a declarar una estructura que representa un número entero, un arreglo de
números enteros es inicializado con valores al azar.
struct entero
{
int N,
int D;
};
struct entero rs[6] = {1, 3, 5, 10, 24, 32};
6.3 Arreglos como miembros
Un arreglo dentro de una estructura pueden ser los mismos miembros que la
componen. Debemos tener mucho cuidado al acceder a los elementos
individuales del arreglo.
Veamos un ejemplo de cómo un miembro de una estructura puede ser un arreglo.
struct nomina
{
char nombre[40];
int dependientes;
charcentro_de_costos[15];
floathoras_diarias[15];
/* arreglo de tipo float */
float sueldo;
}
empleado[200];
/* un arreglo de 200 empleados */
6.4 Uniones
Conforme los programas se vuelven más complejos, en ocasiones necesitaremos
diferentes formas de ver una parte de la información y en otras ocasiones tenemos
la necesidad de trabajar con dos o más valores, pero en un momento dado
podremos utilizar solamente uno. Para estos casos se vuelve muy útil el uso de las
uniones para guardar los datos.
Las uniones agrupan una serie de variables, pero su forma de almacenamiento es
diferente y su resultado también lo es. Una estructura permite almacenar variables
relacionadas juntas y almacenadas en posiciones contiguas en memoria. Las
uniones se declaran con la palabra reservada unión, almacenan también
miembros múltiples en un paquete, la diferencia radica en la posición en que se
guardan, es decir, todos los miembros se solapan entre sí en una misma posición
caso contrario en situar los miembros unos detrás de otro.
Los miembros de una unión pueden ser datos de
cualquier tipo.
El tamaño ocupado por las uniones será analizado de la siguiente manera: el
tamaño de la unión será el mayor tamaño de variable.
La sintaxis de la unión es de la misma manera de una estructura:
union nombre {
tipo1 miembro1;
tipo2 miembro2;
tipo3 miembro3;
….
};
6.5 Enumeraciones:
Una enumeración es el conjunto de constantes enteras representadas por
identificadores, estas constantes de enumeración son constantes simbólicas cuyos
valores pueden ser definidos automáticamente. Una enumeración es una
colección de uno o más tipos de datos llamados miembros, cada uno de los cuales
puede ser un tipo de dato diferente. Una estructura puede contener cualquier
número de miembros, cada uno de los cuales tienen un miembro único, llamado
nombre del miembro.
Las estructuras ayudan a organizar datos complicados, particularmente en largos
programas, porque permiten que un grupo de variables relacionadas como una
unidad en vez de entidades separadas.
En la declaración de un tipo enum se escribe una lista de identificadores que
intermitentemente se asocian con las constantes enteras 0,1,2, etc.
Se utilizara la palabra reservada enum, para realizar su declaración, su sintaxis es:

Forma 1
enum
{
enumerador1, enumerador2,……,enumerador
};

Forma 2
enum nombre
{
enumerador1, enumerador2,…..,enumerador
};
Cuando estamos declarando la enumeración de tipo enum pueden asociarse a los
identificadores valores constantes en vez de la asociación por defecto se hace (0,
1, 2, etc.) Para esta forma utilizaremos:
enum nombre
{
enumerador1, = expresion1_constante,
enumerador2, = expresion2_constante,
…
enumerador, = expresión_constante,
};
Ejemplo 1:
enum switch
{
On,
Off
};
enum Boolean
{
falso,
verdadero
};
Ejemplo 2:
enum autos
{
ford,
chevy,
mazda,
renault,
nissan
};
Ejemplo 3:
enum sexo
{
femenino,
masculino
};
6.6 Typedef
Muchas ocasiones nos será útil definir nombres para tipos de datos, que nos
hagan más fácil declarar variables y parámetros, o que nos faciliten la portabilidad
de nuestros programas.
Para esto disponemos de la palabra reservada typedef.
Sintaxis:
typedef<tipo><identificador>;
Ejemplos:
En la siguiente línea definimos un nuevo tipo como una estructura llamada
stpunto.
typedefstructstpuntotipopunto;
Definimos un nuevo tipo Punto3D, partiendo de una estructura.
typedef struct
{
int x;
int y;
int z;
}Punto3D;
Una de las ventajas de typedef es que nos permite utilizar y dar nombres de tipos
de datos más acordes con lo que representan en una determinada aplicación.
7. Apuntadores (Punteros)
Los apuntadores son una herramienta útil e importante en los lenguajes de
programación ya que nos permite hacer los programas más eficientes y flexibles.
Creo que todos sabemos lo que es un puntero, fuera del ámbito de la
programación, los usamos para señalar cosas sobre las que queremos llamar la
atención, como marcar puntos en un mapa o detalles en una presentación en
pantalla. Con frecuencia usamos el dedo índice para señalar direcciones o lugares
sobre los que estamos hablando o explicando algo. Cuando un dedo no es
suficiente, podemos usar punteros. Antiguamente esos punteros eran una vara de
madera, pero actualmente se usan punteros laser, aunque la idea es la misma.
Un puntero también es el símbolo que representa la posición del ratón en una
pantalla gráfica. Estos punteros también se usan para señalar objetos: enlaces,
opciones de menú, botones, etc. Un puntero sirve, pues, para apuntar a los
objetos a los que nos estamos refiriendo.
Cuando declaramos una variable, el compilador reserva un espacio en memoria
para ella y asocia el nombre de esta a la dirección de memoria desde donde
comienzan los datos de esa variable, las direcciones de memoria se suelen
describir como números hexadecimales.
Una variable puntero o como normalmente se le conoce puntero, es una variable
que contiene direcciones de otras variables. Un apuntador señala a la variable
cuyo valor se almacena a partir de la dirección de memoria que contiene el
apuntador. Por ejemplo, si se tiene el apuntador b que apunta a la dirección en
memoria de la variable x, se dice que b apunta a x.
Direcciones en memoria:
En el momento de declarar una variable, se asocian tres atributos fundamentales
con esta:



Ejemplo:
Nombre
Tipo
Dirección en memoria
El siguiente cuadro representa la posición de almacenamiento en memoria de una
variable, en nombre de la variable es z y su dirección en memoria es0x4fffd34, si
conocemos el valor de la variable lo pondremos dentro del cuadro.
0x4fffd34
z
int
Para acceder al valor de una variable lo hacemos por medio de su nombre y la
siguiente sintaxis:
printf (“%d”,z);
Para acceder a la dirección de memoria de la variable z utilizaremos el operador
de dirección &, para nuestro ejemplo será de la siguiente manera:
printf (“%p”,&z);
El operador de dirección “&” se aplica sobre el nombre de la variable para obtener
sus direcciones.
Ejemplo:
Debemos obtener el valor y la dirección de la variable n.
#include <stdio.h>
void main()
{
int n = 100;
printf(“n = %d/n” ,n);
/*Visualiza el valor de n */
printf(“&n = %p/n”, &n);
/*Visualiza la dirección de n */
}
Veamos el resultado de la ejecución del programa:
n = 100
&n = 0x4fffd34, dirección en memoria en hexadecimal.
7.1 Declaración de punteros
De la misma forma que cualquier otra variable, un puntero se deberá declarar
antes de su uso, en la declaración de un puntero se indicara al compilador el tipo
de dato al que apunta el puntero, para ello se hace preceder a su nombre con un
asterisco (*), la sintaxis es de la siguiente manera:
<tipo de dato apuntado> * <identificador de puntero>
Ejemplos de la sintaxis de declaración de punteros:
Int *puntero1;
/* Puntero a un tipo de dato entero (int) */
Long *puntero2;
/* Puntero a un tipo de dato entero largo (longint)
Char *puntero3;
/* Puntero a un tipo de dato char */
Float *f;
/* Puntero a un tipo de dato float */
*/
Tener en cuenta que el operador * en una declaración indica que la variable
declarada almacenara una dirección de un tipo de dato especifico.
De esta forma la variable puntero1 almacenara la dirección de un entero, la
variable puntero2 almacenara la dirección de un tipo de dato long, la variable
puntero3 almacenara la dirección de un tipo de dato carácter y la variable puntero4
almacenara la dirección de un tipo de dato float.
Una referencia de variables de
punteros es que siempre llevara el
operador asterisco (*).
Ejemplo
Supongamos la siguiente declaración:
int a = 1, b = 2, *p;
Al ejecutar cada una de las siguientes instrucciones el resultado sería:
p = &a;
/* p apunta a la variable a */
b = *p;
/* ahora b es igual a 1 */
*p = 0;
/* ahora a es igual a 0 */
7.2 Inicialización de punteros
Es preciso inicializar las variables de tipo puntero antes de su uso. La inicialización
proporciona al puntero una dirección a la que apuntar.
Inicializar un puntero a una dirección nula:
char *p = NULL;
 El puntero NULL apunta a la dirección 0.
 El puntero NULL no es una dirección de una variable en memoria.
 El puntero nulo proporciona al programa una manera de saber si un puntero
apunta a una dirección valida.
Para poder usar el puntero nulo NULL, podemos hacer una de estas dos cosas:
 Definirlo en la cabecera de nuestro programa:
# define NULL 0
 Incluir alguno de los archivos de cabecera donde ya se encuentre definido:
# include<stdio.h>
#include<string.h>
Inicializar un puntero a una dirección de memoria valida:
Para asignar una dirección de memoria a un puntero, se utiliza el operador de
dirección &. El operador & aplicado a una variable, devuelve la dirección donde se
almacena dicha variable.
&x = 101
char *p = NULL;
char x = ‘a’;
p = &x;
P
apunt
aa x
La inicialización también se puede hacer en la declaración.
char x = ‘a’;
char *p = &x;
Es importante tener en cuenta que el puntero debe apuntar a una variable del
mismo tipo
char x = ‘a’;
int *p = &x;
Er
ro
r!
Otra forma de representar punteros:
7.3 Indirección de punteros
Una vez definida e inicializada una variable de tipo puntero, disponemos de un
mecanismo para obtener el dato que almacena esa dirección de memoria.
El símbolo * se llama también operador de indirección y sirve para acceder al
valor al que apunta el puntero.
int edad;
int * p_edad;
p_edad = &edad;
*p_edad = 20;
Si se desea imprimir el valor de edad, se puede utilizar la siguiente sentencia:
printf(“%d”,edad);
/* Imprime el valor de edad */
También se puede imprimir el valor de edad indireccionando el puntero de edad:
printf(“%d”,*p_edad);
/* Indirecciónp_edad */
Ejemplo del uso básico de apuntadores:
#include“stdio.h”
#include“conio.h”
void main()
{
intvar = 1, *apunt;
apunt = &var;
/* Inicialización del apuntador
printf(“\n Acceso directo,var = %d”,var);
printf(“\n Acceso indirecto, var = %d”,*apunt);
// Se despliega la dirección de la variable de dos maneras
printf(“\n La dirección de var = %d”,&var);
printf(“\n La dirección de var = %d”,apunt);
getch();
}
7.4 Punteros a punteros
Un puntero podrá apuntar a otra variable puntero, esta funcionalidad es muy
utilizada en programas complejos, para declarar un puntero a un puntero se hace
preceder a la variable con dos asteriscos (**).
Ejemplo:
intvalor_unidad = 200;
int *puntero1 = &valor_unidad;
int **puntero5 = &puntero1;
En el ejemplo anterior puntero 5 es un puntero a un puntero.
Puntero1 y puntero5 son punteros mientras que puntero1 apunta a la variable
valor_unidad de tipo entero, puntero5 contiene la descripción de puntero1.
Al uso de punteros de llama variables con niveles de indirección, ya que no
apuntan directamente a un valor, sino que apuntan a alguien que lo tiene.
Basándonos en esto podemos decir que puntero1 es un puntero con un nivel de
indirección y puntero5 es un puntero con dos niveles de indirección.
7.5 Punteros y arrays
Estos dos conceptos están muy relacionados en los lenguajes de programación,
se pueden direccionar los punteros como si fueran arrays y arrays como si fueran
punteros. La posibilidad de almacenar y acceder a punteros y array, implica que se
pueden almacenar cadena de datos en elementos de arrays. Sin punteros eso no
es posible, ya que no existe el tipo de dato cadena (string) en C. No existen
variables de cadena, únicamente constantes de cadena.
Nombre de arrays como punteros:
Un nombre de un array es simplemente un puntero. Supongamos que se tiene la
siguiente declaración de un array.
int lista[5] = {10, 20, 30, 40, 50, 60;
Si se manda a visualizar lista[0] se verá 10. Pero, ¿Qué sucederá si se manda a
visualizar *lista?
Como un nombre de un array es un puntero, también se verá 10, eso significa que:
Lista + 0
apunta a
lista[0]
Lista + 1
apunta a
lista[1]
Lista + 2
apunta a
lista[2]
Lista + 3
apunta a
lista[3]
Lista + 4
apunta a
lista[4]
En conclusión para visualizar o imprimir, almacenar o calcular un elemento de un
array, se puede utilizar la notación de subíndices o notación de punteros. Esto
debido a que un nombre de un array contiene la dirección del primer elemento del
array, se debe indireccionar el puntero para obtener el valor del elemento.
El nombre de un array es un puntero, contiene la dirección en memoria del
comienzo de la secuencia de elementos que forma el array. Es un puntero
constante ya que no se puede modificar, solo se puede acceder para indexar los
elementos del array. En el ejemplo se pone de manifestó operaciones correctas y
erróneas con nombres de arrays.
float v[10];
float *p;
float x = 100.5;
int j;
/* Se indexa a partir de v */
for (j=0; j<10; j++)
*(v+j) = j*10.0;
p = v + 4;
/* Se asigna la dirección del quinto elemento */
v = &x;
/*error: intento de modificar un puntero constante */
7.6 Arrays de Punteros
Cuando nace la necesidad de reservar muchos punteros a muchos valores
diferentes, se puede declarar un array de punteros. Un array de punteros es un
array que contiene como elementos punteros, cada uno de los cuales apunta a un
tipo de dato especifico.
int *puntero[10];
/* Reserva un array de 10 punteros a enteros */
Cada elemento contiene la dirección que apunta a otros valores de la memoria,
donde cada valor apuntado deberá ser un entero. Se puede asignar a un elemento
de puntero una dirección, tal como las variables puntero no arrays.
puntero[40] = &edad;
/* Apunta a la dirección de edad */
puntero[4] = NULL;
/* No contiene dirección alguna */
Ejemplo de arrays de punteros con tipo de dato carácter:
char *puntos[30];
/* arrays de 30 punteros caracteres */
7.7 Punteros de cadenas
Los punteros se pueden utilizar en lugar de índices de arrays.
Un array de caracteres usando punteros:
char *nombre=”Jaime A. vasquez”;
// Array de 20 caracteres
printf (“%s”,nombre);
Sin embargo al tratarse de una constante de caracters no podemos modificarla
luego de definir sus valores. Como por ejemplo no podemos reemplazar un
carácter, o leer un nuevo valor.
gets(nombre);
// Error en ejecución
Para poder modificar el valor de este puntero, este tendría que apuntar a una
dirección que no sea una constante, como un array.
char nombre[] = ”Jaime A. vasquez”;
// Declaramos un array de caracteres
char *puntero = nombre;
array
// Asignamos al puntero el comienzo del
printf(“%s \nIngrese otro nombre: “,puntero);
//Escribimos en pantalla nombre…
gets(puntero);
// Leemos otro nombre
printf(“%s ,puntero);
// Escribimos el nuevo nombre….
Esta vez nos dimos cuenta que si pudimos remplazar el valor del nombre, pero
aun la cantidad de caracteres está limitada por el array original.
7.8 Aritmética de punteros
La aritmética de punteros se limita a suma, resta, comparación, y asignación. Las
operaciones aritméticas en los punteros de tipo X (punteros-a-tipoX) tienen
automáticamente en cuenta el tamaño real de tipo X. Es decir, el número de bytes
necesario para almacenar un objeto tipo X.
Por ejemplo suponiendo una matriz doble con 100 elementos, si ptr es un puntero
a dicha matriz, la sentencia ptr++; supone incrementar el Rvalue de ptr en 6400
bits, porque el tamaño de la matriz es precisamente 100 x 64 bits.
No confundir el puntero a matriz con un puntero a su primer elemento (que aquí
seria puntero a doble).
La aritmética realizada internamente en los punteros depende del modelo de
memoria en uso y de la presencia de cualquier modificador superpuesto.
Las operaciones que implican dos punteros exigen que sean del mismo tipo o se
realice previamente un modelado apropiado.
Operaciones permitidas:
Sean ptr1 y ptr2 punteros a objetos del mismo tipo, y n un tipo entero o una
enumeración; las operaciones permitidas y los resultados obtenidos con ellas son:
Operación
Resultado
Comentario
ptr1++
elemento
puntero
Desplazamiento
ascendente
de
1
ptr1-elemento
puntero
Desplazamiento
descendente
de
1
ptr1 + n
elementos
puntero
Desplazamiento
ascendente
de
n
ptr1 - n
elementos
puntero
Desplazamiento
descendente
de
n
ptr1 - ptr2
entero
Distancia entre elementos
ptr1 == NULL
booleano
Siempre se puede comprobar la igualdad o
desigualdad con NULL
ptr1 != NULL
booleano
Siempre se puede comprobar la igualdad o
desigualdad con NULL
ptr1 <R> ptr2
booleano
<R> es una expresión relacional
ptr1 = ptr2
puntero
Asignación
ptr1 = void
puntero genérico
Asignación
La comparación de punteros solo tiene sentido entre punteros de la misma matriz;
en estas condiciones los operadores relacionales: ==, !=, <, >, <=, >=, funcionan
correctamente.
Hemos señalado que cuando se realizan operaciones aritméticas con punteros, se
tiene en cuenta el tamaño de los objetos apuntados, de modo que si un puntero es
declarado apuntando a tipoX, añadirle un entero n (al puntero) supone hacerlo
avanzar un numero n de objetos tipoX. Si tipoX tiene un tamaño de 10 bytes,
añadir 5 al puntero tipoX lo hace avanzar 50 bytes en memoria (si se trata de
punteros a elementos de una matriz, supone avanzar n elementos en la matriz).
Del mismo modo, la diferencia entre dos punteros resulta ser el número de objetos
tipoX que separa a dos punteros tipoX.
Ejemplo:
Si puntero1 apunta al tercer elemento de una matriz, y puntero2 apunta al decimo
elemento, el resultado puntero2 - puntero1 es 7(en realidad, la diferencia de dos
punteros solo tiene sentido cuando ambos apuntan a la misma matriz).
Observe que no está definida la suma entre punteros.
Si ptr es un puntero a un elemento de la matriz, desde luego no existe un
elemento tal como: “uno después del último”, pero se permite que ptr tenga dicho
valor. Si ptr1 apunta al último elemento del arreglo, ptr+1 es legal, pero ptr+2 es
indefinido (lo que a efectos prácticos significa que devolverá basura, o un runtime,
volcado de memoria, etc).
Si ptr apunta a uno después del último, ptr1 es legal (puntero al último elemento).
Sin embargo, aplicando el operador de indirección * a un puntero después del
último conduce a una indirección. Informalmente puede pensarse en ptr + n como
avanzar el puntero en (n * sizeof(tipoX)) bytes, siempre que ptr se mantenga en su
rango legal(entre el primer elemento y uno después del último).
La resta de dos punteros a elementos de la misma matriz, ptr1 – ptr2, produce un
entero n del tipo ptrdiff_t definido en <stddef.h> Este número representa la
diferencia entre los subíndices i y j de los dos elementos referenciados (n = i-j).
Para esto es necesario que ptr1 y ptr2 apunten a elementos existentes, o uno
después del último.
7.9 Punteros a funciones
Los punteros a funciones se utilizan como cualquier otro tipo de punteros; pueden
ser pasados como argumentos de otras funciones, usados en arreglos, retornados
por funciones, etc. La única diferencia es que lo que se encuentra al tomar el
contenido de (operador *) estos punteros, no es un dato sino un pedazo de código
ejecutable.
Al igual que en los arreglos estáticos, el nombre de una función que ya existe
puede ser utilizada donde se requiera un puntero a función.
Su utilización permite implementar funciones genéricas que operen sobre otras
funciones (búsqueda de ceros, integración, etc.)
Declaración:
Para declarar un puntero a una función se utiliza la siguiente sintaxis:
tipo_de_retorno (* nombre_puntero) (tipo1 arg1, tipo2 arg2,…);
Los nombres de los argumentos (arg1, arg2, etc) no son necesarios, pero pueden
servir para entender cómo se usa la función.
Ejemplo:
double (* f) (double x;
/* declara el puntero a función f notar que los
paréntesis son necesarios para distinguir de
(double *) f (double) */
f = sin;
/* lo inicializa con la dirección de memoria de una
función double ->double */
x = f(3.14);
/* utiliza el puntero como si fuera una función */
x = (* f)(3.14);
utilizarlo */
/* de referencia explícitamente el puntero al
Las dos últimas sentencias son equivalentes (de la misma manera que cuando
trabajamos con punteros a arreglos, era indistinto decir p[i] o *(p+i)), la primera
forma es más cómoda, pero la segunda muestra explícitamente que p es un
puntero.
Arreglos de punteros a función
Para declarar un arreglo de punteros a función la sintaxis es:
tipo_de_retorno (* nombre_de_puntero[tamaño]) (tipo1 arg1, tipo2 arg2,…);
Por ejemplo:
double (* f[3]) (double);
f[0] = sin;
f[1] = inversa;
f[2] = cos;
x = f[0](3.14);
/* x = sin(3.14) */
x = f[1](3.14);
/* x = inversa(3.14) */
x = f[2](3.14);
/* x = cos(3.14) */
En el ejemplo anterior podríamos haber utilizado un arreglo de punteros, de la
siguiente manera:
#include <stdio.h>
#include <math.h>
doublesuma_cuadrados(double (*)(double), int, int);
doubleinversa (double x) { return 1.0/x;}
int main()
{
double s;
double (*f[2])(double) = {sin, inversa}; /*declaración e inicialización */
for (i=0; i<2; 1++)
{
s = suma_cuadrados(f[0], 1, 100);
printf(“suma de 1 a 100 de f[%d](i)^2 = %1f/n”, i, s);
}
return o;
}
doublesuma_cuadrados ( double (*f)(double x), int i0, int if )
{
double s = 0,x;
inti;
for (i=i0; i<=if; i++)
{
x = i;
s += f(x)*f(x); /* (*f)(x)* (*f)(x) en forma más explícita */
}
return s;
}
Glosario
ESTRUCTURA: Una estructura es una colección de uno o más tipos de elementos
llamados miembros, cada uno de los cuales puede ser un tipo de dato diferente.
DECLARACIÓN: La declaración especifica simplemente el nombre y el formato de
la estructura de dato, pero no reversa un espacio en memoria.
DEFINICIÓN: Cada definición de variable creara un espacio en memoria en donde
almacenara los datos de acuerdo al formato estructurado dado en la declaración.
MEMORIA DINAMICA: La memoria dinámica es un espacio de almacenamiento
que se solicita en tiempo de ejecución.
OPERADOR PUNTO: Con el operador punto o flecha (puntero) podemos acceder
a los miembros de la estructura, de esta forma introducimos la información en la
estructura de datos, esta información se puede obtener desde el teclado o ya sea
desde un archivo, o asignar valores calculados.
UNIONES: Las uniones agrupan una serie de variables, pero su forma de
almacenamiento es diferente y su resultado también lo es. Una estructura permite
almacenar variables relacionadas juntas y almacenadas en posiciones contiguas
en memoria. Las uniones se declaran con la palabra reservada unión, almacenan
también miembros múltiples en un paquete,
ENUMERACION: Una enumeración es el conjunto de constantes enteras
representadas por identificadores, estas constantes de enumeración son
constantes simbólicas cuyos valores pueden ser definidos automáticamente. Una
enumeración es una colección de uno o más tipos de datos llamados miembros,
cada uno de los cuales puede ser un tipo de dato diferente.
Bibliografía
Joyanes Aguilar, Luis, Algoritmos y Estructuras de Datos. Una Perspectiva En C
Editorial: McGraw-Hill(2005).
GuardatiBuemo, Silvia. Estructura de datos orientada a objetos: Algoritmos con
C++ Editorial: Pearson(2007).
Prieto A., Lloris A. y Torres J.C. Introducción a la informática Editorial McGraw-Hill
(2001).
Lazaro, Obenza J. C. Estructuras de datos y Algoritmos, Editorial Prentice Hall,
Madrid (2000).
Euguíluz Morán, Andoni Estructuras de datos y algoritmosEditorial McGraw-Hill
(1999).
Rodríguez Baena, Luis; Fernandez Azuela, Matilde; Joyanes Aguilar Fundamentos
de programación: algoritmos, Estructuras de datos y objetos. Editorial McGraw-Hill
(2003).
Descargar