Está en la página 1de 142

SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 1


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Contenido

CAPITULO 1 ........................................................................................................................................6
FUNCIONES ........................................................................................................................................6
1.1 PROPIEDADES DE UNA FUNCION. ................................................................................................6
1.2. FUNCIONES EN C++. ....................................................................................................................7
1.3. DECLARACIÓN DE UNA FUNCIÓN. ...............................................................................................8
1.4. DEFINICION DE UNA FUNCION. ...................................................................................................9
1.5. ACCESO O LLAMADA A UNA FUNCION. .....................................................................................11
1.6. VARIABLES L.OCALES. ................................................................................................................12
1.7. VARIABLES GLOBALES. ..............................................................................................................13
1.8. PASO DE PARAMETROS POR VALOR Y POR REFERNCIA. ...........................................................14
1.9. FUNCIONES RECURSIVAS. ..........................................................................................................16
CAPITULO 2. .....................................................................................................................................19
Programación Orientada a Objetos ..................................................................................................19
2.1 ORIGENES DE LA PROGRAMACION ORIENTADA A OBJETOS. .....................................................20
2.2 CONCEPTOS DE LA PROGRAMACION ORIENTADA A OBJETOS. ..................................................21
2.3 PRESENTACION DE LAS CLASES Y LOS OBJETOS .........................................................................23
2.3.1 DEFINICIÓN DE UNA CLASE. ....................................................................................................24
2.3.2 IDENTIFICADORES DE CLASE. ...................................................................................................24
2.3.2.1 CUERPO DE UNA CLASE. .......................................................................................................25
2.3.3 USO DE UNA CLASE. ................................................................................................................26
2.4 ACCESO A UNA CLASE. ...............................................................................................................29
2.4.1 MIEMBROS DE LA CLASE PRIVATE. ..........................................................................................30
2.4.2 MIEMBROS DE LA CLASE PUBLIC: ............................................................................................31
2.4.3 MIEMBROS DE LA CLASE PROTECTED. ....................................................................................31
2.5. APUNTADORES COMO MIEMBROS DE DATOS. .........................................................................33
2.5.1 APUNTADORES A MIEMBROS DE DATOS DE CLASES. ..............................................................33
2.6. CONSTRUCTORES. .....................................................................................................................34
2.6.1 CONSTRUCTORES PRIVATE. .....................................................................................................36
2.6.2 CONSTRUCTORES CON ARGUMENTOS. ...................................................................................36
2.6.3 CONSTRUCTORES PARA COPIAR OBJETOS. .............................................................................38

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 2


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.7 DESTRUCTORES. .........................................................................................................................38


2.8 CLASES AMIGAS (Palabra reservada friend) ...............................................................................41
2.8.1 FUNCIONES AMIGAS. ..............................................................................................................42
2.8.2 PROPIEDADES DE LA PALABRA RESERVADA friend. .................................................................44
2.9 HERENCIA ...................................................................................................................................45
2.9.1 LIMITACIONES DE LA HERENCIA. .............................................................................................47
2.9.2 QUE NO SE PUEDE HEREDAR. ..................................................................................................47
2.9.3 HERENCIA MULTIPLE. ..............................................................................................................48
2.9.4 USO DE CLASES DE BASE VIRTUAL. ..........................................................................................51
2.10 SOBRECARGA. ..........................................................................................................................53
2.10.1 PORQUE USAR LA SOBRECARGA. ..........................................................................................53
2.10.2 SOBRECARGA DE FUNCIONES................................................................................................53
2.10.3 CONSTRUCTORES SOBRECARGADOS. ....................................................................................57
2.10.4 SOBRECARGA DE OPERADORES. ...........................................................................................58
2.10.4.1 OPERADORES COMO LLAMADAS A FUNCION. ...................................................................59
2.10.4.2 OPERADORES SOBRECARGADOS COMO FUNCIONES MIEMBRO. ......................................59
2.10.4.3 OPERADORES SOBRECARGADOS COMO FUNCIONES FRIEND. ...........................................61
2.11 POLIMORFISMO .......................................................................................................................62
2.11.1 FUNCIONES VIRTUALES. ........................................................................................................62
2.12 EJEMPLOS DE PROGRAMACION ORIENTADA A OBJETOS .........................................................65
CAPITULO 3 ......................................................................................................................................72
INTRODUCCION A LAS ESTRUCTURAS DE DATOS ESTATICAS ...........................................................72
3.1. CLASIFICACIÓN DE LOS TIPOS DE DATOS SEGÚN SU ESTRUCTURA ...........................................72
3.2. ARREGLOS. ................................................................................................................................73
3.2.1. ARREGLOS UNIDIMENSIONALES. VECTORES. .........................................................................74
3.2.1.1. DECLARACIÓN DE UN ARRAY UNIDIMENSIONAL: VECTOR: .................................................74
3.2.1.2. ALMACENAMIENTO DE DATOS EN UN VECTOR. .................................................................75
3.2.1.3. MANEJO DE VECTORES DESDE UNA APLIACION OO. ...........................................................76
3.2.2. ARREGLOS BIDIMENSIONALES. MATRICES. ............................................................................81
3.2.2.1. DECLARACIÓN DE UN ARRAY BIDIMENSIONAL: MATRIZ: ....................................................81
3.2.2.2. ALMACENAMIENTO DE DATOS EN UN VECTOR. .................................................................82
3.2.2.3. MANEJO DE UNA MATRIZ DESDE UNA APLIACION OO. ......................................................84

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 3


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 4 ......................................................................................................................................88
ESTRUCTURAS Y UNIONES ...............................................................................................................88
4.1. ESTRUCTURAS. ..........................................................................................................................88
4.1.1. ESQUEMA DE LA ESTRUCTURA. ..............................................................................................89
4.1.2. DECLRACION DE UN TIPO DE DATO ESTRUCTURA..................................................................89
4.1.3. DECLARACION DE UNA VARIABLE ESTRUCTURA. ...................................................................90
4.1.4. ACCESO A LOS CAMPOS DE UNA VARIABLE ESTRUCTURA .....................................................91
4.1.5. OPERACIONES CON ESTRUCTURAS. .......................................................................................92
4.1.6. ARREGLOS DE ESTRUCTURAS. ................................................................................................93
4.1.7. ESTRUCTURAS ANIDADAS ......................................................................................................97
4.2 UNIONES. ...................................................................................................................................99
CAPITULO 5 ....................................................................................................................................101
PUNTEROS Y ESTRUCTURAS DINÁMICAS DE DATOS ......................................................................101
5.1. OPERADORES PARA EL MANEJO DE PUNTEROS. .....................................................................101
5.1.1. OPERADOR DE DIRECCION ‘&’. .............................................................................................101
5.1.2 OPERADOR DE INDIRECCION O CONTENIDO ‘*’. ...................................................................102
5.2. DECLARACIÓN DE PUNTEROS. .................................................................................................103
5.2.1. ALMACENAMIENTO EN UNA VARIABLE PUNTERO. ..............................................................103
5.3. OPERACIONES CON PUNTEROS. ..............................................................................................105
5.3.1. ASIGNACION.........................................................................................................................105
5.3.2. COMPARACION. ...................................................................................................................106
5.3.3. ARITMETICA CON PUNTEROS. ..............................................................................................106
5.4. PUNTEROS Y ARREGLOS. .........................................................................................................108
5.4.1. PUNTERO A CADENA DE CARACTERES. ................................................................................110
5.4.2. PUNTEROS A ESTRUCTURAS. ................................................................................................112
5.5. ESTRUCTURAS DINÁMICAS DE DATOS. LISTAS SIMPLES. .........................................................114
5.5.1. OPERACIONES BASICAS EN UNA LISTA SIMPLE. ...................................................................115
CAPITULO 6 ....................................................................................................................................120
ARCHIVOS.......................................................................................................................................120
6.1. DEFINICION. ............................................................................................................................120
6.2. PROPIEDADES DE UN ARCHIVO. ..............................................................................................120
6.3. ORGANIZACIÓN DE UN ARCHIVO. ...........................................................................................122

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 4


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

6.3.1. ORGANIZACIÓN SECUENCIAL. ..............................................................................................122


6.3.2. ORGANIZACIÓN DIRECTA/RANDOMICA O ALEATORIA. ........................................................123
6.4. USO DE ARCHIVOS. ..................................................................................................................123
6.5. ENTRADA Y SALIDA EN ARCHIVOS. ..........................................................................................124
6.6. PROCESAMIENTO DE ARCHIVOS EN EL DISCO. ........................................................................124
6.6.1. ABRIR UN ARCHIVO. .............................................................................................................125
6.6.2. CERRAR EL ARCHIVO. ...........................................................................................................126
6.6.3. CONTROL DE FIN DE ARCHIVO ‘EOF’ ....................................................................................127
6.6.4. ACCESO DIRECTO O ALEATORIO (fseek). ..............................................................................127
6.6.5. CONOCER LA POSICION ACTUAL DEL PUNTERO DE L/E. .......................................................128
6.6.6. RESTABLECER EL PUNTERO DE L/E AL PRINCIPIO. ................................................................128
6.7. PASOS PARA EL PROCESAMIENTO DE ARCHIVOS. ...................................................................129
6.8. OPERACIONES BÁSICAS EN UN ARCHIVO. ...............................................................................129
6.9. EJEMPLO DE APLICACIÓN DE ARCHIVOS DIRECTOS. ...............................................................132
BIBLIOGRAFIA.................................................................................................................................142

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 5


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 1

FUNCIONES

La Función es una porción de código, un conjunto de sentencias, agrupadas por separado,


generalmente enfocadas a realizar una tarea específica.

También se suelen denominar subrutinas o subprogramas.

Ventajas:

La división de un programa en unidades más pequeñas o funciones presenta las siguientes


ventajas:

 Modularización: Es el proceso consistente en dividir un programa en una serie de


módulos más pequeños y manejables, llamados funciones. Cada función tiene una
misión muy concreta, de modo que nunca tiene un número de líneas excesivo.
 Ahorro de memoria y tiempo de desarrollo: En la medida en que una función es
utilizada muchas veces, el número total de líneas de código disminuye.
 Independencia de datos y ocultamiento de información: Una función es capaz de
mantener gran independencia con el resto del programa, manteniendo sus propios
datos y definiendo muy claramente la interfaz o comunicación con la función que le
ha llamado.

1.1 PROPIEDADES DE UNA FUNCION.

Desde el punto de vista de la definición matemática una función debe cumplir con las
siguientes propiedades:

 Tiene un nombre. El nombre de la función identifica de manera sintética, es decir en


una sola secuencia de caracteres, la tarea u operación especifica que desarrolla.
 Retorna un resultado. Como el conjunto de código contenido en una función
resuelve una tarea específica, entonces el resultado de dicha operación debe ser el
retorno de la misma. Si bien por la naturaleza de la estructuración de un programa
se desea desarrollar una función que no retorna resultado se la debe considerar
como un procedimiento, para lo cual se dispone de los mecanismos adecuados que
permitan su implementación.
 Se aplica a uno o mas parámetros o argumentos. La tarea específica que se
desarrolla y resuelve en una función debe ser aplicada a uno o mas datos con los
que trabaja la función, estos elementos son los parámetros o argumentos de la
función.

La utilización de funciones nos permite dividir un programa extenso en pequeños


segmentos que realizan tareas concretas. Probablemente, dentro de un mismo programa se

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 6


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

realicen las mismas tareas varias veces, lo que se facilita mediante la utilización de
funciones. Sin embargo, es probable que ciertas funciones no sean reutilizables, pero al
usarlas se mejora la legibilidad del programa.

Con el propósito de permitir un manejo eficiente de los datos, las funciones en C no se


pueden anidar. En otras palabras, una función no se puede declarar dentro de otra función,
por lo que todas las funciones son globales o externas, lo que hace que puedan llamarse
desde cualquier parte de un programa.

1.2. FUNCIONES EN C++.

La estructura general de una función en C es la siguiente:

tipo_de_retorno nombre_de_la_función (lista_de_parámetros)


{
cuerpo_de_la_función
return expresión
}

Donde:

 tipo_de_retorno: es el tipo del valor devuelto por la función, o, en caso de que la


función no devuelva valor alguno, la palabra reservada void.
 nombre_de_la_función: es el nombre o identificador asignado a la función.
 lista_de_parámetros: es la lista de declaración de los parámetros que son pasados a
la función. Éstos se separan por comas. Debemos tener en cuenta que pueden existir
funciones que no utilicen parámetros.
 cuerpo_de_la_función: está compuesto por un conjunto de sentencias que llevan a
cabo la tarea específica para la cual ha sido creada la función.
 return expresión: mediante la palabra reservada return, se devuelve el valor de la
función, en este caso representado por expresión.

Vamos a suponer que queremos crear un programa para calcular el precio de un producto
basándose en el precio base del mismo y el impuesto aplicable. A continuación mostramos
el código fuente de dicho programa:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 7


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>

float precio(float base, float impuesto); /* declaración */


main()
{
float importe = 2.5;
float tasa = 0.07;
printf("El precio a pagar es: %.2f\n", precio(importe, tasa));
return 0;
}

float precio(float base, float impuesto) /* definición */


{
float calculo;
calculo = base + (base * impuesto);
return calculo;
}

El ejemplo anterior se compone de dos funciones, la función requerida main y la función


creada por el usuario precio, que calcula el precio de un producto tomando como
parámetros su precio base y el impuesto aplicable. La función precio calcula el precio de un
producto sumándole el impuesto correspondiente al precio base y devuelve el valor
calculado mediante la sentencia return.

Por otra parte, en la función main declaramos dos variables de tipo float que contienen el
precio base del producto y el impuesto aplicable. La siguiente sentencia dentro de la
función main es la llamada a la función de biblioteca printf, que recibe como parámetro
Una llamada a la función precio, que devuelve un valor de tipo float. De esta manera, la
función printf imprime por la salida estándar el valor devuelto por la función precio. Es
importante tener en cuenta que las variables importe y tasa (argumentos) dentro de la
función main tienen una correspondencia con las variables base e impuesto (parámetros)
dentro de la función precio respectivamente.

1.3. DECLARACIÓN DE UNA FUNCIÓN.

Antes de empezar a utilizar una función debemos declararla. La declaración de una


función se conoce también como prototipo de la función. En el prototipo de una función se
tienen que especificar los parámetros de la función, así como el tipo de dato que devuelve.

Los prototipos de las funciones que se utilizan en un programa se incluyen generalmente en


la cabecera del programa y presentan la siguiente sintaxis:

tipo_de_retorno nombre_de_la_función(lista_de_parámetros);

En el prototipo de una función no se especifican las sentencias que forman parte de la


misma, sino sus características. Por ejemplo:
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 8
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int cubo(int numero);

En este caso se declara la función cubo que recibe como parámetro una variable de tipo
entero (numero) y devuelve un valor del mismo tipo. En ningún momento estamos
especificando qué se va a hacer con la variable numero, sólo declaramos las características
de la función cubo.

Cabe señalar que el nombre de los parámetros es opcional y se utiliza para mejorar la
comprensión del código fuente. De esta manera, el prototipo de la función cubo podría
expresarse de la siguiente manera:

int cubo(int);

Los prototipos de las funciones son utilizados por el compilador para verificar que se
accede a la función de la manera adecuada con respecto al número y tipo de parámetros, y
al tipo de valor de retorno de la misma. Veamos algunos ejemplos de prototipos de
funciones:

int potencia(int base, int exponente);


double area_rectangulo (float base, float altura);
int mayor(int, int);

1.4. DEFINICION DE UNA FUNCION.

Luego de declarar una función, el siguiente paso es implementarla. Generalmente, este paso
se conoce como definición. Es precisamente en la definición de una función donde se
especifican las instrucciones que forman parte de la misma y que se utilizan para llevar a
cabo la tarea específica de la función. La definición de una función consta de dos partes:

El encabezado y el cuerpo de la función. En el encabezado de la función, al igual que en


el prototipo de la misma, se tienen que especificar los parámetros de la función, si los
utiliza y el tipo de datos que devuelve, mientras que el cuerpo se compone de las
instrucciones necesarias para realizar la tarea para la cual se crea la función. La sintaxis de
la definición de una función es la siguiente:

tipo_de_retorno nombre_de_la_función(lista_de_parámetros)
{
sentencias;
}

El tipo_de_retorno representa el tipo de dato del valor que devuelve la función. Este tipo
debe ser uno de los tipos simples de C, un puntero a un tipo de C o bien un tipo struct. De
forma predeterminada, se considera que toda función devuelve un tipo entero (int). En otras
palabras, si en la declaración o en la definición de una función no se especifica el
tipo_de_retorno, el compilador asume que devuelve un valor de tipo int.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 9


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El nombre_de_la_función representa el nombre que se le asigna a la función.

Se recomienda que el nombre de la función esté relacionado con la tarea que lleva a cabo.
En caso de que la función utilice parámetros, éstos deben estar listados entre paréntesis a
continuación del nombre de la función, especificando el tipo de dato y el nombre de cada
parámetro. En caso de que una función no utilice parámetros, se pueden dejar los paréntesis
vacíos o incluir la palabra void, que indica que la función no utiliza parámetros. Después
del encabezado de la función, debe aparecer, delimitado por llaves ({ y }), el cuerpo de la
función compuesto por las sentencias que llevan a cabo la tarea específica de la función.
Veamos la definición de la función cubo declarada
en el apartado anterior:

int cubo(int base)


{
int potencia;
potencia = base * base * base;
return potencia;
}

Es muy importante hacer notar que la definición de la función de la puede realizar después
de la función principal ‘main’, en este caso es necesario la declaración del prototipo o
simplemente antes de la función ‘main’.

A continuación mostramos las dos situaciones:

Con la declaración de un prototipo:

#include <stdio.h>

int cubo(int base);

main()
{
int numero;
for(numero=1; numero<=5; numero++)
{
printf("El cubo del número %d es %d\n", numero, cubo(numero));
}
return 0;
}
int cubo(int base)
{
int potencia;
potencia = base * base * base;
return potencia;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 10


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Con la definición de la función:

#include <stdio.h>

int cubo(int base)


{
int potencia;
potencia = base * base * base;
return potencia;
}

main()
{
int numero;
for(numero=1; numero<=5; numero++)
{
printf("El cubo del número %d es %d\n", numero, cubo(numero));
}
return 0;
}

1.5. ACCESO O LLAMADA A UNA FUNCION.

Para que una función realice la tarea para la cual fue creada, debemos acceder o llamar a la
misma. Cuando se llama a una función dentro de una expresión, el control del programa se
pasa a ésta y sólo regresa a la siguiente expresión de la que ha realizado la llamada cuando
encuentra una instrucción return o, en su defecto, la llave de cierre al final de la función.

Generalmente, se suele llamar a las funciones desde la función main, lo que no implica que
dentro de una función se pueda acceder a otra función.

Cuando queremos acceder a una función, debemos hacerlo mediante su nombre seguido de
la lista de argumentos que utiliza dicha función encerrados entre paréntesis. En caso de que
la función a la que se quiere acceder no utilice argumentos, se deben colocar los paréntesis
vacíos.

Cualquier expresión puede contener una llamada a una función. Esta llamada puede ser
parte de una expresión simple, como una asignación, o puede ser uno de los operandos de
una expresión más compleja. Por ejemplo:

a = cubo(2);
calculo = b + c / cubo(3);

Debemos recordar que los argumentos que utilizamos en la llamada a una función
sedenominan argumentos reales o parámetros actuales. Estos argumentos deben
coincidir en el número y tipo con los argumentos formales o parámetros de la función.
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 11
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

No olvidemos que los argumentos formales son los que se utilizan en la definición y/o
declaración de una función.

Los argumentos reales pueden ser variables, constantes o incluso expresiones más
complejas.

El valor de cada argumento real en la llamada a una función se transfiere a dicha función y
se le asigna al argumento formal correspondiente.

Generalmente, cuando una función devuelve un valor, la llamada a la función suele estar
dentro de una expresión de asignación, como operando de una expresión compleja o como
argumento real de otra función. Sin embargo, cuando la función no devuelve ningún valor,
la llamada a la función suele aparecer sola. Veamos un ejemplo:

z = potencia( a, b);
imprime_valores (x, y, z);

1.6. VARIABLES L.OCALES.

Cuando declaramos variables dentro de la función principal del programa, es decir, dentro
de la función main, están únicamente asociadas a esta función, en otras palabras, son
variables locales de la función main y no se puede acceder a ellas a través de ninguna otra
función.

Al igual que sucede con las variables declaradas dentro de la función main, cualquier
variable que declaremos dentro de una función, es local a esa función, es decir, su ámbito
esta confinado a dicha función. Esta situación permite que existan variables con el mismo
nombre en diferentes funciones y que no mantengan ninguna relación entre sí.

Debemos tener en cuenta que cualquier variable declarada dentro de una función se
considera como una variable automática (auto) a menos que utilicemos algún modificador
de tipo.

El siguiente ejemplo ilustra el manejo de variables locales en funciones diferentes:

#include <stdio.h>

void imprimeValor()
{
int contador = 5; // variable local
printf("El valor de contador es: %d\n", contador);
}

main()
{
int contador = 0; //variable local
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 12
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

contador++;
printf("El valor de contador es: %d\n", contador);
imprimeValor();
printf("Ahora el valor de contador es: %d\n", contador);
return 0;
}

1.7. VARIABLES GLOBALES.

A diferencia de las variables locales cuyo ámbito estaba confinado a la función donde
estaban declaradas, el ámbito de las variables globales se extiende desde el punto en el que
se definen hasta el final del programa. En otras palabras, si definimos una variable al
principio del programa, cualquier función que forme parte de éste podrá utilizarla
simplemente haciendo uso de su nombre.

La utilización de variables globales proporciona un mecanismo de intercambio de


información entre funciones sin necesidad de utilizar argumentos. Por otra parte, las
variables globales mantienen el valor que se les ha asignado dentro de su ámbito, incluso
después de finalizar las funciones que modifican dicho valor. Debemos tener en cuenta que
el uso de variables globales para el intercambio de informaciones entre funciones puede
resultar útil en algunas situaciones (como cuando se desea transferir más de un valor desde
una función), pero su utilización podría llevarnos a programas de difícil interpretación y
complejos de depurar.

En el siguiente ejemplo ilustramos el uso de una variable global:

#include <stdio.h>

int variable; // variable global

void unaFuncion()
{
printf("En la función unaFuncion, variable es: %d\n", variable);
}
void otraFuncion()
{
variable++;
printf("En la función otraFuncion, variable es: %d\n",variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 13


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

main()
{
variable = 9;
printf("El valor de variable es: %d\n", variable);
unaFuncion();
otraFuncion();
printf("Ahora el valor de variable es: %d\n", variable);
return 0;
}

1.8. PASO DE PARAMETROS POR VALOR Y POR REFERNCIA.

En C++ todos los argumentos que se pasan a una función se pasan por valor. En otras
palabras, se pasa una copia del valor del argumento y no el argumento en sí (por ello, este
procedimiento se conoce en algunas ocasiones como paso por copia). Al pasar una copia
del argumento original a la función, cualquier modificación que se realice sobre esta copia
no tendrá efecto sobre el argumento original utilizado en la llamada de la función. Se puede
considerar un argumento pasado por valor como una variable local de la función a la que se
ha pasado, de tal modo que los cambios que se realicen sobre ésta tendrán efecto sólo
dentro de la función.

Veamos un ejemplo del paso por valor de argumentos a una función:

#include <stdio.h>

void modificar(int variable); // PROTOTIPO

main()
{
int i = 1;
printf("\ni=%d antes de llamar a la función modificar", i);
modificar(i);
printf("\ni=%d después de llamar a la función modificar", i);
}

void modificar(int variable)


{
printf("\nvariable = %d dentro de modificar", variable);
variable = 9;
printf("\nvariable = %d dentro de modificar", variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 14


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Dado que lo que se pasa a la función modificar es una copia de la variable i, el valor de ésta
en la función main no se ve alterado cuando dentro de la función modificar se cambia el
valor de variable. De ahí, la salida del ejemplo anterior es la siguiente:

i=1 antes de llamar a la función modificar


variable = 1 dentro de modificar
variable = 9 dentro de modificar
i=1 después de llamar a la función modificar

Como ya hemos visto, cuando se pasa un argumento por valor, realmente se pasa una copia
de éste, y si esta copia se modifica el argumento original no se ve alterado. Sin embargo, en
muchas ocasiones lo que queremos es que una función cambie los valores de los
argumentos que le pasamos. Para lograrlo se utiliza lo que se conoce como paso de
parámetros por referencia. En estos casos, no se pasa una copia del argumento, sino el
argumento mismo.

Cuando realizamos un paso de parámetros por referencia en C++, realmente lo que


estamos pasando son direcciones de memoria. En otras palabras, lo que le pasamos a la
función son las direcciones de memoria de los argumentos.

Como hemos visto en la unidad anterior, esta operación se logra mediante la utilización del
operador de dirección ‘&’. De este modo, cuando llamamos a una función, lo que realmente
le pasamos son punteros a los argumentos que deseamos modificar. Veamos el ejemplo
anterior utilizando el paso de parámetros por referencia:

#include <stdio.h>

void modificar(int &variable);

main()
{
int i = 1;
printf("\ni=%d antes de llamar a la función modificar", i);
modificar(i);
printf("\ni=%d después de llamar a la función modificar", i);
return 0;
}
void modificar(int &variable)
{
printf("\nvariable = %d dentro de modificar", variable);
variable = 9;
printf("\nvariable = %d dentro de modificar", variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 15


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La salida de este ejemplo sería:

i=1 antes de llamar a la función modificar


variable = 1 dentro de modificar
variable = 9 dentro de modificar
i=9 después de llamar a la función modificar

Como se puede observar, el valor de i ha cambiado puesto que la función modificar ha


utilizado la dirección de memoria de esta variable en la sentencia de asignación variable =
9. Analicemos detenidamente este ejemplo. Lo primero que tenemos que tener en cuenta es
que la premisa de que en C++ todos los argumentos se pasan por valor sigue siendo cierta.
Lo que sucede es que en este caso estamos pasando el valor de la dirección de memoria de
la variable i y no el valor de su contenido. Para pasar la dirección de memoria de una
variable se utiliza el operador &. Al finalizar la función, el valor de dicha dirección
permanece igual y lo que se ha modificado es el contenido de esa dirección de memoria.

1.9. FUNCIONES RECURSIVAS.

Las funciones en C++ pueden ser recursivas, en otras palabras, pueden llamarse a sí
mismas directa o indirectamente.

La recursividad directa es el proceso mediante el que una función se llama a sí misma desde
el propio cuerpo de la función, mientras que la recursividad indirecta implica más de una
función.

Un proceso recursivo tiene que tener una condición de finalización, ya que de lo contrario
podría continuar infinitamente.

Un ejemplo típico de aplicación de la recursividad es el cálculo del factorial de un número


entero. Recordemos que el factorial de un número entero (n!) se calcula de la siguiente
manera:

n! = n * (n-1) * (n-2) * ... * 2 * 1

En principio, la solución a este problema podría realizarse sin tener que utilizar la
recursividad con el siguiente programa:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 16


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>

int factorial(int numero);

main()
{
int valor = 4;
int resultado;
resultado = factorial(valor);
printf("El factorial de %d es %d \n", valor, resultado);
return 0;
}

int factorial(int numero)


{
int i;
int devuelve = 1;
for(i = 1; i <= numero; i++)
{
devuelve = devuelve * i;
}
return devuelve;
}

Sin embargo, resulta más intuitivo dada la definición de número factorial utilizar una
función recursiva como la siguiente:

int factorial(int numero)


{
if(numero == 1)
return 1;
else
return (numero * factorial(numero-1));
}

En la función anterior, en el caso de que el argumento utilizado en la llamada sea 1, ésta


devuelve 1, y en caso contrario se calcula un producto que involucra a la variable numero y
una nueva llamada a la función cuyo argumento es menor en una unidad (numero -1).

El funcionamiento de una función recursiva se realiza almacenando las llamadas pendientes,


con sus argumentos, en la pila en tiempo de ejecución.

Veamos un ejemplo:

Si utilizamos el valor 4 como argumento de la función que calcula el factorial, es decir,


factorial(4), el proceso de llamadas será el siguiente:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 17


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Llamada # 1:
numero = 4
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 4 * (realizamos la segunda llamada))
Llamada # 2:
numero = 3
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 3 * (realizamos la tercera llamada))
Llamada # 3:
numero = 2
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 2 * (realizamos la cuarta llamada))
Llamada # 4:
numero = 1
numero == 1 entonces se ejecuta la sentencia del if:
return 1
Fin Llamada # 4 -> DEVUELVE 1
return ( 2 * 1)
Fin Llamada # 3 -> DEVUELVE 2
return ( 3 * 2)
Fin Llamada # 2 -> DEVUELVE 6
return ( 4 * 6)
Fin Llamada #1 -> DEVUELVE 24

En toda función recursiva se debe identifica 2 momentos importante:

 CASO BASICO. En este momento la variable de recursión toma un valor inicial y no


es necesari establecer una llamada a la misma función.
 PROCESO RECURSIVO. En este momento es en el que se implementa un proceso
repetitivo por medio de una llamada a la misma función. Debemos tomar en cuenta que
el parámetro de la llamada recursiva debe ser menor que el parámetro de la función que
se define, de esta manera se evita procesos recursivos infinitos.

En el ejemplo del factorial se identifica estos mementos de la siguiente manera:

Caso básico:
Si numero=1 entoces factorial(1)=1
Proceso recursivo
si numero>1 entonces factorial(numero)= numero *factorial(numero-1)

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 18


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 2.

Programación Orientada a Objetos

Un paradigma de programación es una propuesta tecnológica adoptada por una comunidad


de programadores y desarrolladores cuyo núcleo central es incuestionable en cuanto que
únicamente trata de resolver uno o varios problemas claramente delimitados; la resolución
de estos problemas debe suponer consecuentemente un avance significativo en al menos un
parámetro que afecte a la ingeniería de software.

Un paradigma de programación representa un enfoque particular o filosofía para diseñar


soluciones. Los paradigmas difieren unos de otros, en los conceptos y la forma de abstraer
los elementos involucrados en un problema, así como en los pasos que integran su solución
del problema, en otras palabras, el cómputo.

Tiene una estrecha relación con la formalización de determinados lenguajes en su momento


de definición. Es un estilo de programación empleado.

Un paradigma de programación está delimitado en el tiempo en cuanto a aceptación y uso,


porque nuevos paradigmas aportan nuevas o mejores soluciones que la sustituyen parcial o
totalmente.

El paradigma de programación que actualmente es el más utilizado es la "orientación a


objetos" (OO). El núcleo central de este paradigma es la unión de datos y procesamiento en
una entidad llamada "objeto", relacionable a su vez con otras entidades "objeto".

Tradicionalmente, datos y procesamiento se han separado en áreas diferente del diseño y la


implementación de software. Esto provocó que grandes desarrollos tuvieran problemas de
fiabilidad, mantenimiento, adaptación a los cambios y escalabilidad. Con la OO y
características como el encapsulado, polimorfismo o la herencia, se permitió un avance
significativo en el desarrollo de software a cualquier escala de producción. La OO parece
estar ligada en sus orígenes con lenguajes como Lisp y Simula, aunque el primero que
acuñó el título de "programación orientada a objetos" fue Smalltalk.

La programación orientada a objetos, ha tomado las mejores ideas de la programación


estructurada y los ha combinado con varios conceptos nuevos y potentes que incitan a
contemplar las tareas de programación desde un nuevo punto de vista. La programación
orientada a objetos, permite descomponer mas fácilmente un problema en subgrupos de
partes relacionadas del problema. Entonces, utilizando el lenguaje se pueden traducir estos
subgrupos a unidades autocontenidas llamadas objetos.

El término Programación Orientada a Objetos (POO), hoy en día ampliamente utilizado, es


difícil de definir, ya que no es un concepto nuevo, sino que ha sido el desarrollo de técnicas
de programación desde principios de la década de los setenta, aunque sea en la década de
los noventa cuando ha aumentado su difusión, uso y popularidad. No obstante, se puede

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 19


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

definir POO como una técnica o estilo de programación que utiliza objetos como bloque
esencial de construcción.

Un objeto es una unidad que contiene datos y las funciones que operan sobre esos datos. A
los elementos de un objeto se les conoce como miembros; las funciones que operan sobre
los objetos se denominan métodos y los datos se denominan miembros datos.

2.1 ORIGENES DE LA PROGRAMACION ORIENTADA A OBJETOS.

Al principio se empezaron a hacer lenguajes de alto nivel, orientados a procesos. Esa forma
de trabajar daba más importancia a los procesos que a los datos.

Entonces muchas personas se dieron cuenta de que los datos merecían mayor atención y así
aparecieron los lenguajes orientados a datos. Estos lenguajes tenían mucho cuidado con los
datos, pero los procesos eran muy sencillos o casi inexistentes. El problema era que cuando
había que cambiar la forma de los datos era necesario revisar todas las estructuras
anteriores.

De la síntesis entre la programación orientada a procesos y de la programación orientada a


datos nace la Programación Orientada a Objetos, un equilibrio entre las dos anteriores, que
cuida tanto datos como procesos y evita los problemas de acoplamiento de los otros
paradigmas.

Etapa 1. Lenguajes Ensambladores.

La unidad de programación es la instrucción, compuesta de un operador y los operandos. El


nivel de abstracción que se aplica es muy bajo.

Etapa 2. Lenguajes de Programación: Fortran, Algol, Cobol.

Los objetos y operaciones del mundo real se podían modelar mediante datos y estructuras
de control separadamente. En esta etapa el diseño del software se enfoca sobre la
representación del detalle procedimental y en función del lenguaje elegido. Conceptos
como: refinamiento progresivo, modularidad procedimientos y programación estructurada
son conceptos básicos que se utilizan en esta etapa. Existe mayor abstracción de datos.

Etapa 3.

Se introducen en esta etapa los conceptos de abstracción y ocultación de la información.

Etapa 4.

A partir de los años setenta se trabaja sobre una nueva clase de lenguajes de simulación y
sobre la construcción de prototipos tales como Simula-70 y basado en parte de éste, el

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 20


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Smalltalk. En estos lenguajes, la abstracción de datos tiene una gran importancia y los
problemas del mundo real se representan mediante objetos de datos a los cuales se les
añade el correspondiente conjunto de operaciones asociados a ellos. Términos como
Abstracción de datos, objeto, encapsulación entre otros, son conceptos básicos sobre la que
se fundamenta la POO.

2.2 CONCEPTOS DE LA PROGRAMACION ORIENTADA A OBJETOS.

Existen cuatro conceptos fundamentales dentro de la Programación Orientada a Objetos


que se relacionan entre sí y que nos permitirán tener las riendas de nuestro código:

Abstracción: proceso mental de extracción de las características esenciales de algo,


ignorando los detalles superfluos.

Encapsulación: proceso por el que se ocultan los detalles del soporte de las características
esenciales de una abstracción.

Modularización: proceso de descomposición de un sistema en un conjunto de módulos o


piezas independientes y cohesivos (con significado propio). Lo adecuado es conseguir los
mínimos acoplamientos.

Jerarquización: proceso de estructuración por el que se produce una organización


(jerarquía) de un conjunto de elementos en grados o niveles de responsabilidad,
incumbencia o composición entre otros.

La POO representa una metodología de programación que se basa en las siguientes


características:

1) Los diseñadores definen nuevas clases (o tipos) de objetos.


2) Los objetos poseen una serie de operaciones asociadas a ellos.
3) Las operaciones tienden a ser genéricas, es decir, operan sobre múltiples tipos de
datos.
4) Las clases o tipos de objetos comparten componentes comunes mediante
mecanismos de herencia.

Objeto:

Una estructura de datos y conjunto de procedimientos que operan sobre dicha


estructura. Una definición más completa de objeto es: una entidad de programa que
consiste en datos y todos aquellos procedimientos que pueden manipular aquellos
datos; el acceso a los datos de un objeto es solamente a través de estos
procedimientos, únicamente estos procedimientos pueden manipular, referenciar y/o
modificar estos datos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 21


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Para poder describir todos los objetos de un programa, conviene agrupar éstos en clases.

Clase:
Podemos considerar una clase como una colección de objetos que poseen
características y operaciones comunes. Una clase contiene toda la información
necesaria para crear nuevos objetos.

Encapsulación:
Es una técnica que permite localizar y ocultar los detalles de un objeto. La
encapsulación previene que un objeto sea manipulado por operaciones distintas de
las definidas. La encapsulación es como una caja negra que esconde los datos y
solamente permite acceder a ellos de forma controlada.

Las principales razones técnicas para la utilización de la encapsulación son:

1) Mantener a salvo los detalles de representación, si solamente nos interesa el


comportamiento del objeto.
2) Modificar y ajustar la representación a mejores soluciones algorítmicas o a nuevas
tecnologías de software.

Abstracción:
En el sentido mas general, una abstracción es una representación concisa de una
idea o de un objeto complicado. En un sentido mas especifico, la abstracción
localiza y oculta los detalles de un modelo o diseño para generar y manipular
objetos.

Una abstracción tiene un significado más general que la encapsulación, pudiendo hablar de
abstracción de datos en lugar de encapsulación de datos.

Como resumen de los 3 conceptos expuestos anteriormente podemos decir que:

1) Los objetos son encapsulaciones de abstracciones en la POO.


2) La unidad de encapsulación en la POO es el objeto.

Una clase es un tipo: Un objeto es una instancia de ese tipo. Además, la clase es un
concepto estático: una clase es un elemento reconocible en el texto del programa.

Un objeto es un concepto puramente dinámico, el cual pertenece, no al texto del programa,


sino a la memoria de la computadora, donde los objetos ocupan un espacio en tiempo de
ejecución una vez que haya sido creado.

La programación orientada a objetos, ha tomado las mejores ideas de la programación


estructurada y los ha combinado con varios conceptos nuevos y potentes que incitan a
contemplar las tareas de programación desde un nuevo punto de vista. La programación
orientada a objetos, permite descomponer mas fácilmente un problema en subgrupos de
partes relacionadas del problema. Entonces, utilizando el lenguaje se pueden traducir estos
subgrupos a unidades autocontenidas llamadas objetos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 22


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Objetos: Un objeto es una entidad lógica que contiene datos y un código que manipula
estos datos; el enlazado de código y de datos, de esta manera suele denominarse
encapsulación.

Cuando se define un objeto, se está creando implícitamente un nuevo tipo de datos.

Polimorfismo: Significa que un nombre se puede utilizar para especificar una clase
genérica de acciones.

Herencia: La herencia es un proceso mediante el cual un objeto puede adquirir las


propiedades de otro objeto.

2.3 PRESENTACION DE LAS CLASES Y LOS OBJETOS

Objeto: Un objeto es una entidad abstracta que tiene las características de un objeto real.

Los objetos se crean y eliminan durante la ejecución del programa, además interactúan con
otros objetos. Los objetos son construcciones de programación que se obtienen a partir de
entidades llamadas clases. La definición de una clase se conoce como instanciación de
clases.

Para crear un objeto, es preciso definir primero su forma general utilizando la palabra
reservada class. Una class es parecida a una estructura, es un tipo definido por el usuario
que determina las estructuras de datos y las operaciones asociadas con este tipo.

Las clases son como plantillas o modelos que describen como se construyen ciertos tipos de
objetos, cada vez que se construye un objeto de una clase se crea una instancia de esa clase,
por consiguiente; los objetos son instancias de clases.

Una clase es una colección de objetos similares y un objeto es una instancia de una
definición de una clase; una clase puede tener muchas instancias y cada una es un objeto
independiente.

Una clase es simplemente un modelo que se utiliza para describir uno o mas objetos del
mismo tipo.

Así, por ejemplo sea una clase ventana, un tipo de dato, que contenga los miembros dato:

posx, posy
tipo_ventana
tipo_borde
color_ventana

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 23


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

y unas funciones miembro:

mover_horizontal
mover_vertical

Un objeto de la clase ventana, es una ventana concreta (una instancia de la clase) cuyos
datos tienen por valores:

Posx x
posy y
tipo_ventana desplegable
tipo_borde linea doble
color_ventana amarillo

2.3.1 DEFINICIÓN DE UNA CLASE.

Las clases son estructuras que contienen no sólo declaraciones de datos, sino también
declaraciones de funciones. Las funciones se conocen como funciones miembro, e indican
qué tipos de cosas puede hacer una clase. La palabra reservada class introduce una
declaración de clase.

2.3.2 IDENTIFICADORES DE CLASE.

La longitud máxima para un identificador de clase es 32 caracteres. Una convensión que se


adopta en todas las clases de borland es utilizar nombres que comiencen con una letra
mayúscula para denotar clases y estructuras globales.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 24


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.3.2.1 CUERPO DE UNA CLASE.

La forma general de la declaración de una clase es:

class Nombre_de_la_clase{
private:
datos y funciones privados

public:
datos y funciones publicas

}lista de objetos;
Una clase puede contener tanto partes públicas como partes privadas, por defecto, todos los
elementos que se definen en la clase son privados; esto significa que no pueden acceder a
ellas ninguna función que no sea miembro de la clase.

Class Counter{
long count; // variable privada , variable miembro de la clase

Public:
void SetValue(long); // Funciones públicas, funciones miembro de la
clase
long GetValue();
};

La variable long count, no está disponible o no se puede usar por otras funciones que no
están declaradas en la clase, por lo que tratar de hacer esto es erróneo:

void main()
{
count = 3.111;
}

Una clase puede tener tantas variables como necesite. Estas pueden ser de cualquier tipo,
incluyendo otras clases, apuntadores a objetos de clases e incluso apuntadores a objetos
dinámicamente asignados.

Las funciones miembro SetValue(long) y GetValue(). Solo están declaradas dentro de la


clase, la definición de estas funciones sería así:

void Counter::SetValue(long value)


{
count = value;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 25


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

long Counter::GetValue()
{
return count;
}

2.3.3 USO DE UNA CLASE.

Ya que se ha definido la clase, se debe definir un objeto con ella. Las variables de una clase
se definen de igual manera que como se definen las variables de tipo estructura.

Para el ejemplo de la clase anterior, si quiere declarar un objeto Gente de tipo Counter, lo
podría hacer asi:

Class Counter
{
.
.
public:
.
.
}Gente;

O la declaración la podría hacer de la siguiente forma:

Counter Gente;

En algunos lenguajes orientados a objetos, Smalltalk en particular, la definición de una


variable de clase se denomina instanciación de la clase.

Una instanciación es simplemente una instancia de una clase en la forma de una variable
específica.

Las variables instanciadas a partir de clases son objetos.

El objeto Gente se podría usar así en un programa:

void main()
{
Counter Gente; // Declaración de un objeto
Gente.SetValue(1000); // Invocación a función miembro de Counter
long value = GetValue(); // Invocación a función miembro de Counter
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 26


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La iniciación se tiene que hacer a través de sus funciones miembro, por lo que hacer lo
siguiente sería un error.

void main()
{
Counter Gente;
Gente = 1000; // error, la variable no está disponible en la función main()
long value = GetValue();
}

El código anterior no hace mucho, pero ilustra 2 aspectos importantes:

La declaración de un objeto dentro de una función y la invocación de funciones miembro


de un objeto.

En otro ejemplo, ésta clase define un tipo llamado cola, que se utiliza para crear un objeto
de tipo cola.

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
void iniciar(void);
void ponent(int i);

int quitaent(void);
};

Cuando llega el momento de codificar realmente una función que es miembro de una clase,
es preciso decir al compilador a que clase pertenece la función, calificando el nombre de la
función con el nombre de la clase del cual es miembro. p.e.

void cola :: ponent(int i)


{
if(posfin>=100)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 27


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El :: se llama operador de resolución de ámbito; indica al compilador que la función


ponent(int i) pertenece a la clase cola, o dicho de otra manera, ponent(int i) está dentro del
ámbito de cola.

Para llamar a una función miembro desde una parte del programa que no sea parte de la
clase, se debe utilizar el nombre del objeto y el operador punto. p.e.

Cola a, b; // se crean 2 objetos tipo cola.

a.iniciar(); // llama a la función iniciar para el objeto a.

Consideremos el siguiente ejemplo, de un programa en C++, aunque en una aplicación real


la declaración de las clases debe estar contenida en un archivo de cabecera.

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
void iniciar(void);
void ponent(int i);
int quitaent(void);
};

main(void)
{
cola a, b;
a.iniciar();
b.iniciar();
a.ponent(15);
b.ponent(39);
a.ponent(55);
b.ponent(19);
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
return 0;
}

void cola::iniciar()
{
posprin=posfin=0;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 28


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void cola::ponent(int i)
{
if(posfin==0)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

int cola::quitaent(void)
{
if(posfin==posprin)
{
cout<<"la cola está vacía";
return 0;
}
posprin++;
return c[posprin];
}

2.4 ACCESO A UNA CLASE.

La tarea de una clase consiste en ocultar la mayor cantidad de información posible. Por lo
tanto es necesario imponer ciertas restricciones a la forma en que se puede manipular una
clase. Existen 3 tipos de usuario de una clase:

1.- La clase misma.


2.- Usuarios genéricos.
3.- Clases derivadas.

Cada tipo de usuarios tiene privilegios de acceso asociados a una palabra clave:

1.- Private.
2.- Public.
3.- Protected.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 29


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Ejemplo:

class controlAcceso
{
int a;
public:
int b;
int fi(int a);
protected:
int c;
float C1(float t);
};

Cualquier declaración que aparezca antes de cualquiera de las tres palabras clave, por
default es private; así, int a; es private.

2.4.1 MIEMBROS DE LA CLASE PRIVATE.

Los miembros de la clase private tienen el mas estricto control de acceso. Solo la clase
misma puede tener acceso a un miembro private. En este ejemplo nadie puede usar la clase
ya que todo es private.

Class Privada
{
long valor;

void F1();
void F2();
};

void main()
{
privada objeto1; // Se crea objeto1 de clase privada.
long L = &objeto.valor; // acceso no valido por ser private.
objeto1.F1(); // acceso no valido por ser private.
objeto1.F2(); // acceso no valido por ser private.
}

Para poder tener acceso necesitaría que las funciones miembro fueran declaradas en la
sección public.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 30


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.4.2 MIEMBROS DE LA CLASE PUBLIC:

Para utilizar un objeto de una clase, usted debe tener acceso a datos miembro, a funciones
miembro o a ambos. Para hacer que algunos datos o funciones sean accesibles, se declaran
en la sección public.

class Ej_public
{
public:
int variable;
void función1();
};

void Ej_public::función1(){}

void main()
{
Ej_public Objeto2;
int i = Objeto2.variable;
Objeto2.función1();
}

Cualquier cosa que se declara en la sección public, hace posible el acceso ilimitado a
cualquier persona.

2.4.3 MIEMBROS DE LA CLASE PROTECTED.

Cuando se define una clase que se utiliza subsiguientemente como clase de base para otras
clases, se puede hacer que los miembros estén accesibles solo para funciones de las clases
derivadas mediante el uso de la palabra clave protected.

Considere una jerarquía de objetos como se ilustra a continuación:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 31


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La jerarquía de clase se puede expresar con código así:

class A
{
Protected:
int valor_A;
};

class B
{
public:
void funB();
};

class C
{
public:
void funC();
};

La propiedad de ser protected se extiende indefinidamente hacia abajo en un árbol de


herencia, en tanto que se declare que las clases derivadas tengan clases de base public. Por
ejemplo el código siguiente es aceptable.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 32


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void funB()
{
valor_A = 0;
}

void funC()
{
valor_A = 1000;
}

2.5. APUNTADORES COMO MIEMBROS DE DATOS.

Los miembros de datos pueden ser también apuntadores. Los apuntadores no se pueden
inicializar dentro de la declaración de una clase. Si un miembro de datos apunta a un tipo de
clase, el apuntador no se iniciliza, ni las construcciones son llamadas de manera automática.

Ejemplo.

class Segunda
{
int id;
public:
Primera* Object;
Segunda();
Int getnom() { return id; }
};

Aquí, el miembro se declara para apuntar a un elemento de otra clase llamada primera. En
la construcción de la clase segunda, el espacio de almacenamiento se asigna al objeto
apuntador, pero el apuntador se deja sin inicializar.

2.5.1 APUNTADORES A MIEMBROS DE DATOS DE CLASES.

Las clases no son objetos, pero aveces puede utilizarlas como si lo fueran. Un ejemplo es la
declaración de un apuntador a un miembro de clase.

class Ejemplo
{
public:
int valor;
int identificador;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 33


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void SetValue(Ejemplo& Objeto)


{
int Ejemplo::*ip = & Ejemplo::valor;
Objeto.*ip = 3;
}

void main()
{
Ejemplo Objeto1;
Ejemplo Objeto2;
SetValue(Objeto1);
SetValue(Objeto2);
}

La función SetValue() tiene la declaración inusual:

Int Ejemplo::*ip = & Ejemplo::valor;

Esta instrucción declara la variable ip que apunta a un valor de miembro de datos int en un
objeto de clase Ejemplo sin indicar un objeto especifico.

2.6. CONSTRUCTORES.

Un constructor es una función especial que es miembro de esa clase y que tiene el mismo
nombre de la clase.

Es muy frecuente que una cierta parte de un objeto necesite una iniciación antes de que
pueda ser utilizada; como el requisito de iniciación es tan frecuente C++ permite que los
objetos se den a sí mismos valores iniciales cuando se crean. Esta iniciación
automáticamente se lleva a cabo mediante el uso de una función de construcción o
constructor.

Por ejemplo este es el aspecto que tiene la clase cola cuando se modifica para utilizar las
iniciaciones:

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
void ponent(int i);
int quitaent(void);
};
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 34
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Obsérvese que no se especifica un tipo de dato proporcionado para el constructor cola(). En


C++, los constructores pueden proporcionar valores.

La función cola() se codifica de la siguiente manera:

cola::cola(void)
{
posfin=posprin=0;
cout<<"la cola ya tiene valores iniciales \n";
}

La función de construcción de un objeto se invoca cuando se crea el objeto. Esto significa


que se invoca cuando se ejecuta la declaración del objeto. Además, para los objetos locales,
el constructor se invoca cada vez que se llega a la declaración del objeto.

Como lo dice el nombre, un constructor es una función que se utiliza para construir un
objeto de una clase dada; esto puede implicar la presencia de diferentes escenarios.

1.- Creación de objetos con iniciación definida.


2.- Creación de objetos con iniciación especifica.
3.- Creación de objetos copiando otro objeto.

Cada uno de estos procesos implica un tipo diferente de constructor. Un constructor tiene el
nombre de la clase a la que pertenece.

Un sub objeto es un objeto de clase que se declara dentro de otra clase. Cuando se tiene una
instancia en una clase, su constructor debe crear un objeto de esa clase. Si la clase tiene sub
objetos declarados en ella, el constructor tiene que invocar los constructores de estos
objetos. Considere el ejemplo siguiente.

class counter
{
int value;
public:
Counter() { value = 0; }
};

class Example
{
int value;
public:
Counter cars;
Example() { value = 0; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 35


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
Example e;
}

Cuando se crea el objeto e en main(), se llama al constructor de la clase Example; en este


caso, la función Example::Example() antes de ejecutar su cuerpo, invoca al constructor
Counter::Counter() del sub objeto cars. Cuando se completa este constructor, se ejecuta el
cuerpo de Example::Example().

2.6.1 CONSTRUCTORES PRIVATE.

Obsérvese que el constructor anterior aparece en la sección public de la clase; este no es un


requisito, pero normalmente es el caso.

Un constructor private, impediría que los usuarios genéricos crearan objetos a partir de esa
clase y forzarán el cumplimiento de una de las condiciones siguientes antes de que se pueda
crear un objeto.

1. Un miembro estático de la clase invoca al constructor.


2. Una clase friend de esa clase invoca al constructor.
3. Un objeto existente de la clase tiene una función miembro que crea nuevos
objetos invocando al constructor.

2.6.2 CONSTRUCTORES CON ARGUMENTOS.

La función básica de un constructor consiste en inicializar un objeto antes de usarlo.

Counter(long);

Counter::Counter(long value)
{
count = value;
}

void main()
{
Counter object(5);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 36


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Observe los paréntesis después del nombre de la variable, que hacen que la definición del
objeto se asemeje a una llamada a función. La definición del objeto es en realidad una
llamada a función con argumentos.

Suponga que desea crear una clase counter que sea lo suficientemente flexible para aceptar
cualquier tipo de inicialización, utilizando elementos float, long, int, cadena o incluso
ningún argumento. Estas son las construcciones que se deben declarar.

class Counter
{
public:
Counter(int = 0);
Counter(long);
Counter(double);
Counter(char *);
};

// declaración de constructores.
Counter::Counter(long val_inic)
{
count = val_inic;
}

Counter::Counter(double val_inic)
{
count = val_inic;
}

Counter::Counter(char* val_inic)
{
count = atol(val_inic);
}

// uso de los constructores.


void main()
{
Counter Object(“5”); // Utilizando constructor char*
Counter Object1(5); // Utilizando constructor int
Counter Object2(5L); // Utilizando constructor long
Counter Object3(5.0); // Utilizando constructor double
Counter Object4(); // Utilizando constructor por omisión
}

El compilador puede determinar automáticamente a que constructor llamar en cada caso


examinando los argumentos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 37


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.6.3 CONSTRUCTORES PARA COPIAR OBJETOS.

Cuando se crea un objeto, a menudo no se desea inicializar ningún valor de manera


específica; simplemente se desea que un objeto “sea como otro”. Esto implica hacer una
copia de un objeto preexistente, lo cual requiere un tipo especial de construcción, llamada
en general: constructor de copia. Ejemplo.

class Counter
{
.
.
.
public:
Counter(Counter&);
.
.
};

Counter::Counter(Counter &referencia)
{
count = referencia.count;
}

void main()
{
Counter Object(5); // Constructor entero
Counter Object1 = Object; // Constructor de copia
}

2.7 DESTRUCTORES.

Los destructores entran en la misma categoría que los constructores. Se utilizan para
realizar ciertas operaciones que son necesarias cuando ya no se utiliza un objeto como es la
liberación de memoria.

Existen algunas diferencias importantes entre los constructores y los destructores:

1.- Los destructores pueden ser virtuales, los constructores NO.


2.- A los destructores no se les puede mandar argumentos.
3.- Sólo se puede declarar un destructor para una clase dada.

El destructor se nombra como la clase pero este va precedido de un tilde (~).

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 38


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Se podría escribir una clase que se encargue de manejar todas las gráficas generadas por un
programa de la siguiente manera:

class Graphics
{
public:
Graphics();
~Graphics();
void DrawCircle(int x, int y, int radio);
void DrawDot(int x, int y);
};

El destructor se utiliza para cerrar el dispositivo gráfico y rechazar cualquier espacio de


memoria asignado al objeto.

Por ejemplo vea la clase cola con su constructor y destructor (en el ejemplo de la clase cola
no es necesario un destructor, pero en este caso se pone para ejemplificar su uso).

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
~cola(void); // este es el destructor de la clase cola
void ponent(int i);
int quitaent(void);
};

// Función de Construcción
cola::cola(void)
{
posfin=0;
posprin=0;
}

// Función de destrucción.
cola::~cola(void)
{
cout<<"la cola ha sido destruida \n";
}

Veamos como funcionan los constructores y destructores en la nueva versión del programa
que crea una cola.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 39


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
~cola(void); // este es el destructor de la clase cola
void ponent(int i);
int quitaent(void);
};

main(void)
{
cola a, b;
a.ponent(15);
b.ponent(39);
a.ponent(55);
b.ponent(19);
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
return 0;
}
// Función de Construcción
cola::cola(void)
{
posfin=0;
posprin=0;
cout<<"La cola ya tiene valores iniciales \n"
}
// Función de destrucción.
cola::~cola(void)
{
cout<<"La cola ha sido destruida \n";
}
void cola::ponent(int i)
{
if(posfin>=100)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 40


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int cola::quitaent(void)
{
if(posfin==posprin)
{
cout<<"la cola está vacía";
return 0;
}
posprin++;
return c[posprin];
}

Este programa da como resultado lo siguiente:

La cola ya tiene valores iniciales.


La cola ya tiene valores iniciales.
15 39
55 19
La cola ha sido destruida.
La cola ha sido destruida.

2.8 CLASES AMIGAS (Palabra reservada friend)

A veces se necesitan 2 clases que son tan conceptualmente cercanas que usted desearía que
una de ellas tuviera acceso irrestricto a los miembros de la otra. Considere la implantación
de una lista asociada: necesita una clase que represente nodos individuales, y una que se
encargue de la lista misma. El acceso a los miembros de la lista es a través del manejador
de la misma, pero el manejador debe tener acceso absoluto a los miembros de la clase o una
función. Una clase que no ha sido declarada aún se puede definir como friend de esta
manera:

class Node
{
friend class ObjectList;
int value;
Node* Predecesor;
Node* Sucesor;
public:
void value(int i)
{
value = i;
}

};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 41


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class ObjectList
{
Node* head;
Node* tail;
Node* current;
public:
void InsertNode(Node * ) {}
void DeleteNode(Node *) {}
int CurrentObject(Node* node) { return node->value;}
};

2.8.1 FUNCIONES AMIGAS.

Es posible que una función de una clase que no sea un miembro tenga acceso a las partes
privadas de esa clase, declarando que se trata de un friend (amigo) de esa clase. Por
ejemplo amg() se declara como friend de la class C1

Class C1
{
.
.
.
public:
friend void amg(void);
.
.
.
};

Como se puede ver, la palabra reservada friend precede a toda la declaración de la función,
que es lo que se hace en general.

La razón por la cual se permite en C++ las funciones friend es la de resolver situaciones en
las cuales dos clases deban compartir una misma función, para así aumentar la eficiencia.
Para ver un ejemplo, consideremos un programa que defina dos clases llamadas linea y
recuadro. La clase linea contiene todos los datos y código necesarios para dibujar una línea
horizontal discontinua de cualquier longitud, empezando en la coordenada X, Y que se
indique y utilizando un color especificado, La clase recuadro contiene todo el código y los
datos necesarios para dibujar un recuadro en las coordenadas especificadas para la esquina
superior izquierda y para la esquina inferior derecha, y con el color que se indique. Las dos
clases tienen la misma función mismo_color() para determinar si una línea y un recuadro
están pintados del mismo color. Las clases se declaran según se muestra a continuación:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 42


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class linea;

class recuadro
{
int color;
int xsup, ysup;
int xinf, yinf;
public:
friend int mismo_color(linea l, recuadro b);
void pon_color(int c);
void definir_recuadro(int x1, int y1, int x2, int y2);
void mostrar_recuadro(void);
};

class linea
{
int color;
int xinicial, yinicial;
int longitud;
public:
friend int mismo_color(linea l, recuadro b);
void pon_color(int c);
void definir_linea(int x, int y, int l);
void mostrar_linea();
};

La función mismo_color(), que no es miembro de ninguna de ellas pero es friend de ambas,


proporciona un valor verdadero si tanto el objeto línea como el objeto recuadro, que son sus
argumentos, se dibujan del mismo color; en caso contrario, proporciona un valor nulo. La
función mismo_color se muestra a continuación:

Int mismo_color(linea l, recuadro b)


{
if(l.color == b.color)
return 1;
return 0;
}

También puede declarar una función no miembro como friend antes que el identificador de
la función esté en el campo de acción. Por ejemplo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 43


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Node
{
friend int GetObject(Node*);
int value;
Node* Predecesor;
Node* Sucesor;

public:
void value(int i){ value = i; }
};

int GetObject(Node* n)
{
return n->value;
}

2.8.2 PROPIEDADES DE LA PALABRA RESERVADA friend.

Las funciones y clases declaradas friend para otras clases gozan de privilegios especiales.
Si la función FUN0() es un elemento friend de la clase B y la clase B se deriva de la clase
A. FUN0(), tiene acceso también a los miembros de datos de las clases A, B, y C:

class A
{
friend class FRIEND;
int a1;
protected:
int a2;
public:
int a3;
};

class B
{
int b1;
protected:
friend class FRIEND;
int b2;
public:
int a3;
};

La clase friend puede tener acceso a todos los miembros de datos de C.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 44


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class C
{
int c1;
protected:
int c2;
public:
friend class FRIEND;
int c3;
};

2.9 HERENCIA

La herencia es uno de los rasgos fundamentales de un lenguaje de programación orientado a


objetos. En C++, la herencia se basa en permitir que una clase contenga a otra clase en su
declaración; supongamos una clase Figura:

Class Figura{
.
.
public:
.
.
};

Una clase derivada Figura_Circulo se declara así.

Class Figura_Circulo:public Figura


{
public:
.
private:
double x_centro, y_centr;
double radio;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 45


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La declaración general de la herencia es la que se muestra a continuación:

Class Nombre_de_la_clase_nueva : acceso clase_heredada


{
.
.
.
};

Aquí acceso es opcional, sin embargo, si está presente tiene que ser public, private o
protected.

El uso de public significa que todos los elementos public del antecesor también serán public
para la clase que lo hereda.

El siguiente ejemplo muestra 2 clases donde la segunda de ellas hereda las propiedades de
la primera.

class Box
{
public:
int width, height;
void SetWidth(int w) { width = w; }
void SetHeight(int h) { height = h; }
};

class ColoredBox:public Box


{
public:
int color;
void Setcolor(int c) { color = c; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 46


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La clase Box recibe el nombre de clase base de la clase ColoredBox. Que a su vez recibe el
nombre de clase derivada. La clase Colored Box se declara solo con una función, pero
también hereda 2 funciones y 2 variables de su clase base. Así, se puede crear el código
siguiente:

ColoredBox Cb; // se crea una instancia de ColoredBox

void main()
{
Cb.Setcolor(5); // función miembro de ColoredBox.
Cb.SetWidth(30); // función heredada.
Cb.setHeight(50); // función heredada.
}

Observe como las funciones heredadas se utilizan exactamente como si fueran miembro.

2.9.1 LIMITACIONES DE LA HERENCIA.

Cómo y cuándo se deriva una clase de otra es puramente decisión del programador. Esto
puede parecer obvio, pero es una limitación. El diseñador de un programa debe decidir al
momento de la compilación quien hereda qué, de quién, cómo y cuándo se lleva a cabo la
herencia.

2.9.2 QUE NO SE PUEDE HEREDAR.

Tal y como en la vida real, en C++ no todo se puede transmitir a través de la herencia. Esto
se puede considerar en un principio como una desventaja o limitación, pero en realidad solo
algunos casos especiales inconsistentes por definición con la herencia:

1.- Constructores.
2.- Destructores.
3.- Nuevos operadores definidos por el usuario.
4.- Relaciones friend.

El constructor de una clase de base no puede ser invocado de manera explícita en una clase
derivada como otras funciones heredadas. Considere el código siguiente:
class Parent
{
int value;
public:
Continua…
Parent(){ value = 0; }
Parent(int v){ value = 0; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 47


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Child:public Parent


{
int total;
public:
Child(int t) { total = t; }
void SetTotal(int t);
};

void Child::SetTotal(int t)
{
Parent::Parent(i); // Esto no se puede hacer, ya que el constructor de la
// clase no es heredado como otras funciones.
Total = t;
}

De manera análoga, los destructores están diseñados para ser invocados automáticamente
cuando un objeto sale del campo de acción.

La relación friend no es heredada. Esto es similar a la vida real; los amigos de sus padres no
son automáticamente amigos suyos.

2.9.3 HERENCIA MULTIPLE.

Una clase puede heredar los atributos de dos o más clases. Para lograr esto, se utiliza una
lista de herencia separada mediante comas en la lista de clases base de la clase derivada. La
forma General es:

Class Nombre_clase_derivada : lista de clases base


{
.
.
.
};

Por ejemplo en este programa Z hereda tanto a X como a Y.

# include <iostream.h>
class X
{
protected:
int a;
public:
void hacer_a(int i);
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 48


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Y
{
protected:
int b;
public:
void hacer_b(int i);
};

// Z hereda tanto a X como a Y

class Z : public X, public Y


{
public:
hacer_ab(void);
};
void X::hacer_a(int i)
{
a = i;
}
void Y::hacer_b(int i)
{
b = i;
}
int Z::hacer_ab(void)
{
return a*b;
}

main(void)
{
Z var;
var.hacer_a(10);
var.hacer_b(25);
cout << var.hacer_ab();
return 0;
}

En este ejemplo, Z tiene acceso a las partes public y protected tanto de X como de Y.
Remarcando, una clase puede tener muchos padres y heredar propiedades de cada una de
sus clases base. Considere crear una clase MesaRedonda, que no solo tenga las propiedades
de las mesas, sino también la característica geométrica de ser redonda.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 49


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>
class Circle
{
float radio;
public:
Circle(float r){ radio = r; }
Float Area(){ return radio*radio*3.1416; }
};

class Mesa
{
float height;
public:
Mesa(float h) { height = h; }
float Height() { return height; }
};

class MesaRedonda:public Mesa, public Circle


{
int color;
public:
MesaRedonda(float h, float r, int c);
int Color() { return color; }
};

MesaRedonda::MesaRedonda(float h, float r, int c): Circle(r),Mesa(h)


{
color = c;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 50


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
MesaRedonda Mesa1(15.0, 3.0, 5);
printf("\n Las propiedades de la Mesa son:");
printf("\n Altura = %f ", Mesa.Height());
printf("\n Area = %f ", Mesa.Area());
printf("\n Color = %d ", Mesa.Color());
}

La función main() invoca las tres funciones miembro MesaRedonda::Height(),


MesaRedonda::Area() y MesaRedonda::Color(). Todo sin indicar cuales son funciones
heredadas y cuales no.

2.9.4 USO DE CLASES DE BASE VIRTUAL.

Las clases de base virtual se utilizan sólo en el contexto de la herencia múltiple. Dada la
complejidad de relaciones que pueden surgir en un árbol de herencia construido en torno a
la herencia múltiple, existen situaciones en las que el programador necesita tener cierto
nivel de control sobre la forma en que se heredan las clases de base. Considere el árbol de
herencia de la siguiente figura.

La clase D tiene a A como clase de base. El problema es que hay dos clases A diferentes
que aparecen como clases de base de D, cada una con datos propios.

Esto se ejemplifica con el siguiente código.

class A
{
public:
int value;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 51


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class B : public A{};


class C : public A{};
class D : public B, public C
{
public:
int value()
{
return value;
}
};

El valor miembro de acceso a la instrucción en D es ambiguo. Borland C++ genera error.

Tener múltiples copias de la misma clase de base en árbol de herencia no sólo es confuso,
sino que puede ser un desperdicio de espacio de almacenamiento.

Declarar una base virtual resuelve el problema. Obliga al compilador a admitir sólo una
copia de la clase de base dada en la declaración de una clase derivada. Por lo tanto el
ejemplo anterior lo podemos corregir de la siguiente manera:

class B : public virtual A{};


class C : public virtual A{};
class D : public B, public C
{
public:
int value()
{
return value;
}
};

y el árbol de herencia quedaría como realmente lo deseamos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 52


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.10 SOBRECARGA.

Una de las maneras que tiene el C++ de llegar al polimorfismo es a través de la sobrecarga
de funciones. En C++ , dos o mas funciones pueden compartir un nombre, siempre y
cuando en la declaración, sus parámetros sean diferentes.

Sobrecarga se refiere a la práctica de cargar una función con más de un significado.


Básicamente, el término expresa que se cargan uno o más identificadores de función sobre
un identificador previo.

2.10.1 PORQUE USAR LA SOBRECARGA.

La sobrecarga no es un concepto nuevo en los lenguajes de programación, por ejemplo el


operador = está sobrecargado en muchos lenguajes de alto nivel y se utilizan en
instrucciones de asignación y en expresiones condicionales como:

a = b;
if( a = b)

La sobrecarga otorga flexibilidad, permite a las personas utilizar código con menos
esfuerzo, ya que extiende operaciones que son conceptualmente similares en naturaleza.

2.10.2 SOBRECARGA DE FUNCIONES.

Las funciones sobrecargadas se distinguen por el número y tipo de sus argumentos.

El tipo de retorno no se utiliza para distinguir funciones sobrecargadas, por lo tanto las
funciones:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 53


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void Muestra(int q);


long Muestra(int q);

No son distinguibles y producen un error del compilador.

Cualquier nombre de función puede ser sobrecargada en C++, pero la sobrecarga solo
funciona dentro de un campo de acción dado.

Cuando se declara en una clase más de una función miembro con el mismo nombre, se dice
que el nombre de la función está sobrecargado en esa clase, y su campo de acción será en el
ámbito de esa clase.

class Ejemplo
{
int value;
public:
void value(int v) { value = v; }
int value() { return value; }
};

void main()
{
Ejemplo Ee;
Ee.value(3);
Int i = Ee.value();
}

Este código demuestra que la clase Ejemplo tiene 2 funciones sobrecargadas: una función
para escribir y una para leer una variable.

Las funciones sobrecargadas necesitan diferir en una u otra o en las dos formas siguientes:

1.- Las funciones deben contener un número de argumentos diferente.


2.- Cuando menos uno de los argumentos debe ser diferente.

Considere el siguiente programa en el cual la función al_cuadrado se sobrecarga 3 veces.

# include<iostream.h>
int al_cuadrado(int i);
double al_cuadrado(double d);
long al_cuadrado(long l);

main(void)
{
cout << al_cuadrado(10) <<" \n";
cout << al_cuadrado(1.25) <<" \n";

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 54


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

cout << al_cuadrado(9L) <<" \n";


return 0;
}

int al_cuadrado(int i)
{
cout<<" función al_cuadrado con parámetro entero"
return i*i;
}

double al_cuadrado(double d)
{
cout<<" función al_cuadrado con parámetro doble"
return d*d;
}

long al_cuadrado(long l)
{
cout<<" función al_cuadrado con parámetro largo"
return l*l;
}

La ventaja de sobrecargar las funciones es que permite acceder a conjuntos de funciones


que están relacionadas utilizando un solo nombre. En el programa anterior se crean 3
funciones similares que se llaman, al_cuadrado(), y cada una de las cuales regresa el
cuadrado de su argumento; en cierto sentido, la sobrecarga de funciones permite crear un
nombre genérico para alguna operación, y el compilador resuelve que función es la
adecuada para llevar a cabo la operación.

Así, al_cuadrado(), representa la acción general que se realiza; el programador solo necesita
recordar la acción general que se lleva a cabo, por lo tanto al aplicar el polimorfismo se han
reducido a una las 3 cosas que había que recordar. Aunque este ejemplo es bastante trivial,
si expande el concepto se puede ver que el polimorfismo puede ayudarnos a entender
programas muy complejos.

Para sobrecargar la función de construcción de una clase, solo hay que declarar las
diferentes formas que tiene que adoptar y hay que definir su acción con respecto a esas
formas. Por ejemplo el programa siguiente declara una clase llamada temporizador, que se
comporta como un temporizador descendente. Cuando se crea un objeto del tipo
temporizador, se le da un valor inicial de la hora. Cuando se invoca a la función ejecutar(),
el temporizador cuenta hasta llegar a cero, y hace sonar el timbre. En ese ejemplo, se ha
sobrecargado el constructor para especificar la hora como un entero, como una cadena, o
como dos enteros que especifican los minutos y los segundos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 55


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

# include <iostream.h>
# include <stdlib.h>
# include <time.h>
class temporizador
{
int segundos;
public:
// Se especifican los segundos como una cadena.
temporizador(char *t) {segundos = atoi(t);}
// Se especifican los segundos como un entero
temporizador(int t) {segundos = t;}
// Se especifica la hora en minutos y segundos
temporizador(int min, int seg) {segundos = min* 60 + seg; }
void ejecutar(void);
};

void temporizador::ejecutar(void)
{
clock_t t1, t2;
t1 = t2 = clock()/CLK_TCK;
while(segundos)
{
if(t1/CLK_TCK+1 <= (t2=clock()) /CLK_TCK)
{
segundos --;
t1 = t2;
}
}
cout << "\a"; // toca el timbre
}

main(void)
{
temporizador a(10), b("20"), c(1, 10);
a.ejecutar(); // cuenta 10 segundos
b.ejecutar(); // cuenta 20 segundos
c.ejecutar(); //cuenta 1 minuto, 10 segundos
return 0;
}

Como se puede ver, cuando a, b, y c se crean dentro de main(), se les dan valores iniciales
utilizando los tres métodos diferentes que admiten las funciones de construcción
sobrecargadas.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 56


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.10.3 CONSTRUCTORES SOBRECARGADOS.

Uno de los usos más comunes de la sobrecarga de funciones es con los constructores. La
razón es que cuando se instancía una clase, se deben conservar las cosas lo más flexibles
que sea posible; de modo que los usuarios pueden realizar diferentes clases de instancias.

Considere una clase ventana desplegable en una interfaz gráfica de usuario.

PopupWindow Window; // Genera una ventana con parámetros por


// omisión.
PopupWindow Window_1(x, y); // Genera una ventana con coordenadas
// específicas.
PopupWindow Window_2(x, y, width, Height); // Genera una ventana con
// dimensiones controladas.
PopupWindow Window_3 = Window_2; // Genera una ventana igual a la
// anterior.

La implantación de esta clase podría parecerse al siguiente código.

class PopupWindow
{
Int x, y, Width, Height;
public:
PopupWindow();
PopupWindow(int, int);
PopupWindow(int, int, int, int);
PopupWindow(PopupWindow&);
};

PopupWindow:: PopupWindow()
{
x = y = 100;
Widht = Heigth = 100;
}

PopupWindow:: PopupWindow(int px, int py)


{
x = px;
y = py;
Widht = Heigth = 100;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 57


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

PopupWindow:: PopupWindow(int px,int py, int w, ,int h)


{
x = px;
y = py;
Widht = w;
Heigth = h;
}

PopupWindow:: PopupWindow(PopupWindow& pw)


{
x = pw.x;
y = pw.y;
Widht = pw.Widht;
Heigth = pw.Height;
}

La clase utiliza cuatro funciones sobrecargadas que realizan el trabajo.

Con constructores sobrecargados, usted puede permitir que el usuario especifique qué
variables han de ser inicializadas de manera explícita y cuales deben asumir valores
definidos.

2.10.4 SOBRECARGA DE OPERADORES.

Otra forma en que se logra el polimorfismo en C++ es mediante la sobrecarga de


operadores. En general se puede sobrecargar cualquiera de los operadores de C++
definiendo lo que significa con respecto a una cierta clase.

Aunque los operadores están asociados comúnmente con operaciones matemáticas o


lógicas, simplemente son una notación alternativa para una llamada a una función

La sobrecarga de operadores se utiliza en otros lenguajes de programación, pero sin un


nombre especial. En algunos lenguajes como Pascal, es posible hacer lo siguiente:

StructureA := structureB + structureC;

Lo que da lugar a una adición byte por byte de las estructuras b y c que se copiarán en la
estructura a. Esta sintaxis implica que el operador de adición está sobrecargado para
estructuras, aunque con ciertas reglas de apego a tipos. En el ejemplo anterior se utiliza
también un operador de asignación sobrecargado, ya que la instrucción y no una asignación
escalar definida, fue la que activó una operación de copia de estructuras.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 58


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.10.4.1 OPERADORES COMO LLAMADAS A FUNCION.

Hay dos formas en las que se pueden implantar operadores para objetos de clase: como
funciones miembro y como amigos. Un operador unario aplicado a un objeto es equivalen
te a una llamada a una función. Dados un objeto W y un operador unario @ , la expresión
@W es equivalente a las llamadas a funciones:

W.operator@() // uso de un operador con función miembro.


operator@(W) // uso de un operador con función friend.

Un operador binario aplicado a los objetos es equivalente también a una llamada a función.

Dados los objetos X y Y, y un operador @, la expresión X @ Y es equivalente a las


llamadas a funciónes:

X.opertor@(Y) // uso de un operador con función miembro.


Operator@(X, Y) // uso de un operador con función friend.

El código anterior demuestra que los operadores pueden invocar dos funciones diferentes;
una función que es miembro y otra que es amigo.

2.10.4.2 OPERADORES SOBRECARGADOS COMO FUNCIONES


MIEMBRO.

Las funciones que implantan operadores son un tanto inusuales. Para comenzar, sus
nombres deben comenzar con la cadena operator, seguida de los caracteres que representan
el operador que se implanta. Por ejemplo la función miembro para implantar el operador de
adición tendría que llamarse operator+ . La segunda restricción se aplica al número de
argumentos que pueden tomar estas funciones. Las funciones miembro que implantan
operadores unarios no deben tomar argumentos, en tanto que las que implantan operadores
binarios pueden tomar solo un argumento.

El siguiente código muestra operadores sobrecargados implantados como funciones


miembro.

class Counter
{
public:
int value;
Counter(int i)
{
value = i;
}
Counter operator!(); // operador unario.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 59


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Counter operator+(Counter & c); // operador binario.


};

Counter Counter::operator!()
{
return Counter( ! value );
}

Counter Counter::operator+( Counter & c)


{
return Counter( value + c.value);
}

void main()
{
Counter c1(3), c2(5); // se crean 2 objetos tipo counter.
c1 = ! c1; // se aplica el operador unario
c1 = c1 + c2; // se aplica el operador binario
}

El uso de los operadores en la función main() es completamente intuitivo, y no requiere que


el usuario conozca los detalles de la implantación de clases para averiguar cual será el
recultado de las operaciones.

La restricción en el número de argumentos (solamente uno), limita las posibilidades; pero


esto lo podemos resolver sobrecargando el mismo operador tantas veces como sea
necesario, vea un ejemplo de como se sobrecarga el operador de adición tres veces.

class M
{
public:
int value;
M(int i) { value = i; }
M operator+(M& m);
M operator+(int i);
M operator+(double d);
};

M M::operator+(M& m)
{
return M(value + m.value);
}

M M::operator+(int i)
{
return M(value + i);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 60


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

M M::operator+(double d)
{
returnM(value + d);
}

void main()
{
M m1(3), m2(10); // se crean dos objetos de clase M.
m1 = m1 + m2; // uso M::operator+(M&)
m1 = m2 + 200; // uso M::operator+(int)
m1 = m2 + 3.14159; // uso M::operator+(double)
}

2.10.4.3 OPERADORES SOBRECARGADOS COMO FUNCIONES FRIEND.

En el siguiente ejemplo el operador + se declara como función friend y el operador = como


función miembro de la clase X, ya que el operador = solo puede sobrecargarse como
función miembro, lo que implica que el operador = global no puede ser sobrecargado. Los
diseñadores del lenguaje decidieron que permitir que las funciones friend cambiaran el
significado del operador de asignación causaría mas problemas de los que resolvería.

class X
{
friend X operator+(X&, X&);
public:
int value;
X(int i) { value = i; }
X& operator = (X&);
};

X& X::operator = (X& b)


{
value = b.value;
return *this;
}

X operator+(X& a, X& b)
{
return X(a.value + b.value);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 61


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
X g(2), h(5), i(3);
G = h +h +i;
}

En general, los operadores friend sobrecargados se comportan de manera muy similar a las
funciones miembro.

2.11 POLIMORFISMO

El origen del término polimorfismo es simple: proviene de las palabras griegas poly
(muchos) y morphos (forma) multiforme. El polimorfismo describe la capacidad del código
C++ de comportarse de diferentes maneras dependiendo de situaciones que se presenten al
momento de la ejecución.

El concepto de polimorfismo es crucial para la programación orientada a objetos. En su


concepción relativa a C++, el término polimorfismo se utiliza para describir el proceso
mediante el cual se puede acceder a diferentes implementaciones de una función utilizando
el mismo nombre. Por esta razón el polimorfismo se define a veces mediante la frase “una
interface métodos múltiples”. Esto significa que en general se puede acceder a toda una
clase de operaciones de la misma manera, aunque las acciones concretas que estén
asociadas a cada una de las operaciones pueda ser diferente.

En C++, el polimorfismo se admite tanto en el momento de la ejecución como en el


momento de la compilación. La sobrecarga de operadores y de funciones es un ejemplo de
polimorfismo en el momento de la compilación. Sin embargo, aunque la sobrecarga de
operadores y de funciones son muy potentes, no pueden llevar a cabo todas las tareas que
requiere un verdadero lenguaje orientado a objetos. Por tanto, C++ permite también el
polimorfismo en el momento de la ejecución mediante el uso de clases derivadas y de
funciones virtuales.

2.11.1 FUNCIONES VIRTUALES.

El polimorfismo en el momento de la ejecución se consigue mediante el uso de tipos


derivados y funciones virtuales. En pocas palabras, una función virtual es una función que
se declara como virtual en una clase base y que se define en una o más clases derivadas.

Lo que hace especiales a las funciones virtual es que cuando se accede a una de ellas
utilizando un puntero de clase base señala a un objeto de clase derivada, C++ determina
qué función debe llamar en el momento de la ejecución, basándose en el tipo del objeto al
cual apunta. Por tanto, si apunta a diferentes objetos, se ejecutan versiones diferentes de la
función virtual.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 62


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Como ejemplo examine el siguiente código:

#include<iostream.h>
class Base
{
public:
virtual void quien() { cout << “Base \n”; }
};

class primera_deriv : public Base


{
public:
void quien() { cout << “ Primera derivación \n”; }
};

class seguna_deriv : public Base


{
public:
void quien() { cout << “ Segunda derivación \n”; }
};

main(void)
{
Base obj_base;
Base *p;
Primera_deriv obj_primera;
Segunda_deriv obj_segunda;
p = &obj_base;
p->quien();
p = &obj_primera;
p->quien();
p = &obj_segunda;
p->quien();
return 0;
}

El programa produce la siguiente salida.

Base
Primera derivación
Segunda derivación.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 63


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La clave de la utilización de funciones virtual para lograr el polimorfismo en el momento


de la ejecución es que se debe acceder a esas funciones mediante el uso de un puntero
declarado como puntero de la clase base.

Parte de la clave para aplicar con éxito el polimorfismo consiste en comprender que la base
y las clase derivadas forman una jerarquía, que va desde la mayor generalización a la menor.
Por tanto la clase base cuando se utiliza correctamente, proporciona todos los elementos
que puede utilizar directamente una clase derivada, mas aquellas funciones que la clase
derivada debe implementar por sí misma. Sin embargo dado que la forma de la interface
está determinada por la clase base todas las clases derivadas van a compartir esa interface .

El código siguiente utiliza la clase figura para derivar dos clase concretas llamadas cuadro y
triángulo.

#include<iostream.h>
class Figura
{
protected:
double x, y:
public:
void pon_dim(double I, double j) { x = I; y = j; }
virtual void mostrar_area() { cout << “función no implementada \n”;}
};

class triángulo : public Figura


{
public:
void mostrar_area()
{
cout<<”Triangulo de altura “ << x <<” y base ” << y << ”
y área ” x * y * 0.5;
}
};

class cuadrado : public Figura


{
public:
void mostrar_area()
{
cout << “Cuadrado de lado ” << x <<” por ” << y <<
“área = ” << x * y <<”\n”;
}
};

main (void )
{
Figura *p;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 64


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

triangulo trian;
cuadrado cuad;
p = &trian;
p->pon_dim(10.0, 5.0);
p->mostrar_area();
p = &cuad;
p->pon_dim(10.0, 5.0);
p->mostrar_area();
return 0;
}

Como se puede ver al examinar este programa, la interface de cuadrado y de triángulo es la


misma, aunque cada uno de ellos proporcione sus propios métodos para calcular el área de
cada uno de sus objetos.

2.12 EJEMPLOS DE PROGRAMACION ORIENTADA A OBJETOS

a) Este pequeño programa trata de calcular el área y la longitud de una circunferencia. Es


sencillo y usa clases e instancias.

#include<iostream>

using namespace std;

const double pi=3.141516;

class calcular
{
double radio,area,longitud;

public:
void iniciar(void);
void entradaDatos(void);
void salidaDatos(void);
} calcular1;

int main(void);
{
calcular calcular2;
calcular1.iniciar();
calcular2.iniciar();

calcular1.entradaDatos();
calcular2.entradaDatos();

calcular1.salidaDatos();
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 65
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

calcular2.salidaDatos();
return 0;
}

void calcular::iniciar(void)
{
cout <<"PROGRAMA QUE CALCULA EL AREA Y LONGITUD DE UNA
CIRCUNFERENCIA"<<"\n\n";
}

void calcular::entradaDatos(void)
{
cout<<"INTRODUZCA EL RADIO DE LA CIRCUNFERENCIA"<<"\n";
cin>>radio;

area=pi*radio*radio;
longitud=2*pi*radio;
}

void calcular::salidaDatos(void)
{
cout<<"AREA =\t\t" <<area <<"\n";
cout<<"LONGITUD =\t\t" <<area <<"\n\n";
}

b) El siguiente ejemplo implementa un Programa Orientado a Objetos donde el Esquema


de la clase se dispone en un archivo ‘ .h’, las interfaces en un segundo archivo ‘.cpp’ y la
creación de objetos en un archivo ‘.cpp’.

//implementacion del esquema de la clase


// se graba con una extension .h
//#include <stdlib.h>
class ejemplo
{
private:
int a,b,c;
public:
ejemplo(int,int);//funcion constructora
void leer(void);
void imprimir();
//las funciones set permiten asignar valores a datos privados
void seta(int);
void setb(int);
void setc(int);
//las funciones get permiten recuperar valores de datos privados
int geta();
int getb();

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 66


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int getc();
int mcd();
int producto(int,int);
};

//archivo que implementa las funciones de la clase ejemplo


// se graba con el nombre ejemplo.cpp

#include <iostream.h>
#include <d:/lab1sis2210/ejemplo.h>
ejemplo::ejemplo(int d1,int d2)
{
a=d1;
b=d2;
};
void ejemplo::leer()
{
cout<<"\n valor para la variable a:";
cin>>a;
cout<<"\n valor para la variable b:";
cin>>b;
}
void ejemplo::imprimir()
{
cout<<"\n valor para la variable a="<<a;
cout<<"\n valor para la variable b="<<b;
};

void ejemplo::seta(int d)
{
a=d;
}

void ejemplo::setb(int d)
{
b=d;
}

void ejemplo::setc(int d)
{
c=d;
}

int ejemplo::geta()
{
return a;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 67


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int ejemplo::getb()
{
return b;
}

int ejemplo::getc()
{
return c;
}

int ejemplo::mcd()
{
int n,m;
n=a;m=b;
while (n>0)
if (n>=m)
n=n-m;
else
m=m-n;
return m;
}
int ejemplo::producto(int x,int y)
{
int prod=0,cont=0;
while (cont<y)
{
prod=prod+x;
cont++;
};
return prod;
}

//implementa objetos a partir de la clase ejemplo


#include <iostream.h>
#include <conio.h>
#include <d:/lab1sis2210/ejemplo.cpp>
main()
{
ejemplo e(18,24); //se invoca a la funcion constructora
e.imprimir(); //invoca a la funcion imprimir del objeto e
getch();
cout<<"\n el maximo comun divisor es: "<<e.mcd();
cout<<"\n valor para la variable c:";
int dat;
cin>>dat;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 68


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

e.setc(dat);
cout<<"\n valor de la variable c:"<<e.getc();
cout<<"\n el producto es:"<<e.producto(e.geta(),e.getc());

return 0;
}

c) El ejemplo siguiente implementa una jerarquía de clase e ilustra la herencia y el


polimorfismo.

//implementacion de una jerarqui de clases


//se graba con el nombre 'herencia.h'
#include <stdlib.h>
class persona
{
private:
int ci;
char nombre[30];
int edad;
public:
virtual void leer();
virtual void impre();
};

class estudiante:public persona


{
private:
char carrera[15];
public:
virtual void leer();
virtual void impre();
};
class docente:public persona
{
private:
float salario;
public:
virtual void leer();
virtual void impre();
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 69


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

//implementa las interfaces de la jerarquia de clases.


// se graba con el nombre 'herencia.cpp'

#include <d:/lab2sis2210/herencia.h>
#include <iostream.h>
void persona::leer()
{
cout<<"\n introducir C.I.:";
cin>>ci;
cout<<"\n introducir Nombre:";
cin>>nombre;
cout<<"\n introducir Edad:";
cin>>edad;
}
void persona::impre()
{
cout<<"\n C.I.:"<<ci;
cout<<"\n Nombre:"<<nombre;
cout<<"\n Edad:"<<edad;
}
void estudiante::leer()
{
persona::leer();
cout<<"\n Introducir carrera:";
cin>>carrera;
};
void estudiante::impre()
{
persona::impre();
cout<<"\n Carrera:"<<carrera;
}
void docente::leer()
{
persona::leer();
cout<<"\n Introducir Salario:";
cin>>salario;
};
void docente::impre()
{
persona::impre();
cout<<"\n Salario:"<<salario;
}

//implementa objetos a partir de las clases definidas en 'herencia.h' y 'herencia.cpp'

#include <d:/lab2sis2210/herencia.cpp>
#include <iostream.h>

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 70


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <conio.h>
void main()
{
persona p;
//cout<<"\n tamaño de un entero :"<<sizeof(int);
/*p.leer();
p.impre();
estudiante e;
e.leer();
e.impre();

docente d;
d.leer();
d.impre();*/
persona *a[5];
int i,tipo,n;
cout<<"\n cantidad de personas:";
cin>>n;
for (i=0;i<n;i++)
{
cout<<"\n tipo : ESTUDIANTE = 0 , DOCENTE = 1 ?:";
cin>>tipo;
if (tipo==0)
a[i]=new estudiante;
else
a[i]=new docente;
a[i]->leer();
};
cout<<"\n contenido del vector:";
for (i=0;i<n;i++)
a[i]->impre();
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 71


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 3

INTRODUCCION A LAS ESTRUCTURAS DE DATOS ESTATICAS

La implementación de una aplicación computacional requiere la especificación de un


conjunto de variables u objetos que sustentan la información a procesar, el programa
contiene elementos abstractos, que durante la ejecución del mismo, almacenaran los valores
con los cuales se desarrollan los diferentes cálculos para la obtención de los resultados
deseados. La forma que el analista configura los elementos abstractos para el
almacenamiento de datos se denomina Estructura de datos del Programa y se los puede
definir de la siguiente manera:

 Una estructura de Datos es toda forma particular de organizar la información en la


memoria con fines de procesamiento.
 Una Estructura de datos es el modelo lógico de la representación física de los datos
en la memoria.
 Una estructura de Datos es la forma de establecer y configurar el conjunto de
variables que se constituyen en el sustento de los datos en la memoria durante la
ejecución de la aplicación.

3.1. CLASIFICACIÓN DE LOS TIPOS DE DATOS SEGÚN SU


ESTRUCTURA
La s Estructura de datos se pueden clasificar en dos tipos genéricos:

 Simples: Los tipos simples son cuando cada dato representa un único elemento

Estándar: Están definidos por defecto por el lenguaje


entero, real, carácter, booleano

No estándar: Tipos simples definidos por el usuario


enumeración, subrango

 Estructurados: son cuándo un dato es una estructura que se construyen a partir de


otros complementos.

Estáticos: Ocupan un tamaño de memoria fijo, que se tiene que definir antes de
declararlo.
arrays, cadena, registros, ficheros, conjuntos

Dinámicos: La estructura no ocupa un tamaño fijo de memoria, sino que ocupa la


memoria que ocupa en cada momento. Se van a manejar a través del tipo de dato
puntero.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 72


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Puntero: Es una variable cuyo contenido es una dirección de memoria y esa


dirección de memoria corresponde a la dirección de memoria de otra variable, que
es la variable apuntada.

punteros, listas enlazadas, árboles, grafos

En el presente capítulo se hace énfasis en la estructura de datos más importante y


fundamental en el procesamiento de la información, los arreglos.

3.2. ARREGLOS.

Un arreglo se define como un conjunto finito, ordenado y homogéneo de celdas de


memoria referenciadas por un nombre único, nombre del arreglo, y que pueden almacenar
datos del mismo tipo.

Es finito porque tiene un número determinado de elementos. Es Homogéneo porque todos


los elementos almacenados van a ser del mismo tipo. Es Ordenado porque se puede acceder
a cada elemento del array de manera independiente, porque va a haber una forma de
referenciar a cada elemento (celda). Para referenciar cada elemento de un array se emplea
índices (valor que directa o indirectamente referencia la posición del array).

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 73


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

3.2.1. ARREGLOS UNIDIMENSIONALES. VECTORES.

Un arreglo (array) unimensional, conocido también como Vector, se caracteriza porque


requiere un solo índice o subíndice parea referencias a un elemento o una celda del
conjunto total disponible.

Para referenciar un elemento de un array se emplea el nombre del array y entre corchetes [ ]
el índice que determina la posición de ese elemento en el array.

Nombre_array[numero_celda]

El rango o longitud de un vector o array lineal es la diferencia entre el índice de valor


máximo y el índice de valor mínimo de ese array + 1. Normalmente los índices comienzan
a enumerarse, es decir, el valor mínimo del índice es 0 ó 1, dependiendo del lenguaje (en
Pascal con 1 y en C con 0). Sin embargo nadie impide que comiencen en cualquier otro
valor.

Los arrays se almacenan siempre en posiciones consecutivas de memoria y se puede


acceder a cada elemento del array de manera independiente a través de los índices. Un
índice no tiene por qué ser un valor constante, sino que puede ser también una variable o
una expresión que al ser evaluada devuelva ese índice.

3.2.1.1. DECLARACIÓN DE UN ARRAY UNIDIMENSIONAL: VECTOR:

La declaración es muy similar a la declaración de cualquier tipo de dato simple, debiendo


adicionar la especificación de la cantidad de celdas que conformaran el vector con un
número entero positivo entre corchetes.

Tipo_dato nombre_arreglo[tamaño]

Ejemplo:

int a[100];

‘a’ es un arreglo unidimensional con 100 celdas disponibles, numeradas desde la 0


hasta la 99 y que puede almacenar datos enteros únicamente.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 74


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float b[30];

‘b’ es un arreglo unidimensional con 30 celdas disponibles, numeradas desde la 0


hasta la 29 y que puede almacenar datos reales únicamente.

char nom[45];

‘nom’ es un arreglo unidimensional con 45 celdas disponibles, numeradas desde la 0


hasta la 44 y que puede almacenar datos tipo carácter únicamente.

3.2.1.2. ALMACENAMIENTO DE DATOS EN UN VECTOR.

El almacenamiento de datos en un vector es el proceso mediante el cual se depositan los


valores, es decir datos, en las diferentes celas del arreglo, esta operación se puede realizar
de 3 formas:

a) Por inicialización en la declaración del arreglos.

Esta forma de almacenamiento es muy frecuente cuando se dese que los datos
almacenados en el vector siempre sean los mismos al empezar la ejecución de la
aplicación.

Los datos se almacenan antes de la ejecución del programa, es decir, en proceso de


compilación.

Ejemplo:

int a[10]={4,8,3,9};

Los cuatro valores inicializan las primeras cuatro celdas del vector. Las
celdas restantes del vector que no son inicializadas toman el valor 0 por
defecto:

b) por una función de asignación.

Esta forma de almacenamiento de datos se emplea cuando:


o La aplicación se está ejecutando.
o Los datos a almacenar se generan internamente por medio de una función
específica, la más usual la función ‘random’, datos aleatorios.
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 75
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

o Cada vez que se ejecuta la aplicación, los datos que se almacena en el vector
pueden ser o no los mismos.

Ejemplo:

for (i=0;i<10;i++)
a[i]= random(20);

En las 10 celdas del vector ‘a’, desde la 0 hasta la 9, se almacenan valores


aleatorios generados por medio de la función ‘random’.

c) Por una función de entrada de datos.

Los datos que almacenan en el vector, se introducen por el usuario desde el teclado durante
la ejecución del programa.

Se emplea dominantemente cuando se desea almacenar un conjunto reducido de datos y de


acuerdo a la necesidad del usuario para la ejecución del programa.

Ejemplo:

for (i=0;i<10;i++)
cin>>a[i];

En las 10 celdas del vector ‘a’, desde la 0 hasta la 9, se almacenan valores


introducidos desde el teclado por medio de la función ‘cin’.

Una vez que los datos están almacenados en el vector, estos se encuentran disponibles para
el procesamiento durante toda la ejecución del programa.

3.2.1.3. MANEJO DE VECTORES DESDE UNA APLIACION OO.

El procesamiento de datos almacenados en un vector desde una aplicación orientada a


Objetos supone que de manera previa se realizan las siguientes actividades:

 Especificación del diagrama de la clase


 Implementación de la clase.
 Implementación de las funciones de la clase
 Desarrollo de una aplicación que utiliza objetos del tipo vector.

Estos pasos genéricos contendrán características específicas de acuerdo al problema que se


desea resolver, por ejemplo una ilustración en el procesamiento de vectores podría ser la
siguiente:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 76


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

a) Diagrama de la clase ‘Tvector’

Dónde:
a[], es el nombre del vector que contiene la clase.
n, es la cantidad de celdas que almacenaran datos.
leer(), es la función que almacena datos en las ‘n’ primeras celdas
del vector.
imprimir(), es la función que muestra el contenido de las n primeras
celdas del vector.
buscar(), es la función que verifica si un vlor ‘clave’ esta o no en el
vector.

Nota: Si los datos a y n de la clase Tvector son Privados, entonces es


necesario incorporar las funciones ‘set’ y ‘get’ para el acceso a los mismos
desde otras clases.

b) Implementación del esquema de la clase.

La implementación del esquema de la clase se desarrolla en un archivo ‘.h’, para el


ejemplo que se plantea se tiene el siguiente código que se graba en un archivo
‘vector.h’

class Tvector
{
//private:
public:
int a[50];
int n;
public:
Tvector(int);
void setn(int);
int getn();
int geta(int);
void seta(int,int);
void leer();
void imprimir();

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 77


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int buscar(int);
//otras funciones de la clase vector
void qsort(int[],int,int);

};

c) Implementación de las funciones de la Clase.

Las funciones de una clase se implementan en un archivo ‘.cpp’ independiente, con


el fin de incorporar las características de la POO. Para el ejemplo que se desarrolla
en este capítulo, esta implementación considera las funciones ‘set’ y get’, debido a
que los datos a y n son privados y serán guardados en un archivo ‘vector.cpp’.

#include <d:/lab3sis2210/vector.h>
#include <iostream.h>
#include <stdlib.h>
Tvector::Tvector(int t)
{
n=t;
}
void Tvector::setn(int t)
{
n=t;
}
int Tvector::getn()
{
return n;
}
void Tvector::seta(int dat,int cel)
{
a[cel]=dat;
}
int Tvector::geta(int cel)
{
return a[cel];
}
void Tvector::leer()
{
int i;
randomize();
for (i=0;i<n;i++)
a[i]=random(20)+1;
}
void Tvector::imprimir()
{
int i;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 78


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

for (i=0;i<n;i++)
cout<<a[i]<<" , ";
cout<<"\n";
}
int Tvector::buscar(int dat)
{
//BUSQUEDA SECUENCIAL O LINEAL
int i=0;
while (i<n && dat!=a[i])
i++;
if (i==n)
return (-1);
else
return i;
}
Void Tvector::qsort(int x[],int p,int q)
{
if(p<q)
{
int piv=x[p];
int i=p,j=q+1;
while (i<j)
{
do {i++;} while (x[i]<=piv && i<=q);
do {j--;} while (x[j]>piv && j>=p);
if (i<j)
{
int aux=x[i];
x[i]=x[j];
x[j]=aux;
};
};
x[p]=x[j];
x[j]=piv;
qsort(x,p,j-1);
qsort(x,j+1,q);
};
}

d) Generación y uso de objetos a partir de la clase Tvector.

Se debe desarrollar otro programa ‘.cpp’ donde se crea objetos a partir de la clase
Tvector y se emplea las funciones del objeto creado para resolver un problema
determinado. En el ejemplo que se desarrolla el programa puede ser ‘vecprub.cpp’.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 79


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <d:/lab3sis2210/vector.cpp>
#include <stdlib.h>
#include <iostream.h>
int cant, resp;
main()
{

cout<<"\n tamaño del primer vector:";


cin>>cant;

Tvector v(cant);
v.leer();
v.imprimir();
cout<<"\n tamaño del segundo vector:";
cin>>cant;
Tvector k(cant);
k.leer();
k.imprimir();
// mostrar los elemento del vecto v que se encuentran en el vector k
Tvector r(20);
int i,j=0;
for (i=0;i<v.getn();i++)
if (k.verificar(v.geta(i))>=0)
{
r.seta(v.geta(i),j);
j++;
};
r.setn(j);
cout<<"\n resultado de los elementos comunes\n";
r.imprimir();
v.qsort(v.a,0,v.getn()-1);
v.imprimir();
return 0;
}

El programa anterior, crea dos objetos ‘v’ y ‘k’ partir de la clase Tvector,
almacena cantidades de datos en cada vector de los objetos en forma
aleatoria, por medio de la función ‘random’ y crea un tercer objerto ‘r’ en
cuyo vector se tiene los valores comunes de los vectores de los objetos ‘v’ y
‘k’.

También es recomendable desarrollar otras clases que incorporen operaciones con el


manejo de vectores.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 80


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

3.2.2. ARREGLOS BIDIMENSIONALES. MATRICES.

En un arreglo Bidimensional, el conjunto de celdas se organizan como una tabla, es decir,


se tiene filas y columnas.

En un arreglo unidimensional o vector cada elemento se referencia por un índice, en un


arreglo bidimensional cada elemento se va a referenciar por 2 índices, y ahora la
representación lógica ya no va a ser un vector, sino una matriz.

Un array bidimensional de M filas y N columnas es un conjunto de M*N elementos, todos


del mismo tipo, cada uno de los cuales se referencia a través de 2 subíndices. El primer
subíndice podrá variar entre 0 y M-1, y el segundo índice variará entre 0 y N-1.

3.2.2.1. DECLARACIÓN DE UN ARRAY BIDIMENSIONAL: MATRIZ:

La declaración es muy similar a la declaración de cualquier tipo de dato simple o de un


arreglo unidimensional, debiendo adicionar la especificación de la cantidad de filas y
columnas que contendrá la matriz.

Tipo_dato nombre_arreglo[tamaño_filas][tamaño_columnas];

Ejemplo:

int a[10][10];

‘a’ es un arreglo bidimensional con 100 celdas disponibles, organizadas en 10 filas


y 10 columnas, las filas se numeran desde la 0 hasta la 9, las columnas se numeran
desde la 0 hasta la 9 y se puede almacenar datos enteros únicamente.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 81


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float b[30][5];

‘b’ es un arreglo bidimensional con 150 celdas disponibles, organizadas en 30 filas


y 50 columnas, las filas se numeran desde la 0 hasta la 29, las columnas se numeran
desde la 0 hasta la 4 y se puede almacenar datos reales únicamente.

char lista[10][45];

‘lista’ es un arreglo bidimensional con 10 filas, numeradas desde la 0 hasta la 9 y


cada fila tiene 45 columnas numeradas desde 0 0 hasta la 44 y se puede almacenar
datos tipo carácter únicamente. Esta declaración permite almacenar 10 cadenas de
caracteres de un máximo de 45 letras cada una.

3.2.2.2. ALMACENAMIENTO DE DATOS EN UN VECTOR.

Idéntico a lo establecido con los vectores.

El almacenamiento de datos en una matriz es el proceso mediante el cual se depositan los


valores, es decir datos, en las diferentes celas del arreglo, esta operación se puede realizar
de 3 formas:

a) Por inicialización en la declaración del arreglos.

Esta forma de almacenamiento es muy frecuente cuando se dese que los datos
almacenados en el vector siempre sean los mismos al empezar la ejecución de la
aplicación.

Los datos se almacenan antes de la ejecución del programa, es decir, en proceso de


compilación.

Ejemplo:

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

Los tres grupos de valores inicializan las primeras tres filas de la matriz. Las
celdas restantes de la matriz que no son inicializadas toman el valor 0 por
defecto:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 82


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) por una función de asignación.

Esta forma de almacenamiento de datos se emplea cuando:


o La aplicación se está ejecutando.
o Los datos a almacenar se generan internamente por medio de una función
específica, la más usual la función ‘random’, datos aleatorios.
o Cada vez que se ejecuta la aplicación, los datos que se almacena en el vector
pueden ser o no los mismos.

Ejemplo:

for (i=0;i<10;i++) // filas


for (j=0;j<10;j++) // columnas
b[i][j]= random(20);

En las 100 celdas del vector ‘b, se almacenan valores aleatorios generados
por medio de la función ‘random’.

c) Por una función de entrada de datos.

Los datos que almacenan en el vector, se introducen por el usuario desde el teclado durante
la ejecución del programa.

Se emplea dominantemente cuando se desea almacenar un conjunto reducido de datos y de


acuerdo a la necesidad del usuario para la ejecución del programa.

Ejemplo:

for (i=0;i<4;i++) //filas


for (j=0;j<3;j++) //columnas
cin>>b[i][j];

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 83


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

En las 4 primeras filas y en las 3 primeras columnas de la matriz b’, se


almacenan valores introducidos desde el teclado por medio de la función
‘cin’.

Una vez que los datos están almacenados en el vector, estos se encuentran disponibles para
el procesamiento durante toda la ejecución del programa.

3.2.2.3. MANEJO DE UNA MATRIZ DESDE UNA APLIACION OO.

El procesamiento de datos almacenados en una Matriz desde una aplicación orientada a


Objetos es idéntico al proceso establecido con un vector, se desarrolla las siguientes
actividades:

 Especificación del diagrama de la clase


 Implementación de la clase.
 Implementación de las funciones de la clase
 Desarrollo de una aplicación que utiliza objetos del tipo vector.

Estos pasos genéricos contendrán características específicas de acuerdo al problema que se


desea resolver, por ejemplo una ilustración en el procesamiento de vectores podría ser la
siguiente:

a) Diagrama de la clase ‘matriz’

Donde:
a[][], es el nombre del vector que contiene la clase.
n y m, es la cantidad de filas y columnas de la matriz.
leer(), es la función que almacena datos en la matriz.
imprimir(), es la función que muestra el contenido de la matriz.
verificar(), es la función que verifica si un valor ‘clave’ está o no en
la matriz.

Nota: Si los datos a, n y m de la clase ‘matriz’ son Privados, entonces es


necesario incorporar las funciones ‘set’ y ‘get’ para el acceso a los mismos
desde otras clases.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 84


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) Implementación del esquema de la clase.

La implementación del esquema de la clase se desarrolla en un archivo ‘.h’, para el


ejemplo que se plantea se tiene el siguiente código que se graba en un archivo
‘matriz.h’

class matriz
{
public:
int a[10][10];
int n,m;
public:
matriz(int,int);
void seta(int,int,int);
void setn(int);
int geta(int,int);
int getn();
void setm(int);
int getm();
void leer();
void imprimir();
int verificar(int);
};

c) Implementación de las funciones de la Clase.

Las funciones de una clase se implementan en un archivo ‘.cpp’ independiente, con


el fin de incorporar las características de la POO. Para el ejemplo que se desarrolla
en este capítulo, esta implementación considera las funciones ‘set’ y get’, debido a
que los datos a y n son privados y serán guardados en un archivo ‘matriz.cpp’.

#include <iostream.h>
#include <stdlib.h>
#include <d:\sis2210a\matrizoo\matriz.h>
matriz::matriz(int f,int c) //function constructora
{
n=f;
m=c;

}
void matriz::seta(int valor,int f,int c)
{
a[f][c]=valor;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 85


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void matriz::setn(int f)
{
n=f;
}
int matriz::geta(int f,int c)
{
return a[f][c];
}
int matriz::getn()
{
return n;
};
void matriz::setm(int c)
{
m=c;
}
int matriz::getm()
{
return m;
}
void matriz::leer()
{
int i,j;
cout<<"\n almacenamiento de datos en la matriz";
//randomize();
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{
// cout<<"\nvalor para la celda a["<<i<<"]["<<j<<"]=";
// cin>>a[i][j];
a[i][j]=random(30)+5;
};
}
void matriz::imprimir()
{
int i,j;
cout<<"\n contenido de datos en la matriz\n\n";
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
cout<<a[i][j]<<"\t";
cout<<"\n";
};
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 86


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int matriz::verificar(int clave)


{
int i,j,sw=0;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
if (clave==a[i][j])
sw=1;
return sw;
}

d) Generación y uso de objetos a partir de la clase Tvector.

Se debe desarrollar otro programa ‘.cpp’ donde se crea objetos a partir de la clase
‘matriz’ y se emplea las funciones del objeto creado para resolver un problema
determinado. En el ejemplo que se desarrolla el programa puede ser ‘ejemmat.cpp’.

#include <iostream.h>
#include <d:\sis2210a\matrizoo\matriz.cpp>
int main()
{
//int p,q,r,s;
matriz m1(3,3);
m1.leer();
m1.imprimir();
return 0;
}

El programa anterior es simple y trata de ilustrar la creación de un objeto


‘m1’ a partir de la clase ‘matriz’ inicializando a las variables ‘m’ y ‘n’ con el
valor 3 es decir, si bien el tamaño de la matriz ‘a’ es de 10 filas y 10
columnas, se establece para el almacenamiento de datos únicamente las 3
primeras filas y las 3 primeras columnas, luego se genera datos en las 3
primeras filas y columnas y finalmente muestra el contenido de la matriz..

Es importante remarcar que la definición de clases que incorporan el manejo de


matrices deben estar en función a los requerimientos particulares de los problemas
que se desean resolver, de esta manera se puede lograr una configuración de clases
de tal forma que satisfagan una gran cantidad de requerimientos e con la empleo de
matrices u otras estructuras de datos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 87


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 4

ESTRUCTURAS Y UNIONES

4.1. ESTRUCTURAS.

Todas las variables que se ha utilizado en los temas anteriores han sido de un único tipo,
incluso los arrays son variables con todos los elementos del mismo tipo. La finalidad de
una estructura es agrupar una o más variables, generalmente de diferentes tipos, bajo un
mismo nombre para hacer más fácil su manejo.

Dependiendo del tipo de información a procesar, es necesario agrupar un conjunto de


atributo (variables) respecto a un objeto de interés bajo un mismo denominativo. Por
ejemplo:

 Si se requiere procesar la información de una persona, entonces los atributos a


considerar pueden ser:
o Ci
o Nombre
o Dirección
o Teléfono
o Etc
Todos estos atributos relativos al objeto de interés (entidad) que pueden ser de
diferente tipo, se los debe agrupar en una sola variable u objeto.

 En algunos casos es necesario descomponer cierta información en elelemntos masd


basicos con fines de procesamiento, lo que supone la especificación de atributos de
una entidad, por ejemplo: Nombre_persona se puede descomponer en:
apellido_paterno, apellido_materno y nombre.

DEFINICION:
Una estructura es un conjunto finito de variables de diferente tipo o no
referenciadas por un nombre único y que permiten almacenar el valor en
cada variable simultáneamente.

Para el Procesamiento de una estructura es necesario de manera inicial definir el esquema


de la estructura.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 88


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

4.1.1. ESQUEMA DE LA ESTRUCTURA.

El esquema de la estructura es la presentación gráfica del conjunto de variables, llamados


también campos o miembros de la estructura, relativos a un objeto de interés, permite
establecer de manera clara y simple la configuración y orden del conjunto de campos.

El diseño del esquema de la estructura es una tarea no obligatoria pero resulta importante
en función al grado de complejidad en el proceso de descomposición en atributos del objeto
de interés.

Ejemplo:

4.1.2. DECLRACION DE UN TIPO DE DATO ESTRUCTURA

Para crear una estructura hay que definir un nuevo tipo de datos y declarar una variable de
este tipo. La declaración de un tipo estructura, incluye tanto los elementos que la componen
como sus tipos. Cada elemento de una estructura recibe el nombre de miembro (campo del
registro). La sintaxis es la siguiente:

struct tipo _estructura


{
// Declaración de los miembros de la estructura;
};

Donde tipo_estructura es un identificador que nombra el nuevo tipo definido. La


declaración de un miembro de una estructura no puede contener calificadores de clase de
almacenamiento como extern, static, auto o register y no puede ser inicializado. Su tipo
puede ser: fundamental, array, puntero, unión, estructura o función.

Ejemplo:

struct persona
{
int ci;
char nombre[30];
char direc[20];
float est;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 89


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

char sexo;
};

En el ejemplo anterior se ha creado un nuevo tipo de dato llamado ‘persona’, este


nuevo tipo de dato es una estrucvtura que tiene 5 campos o miembros.

Las reglas para utilizar el nuevo tipo son las mismas que las seguidas para los tipos
predefinidos como float, int y char, entre otros. Esto es, después de definir un tipo
estructura, podemos declarar una variable de ese tipo.

4.1.3. DECLARACION DE UNA VARIABLE ESTRUCTURA.

Es importante tomar en cuenta que en un programa computacional únicamente las variable


u objetos son los elementos que pueden almacenar datos, por lo que es necesario la
declaración de las mismas.

La declaración de una variable estructura se puede realizar de dos maneras:

a) A PARTIR DE UN TIPO DE DATO.

Esta manera, la mas usual en la programación, requiere que de manera previa la declaración
de un tipo de dato struct y es similar a la declaración de variables a partir de los tipos
predefinidos, se emplea el siguiente formato:

struct tipo-estructura varible1, variable2,…..;

Ejemplo:

struct persona reg;

‘reg’ es una variable del tipo persona, es decir, contiene los mismos campos
especificados en el tipo de dato persona.

persona aux;

En C++, no es necesario especificar la palabra reservado ‘struct’ antes del


tipo de dato estructura, siendo totalmente valido.

b) Simultáneamente a la declaración del tipo de dato.

La definición de las variables estructuras se purede realizar también justamente a


continuación de la declaración del nuevo tipo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 90


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

struct persona
{
int ci;
char nombre[30];
char direc[20];
float est;
char sexo;
} reg1, reg2;

En esta declaración se ha desarrollado la creación de un nuevo tipo de dato


‘persona’ y simultáneamente la definición de dos variables reg1 y reg2.

También es posible desarrollar la definición de variables de manera directa:

struct
{
int ci;
char nombre[30];
char direc[20];
float est;
char sexo;
} per1, per2;

En esta definición se tiene dos variables per1 y per2 y no se ha declarado


ningún tipo de dato nuevo.

4.1.4. ACCESO A LOS CAMPOS DE UNA VARIABLE ESTRUCTURA

Una variable estructura hace referencia grupal al conjunto de miembros o campos que lo
conforman, sin embargo en el procesamiento de la información es necesario tener la
posibilidad de procesar de manera individual cada valor almacenado en cada campo.

El Operador ‘.’ (punto) permite accederé a cada campo de manera individual, donde se
utiliza la siguiente notación:

Varible_estructura.miembro

Ejemplo:
Persona reg;


Gráficamente reg tiene la siguiente forma:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 91


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Según corresponda se debe escribir:

reg.ci
reg.nombre
reg.direc
reg.est
reg.sexo

Para acceder a cada uno de los campos.

4.1.5. OPERACIONES CON ESTRUCTURAS.

En un programa se puede realizar operaciones con variables tipo estructura.

a) Asignación.

Dos variables estructura se pueden asignar únicamente si son estructuras del mismo tipo, es
decir, si son compatibles. La asignación supone una asignación equivalente a campo por
campo, el contenido de todos los campos de una variable son asighnadas a todos los
campos de otra variable.

Ejemplo:
persona reg, aux,

….
aux=reg;

La información contenida en los campos de aux son asignados o transferidos a todos


los campos de reg, es decir tanto aux como reg almacenan la misma información en
sus campos.

b) Inicializacion.

Una variable estructura puede ser inicializada con valores en los diferentes campos en el
momento de su definición, esto es similar a la inicialización de los tipos predefinidos.

Ejemplo:

persona reg={5555,”Juan Carlos”, “Arce 234”,1.75,’M’};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 92


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

se tiene:

c) Acceso a los miembros de la Estructura.

Como se ha indicado anteriormente el acceso a los miembros de la estructura se realiza por


medio del operador ‘.’.

Ejemplo:
float est=reg.est;

d) Obtener la Direccion de Memoria.

Esta es una operación muy importante cuando se debe procesar la información contenida en
una estructura por medio de Punteros.

Ejemplo:

Persona *pt=&reg;

Otras operaciones a realizar en el procesamiento de la información contenida en una


estructura se realizan campo por campo de manera individual.

4.1.6. ARREGLOS DE ESTRUCTURAS.

Una variable estructura almacena la información de un solo objeto de interés en un


momento dado, si se requiere procesar simultáneamente la información de varios objetos de
interés, entonces se puede definir varias variables tipo estructura, este camino no siempre es
el mejor, lo más recomendable es declara un arreglo de estructuras, esto significa que cada
celda del vector contiene una estructura de un tipo determinado.

Ejemplo: primero declaramos un tipo de datos estrutura.

typedef struct persona


{
int ci;
char nombre[30];
float est;
} tpersona;

La declaración de vector de estructuras se puede realizar de la siguiente forma:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 93


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

struct persona lista[50];

‘lista’ es un vector de 50 celdas y cada celda contiene una estructura del tipo
persona.

También es posible realizar la siguiente declaración:

tpersona curso[50];

‘curso’ es un vector de 50 celdas y cada celda contiene una estructura del tipo
persona.

Gráficamente:

El siguiente programa ilustra el procesamiento de la información de un vector de


estructuras en una aplicación orientada a objetos.

Archivo personas.h

struct persona
{
int ci;
char nombre[30];
float est;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 94


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class personavec
{
//private:
public:
// int a[50]={5,7,8};
persona lista[50];
int n;
public:
personavec(int);
void leer();
void imprimir();
int verificar(int);
//otras funciones de la clase vector
void ordenar(persona[],int);
float promest();
//otras funciones de la clase pesonavec
};

Archivo personas.cpp

#include <d:/lab4sis2210/persona.h>
#include <iostream.h>
#include <string.h>
personavec::personavec(int t)
{
n=t;
lista[0].ci=123;
strcpy(lista[0].nombre,"luisa");
lista[0].est=1.7;
lista[1].ci=789;
strcpy(lista[1].nombre,"pedro");
lista[1].est=1.63;
lista[2].ci=765;
strcpy(lista[2].nombre,"ana");
lista[2].est=1.75;
lista[3].ci=4653;
strcpy(lista[3].nombre,"mario");
lista[3].est=1.85;
}

void personavec::leer()
{
int i;
for (i=0;i<n;i++)
{
cout<<"\n ingresar C.I.:";
cin>>lista[i].ci;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 95


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

cout<<"\n ingresar NOMBRE:";


cin>>lista[i].nombre;
cout<<"\n ingresar ESTATURA:";
cin>>lista[i].est;
};
}

void personavec::imprimir()
{
int i;
cout<<"\n reporte completo del vector de personas";
for (i=0;i<n;i++)
{
cout<<"\n C.I.:"<<lista[i].ci;
cout<<"\n NOMBRE:"<<lista[i].nombre;
cout<<"\n ESTATURA:"<<lista[i].est;
};
}

int personavec::verificar(int dato)


{
int i=0;
while (i<n && dato!=lista[i].ci)
i++;
if (i==n)
return -1;
else
return i;
}

void personavec::ordenar(persona x[],int y)


{
persona aux;
int i,j;
for (i=0;i<y-1;i++)
for (j=i+1;j<y;j++)
if (strcmp(x[i].nombre,x[j].nombre)<0)
{
aux=x[i];
x[i]=x[j];
x[j]=aux;
}
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 96


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float personavec::promest()
{
int i,suma=0;
float prom;
for (i=0;i<n;i++)
suma+=lista[i].est;//suma=suma+lista[i].est;
prom=suma/n;
return prom;
}

Archivo que implementa objetos:

#include <d:/lab4sis2210/persona.cpp>
#include <iostream.h>

main()
{
personavec pv(4);
//pv.leer();
pv.imprimir();
int clave;
cout<<"\n\n C.I. de la persona a buscar en el vector:";
/*cin>>clave;
int resp=pv.verificar(clave);
if (resp!=-1)
cout<<"\n se encuentra en la celda :"<<resp;
else
cout<<"\n NO se encuentra en el vector.";*/
cout<<"\n\n ordenando el vector\n";
pv.ordenar(pv.lista,pv.n);
pv.imprimir();
return 0;
}

4.1.7. ESTRUCTURAS ANIDADAS

Una estructura anidada se presenta cuando uno o más miembros de la estructura


constituyen es si otra estructura, es decir, una estructura dentro de otra.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 97


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El procesamiento de las estructuras anidadas es similar al de una estructura simple.

Declaración:

a) en un solo bloque.

struct persona
{
int ci;
struct // estructura anidad
{
char nom[15];
char paterno[15];
char materno[15];
} nombre;
char direc[20];
float est;
char sexo;
};

b) Por declaraciones independientes.

//primero todas las estructuras internas.


Struct regnombre
{
char nom[15];
char paterno[15];
char materno[15];
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 98


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

// al final la estructura principal

struct persona
{
int ci;
struct regnombre nombre; // estructura anidada
char direc[20];
float est;
char sexo;
};

4.2 UNIONES.

Una Unión es un conjunto finito de variables de diferente tipo o no referenciadas por un


nombre único y que comparten el mismo espacio de almacenamiento.

A diferencia de las estructuras, el tamaño de una Union es equivalente al tamaño del campo
más grande, mientras que el tamaño de una estructura es equivalente a la suma del tamaño
de todos sus campos.

Una unión es una variable que puede contener, en distintos instantes de la ejecución del
programa, datos de diferentes tipos. Esto permite manipular diferentes tipos de datos
utilizando una misma zona de memoria, la reservada para la variable unión.

La declaración de una unión tiene la misma forma que la declaración de una estructura,
excepto que en lugar de la palabra reservada struct se pone la palabra reservada union. Por
lo tanto, todo lo expuesto para las estructuras es aplicable a las uniones, con la excepción de
que de los miembros especificados, en un instante sólo está uno presente. La sintaxis para
declarar una unión es:

a) Declaración de un tipo de dato ‘union’.

union tipo _union


{
// Declaración de los miembros de la union;
};

Ejemplo:

union bloque
{
int a;
float b;
char c;
};
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 99
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El tipo de dato ‘bloque’ contiene tres miembros a,b y c, el tamaño de este tipo de
dato es equivalente al tamaño del miembro ‘b’, es decir 4 bytes.

b) Declaración de una variable unión.

 A partir de un tipo de dato

Unión bloque pb;

La variable ‘pb’ es del tipo unión bloque y puede almacenar uno de los tres valores
que corresponde a uno de los campos.

 Solo la variable.

union
{
int a;
float b;
char c;
} pq;

La variable ‘pq’ es una variable unión con similares características a la variable ‘pb’.

El acceso a los campos de una ‘union’ es similar al de una estructura, sin embargo se debe
tomar en cuenta que en una ‘union’ solo se puede almacenar el valor de uno de los campos
en un momento dado.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 100


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 5

PUNTEROS Y ESTRUCTURAS DINÁMICAS DE DATOS

Un puntero es una variable que contiene la dirección de memoria de un dato o de otra


variable que contiene al dato, es decir, que el puntero apunta al espacio físico donde está el
dato o la variable. Un puntero puede apuntar a un objeto de cualquier tipo, como por
ejemplo, a una estructura o a una función. Los punteros se pueden utilizar para referenciar y
manipular estructuras de datos, para referenciar bloques de memoria asignados
dinámicamente y para proveer el paso de argumentos por referencia en las llamadas a
funciones.

A diferencia de una variable normal (estática) que hace referencia directa al valor que
almacena, una variable puntero almacena la dirección de memoria del valor en la memoria,
es decir, realiza una referencia indirecta a los valores en la memoria. Los punteros sirven para
expresar direcciones de memoria y permiten modificar el contenido de la memoria a la que apuntan.

Cuando se trabaja con punteros son frecuentes los errores debidos a la creación de punteros
que apuntan a alguna parte inesperada, produciéndose una violación de memoria. Por lo
tanto, debe ponerse la máxima atención para que esto no ocurra, inicializando
adecuadamente cada uno de los punteros que utilicemos.

5.1. OPERADORES PARA EL MANEJO DE PUNTEROS.

Para el trabajo o procesamiento de punteros existe dos operados especiales que permiten el
acceso a los valores almacenados en la memoria y la utilización de la dirección de memoria
donde se encuentran los valores.

5.1.1. OPERADOR DE DIRECCION ‘&’.

Es un operador unitario que se aplica a una variable o a objetos como un elemento de un


vector o un campo de una estructura que pueden utilizarse en los mismos lugares en los que

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 101


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

se utiliza una variable. El resultado de la expresión “&x”, donde x es una variable, es la


dirección de memoria donde se almacena x.

Por ejemplo:
&p da como resultado la dirección de memoria de la variable p.

El resultado del operador ‘&’ se debe almacenar en una variable puntero o en una función
de salida.

5.1.2 OPERADOR DE INDIRECCION O CONTENIDO ‘*’.

Es un operador unitario que se aplica a un puntero. Dada una expresión de tipo puntero p, la
expresión ‘*p’ permite trabajar con la variable u objeto al que apunta p.

El resultado del operador ‘*’ es el contenido de la dirección de memoria (variable puntero)


a la que se aplica el operador.

Por ejemplo:

*pt da como resultado el valor o contenido de la dirección de memoria de


la variable puntero ‘pt’.

El siguiente programa muestra el efecto resultante del uso de los operadores de dirección y
de indirección.

#include <stdio.h>
int void main()
{
//declaración de variables estáticas y dinamicas
int a = 5, b, *p;
p = &a; // asigna la dirección de a, a la variable p
// p apunta a la variable entera a
b = *p; // asigna a b el valor de la variable a (contenido de la
//variable p)
printf("en la dirección %.4X está el dato %d\n". p, b);
printf("En la dirección %.4X está el dato %d\n", p, *p);
return 0;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 102


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

5.2. DECLARACIÓN DE PUNTEROS.

Un puntero se declara anteponiendo al identificador que nombra al puntero, el modificador


*, el cual significa "puntero a". Un puntero inicializado correctamente siempre apunta a un
objeto de un tipo particular. Un puntero no inicializado no se sabe a que apunta. La sintaxis
para declarar un puntero es:

Tipo *var_puntero;

Donde Tipo especifica el tipo del objeto apuntado, puede ser cualquier tipo incluyendo
tipos definidos por el usuario y var_puntero es el identificador de la variable puntero.

Por ejemplo:
int a;
int *pt;

a es una variable entera


pt es un puntero a un entero
pt es igual a la dirección de a, entonces pt apunta a la variable a

float *pf; //pf es un puntero a un real


char *pc; //pc es un puntero a un carácter

El espacio de memoria requerido para un puntero, es el número de bytes necesarios para


especificar una dirección de memoria de la máquina. Son valores típicos 2 o 4 bytes.

5.2.1. ALMACENAMIENTO EN UNA VARIABLE PUNTERO.

En una variable punero se puede almacenar los siguientes valores:

a) DIRECCIONES DE MEMORIA.

Lo normal es almacenar direcciones de memoria de objetos que se emplea en el programa y


que son obtenidos por medio del operador de dirección ‘&’.

Por ejemplo:

int a=5,*p;
p=&a;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 103


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) CONSTANTE NULL (PUNTERO NULO)

Sin importar el tipo de objeto al que apunta, a una variable puntero se le puede asignar la
constante NULL, esto significa que se tiene un puntero nulo, es decir, la variable puntero
no apunta a algo específico.

Por ejemplo:

int *pt;
float *pf;

pt=NULL;
pf=NULL;

c) VALOR CERO (0).

En una variable puntero se puede almacenar el valor cero (0) y es equivalente a almacenar
la constante NULL. El almacenamiento del valor 0 es el único permitido de los valores
enteros que se puede almacenar en una variable puntero. El siguiente programa muestra
estas posibles formas de almacenamiento:

#include <stdio.h>
#include <iostream.h>
int a=5,*pt,*pt1,*pt2;
main()
{
pt=&a;
pt1=NULL;
pt2=0;
cout<<"direccion:"<<pt<<"\tvalor:"<<*pt<<endl;
cout<<"direccion:"<<pt1<<endl;
cout<<"direccion:"<<pt2<<endl;
return 0;
}

Mostrando la siguiente salida:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 104


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

5.3. OPERACIONES CON PUNTEROS.

El trabajo con punteros permite realizar un conjunto de operaciones que exigen mucho
cuidado en la compatibilidad de los objetos a los que apuntan. Se pueden realizar las
siguientes operaciones:

5.3.1. ASIGNACION.

Dos variables puntero se pueden asignar solo si son punteros al mismo tipo de objeto, es
decir, las dos variables puntero deben ser compatibles.

Por ejemplo:

int a=5, *p,*q;

p=&a;
q=p;

En este ejemplo, la variable puntero p recupera la dirección de memoria de ‘a’, es


decir, ‘p’ apunta a la variable ‘a’ y la variable puntero q recibe la dirección de
memoria de la variable ‘p’, por lo que tanto ‘p’ y ‘q’ apuntan a la misma variable ‘a’.

No es posible asignar dos variables puntero si no apuntan al mismo tipo de objeto, el


siguiente ejemplo produce un error:

int a=5,*pt;
float *pf;

pt=&a;
pf=pt; // error de incompatibilidad de tipo.

Como ‘pt’ y ‘pf’ son punteros a diferentes tipos de objetos, la asignación de ambas
variables produce un error.

Una Variable puntero, sea cualquiera el objeto al que apunta, se puede asignar con la
constante NULL (puntero nulo).

pt=NULL;

‘pt’ apunta a nulo, es decir, apunta a nada.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 105


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

5.3.2. COMPARACION.

Dos variables puntero se pueden comparar solo sin son compatibles, es decir, si ambas
variables apuntan al mismo tipo de objeto. Cuando dos variables puntero se comparan solo
es útil el empleo de los operadores de relación igual que (==) y distinto que (!=), el empleo
de otros operadores no tiene sentido.

Por ejemplo:

int *p,*q;
…..
if (p==q)
……..

if (p!=q)
…….

Una Variable puntero, sea cualquiera el objeto al que apunta se puede comparar con la
constante NULL (puntero nulo).

if (p==NULL)
……..

if (p!=NULL)
……..

No es posible comparar dos variables puntero que apuntan a objetos diferentes,


produciendo un error de tipología de datos.

5.3.3. ARITMETICA CON PUNTEROS.

Las únicas operaciones aritméticas permitidas con punteros son el incremento o suma y el
decremento o resta. Tanto el incremento o decremento se realiza únicamente con valores
enteros. Se debe tomar en cuenta que la dirección de memoria almacenada en un puntero
está representada en sistema de numeración hexadecimal.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 106


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

a) INCREMENTO O SUMA.

Si ‘p’ es un puntero a entero, entonces almacena una dirección de memoria donde se


localiza un valor entero. Si a ‘p’ se le incrementa 1, entonces se logra que ‘p’ apunte al
entero siguiente, por lo tanto la dirección de memoria de ‘p’ se incrementa en 2 o 4
dependiendo del tamaño de memoria en bytes que ocupa un valor entero en la memoria del
computador.

Por ejemplo:

int a=5,*pt;
pt=&a;
pt=pt+1; //pt apunta al en tero siguiente
pt=pt+3; //pt apunta al tercer entero más adelante

NOTA:
 la operación de incremento es recomendable realizarla cuando se accede a
los valores de un arreglo unidimensional por medio de las direcciones de
memoria.
 El incremento se realiza en sistema de numeración hexadecimal.

a) DECREMENTO O RESTA.

Si ‘p’ es un puntero a entero, entonces almacena una dirección de memoria donde se


localiza un valor entero. Si a ‘p’ se le decrementa 1, entonces se logra que ‘p’ apunte al
entero anterior, por lo tanto la dirección de memoria de ‘p’ se decrementa en 2 o 4
dependiendo del tamaño de memoria en bytes que ocupa un valor entero en la memoria del
computador.

Por ejemplo:

int a=5,*pt;
pt=&a;
pt=pt-1; //pt apunta al entero anterior
pt=pt-3; //pt apunta al tercer entero más atrás

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 107


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

NOTA:
 la operación de decremento es recomendable realizarla cuando se accede a
los valores de un arreglo unidimensional por medio de las direcciones de
memoria.
 El decremento se realiza en sistema de numeración hexadecimal.

En términos generales, si a un puntero se le Incrementa/Decrementa 1 (uno), entonces el


puntero avanza o retrocede al objeto siguiente o anterior respectivamente y por lo tanto la
dirección de memoria del puntero se incrementa/decrementa en el valor que corresponde al
tamaño en bytes que ocupa en la memoria del objeto al que apunta.

5.4. PUNTEROS Y ARREGLOS.

Existe una relación muy importante entre punteros y arreglos, por lo que es posible acceder
y procesar la información de un arreglo por medio de las direcciones de memoria del
arreglo sin necesidad de emplear la notación de sub índices.

El nombre de un arreglo representa la dirección de memoria donde empieza el arreglo en la


memoria, tomando en cuenta esta consideración y por medio de las operaciones de
incremento o decremento en una variable puntero, se puede procesar la información
almacenada en el arreglo empleando punteros.

Por ejemplo:

int a[5]={3,6,2,8,1};
int *pt;
pt=a; //pt apunta al primer elemento del arreglo ‘a’
cout<<*pt; //muestra el primer valor del arreglo ‘a’, 3
cout<<*(pt+1); // muestra el segundo valor del arreglo ‘a’, 6
cout<<*(pt+2); // muestra el tercer valor del arreglo ‘a’, 2
cout<<*(pt+3); // muestra el cuarto valor del arreglo ‘a’, 8
cout<<*(pt+4); // muestra el quinto valor del arreglo ‘a’, 1

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 108


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El siguiente programa ilustra el procesamiento de la información de un arreglo


unidimensional y de un arreglo bi dimensional por medio de sub índices y por medio de las
direcciones de memoria, asimismo muestra el tamaño de las variables de los tipos
fundamentales del C++.

#include <iostream.h>
int a[10]={5,2,8,1,4};
int a1[5][10]={{2,4,1},{8,1,3},{3,7,1}};
void imprimir(int x[],int y)
{
cout<<"\n CONTENIDO DEL VECTOR POR MEDIO DE DIR. DE MEMORIA";
int *pt;
pt=x;
int i;
for (i=0;i<y;i++)
cout<<"\nvalor="<<*(pt+i)<<"\tdir. de memoria="<<(pt+i);
}
void impmat(int x[][10],int f,int c)
{
int *pt;
int i,j;
cout<<"\n matriz por medio de dir. de memoria";
pt=x[0];
for (i=0;i<f;i++)
for (j=0;j<c;j++)
cout<<"\n valor="<<*((pt+i*10)+j)<<"\tdir. de memoria="<<((pt+i*10)+j);
}
main()
{
int i;
cout<<"\ncontenido del vector por medio de sub indices";
for (i=0;i<5;i++)
cout<<"\nvalor = " <<a[i];
imprimir(a,5);
impmat(a1,3,3);
int p=5,*pt;
float f=6.9,*pf;
char c='a',*pc;
cout<<"\ntamaño de un entero="<<sizeof(int);
cout<<"\ntamaño de un real="<<sizeof(float);
cout<<"\ntamaño de un caracter="<<sizeof(char);
cout<<"\ntamaño de un entero largo="<<sizeof(long);
cout<<"\ntamaño de un real doble="<<sizeof(double);
pt=&p;
pf=&f;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 109


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

pc=&c;
cout<<"\nvalor de p="<<*pt<<"\t dir de memoeria="<<pt;
cout<<"\nvalor de f="<<*pf<<"\t dir de memoeria="<<pf;
cout<<"\nvalor de c="<<*pc<<"\t dir de memoeria="<<&pc;
pt=pt-2;
cout<<"\nnuevo valor de pt ="<<pt;
return 0;
}

Produciendo la siguiente salida:

NOTA: en el programa ejecutado, por la versión del IDE, el tamaño que ocupa un valor
entero en la memoria es de 2 bytes,.

La función ‘imprimir’ muestra el contenido del vector por medio de las direcciones de
memoria empleando una variable puntero.

La función ‘impmat’ muestra el contenido de una matriz de un tamaño de 5 filas y 10


columnas, aunque solo se almacena datos en las tres primeras filas y columnas, por medio
de las direcciones de memoria.

5.4.1. PUNTERO A CADENA DE CARACTERES.

Puesto que una cadena de caracteres es un array de caracteres, es correcto pensar que la
teoría expuesta anteriormente, es perfectamente aplicable a cadenas de caracteres.

La forma de definir un puntero a una cadena de caracteres es:

char *cadena;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 110


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El identificador del array de caracteres es la dirección de comienzo del array y para que una
función manipuladora de una cadena de caracteres pueda saber dónde finaliza dicha cadena,
el compilador añade al final de la cadena el carácter ‘\0’.

El siguiente ejemplo define e inicializa la cadena de caracteres nombre:

#include <stdio.h>
int longcad(char *cad)
{
char *p = cad;
while (*p != '\0')
p++;
return (p - cad);
}

void main ( )
{
char *nombre = "abcd"; //el carácter de terminación '\0' se añade
automáticamente
printf(“\n la longitud de la cadena es: %d \n”,longcad(nombre));
}

El valor (p – cad) devuelto por la función longcad, da la longitud de la cadena. Esta función
realiza las siguientes operaciones:

1. Asigna a p la dirección del primer carácter de la cadena, que coincide con la dirección de
comienzo de la misma, e inicia la ejecución del bucle while.

2. Cuando se ejecuta la condición del bucle while, se compara el carácter *p apuntado por p
con el carácter nulo (\0). Si *p es el carácter nulo el bucle finaliza; si no, se incrementa el
valor de p en una unidad para que apunte al siguiente carácter, y se vuelve a evaluar la
condición.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 111


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

5.4.2. PUNTEROS A ESTRUCTURAS.

En un puntero se puede almacenar la dirección de memoria de cualquier tipo de dato, sea


simple o compuesto, una estructura es un tipo de dato compuesto, por lo que un puntero a
una estructura es similar a la declaración de un puntero a otro tipo de dato. Se emplea el
siguiente formato:

Tipo_estructura *puntero;

struct persona
{
int ci;
char nombre[20];
float est;
};

struct persona *pp;

donde ‘pp’ es un puntero a estructura tipo persona.

Struct fecha
{
int dia;
int mes;
int anio;
};

struct fecha *pf;

Donde ‘pf’ es un puntero a estructura fecha.

El acceso a los miembros o campos de una estructura por medio del puntero se realiza
empleando el operador flecha (->).

Por ejemplo:

pp->ci; hace referencia al campo `ci’ de la estructura persona.


pp->nombre; hace referencia al campo `nombre’ de la estructura persona.
pp->est; hace referencia al campo `est’ de la estructura persona.

El siguiente programa muestra la declaración de una estructura fecha y un puntero a esa


estructura, asimismo el acceso a los campos por medio del operador flecha (->)

#include <iostream.h>
#include <stdlib.h>

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 112


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

struct fecha
{
int dd;
int mm;
int aa;
};

void leer(struct fecha *f)


{
cout<<"\nDia:";
cin>>f->dd;
cout<<"\nMes:";
cin>>f->mm;
cout<<"\nAño:";
cin>>f->aa;
}
void imprimir(struct fecha *f)
{
cout<<"\nDia:"<<f->dd;
cout<<"\nMes:"<<f->mm;
cout<<"\nAño:"<<f->aa;
}

int main()
{
struct fecha *d;
d=(struct fecha *)malloc(sizeof(struct fecha));
leer(d);
imprimir(d);
return 0;
}

La salida del programa anterior es:

Notar que para usar un puntero se debe solicitar memoria dinámica por medio de la
función ‘malloc’.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 113


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

5.5. ESTRUCTURAS DINÁMICAS DE DATOS. LISTAS SIMPLES.

Una de las aplicaciones más interesantes y potentes de la memoria dinámica y los


punteros son las estructuras dinámicas de datos. Las estructuras básicas disponibles en C
y C++ tienen una importante limitación: no pueden cambiar de tamaño durante la
ejecución. Los arreglos están compuestos por un determinado número de elementos,
número que se decide en la fase de diseño, antes de que el programa ejecutable sea
creado.

En muchas ocasiones se necesitan estructuras que puedan cambiar de tamaño durante la


ejecución del programa, se puede crear 'arrays' dinámicos, pero una vez creados, el
tamaño también será fijo, y para hacer que crezcan o disminuyan de tamaño, se debe
reconstruirlas desde el principio.

Una lista simple abierta tiene la siguiente forma:

Por ejemplo:

Definición:

Una lista encadena simple es un conjunto finito de elementos autoreferenciados llamados


nodos, donde cada nodo se conecta al siguiente por medio de un campo de enlace.

Además:

 Existe un puntero ‘raiz’ que almacena la dirección del primer nodo.


 Cada nodo se conecta al siguiente por medio de un enlace (puntero).
 Todos los nodos, excepto el último, tienen un solo nodo sucesor.
 Todos los nodos, excepto el primero tienen un solo nodo antecesor, el cual no es
accesible desde el nodo.
 El campo enlace del ultimo nodo apunta a nulo.
 Son estructuras secuenciales unidireccionales.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 114


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Estructura de un nodo:

Un nodo tiene dos campos: para el almacenamiento de la información (info) y para el


enlace al siguiente nodo (sig)

struct Nodo
{
int info;
Nodo *sig;
};
typedef Nodo *NNodo;

La lista existe a partir de la variable puntero llamada ‘raiz:

RaízNULL lista vacía.

5.5.1. OPERACIONES BASICAS EN UNA LISTA SIMPLE.

En una lista simple se puede realizar las siguientes operaciones básicas:

 Creación: Normalmente la lista se crea vacía.


 Adición: se aumenta un nodo a la lista y puede ser al principio, al final o en una lista
ordenada.
 Eliminación: se elimina un nodo de la lista y puede ser el primero, el último o un
nodo de referencia.
 Recorrido: es el acceso a todos los nodos de la lista con un propósito determinado.
 Búsqueda: para verificar si una valor está o no en la lista.

ADICION.

Se aumenta un nodo en la lista. En la siguiente ilustración se adiciona al principio de


la lista.

Se considera un nodo a insertar, con un puntero que apunte a él, y de una lista, en este
caso puede ser vacía o no vacía:

 Pedir memoria en un puntero ‘nuevo’


 Almacenar la información ‘dato’ en el campo info.
 El campo ‘sig’ del ‘nuevo’ nodo apunta a la ’raiz’
 La ‘raiz’ apunta al nodo ‘nuevo’

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 115


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

ELIMINACION.

Se quita un nodo de la lista. En la siguiente ilustración se quita el primer nodo de la lista. Se


asume que la lista no está vacía.

 Se apunta al primer nodo con el puntero ‘pt’


 Se recupera el valor del campo ‘info’ del nodo ‘pt’
 ‘raiz’ apunta al siguiente nodo.
 Retornar el valor.

RECORRIDO.

El recorrido es el acceso a todos los nodos sin afectar la estructura, se debe emplear una
variable puntero de apoyo ‘pt’.

 ‘pt’ apunta a la ‘raiz’.


 Mientras ‘pt’ sea distinto de NULL
o Procesar la información de ‘pt’
o Recorrer al siguiente nodo.

BUSQUEDA.

Consiste en verificar si un valor está o no en la lista, esta operación es muy similar al


recorrido pero con la variante de que el proceso finaliza cuando se encuentra el valor
buscado o cuando se llega al final de la lista.

El siguiente programa ilustra las operaciones básicas descritas anteriormente.

El esquema de la clase se implementa en un archivo ‘.h’

struct Nodo
{
int info;
Nodo *sig;
};
typedef Nodo *NNodo;

class listasimple
{
Nodo *raiz;
public:
listasimple();
void crear();
int esvacia();
void adicion(int);

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 116


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int eliminar();
NNodo buscar(int);
void recorrido();
};

La implementación de la funciones de la clase se realiza en un programa ‘.cpp’

#include <d:\sis2210a\listas\lisimple.h>
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
//funcion constrauctora asigna NULL a la variable 'raiz'
// crea la lista vacia (raiz=NULL)
listasimple::listasimple()
{
raiz=NULL; //la lista se crea vacia
};

//la funcion crear, crea la lista vacia


//asigna el valor NULL a la variable raiz;
void listasimple::crear()
{
raiz=NULL;
}
// la funcion estado verifica si la lista esta vacia o no.
// retorna 1 si la lista esta vacia y 0 en caso contrario.
int listasimple::esvacia()
{
return (raiz==NULL);
}

//la funcion adicion aumenta un nodo al principio de la lista


// el nuevo nodo se constituira en el primero de la lista
void listasimple::adicion(int dato)
{
Nodo *nuevo;
nuevo=(Nodo *)malloc(sizeof(Nodo));
nuevo->info=dato;
nuevo->sig=raiz;
raiz=nuevo;
}
//la funcion eliminar recupera el valor del primer nodo de la lista
// y elimina ese nodo liberando memoria
//la fincion de eliminacion se invoca luego de verificar que la lista no este vacia.
int listasimple::eliminar()
{
Nodo *pt;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 117


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

pt=raiz;
int dato;
dato=raiz->info;
raiz=raiz->sig;
free(pt);
return dato;
}
// la funcion buscar verifica si un valor esta o no en la lista
// retorna NULL si el valor no esta den la lista y retorna distinto a NULL
// si el valor esta en la lista.
NNodo listasimple::buscar(int valor)
{
Nodo *pt=raiz;
while (pt!=NULL && valor!=pt->info)
pt=pt->sig;
return pt;
}
//la funcion recorrido accede a todos los nodos de la lista
//con un proposito determinado sin modificar la lista.
void listasimple::recorrido()
{
Nodo *pt=raiz;
cout<<"\nCONTENIDO DE LA LISTA:\n";
while (pt!=NULL)
{
cout<<pt->info<<"--->";
pt=pt->sig;
};
cout<<"null\n";
}

La implementación de objetos en un tercer archivo ‘.cpp’

#include <d:\sis2210a\listas\lisimple.cpp>
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>

main()
{
listasimple li;
li.crear();
li.adicion(11);
li.adicion(8);
li.adicion(17);
li.recorrido();
int dat=li.eliminar();
cout<<"\n valor eliminado :"<<dat;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 118


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

li.recorrido();
return 0;
}

La salida de la aplicación es la siguiente:

NOTA: los programas deben estar en la siguiente ruta: d:\sis2210a\listas\

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 119


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 6

ARCHIVOS

Todos los programas realizados hasta ahora obtenían los datos necesarios para su ejecución
de la entrada estándar (TECLADO) y visualizaban los resultados en la salida estándar
(PANTALLA). Por otra parte, el programa retiene los datos que manipula mientras esté en
ejecución; es decir, los datos introducidos se pierden cuando el programa finaliza.

La solución para hacer que los datos persistan de una ejecución para otra es almacenarlos
en un fichero o archivo en el disco, en vez de en un array en memoria. Entonces, cada vez
que se ejecute el programa que trabaja con esos datos, podrá leer del archivo los que
necesite y manipularlos. Nosotros procedemos de forma análoga en muchos aspectos de la
vida ordinaria; almacenamos los datos en fichas y guardamos el conjunto de fichas en 1o
que generalmente denominamos fichero o archivo.

6.1. DEFINICION.

Desde el punto de vista informático, un archivo es una colección de información que


almacenamos en un soporte magnético para poder manipularla en cualquier momento. Esta
información se almacena como un conjunto de registros (estructuras), conteniendo todos
ellos los mismos campos (miembros de la estructura). Cada campo almacena un dato de un
tipo predefinido o definido por el usuario.

Un archivo es un conjunto de información relacionada, manejada como unidad y que se


dispone en un dispositivo de almacenamiento secundario.

6.2. PROPIEDADES DE UN ARCHIVO.

Todo archivo localizado en un dispositivo de almacenamiento secundario tiene las


siguientes propiedades:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 120


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

NOMBRE.

Es un conjunto de caracteres que identifica el contenido del archivo, no puede


exceder los 8 caracteres, es decir es un identificador valido.

 El primer carácter es una letra.


 No contiene espacios en blanco.
 No contiene operadores aritméticos.
 No contiene operadores de relación.
 No es una palabra reservada del lenguaje o del sistema.

EXTENSIÓN.

Normalmente es un conjunto de tres caracteres que establece el tipo de archivo en el


dispositivo de almacenamiento secundario.

.exe Archivo ejecutable intersegmentario.


.com Archivo ejecutable unisegmentario.
.bat Archivo de ejecución por lotes.
.sys Archivo de configuración del sistema.
.*** Archivo del usuario.
.cpp
.pas
.doc
.xls
.ppt
.dat archivo de datos del usuario.

TAMAÑO.

Todo archivo ocupa un espacio en el dispositivo magnético y normalmente se


expresa en bytes.

LOCALIZACION O PATH.

Un archivo se localiza en algún lugar del dispositivo de almacenamiento secundario,


se denomina también ruta del archivo.

FECHA DE CREACION/MODIFICACION/ULTIMO ACCESO.

El sistema operativo almacena automáticamente estas fechas de procesamiento del


archivo.

PUNTERO DE LECTURA/ESCRITURA.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 121


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Permite el acceso al contenido del archivo y se desplaza automáticamente cada vez


que se realiza una operación de lectura y escritura, el comportamiento del puntero
de L/E del archivo varia dependiendo de la forma de organización del archivo.

FIN DE ARCHIVO.

Al final del contenido de un archivo existe una marca de finalización EOF (End Of
File) que evita que se afecte otros sectores de memoria que no pertenecen al archivo.

6.3. ORGANIZACIÓN DE UN ARCHIVO.

La organización de un archivo define la forma de almacenamiento de la información en el


medio magnético, al mismo tiempo establece el comportamiento que tendrá el puntero de
lectura y escritura del archivo y la forma de lectura y escritura de información en el archivo.

Básicamente se tiene dos formas de organización de un archivo que determina la forma de


acceso a la información contenida en el mismo.

6.3.1. ORGANIZACIÓN SECUENCIAL.

La organización secuencial se caracteriza porque la información se graba como una


secuencia de caracteres, es decir, son archivos de texto. Tienen las siguientes
características:

 Ocupan un bloque compacto y contiguo de memoria.


 Los registros lo constituyen líneas de texto que son de diferente longitud.
 No tiene significancia el desplazamiento arbitrario del puntero de lectura y escritura,
es decir, el puntero de L/E se desplaza automáticamente cada vez que se realiza una
lectura o escritura en el archivo.
 La información se lee o graba por: caracteres, palabras o por cadenas de caracteres
(líneas de texto).
 El acceso a la información es secuencial.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 122


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

6.3.2. ORGANIZACIÓN DIRECTA/RANDOMICA O ALEATORIA.

La Organización Directa/Aleatoria/Randómica se caracteriza porque la información se


graba por bloques del mismo tamaño, corresponde a los archivos de datos tipeados. Tiene
las siguientes características:

 Ocupan bloques dispersos y aleatorios de memoria.


 Los registros tienen el mismo tamaño y corresponden a tipos de datos predefinidos
o definidos por el usuario.
 Cada registro tiene una dirección de registro.
 El Puntero de L/E se puede desplazar arbitrariamente por medio de la dirección del
registro.
 Establece un Acceso Directo a la información del archivo, es decir, para localizar
un registro se puede emplear la dirección del registro y no es necesario recorrer toda
la información previa.
 El archivo es similar a una tabla donde las columnas lo constituyen los campos de la
estructura y las filas lo constituyen los registros del archivo.
 La Lectura y Escritura de información se realiza por bloques del mismo tamaño.
 El acceso a la información es directa.

6.4. USO DE ARCHIVOS.

La información contenida en un archivo, normalmente tiene 2 usos fundamentales:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 123


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

a) CONSULTAS.

Se puede acceder a la información contenida en el archivo por medio de algún


criterio de consulta, ya sea para reportes o para algún otro proceso especifico. Se
puede consultar toda la información del archivo o simplemente alguna porción de la
información.

b) ACTUALIZACION.

La información contenida en el archivo debe reflejar cierta realidad en un momento


específico, es decir debe ser actualizada, para lograr que la información este
actualizada se realiza operaciones de ADICION, MODIFICACION Y
ELIMINACION.

6.5. ENTRADA Y SALIDA EN ARCHIVOS.

La Entrada y Salida en un archivo, conocido también como Lectura y Escritura, se realiza


de maneras diferentes dependiendo de la organización del archivo. Puede ser de la siguiente
manera:

6.6. PROCESAMIENTO DE ARCHIVOS EN EL DISCO.

Para poder escribir o leer sobre un fichero, primeramente hay que abrirlo. El fichero puede
ser abierto para leer, para escribir o para leer y escribir.

En C y en C++ abrir un fichero significa definir un stream (flujo) que permita el acceso al
fichero en el disco para leer o escribir. La definición del stream supone la definición de un
buffer (memoria intermedia) para conectar el stream con el fichero en el disco. Esto permite
referirse al stream como si fuera el fichero (más adelante veremos que un stream se define
como un puntero a una estructura de tipo FILE).

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 124


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

6.6.1. ABRIR UN ARCHIVO.

Para poder escribir o leer de un archivo, primeramente hay que abrirlo con las funciones
fopen o freopen. El fichero puede ser abierto para leer, para escribir o para leer y escribir.

Cuando un programa comienza su ejecución, son abiertos automáticamente tres ficheros,


que se corresponden con otros tres dispositivos. Estos ficheros, direccionados por streams,
y los dispositivos asociados por defecto son:

Para la apertura de un archivo es necesario declarar un puntero a una estructura del tipo
FILE, este puntero se constituye en el stream que se emplea en el programa.

Por ejemplo:

FILE *arch;

La función ‘fopen’ abre un archivo especificado para un modo determinado.

fopen(“nombre-archivo”,”modo-aperttura”)

Por ejemplo:

arch = fopen (“medicina.dat”,”wb”);

el puntero ‘arch’ captura el resultado de la apertura del archivo ‘medicina.dat’ para el modo
de escritura (w) y en formato binario(b).

Los diferentes modos de apertura de un archivo o fichero son los que se ilustran en la
siguiente tabla:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 125


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Es recomendable utilizar, adicionalmente, el modo binario ‘b’ que se adiciona al modo de


apertura descrito en la tabla anterior. Si no se especifica el modo binario ‘b’, entonces el
lenguaje asume que el archivo se abre en modo texto (t).

La función fopen devuelve un puntero a una estructura de tipo FILE que define, entre otros
datos, el buffer asociado con el fichero abierto. Un puntero nulo indica un error en la
apertura. El puntero devuelto por fopen recibe el nombre de stream y es utilizado por las
funciones estándar de E/S para leer y escribir datos en un archivo. Por esta razon, antes de
invocar a la función fopen hay que definir un puntero que apunte a una estructura de tipo
FILE.

Por ejemplo:

FILE *arch;
arch = fopen("datos", "w");
if (arch== NULL)
printf("Error: el fichero no se puede abrir\n");

6.6.2. CERRAR EL ARCHIVO.

Después de realizar las tareas de procesamiento en el archivo, es necesario cerrar el archivo


con la función ‘fclose’. Si un archivo no se cierra explícitamente, el lenguaje se encarga de
cerrarlo automáticamente una vez finalizada la ejecución del programa. Sin embargo es
recomendable cerrar el archivo durante la ejecución de un programa debido a que existe un
límite para mantener archivos abiertos simultáneamente.

La función ‘fclose’ cierra el stream que se especifica.

Por ejemplo:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 126


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

fclose(arch);

6.6.3. CONTROL DE FIN DE ARCHIVO ‘EOF’

El sistema incorpora una marca de fin de archivo EOF automáticamente cuando el archivo
es creado y si se intenta leer un archivo más allá de la marca de fin de archivo, entonces se
activa el indicador de fin de archivo.

La función ‘feof’ determina el estado del indicador de fin de archivo. La función feof
devuelve un valor distinto de 0 cuando se intenta leer un elemento del archivo y nos
encontramos con un eof (end of file - fin de fichero), en caso contrario devuelve un 0.

Por ejemplo:
while (!feof(arch)) // mientras no se llegue al final del archivo ‘arch’
….

6.6.4. ACCESO DIRECTO O ALEATORIO (fseek).

Normalmente el acceso a la información de un archivo es de manera secuencial, es decir,


primero se accede al primer registro, luego al segundo, luego al tercero y así sucesivamente
hasta llegar al final del archivo, sin embargo en archivos con organización directa es
posible acceder a cualquier registro del archivo sin necesidad de acceder a los registros
anteriores.

La función ‘fseek’ permite desplazar el puntero de Lectura/Escritura de un puntero


asociado a un archivo a una nueva localización desplazando cierta cantidad de bytes a partir
de una posición dada.

El formato de la función ‘fseek’ es el siguiente:

int fseek(File *p, long desp, int pos);

Desplaza el puntero de L/E de ‘p’ ‘desp’ bytes a partir de la posición ‘pos’

Generalmente ‘desp’ es un valor entero mayor o igual a 0 y es un múltiplo del


tamaño en bytes del registro que se almacena en el archivo.

La posición ‘pos’ a partir de la cual se desplaza el puntero de L/E puede tomar


alguno de los siguientes valores:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 127


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La función ‘fseek’ retorna un valor 0 si no se ha producido un error y retorna un valor


distinto a 0 si existe un error.

Por ejemplo:

fseek(arch,0,SEEK_END);

Esta instrucción desplaza el puntero de L/E de ‘arch’ 0 bytes a partir del final del
archivo, es decir, lleva el puntero de L/E de ‘arch’ al final del archivo.

6.6.5. CONOCER LA POSICION ACTUAL DEL PUNTERO DE L/E.

Si se desea conocer la posición actual del puntero de L/E del archivo se debe emplear la
función ‘ftell’. El valor o posición que retorna ‘ftell’ es un entero relativo al principio del
archivo.

La función ‘ftell’ tiene el siguiente formato:

long ftell(FILE *p);

Por ejemplo:

posi=ftell(arch);

Almacena en la variable ‘posi’ la posición actual del puntero de L/E del archivo
apuntado por arch.

6.6.6. RESTABLECER EL PUNTERO DE L/E AL PRINCIPIO.

La función ‘rewind’ establece el puntero de L/E de un archivo al principio del archivo.

La función ‘rewind’ tiene el siguiente formato:

(void) rewind(FILE *p);

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 128


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Por ejemplo:

rewind(arch);

Establece el puntero de L/E de ‘arch’ al principio del archivo.

Es equivalente a ejecutar la siguiente instrucción:

fseek(arch,0,SEEK_SET);

6.7. PASOS PARA EL PROCESAMIENTO DE ARCHIVOS.

El Procesamiento de la información contenida en un archivo, independientemente del


lenguaje de programación, estable el cumplimiento de los siguientes pasos:

1. Definir la estructura del registro del archivo.


2. Declarar un puntero a archivo
3. Abrir el archivo
4. Procesar la información del archivo:
a. Lectura
b. Escritura
c. control de fin de archivo
d. desplazar el puntero de lectura y escritura del archivo
e. conocer la posición actual del puntero de L/E
f. etc.
5. Cerrar el archivo.

Generalmente los pasos 1 y 2 se realizan una vez pero los pasos 3, 4 y 5 se realizan cada
vez que se manipula la información del archivo.

6.8. OPERACIONES BÁSICAS EN UN ARCHIVO.

Existe un conjunto de operaciones básicas que se desarrollan en un archivo.

a) CREACIÓN.

Normalmente un archivo se crea vacío. Se debe ejecutar las siguientes acciones:

 Abrir el archivo para escritura (“wb”)


 Cerrar el archivo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 129


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) ADICION DE REGISTROS.

La adición de registros consiste en aumentar un registro a partir del final del archivo
y se debe considerar las siguientes acciones:

 Abrir el archivo para adición (“ab+”).


 Leer la información de un registro desde el teclado o recuperar de otro
proceso.
 Grabar el registro en el archivo.
 Cerrar el archivo.

c) REPORTE GENERAL DE REGISTROS.

Muestra todos los registros del archivo, normalmente por pantalla.

 Abrir el archivo para lectura (“rb”).


 Leer todos los registros y mostrar por pantalla.
 Cerrar el archivo.

d) BUSQUE DE UN REGISTRO.

La operación de búsqueda consiste en determinar si un registro, a base de un campo


arbitrario, está o no en el archivo. Si está en el archivo retorna la posición del
registro en el archivo y retorna -1 en caso contrario.

 Abrir el archivo para lectura (“rb”).


 Leer los registros del archivo mientras no se llegue al final del archivo y el
registro buscado no sea encontrado.
 Determinar la posición del registro encontrado 0 -1 en caso contrario.
 Cerrar el archivo
 Retornar la posición determinada.

e) MODIFICACIÓN DE REGISTROS.

La operación de modificación de registros consiste en cambiar el contenido de uno o


más campos del registro, la nueva información se debe grabar en el mismo lugar del
registro en el archivo.

 Buscar el registro a modificar.


 Si el registro a modificar esta en el archivo, entonces
o Abrir el archivo para lectura y escritura (“rb+”).
o Posicionar el puntero de L/E en el lugar del registro.
o Leer el registro del archivo.
o Mostrar la información actual del registro.
o Leer la nueva información del registro.
o Posicionar el puntero de L/E en el lugar del registro.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 130


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

o Grabar la nueva información del registro.


o Cerrar el archivo.

f) ELIMINACION LOGICA DE REGISTROS.

La eliminación lógica de registros consiste en desactivar el registro deseado, es


decir, la información no desaparece del archivo. Los registros del archivo tienen un
campo especial llamado ‘estado’, este campo almacena un valor 1 cuando el registro
está activo y almacena el valor 0 cuando el registro está inactivo, por lo tanto, la
eliminación lógica de registros consiste en almacenar el valor 0 en el campo estado
del registro deseado.
 Buscar el registro a eliminar en forma lógica.
 Si el registro a eliminar esta en el archivo, entonces
o Abrir el archivo para lectura y escritura (“rb+”).
o Posicionar el puntero de L/E en el lugar del registro.
o Leer el registro del archivo.
o Mostrar la información actual del registro.
o Almacenar 0 en el campo estado.
o Posicionar el puntero de L/E en el lugar del registro.
o Grabar la nueva información del registro.
o Cerrar el archivo.

g) ELIMINACION FISICA DE REGISTROS.

Esta operación se ejecuta muy pocas veces porque la información del registro
desaparece del archivo definitivamente. Regularmente solo se elimina físicamente
los registros que previamente han sido eliminados en forma lógica.

La eliminación física de registros supone el empleo de un archivo temporal. Se


copia al archivo temporal todos los registros del archivo original cuyo campo estado
es 1, luego se borrar el archivo original y se renombra el archivo temporal por el
nombre del archivo original

 Abrir el archivo original o principal para lectura (“rb”).


 Abrir el archivo temporal para escritura (“wb+”).
 Copiar todos los registros del archivo original al temporal con el campo
estado 1.
 Cerrar los dos archivos.
 Borrar el archivo original.
 Renombrar el archivo temporal.

h) RESTAURACION DE REGISDTROS ELIMINADOS EN FORMA LÑOGICA.

Un registro eliminado en forma lógica (inactivo) se puede restaurar para que este
activo nuevamente, esto significa que se debe almacenar 1 en el campo estado.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 131


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

 Buscar el registro a restaurar.


 Si el registro a restaurar está en el archivo, entonces
o Abrir el archivo para lectura y escritura (“rb+”).
o Posicionar el puntero de L/E en el lugar del registro.
o Leer el registro del archivo.
o Mostrar la información actual del registro.
o Almacenar 1 en el campo estado.
o Posicionar el puntero de L/E en el lugar del registro.
o Grabar la nueva información del registro.
o Cerrar el archivo.

Este conjunto de operaciones básicas constituyen la base fundamental para el desarrollo de


otras operaciones con la información contenida en un archivo como ser: partición de
archivos, mezcla de archivo, clasificación de archivos, etc.

6.9. EJEMPLO DE APLICACIÓN DE ARCHIVOS DIRECTOS.

El programa siguiente implementa las operaciones básicas en un archivo de acceso directo.

1. DEFINICIÓN DE LA ESTRUCTURA DEL REGISTRO.

Para la presente ilustración se emplea el almacenamiento de información de medicamentos


con los siguientes campos:

 Código
 Nombre
 Precio
 Procedencia
 Estado

2. ESQUEMA DE LA CLASE

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 132


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

3. IMPLEMENTACION.

a) Esquema de la clase: ‘farmacia.h’

//definicion de la estructura del registro


struct producto
{
int cod;
char nombre[15];
float precio;
int proced;
int estado;
};
//definicion del esquema de la clase 'farmacia'
class farmacia
{
FILE *arch;
public:
void crear();
void adicion();
int buscar(int);
void modificar(int);
void elilogica(int);
void elifisica();
void reporte();
void reportei();
void reporteesp(int);
void restaurar(int);
};

b) Implementación de los métodos o funciones de la clase farmacia: ‘farmacia.cpp’

#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <e:/jcbv/materia/sis2210/sis2210prog/archivosc++/farmacia.h>

//CREACION DE UN ARCHIVO
//EL ARCHIVO SE CREA VACIO.
void farmacia::crear()
{
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","wb");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
cout<<"\n ARCHIVO CREADO CON EXITO, FELICIDADES\n";

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 133


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

cout<<"\n presione cualquier tecla para continuar: ";


getch();
}

//ADICION DE REGISTRO.
//ADICIONA UN REGISTRO A PARTIR DEL FINAL DEL ARCHIVO
void farmacia::adicion()
{
producto reg;
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","ab+");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n ADICION DE UN REGISTRO EN EL ARCHIVO\n";
cout<<"\n codigo del MEDICAMENTO:";
cin>>reg.cod;
cout<<"\n NOMBRE del MEDICAMENTO:";
cin>>reg.nombre;
cout<<"\n PRECIO del MEDICAMENTO:";
cin>>reg.precio;
cout<<"\n PROCEDENCIA del MEDICAMENTO 0:NACIONAL; 1: IMPORTADO:";
cin>>reg.proced;
reg.estado=1;
fwrite(&reg,sizeof(struct producto),1,arch);
cout<<"\nregistro grabado con exito\n";
fclose(arch);
getch();
};
}

//REPORTE GENERAL DEL ARCHIVO


void farmacia::reporte()
{
producto reg;
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n REPORTE DE LOS REGISTROS activos DEL ARCHIVO\n";
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
fread(&reg,sizeof(struct producto),1,arch);
while (!feof(arch))
{
if (reg.estado==1)
printf("\n%5d %15s %5.2f %4d %4d",reg.cod,reg.nombre,reg.precio,reg.proced,reg.estado);
//cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
fread(&reg,sizeof(struct producto),1,arch);
};
cout<<"\n===================================================";
cout<<"\npresione cualquier tecla para continuar:";

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 134


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

getch();
fclose(arch);
};
}

// reporte de registros inactivos


void farmacia::reportei()
{
producto reg;
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n REPORTE DE LOS REGISTROS INactivos DEL ARCHIVO\n";
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
fread(&reg,sizeof(struct producto),1,arch);
while (!feof(arch))
{
if (reg.estado==0)
cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
fread(&reg,sizeof(struct producto),1,arch);

};
cout<<"\n===================================================";
cout<<"\npresione cualquier tecla para continuar:";
getch();
fclose(arch);
};
}

//BUSQUEDA DE UN REGISTRO EN EL ARCHIVO


//LA BUSQUEDA SE REALIZA POR MEDIO DEL CAMPO CODIGO
int farmacia::buscar(int clave)
{
producto reg;
int sw=0,res;
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
while (!feof(arch) && sw==0)
{
fread(&reg,sizeof(struct producto),1,arch);
if (clave==reg.cod)
sw=1;
};
if (sw==0)
res=-1;
else
res=ftell(arch)-sizeof(struct producto);
fclose(arch);

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 135


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

}; return res;
}

//MODIFICA UN REGISTRO DEL ARCHIVO


void farmacia::modificar(int clave)
{
producto reg;
int res;
res=buscar(clave);
if (res==-1)
cout<<"\n El registro N0 esta en el archivo\n";
else
{
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb+");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n CONTENIDO ACTUAL DEL REGISTRO EN EL ARCHIVO\n";
fseek(arch,res,SEEK_SET);
fread(&reg,sizeof(producto),1,arch);
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
cout<<"\n===================================================";
cout<<"\nINTRODUCIR LA NUEVA INFORMACION DEL MEDICAMENTO:\n";
cout<<"\n NOMBRE del MEDICAMENTO:";
cin>>reg.nombre;
cout<<"\n PRECIO del MEDICAMENTO:";
cin>>reg.precio;
cout<<"\n PROCEDENCIA del MEDICAMENTO 0:NACIONAL; 1: IMPORTADO:";
cin>>reg.proced;
fseek(arch,res,SEEK_SET);
fwrite(&reg,sizeof(struct producto),1,arch);
cout<<"\nregistro modificadoo con exito\n";
fclose(arch);
};
};
getch();
}

//ELIMINACION LOGICA DE REGISTROS DEL ARCHIVO


void farmacia::elilogica(int clave)
{
producto reg;
int res;
res=buscar(clave);
if (res==-1)
cout<<"\n El registro N0 esta en el archivo\n";
else
{
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb+");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 136


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

else
{
clrscr();
cout<<"\n CONTENIDO ACTUAL DEL REGISTRO EN EL ARCHIVO\n";
fseek(arch,res,SEEK_SET);
fread(&reg,sizeof(producto),1,arch);
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
cout<<"\n===================================================";
cout<<"\npresione cualquier tecla para continuar:\n";
getch();
reg.estado=0;
fseek(arch,res,SEEK_SET);
fwrite(&reg,sizeof(struct producto),1,arch);
cout<<"\nregistro eliminado exito\n";
fclose(arch);
};
};
getch();
}
// eliminacion fisica de registros
// solo se elimina los registros eliminados en forma logica
void farmacia::elifisica()
{
producto reg;
FILE *ft;
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb");
ft=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.tmp","wb");
if (arch==NULL || ft==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n ELIMINACION FISICA DE REGISTROS\n";
fread(&reg,sizeof(struct producto),1,arch);
while (!feof(arch))
{
if (reg.estado==1)
fwrite(&reg,sizeof(struct producto),1,ft);
fread(&reg,sizeof(struct producto),1,arch);
};
cout<<"\nse han copiado satisfactoriamente los registros al archivo temporal\n";
cout<<"\npresione cualquier tecla para continuar:";
getch();
fclose(arch);
fclose(ft);
char cad[100],cad1[100];
strcpy(cad,"e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat");
strcpy(cad1,"e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.tmp");
remove(cad);
rename(cad1,cad);
};
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 137


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

//reporte de un registro especifico


void farmacia::reporteesp(int clave)
{
producto reg;
int res;
res=buscar(clave);
if (res==-1)
cout<<"\n El registro N0 esta en el archivo\n";
else
{
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n CONTENIDO ACTUAL DEL REGISTRO EN EL ARCHIVO\n";
fseek(arch,res,SEEK_SET);
fread(&reg,sizeof(producto),1,arch);
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
cout<<"\n===================================================";
cout<<"\npresione cualquier tecla para continuar\n";
fclose(arch);
};
};
getch();
}
//restauracion de registros eliminados en forma logica
void farmacia::restaurar(int clave)
{
producto reg;
int res;
res=buscar(clave);
if (res==-1)
cout<<"\n El registro N0 esta en el archivo\n";
else
{
arch=fopen("e:/jcbv/materia/sis2210/sis2210prog/archivosc++/medicina.dat","rb+");
if (arch==NULL)
cout<<"\n ERROR EN LA APERTURA DEL ARCHIVO\n";
else
{
clrscr();
cout<<"\n CONTENIDO ACTUAL DEL REGISTRO EN EL ARCHIVO\n";
fseek(arch,res,SEEK_SET);
fread(&reg,sizeof(producto),1,arch);
cout<<"\nCODIGO NOMBRE PRECIO PROCDEDENCIA ESTADO";
cout<<"\n===================================================";
cout<<"\n"<<reg.cod<<" "<<reg.nombre<<" "<<reg.precio<<" "<<reg.proced<<"
"<<reg.estado;
cout<<"\n===================================================";
reg.estado=1;
fseek(arch,res,SEEK_SET);

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 138


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

fwrite(&reg,sizeof(struct producto),1,arch);
cout<<"\nregistro restaurado con exito\n";
fclose(arch);
};
};
getch();
}

c) Implantación del programa: ‘prueba.cpp’

#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <e:/jcbv/materia/sis2210/sis2210prog/archivosc++/farmacia.cpp>
int main()
{
farmacia f;
int op,clave;

do {
clrscr();
cout<<"\n PROCEAMIENTO DE ARCHIVOS DIRECTOS";
cout<<"\n ======================================";
cout<<"\n 1: CREACION DEL ARCHIVO VACIO";
cout<<"\n 2: ADICION DE REGISTROS";
cout<<"\n 3: REPORTE GENERAL DE REGISTROS ACTIVOS";
cout<<"\n 4: REPORTE DE REGISTROS INACTIVOS";
cout<<"\n 5: REPORTE DE UN REGISTRO ESPECIFICO";
cout<<"\n 6: MODIFICACION DE REGISTROS";
cout<<"\n 7: ELIMINACION LOGICA";
cout<<"\n 8: ELIMINACION FISICA !!!!!";
cout<<"\n 9: RESTAURAR REGISTROS";
cout<<"\n 10: SALIR DE LA APLICACION";
cout<<"\n ======================================";
cout<<"\n ELIJA LA TAREA A REALIZAR : ";
cin>>op;
switch (op)
{
case 1: f.crear();break;
case 2: f.adicion();break;
case 3: f.reporte();break;
case 4: f.reportei();break;
case 5: clrscr();
cout<<"\ncodigo del medicamento:";
cin>>clave;
f.reporteesp(clave);
break;
case 6: clrscr();
cout<<"\ncodigo del medicamento a modificar:";
cin>>clave;
f.modificar(clave);
break;
case 7: clrscr();
cout<<"\ncodigo del medicamento a eliminar:";
cin>>clave;
f.elilogica(clave);

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 139


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

break;
case 8: clrscr();
f.elifisica();
break;
case 9: clrscr();
cout<<"\ncodigo del medicamento a RESTAURAR:";
cin>>clave;
f.restaurar(clave);
break;
};
} while (op<10);
return 0;
}

4. Salida de la ejecución del programa.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 140


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 141


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

BIBLIOGRAFIA

1. DEITEL/DEITEL. COMO PROGRAMAR EN C/C++.


2. JOYANES AGUILAR LUIS. FUNDAMENTOS DE PROGRAMACION.
3. CEBALLOS SIERRA FCO. XAVIER. CURSO DE. PROGRAMACION C/C++.
4. JOYANES AGUILAR LUIS. PROGRAMACION ORIENTADA A OBJETOS.
5. MARTINES DEL RIO FRANCISCO. FUNDAMENTOS BASICDOS DE PROGRAMACION EN C++.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 142

También podría gustarte