Anda di halaman 1dari 204

ALGORITMOS

Y
ESTRUCTURAS DE DATOS
EN
LENGUAJE C/C++
Humberto Mazuera Prraga

TABLA DE CONTENIDO alfabtica


Agente Aprende a Recorrer Laberinto.................................................................
rboles(esta en archivo separado).....................................................................
Archivos Binarios y de Texto...............................................................................
Bsqueda Binaria: Algoritmo Recursivo para encontrar Elemento en Vector.......
Cadenas de Caracteres........................................................................................
Cdigo ASCII.......................................................................................................
Cola en Arreglo...................................................................................................
Cola como Lista Enlazada....................................................................................
Estadstica Bsica...............................................................................................
Evaluacin de Expresin Algebraica....................................................................
Expresin de Lgica Proposicional.....................................................................
Leer Cadena en Modo Grfico..............................................................................
Lista de Listas enlazadas y en memoria dinmica...............................................
Lista Doblemente Enlazada.................................................................................
Lista Simplemente Enlazada y Ordenada.............................................................
Listas Enlazadas, Ejercicios de Programacin.....................................................
Lgica Proposicional, expresiones......................................................................
MergeSort: Algoritmo Recursivo de Ordenamiento..............................................
Ordenamientos. Comparacin Grfica.................................................................
Paso de Parmetros por Referencia en Funciones...............................................
Pila en Arreglo y Memoria Esttica......................................................................
Pila en Lista Enlazada y en Memoria Dinmica....................................................
Polaca. Notacin para expresiones algebraicas...................................................
Polaca. Expresin de Lgica Proposicional.........................................................
Puntero a Notas Musicales..................................................................................
Punteros o Apuntadores.....................................................................................
QuickSort............................................................................................................
Recursin............................................................................................................
Torres de Hanoi..................................................................................................
Vector de Punteros a Funciones.........................................................................
Primera Parte

Segunda Parte

Tercera Parte

PRIMERA PARTE
PILAS Y COLAS EN ARREGLOS.
RECURSIN.
PUNTEROS.
PASO POR REFERENCIA.
CADENAS.
REFUERZO REGISTROS Y ARCHIVOS.
Algoritmos de Ordenamiento.
Primera Parte

Segunda Parte

Tercera Parte

Pila en Arreglo
Introduccin
Una pila, a un nivel lgico, es una estructura de datos lineal compuesta de
elementos del mismo tipo, en la cual cada uno de ellos solo puede ser insertado y
eliminado por su parte final. La posicin final la llamamos cima o tambin cabeza
de la pila; para darnos una mejor representacin (abstraccin) de ella su
representacin grfica en el papel la hacemos en forma vertical, con la cima en
la parte de arriba. De esta forma cuando aadamos un nuevo elemento solo podr
ser colocado en la parte superior, piense en una pila de platos de cocina o en
una pila de libros, los cuales coloque en orden uno encima de otro. Debido a esto
ltimo las pilas tambin son llamadas listas en las cuales "el ltimo elemento en
entrar es el primero en salir", en ingls el acrnimo LIFO(Last Input, First
Out).
La pila se considera un grupo ordenado de elementos porque estos estn
clasificados de acuerdo al tiempo en que estn residiendo en la pila, el elemento
que se elimina de la cabeza es siempre el que lleve menos tiempo en ella. En
resumen una pila es una lista en la cual los elementos solo pueden ser insertados
y eliminados por un extremo de ella, este extremo es llamado la cima. De esta
forma los elementos son eliminados en forma contraria a como fueron insertados.
Las operaciones bsicas de insertar y eliminar las llamaremos Meter() y
Sacar() respectivamente, y sern implementadas sobre la estructura de datos
arreglo unidimensional en el presente captulo.
Una Pila es una estructura de datos que almacena elementos de un tipo
determinado, que sigue la poltica de que el primer elemento que se extrae (se
desapila) es el ltimo que se introdujo (se apil) -primero en salir, ultimo
en entrar (LIFO)-.

Pila de Cadena de caracteres.


#include
#include
#include
#include

//PILACHAR.CPP

<iostream.h>
<stdio.h>
<ctype.h>
<string.h>

const int MaxPila=5;


const int LargoCadena=20;
const int PilaVacia=-1;
char Pila[MaxPila][LargoCadena]; //Variables globales
int Cima = PilaVacia;
void meter();
// Definicin de prototipos
void sacar();
void EscribirValoresEnPila();
void meter(){
char item[LargoCadena];
if (Cima == MaxPila-1){
cout << "\n\nDesbordamiento. Digite una tecla";
}
else{
cout << "\nDigite elemento (una palabra): ";
cin >> item;
Cima++;
strcpy(Pila[Cima], item);
}
}
void sacar(){
char item[LargoCadena];
if (Cima == PilaVacia)
cout << "\n\nSubdesbordamiento. digite una tecla";
else {
strcpy(item, Pila[Cima]);
cout << "Sacado de la pila: " << item;
Cima--;
}
}
void EscribirValoresEnPila(){
int i;
if (Cima > PilaVacia)
for (i = Cima; i >= 0; i--)
cout << i << ": " << Pila[i] << endl;
else
cout << "Pila est vaca\n";
}
void main(){
char opcion;

do{
EscribirValoresEnPila();
cout << "\nPuede introducir en la Pila un mximo de "
<< MaxPila << " elementos\n";
cout << "Meter Sacar Terminar: digite M, S o T: ";
cin >> opcion;
switch (toupper(opcion)) {
case 'M' : meter(); break;
case 'S' : sacar(); break;
}
} while (opcion != 'T');
}
La siguiente es una prueba de ejecucin manual del programa PILACHAR.CPP anterior
y el cual maneja una pila de cadenas de caracteres:
Inicialmente se definen las siguientes constantes y variables:
const
const
const
char

int MaxPila = 5;
int LargoCadena = 10;
int PilaVaca = -1;
Pila[MaxPila][LargoCadena];
4
3
2
1
0

Cima=PilaVacia;

-1

A partir de la funcin principal, main(), podemos efectuar invocacin


interactiva de las funciones meter() y sacar(). Analicemos primero la funcin
meter():
void meter(){
char item[LargoCadena];
if (Cima == MaxPila-1)
cout << "\n\nDesbordamiento. Digite una tecla";
else{
cout << "\nDigite elemento (una palabra): ";
cin >> item;
Cima++;
strcpy(Pila[Cima], item);
}
}
Al entrar a la funcin meter() nos encontramos con:
if(Cima == MaxPila-1)
-1 == 5-1
es falso vamos para el else, si fuera verdadera estara ya llena la pila. A

continuacin se pide digitar un elemento, o sea una palabra, leyendose en la


variable item: "Cali", Cima se incrementa en uno, y se asigna el item digitado a
la Cima de la Pila:
item

Cali

4
3

Cima

2
1
0

Pila

Cali

A continuacin volvamos a invocar la funcin meter(): Cima no es igual a


MaxPila-1, por esto, se digitan los caracteres: "Palmira" los cuales son ledos
en la variable item, se encrementa Cima y se asignan a la Cima de la Pila,
retornando al sitio donde la funcin fu invocada, en el main():
item

Palmira

4
3

Cima

2
1
0

Pila

Palmira

Cali

Una vez ms se invoca meter(): se digita la palabra "Zarzl" y la pila


ahora as:
item

Zarzl

4
3

Cima

2
1
0

queda

Pila

Zarzl

Palmira

Cali

Se invoca meter(): se digita la cadena "Toro" y la pila quedar ahora:


item

Toro

4
3

Cima

Pila

Toro

2
1
0

Zarzl

Palmira

Cali

Se invoca meter(): se digita la palabra "Jamund" y la pila queda:


item

Jamund

4
3

Cima

2
1
0

Pila

Jamund

Toro

Zarzl

Palmira

Cali

Se invoca meter():
con este caso if (Cima==MaxPila-1)
es verdadero,
aparecer en pantalla: "Desbordamiento. Digite una tecla" y volver a la funcin
main() del programa.
Si invocamos a continuacin la funcin sacar():
void sacar(){
char item[LargoCadena];
if (Cima == PilaVacia)
cout << "\n\nSubdesbordamiento. digite una tecla";
else {
strcpy(item, Pila[Cima]);
cout << "Sacado de la pila: " << item;
Cima--;
}
}
Inicialmente intruccin if (Cima == PilaVaca) es falsa por esto seguir el
algoritmo en el else; en la variable item se asigna el valor que est en la Cima
de la Pila por medio de strcpy (item, Pila[Cima]) y a continuacin se decrementa
Cima en 1, quedando la pila as:
item

Jamund

Pila

3
Toro

Cima

2
Zarzl

1
Palmira

0
Cali

El elemento que estaba en la posicin 4 del vector Pila se ha borrado


"lgicamente", es decir del dibujo o sea de lo que debemos abstraer est

ocurriendo, en realidad la palabra Jamund sigue en Pila[4], empero ya como


"basura". Ahora, de nuevo, invoquemos sacar():
item

Toro

4
3

Cima

2
1
0

Pila

Zarzl

Palmira

Cali

Invocamos sacar():
item

Zarzal

4
3

Cima

2
1
0

Pila

Palmira

Cali

Invocamos sacar():
item

Palmira

Cima

de nuevo
item

Cali

Pila

0
Cali

invoquemos sacar():

4
3

Cima

-1

2
1
0

Pila

if (Cima == PilaVaca)
-1
-1
El if anterior
"subdesbordamiento.
continuacin.

es verdadero, por esto, aparecer en pantalla el aviso


Digite una tecla" y se regresar a la parte principal a

Pila Implementada con Punteros


//PILAPUNT.CPP
#include
#include
#include
#include
#include

<iostream.h>
<conio.h>
<iomanip.h>
<ctype.h>
<stdlib.h>

const int MaxPila=5;


void EscribirValoresEnPila(); //Definicin de prototipos
void meter(int *P);
void sacar(int *P);
int Pila[MaxPila]; //Definicin variables globales
int *Cima=NULL;
void main(){
int opcion;
for(;;){
EscribirValoresEnPila();
cout << "\nPuede introducir en la Pila un mximo de "
<< MaxPila << " elementos ";
cout << "\n\nMeter Sacar Terminar: digite M, S o T: ";
opcion = toupper( getch() );
switch (opcion) {
case 'M' : meter(Pila);
break;
case 'S' : sacar(Pila);
break;
case 'T' : exit(0);
}
}
}
void meter(int *P){
int item;
if (Cima == (P+MaxPila-1)){
cout << "\n\nDesbordamiento. Digite una tecla";
getch();
}
else {
if (Cima == NULL)
Cima = Pila; /*Inicializa Pila*/
else
Cima++;
cout << "\nDigite elemento(un entero): ";
cin >> item;
*Cima = item;
}
}
void sacar(int *P){
if ( !Cima )

10

cout << "\n\nSubdesbordamiento.";


else {
cout << "\n\nSacado de la pila: " << *Cima;
if (Cima == P) // Era el ltimo elemento
Cima = NULL;
else
Cima--;
}
}
void EscribirValoresEnPila(){
int *p;
clrscr();
if (Cima){
p = Cima;
while (p >= Pila){
cout << setw(10) << *p << endl;
p--;
}
}
else
cout << "Pila est vaca\n";
}

Programar a Manera de ejercicio


1. En el programa del laberinto que el profesor le entregar, efectele los
cambios necesarios para que el agente que se desplaza por el mismo, se pueda
devolver siguiendo sus mismos pasos. Para esto debe almacenar(meter), la posicin
inicial de el agente, y a continuacin almacenar (meter), cada movimiento,
derecha, izquierda, arriba o abajo en una pila, y cuando se le de la orden de
devolverse por medio del men, proceder a sacar desde el ltimo movimiento, y as
sucesivamente hasta llegar a la posicin inicial.
2. Disee funcin que en modo grfico presente una ventana al estilo de las del
Windows en una posicin dada por el usuario (x, y) de su esquina superior
izquierda, el ancho y el alto de la misma, los colores dselos por defecto. A
partir de un men se debe invocar esta funcin, de tal suerte que en pantalla
queden mltiples ventanas, eventualmente sobrepuestas a las anteriores. Almacene
la informacin de cada ventana en una pila de registros para que cuando se pida
desde el men poder retirar cada una en orden inverso a como fueron creadas.

11

Cola Implementada en Arreglo


Introduccin

Una cola es una lnea de espera como las que se forman en las casillas de los
bancos o en las entradas a cine. Desde el punto de vista de las estructuras de
datos una cola es una estructura de lineal, en la cual sus elementos solo pueden
ser insertados por un extremo y eliminados por el otro. La palabra cola viene del
poder simular con esta estructura la situacin real de las colas que hay que
efectuar para entrar a algn lugar o para poder recibir algn servicio, por
ejemplo: bancos, espectculos pblicos, transportes colectivos, etc.
En general en una cola, de la vida diaria, el primero que llega ser
atendido primero, pasando a continuacin el segundo de la cola al frente; y cada
que llega un nuevo elemento este se colocar al final de la cola. De aqu que el
extremo por donde se insertan los elementos se llamar "final" y por donde se
retiran "frente". Debido a esto ltimo las colas tambien son llamadas listas en
las cuales el primer elemento en entrar es el primero en salir, en ingles
FIFO(First Input, First Out). Para las colas que trabajaremos se sobreentender,
a menos de decir lo contrario, que la regla es que siempre el primero se atiende
primero.
Una Cola es una estructura de datos la cual almacena elementos de un tipo
determinado, que sigue la poltica de que el primer elemento que se extrae (se
desencola) es el primero que se introdujo (se encol)
-primero en salir,
primero en entrar (FIFO)-.

Implementacin

Para la implementacin de la cola utilizaremos la estructura de datos arreglo


unidimensional. Las funciones que manejarn la cola sern: Insertar() y
Atender(). Desarrollemos estas dos funciones de forma "simultnea"; partamos de
las definiciones de constantes y variables siguientes:
const int MaxCola = 5;
const int nulo = -1;
int frente = nulo;
int final = nulo;
int cola[MaxCola];
cola

frente

final

12

0
1
2
3
4

nulo

nulo

Cuando una cola est vaca el primer elemento que llegue, lgicamente que
llegar al frente, supongamos ese elemento es 15:
cola

15

0
1
2
3
4

frente

final

Las variables frente y final deben colocarse en cero, el fragmento de cdigo


correspondiente para obtener lo anterior sera:
if (frente == nulo){ //la cola estaba vaca
frente = final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[frente];
}
Si llega otro elemento, supongamos 18, tendramos que colocarlo al "final de
la cola", quedando:
cola

15 18

0
1
2
3
4

frente

final

Vemos que el final se ha movido hacia la derecha, el cdigo que podra hacer
esto, sera:
final++;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
Este ser el "caso general", empero hay varios casos particulares, los cuales
trataremos a continuacin. Supongamos que siguen llegando elementos a la cola,
as:
cola

15 18 -4

0
1
2
3
4

frente

final

cola

15 18 -4 0

0
1
2
3
4

frente

final

cola

15 18 -4 0 65

0
1
2
3
4

frente

final

13

Si trataramos de insertar otro ms, debera el programa darnos un mensaje de


"Cola llena", para esto mejoraremos el cdigo anterior de esta forma:
if ( (final+1 == MaxCola && frente == 0) )
cout << "cola llena ";
else{
final++;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
Ahora supongamos que se comienza a atender(eliminar) elementos, en el frente:
cola

18 -4 0 65

0
1
2
3
4

frente

final

Observe que no vamos a correr los elementos hacia la izquierda, como


sucedera en una cola de la vida real, no!, todos los elementos permanecern
siempre en el mismo sitio, hasta que sean atendidos. Atendamos ahora al 18 en la
posicin frente de 1:
cola

-4 0 65

0
1
2
3
4

frente

final

Si atendemos al -4 en la posicin frente igual a 2:


cola

0 65

0
1
2
3
4

frente

final

Hasta aqu podramos copiar el algoritmo de atender(eliminar) as:


cout << "Atendido el frente: " << cola[frente];
frente++;
Estn "desocupadas" en este momento las posiciones 0, 1 y 2, si llega otro
elemento, debemos aprovechar esas posiciones, de la siguiente forma, insertemos
el elemento 57:
cola

57

0 65

0
1
2
3
4

frente

final

0 final pasa de 4 a 0

Es de notar que la cola que el usuario tiene en mente tiene el orden:

14

65

57

Esto ocasiona una nueva modificacin al algoritmo de insertar, veamos:


if ( (final+1 == MaxCola && frente == 0)
cout << "cola llena ";
else {
final++;
if (final == MaxCola)
final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
}
Verifique el algoritmo anterior insertando el elemento 14:
cola

57 14
0 65

0
1
2
3
4

frente

final

La cola para el usuario estara en este orden: 0, 65, 57, 14. Insertemos
ahora otro elemento, por ejemplo 81:
cola

57 14 81 0 65

0
1
2
3
4

frente

final

La cola para el usuario estara como: 0, 65, 57, 14, 81. Llegados a este
punto no podramos seguir insertando elementos, ya que esta la cola est llena.
Verifique nuestro algoritmo y se dar cuenta que fracasar, permitiendo insertar
otro y de esta forma borrando el valor que tenemos en el frente, por ello
recodificamos, teniendo en cuenta que si el final est una posicin menos que el
frente, la cola est, tambin llena:
if ( (final+1 == MaxCola && frente == 0) || (final+1 == frente) )
cout << "cola llena ";
else {
final++;
if (final == MaxCola) // se da "la vuelta al inicio"
final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
A continuacin insertmosle al anterior cdigo, el caso inicial, cuando la
cola estaba vaca y tendramos finalmente:
if ( (final+1 == MaxCola && frente == 0) || (final+1 == frente) )
cout << "cola llena ";
else
if (frente == nulo){ //la cola estaba vaca
frente = final = 0;
cout << "\n\nElemento a insertar: ";

15

cin >> cola[frente];


}
else { // caso general
final++;
if (final == MaxCola) // se da "la vuelta al inicio"
final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
Dediqumonos ahora a terminar la funcin de Atender(eliminar). Eliminemos el
frente, posicin 3,
La cola para el usuario est as: 65, 57, 14, 81. Recordemos el cdigo hasta
el momento y que nos sirve para este caso:
cout << "Atendido el frente: " << cola[frente];
frente++;
Atendamos otro, el 65 en posicin frente de 4:
cola

57 14 81

0
1
2
3
4

frente

final

El frente "da la vuelta", el algoritmo se modifica as:


cout << "\nAtendido: " << cola[frente];
frente++;
if (frente == MaxCola)
frente = 0;
Sigamos,
sucesivamente,
atendiendo
los
dems
verificndolo cada vez en el algoritmo anterior:

elementos

cola

14 81

0
1
2
3
4

frente

final

cola

81

0
1
2
3
4

frente

final

en

cola

Observe que cuando queda un solo elemento en cola, el frente es igual al


final. Luego al eliminar el ltimo elemento el algoritmo fallara, las variables
deberan quedar:
cola
frente
final

nulo
nulo

0
1
2
3
4
Para esto se debe modificar nuevamente el cdigo para Atender:

16

cout << "\nAtendido: " << cola[frente];


if (frente == final)
frente = final = nulo;
else{
frente++;
if (frente == MaxCola)
frente = 0;
}
En este momento tenemos la cola vaca. si tratramos de Atender un elemento,
el algoritmo anterior nos mostrara "basura", por esto, al fin, recodificamos el
algoritmo Atender:
if (frente == nulo)
cout << "\nCola vacia\a";
else {
cout << "\nAtendido: " << cola[frente];
if (frente == final)
frente = final = nulo;
else{
frente++;
if (frente == MaxCola)
frente = 0;
}
}

Programa Cola.exe.. ................................


Como resumen de lo anterior a continuacin se presenta el programa COLA.CPP con
la implementacin, completa, de la estructura cola en un arreglo unidimensional:
//ColaVector.CPP
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
const int MaxCola = 5;
const int nulo = -1;
int frente = nulo;
int final = nulo;
int cola[MaxCola];
void Insertar(){
if ( (final+1 == MaxCola && frente == 0) || (final+1 == frente) ){
cout << "cola llena ";
getch();
}
else
if (frente == nulo){ //la cola estaba vaca
frente = final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[frente];
}
else { // caso general

17

final++;
if (final == MaxCola) // se da "la vuelta al inicio"
final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
}
void Atender(){
if (frente == nulo)
cout << "\nCola vacia\a";
else {
cout << "\nAtendido: " << cola[frente];
if (frente == final) // cola qued vaca
frente = final = nulo;
else{
frente++;
if (frente == MaxCola)
frente = 0;
}
}
}
void Listar(){
int i;
if (frente==nulo)
cout << "\nCola vacia \a\n";
else
if (frente <= final)
for (i=frente; i <= final; i++)
cout << setw(4) << cola[i];
else {
for (i=frente; i < MaxCola; i++)
cout << setw(4) << cola[i];
for (i=0; i <= final; i++)
cout << setw(4) << cola[i];
}
}
void main(){
char opcion;
do{
clrscr();
Listar();
cout << "\n\nInsertar Atender Salir \n";
switch (opcion=getch()){
case 'I':; case 'i': Insertar(); break;
case 'A':; case 'a': Atender(); break;
}
} while (opcion != 'S' && opcion != 's');
}
Estudie el siguiente programa, el cual tiene un pequeo cambio, en relacin al
anterior:

18

Cola de Registros:
#include
#include
#include
#include

<iostream.h>
<iomanip.h>
<conio.h>
<stdio.h>

const int MaxCola = 40;


const int nulo = -1;
int frente = nulo, final = nulo;
typedef struct persona PERSONA;
struct persona{
char nombre[25];
int edad;
float alto;
} Cola[MaxCola];
void Insertar(){
PERSONA registro;
if ( (final+1 == MaxCola && frente == 0) || (final+1 == frente) ){
cout << "Cola llena ";
getch();
}
else{
cout << "\n\nDigite nombre: ";
cin >> registro.nombre;
cout << "Digite edad en aos: ";
cin >> registro.edad;
cout << "Digite estatura en metros: ";
cin >> registro.alto;
if (frente == nulo){ //la Cola estaba vaca
frente = final = 0;
Cola[frente] = registro;
}
else { // caso general
final++;
if (final == MaxCola) // se da "la vuelta al inicio"
final = 0;
Cola[final] = registro;
}
}
}
void Atender(){
if (frente == nulo)
cout << "\nCola vacia\a";
else {
cout << "\nAtendido: " << Cola[frente].nombre
<< Cola[frente].edad
<< " "

<< "

"

19

<< Cola[frente].alto;
if (frente == final) // cola qued vaca
frente = final = nulo;
else {
frente++;
if (frente == MaxCola)
frente = 0;
}
}
getch();
}
void listar(){
int i;
clrscr();
if (frente==nulo)
cout << "Cola vacia \a\n";
else
if (frente <= final)
for (i = frente; i <= final; i++)
cout
<< "\n" << Cola[i].nombre << " "
<< Cola[i].edad
<< " "
<< Cola[i].alto;
else {
for (i=frente; i<MaxCola; i++)
cout << "\n" << Cola[i].nombre << " "
<< Cola[i].edad << " " << Cola[i].alto;
for (i=0; i <= final; i++)
cout << "\n" << Cola[i].nombre << " " << Cola[i].edad
<< " " << Cola[i].alto << endl;
}
}
void main(){
char opcion;
do {
listar(); cout << "\n\nInsertar Atender
opcion = getch();
switch (opcion){
case 'I':;
case 'i': Insertar(); break;
case 'A':;
case 'a': Atender(); break;
}
} while (opcion != 'S' && opcion != 's');

Salir ";

Ejemplo Real de Aplicacin de las Colas.............


Cola de instrucciones en microprocesadores. Algunos microprocesadores
utilizan colas como lneas de espera para sus instrucciones. Dicho de otra
manera, las instrucciones que han de ejecutarse llegan al procesador antes
de lo necesario y esperan en una cola de instrucciones. Este sistema posee
la ventaja de que cada instruccin puede extraerse de memoria mientras
otras se estn ejecutando, reducindose en consecuencia el tiempo de
proceso. Por ejemplo, las instrucciones que incluyen directamente al dato

20

datos inmediatos- se ejecutan prcticamente a la misma velocidad que


aquellas otras que utilizan datos de los registros de la CPU. Es tambin
muy til cuando se usa el procesador con memorias lentas tales como
EPROM(Erasable Read Only Memory)
La situacin es muy similar a la de un jefe que tiene una secretaria para
coger el telfono y para la correspondencia. La secretaria trabaja al mismo
tiempo que el jefe hace otras cosas, liberndole de muchos detalles del mundo
exterior. Las llamadas que se acumulan para el jefe se tratan se una en una, y
en el orden que prefiera el jefe.

Programa a Realizar como Ejercicio..................


Suponga que 4 estudiantes se dirigen en cola a la biblioteca, cada uno de ellos
lleva en su maletn escolar un nmero diferente de libros (suponga un mximo de
10 libros), los cuales deben dejar en la portera. Para esto, colocan los libros
formando pilas separadas para cada uno en una mesa, cada una a continuacin de la
otra, formando una cola de pilas de libros. Despus de unas horas los estudiantes
se retiran formando una cola en el mismo orden que al entrar, retirando cada uno
de ellos sus libros y colocando cada uno de ellos en su maletn escolar.
Simule el proceso anterior por medio de la elaboracin de un programa en
lenguaje C++. Debe considerar el nombre de cada uno de los estudiantes y su
nmero de libros en la cola, y as mismo el nombre de cada uno de los libros en
las pilas.
La abstraccin de la estructura de datos a realizar es la siguiente:
- Las pilas de libros represntelas en cuatro vectores separados, de 10
posiciones cada uno.
- La cola de estudiantes represntela como dos vectores paralelos de cuatro
sendas posiciones as: uno para los nombres de cada estudiante y el otro para
manejar la cima de la pila de libros de cada uno de los estudiantes.
PILAS DE LIBROS EN COLA

VECTOR CIMAS

0
1
2
3
VECTOR NOMBRES

nombre_1

nombre_2

nombre_3

nombre_4

0
1
2
3

21

Efecte Prueba de Escritorio.. .. .. ..............


const int MaxCola = 3, Vacia = -1;
int frente = Vacia, final = Vacia, cola[MaxCola]; //variables globales
void Insertar(){
if ( (final+1 == MaxCola && frente == 0) || (final+1 == frente) )
cout << "cola llena ";
else
if (frente == Vacia){
frente = final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[frente];
}
else { // caso general
final++;
if (final == MaxCola)
final = 0;
cout << "\n\nElemento a insertar: ";
cin >> cola[final];
}
}
void Atender(){
if (frente == Vacia)
cout << "\nCola vacia\a";
else {
cout << "\nAtendido: " << cola[frente];
if (frente == final)
frente = final = Vacia;
else{
frente++;
if (frente == MaxCola)
frente = 0;
}
}
}
void main(){
Atender();
Insertar();
Insertar();
Insertar();
Insertar();
Atender();
Insertar();
Atender();
Atender();
Insertar();
}
El siguiente dibujo es la representacin en RAM inicial:
cola
frente
final

-1

-1
recuerde que Vacia=-1

0
1
2

22

23

RECURSIN
1. INTRODUCCIN
La recursin consiste en la invocacin de una funcin a si misma, es decir que en
el mbito de ella se efecta una llamada con el mismo identificador con el que
est definida.
En cada invocacin de una funcin, el compilador le asigna una direccin base
de memoria a partir de la cual "trabajar" esta funcin, por esto en cada nueva
invocacin recursiva, el compilador asignar nuevas direcciones de memoria, de
esta forma y eventualmente la memoria podra llegar a llenarse. En cada
invocacin se haran copias de los parmetros que se estn pasando y de las
variables locales en ella definidas.
Para evitar el llenar la memoria del computador, toda funcin recursiva debe
estar construida de tal suerte que bajo alguna condicin no se siga invocando
ms, esto es lo que se conoce como el criterio base de la funcin recursiva.
Explicaremos el mecanismo de invocaciones
clculo del factorial de un nmero.

recursivas

con

el

ejemplo

De la definicin del factorial de un nmero: Factorial(N) = 1 * 2


debera usted estar de acuerdo con lo siguiente:

del

.... * N

Factorial(N) = N * Factorial(N-1)
Veamos el siguiente ejemplo:
Fac(5) = 5 * Fac(5-1) = 5 * Fac(4)
Fac(4) = 4 * Fac(4-1) = 4 * Fac(3)
Fac(3) = 3 * Fac(3-1) = 3 * Fac(2)
Fac(2) = 2 * Fac(2-1) = 2 * Fac(1)
Fac(1) = 1 * Fac(1-1) = 1 * Fac(0)
Fac(0) = 1
sabemos que factorial de cero es igual a uno, tomaremos este hecho como el
"criterio base" y a partir de aqu nos "devolvemos" reemplazando en las
expresiones anteriormente obtenidas, hasta llegar al resultado deseado:
Fac(1) = 1 * Fac(0) = 1 * 1 = 1
Fac(2) = 2 * Fac(1) = 2 * 1 = 2
Fac(3) = 3 * Fac(2) = 3 * 2 = 6
Fac(4) = 4 * Fac(3) = 4 * 6 = 24
Fac(5) = 5 * Fac(4) = 5 * 24 = 120
A partir de esto codificaremos la siguiente funcin recursiva:
float factorial(int n){
float fac;
if (n == 0)
return (1);

24

fac = n * factorial(n-1);
return(fac);
}
Supongamos que al efectuar su invocacin inicial, ver el programa
RECURSI.CPP siguiente, se le est pasando por valor el entero 5: el compilador le
asignar a la funcin un "espacio" en la memoria para realizar su trabajo,
representemos ese espacio como un rectngulo y de esta forma tener una mejor
abstraccin de lo que ocurre, as:
factorial(5)

entra a la funcin recibiendo n el valor de 5


5 se define la variable local fac

fac
if (n==0) es falso. El algoritmo continuar en


fac = n * factorial(n-1);

= 5 * factorial(5-1);

= 5 * factorial(4); se invoca recursivamente

Con el valor de n=4 se produce una invocacin recursiva de la funcin,


debemos imaginarnos y es realmente lo que ocurre, que el compilador y a travs
del sistema operativo, gestiona una nueva direccin en memoria para trabajar en
esta nueva invocacin, as:
factorial(4)

entra a la funcin recibiendo n el valor de 4


4 se define otra variable local fac

fac
if (n==0) ser falso. El algoritmo continuar en


fac = n * factorial(n-1);

= 4 * factorial(4-1);

= 4 * factorial(3); se invoca recursivamente

Con el valor de n=3 se produce una segunda invocacin recursiva, tercera para
la funcin, en memoria se gestionar un nuevo "espacio" as:
factorial(3)

entra a la funcin recibiendo n el valor de 3


3 n y fac son "otras" variables locales

fac
if (n==0) es falso, el algoritmo continuar en


fac = n * factorial(n-1);

= 3 * factorial(3-1);

= 3 * factorial(2); se invoca recursivamente

25

Hasta el momento, debe tenerse en mente, la funcin se ha invocada cuatro


veces, tres de las cuales son recursivas, en la ltima con el valor de n=2 en
memoria se gestionar un nuevo "espacio" as:

factorial(2)

se crea una nueva variable n recibiendo un valor de 2


2 fac ser otra variable local

fac
if (n==0) es falso, el algoritmo continuar en


fac = n * factorial(n-1);

= 2 * factorial(2-1);

= 2 * factorial(1); se invoca recursivamente

La siguiente invocacin nos la imaginaremos as:


factorial(1)

se crea una nueva variable n recibiendo un valor de 1


1 fac ser otra variable local

fac
if (n==0) es falso, el algoritmo continuar en


fac = n * factorial(n-1);

= 1 * factorial(1-1);

= 2 * factorial(0); se invoca recursivamente

Se producir una nueva invocacin pasando el valor de cero, as:


factorial(0)

se crea una nueva variable n recibiendo un valor de 0


0 fac ser otra variable local

fac
if (n==0) es verdadero

return (1);



la funcin termina, se sale, y vuelve DONDE FUE

INVOCADA

26

La funcin alcanza el criterio base, cuando n=0, de esta forma se ejecuta la


instruccin return(1); la funcin termina retornando un 1, se borra de la
memoria, y el programa sigue en la invocacin anterior a esta, es decir
en(devuelva la pgina para comparar):
factorial(1)


1

fac

fac = n * factorial(n-1);
= 1 * factorial(1-1);
= 1 * factorial(0);
el 1 retornado "llega" a factorial(0)
y de este modo se sigue:
fac = 1 * factorial(0) = 1*1 = 1
continuando en return(fac)
return(2) y termina esta invocacin

Vemos que la invocacin de factorial(0) recibe el valor de 1 y se produce la


evaluacin de la expresin que calcula el valor para fac de 1, retornando este
valor a la anterior invocacin, de la siguiente forma:
factorial(2)


2

fac

fac = n * factorial(n-1);
= 2 * factorial(2-1);
= 2 * factorial(1);
el 1 retornado "llega" a factorial(1)
y de este modo se sigue:
fac = 2 * factorial(1) = 2*1 = 2
continuando en return(fac)
return(2) y termina esta invocacin

Vemos que la invocacin de factorial(1) recibe el valor de 1 y se produce la


evaluacin de la expresin que calcula el valor para factorial de 2 de 1,
retornando este valor a la anterior invocacin, de la siguiente forma:
factorial(3)


3

fac

fac = n * factorial(n-1);
= 3 * factorial(3-1);
= 3 * factorial(2);
el 2 retornado "llega" a factorial(2)
y de este modo se sigue:
fac = 3 * factorial(2) = 3*2 = 6
continuando en return(fac)
return(6) y termina esta invocacin

de nuevo en la invocacin que corresponde a factorial(4) tenemos:


factorial(4)

fac = n * factorial(n-1);

27


4

fac


24

= 4 * factorial(4-1);
= 4 * factorial(3);
el 6 retornado "llega" a factorial(3)
y de este modo se sigue:
fac = 4 * factorial(3) = 4*6 = 24
continuando en return(fac)
return(24) y termina esta invocacin

Estamos ahora en la invocacin inicial de factorial(5):


factorial(5)


5

fac


120

fac = n * factorial(n-1);
= 5 * factorial(5-1);
= 5 * factorial(4);
el 24 retornado "llega" a factorial(4)
y de este modo se sigue:
fac = 5 * factorial(4) = 5*24 =120
continuando en return(fac)
return(120) y termina esta invocacin

Regresamos de esta forma al sitio donde se invoc originalmente la funcin


con el valor de 120 retornado, y terminado todo el proceso de invocaciones.
Resumiendo el proceso de invocaciones y el "espacio que ocup" en memoria fue
el siguiente:

28

2. Ejemplo de funcin recursiva. Clculo de un factorial.


#include <iostream.h>
#include <conio.h>
//RECURSI1.CPP
float factorial(int n);
void main(){
int n;
clrscr(); cout << "Digite un nmero negativo para terminar\n\n";
do{
cout << "Nmero entero: "; cin >> n;
if (n >= 0)
cout <<"factorial = " << factorial(n) << endl;
}while (n >= 0);
}
float factorial(int n){
if (n == 0)
return (1);
return ( n * factorial(n-1) );
}
3. Calculo del mximo comn divisor de dos nmeros enteros.
//MCD.CPP
#include <ConStrea.h>
long int MCD(int a, int b){
if ( !b )
return a;
else
return ( MCD(b, a%b) );
}
void main(){
long int a, b;
constream Escribir;
Escribir.window(1,1,80,25);
textbackground(BLUE); Escribir.clrscr();
Escribir << setbk(CYAN) << setclr(RED)
<< setxy(10,5) << "Digite entero: ";
cin >> a;
Escribir << setbk(MAGENTA) << setclr(GREEN)
<< setxy(10,7) << "Digite otro entero: ";
cin >> b;
Escribir << setbk(BROWN) << setclr(GREEN)
<< setxy(10,9) << "Mximo comn divisor = " << MCD(a, b);
}

29

4. Tringulo de Pascal de coeficientes binomiales


n
n-i i
S ( n! / (i!(n-i)!))a b
i=0

(a+b)_ =

#include <iostream.h>
#include <conio.h>
//RTPASCAL.CPP
float factorial(int);
main(){
int N=10, n, i, coeficiente, espacio;
clrscr();
cout << "\t\tTRIANGULO DE PASCAL DE COEFICIENTES BINOMIALES\n\n";
for(n = 0; n <= N; n++) {
for(espacio=1; espacio <= (80/2-6)-n*3; espacio++)
cout << " ";
for(i = 0; i <= n; i++){
coeficiente = factorial(n)/(factorial(i)*factorial(n-i));
cout.width(6); cout << coeficiente;
}
cout << endl;
}
getch();
}
float factorial(int n){
float f;
if ((n == 1) || (n == 0))
return(1);
f = n * factorial(n-1);
return(f);
}
Tabla: Tringulo de Pascal de coeficientes binomiales.
1
1
1
1
1

1
3

6
10

1
4

10

1
15
20
15
6
1
1
7
21
35
35
21
7
1
1
8
28
56
70
56
28
8
9
36
84
126
126
84
36
9
10
45
120
210
252
210
120
45
1

3
4

1
2

1
1
10

30

5 Multiplicar dos nmeros utilizando recursin. Sin operador *.


#include <iostream.h>
#include <conio.h>
//RECURSI2.CPP
float multiplicar(float a, int b){
if (b==1)
return (a);
return(multiplicar(a,b-1) + a);
}
void main(){
float a=2;
int b=4;
clrscr();
cout << a << " * " <<
getch();

b << " = " << multiplicar(a,b);

}
Veamos una prueba para el anterior algoritmo:
Multiplicar(2,4)= Multiplicar(2,4-1)+ 2 = Multiplicar(2,3) + 2
Multiplicar(2,3)= Multiplicar(2,3-1)+ 2 = Multiplicar(2,2) + 2
Multiplicar(2,2)= Multiplicar(2,2-1)+ 2 = Multiplicar(2,1) + 2
Multiplicar(2,1) = 2
Multiplicar(2,2)= Multiplicar(2,1) + 2 = 2 + 2 = 4
Multiplicar(2,3)= Multiplicar(2,2) + 2 = 4 + 2 = 6
Multiplicar(2,4)= Multiplicar(2,3) + 2 = 6 + 2 = 8
6. Eleve el nmero 10 a diferentes potencias utilizando una funcin recursiva.
//RECURS_3.CPP
#include <IOSTREAM.H>
#include <CONIO.H>
float potencia (int, int);
main(){
int x = 10;
int y = 0;
clrscr();
do{
cout << "\n10 elevado a la " << y << " = " << potencia(x, y);
y++;
}while ( y<11 );
}
float potencia (int base, int exponente){
if ( exponente < 0 )
return(-1);
else
if (exponente == 0)
return(1); /* criterio base */
else
return (base * potencia (base, exponente-1));
}

31

7. Se pasa un nmero de base 10 a base 2 utilizando recursin.


#include <iostream.h>
#include <conio.h>
//RDECIBIN.CPP
void DecimalABinario(int Dividendo){
int cociente, resto;
cociente = Dividendo >> 1; //Divide entre dos, desplaza un byte a derecha
resto = Dividendo % 2;
if(cociente)
DecimalABinario(cociente);
cout << resto;
}

void main(){
int dec;
clrscr();
cout << "Digite un entero: ";
cin >> dec;
cout << "\nEn binario es = ";
DecimalABinario(dec);
}
8. Presenta las tablas de multiplicar desde un valor t1 a uno t2. Utilizando
recursin. Efecte prueba de ejecucin manual. Explique en palabras lo que hace;
muestre lo ms grficamente que pueda cada una de las invocaciones recursivas;
mencione los criterios base para cada una de las funciones, escriba como se
"devuelven" las invocaciones recursivas; de los correspondientes valores a las
variables en cada invocacin.
#include <conio.h>
#include <dos.h>
#include <iostream.h>
//R_TABLAM.CPP
void Tabla(int a, int b){
if(b>1)
Tabla(a, b-1);
cout << a << " x " << b << " = " << a*b << endl;
}
void Tablas(int del, int al){
if(del < al)
Tablas(del, al-1);
clrscr();
Tabla(al,10);
delay(500);
}
void main(){
int t1,t2;
clrscr();
cout << "Nmero de la tabla inicial: ";

32

cin >> t1;


cout << "Nmero de la tabla final: ";
cin >> t2;
Tablas(t1,t2);
}
Efecte a continuacin prueba de ejecucin manual del algoritmo del anterior
programa. Llene el siguiente tabulado y "pantalla".
Variables en forma tabular
"PANTALLA"
t1

t2

del

al

33

9. Serie de Fibonacci utilizando recursin:


Serie:
0 1 1 2 3 5 8 13 21 34
Posicin:
0 1 2 3 4 5 6
7
8
9

55
10

89
11
//RFIBONAC.CPP

#include <iostream.h>
#include <conio.h>
int fibonacci(int n){
if (n <= 1)
return (n);
return(fibonacci(n-2) + fibonacci(n-1));
}
main(){
int N=11;
clrscr();
cout <<"El " <<N <<" trmino de la serie de Fibonacci es " << fibonacci(N);
getch(); return 0;
}

10. La funcin Log2, la cual encuentra el logaritmo en base 2 de n, se puede


definir en forma recursiva de la siquiente forma:
Log2(n) = 0

si n = 1

Log2(n) = 1 + Log2( [n/2] )

si n > 1
RLOG2_N.CPP

#include <iostream.h>
#include <conio.h>
int Log2(int n){
if (n < 1)
return -1;
if (n == 1)
return 0;
return ( 1 + Log2(n/2) ) ;
}
void main(){
int N, L;
clrscr(); cout << "Digite un Entero: ";
cin >> N;
L = Log2(N);
if ( L<0 )
cout << "Error \a";
else
cout << "Parte entera del Logaritmo en base 2 de " << N << " = " << L;
}

34

11. Implementacin del Algoritmo de Euclides para el clculo del Mximo Comn
Divisor:
Sean A y B enteros no negativos. Suponga que una funcin MCD se define
recursivamente como sigue:
MCD(A,B) = MCD(B,A)
MCD(A,B) = A
MCD(A,B) = MCD(B, A % B)

si A < B
si B = 0
de otro modo

#include <iostream.h>
#include <conio.h>
//REUCLIDES.CPP
int MCD(int A, int B){
if (A<B)
return(MCD(B,A));
else
if (!B)
return A;
else
return(MCD(B, A%B));
}
void main(){
int a = 13, b = 130;
clrscr();
cout << "Mximo Comn Divisor de " << a << " y " << b << " es " << MCD(a,b);
getch();
}

12. Multiplicar dos nmeros utilizando recursin. Sin operador *.


#include <iostream.h>
#include <conio.h>
//RMULTIPL.CPP
float multiplicar(float a, int b){
if(b==1)
return a;
return (multiplicar(a, b-1) +a);
}
void main(){
clrscr();
cout << "12.8 * 5 = " << multiplicar(12.8, 5);
getch();
}

35

14. Clculo de la funcin recursiva de Ackermann.


#include <iostream.h>
#include <conio.h>
//RACKERMAN.CPP
int Ackermann(int m, int n){
if (m == 0)
return(n+1);
else
if ((m != 0) && (n==0))
return( Ackermann(m-1,1) );
else
return( Ackermann( m-1, Ackermann(m, n-1) ) );
}
void main(){
int a, b;
clrscr(); cout << "FUNCION RECURSIVA DE ACKERMANN\n\n";
cout << "Digite un entero pequeo(0 al 3): "; cin >> a;
cout << "Digite otro entero pequeo: ";
cin >> b;
cout << "\nACKERMANN(" << a << "," << b << ") = " << Ackermann(a,b) ;
}
15. Algoritmo de bsqueda binaria. Debe hacerse sobre un vector ordenado. Se
utiliza recursin.
#include <iostream.h>
#include <conio.h>
//RBBINARIA.CPP
const int Max = 10, Min = 0;
int item, v[Max]={2,4,8,12,13,65,73,87,99,121}; //Observe Vector ordenado
int BusquedaBinaria(int izq, int der){
int medio;
if (izq <= der){
medio = (izq + der) >> 1;
if (item < v[medio])
return( BusquedaBinaria(izq, medio-1) );
else
if (item > v[medio])
return( BusquedaBinaria(medio+1, der) );
else
return medio; // Criterio Base
} else
return -1; // No se encuentra
}
void main(){
int i;
for(i=0; i<Max; i++){
cout.width(5); cout << v[i];
}
cout << endl;
for(i=0; i<Max; i++){
cout.width(5); cout << i;

36

}
cout << "\n\nDigite nmero a buscar en el vector: "; cin >> item;
i = BusquedaBinaria(Min, Max-1);
if ( (i>=Min) && (i<Max) )
cout << "\n\n" << v[i] << " est en la posicin " << i;
else
cout << "\n\n" << item << " no se encuentra";
}
16. TORRES DE HANOI: El objeto de este juego es mover de un poste inicial N
discos de diferente tamao, colocados de mayor a menor tamao uno encima de otro,
hasta un poste final y utilizando un poste auxiliar. Solo se puede mover un disco
cada vez, de poste a poste. Nunca puede haber un disco mayor sobre un disco
menor.
//TORHANOI.CPP
#include <iostream.h>
#include <conio.h>
void torres(int N, int inicio, int aux, int final);
void main(){
int anillos=0;
const int poste1=1, poste2=2, poste3=3;
clrscr();
cout << "Nmero de anillos con que quiere jugar: ";
torres(anillos, poste1, poste2, poste3);

cin >> anillos;

}
void torres(int N, int inicio, int aux, int final){
if (N == 1)
cout << "Mover torre " << inicio << " a torre " << final << endl;
else{
torres(N-1,inicio,final, aux);//N-1 discos del poste inicial al auxiliar
cout << "Mover torre " << inicio << " a torre " << final << endl;
torres(N-1, aux, inicio, final);//N-1 discos del poste auxiliar al final
}
}

Para 3 anillos:

Mover
Mover
Mover
Mover
Mover
Mover
Mover

Torre
Torre
Torre
Torre
Torre
Torre
Torre

Para 4 anillos:
1
1
3
1
2
2
1

a
a
a
a
a
a
a

Torre
Torre
Torre
Torre
Torre
Torre
Torre

3
2
2
3
1
3
3

Mover Torre 1 a Torre 2


Mover Torre 1 a Torre 3
Mover Torre 2 a Torre 3
Mover Torre 1 a Torre 2
Mover Torre 3 a Torre 1
Mover Torre 3 a Torre 2
Mover Torre 1 a Torre 2
Mover Torre 1 a Torre 3
Mover Torre 2 a Torre 3
Mover Torre 2 a Torre 1
Mover Torre 3 a Torre 1
Mover Torre 2 a Torre 3
Mover Torre 1 a Torre 2
Mover Torre 1 a Torre 3
Mover Torre 2 a Torre 3

37

PROGRAMA A REALIZAR COMO EJERCICIO


Realice programa tipo tutor(para sus compaeros del prximo semestre), en modo
grfico, y el cual permita explicar uno cualquiera de los algoritmos del presente
captulo sobre recursividad. Recuerde que en el modelo constructivo de educacin
lo importante es el proceso que se lleve a cabo para llegar al objetivo; el
cumplimiento del objetivo en s no es lo importante(recuerde que el fin no debe
justificar los medios), de modo que comente en cada clase con el profesor sus
avances y dudas, el profesor deber estar contento de ver sus avances y tratar
de corregir sus eventuales errores(siempre cometeremos errores), sin espritu de
represin.

38

ALGORITMO DEL QUICKSORT


A continuacin se explica una versin del algoritmo del
clasificacin rpida, para ello partamos del siguiente vector:

Quicksort

de

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

0 12 43 2 90 50 87100-10 68 13 7 21 45 50 0
43

Pivote
<
En este caso la posicon ms a la izquierda es 0, la ms a la derecha es 12,
se escoge como "pivote" el primer trmino de la lista, es decir la posicin ms a
la izquierda, tal como est escrito en la tabla anterior.
Se procede a comparar el pivote, 43, con el valor ms a la derecha, posicin
12 cuyo valor es 50. Se verifica que 43 y 50 estn en posiciones relativas,
ascendentemente, adecuadas, por esto comenzamos a movernos a la izquierda,
decrementando der, as:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

0 11 43 2 90 50 87100-10 68 13 7 21 45 50 0
43

Pivote
<
Se compara ahora el pivote 43, en posicin cero, con el nmero en posicin
der=11, es decir 45, nuevamente estan en posiciones relativas adecuadas a nuestro
ordenamiento ascendente, por esto se decrementa derecha (Der--):

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

0 10 43 2 90 50 87100-10 68 13 7 21 45 50 0
43

Pivote
<
Se compara ahora 43 con 21 de la posicin der=10, no estn en posiciones
relativas ordenadas, se proceder entonces a su intercambio, quedando el vector,
paso a paso as:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

0 10 21 2 90 50 87100-10 68 13 7 21 45 50 0
43

21 2 90 50 87100-10 68 13 7 43 45 50 10

39

>

Pivote

Se actualiza la posicin del pivote, ahora est en 10, y se comienza a


comparar desde la izquierda, como lo seala la flecha en la tabla anterior. As
se compara 43 con 21, los cuales estan en posiciones relativas adecuadas:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

1 10 21 2 90 50 87100-10 68 13 7 43 45 50 10 43

>
Pivote
por esto se incrementa izquierda y se compara el 43 con el 2, igualmente estn
en orden ascendente relativo; se incrementa izquierda nuevamente llegando a donde
est el nmero 90 en la posicin 2 del vector:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

2 10 21 2 90 50 87100-10 68 13 7 43 45 50 10 43

>
Pivote
El 90 al compararlo con el pivote 43 es mayor,
intercambiados, y actualizada la posicin del pivote:

por

esto

debern

ser

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

2 10 21 2 90 50 87100-10 68 13 7 90 45 50 10 43

21 2 43 50 87100-10 68 13 7 90 45 50
2

Pivote
<
Siguiendo este proceso se obtiene la siguiente secuencia de posiciones:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

2 9 21 2 43 50 87100-10 68 13 7 90 45 50 2
43

Pivote
<

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

2 9 21 2 7 50 87100-10 68 13 7 90 45 50
2 43

21 2 7 50 87100-10 68 13 43 90 45 50
9

>
Pivote

40

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

3 9 21 2 7 50 87100-10 68 13 43 90 45 50
9 43

>
Pivote

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

3 9 21 2 7 50 87100-10 68 13 50 90 45 50
9 43

21 2 7 43 87100-10 68 13 50 90 45 50
3

Pivote
<

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

3 8 21 2 7 43 87100-10 68 13 50 90 45 50
3 43

Pivote
<

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

3 8 21 2 7 13 87100-10 68 13 50 90 45 50
3 43

21 2 7 13 87100-10 68 43 50 90 45 50
8

>
Pivote

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

4 8 21 2 7 13 87100-10 68 43 50 90 45 50
8 43

>
Pivote

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

4 8 21 2 7 13 87100-10 68 87 50 90 45 50
8 43

21 2 7 13 43100-10 68 87 50 90 45 50
4 43

Pivote
<

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

4 7 21 2 7 13 43100-10 68 87 50 90 45 50
4 43

Pivote
<

41


izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

4 6 21 2 7 13 43100-10 68 87 50 90 45 50
4 43

Pivote <

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

4 6 21 2 7 13-10100-10 68 87 50 90 45 50
4 43

21 2 7 13-10100 43 68 87 50 90 45 50
6

> Pivote

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

5 6 21 2 7 13-10100 43 68 87 50 90 45 50
6 43

>Pivote

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

5 6 21 2 7 13-10100100 68 87 50 90 45 50
6 43

21 2 7 13-10 43100 68 87 50 90 45 50
5

Pivote<
Al avanzar desde la derecha hacia la izquierda, la variable der se encuentra
con la posicin donde est el pivote, e izq ya estaba en el mismo valor, es decir
las tres variables "se encuentran en el mismo sitio", asi:

izqder 0
1
2
3
4
5
6
7
8
9 10 11 12 PosPivPivote

5 5 21 2 7 13-10 43100 68 87 50 90 45 50
5 43

Pivote
Se observa que el valor del pivote, 43, est en el sitio que le corresponde
en ordenamiento ascendente, y que a su izquierda se forma una sublista,
desordenada, desde la posicin 0 a la 4, con todos sus elementos menores; y una
sublista a la derecha, desde la posicin 6 hasta la 12, en desorden y con todos
mayores que el pivote. A partir de este punto se procede con el mismo
procedimiento sequido para la lista completa, en cada una de las sublistas y por
separado. El correspondiente programa, QUICKPIL.CPP, se presenta a continuacin:
2. Ejemplo de aplicacin de la estructura pila en el ordenamiento por el
algoritmo del QuickSort. El profesor explicar en clase magistral las reglas de
juego del algoritmo, usted deber efectuar prueba de ejecucin manual y entender
su abstraccin.
//QUICKPIL.CPP
#include <iostream.h>

42

#include <iomanip.h>
# include <stdlib.h>
#include <conio.h>
#include <values.h>
const int N=100;
int QuickSort(int *a, int izq, int der){
int PosPiv=izq, pivote=a[PosPiv];
do {
while ((pivote <= a[der]) && (PosPiv != der))
der --;
if (PosPiv != der) {
if (pivote > a[der]) {
a[PosPiv] = a[der];
a[der] = pivote;
}
PosPiv = der;
while ((a[izq] <= pivote) && (izq != PosPiv))
izq++;
if (PosPiv != izq){
if (a[izq] > pivote){
a[PosPiv] = a[izq];
a[izq] = pivote;
}
PosPiv = izq;
}
}
} while ( (PosPiv != der) || (PosPiv != izq) );
return(PosPiv);
}
void Ordenar(int *arreglo){ /* Clasificacin rpida */
int cima = -1, com, fin, PosPiv, menor[N], mayor[N];
cima++;
menor[cima] = 0;
mayor[cima] = N-1;
while (cima > -1) {
com = menor[cima];
fin = mayor[cima];
cima--;
PosPiv = QuickSort(arreglo, com, fin);
if ( com < PosPiv - 1) {
cima++;
menor[cima] = com;
mayor[cima] = PosPiv - 1;
}
if (PosPiv + 1 < fin){
cima++;
menor[cima] = PosPiv + 1;
mayor[cima] = fin;
}

43

}
}
void main(){
int i;
int vector[N];
clrscr();
cout << N << " Nmeros generados al azar:\n";
randomize();
for (i = 0; i < N; i++) {
vector[i] = random(MAXINT);
cout << setw(8) << vector[i];
}
Ordenar(vector);
cout << "\n\nOrdenados son:\n";
for (i = 0; i < N; i++)
cout << setw(8) << vector[i];
}

44

3. Clasificacin de un vector generado al azar, con el algoritmo de QuickSort. Se


utiliza recursin.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
//RQUICKSOR.CPP
const int N=50;
float Vector[N]; //Variable global
void QuickSort(int izq, int der) /* QuickSort */
{
register int i=izq, d=der;
float medio, aux;
medio = Vector[(izq+der)/2];
do{
while (Vector[i] < medio)
i++;
while (medio < Vector[d])
d--;
if(i <= d) {
aux = Vector[i];
Vector[i] = Vector[d];
Vector[d] = aux;
i++;
d--;
}
} while(i <= d);
if(izq < d)
QuickSort(izq, d);
if(i < der)
QuickSort(i, der);
}
void main(){
int i=0;
clrscr();
cout << N << " Nmeros generados al azar \n\n";
randomize();
for (i = 0; i < N; i++) {
Vector[i] = (float) rand();
cout.width(10); cout << Vector[i];
}
QuickSort(0, N-1);
cout << "\n\nLos nmeros ordenados son:\n\n";
for (i = 0; i < N; i++){
cout.width(10);
cout << Vector[i];
}
}

45

1.18 Clasificacin de un vector de cadenas


algoritmo del QuickSort. Se utiliza recursin.

de

caracteres(matriz),

con

el

#include <iostream.h>
#include <conio.h>
#include <string.h>
//RQUICKCAD.CPP
const int N=5;
const int LargoCadena=20;
char Cadena[N][LargoCadena]; //Variable global
void QuickSort(int izq, int der) /* Funcin recursiva QuickSort */
{
register int i=izq, d=der;
char mitad[LargoCadena], aux[LargoCadena];
strcpy(mitad, Cadena[(izq+der)/2]);
do{
while (strcmp(Cadena[i], mitad) < 0)
i++;
while (strcmp(mitad, Cadena[d]) < 0)
d--;
if(i <= d) {
strcpy(aux, Cadena[i]);
strcpy(Cadena[i], Cadena[d]);
strcpy(Cadena[d], aux);
i++;
d--;
}
} while(i <= d);
if(izq < d)
QuickSort(izq, d);
if(i < der)
QuickSort(i, der);
}
void main(){
int i=0;
clrscr();
cout << "Digite " << N << " palabras\n";
while (i < N)
cin >> Cadena[i++];
QuickSort(0, N-1);
cout << "\n\tLas palabras ordenadas son:\n\n";
for (i = 0; i < N; i++)
cout << Cadena[i] << endl;
}

46

PUNTEROS O APUNTADORES
1. INTRODUCCIN
Los punteros son variables las cuales guardan direcciones de memoria RAM.
memoria un puntero ocupa 2 bytes. La direccin de memoria RAM la cual almacena
puntero(p) corresponder a la direccin base de otra variable(var) que est
memoria, decimos entonces que el puntero "apunta" a esta variable, de
siguiente forma:
P

1000

VAR

1000

En
un
en
la

"P apunta a VAR"

1000 es una direccin(ficticia en nuestro ejemplo, la verdadera la dar el


sistema operativo por intermedio del compilador, cuando est ejecutndose el
programa) en memoria, la variable P almacena un valor de 1000. La variable VAR se
encuentra en la direccin de memoria 1000(inicia desde hay). La abstraccin que
se debe hacer es la de que P apunta o seala a VAR.
Se puede definir un puntero de cualquier tipo bsico o de tipos
estructurados; al efectuar su declaracin se debe anteponer un asterisco, *, al
identificador del mismo.

2. PUNTERO A ENTERO
El siguiente es un ejemplo con un puntero que apuntar a un entero(recuerde
que un entero ocupa 2 bytes en memoria):
int *p, entero=13;
p

entero

1 3

1500 1501

1500 es la direccin base de la variable entero, entero al ocupar 2 bytes


estamos suponiendo que ocupar las direcciones 1500 y 1501, estos dos bytes son
el desplazamiento(offset) de la variable entero.
Observe que el 13 almacenado en la variable entero no est en base 10 como es
mostrado, sino en binario, empero lo supondremos de esta forma por facilidad.
A continuacin el puntero p tomar la direccin de la variable entero:
p = &entero;
se lee esta instruccin as: "la direccin(&) de la variable entero se asigna
a la variable puntero p"; en memoria el efecto es el siguiente:

47

1500

entero

1 3

1500 1501

Si se quiere visualizar el valor de la variable entero a travs del puntero


escribiremos la siguiente instruccin:
cout << *p;
Est mostrar el valor de 13 en pantalla; *p debe ser ledo como: "el valor
al cual apunta p", y para saber cual es el valor al cual apunta p, debemos
"saber" la direccin que tiene almacenada p y a qu tipo de datos apunta, en este
caso la variable p, sabemos, ha sido definida como un puntero a un entero.
A travs del puntero podemos, adems y es lo ms importante, modificar el
valor de la variable a la cual est apuntando, esto se efecta as:
*p = 21;
se leer "al valor al que apunta p se le asigna 21", otra vez, para saber
cual es el valor al que apunta p, debemos conocer la direccin que almacena, de
esta forma en memoria las variables quedarn as:
p

1500

entero

2 1

1500 1501

el 13 ha sido destruido al efectuarse la asignacin *p = 21. De similar forma


podremos efectuar una lectura por teclado y asignarselo a la variable entero a
travs del puntero con la instruccin:
cin >> *p;

3. PUNTERO A VARIABLE DE PUNTO FLOTANTE


Los punteros pueden apuntar a variables de cualquier tipo; en el siguiente
ejemplo un puntero, pf, apuntarar a una variable, real, de punto flotante, como
sabemos este ltima tipo de variables ocupan 4 bytes en memoria, la sintaxis de
la declaracin ser:
float *pf, real=4.67;
pf

real

4.67

2500 2501 2502 2503

2500 es la direccin base de la variable real, real ocupa 4 bytes en RAM, y


estamos suponiendo que ocupar las direcciones 2500 a la 2503, estos cuatro bytes
son el desplazamiento(offset) de la variable real.
A continuacin el puntero pf tomar la direccin de la variable real:

48

pf = &real;
se lee esta instruccin as: "la direccin(&) de la variable real se asigna a
la variable puntero pf"; en memoria nos no imaginaremos as:
pf

2500

real

4.67

2500 2501 2502 2503

Para mostrar el valor de la variable real por medio puntero pf, escribiremos
la siguiente instruccin:
cout << *pf;
Mostrar el valor de 4.67 en pantalla; *pf debe ser ledo como: "el valor al
cual apunta pf", y para saber cual es el valor al cual apunta pf, debemos "saber"
la direccin que tiene almacenada pf y a qu tipo de datos apunta, en este caso p
sabemos ha sido definido como un puntero a un float.
A travs del puntero podemos modificar el valor de la variable a la cual est
apuntando:
*pf = -23.56;
se leer "al valor al que apunta pf se le asigna -23.56", otra vez, para
saber cual es el valor al que apunta pf, debemos conocer la direccin que
almacena, de esta forma en memoria las variables quedarn as:
pf

2500

real

-23.56

2500 2501 2502 2503

el 4.67 ha sido destruido al efectuarse la asignacin *pf = -23.56. De


similar forma podremos efectuar una lectura por teclado y asignarselo a la
variable entero a travs del puntero con la instruccin: cin >> *pf;

4. PUNTERO A UN VECTOR
Supongamos tenemos la siguiente declaracin de variables:
int *pv, vector[5] = {17,2,-6,3,28};
la cual corresponde a la siguiente abstraccin:
vector
pv
0
1
2
3
4
<---ndices

17
2
-6

28

direcciones---> 500 501 502 503 504 505 506 507 508 509
Para hacer que el puntero, pv, tome la direccin base del vector se debe

49

escribir la siguiente instruccin:


pv = vector;
observe que no se coloca el operador de direccin &. La abstraccin que
debemos tener quedar:
vector
pv
0
1
2
3
4
<---ndices

500

17
2
-6

28

direcciones---> 500 501 502 503 504 505 506 507 508 509
Los arreglos tienen gran relacin con los punteros y deben ser vistos como
punteros a los cuales no se les puede cambiar la direccin(la direccin base que
almacenan) es decir como punteros constantes. En este caso la variable vector
tiene una direccin base de 500 y un desplazamiento de 2bytes*5=10 bytes, desde
la direccin 500 hasta 509. El anterior arreglo, vector, se puede recorrer con el
puntero, segn el siguiente fragmento:
for(i=0; i<5; i++)
cout << setw(4) << pv[i];
que nos mostrar en pantalla los valores: 17
2 -6
3 28. Es decir que
el puntero, pv, se puede indexar de igual forma que se hace con los
identificadores de los arreglos. Al ejecutar el fragmento anterior el valor en
memoria de pv es de 500, es decir apunta todo el tiempo a la direccin base, el
ndice es el que "avanza" en el arreglo.
Diferente ser si queremos avanzar en el vector, cambiando la direccin del
puntero, es decir que de 500 pase a 502, 504, 506, 508 las cuales son las
posiciones base de cada uno de los elementos enteros del vector: vector[0],
vector[1], vector[2], vector[3] y vector[4], esto se codificar as:
pv = vector;
while (*pv && i<5){
cout << setw(4) << *pv;
pv++;
i++;
}
En pantalla el efecto sera idntico que en el caso anterior, aparecern: 17
2 -6 3 28. En memoria sera muy diferente, la variable pv cada que se le "suma
uno" se incrementar segn el tipo de datos al que apunta, al ser un entero se
desplazar en dos bytes, para entenderlo, veamos prueba de ejecucin manual del
anterior fragmento en el siguiente tabulado:

pv
*pv while(*pv) cout<<setw(4)<<*pv
pv++

500 17
verdad
17
502
502 2
verdad
2
504
504 -6
verdad
-6
506
506 3
verdad
3
508
508 28
verdad
28
510
510 ???
???
La abstraccin de lo que ocurre en memoria, despus de esto, quedara as:
vector

50

pv
0
1
2
3
4
<---ndices

510

17
2
-6

28 ???

direcciones-> 500 501 502 503 504 505 506 507 508 509 510
El puntero pv apuntara a un valor de "basura", mostrado como ???, y por esto
mostrara, eventualmente, en pantalla, algo inesperado, si no se coloca la
instruccin i<5 para que termine.
5. Esta es una demostracin del manejo de un puntero a un nmero real.
#include <iostream.h>
#include <conio.h>
//PUNTERO1.CPP
void main(){
float N=5, *p;
clrscr();
cout << "N = " << N;
p = &N;
cout << "\nA la variable p se le asign el valor: " << p;
cout << "\nN = " << *p;
cout << "\nDigite un valor para la variable N: ";
cin >> *p;
cout << "\nN = " << N;
cout <<"\n\nVariable N est en la direccin de memoria: " <<p;
cout <<"\n\nVariable N est en la direccin de memoria: "<<&N;
cout <<"\n\nPuntero p est en la direccin de memoria: " <<&p;
}
6. Esta es una demostracin del manejo de los punteros.
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
//PUNTERO2.CPP
main(){
int *pE, i, j,
entero=234,
vectorE[] = {3,45,23,67,9},
matrizE[][3] = {4, 7, 8,
9, 2, 0,
6, 2, 9};
char *pC = "Esta es una demostracin\n\n",
caracter
= '',
Cadena[] = {'C','a','l','i','\0'},
*Cad[] = {'\0'},
*Cadenas[] = {"Palmira ", "Valle
","Colombia" };
float *pR,
real = 7.5,
vectorR[] = {3.2, 4.5, -5.7, 0, 0.2},
matrizR[][3] = {4.3, 6.5, 7.8,

51

9.8, 1.2, 0.4,


6.4, 2.3, 9.6};
clrscr();
cout << "VARIABLE
VALOR
DIRECCION\n\n";
pE = &entero;
cout << "entero \t" << *pE << "\t" << pE << "\n\n";
pE = vectorE;
for (i=0; i<5; i++) {
cout <<"\nvectorE[" << i << "]\t" << *pE << "\t" << pE;
pE++;
}
cout <<"\n";
pE = (int *) matrizE;
for (i=0; i<3; i++)
for (j=0; j<3; j++){
cout <<"\nmatrizE[" <<i <<"][" <<j <<"]\t" <<*pE<<"\t" <<pE;
pE++;
}
getch();
clrscr();
cout << "VARIABLE
pR = &real;
cout <<"real

VALOR

DIRECCION\n\n";

\t" << *pR << "\t" << pR << "\n\n";

pR = vectorR;
for (i=0; i<5; i++) {
cout <<"\nvectorR[" << i << "]\t" << *pR << "\t" << pR;
pR++;
}
cout << "\n";
pR = (float *) matrizR;
for (i=0; i<3; i++)
for (j=0; j<3; j++){
cout <<"\nmatrizR[" <<i <<"][" <<j <<"]\t" <<*pR <<"\t"<<pR;
pR++;
}
getch();
clrscr();
cout <<"VARIABLE
VALOR
DIRECCION\n\n";
pC = &caracter;
cout <<"caracter\t"<<*pC<<"\t"<<pC<<"\n\n";//No d la direccin
cout <<"Cadena

\t" << Cadena <<"\t" << &Cadena << "\n\n";

*Cad = Cadena;
cout <<"*Cad\t"<< *Cad<< "\t"<<Cad<<"\n\n";//No d la direccin
pC = Cadena;
i=0;
while (*pC) {
cout<<"\nCadena["<<i<<"]\t"<<*pC <<"\t"<<pC;//No d direccin
pC++;

52

i++;
}
cout <<"\n";
for (i=0; i<3; i++)
cout<<"\n*Cadenas["<<i<<"]\t"<<Cadenas[i]<<"\t"<<&Cadenas[i];
getch();
return 0;
}
7. Invierte una cadena de caracteres.
#include <iostream.h>
#include <stdio.h>
//RCADINVE.CPP
void invierte(char *C){
if (*C) {
invierte(++C);
putchar(*(--C));
}
}
void main(){
char cadena[10];
clrscr();
cout << "Digite cadena: ";
gets(cadena);
cout << "\n
";
invierte(cadena);
getch(); return;
}
Prueba de ejecucin manual se efecta a continuacin: en la funcin principal de
pide se digite una cadena, supongamos la palabra CALI, recuerde que es colocado,
por la instruccin de lectura gets, un terminador nulo '\0' despus del ltimo
caracter vlido, imaginemos la situacin as:
Pantalla
CADENA (en RAM)

0 1 2 3 4 5 6 7 8 9
Digite cadena: CALI

C A L I \0

A continuacin es invocada la funcin invierte, pasando como parmetro el


identificador de cadena, al ser cadena un arreglo se pasa su direccin base es
decir 1000, ocurriendo lo siguiente:
Invierte(1000)

1000

Ya en la funcin y en la instruccin if(*C), esta debe ser leda como "si el


valor al que apunta C es verdadero" C tiene un valor de 1000, debido a esto

53

apunta a la posicin base del vector cadena, o en otras palabras apunta a


cadena[0], en esta posicin est almacenada la letra 'C' esto quiere decir que el
if(*C) es verdadero. Se entra en este if y se produce una invocacin recursiva de
la funcin Invierte, empero antes se produce el incremento de la instruccin ++c,
pasando de 1000 a 1001, este ltimo valor es el que es pasado a la funcin:

1000
1001

Invierte(1001)

1001

En el mbito de la invocacin de esta funcin ocurre algo similar, se ha


recibido la direccin 1001 en la variable C, el if(*C) ser verdadero debido a
que C apunta a la direccin 1001 donde est la letra 'A', se incrementar C a
1002 y se pasar como parmetro en otra invocacin recursiva:

1000
1001

1001
1002

Invierte(1002)

1002

se sigue invocando recursivamente otras dos veces, verifquelo usted mismo:


Invierte(1003)

1000
1001
1002
1003
1001
1002
1003

Invierte(1004)

1000
1001
1002
1003
1004
1001
1002
1003
1004

if(*C) apunta a un nulo, C tiene el valor de 1004 y en esta direccin est


almacenado un nulo, por esto es falso y por consiguiente se sale de la funcin,
retornando a la invocacin anterior; ya en esta putchar(*(--C); se
decrementa
inicialmente al puntero C as:
Invierte(1003)

1003
1004
1003

por consiguiente C apunta a la letra I en el vector cadena, en pantalla


aparecer la letra I, terminando la funcin y volviendo al sitio
en que fu
invocada anteriormente,
Invierte(1002)

Digito Cadena: Cali


1000
1001
1002

1001
1002
1003

1000
1001

1001
1002

1002
1003

54

es decir en Invierte(--C); ya aqu en la instruccin putchar(*(--C) se


decrementa C, de 1003 a 1002, y a continuacin se escribe en pantalla el caracter
L, ya que es el que est en la direccin 1002. Se termina la funcin
devolvindose.

Digito Cadena: Cali

IL

1000
1001

1001
1002

Invierte(1002)

1002
1003
1002

Ahora a la invocacin anterior, de nuevo en putchar(*(--C); se decrementa C


de 1002 a 1001, de esta forma C apunta a la direccin 1001, donde est la letra
A, escribindola en pantalla:

Digite Cadena: Cali

ILA

1000
1001

Invierte(1001)

1001
1002
1001

Termina esta invocacin y se devuelve a la anterior, decrementndose C de 1001 a


1000; apuntando C al caracter C y escribindolo en pantalla:

Digite Cadena: Cali

ILAC

Invierte(1000)

1000
1001
1000

Retorna esta vez a la intruccin siguiente


originalmente, en el main(), terminando el algoritmo.

la

que

fu

llamada

8. Se calcula la longitud de una cadena de caracteres utilizando recursin.


#include <iostream.h>
#include <stdio.h>
//RLARGCAD.CPP
Longitud(char *p){
if(*p) {
p++;
return (1 + Longitud(p));
}
else

55

return (0);
}
void main(){
char palabra[30];
cout << "Digite Una cadena: ";
gets(palabra);
cout << "Longitud: " << Longitud(palabra);
}
9. El siguiente es un ejemplo en el cual un puntero "apunta" a un
registro(struct). Ver el siguiente captulo para la definicin de este tipo de
datos estructurado.
//PUNTERO3.CPP
#include <iostream.h>
#include <stdio.h>
typedef struct persona PERSONA;
struct persona{
char nombre[20];
int edad;
float alto;
}
void main(){
PERSONA amigo, *p;
p = &amigo;
cout << "Nombre: "; gets(p->nombre);
cout << "Edad: "; cin >> p->edad;
cout << "Altura: "; cin >> p->alto;
cout << p->nombre << " " << p->edad << " " << p->alto;
}
10. El siguiente algoritmo presenta el intercambio del valor de dos variables en
la memoria RAM del computador, por medio de una invocacin de una funcin por
referencia al estilo del C.
//FUNCION8.CPP
#include <iostream.h>
#include <conio.h>
IntercambioEnMemoria(int *a, int *b){
int *aux;
//variable local
*aux= *a;
*a
= *b;
*b
= *aux;
}
main(){
int a,b;
clrscr();
cout << "Digite un real para almacenar en variable A: ";
cout << "Digite un real para almacenar en variable B: ";

cin >> a;
cin >> b;

56

IntercambioEnMemoria(&a, &b);
cout <<"\nDespus de intercambiadas, A ahora es igual a "<<a;
cout << "\ny la variable B ahora es igual a " << b;
}

57

11. El siguiente algoritmo en lenguaje C ordena alfabticamente, en forma


ascendente, cadena de caracteres. Advertencia: Alguna vez puede que le falle este
programa debido a la forma que se define la variable *cadena, se le explicar
esto en el captulo sobre cadenas, ms adelante.
//PUNTERO11.CPP
#include <iostream.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>
void main(){
char *cadena, aux;
int i, j;
cout << "Digite una frase: "; gets(cadena);
cout << "Longitud cadena = " << strlen(cadena) << "\n\n";
for(i=0; i<strlen(cadena); i++)
for(j = i+1; j<strlen(cadena); j++)
if(cadena[i] > cadena[j]){
aux = cadena[i];
cadena[i] = cadena[j];
cadena[j] = aux;
}
cout << "\"frase ordenada alfabticamente\": \n" ;
puts(cadena);
}
12. A continuacin se presenta una demostracin de como el lenguaje C maneja cada
posicin de un arreglo bidimensional por medio de punteros. Recuerde que un
arreglo bidimensional es solamente un arreglo de arreglos.
//PMATRI12.CPP
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
const int MaxFila=5, MaxCol=4;
void main(){
int Matriz[MaxFila][MaxCol], Fila, Col;
for ( Fila = 0; Fila < MaxFila; Fila++){
for ( Col = 0; Col < MaxCol; Col++){
Matriz[Fila][Col]= Fila*Col+1;
cout << setw(10) << Matriz[Fila][Col];
}
cout << endl;
}
getch();
for ( Fila = 0; Fila < MaxFila; Fila++) {
for ( Col = 0; Col < MaxCol; Col++)
cout << setw(10) << *( *(Matriz+Fila) + Col) ;
cout << endl;
}
}

58

13. Se digitan N nmeros se almacenan en vector y luego se ordenan.


//PUNTERO13.CPP
#include <iostream.h>
#include <conio.h>
#define N 10
Leer(int *v){
int i=0, num;
gotoxy(10,2); cout << "Digite " << " nmeros";
while (i < N){
gotoxy(10,4+i);
cin >> v[i++];
}
}
Ordenar(int *v){
int i,j,aux ;
for (i = 0; i < N; i++)
for (j = i+1; j < N; j++)
if (v[i] > v[j]){
aux = v[j];
v[j]= v[i];
v[i] = aux;
}
}
Escribir(int *v){
int i;
cout << "\n\tLos nmeros ordenados son:\n\n";
for (i = 0; i < N; i++){
cout.width(5);
cout << v[i];
}
}
void main(){
int numeros[N];
clrscr();
Leer(numeros);
Ordenar(numeros);
Escribir(numeros);
while (!kbhit());
}

59

14.

Este programa convierte un decimal a binario.


//PUNTERO14.CPP

#include <iostream.h>
#include <conio.h>
int leer(){
int N;
clrscr();
cout << "Digite un entero para convertirlo a binario: ";
cin >> N;
return (N);
}
void CalcularBinario(int N, int *r){
int c;
c = N >> 1;
*r = N % 2;
while(c){
r++;
*r = c % 2;
c >>= 1;
}
r++;
*r = 2; //se utiliza el dos como terminador
}
void main(){
int b=0, j, decimal, binario[20];
decimal = leer();
CalcularBinario(decimal, binario);
cout << "\n\nbinario = " ;
while(binario[b]==1 || binario[b]==0)
b++;
for(j=b-1; j>=0; j--)
cout << binario[j];

// busca el final de la cadena

// escribe el binario adecaudamente

PROGRAMA A REALIZAR COMO EJERCICIO


Dibuje en forma grfica rectngulo con divisiones, el cual represente un vector
de N posiciones en las cuales almacenar enteros. Efectue a continuacin lectura
con la funcin LeerInt(.. ), la cual encontrar en el programa IO_Graph.CPP
(utilcela solo como herramienta, en captulo ms adelante se le explicarn los
conceptos bsicos para poder entender el algoritmo contenido en ella), de cada
uno de los enteros en sus respectivas posiciones. Luego utilizando funcin de
ordenamiento de nmeros enteros cualquiera y presentada en este captulo, muestre
en pantalla la correspondiente clasificacin paso a paso(step by step).

60

PASO DE PARMETROS POR REFERENCIA


1. FORMA TRADICIONAL DEL LENGUAJE C.
Otra forma de comunicacin, adicional al retorno de un valor, el cual puede
producir una funcin, consiste en el paso de parmetros por referencia, en el
cual cada variable pasada como parmetro, puede ser modificada por las
instrucciones contenidas en el mbito de la funcin. Recordemos que cuando una
variable es pasada como parmetro por valor, esto no es posible (ver mdulo
anterior).
Para entender esto estudiemos el programa REFEREN1.CPP a continuacin:
1.1 El siguiente algoritmo presenta el intercambio del valor de dos variables en
la memoria RAM del computador, por medio de una invocacin de una funcin por
referencia al estilo del C.
//REFEREN1.CPP
#include <iostream.h>
#include <conio.h>
void IntercambioEnMemoria(float *a, float *b){
float aux;
//variable local
aux= *a;
*a
= *b;
*b
= aux;
}
void main(){
float X, Y;
clrscr();
cout << "Digite un real para almacenar en variable X: ";
cin >> X;
cout << "Digite un real para almacenar en variable Y: ";
cin >> Y;
IntercambioEnMemoria(&X, &Y);
cout << "\nDespus de intercambiadas, X ahora es igual a "
cout << "\ny la variable Y ahora es igual a " << Y;
getch();

<< X;

}
Inicialmente, en la funcin main del programa anterior, se pide ser digitados
los valores de las variables X y Y, supongamos, que despus de esto, la memoria
RAM se encuentra as:
RAM

main()

X
Y

13.1
7.4

61

1000
1002

Se invoca la funcin IntercambioEnMemoria pasando los parmetros &X y &Y,


esto significa que se pasan las direcciones en RAM de las dos variables, y no sus
valores. Supongamos que estas direcciones son 1000 y 1002, estas son recibidas
por los punteros a entero *a y *b, en memoria sera:
RAM

main()

IntercambioEnMemoria()

X
Y

a
b
aux

13.1
7.4 1000 1002

1000
1002

Se define adicionalmente la variable local aux. Las tres instrucciones del


cuerpo de la funcin IntercambioEnMemoria() realizan lo siguiente:
aux = *a;
su efecto en memoria RAM es:
RAM

main()

IntercambioEnMemoria()

X
Y

a
b
aux

13.1
7.4 1000 1002 13.1

1000
1002

Contina:
*a = *b;
la cual debe ser leda como: "a la direccin a la que apunta la variable a
se le asigna el valor al que apunta la variable b", es decir que la direccin
1000 de la variable X tomar el valor de la direccin 1002 que es 7.4, veamos:

RAM

main()

IntercambioEnMemoria()

X
Y

a
b
aux

7.4
7.4 1000 1002 13.1

1000
1002

Finalmente, la instruccin:
*b = aux;

62

que se leer como: "A la direccin a la que apunta b se le asigna el valor de


aux, quedando finalmente:
RAM

main()

IntercambioEnMemoria()

X
Y

a
b
aux

7.4
13.1 1000 1002 13.1

1000
1002

Terminando la funcin y volviendo el flujo del programa a la instruccin a


continuacin de la invocacin de IntercambioEnMemoria. Recordar que cuando
termina una funcin, las variables locales se destruyen, por esto en este momento
tendremos en RAM:

X
Y

7.4
13.1

1000
1002

Y por lo tanto, estos son los valores para cada una de las variables, X y Y,
que mostrar en pantalla.
1.2 Convierte un decimal a binario. Se presenta ejemplo de paso de parmetro por
referencia.
#include <iostream.h>
#include <conio.h>
//PUNTERO6.CPP
int leer(){
int N;
clrscr();
cout << "Digite un entero para convertirlo a binario: ";
cin >> N;
return (N);
}
CalcularBinario(int N, int *p){
int c,r;
c = N >> 1;
*p = N % 2;
cout <<"\n
Leer desde abajo hacia arriba" << *p;
while(c){
p++;
*p = c % 2;
cout << "\n" << *p;
c >>= 1;
}
return 0;
}
main(){

63

int i, decimal, binario[20];


decimal = leer();
CalcularBinario(decimal, binario);
getch(); return 0;
}
1.3 Se digitan N nmeros se almacenan en vector y luego se ordenan.
#include <iostream.h>
#include <conio.h>
//PUNTERO8.CPP
const int N=10;
Leer(int *v){
int i=0;
gotoxy(10,2); cout << "Digite " << N << " nmeros";
while (i < N) {
gotoxy(10,4+i); cin >> v[i++];
}
}

Ordenar(int *i){
int *j, aux ;
while(*i) {
j = i+1;
while(*j) {
if (*i > *j){
aux = *i;
*i = *j;
*j = aux;
}
j++;
}
i++;
}
}
Escribir(int *v){
cout <<"\n\tLos nmeros ordenados son:\n\n";
while(*v){
cout.width(4);
cout << *v++;
}
}
void main(){
int vector[N];
clrscr();
Leer(vector);
Ordenar(vector);
Escribir(vector);
while (!kbhit()); return 0;
}

64

1.4 Se digitan N nmeros se almacenan en vector y luego se ordenan.


#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
//PUNTERO9.CPP
const int N=10;
Leer(int *v){
int i=0, num;
gotoxy(10,2);
cout << "Digite " << " nmeros";
while (i < N){
gotoxy(10,4+i); cin >> v[i++];
}
}
Ordenar(int *v){
int i,j,aux ;
for (i = 0; i < N; i++) {
for (j = i+1; j < N; j++)
if (v[i] > v[j]){
aux = v[j];
v[j]= v[i];
v[i] = aux;
}
}
}

Escribir(int *v){
int i;
cout << "\n\tLos nmeros ordenados son:\n\n";
for (i = 0; i < N; i++)
cout << setw(5) << v[i];
}
}
void main(){
int numeros[N];
clrscr();
Leer(numeros);
Ordenar(numeros);
Escribir(numeros);
while (!kbhit());
}

2. NUEVA FORMA DEL C++


En

el

C++,

adicionalmente,

se

puede

pasar

por

referencia

el

parmetro

65

real(verdadero) de una funcin de la siguiente forma: En la invocacin se pasa la


variable de igual forma que se hace por valor, esto es una "desventaja" ya que al
ver la instruccin no nos daramos cuenta si se est pasando por referencia o
valor, la costumbre nos hara pensar que es por valor, empero para estar seguros
debemos ver la definicin de la funcin; al identificador que recibe, en la
definicin de la funcin, se le antepondr el operador de direccin, &; de esta
forma, en la memoria RAM tomar la misma direccin del parmetro de invocacin;
veamos el programa REFEREN3.CPP a continuacin:
2.1 El siguiente algoritmo presenta el intercambio del valor de dos variables en
la memoria RAM del computador, por medio de una invocacin de una funcin con
parmetros por referencia al estilo del Pascal en C++;
//REFEREN3.CPP
#include <iostream.h>
#include <conio.h>
void IntercambioEnMemoria(float &a, float &b){
float aux;

//El & dara error en C

aux = a;
a
= b;
b
= aux;
}
void main(){
float X, Y;
clrscr();
cout << "Digite un real para almacenar en variable X: ";
cin >> X;
cout << "Digite un real para almacenar en variable Y: ";
cin >> Y;
IntercambioEnMemoria(X, Y);
cout << "\nDespus de intercambiadas, X ahora es igual a "
cout << "\ny la variable Y ahora es igual a " << Y;

<< X;

}
Inicialmente, en la funcin main() del programa anterior, se pide ser
digitados los valores de las variables X y Y, supongamos, que despus de esto, la
memoria RAM se encuentra as:

X
Y

13.1
7.4

1000
1002

Se invoca la funcin IntercambioEnMemoria pasando los parmetros X y Y, esto


significa que se pasan los valores en RAM de las dos variables, y no sus
direcciones. Estos son recibidos por las variables &a y &b, lo que significa que
en la misma direccin de memoria se definirn a y b, de la siguiente forma:
RAM

66


main()

IntercambioEnMemoria()

(a)
(b)

X
Y

aux

13.1
7.4

1000
1002

Se define tambien la variable local aux. Las tres instrucciones del cuerpo de
la funcin IntercambioEnMemoria() realizan lo siguiente:
aux = a;
el efecto en memoria RAM es:

main()

IntercambioEnMemoria()

(a)
(b)

X
Y

aux

13.1
7.4
13.1

1000
1002

Contina:
a = b;

main()

IntercambioEnMemoria()

(a)
(b)

X
Y

aux

7.4
7.4
13.1

1000
1002

Finalmente, la instruccin:
b = aux;
RAM

main()

IntercambioEnMemoria()

(a)
(b)

X
Y

aux

7.4
13.1
13.1

1000
1002

Terminando la funcin y volviendo el flujo del programa a la instruccin a


continuacin de la invocacin de IntercambioEnMemoria. Recordar que cuando
termina una funcin, las variables locales se destruyen, por esto en este momento
tendremos en RAM:

X
Y

7.4
13.1

67


1000
1002

Y por lo tanto, estos son los valores para cada una de las variables, X y Y,
que mostrar en pantalla.

2.2 Ejemplo de paso de parmetro por referencia


Convierte un nmero en base 10 a base binaria.

al

nuevo

estilo

del

C++.

#include <iostream.h>
#include <conio.h>
//REFEREN2.CPP
leer(int &N){
clrscr();
cout << "Digite: ";
cin >> N; //observe que N al ser puntero se coloca sin &
}
CalcularBinario(int &N){
int c,r;
c = N >> 1;
// divide entre dos
r = N % 2;
cout << "\n" << r << " Leer de abajo hacia arriba";
while(c){
r = c % 2;
c >>= 1;
cout << "\n" << r;
}
}
void main(){
int decimal;
leer(decimal); //invocacin por referencia
CalcularBinario(decimal); //invocacin por valor
}
2.3 Ejemplo de paso de parmetro por referencia
Convierte un nmero en base 10 a base binaria

al

nuevo

estilo

del

C++.

#include <iostream.h>
#include <conio.h>
//REFEREN2.CPP
leer(int &N){
cout << "Digite: "; cin >> N;//observe que N al ser puntero se coloca sin &
}
CalcularBinario(int &N){
int c, r;
c = N >> 1;
// divide entre dos
r = N % 2;
cout << "\n" << r << " Leer de abajo hacia arriba";
while(c){
r = c % 2;

68

c >>= 1;
cout << "\n" << r;
}
}
void main(){
int decimal;
leer(decimal); //invocacin por referencia
CalcularBinario(decimal); //invocacin por valor
}

2.4 El siguiente algoritmo presenta el intercambio del valor de dos variables en


la memoria RAM del computador, por medio de una invocacin de una funcin con
parmetros por referencia.
//FUNCION9.CPP
#include <iostream.h>
#include <conio.h>
IntercambioEnMemoria(int &a, int &b){ //Esto dara error en C, y no en C++
int aux;
//variable local
aux = a;
a
= b;
b
= aux;
}
void main(){
int a,b;
cout << "Digite un real para almacenar en variable A: ";
cin >> a;
cout << "Digite un real para almacenar en variable B: ";
cin >> b;
IntercambioEnMemoria(a, b);
cout <<"\nAhora A = " <<a << " y B = " << b << " despus del intercambio";
}

69

PROGRAMA DE ESTADSTICA BASICA


1. Se utiliza paso de parmetros por referencia y por valor en varias funciones.
Se utiliza la estructura de datos vector para almacenar los datos en memoria
principal, pudiendo grabar y recuperar desde disco. Adicionalmente se presente un
grfico de barras paralelas con los datos de cada muestra.
//ESTADIST.CPP
#include
<iostream.h>
#include
<iomanip.h>
#include
<fstream.h>
#include
<graphics.h>
#include
<math.h>
#include
<conio.h>
#include
<ctype.h>
#include
<stdlib.h>
#include
<io.h>
#include
<fcntl.h>
const int MaxArreglo = 20;
int intro_datos(float *datos) {
int t, max;
gotoxy(38,1); cout << "Digite nmero de items?: ";
gotoxy(63,1); cin >> max;
for(t=0; t<max; ++t) {
gotoxy(40, 2+t); cout << "Introduzca Item " << t+1 << ": ";
cin >> datos[t];
}
gotoxy(40, 3+t); cout << "Cualquier tecla y seguir..." ; getch();
return max;
}
void marco(){
int indice;
window(1,1,80,25);
clrscr();
cout<<"";
cout<<"
EJEMPLO DE ESTADISTICA BASICA
";
cout<<"";
for(indice = 5; indice < 25; ++indice)
cout<<"
";
cout<<"";
window(2,7,70,23);
}
char CaracterEstaEn(char ch, char *s){
while(*s) {
if(ch == *s) return ch;
else s++;
}
return 0;
}
float CalcularPromedio(float Datos[], int N){ //PRUEBA ESCRITORIO

70

int t;
float Promedio=0, *P;
P = Datos;
for(t = 0; t < N; ++t){
Promedio += *P;
// Promedio = Promedio + *P; es lo mismo
P++;
}
Promedio /= N;
return Promedio;
}
float CalcularPromedio(float Datos[], int N){ //PRUEBA ESCRITORIO
int t;
float Promedio=0, *P;
P = Datos;
for(t = 0; t < N; ++t){
Promedio += *P;
// Promedio = Promedio + *P; es lo mismo
P++;
}
Promedio /= N;
return Promedio;
}
float CalcularMediana(float Datos[], unsigned int N){ //PRUEBA ESCRITORIO
register int t;
float temporal[MaxArreglo];
for (t=0; t<N; ++t)
temporal[t] = Datos[t]; /* copiar Datos*/
ClasificarMuestraAscendentemente(temporal, N);
return (temporal[(N-1)/2]);
}
void IntercambiarValoresDosVariables(float *a, float *b){
float aux;
aux = *a;
*a = *b;
*b = aux;
}
void ClasificarMuestraAscendentemente(float *Datos, unsigned int N){
//PRUEBA ESCRITORIO cuando sea invocada desde la funcion CalcularMediana()
int i,j;
float aux;
for (i = 0; i < N; i++)
for (j = i; j < N; j++)
if (Datos[i] > Datos[j])
IntercambiarValoresDosVariables(&Datos[i], &Datos[j]);
}
float EncontrarModa(float *Datos, int N){ //PRUEBA ESCRITORIO
register int t, w;

71

float md, AnteriorModa;


int cont, antcont;
AnteriorModa=0;
antcont=0;
for (t=0; t< N; ++t) {
md = Datos[t];
cont = 1;
for(w=t+1; w < N; ++w)
if(md == Datos[w])
cont++;
if(cont > antcont) {
AnteriorModa = md;
antcont = cont;
}
}
return AnteriorModa;
}
float BuscarMenorYMayor(float *Datos, int N, float &mayor){//PRUEBA ESCITORIO
int t;
float menor;
menor = mayor = Datos[0];
for(t=1; t < N; ++t)
if(Datos[t] < menor)
menor = Datos[t];
else
if(Datos[t] > mayor)
mayor = Datos[t];
return menor;
}
void Mostrar(float *Datos, int max){
register int t;
float total=0, porcentajes[MaxArreglo];
for (t = 0; t < max; t++)
total += Datos[t];
for (t = 0; t < max; t++)
porcentajes[t] = Datos[t] / total;
for(t = 0; t < max; ++t) {
gotoxy(32,1+t);
cout << setfill('.') << setw(2) << t+1 << setiosflags(ios::fixed)
<< setiosflags(ios::showpoint) << setiosflags(ios::right)
<< setprecision(2) << setw(10) << Datos[t]
<< setw(10) << porcentajes[t]*100 << "%";
}
gotoxy(35,4+t);
cout <<"Cualquier tecla y seguir...
";
getch();
}
float DesviacionEstandard(float *Datos, int max){//PRUEBA ESCRITORIO
register int t;

72

float DesvStd=0, Promedio;


double aux;
Promedio = CalcularPromedio(Datos,max);
for(t = 0; t < max; ++t)
DesvStd += ((Datos[t] - Promedio) * (Datos[t] - Promedio));
if(max)
DesvStd /= max;
DesvStd = sqrt(DesvStd);
return DesvStd;
}
void GraficarPorcentajes(float *Datos, int max){//PRUEBA ESCRITORIO
int
ManejadorGrafico, ModoGrafico;
int i, izquierda, arriba, ancho, abajo, profundidad;
float total=0;
float porcentajes[MaxArreglo];
if (max){
for (i = 0; i < max; i++)
total += Datos[i];
for (i = 0; i < max; i++)
porcentajes[i] = ((float) Datos[i]) / total;
detectgraph(&ManejadorGrafico, &ModoGrafico);
initgraph(&ManejadorGrafico, &ModoGrafico, "c:\\tc\\bgi");
ancho = (int)( (getmaxx()) / ((max * 2 ) + 1) );
abajo = getmaxy() - 10;
profundidad = (int) (ancho / 4);
izquierda = ancho;
setbkcolor(WHITE);
for (i = 0; i < max; i++) {
arriba = (abajo) - ((int)(porcentajes[i] * (getmaxy() - 25)));
setcolor(RED); //color de las lneas de cada barra
setfillstyle(i+1, i+1);
bar3d(izquierda,arriba,(izquierda+ancho),abajo,profundidad,1);
izquierda += (ancho * 2);
}
getch();
closegraph();
MarcoPresentacion();
}
}
void ImprimirEnImpresora(float *Datos, int max){
register int t;
float total=0, porcentajes[MaxArreglo];
ofstream Imprimir("PRN");
for (t = 0; t < max; t++)
total += Datos[t];
for (t = 0; t < max; t++)
porcentajes[t] = Datos[t] / total;
gotoxy(35,4);
cout <<"Imprimiendo...
";
Imprimir << "\n
Registro

Datos

Porcentajes \n\n";

73

for(t = 0; t < max; ++t) {


Imprimir << setfill('.') <<setw(5) << t+1 << setiosflags(ios::fixed)
<< setiosflags(ios::showpoint) << setiosflags(ios::right)
<< setprecision(2) << setw(15) << Datos[t]
<< setw(15) << porcentajes[t]*100 << "%" << endl;
}
Imprimir << "\f";
}
void LeerArchivoYCargarEnDatos(float *Datos, int &N){
int IDArchivo;
fstream Archivo;
N=0;
Archivo.open("Estadist.ica", ios::in | ios::binary);
if(Archivo){
while( Archivo.read( (char *)&Datos[N], sizeof(float) ) )
N++;
Archivo.close();
cout << "Ledos desde disco: " ; Mostrar(Datos, N);
}
else
cout << "Archivo no existe";
}
void GrabarDatosEnArchivo(float *Datos, int N){
int i;
fstream Archivo;
Archivo.open("Estadist.ica", ios::out|ios::binary|ios::trunc);
if (!Archivo)
cout << "Error en la apertura del archivo \a";
else{
for(i=0; i<N; i++)
Archivo.write((char *)&Datos[i], sizeof(float));
Archivo.close();
}
}

char OpcionMenu(){
char entrada;
clrscr();
do {
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(
gotoxy(

3, 1);
3, 2);
3, 3);
3, 4);
3, 5);
3, 6);
3, 7);
3, 8);
3, 9);
3,13);

cout
cout
cout
cout
cout
cout
cout
cout
cout
cout

<<
<<
<<
<<
<<
<<
<<
<<
<<
<<

"MENU PRINCIPAL";
"==============";
"Capturar Datos";
"Estadsticas b sicas";
"Ordenar de menor a mayor";
"Mostrar Datos";
"Graficar en barras";
"Imprimir en papel";
"Terminar";
"Elija letra inicial (C E O M G I T): ";

74

gotoxy(39,13); entrada = AMayuscula(getch());


} while (!CaracterEstaEn(entrada, "CEOMGIT"));
return entrada;
}
void main(){ //ESTADISTICA BASICA FUNCION PRINCIPAL
float Datos[MaxArreglo]; // almacena valores de la muestra
int N=0; //Nmero verdadero de elementos
float Promedio=0,Mediana=0,DesvStd=0, Varianza=0, Moda=0,
Mayor=0, Menor=0;
MarcoPresentacion();
LeerArchivoYCargarEnDatos(Datos, N);
for(;;) {
switch( OpcionMenu() ) {
case 'C': N = Intro_Datos(Datos);
break;
case 'E': Promedio = CalcularPromedio(Datos, N);
Mediana = CalcularMediana(Datos, N);
Moda = EncontrarModa(Datos, N);
Menor = BuscarMenorYMayor(Datos, N, Mayor);
DesvStd = DesviacionEstandard(Datos, N);
Varianza = DesvStd*DesvStd;
gotoxy(30, 1);
cout<<"Promedio
: " <<Promedio;
gotoxy(30, 2);
cout <<"Mediana
: " <<Mediana;
gotoxy(30, 3);
cout <<"Desviacin Std : " <<DesvStd;
gotoxy(30, 4);
cout <<"Varianza
: "<<Varianza;
gotoxy(30, 5); cout <<"Moda
: " << Moda;
gotoxy(30, 6); cout <<"Mximo
: "<<Mayor;
gotoxy(30, 7); cout <<"Mnimo
: " << Menor;
gotoxy(30, 9);
cout <<"Cualquier tecla y seguir...";
getch();
break;
case 'M': Mostrar(Datos, N);
break;
case 'O': ClasificarMuestraAscendentemente(Datos, N);
Mostrar(Datos, N);
break;
case 'G': GraficarPorcentajes(Datos, N);
break;
case 'I': ImprimirEnImpresora(Datos, N);
break;
case 'T': GrabarDatosEnArchivo(Datos, N);
exit(0);
}

75

}
}
PROGRAMA A REALIZAR COMO EJERCICIO
Utilizando datos obtenidos en algn laboratorio de los realizados aqu en la
universidad, y claro que dentro de otras asignaturas, estudie y utilice el
programa ESTADIST.CPP anterior para efectuar clculos estadsticos bsicos.
Presente dibujo en pantalla representativo del experimento en cuestin, discuta
esto primero con el profesor. El programa debe presentar men diseado por usted
mismo a partir de la primera clase y todo en forma grfica. Para la lectura de
los correspondientes valores reales(float) utilice la funcin LeerFloat(...) la
cual encontrar en el archivo IO_Graph.CPP.

76

PUNTERO A NOTAS MUSICALES


1. El siguiente programa permite escuchar varias melodas. Las notas de estas
estn almacenadas en vectores. Los vectores son recorridos por medio de un
puntero.
//Musica.cpp
#include
#include
#include
#include
#include
#include

<ConIO.h>
<IOStream.h>
<ConStream.h>
<Math.h>
<CType.h>
<DOS.h>

constream Escribir;
void main(){
int I, J, K, Tecla[71], tempo=60, ModoVideo;
Tecla[0]=0;
Tecla[39]= 5; Tecla[40]= 7; Tecla[41]= 8; Tecla[42]= 9;
Tecla[44]=11; Tecla[45]=13; Tecla[46]=14; Tecla[47]=15;
Tecla[49]=17; Tecla[50]=18; Tecla[51]=19; Tecla[52]=21;
Tecla[54]=23; Tecla[55]=24; Tecla[56]=25; Tecla[57]=27;
Tecla[59]=29; Tecla[60]=30; Tecla[61]=31; Tecla[62]=32;
Tecla[64]=35; Tecla[65]=36; Tecla[66]=37; Tecla[67]=38;
Tecla[69]=40; Tecla[70]=42;
int Nota[88];
char C[2], opcion, *p;
char Sinfonia40[]
55,2, 54,2,
62,2, 61,2,
54,2, 52,2,
61,2, 59,2,
62,2, 61,2,
62,2, 61,2,
55,2, 54,4,
0,4, 64,8,
64,4, 65,4,

= {
//Mozart
54,4, 55,2, 54,2,
59,4, 59,2, 57,2,
52,4, 54,2, 52,2,
58,4, 58,2, 55,2,
61,4, 64,4, 58,4,
61,4, 64,4, 58,4,
46,4, 47,4, 49,4,
65,2, 0,6, 64,8,
-1,-1};

54,4,
55,4,
52,4,
54,4,
61,4,
61,4,
50,4,
65,2,

55,2,
55,2,
54,2,
54,2,
59,4,
59,4,
52,2,
0,6,

54,2,
54,2,
52,2,
52,2,
54,4,
62,4,
50,2,
64,8,

Tecla[43]=10;
Tecla[48]=16;
Tecla[53]=22;
Tecla[58]=28;
Tecla[63]=33;
Tecla[68]=39;

54,4,
52,4,
52,4,
50,4,
0,4,
61,2,
49,4,
65,4,

62,4,
52,4,
61,4,
50,4,

0,4,
0,4,
0,4,
0,4,

59,2, 57,2,
47,4, 54,4,
64,4, 65,4,

char LaCucaracha[] = { //popular mejicano


42,1,0,1, 42,1,0,1, 42,1,0,1,47,1,0,5,51,1,0,3,42,1,0,1,42,1, 0,1,
42,1,0,1,47,1,0,5,51,1,0,5,30,1,0,1,30,1,0,1,35,1,0,3,47,1, 0,1,
47,1,0,1,46,1,0,1,46,1,0,1,44,1,0,1,44,1,0,1,42,8,0,2,42,1, 0,1,
42,1,0,1,42,1,0,1,46,1,0,5,49,1,0,3,42,1,0,1,42,1,0,1,42,1, 0,1,
46,1,0,5,49,1,0,5,37,1,0,1,37,1,0,1,30,1,0,3,54,2,56,2,54,2, 52,2,
51,2,49,2,47,8, -1,-1};
char ElDanubioAzul[] = { // J.S.Strauss
42,4,46,4,49,4,49,4,0,4, 61,2,0,2, 61,2,0,6, 58,2,0,2, 58,2,0,6, 42,4,
42,4,46,4,49,4,49,4,0,4, 61,2,0,2, 61,2,0,6, 59,2,0,2, 59,2,0,6, 41,4,
41,4,44,4,51,4,51,4,0,4, 63,2,0,2, 63,2,0,6, 59,2,0,2, 59,2,0,6, 41,4,
41,4,44,4,51,4,51,4,0,4, 63,2,0,2, 63,2,0,6, 58,2,0,2, 58,2,0,6, 42,4,
42,4,46,4,49,4,54,4,0,4, 66,2,0,2, 66,2,0,6, 61,2,0,2, 61,2,0,6, 42,4,
42,4,46,4,49,4,54,4,0,4, 66,2,0,2, 66,2,0,6, 63,2,0,2, 63,2,0,6, 44,4,
44,4,47,4,51,2,0,2,51,14,0,2, 48,4,49,4,58,16,54,4,46,4,46,8,44,4,51,8,

77

49,4,42,4,0,2,42,2,42,4,0,8, 49,2,0,2, 47,2,0,6, 49,2,0,2, 47,2,0,6,


49,4,58,16,56,4,49,2,0,2,46,2,0,6, 49,2,0,2, 46,2,0,6, 49,4,56,16,54,4,49,
2,0, 2,47,2,0,6, 49,2,0,2, 47,2,0,6, 49,4,58,16,56,4,49,4,54,4,56,4,58,
4,61,8,59,4,58,2,58,2,58,4,56,2,0,2, 54,4,0,8, -1,-1};

char Humoresque[] = { // Dvorak


47,3,0,2,49,1,47,3,0,2,49,1,51,3,0,2,54,1,56,3,0,2,54,1,59,3,0,2,58,1,
61,3,0,2,59,1,58,3,0,2,61,1,59,3,0,2,56,1,54,3,0,2,54,1,56,3,0,2,54,1,
59,3,0,2,56,1,54,3,0,2,51,1,49,24,47,3,0,2,49,1,47,3,0,2,49,1,51,3,
0,2,54,1,56,3,0,2,54,1,56,3,0,2,58,1,61,3,0,2,59,1,58,3,0,2,61,1,59,3,
0,2,56,1,
54,3, 0,2, 54,1, 59,3, 0,2, 47,1, 49,6, 54,6, 47,18, -1,-1};
char PopGoesTheWeasle[] = { // Annimo
47,2,0,2,47,2,49,2,0,2,49,2,51,2,54,2,51,2,47,2,0,2,42,2,
47,2,0,2,47,2,49,2,0,2,49,2,51,6,47,2,0,2,42,2,47,2,0,2,47,2,49,2,
0,2,49,2,51,2,54,2,51,2,47,2,0,4,56,2,0,4,49,2,0,2,52,2,51,6,47,2,
0,4,59,2,0,2,59,2,56,2,0,2,59,2,58,2,61,2,58,2,54,2,0,4,59,2,0,2,
59,2,56,2,0,2,59,2,58,6,54,2,0,2,51,2,52,2,0,2,51,2,52,2,0,2,54,2,
56,2,0,2,58,2,59,2,0,4,56,2,0,4,49,2,0,2,52,2,51,6,47,2, -1,-1};
char YankeeDoodle[] = { // - Annimo
50,3,50,3,52,3,54,3,50,3,54,3,52,3,45,3,50,3,50,3,52,3,54,3,50,6,49,3,0,3,
50,3,50,3,52,3,54,3,55,3,54,3,52,3,50,3,49,3,45,3,47,3,49,3,50,6,50,3,0,3,
47,5,49,1,47,3,45,3,47,3,49,3,50,3,0,3,45,5,47,1,45,3,43,3,42,6,45,3,0,3,
47,5,49,1,47,3,45,3,47,3,49,3,50,3,47,3,45,3,50,3,49,3,52,3,50,6,50,6,-1,
-1};
char MarchaFuneralDeLasMarionetas[] = { // Gounod
37,1,0,2,30,1,0,5,42,3,42,3,41,3,39,3,41,3,0,3,42,3,44,3,0,3,37,1,0,2,
30,1,0,5,42,3,42,3,41,3,39,3,41,3,0,3,42,3,44,3,0,3,37,3,42,3,0,3,45,3,
49,6,47,3,45,3,0,3,49,3,52,6,50,3,49,3,0,3,53,3,56,6,54,3,53,3,50,3,
49,3,47,3,45,3,44,3,30,1,0,5,42,3,42,3,41,3,39,3,41,3,0,3,42,3,44,3,
0,3,37,1,0,2,30,1,0,5,42,3,42,3,41,3,39,3,41,3,0,3,42,3,44,3,0,3,
37,3,45,3,0,3,49,3,52,6,50,3,49,3,47,3,45,3,43,3,47,3,50,3,42,3,
41,3,42,3,44,3,0,3,45,1,0,2,44,9,42,1, -1,-1};
char StarsAndStripesForever[] = { //Sousa
54,6,54,6,52,3,51,3,51,6,50,3,51,3,51,16,0,2,50,3,
51,3,51,6,50,3,51,3,54,6,51,3,54,3,52,12,49,6,0,3,49,3,49,6,48,3,49,3,
49,6,48,3,49,3,52,16,0,2,51,3,49,3,51,3,54,9,56,9,56,3,49,16,0,2,54,6,
54,6,52,3,51,3,51,6,50,3,51,3,51,16,0,2,50,3,51,3,51,6,50,3 ,51,3,
52,3,51,3,49,5,46,1,49,12,47,6,0,3,47,3,47,6,46,3,47,3,50,6,49,3,47,3,
59,15,0,3,47,3,49,3,51,3,54,1,0,2,47,3,49,3,51,3,54,1,0,2,42,3,44,5,
51,1,49,12,47,1, -1,-1};
char PopularMejicana[] = { //Anonimo
52,2,57,2,0,2,52,2,57,2,0,2,52,2,57,6,0,4,52,2,57,2,59,2,57,2,56,4,
57,2,59,2,0,8,52,2,56,2,0,2,52,2,56,2,0,2,52,2,56,6,0,4,52,2,
56,2,57,2,56,2,54,4,56,2,57,2,0,6,64,2,63,2,64,2,61,2,60,2,61,2,
57,2,56,2,57,2,52,2,0,4,49,2,50,2,52,2,54,2,56,2,57,2,59,2,61,2,
62,2,59,2,0,4,62,2,61,2,62,2,59,2,58,2,59,2,56,2,55,2,56,2,52,2,
0,4,64,2,63,2,64,2,66,2,64,2,62,2,61,2,59,2,57,2, -1,-1};

78

char Sakura[] = {// Melodia folclorica japonesa


49,8, 49,8, 51,12, 0,4, 49,8, 49,8, 51,12, 0,4,
49,8,51,8,52,8,51,8, 49,8,51,4,49,4,45,16,44,8,40,8,44,8,45,8,
44,8,44,4,40,4,39,16,49,8,49,8,51,12,0,4,49,8,49,8,51,12,0,4,
40,8,44,8,45,8,49,8,51,4,49,4,45,8,44,16, -1,-1 };
char Escalas[]={ 38,1,39,1,40,1,41,1,42,1,43,1,44,1,45,1,46,1,47,1,
48,1,49,1,50,1,51,1,52,1,53,1,54,1,55,1,56,1,57,1,58,1,59,1,60,1,
61,1,62,1,63,1,64,1,65,1,66,1,67,1,68,1,0,4,68,1,67,1,66,1,65,1,64,1,
63,1,62,1,61,1,60,1,59,1,58,1,57,1,56,1,55,1,54,1,53,1,52,1,51,1,
50,1,49,1,48,1,47,1,46,1,45,1,44,1,43,1,42,1,41,1,40,1,39,1,38,8,-1,-1};
for (int i=0; i<=6; i++){
Nota[i]= 32767;
}
for (i=7; i<88; i++){
Nota[i] = 36.8*pow( pow(2, (float)1/12), i-6 ) ;
}
clrscr();
cout<< "
MODOS ESTANDARD DE TEXTO
\n";
cout <<
"Constante Valor Modo de Texto
\n";
cout << "\n";
cout << " LASTMODE -1 Modo de texto previo
\n";
cout << " BW40
0 Blanco y negro
40 columnas\n";
cout << " C40
1 Color
40 columnas\n";
cout << " BW80
2 Blanco y Negro
80 columnas\n";
cout << " C80
3 Color
80 columnas\n";
cout << " MONO
7 Monocromo
80 columnas\n";
cout << " C4350
64 EGA
43-lineas \n";
cout << "

VGA
50-lineas \n";
cout << "\nNOTA: Para un tipo dado de monitor de video no todos
funcionarn como se espera\n";
cout <<"Ensaye cada uno para su monitor de video, y determine los que ""le
sirven""\n";
cout<<"\n\nDigite Valor del modo de texto deseado: ";
cin >> ModoVideo;
textmode(ModoVideo);
Escribir.window(1,1,80,25); textbackground(BLUE); Escribir.clrscr();
textcolor(MAGENTA);
gotoxy(12,5); Escribir << "PROGRAMA";
gotoxy(12,7); Escribir << "DEMOSTRACION";
textcolor(LIGHTGREEN); gotoxy(9,10); Escribir<<(char)213;
for(i=1; i<=21; i++)
Escribir << (char)205;
Escribir<<(char)184;
gotoxy(9,11);Escribir<<(char)179<<"
gotoxy(9,12);Escribir<<(char)179;

TECLADO

"<<(char)179;

MUSICAL

"<<(char)179;

for(i=1; i<=21; i++)


Escribir << (char)32;
Escribir<<(char)179;
gotoxy(9,13);Escribir<<(char)179<<"

79

gotoxy(9,14);Escribir<<(char)212;
for(i=1; i<=21; i++)
Escribir << (char)205;
Escribir<<(char)190;
textcolor(YELLOW); gotoxy(7,23);
Escribir << "CUALQUIER TECLA PARA SEGUIR";
getch();
textcolor(WHITE); Escribir.clrscr();
gotoxy(3,15);Escribir << "------------ CANCIONES -------------";
gotoxy(3,16);Escribir << "A-Marcha
E-Humoresca
I-Japonesa";
gotoxy(3,17);Escribir << "B-Stars
F-La Cucaracha J-Pop
";
gotoxy(3,18);Escribir << "C-Mozart
G-Danubio Azul K-Escalas ";
gotoxy(3,19);Escribir << "D-Mejicana H-Dandy
ESC- Salir";
textcolor(WHITE); textbackground(BLACK);
for( I=0; I<=17; I++)
// Dibuja teclas blancas
for(J=0; J<=8; J++){
gotoxy(2+I*2,5+J); Escribir << (char)219<<(char)221;
}
for( I=0; I<=15; I++)
//Dibuja teclas negras
for( J=0; J<=4; J++){
if( I==2 || I==6 || I==9 || I==13 )
continue;
gotoxy(5+I*2, 5+J);
Escribir<< (char)32<<(char)222;
}
for( J=0; J<=9; J++){ //Dibuja el borde del teclado
gotoxy(1,4+J); textcolor(RED); textbackground(BLACK);
Escribir <<(char)221;
gotoxy(37, 4+J); textcolor(WHITE); Escribir <<(char)221;
textcolor(RED); textbackground(BLUE);Escribir << (char)221;
}
textcolor(RED); textbackground(BLUE); gotoxy(1,4);
for( I=0; I<=36; I++)
Escribir<< (char)219;
Escribir<< (char)(221); gotoxy(1, 13);
for( I=0;I<=36;I++)
Escribir<< (char)219;;
Escribir<< (char)(221);
for(;;){
textcolor(MAGENTA); textbackground(LIGHTGRAY);
gotoxy(2,21); Escribir<< "
gotoxy(2,21); Escribir<<"Digite letra ====>";

";

switch( opcion=toupper( getch() ) ){


case 'A': Escribir<<"Marcha";
p=MarchaFuneralDeLasMarionetas;
break;

80

case
case
case
case
case
case
case
case
case
case
case

'B': Escribir<<"Stars";
p=StarsAndStripesForever;
break;
'C': Escribir<<"Cuarenta";
p=Sinfonia40;
break;
'D': Escribir<<"Mejicana";
p=PopularMejicana;
break;
'E': Escribir<<"Humoresca";
p=Humoresque;
break;
'F': Escribir<<"La Cucaracha";
p=LaCucaracha;
break;
'G': Escribir<<"Azul";
p=ElDanubioAzul;
break;
'H': Escribir<<"Dandy ";
p=YankeeDoodle;
break;
'I': Escribir<<"Sakura";
p=Sakura;
break;
'J': Escribir<<"Pop";
p=PopGoesTheWeasle;
break;
'K': Escribir<<"Escalas ";
p=Escalas;
break;
27: return;

}
_setcursortype(_NOCURSOR);
if(opcion>='A' && opcion<='K'){
while(*p!=-1 && !kbhit()){
J=*p;
K=*(p+1);
int Q = Tecla[J]-3;
if( J>=39 && J<=68 ){
gettext(Q,5,Q,5, C);
if (C[0]!=32){
textcolor(BLACK);
textbackground(LIGHTGRAY);
gotoxy(Q,11); Escribir<<(char)14;
textcolor(WHITE); textbackground(BLACK);
}
else{
textcolor(WHITE); textbackground(BLACK);
gotoxy(Q,7); Escribir<< (char)14;
textcolor(BLACK);
textbackground(LIGHTGRAY);
}
}
sound(Nota[J]);
delay(K*tempo);

81

if(! (J==0 && K==1) ){


sound(32767);
delay(tempo);
}
if(J>=39 && J<=68) {
gettext(Q,5,Q,5, C);
textcolor(WHITE); textbackground(BLACK);
if (C[0]==32){
gotoxy(Q,7); Escribir<<(char)32;
}
else{
gotoxy(Q,11); Escribir<< (char)219;
}
}
p = p+2;
}
}
_setcursortype(_SOLIDCURSOR);
}
}

82

VECTOR DE PUNTEROS A FUNCIN


1. El siguiente programa es un ejemplo de la declaracin de un vector de
punteros a funciones.
//PilaVect.cpp
#include
#include
#include
#include

<graphics.h>
<conio.h>
<stdlib.h>
<dos.h>

//Definicin de algunas constantes ("por facilidad")


const int AltoIcono=50, AnchoIcono=50, MaxIco=36;
//Declaracin de prototipos de funciones:
void Cursor(int X,int Y,char *Cad,int Color,int pos, int Oprimido);
void MarcoVentana(int x1, int y1, int x2, int y2,
int ColorArribaIzquierda, int ColorAbajoDerecha);
void Icono1(int x, int y); void Icono2(int x, int y);
void Icono3(int x, int y); void Icono4(int X, int Y);
void Icono5(int x, int y); void Icono6(int x, int y);
void Icono7(int x, int y); void Icono8(int x, int y);
void Icono9(int x, int y); void Icono10(int x, int y);
void Icono11(int x, int y); void Icono12(int x, int y);
void Icono13(int x, int y); void Icono14(int x, int y);
void Icono15(int x, int y); void Icono16(int x, int y);
void Icono17(int x, int y); void Icono18(int x, int y);
void Icono19(int x, int y); void Icono20(int x, int y);
void Icono21(int x, int y); void Icono22(int x, int y);
void Icono23(int x, int y); void Icono24(int x, int y);
void Icono25(int x, int y); void Icono26(int x, int y);
void Icono27(int x, int y); void Icono28(int x, int y);
void Icono29(int x, int y); void Icono30(int x, int y);
void Icono31(int x, int y); void Icono32(int x, int y);
void Icono33(int x, int y); void Icono34(int x, int y);
void Icono35(int x, int y); void Icono36(int x, int y);
//Definicin de arreglo de punteros a funciones:
void (*Icono[MaxIco])(int, int) =
{Icono1,Icono2,Icono3,Icono4,Icono5,Icono6,Icono7,Icono8,Icono9,Icono10,
Icono11,Icono12,Icono13,Icono14,Icono15,Icono16,Icono17,Icono18,Icono19,
Icono20,Icono21,Icono22,Icono23,Icono24,Icono25,Icono26,Icono27,Icono28,
Icono29,Icono30,Icono31,Icono32,Icono33,Icono34,Icono35,Icono36};
//Funciones del programa:
void Icono1(int x, int y){
setcolor(BLUE);
setfillstyle(1,DARKGRAY);
fillellipse(x+25,y+10,7,7);
bar3d(x+17,y+20,x+32,y+46, 1, 0);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA); outtextxy(x+AnchoIcono/2, y+AltoIcono, "Informar");
}
void Icono2(int x, int y){
setcolor(WHITE); setfillstyle(1,LIGHTGRAY);
bar3d(x+10,y+25,x+30,y+30,12,2);

83

setfillstyle(1,BLUE);
bar3d(x+15,y+10,x+30,y+22,7,1);
line(x+22,y+27,x+27,y+27); line(x+10,y+33,x+30,y+33);
line(x+6,y+38,x+26,y+38);
line(x+10,y+33,x+6,y+38); line(x+30,y+33,x+26,y+38);
line(x+27,y+30,x+25,y+33);
setcolor(RED);line(x+26,y+29,x+28,y+29);
setcolor(LIGHTGRAY);line(x+31,y+16,x+36,y+16);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono, "Computo");
}
void Icono3(int x, int y){
setcolor(DARKGRAY); setfillstyle(1,LIGHTMAGENTA);
fillellipse(x+25, y+10, 5, 5);
bar(x+15,y+22,x+35,y+30);
setfillstyle(1,WHITE); bar(x+15, y+16, x+35, y+21);
setfillstyle(1,BLUE);
bar(x+20, y+20, x+30, y+45);
setfillstyle(1,RED);
bar(x+19, y+46, x+31, y+48);
setcolor(DARKGRAY);
line(x+25,y+30, x+25,y+48); line(x+20,y+10, x+32,y+10);
setcolor(BLUE);
line(x+22,y+15, x+22,y+20); line(x+29,y+15, x+29,y+20);
setcolor(LIGHTGRAY);
line(x+18,y+14, x+11,y+19);
line(133,364,137,369);
setfillstyle(1,GREEN); setcolor(DARKGRAY);
bar3d(x+31,y+31, x+36,y+36,3,0);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Personal");
}
void Icono4(int x, int y){
setcolor(WHITE); line(x+30,y+10,x+10,y+30); line(x+10,y+30, x+20,y+40);
line(x+20,y+40, x+40,y+20); line(x+40,y+20, x+30,y+10);
line(x+10,y+30, x+10,y+35); line(x+10,y+35, x+20,y+45);
line(x+20,y+40, x+20,y+45); line(x+20,y+45, x+40,y+25);
line(x+40,y+25, x+40,y+20); line(x+12,y+28,x+7,y+23);
line(x+7,y+23, x+20,y+10); line(x+20,y+10, x+25,y+15);
line(x+22,y+12, x+24,y+10); line(x+24,y+10, x+27,y+13);
setcolor(DARKGRAY);
line(x+38,y+29, x+26,y+41);
line(x+39,y+30,x+27,y+42);
line(x+40,y+31, x+28,y+43); line(x+41,y+32, x+29,y+44);
setcolor(BLUE); line(x+20,y+14, x+11,y+23); line(x+20,y+16, x+12,y+24);
setcolor(RED); line(x+35,y+20, x+32,y+23);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Impresin");
}
void Icono5(int x, int y){
setcolor(DARKGRAY); setfillstyle(1,YELLOW); fillellipse(x+10, y+10, 8, 8);
line(x+10,y+7,x+10,y+11); line(x+12,y+10,x+6,y+10);
line(x+10,y+5,x+10,y+3);
setcolor(WHITE); line(x+10,y+25,x+30,y+5); line(x+30,y+5,x+40,y+15);
line(x+40,y+15,x+20,y+35);
line(x+10,y+25,x+25,y+20);
line(x+25,y+20,x+30,y+5);
line(x+40,y+15,x+27,y+13);
setcolor(RED); line(x+29,y+19,x+33,y+15);
line(x+30,y+20,x+34,y+16);line(x+31,y+21,x+35,y+17);
setcolor(DARKGRAY);
line(x+5,y+30,x+18,y+22);
line(x+18,y+22,x+22,y+30); line(x+22,y+30,x+17,y+34);

84

setfillstyle(1,LIGHTGREEN); bar3d(x+5,y+30,x+20,y+47,1,0);
setfillstyle(1,WHITE); bar3d(x+7,y+32,x+18,y+35,1,0);
circle(x+29,y+35,3); circle(x+36,y+35,3);
line(x+27,y+35,x+35,y+28);
line(x+38,y+36,x+44,y+28);
line(x+35,y+28,x+35,y+31); line(x+44,y+28,x+44,y+31);
setfillstyle(1,YELLOW); bar3d(x+45,y+10,x+47,y+28,1,0);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Gerencia");
}
void Icono6(int x, int y){
setcolor(RED); setfillstyle(1,WHITE); bar3d(x+20,y+5,x+40,y+30,1,0);
bar3d(x+15,y+10,x+35,y+35,1,0); bar3d(x+10,y+15,x+30,y+40,1,0);
line(x+12,y+20,x+28,y+20); line(x+12,y+25,x+28,y+25);
line(x+12,y+30,x+28,y+30);line(x+12,y+35,x+28,y+35);
line(x+12,y+40,x+28,y+40);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Listados");
}
void Icono7(int x, int y){
setfillstyle(1, DARKGRAY);
bar(x+10,y+10,x+40,y+40);
setfillstyle(1, YELLOW);
bar(x+15,y+25,x+35,y+39);
setcolor(WHITE);line(x+12,y+37,x+12,y+39);line(x+38,y+37,x+38,y+39);
line(x+15,y+10,x+15,y+20); line(x+15,y+20,x+35,y+20);
setfillstyle(1,WHITE); bar(x+20,y+10,x+35,y+20);
setfillstyle(1,DARKGRAY);
bar(x+18,y+11,x+32,y+19);
setcolor(LIGHTGRAY);line(x+38,y+17,x+42,y+13);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Archivos");
}
void Icono8(int x, int y){
setfillstyle(1,YELLOW); bar3d(x+5,y+15,x+30,y+45,10,1);
bar3d(x+7,y+17,x+27,y+28,1,0); bar3d(x+7,y+32,x+27,y+43,1,0);
setcolor(DARKGRAY);
line(x+13,y+24,x+22,y+24);
line(x+13,y+37,x+22,y+37);
line(x+13,y+23,x+13,y+24); line(x+22,y+23,x+22,y+24);
line(x+13,y+36,x+13,y+37); line(x+22,y+36,x+22,y+37);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Almacen");
}
void Icono9(int x, int y){
setcolor(DARKGRAY);
arc(x+10,y+10,630,370,20);
line(x+30,y+5,x+10,y+30); line (x+25,y+10,x+15,y+10);
line(x+15,y+10,x+15,y+22); line (x+20,y+15,x+12,y+7);
line(x+20,y+27,x+20,y+40); line(x+28,y+19,x+35,y+40);
fillellipse(x+12,y+7,1,1);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Par bola");
}
void Icono10(int x, int y){

85

setcolor(RED); line(x+11,y+18,x+10,y+20); line(x+14,y+18,x+15,y+20);


line(x+10,y+20,x+10,y+25); line(x+15,y+20,x+15,y+25);
line(x+15,y+25,x+10,y+30); line(x+10,y+25,x+15,y+30);
setfillstyle(1,RED); bar(x+9,y+30,x+10,y+45); bar(x+15,y+30,x+16,y+45);
setcolor(DARKGRAY);
line(x+20,y+5,x+22,y+5);
moveto(x+22,y+5); lineto(x+25,y+8); lineto(x+25,y+10); lineto(x+40,y+25);
lineto(x+42,y+25); lineto(x+45,y+28); lineto(x+45,y+30);
lineto(x+42,y+27);
lineto(x+40,y+30); lineto(x+43,y+33); lineto(x+40,y+33);
lineto(x+37,y+30);
lineto(x+37,y+27); lineto(x+23,y+13);
lineto(x+20,y+13);
lineto(x+17,y+10);
lineto(x+17,y+7); lineto(x+20,y+10); lineto(x+22,y+8);
line(x+21,y+8,x+20,y+5); setfillstyle(1,DARKGRAY);
setcolor(WHITE);
bar3d(x+22,y+32,x+32,y+35,1,0);bar3d(x+25,y+35,x+29,y+45,1,0);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Taller");
}
void Icono11(int x,int y){
static char diamante[] = {20,21, 20,22, 20,23, 19,24, 19,25, 19,26, 18,27,
18,28, 17,29, 16,30, 15,31, 15,32, 14,33, 13,34, 12,35, 11,35, 11,36, 12,36,
13,37, 14,38, 15,39, 15,40, 16,41, 17,42, 18,43, 18,44, 19,45, 19,46, 19,47,
20,48, 20,49, 20,50, 21,50, 21,49, 21,48, 22,47, 22,46, 22,45, 23,44, 23,43,
24,42, 25,41, 26,40, 26,39, 27,38, 28,37, 29,36, 30,36, 30,35, 29,35, 28,34,
27,33, 26,32, 26,31, 25,30, 24,29, 23,28, 23,27, 22,26, 22,25, 22,24, 21,23,
21,22, 21,21 };
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Diamante");
x+=5; y-=10;
for(i=0; i<sizeof(diamante); i+=2)
putpixel(x+diamante[i], y+diamante[i+1], RED);
setfillstyle(SOLID_FILL, RED);

floodfill(x+20, y+30, RED);

}
void Icono12(int x, int y){
static char pica[] = {20,21,
15,28, 15,29, 14,30, 13,31, 13,32,
11,39, 12,40, 13,41, 14,42, 15,42,
19,44, 19,45, 18,46, 18,47, 17,48,
23,49, 24,49, 24,48, 23,47, 23,46,
24,42, 25,42, 26,42, 27,42, 28,41,
30,34, 29,33, 28,32, 28,31, 27,30,
22,23, 21,22,21,21};
int i;

20,22,
12,33,
16,42,
17,49,
22,45,
29,40,
26,29,

19,23,
11,34,
17,42,
18,49,
22,44,
30,39,
26,28,

18,24,
11,35,
18,42,
19,49,
21,43,
30,38,
25,27,

17,25,
11,36,
19,41,
20,49,
21,42,
30,37,
24,26,

17,26,
11,37,
20,42,
21,49,
22,41,
30,36,
24,25,

16,27,
11,38,
20,43,
22,49,
23,42,
30,35,
23,24,

settextstyle(SMALL_FONT, HORIZ_DIR, 4);


settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Pica");
x+=5; y-=10;
for(i=0; i<sizeof(pica); i+=2)
putpixel(x+pica[i], y+pica[i+1], DARKGRAY);

86

setfillstyle(SOLID_FILL, DARKGRAY);
floodfill(x+20, y+30, DARKGRAY);
floodfill(x+20, y+46, DARKGRAY);
}
void Icono13(int x,int y){
static char corazon[]={20,25, 19,24, 19,23, 19,22, 18,21, 17,21, 16,21,
15,21, 14,21, 13,22, 12,23, 12,24, 11,25, 11,26, 11,27, 11,28, 11,29, 11,30,
11,31, 12,32, 12,33, 13,34, 13,35, 14,36, 14,37, 15,38, 16,39, 17,40, 17,41,
18,42, 18,43, 19,44, 19,45, 19,46, 20,47, 20,48, 21,48, 21,47, 22,46, 22,45,
22,44, 23,43, 23,42, 24,41, 24,40, 25,39, 26,38, 27,37, 27,36, 28,35, 28,34,
29,33, 29,32, 30,31, 30,30, 30,29, 30,28, 30,27, 30,26, 30,25, 29,24, 29,23,
28,22, 27,21, 26,21, 25,21, 24,21, 23,21, 22,22, 22,23, 22,24, 21,25};
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Corazn");
x+=5; y-=10;
for(i=0; i<sizeof(corazon); i+=2)
//
putpixel(x+corazon[i], y+corazon[i+1], RED);
setfillstyle(SOLID_FILL, RED);

floodfill(x+20, y+30, RED);

}
void Icono14(int x,int y){
static char trebol[] ={20,21, 19,21, 18,22, 17,23, 16,24, 16,25, 16,26,
17,27, 17,28, 18,29, 19,30, 18,31, 17,31, 16,30, 15,30, 14,30, 14,31, 15,31,
16,31, 13,31, 12,32, 11,33,
11,34, 11,35, 11,36, 12,37, 12,38, 13,38, 14,39,
15,39, 16,39, 17,39, 18,38,
18,37, 19,36, 20,37, 20,38, 20,39, 20,40, 19,41,
19,42, 19,43, 19,44, 18,45,
18,46, 18,47, 18,48, 17,49, 17,50, 18,50, 19,50,
20,50, 21,50, 22,50, 23,50, 24,50, 24,49, 23,48, 23,47, 23,46, 23,45,
22,44,
22,43, 22,42, 22,41, 21,40, 21,39, 21,38, 21,37, 22,36, 23,37, 23,38,
24,39,
25,39, 26,39, 27,39, 28,38, 29,38, 29,37, 30,36, 30,35, 30,34, 30,33,
29,32,
28,31, 27,30, 26,30, 25,30, 25,31, 26,31, 27,31, 24,31, 23,31, 22,30,
23,29,
24,28,24,27, 25,26, 25,25, 25,24, 24,23, 23,22, 22,21, 21,21}; //98 puntos
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Trbol");
x+=5; y-=10;
for(i=0; i<sizeof(trebol); i+=2)
//
putpixel(x+trebol[i], y+trebol[i+1], DARKGRAY);
setfillstyle(SOLID_FILL, DARKGRAY);
floodfill(x+20, y+30, DARKGRAY);
floodfill(x+20, y+45, DARKGRAY);
}
void Icono15(int x, int y){
static char uva[]={ 37,25, 38,25, 39,25,
39,26, 40,26, 41,26, 37,27, 38,27, 39,27,
39,28, 40,28, 41,28, 42,28, 43,28, 44,28,
39,29, 40,29, 41,29, 47,29, 37,30, 38,30,
37,31, 38,31, 39,31, 40,31, 41,31, 47,31,
41,32, 42,32, 43,32, 44,32, 45,32, 46,32,
41,33, 37,34, 38,34, 39,34, 40,34, 41,34,
41,35 };
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);

40,25,
40,27,
45,28,
39,30,
37,32,
37,33,
37,35,

41,25,
41,27,
46,28,
40,30,
38,32,
38,33,
38,35,

37,26,
37,28,
37,29,
41,30,
39,32,
39,33,
39,35,

38,26,
38,28,
38,29,
48,30,
40,32,
40,33,
40,35,

87

setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Uva");
x-=15; y-=25;
setcolor(MAGENTA);
circle(x+28,y+40,6);circle(x+40,y+40,6);circle(x+52,y+40,6);
circle(x+34,y+50,6);circle(x+46,y+50,6);circle(x+40,y+60,6);
setfillstyle(SOLID_FILL, MAGENTA); floodfill(x+29, y+39,MAGENTA);
floodfill(x+41, y+39, MAGENTA);
floodfill(x+53, y+39, MAGENTA);
floodfill(x+35, y+49, MAGENTA);
floodfill(x+47, y+49, MAGENTA);
floodfill(x+41, y+59, MAGENTA);
int i;
for(i=0; i<sizeof(uva); i+=2)
putpixel(x+uva[i]+12, y+uva[i+1]+20, BROWN);
}
void Icono16(int x, int y){
static char manzana[] = {16,16, 17,16, 18,16, 19,16, 20,16, 21,16, 22,16,
36,16, 37,16, 38,16, 39,16, 40,16, 41,16, 42,16, 15,17, 23,17, 35,17,
43,17, 14,18, 24,18, 34,18, 44,18, 13,19, 25,19, 33,19, 45,19, 12,20,
26,20, 32,20, 46,20, 11,21, 27,21, 31,21, 47,21, 10,22, 28,22, 30,22,
48,22, 10,23, 29,23, 49,23, 10,24, 50,24, 9,25, 50,25, 8,26, 50,26,
8,27, 50,27, 8,28, 50,28, 8,29, 50,29, 8,30, 50,30, 8,31, 50,31,
8,32, 50,32, 8,33, 50,33, 8,34, 50,34, 8,35, 50,35, 8,36, 50,36,
8,37, 50,37, 8,38, 50,38, 9,39, 49,39, 10,40, 48,40, 10,41, 48,41,
10,42, 48,42, 11,43, 47,43, 12,44, 46,44, 13,45, 45,45, 14,46, 44,46,
15,47, 43,47, 16,48, 42,48, 17,49, 41,49, 18,50, 19,50, 20,50, 21,50,
22,50, 23,50, 24,50, 25,50, 26,50, 27,50, 28,50, 29,50, 30,50, 31,50,
32,50, 33,50, 34,50, 35,50, 36,50, 37,50, 38,50, 39,50, 40,50
};
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Manzana");
x-=15; y-=25;
for(i=0; i<sizeof(manzana); i+=2)
putpixel(x+manzana[i]+12, y+manzana[i+1]+20, LIGHTRED);
setfillstyle(SOLID_FILL, RED);
floodfill(x+41, y+52, LIGHTRED);
static char palo[] = { 28, 8, 29, 8, 30, 8, 28, 9, 30, 9, 24,10, 25,10,
26,10, 27,10, 28,10, 30,10, 31,10, 32,10, 33,10, 34,10, 23,11, 35,11,
36,12, 23,13, 35,13, 24,14, 25,14, 26,14, 27,14, 28,14, 30,14, 31,14,
33,14, 34,14, 28,15, 30,15, 28,16, 30,16, 28,17, 30,17, 28,18,
28,19, 30,19, 28,20, 30,20, 28,21, 30,21, 29,22 };
for(i=0; i<sizeof(palo); i+=2)
//45*2 = 90
putpixel(x+palo[i]+12, y+palo[i+1]+20, GREEN);
setfillstyle(SOLID_FILL, GREEN);
floodfill(x+42, y+31, GREEN);

26,10,
22,12,
32,14,
30,18,

}
void Icono17(int x, int y){
static char naranja[]={ 37,25, 38,25, 39,25, 40,25, 41,25, 37,26, 38,26,
39,26, 40,26, 41,26, 37,27, 38,27, 39,27, 40,27, 41,27, 37,28, 38,28,
39,28, 40,28, 41,28, 42,28, 43,28, 44,28, 45,28, 46,28, 37,29, 38,29,
39,29, 40,29, 41,29, 47,29, 37,30, 38,30, 39,30, 40,30, 41,30, 48,30,
37,31, 38,31, 39,31, 40,31, 41,31, 47,31, 37,32, 38,32, 39,32, 40,32,
41,32, 42,32, 43,32, 44,32, 45,32, 46,32, 37,33, 38,33, 39,33, 40,33,
41,33, 37,34, 38,34, 39,34, 40,34, 41,34, 37,35, 38,35, 39,35, 40,35,
41,35 };
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);

88

settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Naranja");
x-=15; y-=20;
setcolor(YELLOW); circle(x+39,y+50,14);
for(i=0; i<sizeof(naranja); i+=2)
putpixel(x+naranja[i], y+naranja[i+1], GREEN);
setfillstyle(SOLID_FILL, GREEN);
floodfill(x+45, y+30, GREEN);
setfillstyle(SOLID_FILL, YELLOW);
floodfill(x+40, y+51, YELLOW);
}
void Icono18(int x, int y){
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Banano");
x-=10; y-=20;
setcolor(YELLOW); setfillstyle(SOLID_FILL,YELLOW);
fillellipse(x+38,y+45,20,20);
setcolor(LIGHTGRAY);
setfillstyle(SOLID_FILL,LIGHTGRAY);
fillellipse(x+30,y+41,18,18);
setcolor(DARKGRAY);
setfillstyle(SOLID_FILL,DARKGRAY);
fillellipse(x+24,y+60,2,2);
fillellipse(x+41,y+26,2,2);
}
void Icono19(int x, int y){
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 5);
settextjustify(CENTER_TEXT, CENTER_TEXT);
setcolor(YELLOW); outtextxy(x+25, y+20,"");
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"");
}
void Icono20(int x, int y){
static char cereza[] = {
42,25, 43,25, 42,26, 43,26, 42,27, 43,27,
42,28, 43,28, 42,29, 43,29, 42,30, 43,30, 42,31, 43,31, 42,32,
43,32, 42,33, 43,33, 42,34, 43,34, 42,35, 43,35, 42,36, 43,36,
42,37, 43,37, 42,38, 43,38, 42,39, 43,39, 42,40, 43,40, 42,41,
43,41, 42,42, 43,42, 42,43, 43,43, 42,44, 43,44, 42,45, 43,45,
42,46, 43,46, 42,47, 43,47, 42,48, 43,48, 42,49, 43,49, 42,50,
43,50, 42,51, 43,51, 42,52, 43,52, 33,37, 34,37, 34,36, 35,36,
35,35, 36,35, 36,34, 37,34, 37,33, 38,33, 38,32, 39,32, 39,31,
40,31, 40,30, 41,30, 41,29, 42,29, 43,29, 44,29, 45,29, 45,30,
46,30, 46,31, 47,31, 47,32, 48,32, 48,33, 49,33, 49,34, 50,34,
50,35, 51,35, 51,36, 52,36, 52,37, 53,38};
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Cereza");
x-=15; y-=20;
setcolor(LIGHTRED);
circle(x+30,y+45,5);
circle(x+50,y+45,5);
circle(x+40,y+60,5);
setfillstyle(SOLID_FILL,LIGHTRED); floodfill(x+31, y+44, LIGHTRED);
floodfill(x+51, y+44, LIGHTRED);floodfill(x+41, y+59, LIGHTRED);
for(int i=0; i<sizeof(cereza); i+=2)
putpixel(x+cereza[i]-3, y+cereza[i+1]+2, DARKGRAY);
}
void Icono21(int x, int y){
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);

89

setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Moneda");
setfillstyle(SOLID_FILL, YELLOW);
setcolor(YELLOW); circle(x+25,y+25,15);
floodfill(x+25, y+25,YELLOW);
setcolor(BLACK); circle(x+25, y+25,13);
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 1);
settextjustify(CENTER_TEXT, CENTER_TEXT); outtextxy(x+25, y+25,"$");
}
void Icono22(int x, int y){
static char fresa[] =
31,16, 32,16, 33,16,
22,18, 40,18, 21,19,
18,23, 44,23, 18,24,
27,25, 37,25, 39,25,
46,26, 18,27, 21,27,
30,28, 34,28, 42,28,
32,30, 46,30, 18,31,
38,34, 46,34, 19,35,
34,38, 44,38, 20,39,
42,42, 22,43, 42,43,
25,47, 39,47, 26,48,
30,52, 31,52, 32,52,
int i;

{
24,16, 25,16, 26,16, 27,16, 28,16, 29,16, 30,16,
34,16, 35,16, 36,16, 37,16, 38,16, 23,17, 39,17,
41,19, 20,20, 42,20, 19,21, 43,21, 18,22, 44,22,
24,24, 25,24, 26,24, 38,24, 44,24, 18,25, 23,25,
45,25, 18,26, 22,26, 28,26, 36,26, 40,26, 44,26,
29,27, 35,27, 41,27, 43,27, 46,27, 18,28, 20,28,
46,28, 18,29, 19,29, 31,29, 33,29, 46,29, 18,30,
46,31, 18,32, 22,32, 46,32, 18,33, 46,33, 18,34,
45,35, 20,36, 26,36, 44,36, 20,37, 44,37, 20,38,
44,39, 20,40, 44,40, 21,41, 43,41, 22,42, 30,42,
22,44, 42,44, 23,45, 41,45, 24,46, 34,46, 40,46,
38,48, 27,49, 38,49, 28,50, 38,50, 29,51, 37,51,
33,52, 34,52, 35,52, 36,52
};//138 puntos

settextstyle(SMALL_FONT, HORIZ_DIR, 4);


settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Fresa");
x-=15; y-=18;
for(i=0; i<sizeof(fresa); i+=2)
putpixel(x+fresa[i]+9, y+fresa[i+1]+12, LIGHTRED);
setfillstyle(SOLID_FILL, RED);
floodfill(x+30, y+40, LIGHTRED);
floodfill(x+41, y+33, LIGHTRED);
static char palo[] = {
30,10, 31,10, 32,10, 30,11, 32,11, 30,12, 32,12,
30,13, 32,13, 30,14, 32,14, 30,15, 31,15, 32,15, 24,24, 25,24, 26,24,
38,24, 23,25, 27,25, 37,25, 39,25, 22,26, 28,26, 36,26, 40,26, 44,26,
21,27, 29,27, 35,27, 41,27, 43,27, 20,28, 30,28, 34,28, 42,28, 19,29,
31,29, 33,29, 24,30, 32,30, 38,34, 26,36, 34,38, 30,42, 34,46 };
for(i=0; i<sizeof(palo); i+=2)
//46*2 = 92
putpixel(x+palo[i]+9, y+palo[i+1]+12, GREEN);
setfillstyle(SOLID_FILL, GREEN);
floodfill(x+40, y+25,GREEN);
}
void Icono23(int x, int y){
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
setcolor(MAGENTA); settextjustify(CENTER_TEXT, TOP_TEXT);
outtextxy(x+AnchoIcono/2, y+AltoIcono,"Cereza");
y-=10; x+=5;
setcolor(RED); setfillstyle(SOLID_FILL, RED);
circle(x+26,y+40,4);
circle(x+20,y+45,4);
circle(x+13,y+40,4);

floodfill(x+26, y+40, RED);


floodfill(x+20, y+45, RED);
floodfill(x+13, y+40, RED);

static char cereza[]={30,15, 29,16, 28,16, 28,17, 27,17, 27,18, 26,19,


26,20, 25,21, 25,22, 24,23, 24,24, 23,25, 23,26, 22,27, 22,28,
21,29, 21,30, 20,31, 20,32, 20,33, 20,34, 20,35, 20,36,

90

20,37, 20,38, 20,39, 20,40, 19,32, 18,33, 17,34, 16,35,


15,36, 14,37, 21,32, 22,33, 23,34, 24,35, 25,36, 26,37

};

for(int i=0; i<80; i+=2)


//40*2 = 80
putpixel(x+cereza[i], y+cereza[i+1], GREEN);
setfillstyle(SOLID_FILL, GREEN);
floodfill(x+17, y+27, GREEN);

fillellipse(x+18,y+27,3,2);

}
void Icono24(int x, int y){
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Naranja");
y-=10; x+=5;
setcolor(LIGHTRED);
setfillstyle(SOLID_FILL,YELLOW);
circle(x+20,y+40,10);
floodfill(x+20,y+40, LIGHTRED);
static char naranja []={30,15, 29,16, 28,16, 28,17, 27,17, 27,18, 26,19,
26,20,25,21,25,22,24,23,24,24,23,25,23,26,22,27,22,28,21,29,21,30, 20,31};
for(int i=0; i<38; i+=2)
putpixel(x+naranja[i], y+naranja[i+1], GREEN);
setfillstyle(SOLID_FILL, GREEN);
fillellipse(x+17,y+23,6,3);
floodfill(x+17, y+23, GREEN);
}
void Icono25(int x, int y){ // Arriba
int Color=DARKGRAY;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Arriba");
y-=10; x+=5; setcolor(Color);
line(x+20,y+20,x+12,y+36);
line(x+12,y+36,x+18,y+36);
line(x+18,y+36,x+18,y+49);
line(x+18,y+49,x+22,y+49);
line(x+22,y+49,x+22,y+36);
line(x+22,y+36,x+28,y+36);
line(x+28,y+36,x+20,y+20);
setfillstyle(SOLID_FILL, Color);
floodfill(x+20, y+45, Color);
}
void Icono26(int x, int y){// abajo
int Color=DARKGRAY;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Abajo");
y-=10; x+=5; setcolor(Color);
line(x+18,y+20,x+22,y+20);
line(x+22,y+20,x+22,y+36);
line(x+22,y+36,x+28,y+36);
line(x+28,y+36,x+20,y+49);
line(x+20,y+49,x+12,y+36);
line(x+12,y+36,x+18,y+36);
line(x+18,y+36,x+18,y+20);
setfillstyle(SOLID_FILL, Color);
floodfill(x+20, y+45, Color);
}
void Icono27(int X, int Y){
int r = 20, x, y, color;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(X+AnchoIcono/2, Y+AltoIcono,"OVNI");

91

for( int i=0 ; i<500 ; ++i ){


x = 2 + random( 50 - 3 );
y = 2 + random( 50 - 3 );
color = random( 15 );
putpixel( X+x, Y+y, color );
}
X+=25; Y+=25;
setfillstyle( SOLID_FILL, getmaxcolor() );
fillellipse(X, Y, r, (r/3)+2);
ellipse(X, Y-4, 190, 357, r, r/3);
line(X+7, Y-6, X+10, Y-12);
fillellipse(X+10, Y-12, 2, 2);
line(X-7, Y-6, X-10, Y-12);
fillellipse(X-10, Y-12, 2, 2);
}
void Icono28(int x, int y){ //NOT
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"NOT");
setcolor(LIGHTBLUE); x+=10; y+=15;
line(x,y+5,x+5,y+5);line(x,y+15,x+5,y+15);line(x+5,y,x+5,y+20);
line(x+5,y+20,x+23,y+10);line(x+23,y+10,x+5,y);circle(x+24,y+10,2);
line(x+26,y+10,x+30,y+10);
}
void Icono29(int x, int y){ //AND
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"AND");
setcolor(CYAN); x+=10; y+=15;
line(x,y+5,x+5,y+5);line(x,y+15,x+5,y+15);line(x+5,y,x+5,y+20);
line(x+5,y+20,x+17,y+20);
line(x+5,y,x+15,y);arc(x+15,y+10,270,90,10);line(x+25,y+10,x+30,y+10);
}
void Icono30(int x, int y){ //OR
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"OR");
setcolor(BROWN); x+=10; y+=15;
line(x,y+5,x+9,y+5); line(x,y+15,x+9,y+15);
arc(x+15,y+10,270,90,10); line(x+5,y,x+15,y); line(x+5,y+20,x+15,y+20);
arc(x,y+10,300, 72.7,10);line(x+25,y+10,x+30,y+10);
}
void Icono31(int x, int y){
settextstyle(SMALL_FONT, VERT_DIR, 4);
settextjustify(CENTER_TEXT, CENTER_TEXT);
setcolor(YELLOW); outtextxy(x+20, y+25,"Vertical");
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Horizontal");
}
void Icono32(int x, int y){
static char Torre[] = {
16,5, 17,5, 18,5, 19,5, 20,5, 21,5, 22,5, 23,5, 24,5, 25,5, 26,5, 27,5,
28,5, 29,5, 30,5, 16,6, 16,7, 16,8, 16,9, 17,10, 18,11, 19,12, 19,13, 19,14,
19,15, 19,16, 19,17, 19,18, 19,19, 19,20, 19,21, 19,22, 19,23, 19,24, 19,25,

92

18,25, 17,26, 16,27, 16,28, 16,29, 16,30, 16,31, 16,32, 17,32,


20,32, 21,32, 22,32, 23,32, 24,32, 25,32, 26,32, 27,32, 28,32,
30,31, 30,30, 30,29, 30,28, 30,27, 29,26, 28,25, 27,24, 27,12,
27,15, 27,16, 27,17, 27,18, 27,19, 27,20, 27,21, 27,22, 27,23,
30,9, 29,10, 28,11, 27,12, 16,4, 16,3, 16,2, 16,1, 23,4, 23,3,
30,3, 30,2, 30,1 };

18,32, 19,32,
29,32, 30,32,
27,13, 27,14,
30,6, 30,7, 30,8,
23,2, 23,1, 30,4,

settextstyle(SMALL_FONT, HORIZ_DIR, 4);


settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Torre");
y+=10;
for(int i=0; i<sizeof(Torre); i+=2)
putpixel(x+Torre[i], y+Torre[i+1],DARKGRAY);
setfillstyle (SOLID_FILL, BLUE); floodfill (x+24,y+20,DARKGRAY);
}
void Icono33(int x, int y){
static char Peon[]={
21,11, 20,12, 19,13, 18,14, 17,15, 16,16, 16,17, 16,18, 16,19,
16,20, 17,21, 18,22, 19,23, 18,24, 17,25,
16,26, 17,27, 18,28, 19,29, 20,30, 19,31, 18,32, 17,33, 16,34,
15,35, 14,36, 14,37, 14,38, 14,39, 14,40,
15,40, 16,40, 17,40, 18,40, 19,40, 20,40, 21,40, 22,40, 23,40,
24,40, 25,40, 26,40, 27,40, 28,40, 29,40,
30,40, 31,40, 32,40, 32,39, 32,38, 32,37, 32,36, 26,35, 30,34,
29,33, 28,32, 27,31, 26,30, 27,29, 28,27,
29,27, 30,26, 29,27, 28,24, 27,23, 28,22, 29,21, 30,20, 22,11,
23,11, 24,11, 25,11, 26,12, 27,13, 28,14,
29,15, 30,16, 30,17, 30,18, 30,19, 31,35, 28,28, 30,26, 29,25};
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono," Pen");
int i;
for(i=0;i<sizeof(Peon);i+=2)
putpixel(x+Peon[i],y+Peon[i+1], DARKGRAY);
setfillstyle (SOLID_FILL, LIGHTCYAN); floodfill(x+25,y+15, DARKGRAY);
}
void Icono34(int x, int y){
static char Reina[] = { 23,7, 23,8, 23,9, 23,10, 23,11, 23,12, 23,13, 23,14,
23,15, 23,16, 23,17, 20,10, 22,10, 24,10,
25,10, 26,10, 20,16, 21,16, 22,16, 24,16, 25,16, 26,16, 21,10, 19,18,18,19,
17,20, 16,21, 16,22, 16,23, 16,24, 16,25, 16,26, 17,27, 18,28, 19,29, 19,30,
27,18, 28,29, 29,20, 30,21, 30,22, 30,23, 30,24, 30,25, 30,26, 29,27, 28,28,
27,29, 27,30, 26,17, 20,17, 28,19, 19,31, 19,32, 19,33, 19,34, 18,35, 17,36,
16,37, 17,38, 18,39, 18,40, 18,41, 18,42, 18,43, 18,44, 17,45, 16,46, 16,47,
16,48, 16,49, 16,50, 16,51, 16,52, 16,53, 15,54, 15,64, 14,55, 13,56, 12,57,
11,58, 11,59, 11,60, 11,62, 11,63, 11,64, 12,64, 13,64, 14,64, 15,64, 16,64,
17,64, 18,64, 19,64, 20,64, 21,64, 22,64, 23,64, 25,64, 26,64, 11,61, 24,64,
27,64, 28,64, 29,64, 30,64, 31,64, 32,64, 33,64, 34,64, 35,64, 30,37, 29,38,
28,39, 28,40, 28,41, 28,42, 28,43, 28,44, 29,45, 30,46, 30,47, 30,48, 30,49,
30,50, 30,51, 30,52, 30,53, 31,54, 27,31, 27,32, 27,33, 27,34, 28,35, 29,36,
32,55, 33,56, 34,57, 35,58, 35,59, 35,60, 35,61, 35,62, 35,63, 35,64
};
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"REINA");
y-=13;
for(int i=0;i<sizeof(Reina);i+=2)

93

putpixel(x+Reina[i],y+Reina[i+1], DARKGRAY);
setfillstyle (SOLID_FILL, LIGHTRED);
floodfill (x+23,y+25, DARKGRAY);
}
void Icono35(int x, int y){
static char Caballo[] = {12,10, 13,11, 14,12, 13,13, 12,14, 13,14, 14,14,
15,14, 16,14, 17,15, 18,16, 19,17, 20,18, 19,19, 19,20, 18,21, 17,22, 16,23,
15,24, 15,25, 15,26, 15,27, 15,28, 16,29, 17,30, 18,31, 17,32, 16,33, 15,34,
15,35, 15,36, 15,37, 15,38, 15,39, 15,40, 16,40, 17,40, 18,40, 19,40, 20,40,
21,40, 22,40, 23,40, 24,40, 25,40, 26,40, 27,40, 28,40, 29,40, 30,40, 13,9,
14,8, 15,7, 16,6, 17,7, 18,8, 19,9, 20,9, 21,9, 22,9, 23,8, 24,7, 25,6, 26,5,
27,6, 27,7, 27,8, 28,9, 29,10, 30,11, 31,12, 32,13, 32,14, 32,15, 32,16, 32,17,
32,18, 31,19, 31,20, 31,21, 30,22, 29,23, 28,24, 27,25, 27,26, 27,27, 27,28,
27,29, 27,30, 28,31, 29,32, 30,33, 30,34, 30,35, 30,36, 30,37, 30,38, 30,39
};
int i;
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA);outtextxy(x+AnchoIcono/2, y+AltoIcono,"Caballo");
for(i=0;i<sizeof(Caballo);i+=2)
putpixel(x+Caballo[i],y+Caballo[i+1], DARKGRAY);
setfillstyle (SOLID_FILL, LIGHTMAGENTA);floodfill(x+25,y+21, DARKGRAY);
}
void Icono36(int x, int y){
static char LORO[] = { 4, 8, 3, 4, 9, 3, 4,10, 3, 4,11, 3, 4,12, 3, 4,13,
3, 4,14, 3, 4, 7, 4, 12, 8, 4, 12, 9, 4, 12,10, 4, 12,11, 4, 12,12, 4, 12,13,
4, 12,14, 4, 4,15, 4, 4, 6, 5, 12, 7, 5, 12, 8, 5, 12, 9, 5, 12,10, 5, 12,11,
5, 12,12, 5, 12,13, 5, 12,14, 5, 12,15, 5, 4,16, 5, 4, 5, 6, 12, 6, 6, 12, 7,
6, 12, 8, 6, 4, 9, 6, 4,10, 6, 4,11, 6, 4,12, 6, 4,13, 6, 12,14, 6, 12,15,
6, 12,16, 6, 4,17, 6, 0, 5, 7, 0, 6, 7, 0, 7, 7, 4, 8, 7, 15, 9, 7, 15,10,
7, 14,11, 7, 14,12, 7, 15,13, 7, 0,14, 7, 0,15, 7, 12,16, 7, 12,17, 7, 4,18,
7, 0, 4, 8, 14, 5, 8, 14, 6, 8, 14, 7, 8, 0, 8, 8, 15, 9, 8, 14,10, 8, 0,11,
8, 0,12, 8, 14,13, 8, 15,14, 8, 0,15, 8, 0,16, 8, 12,17, 8, 4,18, 8, 0, 3,
9, 14, 4, 9, 14, 5, 9, 14, 6, 9, 14, 7, 9, 0, 8, 9, 15, 9, 9, 14,10, 9, 0,11,
9, 0,12, 9, 14,13, 9, 15,14, 9, 0,15, 9, 0,16, 9, 12,17, 9, 12,18, 9, 4,19,
9, 0, 2,10, 14, 3,10, 14, 4,10, 14, 5,10, 14, 6,10, 14, 7,10, 0, 8,10, 15,
9,10, 15,10,10, 14,11,10, 14,12,10, 15,13,10, 15,14,10, 0,15,10, 0,16,10,
12,17,10, 12,18,10, 4,19,10, 0, 2,11, 14, 3,11, 14, 4,11, 0, 5,11, 0, 6,11,
0, 7,11, 0, 8,11, 15, 9,11, 15,10,11, 15,11,11, 15,12,11, 15,13,11, 15,14,11,
0,15,11, 0,16,11, 12,17,11, 12,18,11, 4,19,11, 0, 2,12, 14, 3,12, 0, 4,12,
0, 5,12, 0, 6,12, 0, 7,12, 15, 8,12, 15, 9,12, 15,10,12, 15,11,12, 15,12,12,
15,13,12, 15,14,12, 0,15,12, 0,16,12, 12,17,12, 12,18,12, 4,19,12, 0, 3,13,
8, 5,13, 15, 6,13, 15, 7,13, 15, 8,13, 15, 9,13, 15,10,13, 15,11,13, 15,12,13,
15,13,13, 15,14,13, 0,15,13, 0,16,13, 12,17,13, 12,18,13, 4,19,13, 8, 5,14,
15, 6,14, 15, 7,14, 15, 8,14, 15, 9,14, 15,10,14, 15,11,14, 15,12,14, 15,13,14,
0,14,14, 0,15,14, 0,16,14, 12,17,14, 12,18,14, 4,19,14, 8, 6,15, 15, 7,15,
15, 8,15, 15, 9,15, 15,10,15, 15,11,15, 15,12,15, 0,13,15, 0,14,15, 0,15,15,
0,16,15, 12,17,15, 12,18,15, 4,19,15, 8, 7,16, 0, 8,16, 0, 9,16, 0,10,16,
0,11,16, 0,12,16, 0,13,16, 0,14,16, 0,15,16, 0,16,16, 12,17,16, 12,18,16,
4,19,16, 0, 7,17, 0, 8,17, 0, 9,17, 0,10,17, 0,11,17, 0,12,17, 0,13,17,
0,14,17, 0,15,17, 12,16,17, 12,17,17, 12,18,17, 12,19,17, 4,20,17, 0, 7,18,
0, 8,18, 0, 9,18, 0,10,18, 0,11,18, 0,12,18, 0,13,18, 0,14,18, 12,15,18,
12,16,18, 12,17,18, 12,18,18, 12,19,18, 4,20,18, 0, 7,19, 0, 8,19, 0, 9,19,
0,10,19, 0,11,19, 0,12,19, 12,13,19, 12,14,19, 12,15,19, 12,16,19, 12,17,19,
12,18,19, 12,19,19, 12,20,19, 4,21,19, 4, 6,20, 4, 7,20, 4, 8,20, 12, 9,20,
12,10,20, 12,11,20, 12,12,20, 12,13,20, 12,14,20, 12,15,20, 12,16,20, 12,17,20,
12,18,20, 12,19,20, 12,20,20, 4,21,20, 4,22,20, 4,23,20, 4,24,20, 4,25,20,
4, 5,21, 12, 6,21, 12, 7,21, 4, 8,21, 12, 9,21, 12,10,21, 12,11,21, 12,12,21,

94

12,13,21, 12,14,21, 12,15,21, 12,16,21, 12,17,21, 12,18,21, 12,19,21, 4,20,21,


4,21,21, 12,22,21, 4,23,21, 12,24,21, 12,25,21, 4,26,21, 4,27,21, 4, 5,22,
12, 6,22, 12, 7,22, 4, 8,22, 12, 9,22, 12,10,22, 12,11,22, 12,12,22, 12,13,22,
12,14,22, 12,15,22, 12,16,22, 12,17,22, 12,18,22, 4,19,22, 4,20,22, 12,21,22,
12,22,22, 12,23,22, 4,24,22, 12,25,22, 12,26,22, 12,27,22, 4,28,22, 4, 4,23,
12, 5,23, 12, 6,23, 12, 7,23, 4, 8,23, 12, 9,23, 12,10,23, 12,11,23, 12,12,23,
12,13,23, 12,14,23, 12,15,23, 12,16,23, 12,17,23, 4,18,23, 12,19,23, 12,20,23,
4,21,23, 12,22,23, 12,23,23, 12,24,23, 4,25,23, 12,26,23, 12,27,23, 12,28,23,
4,29,23, 4, 4,24, 12, 5,24, 12, 6,24, 0, 7,24, 12, 8,24, 12, 9,24, 12,10,24,
12,11,24, 12,12,24, 12,13,24, 12,14,24, 12,15,24, 12,16,24, 12,17,24, 0,18,24,
1,19,24, 1,20,24, 1,21,24, 4,22,24, 12,23,24, 12,24,24, 12,25,24, 4,26,24,
12,27,24, 12,28,24, 12,29,24, 4,30,24, 4, 4,25, 12, 5,25, 1, 6,25, 0, 7,25,
12, 8,25, 12, 9,25, 12,10,25, 12,11,25, 12,12,25, 12,13,25, 12,14,25, 12,15,25,
12,16,25, 12,17,25, 0,18,25, 1,19,25, 1,20,25, 1,21,25, 1,22,25, 6,23,25,
14,24,25, 14,25,25, 14,26,25, 6,27,25, 14,28,25, 14,29,25, 4,30,25, 0, 4,26,
1, 5,26, 1, 6,26, 0, 7,26, 12, 8,26, 12, 9,26, 12,10,26, 12,11,26, 12,12,26,
12,13,26, 12,14,26, 12,15,26, 12,16,26, 12,17,26, 0,18,26, 1,19,26, 1,20,26,
1,21,26, 1,22,26, 1,23,26, 6,24,26, 14,25,26, 14,26,26, 6,27,26, 14,28,26,
14,29,26, 14,30,26, 6,31,26, 0, 4,27, 1, 5,27, 1, 6,27, 0, 7,27, 12, 8,27,
12, 9,27, 12,10,27, 12,11,27, 12,12,27, 12,13,27, 12,14,27, 12,15,27, 12,16,27,
12,17,27, 12,18,27, 0,19,27, 1,20,27, 1,21,27, 1,22,27, 1,23,27, 6,24,27,
14,25,27, 14,26,27, 14,27,27, 6,28,27, 1,29,27, 1,30,27, 0,31,27, 0, 4,28,
1, 5,28, 1, 6,28, 0, 7,28, 12, 8,28, 12, 9,28, 12,10,28, 12,11,28, 12,12,28,
12,13,28, 12,14,28, 12,15,28,12,16,28, 12,17,28, 12,18,28, 0,19,28, 1,20,28,
1,21,28, 1,22,28, 1,23,28, 1,24,28, 6,25,28, 14,26,28, 1,27,28, 0,28,28,
1,29,28, 1,30,28, 1,31,28, 0,32,28, 0, 4,29, 1, 5,29, 1, 6,29, 0, 7,29,
12, 8,29, 12, 9,29, 12,10,29, 12,11,29, 12,12,29, 12,13,29, 12,14,29, 12,15,29,
12,16,29, 12,17,29, 12,18,29, 12,19,29, 0,20,29, 1,21,29, 1,22,29, 1,23,29,
1,24,29, 6,25,29, 1,26,29, 1,27,29, 1,28,29, 0,29,29, 1,30,29, 1,31,29,
0,32,29, 0, 4,30, 1, 5,30, 1, 6,30, 0, 7,30, 12, 8,30, 12, 9,30, 12,10,30,
12,11,30, 12,12,30, 12,13,30, 12,14,30, 12,15,30, 12,16,30, 12,17,30, 12,18,30,
12,19,30, 0,20,30, 1,21,30, 1,22,30, 1,23,30, 1,24,30, 1,25,30, 0,26,30,
1,27,30, 1,28,30, 1,29,30, 0,30,30, 1,31,30, 1,32,30, 0,33,30, 0, 4,31,
1, 5,31, 1, 6,31, 0, 7,31, 12, 8,31, 12, 9,31, 12,10,31, 12,11,31, 12,12,31,
12,13,31, 12,14,31, 12,15,31, 12,16,31, 12,17,31, 12,18,31, 12,19,31, 12,20,31,
0,21,31, 1,22,31, 1,23,31, 1,24,31, 1,25,31, 0,26,31, 1,27,31, 1,28,31,
1,29,31, 1,30,31, 0,31,31, 1,32,31, 1,33,31, 0,34,31, 0, 4,32, 1, 5,32,
1, 6,32, 0, 7,32, 12, 8,32, 12, 9,32, 12,10,32, 12,11,32, 12,12,32, 12,13,32,
12,14,32, 12,15,32, 12,16,32, 12,17,32, 12,18,32, 12,19,32, 12,20,32, 12,21,32,
0,22,32, 1,23,32, 1,24,32, 1,25,32, 1,26,32, 0,27,32, 1,28,32, 1,29,32,
1,30,32, 1,31,32, 0,32,32, 1,33,32, 1,34,32, 0,35,32, 0,36,32, 0, 4,33,
1, 5,33, 1, 6,33, 0, 7,33, 12, 8,33, 12, 9,33, 12,10,33, 12,11,33, 12,12,33,
12,13,33, 12,14,33, 12,15,33, 12,16,33, 12,17,33, 12,18,33, 12,19,33, 12,20,33,
12,21,33, 12,22,33, 0,23,33, 1,24,33, 1,25,33, 1,26,33, 1,27,33, 0,28,33,
1,29,33, 1,30,33, 1,31,33, 0,32,33, 1,33,33, 1,34,33, 1,35,33, 1,36,33,
0,37,33, 0, 5,34, 1, 6,34, 1, 7,34, 0, 8,34, 12, 9,34, 12,10,34, 12,11,34,
12,12,34, 12,13,34, 12,14,34, 12,15,34, 12,16,34, 12,17,34, 12,18,34, 12,19,34,
12,20,34, 12,21,34, 12,22,34, 12,23,34, 0,24,34, 1,25,34, 1,26,34, 1,27,34,
1,28,34, 0,29,34, 1,30,34, 1,31,34, 1,32,34, 0,33,34, 1,34,34, 1,35,34,
1,36,34, 0,37,34, 0, 5,35, 1, 6,35, 1, 7,35, 0, 8,35, 12, 9,35, 12,10,35,
12,11,35, 12,12,35, 12,13,35, 12,14,35, 12,15,35, 12,16,35, 12,17,35, 12,18,35,
12,19,35, 12,20,35, 12,21,35, 12,22,35, 12,23,35, 12,24,35, 0,25,35, 1,26,35,
1,27,35, 1,28,35, 1,29,35, 0,30,35, 1,31,35, 1,32,35, 1,33,35, 0,34,35,
1,35,35, 0,36,35, 4,37,35, 4,38,35, 4,39,35, 0, 5,36, 1, 6,36, 1, 7,36,
0, 8,36, 12, 9,36, 12,10,36, 12,11,36, 12,12,36, 12,13,36, 12,14,36, 12,15,36,
12,16,36, 12,17,36, 12,18,36, 12,19,36, 12,20,36, 12,21,36, 12,22,36, 12,23,36,
12,24,36, 12,25,36, 0,26,36, 0,27,36, 1,28,36, 1,29,36, 1,30,36, 0,31,36,
1,32,36, 1,33,36, 0,34,36, 0,35,36, 12,36,36, 12,37,36, 12,38,36, 12,39,36,
4,40,36, 4,41,36, 4,42,36, 4,43,36, 4,44,36, 4,45,36, 0, 6,37, 1, 7,37,

95

1, 8,37, 0, 9,37, 12,10,37, 12,11,37, 12,12,37, 12,13,37, 12,14,37, 12,15,37,


12,16,37, 12,17,37, 12,18,37, 12,19,37, 12,20,37, 12,21,37, 12,22,37, 12,23,37,
12,24,37, 12,25,37, 12,26,37, 12,27,37, 0,28,37, 0,29,37, 0,30,37, 0,31,37,
0,32,37, 0,33,37, 12,34,37, 12,35,37, 12,36,37, 12,37,37, 12,38,37, 12,39,37,
12,40,37, 12,41,37, 12,42,37, 12,43,37, 12,44,37, 12,45,37, 4,46,37, 4,47,37,
4,48,37, 4,49,37, 4,50,37, 4,51,37, 4,52,37, 4,53,37, 4,54,37, 0, 6,38,
1, 7,38, 1, 8,38, 0, 9,38, 12,10,38, 12,11,38, 12,12,38, 12,13,38, 12,14,38,
12,15,38, 12,16,38, 12,17,38, 12,18,38, 12,19,38, 12,20,38, 12,21,38, 12,22,38,
12,23,38, 12,24,38, 12,25,38, 12,26,38, 12,27,38, 12,28,38, 12,29,38, 4,30,38,
12,31,38, 12,32,38, 12,33,38, 12,34,38, 12,35,38, 12,36,38, 12,37,38, 12,38,38,
12,39,38, 12,40,38, 12,41,38, 12,42,38, 12,43,38, 12,44,38, 12,45,38, 12,46,38,
12,47,38, 12,48,38, 12,49,38, 12,50,38, 12,51,38, 12,52,38, 12,53,38, 12,54,38,
4,55,38, 4,56,38, 4,57,38, 4,58,38, 0, 7,39, 1, 8,39, 1, 9,39, 0,10,39,
12,11,39, 12,12,39, 12,13,39, 12,14,39, 12,15,39, 12,16,39, 12,17,39, 12,18,39,
12,19,39, 12,20,39, 12,21,39, 12,22,39, 12,23,39, 12,24,39, 12,25,39, 12,26,39,
12,27,39, 12,28,39, 12,29,39, 4,30,39, 12,31,39, 12,32,39, 12,33,39, 12,34,39,
12,35,39, 12,36,39, 12,37,39, 12,38,39, 12,39,39, 12,40,39, 12,41,39, 12,42,39,
12,43,39, 12,44,39, 12,45,39, 12,46,39, 12,47,39, 12,48,39, 12,49,39, 12,50,39,
12,51,39, 12,52,39, 12,53,39, 12,54,39, 12,55,39, 12,56,39, 12,57,39, 12,58,39,
4,59,39, 0, 7,40, 1, 8,40, 1, 9,40, 0,10,40, 12,11,40, 12,12,40, 12,13,40,
12,14,40, 12,15,40, 12,16,40, 12,17,40, 12,18,40, 12,19,40, 12,20,40, 12,21,40,
12,22,40, 12,23,40, 12,24,40, 12,25,40, 12,26,40, 12,27,40, 12,28,40, 4,29,40,
12,30,40, 12,31,40, 12,32,40,12,33,40, 12,34,40, 12,35,40, 12,36,40, 12,37,40,
12,38,40, 12,39,40, 12,40,40,12,41,40, 12,42,40, 12,43,40, 12,44,40, 12,45,40,
12,46,40, 12,47,40, 12,48,40,12,49,40, 12,50,40, 12,51,40, 12,52,40, 12,53,40,
12,54,40, 12,55,40, 12,56,40,12,57,40, 12,58,40, 4,59,40, 0, 8,41, 0, 9,41,
4,11,41, 12,12,41, 12,13,41, 12,14,41, 12,15,41, 12,16,41, 12,17,41, 12,18,41,
12,19,41, 12,20,41, 12,21,41,12,22,41, 12,23,41, 12,24,41, 12,25,41, 12,26,41,
12,27,41, 12,28,41, 4,29,41,12,30,41, 12,31,41, 12,32,41, 12,33,41, 12,34,41,
12,35,41, 12,36,41, 12,37,41,12,38,41, 12,39,41, 12,40,41, 12,41,41, 12,42,41,
12,43,41, 12,44,41, 12,45,41,12,46,41, 12,47,41, 12,48,41, 12,49,41, 12,50,41,
12,51,41, 12,52,41, 12,53,41,12,54,41, 4,55,41, 4,56,41, 4,57,41, 4,58,41,
4,12,42, 12,13,42, 12,14,42,12,15,42, 12,16,42, 12,17,42, 12,18,42, 12,19,42,
12,20,42, 12,21,42, 12,22,42, 12,23,42, 12,24,42, 12,25,42, 12,26,42, 12,27,42,
4,28,42, 4,29,42, 4,30,42, 4,31,42, 4,32,42, 4,33,42, 12,34,42, 12,35,42,
12,36,42, 12,37,42, 12,38,42,12,39,42, 12,40,42, 12,41,42, 12,42,42, 12,43,42,
12,44,42, 12,45,42, 12,46,42,12,47,42, 4,48,42, 4,49,42, 4,50,42, 4,51,42,
4,52,42, 4,53,42, 4,54,42, 4,13,43, 12,14,43, 12,15,43, 12,16,43, 12,17,43,
12,18,43, 12,19,43, 12,20,43, 12,21,43, 12,22,43, 12,23,43, 12,24,43, 12,25,43,
12,26,43, 4,27,43, 4,34,43, 4,35,43, 4,36,43, 4,37,43, 4,38,43, 4,39,43,
4,40,43, 4,41,43, 4,42,43, 4,43,43, 4,44,43, 4,45,43, 4,46,43, 4,47,43,
4,14,44, 4,15,44, 12,16,44,12,17,44, 12,18,44, 12,19,44, 12,20,44, 12,21,44,
12,22,44, 12,23,44, 12,24,44, 4,25,44, 4,26,44, 4,16,45, 4,17,45, 4,18,45,
4,19,45, 4,20,45, 4,21,45, 4,22,45, 4,23,45, 4,24,45, 8,17,46, 8,18,46,
8,22,46, 8,23,46, 8,17,47, 8,18,47, 8,22,47, 8,23,47, 8,17,48, 8,18,48,
8,22,48, 8,23,48, 8,16,49, 8,17,49, 8,18,49, 8,21,49, 8,22,49, 8,23,49,
0,12,50, 0,13,50, 8,14,50, 8,15,50, 8,16,50, 8,17,50, 8,18,50, 8,19,50,
8,20,50, 8,21,50, 8,22,50, 8,23,50, 8,24,50, 0,11,51, 0,15,51, 0,16,51,
0,17,51, 0,18,51, 8,19,51, 8,20,51, 8,22,51, 8,23,51, 8,24,51, 8,25,51,
0,14,52, 0,16,52, 0,20,52, 0,21,52, 8,22,52, 8,23,52, 8,24,52, 0,25,52,
0,26,52, 0,19,53, 0,27,53};
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, TOP_TEXT);
setcolor(MAGENTA); outtextxy(x+AnchoIcono/2, y+AltoIcono,"LORO");
setviewport(x, y, x+AnchoIcono, y+AltoIcono, 1);
for(int i=0;i<sizeof(LORO);i+=3)
putpixel(LORO[i+1], LORO[i+2], LORO[i]);

96

setviewport(0, 0, 639, 479, 1); //Pantalla completa


}
/************************************************************************** */
/* Funcion : MarcoVentana
*/
/* Objetivo : Dibujar un ReCuadro resaltado o undido.
*/
/************************************************************************** */
void MarcoVentana(int x1, int y1, int x2, int y2,
int ColorArribaIzquierda,
int ColorAbajoDerecha)
{
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
setcolor(ColorArribaIzquierda);
line(x1, y1, x1, y2);
line(x1, y1, x2, y1);
setcolor(ColorAbajoDerecha);
line(x2, y1, x2, y2);
line(x1, y2, x2, y2);
}
/************************************************************************** */
/* Funcion : Cursor
*/
/* Objetivo : Realiza recuadro, con una cadena centrada en su interior,
*/
/*
da a significar una de las opciones de un men
*/
/************************************************************************** */
void Cursor(int x,int y, int pos, int Oprimido)
{
Icono[pos](x, y);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH); setcolor(DARKGRAY);
moveto(x, y); lineto(x+AnchoIcono, y);
lineto(x+AnchoIcono, y+AltoIcono); lineto(x, y+AltoIcono); lineto(x, y);
if (!Oprimido) {
setcolor(DARKGRAY);
line(x+1, y+1, x+1, y+AltoIcono-1);
line(x+1, y+1, x+AnchoIcono-1, y+1);
setcolor(WHITE);
line(x+AnchoIcono-1, y+1, x+AnchoIcono-1,
line(x+1, y+AnchoIcono-1, x+AnchoIcono-1,
}
else {
setcolor(WHITE);
line(x+1, y+1, x+1, y+AltoIcono-1);
line(x+1, y+1, x+AnchoIcono-1, y+1);
setcolor(DARKGRAY);
line(x+AnchoIcono-1, y+1, x+AnchoIcono-1,
line(x+1, y+AnchoIcono-1, x+AnchoIcono-1,
}

y+AnchoIcono-1);
y+AnchoIcono-1);

y+AnchoIcono-1);
y+AnchoIcono-1);

}
/************************************************************************** */
/* Funcion : main
*/
/* Objetivo : El programa inicia siempre por la funcin principal
*/
/************************************************************************** */
void main(){
int Manejador = DETECT, Modo, i, PosXi=25, PosYi=20, Deltax=80, Deltay=70;
initgraph(&Manejador, &Modo, "c:\\tc\\bgi");
cleardevice();
setbkcolor(LIGHTGRAY);
MarcoVentana(2, 2, 637, 477, DARKGRAY, WHITE);
MarcoVentana(4, 4, 635, 475, WHITE, DARKGRAY);
int x=PosXi, y=PosYi;

97

for(i=0; i<MaxIco; i++){


Cursor(x, y, i, 0);
x+=Deltax;
if(x>=639-Deltax){
x=PosXi; y+=Deltay;
}
}
Cursor(PosXi, PosYi, 0, 1); //Se activa opcin del "men"
getch();
}

98

MANEJO DE CADENAS DE CARACTERES


1. DECLARACION DE CADENA COMO VECTOR DE CARACTERES
A diferencia de muchos otros lenguajes, el lenguaje C/C++, no trae un tipo
primitivo de datos para el manejo de variables de tipo cadena, sino que, estas,
deben ser definidas o como un vector de caracteres(char) o como un puntero a
caracter.
En la definicin como vector, veamos el siguiente programa CADENAS1.CPP:
0.1 Se lee una variable, definida como vector, de cadena de caracteres por
teclado y luego se muestra en pantalla su valor, como si fuera un vector de
caracteres y como "cadena".
//CADENAS1.CPP
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
void main(){
const LargoCadena = 10;
char cadena[LargoCadena+1];
int longitud;
clrscr();
cout << "Digite una cadena, hasta de " << LargoCadena << " caracteres: ";
gets(cadena);
longitud = strlen(cadena);
cout << endl << endl;
for(int i = 0; i < longitud; i++)
cout << cadena[i];
cout << "\n\n" << cadena;
getch();
}
En el programa anterior se define una variable de tipo cadena como un vector
de caracteres, su abstraccin es la siguiente, al iniciar la ejecucin del
programa:
cadena
longitud LargoCadena

10

0
1
2
3
4
5
6
7
8
9 10 11
Observe que la variable cadena se ha dimensionado con LargoCadena+1
posiciones, es decir 10+1=11 posiciones(bytes), debe tener siempre esto en
cuenta, ya que se debe considerar un terminador de nulo, '\0' adicional a la
cadena que se pretenda almacenar en la variable cadena.
Inicialmente se pide se digite una cadena hasta de 10 caracteres de largo,
supongamos que esa cadena es: Cali Valle, en memoria quedar as:

99

cadena

'C''a''l''i'' ''V''a''l''l''e''\0'

0
1
2
3
4
5
6
7
8
9 10
11

longitud

LargoCadena

10

Observe que en la posicin, 10, es decir a continuacin del ltimo caracter


vlido, se ha asignado el caracter nulo "automticamente por la instruccin
gets(), de esta forma es que el compilador "sabr" hasta donde llega la cadena
que se ha asignado a la variable. Se deben digitar solo hasta LargoCadena
caracteres, en este caso, si se digitan ms, el programa tomar un rumbo
inesperado y puede llegar hasta a bloquearse( simule esta situacin, previo
almacenaje del archivo en disco).
A continuacin se invoca la funcin strlen() de l archivo a incluir
string.h, ella de regreso, retornar el largo de la cadena, para nuestro caso 9,
asignndoselo a la variable longitud, de la siguiente forma:
cadena

'C''a''l''i'' ''V''a''l''l''e''\0'

0
1
2
3
4
5
6
7
8
9 10
11

longitud

LargoCadena

10

A continuacin se recorre la variable cadena, como cualquier otro vector,


utilizando un indice, i, y la instruccin repetitiva for. El efecto neto es
mostrar cada caracter en pantalla. Igual efecto se consigue con la instruccin
cout << cadena, como puede confirmar ejecutando el programa.
0.2 El siguiente programa pide digitar una cadena de caracteres y luego esta es
presentada centrada en la pantalla dos filas ms abajo.
//CADENAS3.CPP
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
void main(){
char cadena[80]; int longitud;
clrscr();
cout <<"Digite una cadena para luego centrarla en la pantalla: ";
gets(cadena);
cout << endl << endl;
for(longitud = (80 - strlen(cadena))/2; longitud > 0; longitud--)
cout << " ";
cout << cadena;
}
2.0 DECLARACION DE CADENA COMO UN PUNTERO A CARCTER
En este caso
por medio de un
almacenar, esto
mayor cuidado en

la declaracin de la variable
puntero a caracter, sin darle
ltimo puede ser la ventaja,
el cdigo de programacin como

cadena de
un lmite
pero tiene
es siempre

caracteres se efecta
mximo a la cadena a
el inconveniente del
cuando se trabaja con

100

punteros. Recuerde que si en C no trabaja con punteros no est utilizando las


verdaderas posibilidades que ofrece el lenguaje. Ejecute el siguiente programa
CADENAS2.CPP y efectele todos los cambios que se le ocurr... es probable que
hasta se le bloquee el computador. Recomendamos no trabajar de esta forma.

101

0.1 Se lee una variable, definida como puntero, de cadena de caracteres por
teclado y luego se muestra en pantalla su valor.
//CADENAS2.CPP
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
void main(){
char *cadena;
clrscr();
cout << "Digite una cadena de caracteres: ";
gets(cadena);
cout << endl << endl;
cout << cadena << endl;
puts(cadena);//puts escribe cadena y es la instruccin "compaera" de gets
getch();
}
0.2 El siguiente programa presenta, a partir de la lectura de una cadena de
caracteres, su ordenamiento alfabtico ascendentemente. La variable cadena se ha
definido como un puntero a caracter, no reservndole espacio adecuado para
trabajo, es probable que este programa le funcione bien muchas veces, pero alguna
vez le fallar, en especial cuando digita cadenas largas. Insistimos en no
recomendar esta forma de trabajo. Las variables de cadena deben ser definidas
como vectores de caracter, con el dimencionamiento adecuado. Los punteros se
dejan exclusivamente para recibir parmetros en la definicin de funciones.
//CADENAS4.CPP
#include <iostream.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>
void main(){
char *cadena, aux;
int i, j;
clrscr();
cout << "Digite una frase: ";
gets(cadena);
cout << "Longitud cadena = " << strlen(cadena) << "\n\n";
for(i=0; i<strlen(cadena); i++)
for(j = i+1; j<strlen(cadena); j++)
if(cadena[i] > cadena[j]){
aux = cadena[i];
cadena[i] = cadena[j];
cadena[j] = aux;
}
cout << "\"frase ordenada alfabticamente\": \n" ;
puts(cadena);

102

103

30 PROGRAMAS DE APLICACIN
3.1 Ejemplo de funciones varias para manipular cadenas de caracteres. La mayora
vienen incorporadas en el archivo a incluir string.h.
//CADENAS5.CPP
#include
#include
#include
#include
#include

<iostream.h>
<stdlib.h> /* NULL*/
<ctype.h>
<conio.h>
<stdio.h>

int longitud (char *cadena){


int c=0;

//Similar a la funcin strlen de string.h

while(*cadena){
c++;
cadena++;
}
return c;
}
void AMayusculas(char *cadena){ //similar a strupr de string.h
while (*cadena){
if (*cadena>=97 && *cadena<=122 ) // ASCII: a=97 z=122 A=65
*cadena = *cadena - (97-65);
cadena++;
}
}
void AMinusculas(char *cadena){ //similar a strlwr de string.h
while (*cadena){
if (*cadena>=65 && *cadena<=90 ) // ASCII: A=65 Z=90 a=97
*cadena = *cadena + (97-65);
cadena++;
}
}
void Apropiado(char *s){
while(*s){
*s = toupper(*s);
s++;
while(*s && *s!=' '){
*s = tolower(*s);
s++;
}
while(*s && *s==' ')
s++;
}
}
void CopiarCadena(char *cadena2, char *cadena1){//Copia cadena1 en cadena2
*cadena2 = *cadena1;
while(*cadena1){
cadena2++;
cadena1++;
*cadena2 = *cadena1;

104

}
}
void ConcatenarCadena(char *cadena2, char *cadena1){
//esta funcin es similar a strcat de string.h
while (*cadena2) //Encuentra final de cadena2
cadena2++;
while(*cadena1){
//aade contenido de cadena1 a cadena2
*cadena2 = *cadena1;
cadena2++;
cadena1++;
}
*cadena2 = '\0'; //coloca terminador nulo a la cadena2
}
int CompararCadenas(char *cadena2, char *cadena1){//Similar a strcmp de string.h
int posicion=1; /*de la primera diferencia.*/
while(*cadena1 == *cadena2){
if( *cadena1 == NULL && *cadena2 == NULL)
return 0;
//las cadenas son iguales
cadena1++;
cadena2++;
posicion++;
}
if (*cadena1-1 < *cadena2-1)
posicion = -posicion;
return posicion;
}
int ContarOcurrenciaCaracter(char *cadena, char caracter){
int c=0;
while(*cadena != NULL){
if (*cadena == caracter)
c++;
cadena++;
}
return c;
}
int SustituirCaracterPorOtro(char *cadena, char carviejo, char carnuevo){
int contador=0;
while(*cadena){
if (*cadena == carviejo){
*cadena = carnuevo;
contador++;
}
cadena++;
}
return contador;
}
void main(){
char c1, c2, s2[80], *s1="Esto es una prueba";

105

int pos;
clrscr();
cout << s1;
cout << ": Tiene una longitud de " << longitud(s1) << " caracteres \n";
AMayusculas(s1);
cout << "\n\nEn maysculas fijas es: " <<s1;
AMinusculas(s1);
cout << "\n\nEn minsculas fijas es: " <<s1;
Apropiado(s1);
cout << "\n\nEn forma Apropiada es: " <<s1;
CopiarCadena(s2, s1);
cout << "\n\nCopiado S1 en s2 = "<< s2;
ConcatenarCadena(s2, " de cadenas");
cout << "\n\nConcatenado S2 con un mensaje = " << s2;
getch(); clrscr();
cout

<< "\n\nEJEMPLO DE COMPARACION DE CADENAS \n"


<< "Digite cadena:";
gets(s1);
cout << "\n\nDigite otra cadena:";
gets(s2);
pos = CompararCadenas(s2,s1);
if ( pos > 0)
cout << "\n\nCadena " << s1 << " es mayor alfabeticamente que " << s2;
else
if ( pos < 0)
cout <<"\n\nCadena " << s1 << " es menor alfabeticamente que " << s2;
else
cout << "\n\nLas cadenas "<< s2 << " y " << s1 << " son iguales";
getch(); clrscr();
cout << "\n\n\nDigite frase para contarle las vocales:";
gets(s2);
cout << "\na = "<< ContarOcurrenciaCaracter(s2, 'a');
cout << "\ne = "<< ContarOcurrenciaCaracter(s2, 'e');
cout << "\ni = "<< ContarOcurrenciaCaracter(s2, 'i');
cout << "\no = "<< ContarOcurrenciaCaracter(s2, 'o');
cout << "\nu = "<< ContarOcurrenciaCaracter(s2, 'u');
cout << "\nDigite un caracter de anterior frase: ";
cin >> c1;
cout<<"\nDigite nuevo caracter para sustituir a: " << c1 << "\n";
cin >> c2;
if ( SustituirCaracterPorOtro(s2, c1, c2) )
cout << "\n" << s2;
else
cout << "El caracter digitado no se encontr en frase";
getch();
}
3.2 El siguiente programa permite leer una cadena de caracteres, con un tamao

106

mximo permitido, y sin utilizar las instruccin tradicionales de lectura para


cadenas, tales como: gets, scanf cin. Se efecta lectura de caracter tras
caracter, analizando cada uno de ellos y obrando en consecuencia.
//LEERCADE.CPP
#include <iostream.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
int LeerCadena(char *Cadena, int LargoCad)
{
char car;
int pos=0, x=wherex(), y=wherey();
Cadena[0]=NULL;
do{
car = getche();
switch(car)
{
case 0: car = getch(); //se debe "perder" es tecla de funcin
cout <<(char)8;//retrocede
break;
case 8: if(pos>0) {
//BS: retroceso
cout <<(char)32; cout <<(char)8;//escribe blanco y retrocede
pos--;
}
break;
case 9: cout <<(char)8 <<(char)32 <<(char)8; //HT: tabulador
break;
case 13: if(pos<LargoCad)
//CR: entrar
Cadena[pos]=NULL;
else
Cadena[LargoCad]=NULL;
break;
case 27: Cadena[0]=NULL;
//ESC: Escape
gotoxy(x,y);
clreol();
break;
default: Cadena[pos]=car;
pos++;
}
} while ((car != 13) && (car != 27));
if(car==27)
return (0);
return (1);
}
void main(){
char *puntero, vector[80];
clrscr();
cout << "\n\nDigite una cadena: ";
LeerCadena(puntero, 8);
//puede que le falle algn da
cout << "\n\nCadena digitada: " << puntero;
cout << "\n\nDigite otra cadena: ";
if(LeerCadena(vector, 10))

107

cout << "\n\nCadena digitada" << vector;


else
cout << "Se cancel la lectura con ESC";
getch();
}
3.3 La siguiente funcin, ASCIIaInt, convierte una cadena de texto en un entero,
siempre y cuando lo sea. Reemplaza a la funcin atoi(...). Ver el programa
Graph_IO.cpp para su utilizacin.
int ASCIIaInt(char *CadALeer){
int pos, numero=0, Menos=0, Inicio=0;
float exp=1;

//de -32768 a 32767

pos=strlen(CadALeer)-1;
if(CadALeer[0]=='-' || CadALeer[0]=='+'){
Inicio++;
if(CadALeer[0]=='-')
Menos++;
}
for(int i=pos; i>=Inicio; i--){
numero = numero+(int)((CadALeer[i]-'0')*exp );
exp*=10;
}
if(Menos)
numero = -numero;
return numero;
}
3.4 La siguiente funcin, ASCIIaFloat, convierte una cadena de texto en un real,
siempre y cuando lo sea. Reemplaza a la funcin atof(...). Precaucin: No acepta
el caracter e, como en: 5.3e5 . Ver el programa Graph_IO.cpp para su utilizacin.
float ASCIIaFloat(char *CadNumerica) {
int punto=0, LargoCad=0, i=0, Signo=1, PosPunto=0;
float Real, Exponente;
char *c;
while (*CadNumerica == ' '){ // Elimina espacios en blanco al inicio
c=CadNumerica;
while(*c){
*c= *(c+1);
c++;
}
}
c=CadNumerica;
if(*c=='-')
Signo = -1;
if(*c=='+' || *c=='-'){
c++;
LargoCad++;

//avanza un caracter si es un signo

108

}
while( (*c>='0' && *c<='9') || (*c=='.') ){
LargoCad++;
//Cuenta el nmero de caracteres en la cadena
if(*c=='.'){
punto++;
if(punto>1){
cout <<'\a';return 0;
}
PosPunto=LargoCad-1;
}
c++;
}
if(*c){//No lleg al final de cadena numrica, No es numrico, hay error
cout <<'\a'; return 0;
}
c=CadNumerica;
Real=0;
if(PosPunto>0) //Se digit el punto decimal
i=PosPunto-1;
else
//No se digit un punto decimal
i=LargoCad-1;
Exponente=1;
while(i>=0 && c[i]!='+' && c[i]!='-'){
Real += (c[i]-'0')*Exponente; //Suma valor numrico de parte entera
Exponente *= 10;
i--;
}
if(PosPunto>0){ //Se digit el punto decimal
i=PosPunto+1;
Exponente=0.1;
while(i<LargoCad){
Real += (c[i]-'0')*Exponente;//Suma valor numrico de parte decimal
Exponente /=10.;
i++;
}
}
Real *= Signo;
return (Real);
}
3.5 La siguiente funcin se encarga de capturar una cadena en una posicin de la
pantalla en modo grfico.
int LeerCadena(char *CadALeer,
int x=10, int y=10, int largo=80,
int ColorTexto=BLUE, int ColorFondo=WHITE)
{
int pos=0, fin=0, LongCar, AltoCar, Terminar=0, L, i, Insertar=1;
struct textsettingstype AnteriorTexto;
struct viewporttype Vista;
char Tecla;
getviewsettings(&Vista); gettextsettings(&AnteriorTexto);

109

settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); //valores por defecto


LongCar= textwidth("H"); AltoCar= textheight("I");
L = (Vista.right - x) /LongCar-1;
if(largo>L)
largo = L;
CadALeer[0] = Nulo;
setfillstyle(SOLID_FILL, ColorFondo);
bar(x,y,x+LongCar*largo,y+AltoCar); //barra en que se escribe
setcolor(ColorTexto); rectangle(x-1,y-1,x+LongCar*largo+1,y+AltoCar+1);
outtextxy(x,y+1,"_"); // Simular el cursor
do {
Tecla = getch();
// lee la tecla digitada
if(Tecla) { // es tecla que genera un byte
switch(Tecla){
case CtrlC: Terminar = 1; break;
case Retroceso:
if (pos > 0) {
pos--;
i = pos;
while(i<=fin){
CadALeer[i] = CadALeer[i+1];
i++;
}
fin--;
} else cout <<"\a";
break;
case Tab: cout << '\a'; break; //Tecla tabulador. Que no haga nada
case Entrar: Terminar=1; break;
case Esc: pos=fin=0;
CadALeer[0] = Nulo;// tecla de escape. Borra lo escrito
break;
default:
if(pos>=largo)
cout<< "\a";
else{
if(Tecla>=Espacio){
CadALeer[pos]=Tecla; // asignar el caracter
if(!Insertar || pos==fin){
if(pos>=fin){
CadALeer[pos+1]=Nulo;
fin++;
}
}
else{
if(fin>=largo)
cout<< "\a";
else{
i = fin;
while(i>=pos){
CadALeer[i+1] = CadALeer[i];
i--;
}
fin++;
}
}
pos++;
}

110

else
cout << '\a';
}
}
}
else{ // tecla de secuencia de ESC. Tecla es igual a 0 en primer byte
Tecla = getch();
// lee el segundo byte
switch (Tecla) {
case Home: pos=0; break;
case AltX: Terminar = 1; exit(0); //Alt+X aborta el programa
case End : pos=fin; break;
case Ins : if(Insertar) Insertar=0; //Modo se insercin
else Insertar=1;
break;
case Del: i = pos;//pos queda en el mismo sitio, a medida que borra
while(i<=fin){
CadALeer[i] = CadALeer[i+1];
i++;
}
fin--;
break;
case Izq: if (pos > 0) {
pos--;
} else cout <<"\a";
break;
case Der: if(pos>=largo-1)
cout<< "\a";
else{
if(pos >= fin){
fin++;
CadALeer[pos]=Espacio;
CadALeer[fin+1]=Nulo;
}
pos++;
}
break;
//Tecla Derecha. Que no haga nada
case CtrlIzq: ;
case CtrlDer: ;
default: cout<< "\a";
}
}
bar(x,y,x+LongCar*largo,y+AltoCar); //barra en que se escribe
rectangle(x-1,y-1,x+LongCar*largo+1,y+AltoCar+1);
if ( (pos < largo) && !Terminar)
outtextxy(x+(pos*LongCar),y+1,"_");
outtextxy(x, y+1, CadALeer);
} while (!Terminar);
while(CadALeer[fin-1]==Espacio){//Se eliminarn espacios blancos al final
CadALeer[fin]=Nulo; //se corre el nulo
fin--;
}
while(CadALeer[0]==Espacio){ //Se eliminarn espacios en blanco al inicio
i = 0;
while(i<=fin){
CadALeer[i] = CadALeer[i+1];
i++;

111

}
fin--;
}
bar(x,y,x+LongCar*largo,y+AltoCar); //barra en que se escribe
rectangle(x-1,y-1,x+LongCar*largo+1,y+AltoCar+1);
outtextxy(x, y+1, CadALeer); //Se reescribe sin espacios al inicio y final
//Restaura las condiciones antes de antes de entrar a esta funcin
settextstyle(AnteriorTexto.font,AnteriorTexto.direction,AnteriorTexto.charsize);
settextjustify(AnteriorTexto.horiz, AnteriorTexto.vert);
return fin; // retorna el largo de la cadena
}
PROGRAMA A REALIZAR COMO EJERCICIO
1. En el programa de las ventanas realizado en el captulo sobre pilas y con la
ayuda de la funcin LeerCadena presentada en este captulo y en el programa
IO_Graph.CPP, permita efectuar lectura de varias lineas en cada ventana. Numere
cada una de las ventanas en orden ascendente a medida que se van creando. El
texto que se digite en cada ventana debe poder ser actualizado a voluntad en el
nmero de ventana que se desee. El texto debe ser reescrito adecuadamente en cada
ventana cuando se retire una ventana que lo estaba tapando. Efecte los cambios
necesarios para utilizar el programa IO_Graph.CPP como archivo a incluir.
2. En todos los proyectos a presentar en este curso no utilice la librera
String.H, en su lugar emplee las funciones dadas en este captulo, las que le
faltaren elabore el correspondiente algoritmo en lenguaje C y utilcelas. Cree un
archivo a incluir dentro de su proyecto con ellas.

112

3. El siguiente programa permite convertir en nmero entero a cadena.


//NUMASCII.CPP
#include <IOStream.H>
#include <ConIO.H>
int EnteroASCII(long Entero, char *Cad){//reemplaza a la funcin itoa
//Retorna el largo de la cadena numrica
long E;
int largo=0;
char aux;
E = Entero;
if (E==0){
Cad[0]='0';
Cad[1]='\0';
}
else{
if(E<0)
E = -E;
while(E){
Cad[largo] = (char) (E % 10 +48); //'0'= 48 en ASCII
E /= 10;
largo++;
}
Cad[largo] = '\0';
for(int i=0, j=largo-1; i<largo/2; i++, j--){
aux = Cad[i];
Cad[i] = Cad[j];
Cad[j] = aux;
}
i=largo;
if(Entero<0){
while (i >= 0){ //Se inserta el signo menos
Cad[i+1] = Cad[i];
i--;
}
Cad[0] = '-'; //signo menos
largo++;
}
}
return largo;
}
void main(){
char Cad[20];
int Entero;
cout << "Digite un nmero entero: "; cin >> Entero;
EnteroASCII(Entero, Cad);
cout << "Convertido a cadena = " << Cad;
}

113

114

EVALUACIN EXPRESIN ALGEBRAICA


1. APLICACIN DE NOTACIN POLACA INVERSA
La notacin postfija tambin en conocida como notacin polaca inversa, a
continuacin presento programa que convierten una expresin en infija a postfija
y posteriormente se efecta la evaluacin de esta ltima.
En el siguiente programa se efecta evaluacin de expresin algebraica.
Consultar descripcin del algoritmo en el libro "Estructura de Datos" de S.
Lipschutz. Pgina 191 a la 196.
//POLACA.
CPP
//============================================================================
// Inclusin de archivos de libreras con los que se trabajar
//============================================================================
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <Cadenas.h>
//============================================================================
// Definicin de algunas constantes y MACROS
//============================================================================
#define Max 20
#define Nulo '\0'
#define ValorAbsoluto(x) ( (x>=0)? x : 0-x )
#define EsNumerico(x) ( ((x>='0' && x<='9') || x=='.')? 1 : 0 )
#define EsOperador(op) ((op=='+'||op=='-' || op=='/' ||op=='*' ||op =='^')? 1:0)
#define EsOtros(p) ( (p=='(' || p==')' || p==' ')? 1 : 0)
#define CaracterValido(x) ( (EsNumerico(x) || EsOperador(x) ||EsOtros(x))? 1:0 )
//============================================================================
//
Definicin de prototipos DE FUNCIONES
//============================================================================
void
Meter(char *, char);
//Observe que est sobrecargada
void
Meter(double *, double);
char
Sacar(char);
//Observe que est sobrecargada
double Sacar(double *);
double EvaluarPostfija(char *);
int
ConvertirInfijaAPostfija(char, char *);
int
PriorizarOperadores(char, char);
//============================================================================
//
Definicin variables globales
//============================================================================
char
PilaChar[Max],*CimaChar= Nulo;
double PilaNum[Max], *CimaNum = Nulo;
//============================================================================
// FUNCIONES PROPIAS DE LA EVALUACION DE UNA EXPRESION ALGEBRAICA
//============================================================================
int PriorizarOperadores(char op1, char op2){
if (op1 == '(' ) return 0;

115

if (op1 == '^') return 1;


if( (op1 == '/') || (op1 == '*') ){
if (op2 == '^')
return 0;
if ((op2=='/') || (op2=='*') || (op2=='+') || (op2=='-') || (op2=='_') )
return 1;
}
if (op1 == '_') //menos unario despus de parntesis
return 1;
if ((op1 == '+') || (op1 == '-') || (op1 == '_') ){
if ((op2 == '^') || (op2 == '/') || (op2 == '*'))
return 0;
if ((op2 == '+') || (op2 == '-') || (op2 == '_') )
return 1;
}
}
//---------------------------------------------------------------------------void Meter(char *P, char item){
if (CimaChar == (P+Max-1)){
cout <<"\n\nDesbordamiento\a";
getch(); exit(1);
}
else {
if (CimaChar == Nulo)
CimaChar = PilaChar; /*Inicializa PilaChar*/
else
CimaChar++;
*CimaChar = item;
}
}
//---------------------------------------------------------------------------char Sacar(char *P){
char item;
if (CimaChar) {
item = *CimaChar;
if (CimaChar == P) // Era el ltimo elemento
CimaChar = Nulo;
else
CimaChar--;
return item;
}
}
//---------------------------------------------------------------------------void Meter(double *P, double item){
if (CimaNum == (P+Max-1)){
cout <<"\n\nDesbordamiento"; while(!kbhit()); exit(1);
}
else {
if (CimaNum == Nulo)
CimaNum = PilaNum; /*Inicializa PilaNum*/
else
CimaNum++;
*CimaNum = item;

116

}
return;
}
//---------------------------------------------------------------------------double Sacar(double *P){
double item;
if (CimaNum) {
item = *CimaNum;
if (CimaNum == P) /* Era el ltimo elemento*/
CimaNum = Nulo;
else
CimaNum--;
}
return item;
}
//---------------------------------------------------------------------------int ConvertirInfijaAPostfija(char *Infija, char *Postfija){
char *Op=" \x0";
int Digito=0; //saber si el anterior(es) ha sido numrico(incluye punto)
int Punto=0; //para saber si un nmero tiene ms de un punto
int ParDer=0; //solucionar casos como: -(-3, con memos unario
CimaChar= Nulo;
ConcatenarCadenas(Infija, ")");
AsignarCadena(Postfija, "");
Meter(PilaChar, '(');
while(*Infija){
if(!CaracterValido(*Infija)) return 0;
if (EsNumerico(*Infija)){
if(*Infija=='.'){
if(Punto) return 0; //ya hay un punto, no es un # vlido
Punto++; // cuenta solo el primer punto
}
if(!Digito && *Infija=='.')
ConcatenarCadenas(Postfija, "0");
Digito=1;
Op[0] = Infija[0];
ConcatenarCadenas(Postfija, Op);
}
else{
if(Digito) {
if( *Infija==' ' && EsNumerico( *(Infija+1) ) )
return 0;
ConcatenarCadenas(Postfija, " ");
Digito=0;
Punto=0;
}
if (*Infija == '('){
Meter(PilaChar, '('); ParDer=1;
}
else
if (EsOperador(*Infija)){
if (!ParDer){
while( PriorizarOperadores(*CimaChar, *Infija)){
//Si el operador en PilaChar es mayor o igual en presedencia
Op[0] = Sacar(PilaChar);
ConcatenarCadenas(Postfija, Op );//se concatena con Postfija

117

ConcatenarCadenas(Postfija, " ");


}
}
else
if(*Infija=='-'){
//se cambia - por _
*Infija = '_'; // '_' simbolizar el menos unario
ParDer=0;
}
Meter(PilaChar, *Infija);
}
else
if (*Infija == ')')
while ( (*Op=Sacar(PilaChar)) != '(' ){
ConcatenarCadenas(Postfija, Op);
ConcatenarCadenas(Postfija, " ");
}
}//if-else
Infija++;
}//while
return 1;
}
//---------------------------------------------------------------------------double EvaluarPostfija(char *p){
double a, b;
char *aux=" \x0", // ojo con el espacio en blanco, no lo borre
Numero[80]="\0";
CimaNum = Nulo;
while (*p){
if(EsNumerico(*p)){
AsignarCadena(Numero, Nulo);
while (EsNumerico(*p)){
aux[0] = *p;
ConcatenarCadenas(Numero, aux);
p++;
}
Meter(PilaNum, atof(Numero)); //Mete en PilaNum el valor numrico
}
else{
if(*p=='_'){ // operador monario despus de un parntesis en infija
a = Sacar(PilaNum);
Meter(PilaNum, -a);
}
else{
if(EsOperador(*p) ){
b = Sacar(PilaNum);
a = Sacar(PilaNum);
switch(*p){
case '^': Meter(PilaNum, pow(a,b)); break;
case '/': Meter(PilaNum, a/b); break;
case '*': Meter(PilaNum, a*b); break;
case '+': Meter(PilaNum, a+b); break;
case '-': Meter(PilaNum, a-b); break;
}
}//if
}
p++;

118

}//if-else
}//while
return(Sacar(PilaNum));
}
//---------------------------------------------------------------------------void main(){
char Infija[Max], Postfija[Max];
clrscr();
puts("Los operadores pueden ser + - / * ^ ");
puts("Puede dejar espacios en blanco entre operandos y operador\n");
puts("En expresiones como: 2 ^ -1
digite como 2^(-1)");
puts("
2 ^ -1.1 digite como 2^(-1.1)" );
puts("NOTA: los menos unarios sern convertidos al caracter _");
puts("Digite expresin algebraica en Infija: ");
gets(Infija);
if(ConvertirInfijaAPostfija(Infija,Postfija) ){
cout <<"\nExpresin correspondiente en Postfija: ";
puts(Postfija);
cout <<"\n\nResultado = " << EvaluarPostfija(Postfija);
}
else
puts("\nError en expresin Infija");
while(!kbhit());
}//Fin main()
//-----------------------------------------------------------------------------

119

PROGRAMAS A REALIZAR COMO EJERCICIO


1. Utilizando el programa POLACA.CPP de este captulo, permita que se pueda
digitar una expresin algebraica con variables. Inicie el trabajo recodificando
para expresiones del tipo y=f(x) y posteriormente, ample a varias variables, por
ejemplo: y = f(x,y,...).
2. Con la ayuda del programa MATRIZEL.CPP y con POLACA.CPP disee una pequea
hoja de clculo electrnico.
3. Con la ayuda de POLACA.CPP como herramienta, debe el programa permitir digitar
una expresin algebraica del tipo y = F(x) y a continuacin aparecer la
correspondiente grfica en pantalla, este programa le ser de mucha utilidad en
la asignatura de Mtodo Numricos que cursar posteriormente.

120

EXPRESIN EN LGICA PROPOSICIONAL


#include
#include
#include
#include

<IOStream.H>
<ConIo.H>
<StdLib.H>
<StdIO.H>

//=============================================================================/
/Definicin de prototipos de todas las funciones utilizadas
char AMayuscula(char c);
char AMinuscula(char c);
void AMinusculas(char *c);
void EsperarTecla();
int EstaEn(char Caracter, char *CaracteresValidos);
int LongitudCadena(char *cadena);
int ASCIIaInt(char *CadALeer);
void AsignarCadena(char *cadena2, char *cadena1);
int CompararCadenas(char *cadena1, char *cadena2);
//-----------------------------------------------------------------------------void AnalizarExpresionLogica();
//Funcin sobrecargada
void AnalizarExpresionLogica(int *Valor);
void MostrarNumeroError(int NumError);
void ObtenerOperadorOR(int *Valor);
void ObtenerOperadorAND(int *Valor);
void ObtenerOperadorNOT(int *Valor);
void ObtenerParentesisIzquierdo(int *Valor);
int ObtenerValorPrimitivo(int *Valor);
void DeterminarOperador(char Operador, int *Operando1, int *Operando2);
void LeerLeyesDeDeMorgan();
void TransformarExpresionLogica();
int
ObtenerSimbolo();
void main();
//=============================================================================/
/DEFINICION DE VARIABLES GLOBALES:
char Expresion[80];
char Simbolo[80];
char *Pos;
char CarValidos[10];
//=============================================================================
char AMayuscula(char c){
if(c>=97 && c<=122)
c -= (97-65);
return c;
}
//--------------------------------------------------------------------------char AMinuscula(char c){
if(c>=65 && c<=90)
c += (97-65);
return c;
}
//--------------------------------------------------------------------------//esta funcion reemplaza a strlwr de la librera string.h

121

void AMinusculas(char *c){


while(*c){
*c = AMinuscula(*c);
c++;
}
}
//--------------------------------------------------------------------------void EsperarTecla(){
cout << "\n\n\nDigite cualquier tecla para seguir: ";
if(getch()==0) getch();
}
//--------------------------------------------------------------------------int EstaEn(char Caracter, char *CaracteresValidos){
while(*CaracteresValidos)
if(Caracter == *CaracteresValidos)
return 1; // Encontrado el caracter buscado
else
CaracteresValidos++;
return 0; //No encontrado el caracter buscado
}
//--------------------------------------------------------------------------int LongitudCadena(char *cadena){//Similar a la funcion strlen de string.h
int c=0;
while(*cadena++)
c++;
return c;
}
//--------------------------------------------------------------------------/* Funcion
: int ASCIIaInt
*/
/* Objetivo : Esta funcion convierte una cadena de texto en un entero,
*/
/*
siempre y cuando lo sea.
*/
/*
Reemplaza a la funcion atoi(...)
*/
//--------------------------------------------------------------------------int ASCIIaInt(char *CadALeer){
int pos, numero=0, Menos=0, Inicio=0;
//de -32768 a 32767
float exp=1;
pos=LongitudCadena(CadALeer)-1;
if(CadALeer[0]=='-' || CadALeer[0]=='+'){
Inicio++;
if(CadALeer[0]=='-')
Menos++;
}
for(int i=pos; i>=Inicio; i--){
numero = numero+(int)((CadALeer[i]-'0')*exp );
exp*=10;
}
if(Menos)
numero = -numero;
return numero;
}
//--------------------------------------------------------------------------//La siguiente funcion reemplaza a strcpy del archivo a incluir string.h
void AsignarCadena(char *cadena2, char *cadena1){
while(*cadena1){

122

*cadena2 = *cadena1;
cadena2++;
cadena1++;
}
*cadena2 = *cadena1;

//Siempre debe ser NULL lo que asigne aqu


}
//--------------------------------------------------------------------------int CompararCadenas(char *cadena1, char *cadena2)
{
int pos=1;
while(*cadena1==*cadena2)
{
if(*cadena1==NULL && *cadena2==NULL)
return 0;
cadena1++;
cadena2++;
pos++;
}
if(*cadena1<*cadena2)
pos = -pos;
return pos;
}
//=============================================================================
void AnalizarExpresionLogica(){ //Funcion sobrecargada
int Valor;
clrscr();
AsignarCadena(CarValidos, "()|&!");
cout << "Puede digitar operadores: & | !";
cout << "\ny constantes: 1 0 d \n\n";
cout << "Solo se pueden utilizar parntesis redondos(), para agrupar\n";
cout << "Digite expresion logica, Por ejemplo: 1 & (d | 1) \n";
cout << "Separe con espacios en blanco: ";
gets (Expresion);
if(*Expresion){
AMinusculas(Expresion);
cout << Expresion << endl;
Pos = Expresion;
AnalizarExpresionLogica(&Valor);
cout << "\nEl resultado es: ";
switch(Valor){
case 0 : cout << "Falso\n";
break;
case 1 : cout << "Verdad\n";
break;
case 'd': cout << "Desconocido\n";
break;
}
EsperarTecla();
}
}
//--------------------------------------------------------------------------void AnalizarExpresionLogica(int *Valor){ //Funcion sobrecargada
ObtenerSimbolo();
if(! *Simbolo )
MostrarNumeroError(2);
else

123

ObtenerOperadorOR(Valor);
}
//--------------------------------------------------------------------------void MostrarNumeroError(int NumError){
static char *MensajeError[]={"Error de sintasis",
"Parntesis desequilibrado",
"Ninguna Expresion presente"
};
cout << MensajeError[NumError] << endl;
}
//--------------------------------------------------------------------------void ObtenerOperadorOR(int *Valor){
char op;
int Mantiene;
ObtenerOperadorAND(Valor);
while( (op = *Simbolo) == '|') {
ObtenerSimbolo();
ObtenerOperadorAND(&Mantiene);
DeterminarOperador(op, Valor, &Mantiene);
}
}
//--------------------------------------------------------------------------void ObtenerOperadorAND(int *Valor){
char op;
int Mantiene;
ObtenerOperadorNOT(Valor);
while( (op = *Simbolo) == '&') {
ObtenerSimbolo();
ObtenerOperadorNOT(&Mantiene);
DeterminarOperador(op, Valor, &Mantiene);
}
}
//--------------------------------------------------------------------------void ObtenerOperadorNOT(int *Valor){
char op;
op = 0;
if( *Simbolo == '!') {
op = '!';
ObtenerSimbolo();
}
ObtenerParentesisIzquierdo(Valor);
if(op)
DeterminarOperador(op, Valor, Valor);
}
//--------------------------------------------------------------------------void ObtenerParentesisIzquierdo(int *Valor){
if( *Simbolo == '(') {
ObtenerSimbolo();
ObtenerOperadorOR(Valor);
if( *Simbolo != ')')
MostrarNumeroError(1);
ObtenerSimbolo();

124

}
else
ObtenerValorPrimitivo(Valor);
}
//--------------------------------------------------------------------------int ObtenerValorPrimitivo(int *Valor){
int i;
if( EstaEn(*Simbolo, "01d") ){
if( *Simbolo == 'd')
*Valor = 'd';
else
*Valor = ASCIIaInt(Simbolo);
return ObtenerSimbolo();
}
MostrarNumeroError(0); //Error en sintaxis de expresion
}
//--------------------------------------------------------------------------void DeterminarOperador(char Operador, int *Operando1, int *Operando2){
switch(Operador){
case '&': if(*Operando1 != 'd' && *Operando2 != 'd'){
*Operando1 = *Operando1 && *Operando2;
return;
}
if(*Operando1 == 'd' && *Operando2 == 0)
*Operando1 = 0;
else
if(*Operando1 == 0 && *Operando2 == 'd')
*Operando1 = 0;
else
*Operando1 = 'd';
break;
case '|': if(*Operando1 != 'd' && *Operando2 != 'd'){
*Operando1 = *Operando1 || *Operando2;
return;
}
if(*Operando1 == 1 || *Operando2 == 1)
*Operando1 = 1;
else
*Operando1 = 'd';
break;
case '!': if(*Operando1 != 'd')
*Operando1 = !*Operando1;
else
*Operando1 = 'd';
break;
}
}
//--------------------------------------------------------------------------void LeerLeyesDeDeMorgan(){
AsignarCadena(CarValidos, "()");
clrscr();
cout << "Las reglas de De Morgan son : \n";
cout << "
no (P y Q) => no P o no Q \n";
cout << "
no (P o Q) => no P y no Q \n";

125

cout << "Digite una de las cuatro expresiones mostradas antes \n";
gets(Expresion);
if(*Expresion){
AMinusculas(Expresion);
cout << Expresion << endl;
Pos = Expresion;
TransformarExpresionLogica();
EsperarTecla();
}
}
//--------------------------------------------------------------------------void TransformarExpresionLogica(){
char p[80], q[80], s[4], EsY;
//Teoremas de De Morgan en forma inversa : \n";
//
~ P o ~ Q => ~ (P y Q)
//
~ P y ~ Q => ~ (P o Q)
Pos = Expresion; // se reinicializa
ObtenerSimbolo();
if(!CompararCadenas(Simbolo, "no") ){
ObtenerSimbolo();
AsignarCadena(p, Simbolo);
ObtenerSimbolo();
if(!CompararCadenas(Simbolo, "y") )
EsY = 1;
else
EsY = 0;
ObtenerSimbolo();
if(!CompararCadenas(Simbolo, "no") ){
ObtenerSimbolo();
AsignarCadena(q, Simbolo);
if(EsY)
AsignarCadena(s, "o");
else
AsignarCadena(s, "y");
cout << "\n\nno (" << (char)AMayuscula(p[0])
<< " " << s << " " << (char)AMayuscula(q[0]) << ")";
return;
}
}
//Teoremas de De Morgan son : \n";
//
~ (P y Q) => ~ P o ~ Q
//
~ (P o Q) => ~ P y ~ Q
Pos = Expresion;
ObtenerSimbolo();
if(!CompararCadenas(Simbolo, "no") ){
ObtenerSimbolo();
if(*Simbolo=='(') {
ObtenerSimbolo();
AsignarCadena(p, Simbolo);
ObtenerSimbolo();
if(!CompararCadenas(Simbolo, "y") )
EsY = 1;
else

126

EsY = 0;
ObtenerSimbolo();
AsignarCadena(q, Simbolo);
ObtenerSimbolo();
if(*Simbolo, ")") { //Es una expresion v lida de De Morgan
if(EsY)
AsignarCadena(s, "o");
else
AsignarCadena(s, "y");
cout << "\n\nno " << (char)AMayuscula(p[0])
<< " " << s << " no " << (char)AMayuscula(q[0]);
return;
}
}
}
Pos = Expresion; // Se reinicializa
cout << "\n\nTautologa no implementada o mal escrita \a\a";
return;
}
//--------------------------------------------------------------------------int
ObtenerSimbolo(){
char *p;
p = Simbolo;
while(*Pos==' ') Pos++; //Salta espacios en blanco al inicio
if(*Pos == '\0') { // es el final de la entrada
*p++ = '\0';
return 0;
}
if(EstaEn(*Pos, CarValidos) ) {
*p = *Pos;
p++;
Pos++;
*p = '\0';
return 1;
}
//Avanza caracteres hasta encontrar un espacio o parntesis,
// determinando una palabra
while(*Pos != ' ' && !EstaEn(*Pos, CarValidos) ) {
*p = *Pos;
Pos++;
p++;
}
*p = '\0';
return 0;
}
//--------------------------------------------------------------------------void main(){
char opcion;
do{
clrscr();
cout << " 1. Analizar expresion logica
\n";
cout << " 2. Verificar leyes de De Morgan \n";
cout << "Esc. para terminar el programa
\n";

127

opcion = getch();
switch(opcion){
case '1': AnalizarExpresionLogica(); break;
case '2': LeerLeyesDeDeMorgan(); break;
}
}while(opcion != 27);
}
//=============================================================================

128

COMPARACIN DE ORDENAMIENTOS
1. INTRODUCCIN
En el siguiente programa, podr observar una comparacin grfica entre los
algoritmos de ordenamiento: Merge Sort con recursin, Sorteo por Seleccin
Recursiva, QuickSort con recursin y el tradicional y psimo de Burbuja en forma
iterativa. Lo anterior no quiere decir que los algoritmos recursivos sean ms
rpidos. No, todo lo contrario. Las versiones iterativos de los mismos degen
trabajar ms rpido que los presentados en este programa.
2. EL PROGRAMA
/****************************************************************************/
#include<Graphics.h>
#include <StrStream.H>
#include <StdLib.H>
#include<ConIO.h>
#include <DOS.h>
#include <Time.H>
/****************************************************************************/
//Prototipos de funciones principales
void MergeSort(int *Vector, int Izq, int Der);
void SorteoPorSeleccionRecursiva(int *Vector, int i, int N);
void QuickSort(int *Vector, int Izq, int Der);
void Burbuja(int *Vector, int N);
void GraficarValores(int *Datos, int N, int PosA, int PosB, int Retardo=0);
/****************************************************************************/
const Max = 312; //Tamao del vector.
int N=0;
//Si lo aumenta de 314, la escala de las barras no queda bien.
const Entrar=13, Retroceso=8, CtrlC=3, Tab=9, Esc=27, Espacio=32, Nulo='\0';
const Home=71, Izq=75, AltX=45, Der=77, End=79, Ins=82,
Del=83, CtrlIzq=115, CtrlDer=116;
//***************************************************************************
void MergeSort (int *Vector, int Izq, int Der){
int i, j, k, Medio;
int b[Max];
if(Der>Izq){
Medio = (Der+Izq) >> 1;
MergeSort(Vector, Izq, Medio);
MergeSort(Vector, Medio+1, Der);
for(i = Medio+1; i>Izq; i--)
b[i-1] = Vector[i-1];
for(j = Medio; j < Der; j++)
b[Der+Medio-j] = Vector[j+1];
for(k = Izq; k <= Der; k++){
Vector[k] = (b[i]<b[j])? b[i++]:b[j--];
GraficarValores(Vector, N, k, j);
}
}
}
/****************************************************************************/
void SorteoPorSeleccionRecursiva (int *Vector, int i, int N)
{
int j, PosMenor;
int Aux;

129

if(i<N-1){
PosMenor = i;
for(j=i+1; j<N; j++)
if(Vector[j] < Vector[PosMenor])
PosMenor = j;
Aux = Vector[PosMenor];
Vector[PosMenor] = Vector[i];
Vector[i] = Aux;
GraficarValores(Vector, N, PosMenor, i);
SorteoPorSeleccionRecursiva(Vector, i+1, N);
}
}
/****************************************************************************/
void QuickSort (int *Vector, //Clasificacin r pida
int Izq,
int Der)
{
int izq=Izq, der=Der;
int pivote, aux;
pivote = Vector[(Izq+Der)/2];
do{
while (Vector[izq] < pivote)
izq++;
while (pivote < Vector[der])
der--;
if(izq <= der) {
aux = Vector[izq];
Vector[izq] = Vector[der];
Vector[der] = aux;
GraficarValores(Vector, N, izq, der);
izq++;
der--;
}
} while(izq < der);
if(Izq < der)
QuickSort(Vector, Izq, der);
if(izq < Der)
QuickSort(Vector, izq, Der);
}
/****************************************************************************/
void Burbuja (int *Vector, int N){
int i, j;
int Aux;
for(i=0; i<N-1; i++)
for(j=0; j<N-i; j++)
if(Vector[j] > Vector[j+1]){
Aux = Vector[j];
Vector[j] = Vector[j+1];
Vector[j+1] = Aux;
GraficarValores(Vector, N, j, j+1);
}
}
/* **************************************************************************/
/* Funcin
: CentrarXCad
*/
/* Objetivo : Esta funcin se encarga de Escribir una cadena
*/

130

/*
centrada en la pantalla en modo gr fico
*/
/****************************************************************************/
void CentrarXCad(int Fila, char *Cad, int Color){
int largo;
setcolor(Color);
largo = textwidth(Cad); outtextxy((getmaxx()-largo)/2,Fila,Cad);
}
/****************************************************************************/
void GraficarValores(int *Datos,
int N,
int PosA,
int PosB,
int Retardo)
{
int i, Izquierda, Arriba=5, ArribaBar, Ancho, Abajo, Eje=10, MayorValor=0;
float Fraccion, Delta;
if( N ){
MayorValor=Datos[0];
for( i=1; i<N; i++)
if(Datos[i]>MayorValor)
MayorValor = Datos[i];
Ancho = (int)( (getmaxx()-Eje) / ((N * 2 ) + 1) );
Abajo = getmaxy() - 40;
Izquierda = Ancho+Eje;
Delta= (float)(Abajo-Arriba+1)/MayorValor;
if(PosA==-1 || PosB==-1){
setcolor(WHITE); line(Eje/2, Arriba, Eje/2, Abajo); //Eje y
for(float rayita=Abajo; rayita>=Arriba-Delta; rayita-=Delta)
line(3, (int)rayita, 7, (int)rayita);
for( i=0; i<N; i++){
Fraccion = (float) Datos[i] / MayorValor;
ArribaBar = (int)(Abajo - Fraccion * (Abajo-Arriba) );
setcolor(RED); setfillstyle(SOLID_FILL, MAGENTA);
bar(Izquierda, ArribaBar, (Izquierda + Ancho), Abajo);
Izquierda += (Ancho * 2);
}
}
else
for( i=0; i<N; i++){
if(PosA==i || PosB==i){
Fraccion = (float) Datos[i] / MayorValor;
ArribaBar = (int)(Abajo - Fraccion * (AbajoArriba) );
setcolor(RED); setfillstyle(SOLID_FILL, MAGENTA);
bar(Izquierda, ArribaBar, (Izquierda + Ancho),
Abajo);
setfillstyle(SOLID_FILL, BLUE);
bar(Izquierda, Arriba, (Izquierda + Ancho),
ArribaBar);
}
Izquierda += (Ancho * 2);
}
delay(Retardo);
}
else{

131

settextstyle(TRIPLEX_FONT, HORIZ_DIR, 8);


CentrarXCad(140, "NO HAY DATOS", RED);
}
}
/****************************************************************************/
/* INICIO FUNCIONES PARA EL MANEJO DEL MOUSE CON INTERRUPCION 33 DEL DOS
*/
/****************************************************************************/
int IniciarMouse(int &BotonMouse){
union REGS entra,sale;
entra.x.ax = 0x0000;
int86( 0x33, &entra, &sale);
BotonMouse = sale.x.bx;
return ( sale.x.ax );
}
/****************************************************************************/
void MostrarCursorMouse(void){
union REGS entra, sale;
entra.x.ax = 0x0001;
int86 ( 0x33, &entra, &sale );
}
/****************************************************************************/
void EsconderCursorMouse(void){
union REGS entra, sale;
entra.x.ax = 0x0002;
int86( 0x33, &entra, &sale);
}
/****************************************************************************/
int ClickMouseEnXY( int &x, int &y){
union REGS entra,sale;
entra.x.ax = 0x0003;
int86( 0x33, &entra, &sale );
x = sale.x.cx;
y = sale.x.dx;
return(sale.x.bx);
}
//**************************************************************************
void CursorMouseAXY( int x, int y ){
union REGS entra, sale;
entra.x.ax = 0x0004;
entra.x.cx = x;
entra.x.dx = y;
int86( 0x33, &entra, &sale);
}
/****************************************************************************/
/* FIN FUNCIONES PARA EL MANEJO DEL MOUSE CON INTERRUPCION 33 DEL DOS
*/
/****************************************************************************/
/****************************************************************************/
/* Funcin
: BarColor
*/
/* Objetivo : Esta funcion se encarga de hacer una barra
*/
/*
en la pantalla, de un color dado y un patrn.
*/
/****************************************************************************/
void BarraDeColor(int x1,int y1,int x2,int y2,int Patron, int Color){
int ColorAnterior = getcolor();
EsconderCursorMouse();
setfillstyle(Patron,Color);
bar(x1,y1,x2,y2);
setcolor(ColorAnterior);
MostrarCursorMouse();
}

132

/****************************************************************************/
/* Funcin : MarcoVentana
*/
/* Objetivo : Dibujar un ReCuadro resaltado o undido.
*/
/****************************************************************************/
void RecuadroVentana(int X1,int Y1,int X2,int Y2,int ArbAbj){
EsconderCursorMouse();
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
if(ArbAbj == 1)
setcolor(DARKGRAY);
else
setcolor(WHITE);
line(X1, Y1, X1, Y2);
line(X1, Y1, X2, Y1);
if(ArbAbj == 1)
setcolor(WHITE);
else
setcolor(DARKGRAY);
line(X2, Y1, X2, Y2);
line(X1, Y2, X2, Y2);
MostrarCursorMouse();
}
/****************************************************************************/
/* FUNCION
: RealzarCursor
*/
/* OBJETIVO : Muestra un rectangulo en pantalla, el cual significa
*/
/*
una de las opciones de un men.
*/
/****************************************************************************/
void RealzarCursor(int x1,int y1,int x2,int y2,int Color1,int Color2,int Color3)
{
EsconderCursorMouse();
setcolor(Color1);line(x1,y1,x2,y1); line(x1,y1,x1,y2);
setcolor(Color2);line(x1,y2,x2,y2); line(x2,y2,x2,y1);
setcolor(Color3);line(x1+1,y1+1,x2-1,y1+1);line(x1+1,y1+1,x1+1,y2-1);
line(x1+1,y2-1,x2-1,y2-1);line(x2-1,y2-1,x2-1,y1+1);
setfillstyle(1,Color3); floodfill(x1+5,y1+5,Color3);
setcolor(Color2); line(x1+1,y2-1,x2-1,y2-1); line(x2-1,y2-1,x2-1,y1+1);
MostrarCursorMouse();
}
/****************************************************************************/
/* Funcin : Cursor
*/
/* Objetivo : Realiza recuadro, con una cadena centrada en su interior,
*/
/****************************************************************************/
void Cursor(int X, int Y, int LargoCuadro, char *Cad,
int Col1,int Col2,int Col3,int Col4,int
Col5,int Oprimido){
int AltoCuadro;
char c[3];
EsconderCursorMouse();
settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
AltoCuadro=textheight(Cad) + 10;
if(LargoCuadro==0)
LargoCuadro = X + textwidth(Cad) + 10;
else
LargoCuadro = X + LargoCuadro + 10;
if(!Oprimido){
BarraDeColor(X,Y,LargoCuadro,Y+AltoCuadro,SOLID_FILL,Col1);
RecuadroVentana(X,Y,LargoCuadro,Y+AltoCuadro,1);
setcolor(Col3);
}

133

else{
BarraDeColor(X,Y,LargoCuadro,Y+AltoCuadro,SOLID_FILL,Col2);
RecuadroVentana(X,Y,LargoCuadro,Y+AltoCuadro,1);
setcolor(Col4);
}
outtextxy(X+5,Y+5,Cad);
setcolor(Col5);
c[0] = Cad[0];
outtextxy(X+5,Y+5,c);
MostrarCursorMouse();

c[1] ='\0';

}
/**************************************************************************/
/* Funcin : PulsadoCuadro
*/
/* Objetivo : Realiza Cursor con una cadena centrada en su
*/
/*
interior y da la sensacion de que se oprime.
*/
/**************************************************************************/
void UndidoCursor(int X,int Y,int LargoCadenaMayor,
char *Cad, int Col1, int Col2, int
Col3, int Col4, int Col5){
const NoActual=0, Actual=1;
EsconderCursorMouse();
Cursor(X, Y, LargoCadenaMayor,Cad, Col1, Col2, Col3, Col4,

Col5, NoActual

);
delay(100);
Cursor(X, Y, LargoCadenaMayor,Cad, Col1, Col2, Col3, Col4, Col5, Actual );
delay(100);
Cursor(X, Y, LargoCadenaMayor,Cad, Col1, Col2, Col3, Col4, Col5,
NoActual);
MostrarCursorMouse();
}
/* *********************************************************************** */
/* Funcin : AMAYUSCULA
*/
/* Objetivo : Convierte un caracter en minscula a mayscula.
*/
/* *********************************************************************** */
char AMayuscula(char c){
if(c>=97 && c<=122)
c -= (97-65);
return c;
}
/* ************************************************************************
/* Funcin : EscribirComentarioOpcionMenu
/* Objetivo : Muestra avisos correspondientes a opciones del men
/* ************************************************************************
void EscribirComentarioOpcionMenu(char *Comentario,

*/
*/
*/
*/

int Xo=1, int Yo=460,


int Xf=638, int Yf=480)
{
//

EsconderCursorMouse();
RealzarCursor(Xo, Yo, Xf, Yf, DARKGRAY, WHITE, BLUE);
setfillstyle(SOLID_FILL, BLUE);
bar(Xo+4, Yo+4, Xf-4, Yf-2);
settextstyle(DEFAULT_FONT, 0, 1);
CentrarXCad(Yo+5, Comentario, WHITE);
MostrarCursorMouse();

}
/****************************************************************************/

134

void PresentacionInicial(){
EsconderCursorMouse();
setcolor(WHITE); rectangle(0,0,getmaxx(),getmaxy());
RealzarCursor(170,110,480,370,WHITE,DARKGRAY,LIGHTGRAY);
RealzarCursor(16,20,624,435,WHITE,DARKGRAY,LIGHTGRAY);
RealzarCursor(55,60,585,400,DARKGRAY,WHITE,LIGHTGRAY);
RealzarCursor(58,63,582,397,WHITE,DARKGRAY,LIGHTGRAY);
setcolor(11);
for(int i=170;i<480;i+=5)
line(325,240,i,110);
setcolor(14);
for(i=170;i<479;i+=3)
line(170,110,i,368);
setcolor(15);
for(int j=110;j<379;j+=20) line(325,240,478,j);
CentrarXCad(150,"ITESM", BLACK);
CentrarXCad(190,"CIENCIAS DE LA COMPUTACION", BLACK);
CentrarXCad(230,"ANALISIS DE ALGORITMOS", RED);
CentrarXCad(270,"GRUPO 21", MAGENTA);
CentrarXCad(310,"Noviembre-2000", BLACK);
MostrarCursorMouse();
}
/* *********************************************************************** */
/*
FUNCION PRINCIPAL
*/
/* *********************************************************************** */
void main(){
const Der=77, Izq=75, Esc=27, Entrar=13, MaxOp=5,
NoActual=0, Actual=1, DeMas=12;
int Pos=0, Invocar=1,
i, Fila=442, Xm=320, Ym=Fila-20,
Click, PosX[MaxOp], AnchoCursor=0;
int Vector[Max], Aux[Max];
char Tecla, Cad[80],
Op[MaxOp][20]={"Random", "Seleccin","QuickSort","MergeSort","Burbuja"},
Comentario[MaxOp][80]={
"Generar al azar valores para vector",
"Algoritmo de Sorteo por Seleccin con Recursin",
"Algoritmo de Sorteo del QuickSort Recursivo",
"Algoritmo de Sorteo por fusin de sublistas",
"Algoritmo de Ordenamiento de Burbuja" };
clock_t TiempoInicial, TiempoFinal;//ver Time.h
int Manejador = DETECT, Modo;
initgraph (&Manejador, &Modo, "\\tc\\bgi");
setbkcolor(BLUE);
if(!IniciarMouse(Click)){
outtextxy(10,10,"El ratn NO est
delay(2000);
return;
}
CursorMouseAXY(Xm, Ym);
PresentacionInicial();
settextstyle(DEFAULT_FONT,HORIZ_DIR,0);
settextjustify(LEFT_TEXT,TOP_TEXT);

instalado");

for(i=0;i<MaxOp;i++)
AnchoCursor += textwidth(Op[i])+DeMas;
PosX[0] = (getmaxx()-AnchoCursor)/2;
for(i=1;i<MaxOp;i++)
PosX[i] = PosX[i-1]+textwidth(Op[i-1])+DeMas;
EscribirComentarioOpcionMenu(Comentario[Pos]);
for(i=0; i<MaxOp; i++)
Cursor(PosX[i],Fila,0,Op[i],LIGHTGRAY,CYAN,WHITE,WHITE,RED, NoActual);
Cursor(PosX[Pos],Fila,0,Op[Pos],LIGHTGRAY,CYAN,WHITE,WHITE,RED,Actual);
Invocar = 0;

135

Xm=PosX[Pos]+1;
Ym=Fila+DeMas;
for(;;){
if(Invocar){
EscribirComentarioOpcionMenu(Comentario[Pos]);
for(i=0; i<MaxOp; i++)
Cursor(PosX[i],Fila,0, Op[i], LIGHTGRAY, CYAN, WHITE,
WHITE, RED, NoActual);
Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY, CYAN, WHITE,
WHITE, RED, Actual);
Invocar = 0;
Xm=PosX[Pos]+1;
Ym=Fila+DeMas;
}
MostrarCursorMouse();
do{
Click = ClickMouseEnXY(Xm,Ym);
if(Ym>=Fila && Ym<=Fila+textheight("H")+10){
i=0;
while(i<MaxOp && !(Xm>PosX[i] &&
Xm<PosX[i]+textwidth(Op[i])+DeMas))
i++;
if(i<MaxOp){
if(Click)//
Se hizo "click" en recuadro del men
Invocar = 1;
if(i!=Pos){
Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,NoActual);
Pos=i;
EscribirComentarioOpcionMenu(Comentario[Pos]);

Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,Actual);
}
}
}
} while (!kbhit() && !Click);
if(!Click){ //Se digit del teclado
Tecla = getch();
if(Tecla == 0 ){
Tecla = getch();
switch(Tecla){
case Der:
Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,NoActual);
EscribirComentarioOpcionMenu(Comentario[Pos]);
Pos++;
if(Pos == MaxOp) Pos=0;
EscribirComentarioOpcionMenu(Comentario[Pos]);

Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,Actual);
break;
case Izq:
Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,NoActual);

136

EscribirComentarioOpcionMenu(Comentario[Pos]);

Pos--;
if(Pos == -1)
Pos = MaxOp-1;
EscribirComentarioOpcionMenu(Comentario[Pos]);

Cursor(PosX[Pos],Fila,0,Op[Pos], LIGHTGRAY,
CYAN, WHITE, WHITE, RED,Actual);
break;
case 45: return; //
Alt-X
case 59:
//F1
break;
}
}
else{

//Se digit una tecla del teclado con cdigo ASCII


if(Tecla==Esc)
return;
if(Tecla==Entrar)
Invocar = 1;
else{
Tecla=AMayuscula(Tecla);
i=0;
while(Tecla!=Op[i][0] &&
i<MaxOp)
i++;
if(i<MaxOp){ // digit letra inicial de opcin
if(i!=Pos){

EscribirComentarioOpcionMenu(Comentario[Pos]);

Cursor(PosX[Pos],Fila,0,Op[Pos],
LIGHTGRAY, CYAN, WHITE, WHITE,
RED,NoActual);
Pos=i;
Cursor(PosX[Pos],Fila,0,Op[Pos],
LIGHTGRAY, CYAN, WHITE, WHITE,
RED,Actual);
}
Invocar=1;
}
}
}
}
if(Invocar){
UndidoCursor(PosX[Pos],Fila,0,Op[Pos],
LIGHTGRAY, CYAN, WHITE, 15, RED);
EsconderCursorMouse();
setfillstyle(SOLID_FILL, BLUE);
bar(1,1, 638, Fila-2);
setcolor(WHITE); rectangle(1,1, 638, Fila-2);
switch(Pos){
case 0:randomize();
for(int j=0; j<Max; j++){
Vector[j] = random(100)+1;
Aux[j] = Vector[j];
}
N=Max;
GraficarValores(Vector, N, -1, -1);
setfillstyle(SOLID_FILL, BLUE);
bar(getmaxx()-111, getmaxy()-31,
getmaxx()-1, getmaxy()-1);
setcolor(YELLOW);

137

case

case

case

case

settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);


outtextxy(getmaxx()-110, getmaxy()-30, "Tiempo");
break;
1: for(j=0; j<N; j++)
Vector[j] = Aux[j];
GraficarValores(Vector, N, -1, -1);
TiempoInicial = clock();
SorteoPorSeleccionRecursiva(Vector, 0, N);
TiempoFinal = clock();
ostrstream(Cad, 80)
<<(TiempoFinal-TiempoInicial)/CLK_TCK
<< " seg." << ends;
setfillstyle(SOLID_FILL, BLUE);
bar(getmaxx()-111, getmaxy()-31,
getmaxx()-1, getmaxy()-1);
setcolor(YELLOW);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
outtextxy(getmaxx()-110, getmaxy()-30, Cad);
break;
2: for(j=0; j<N; j++)
Vector[j] = Aux[j];
GraficarValores(Vector, N, -1, -1);
TiempoInicial = clock();
QuickSort(Vector, 0, N-1);
TiempoFinal = clock();
ostrstream(Cad, 80) << (TiempoFinal
TiempoInicial)/CLK_TCK
<< " seg." << ends;
setfillstyle(SOLID_FILL, BLUE);
bar(getmaxx()-111, getmaxy()-31,
getmaxx()-1, getmaxy()-1);
setcolor(YELLOW); settextstyle(DEFAULT_FONT,
HORIZ_DIR, 1);
outtextxy(getmaxx()-110, getmaxy()-30, Cad);
break;
3: for(j=0; j<N; j++)
Vector[j] = Aux[j];
GraficarValores(Vector, N, -1, -1);
TiempoInicial = clock();
MergeSort(Vector, 0, N-1);
TiempoFinal = clock();
ostrstream(Cad, 80) <<(TiempoFinal
TiempoInicial)/CLK_TCK
<< " seg." << ends;
setfillstyle(SOLID_FILL, BLUE);
bar(getmaxx()-111, getmaxy()-31,
getmaxx()-1, getmaxy()-1);
setcolor(YELLOW);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
outtextxy(getmaxx()-110, getmaxy()-30, Cad);
break;
4: for(j=0; j<N; j++)
Vector[j] = Aux[j];
GraficarValores(Vector, N, -1, -1);
TiempoInicial = clock();
Burbuja(Vector, N);
TiempoFinal = clock();
ostrstream(Cad, 80) <<(TiempoFinal
TiempoInicial)/CLK_TCK

138

<< " seg." << ends;


setfillstyle(SOLID_FILL, BLUE);
bar(getmaxx()-111, getmaxy()-31,
getmaxx()-1, getmaxy()-1);
setcolor(YELLOW);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
outtextxy(getmaxx()-110, getmaxy()-30, Cad);
break;
}
MostrarCursorMouse();
}
Click=0; Tecla=0;
//
for(;;);

}
}
/****************************************************************************/

139

SEGUNDA PARTE
ESTRUCTURAS AUTOREFERENCIADAS.
LISTAS ENLAZADAS.
VARIABLES EN MEMORIA DINAMICA.

EDUCACION LIBERADORA
En la educacin hay que poner el
acento en el amor, no en el temor:
"Procura ms bien hacerte amar,
que hacerte temer".
(San Juan Bosco.)
El amor nos da personas
sinceras, el temor incita a mentir y
acaba con la confianza.
El amor inpulsa a nios y
jovenes a ser decididos, y positivos;
el temor engendra seres
acomplejados y pesimistas.
Quien educa con el amor sabe
corregir e imponer sanciones sin
injusticias, amenazas, ni malos
tratos.
En la educacin hay que poner el
acento en la autonoma, no en la
dependencia. Se educa para liberar
no para esclavizar.
Una educacin liberadora forma
al individuo desde nio para que
tome decisiones y sea artfice de su
vida.
Supone trazar lmites, pero no
aquellos que brotan de la
sobreproteccin, el egosmo o los
celos.
Implica saber correr riesgos y no
tener a los seres como posesin.
Eduquemos para una libertad responsable.
GONZALO GALLO GONZALEZ
"CUATRO AMORES"

140

Primera Parte

Segunda Parte

Tercera Parte

141

PILA COMO LISTA ENLAZADA


1. INTRODUCCIN
Como ya habamos visto, una pila es una estructura de datos lineal, en la cual
sus
elementos solo pueden ser
insertados
y eliminados por
la cima.
Implementaremos una pila como una lista simplemente enlazada y en memoria
dinmica y en la cual cumpliremos la condicin de toda pila: "El ltimo elemento
que entra es el primero que sale". La implementacin de los algoritmos bsicos de
insertar y eliminar las llamaremos Meter() y Sacar() respectivamente.
Se emplear en el diseo de los algoritmos correspondientes que manejarn la
pila las siguientes definiciones:
typedef struct INFO INFO; // informacin que se colocar en pila
typedef struct PILA PILA; //Cada nodo de la pila
struct INFO{
char Nombre[20];
int Edad;
float Altura;
}
struct PILA{
INFO Info; // informacin en la pila
PILA *Ant; //anterior nodo de la pila
} *Cima = NULL;
La nica variable que se mantendr en forma global ser el puntero (A pila)
Cima.
2. FUNCION INSERTAR EN PILA: METER
En la primera invocacin a la funcin meter, que estamos disendo, el puntero a
la pila Cima est en NULL, es decir est vaca. Con la instruccin, operador, new
del C++ se asignar espacio en la parte de la memoria dinmica, de la siguiente
forma:
Cima = new (Pila);
Cima

0x1000

0x1000

Datos en pila Info


puntero Ant

la anterior es la correspondiente abstraccin en RAM, y suponiendo


direccin en memoria RAM de 0x1000 asignada a Cima y disponible de utilizar.

la

new a asignado el valor entero de 0x1000, esto es solo una suposicin para
explicar lo ocurrido, al puntero Cima. Diremos que Cima vale 0x1000. De esta
forma Cima apunta a la direccin de memoria, en RAM, de 0x1000; en esta direccin
y con un desplazamiento (offset) en bytes dado por el tamao de struct PILA. En
este momento las posiciones de memoria que inician en 0x1000 tendrn "basura". Se
deber proceder a asignar informacin al campo de Info y al puntero ant, por
medio de alguna operacin adecuada.

142

Supongamos el siguiente cdigo para la asignacin a la posicin acabada de


generar dinmicamente, y la correspondiente abstraccin en forma de recuadros en
RAM:
LeerRegistro(&Cima->Info);
Cima->Ant = NULL;

Cima

0x1000

0x1000

Carolina

16

1.56

NULL

Datos en pila Info


puntero Ant

En esta primera invocacin de la funcin meter es todo lo que debe hacer,


observe que la lista enlazada que representar la pila inicia en Cima, el cual
apunta al primer nodo, en el que esta Carolina, en este nodo el puntero Ant est
en NULL, indicando que la lista termina all.
Supongamos una nueva invocacin de la funcin meter. En esta y en posteriores
invocaciones es necesario utilizar una variable auxiliar de tipo puntero a PILA
para cada uno de los nuevos nodos, la llamaremos Nuevo como veremos a
continuacin:
PILA *Nuevo;
A continuacin tomamos memoria dinmica con el operador new, asignndoselo a
Nuevo:
Nuevo = new PILA;
A continuacin se deber asignar informacin al campo de Info, por medio de
la funcin de lectura: LeerRegistro(&Nuevo->Info) correspondiente, quedando en
RAM, as:

Cima

0x1000

0x1000

Carolina

16

1.56

NULL

0x1050

Tania

23

1.55

NULL

Nuevo

0x1050

Para efectuar el enlace de este nuevo nodo y que quede la lista enlazada
representando una pila, procedemos por medio de la siguiente instruccin:
Nuevo->Ant = Cima;

Cima

0x1000

Carolina

0x1050

Tania

Nuevo

143


0x1000

16

1.56

NULL

23

1.55

0x1000

0x1050

a continuacin actualizamos el valor de Cima, y rearreglando la figura de la


abstrccin:
Cima = Nuevo;

Cima

0x1050

0x1050

Tania

23

1.55

0x1000

0x1000

Carolina

16

1.56

NULL

Nuevo

0x1050

Resumiendo el cdigo de la funcin meter, en una primera versin, es el


siguiente:
Meter(){
PILA *Nuevo;
if(!Cima){ // Pila est vaca
Cima = new Pila;
LeerRegistro(&Cima->Info);
Cima->Ant = NULL;
}
else{
// caso general
Nuevo = new PILA;
LeerRegistro(&Nuevo->Info);
Nuevo->Ant = Cima;
}
}
Observando el anterior cdigo, para cuando la pila est vaca y el caso
general, se ve que se puede resumir al caso general, como a continuacin se
presenta, agregando la validacin del caso de memoria llena:
Meter(){
PILA *Nuevo;
Nuevo = new PILA;
if(Nuevo){ // Hay espacio en RAM para el nuevo nodo de Pila
LeerRegistro(&Nuevo->Info);
Nuevo->Ant = Cima;
}
else

144

cout << "MEMORIA LLENA";


}
Como ejemplo verifique la insercin de otro nodo, usted mismo, y que queda en
memoria RAM de la siguiente forma:

Cima

0x1100

0x1100

Valentina

0.75

0x1050

0x1050

Tania

23

1.55

0x1000

0x1000

Carolina

16

1.56

NULL

Nuevo

0x1100

3. FUNCION ELIMINAR DE PILA: SACAR


De una pila siempre se deben eliminar el elemento que est en Cima, as de la
figura anterior seguiremos los siguientes pasos:
PILA *Aux;
Aux = Cima;
Cima = Cima->Ant;
vale 0x1050

//Cima vale 0x1100


//Cima->Ant vale 0x1050, a partir de ahora Cima

Observe que a partir de ahora Cima toma el valor de 0x1050, apuntado al


siguiente nodo de la pila, y de esta forma eliminando el que estaba inicialmente
en la Cima, ms no fisicamente, solo lgicamente, as:

Cima

0x1050

Aux

0x1100

0x1100

Valentina

0.75

0x1050

0x1050

Tania

23

1.55

0x1000

0x1000

Carolina

16

1.56

NULL

Ya habr caido en cuenta el por qu de la utilizacin de la variable Aux. Se


procede a liberar la memoria dinmica apuntada por Aux con la instruccion delete,
as:
delete(Aux);

Cima

0x1050

0x1050

Tania

23

1.55

0x1000

0x1000

Carolina

16

1.56

NULL

145

Resumiendo, el correspondiente cdigo para eliminar


inplementada en una lista enlazada, es el siguiente:

un

nodo

de

la

pila

Sacar(){
PILA *Aux;
if(Cima){
Aux = Cima;
cout << "Eliminado el nodo de la persona: " << Cima->Info,Nombre << " de
la cima de la pila" << endl;
delete(Aux);
}
else
cout << "Pila est vaca";
}
4. FUNCION LISTAR ELEMENTOS EN PILA
Aunque estrictamente, siendo dogmticos, solo se debe tener acceso al elemento en
la cima de la pila, a continuacin mostramos cdigo para recorrer la lista
enlazada en la que est la pila:
ListarPila(){
Pila *p;
int N=0;
if(Cima){
p = Cima;
while (p){
N++;
cout <<p->Info.Nombre <<" tiene " <<p->Info.Edad <<" aos" << endl;
p = p->Ant;
}
cout << "En pila existen " << N << " elementos en espera\n";
}
else
cout << "Pila est vaca";
}
5. PROGRAMA DE EJEMPLO DE ESTRUCTURA DE DATOS PILA
El siguiente programa, PILALIST.CPP, implementa la estructura de datos pila como
una lista simplemente enlazada en memoria dinmica. Observe los cambios
efectuados en las funciones bsicas, buscando una mayor generalidad del cdigo y
evitar repeticiones en el mismo.
#include
#include
#include
#include
#include
#include
#include

<iostream.h>
<iomanip.h>
<fstream.h>
<conio.h>
<stdio.h>
<cadenas.h>
<graphics.h>

const char NombreArchivo[15]="PILA.LST";


struct Datos {

146

char Titulo[20];
char Autor[15];
char Cota[10];
float CostoLibro;
int NumeroEjemplares;
};
struct PILA {
struct Datos Datos;
struct PILA *sig;
} *Cima = NULL;
//--------------------------------------------------------------------------//
int MeterEnPila(Datos Item)
{ struct PILA *Nuevo;
clrscr();
Nuevo = new(PILA);
if(Nuevo==NULL)
{
cout << "\nMemoria llena" << endl;
return(0);
}
else
{
Nuevo->Datos = Item;
Nuevo->sig = NULL;
if(Cima)
Nuevo->sig = Cima;
Cima = Nuevo;
return(1);
}
}
//--------------------------------------------------------------------------//
void CapturarDatos()
{ Datos Item;
clrscr();
cout << "\nColocar un libro en pila"<< endl;
cout << "============================"<< endl;
cout << "El nombre del libro :";
gets(Item.Titulo);
cout << "El nombre del autor:";
gets(Item.Autor);
cout<<"El cdigo Dewey del libro: ";
gets(Item.Cota);
cout<<"El valor del libro: ";
cin >> Item.CostoLibro;
cout<<"Nmero de ejemplares: ";
cin >> Item.NumeroEjemplares;
MeterEnPila(Item);
}
//--------------------------------------------------------------------------//
void SacarLibroDePila()
{ struct PILA *p;
clrscr();
if(Cima==NULL)
{
cout<<"\nNo hay registros en memoria"<<endl;
}
else

147

{
cout << "\nLibro en la cima de la pila:" << endl
<< "=================================" << endl
<< "Nombre del libro: " << Cima->Datos.Titulo << endl
<< "Codigo del libro: "<< Cima->Datos.Cota << endl
<< "Valor de cada ejemplar: "<< Cima->Datos.CostoLibro << endl
<< "Nmero de ejemplares en existencia: "
<<Cima->Datos.NumeroEjemplares;
p = Cima;
Cima = Cima->sig;
delete(p);
}
getch();
}
//--------------------------------------------------------------------------//
void ListarLibrosEnPila()
{
clrscr();
if(Cima==NULL){
cout<<"No hay ningn libra en la pila";
}
else {
int NumTitulos=0, NumLibros=0;
struct PILA *p=Cima;
cout << "No. Ttulo
Autor
Cota"
<< "
Valor
Ejemplares\n\n";
while(p) {
NumTitulos++;
NumLibros += p->Datos.NumeroEjemplares;
cout << setiosflags(ios::right) << setw(2) << NumTitulos << "
"
<< setiosflags(ios::left) << setw(20) << p->Datos.Titulo
<< setw(15) << p->Datos.Autor
<< setw(10) << p->Datos.Cota
<< setiosflags(ios::right | ios::showpoint | ios::fixed)
<< setprecision(2) << setw(15) << p->Datos.CostoLibro
<< setiosflags(ios::right)
<< setw(8) << p->Datos.NumeroEjemplares << endl;
p = p->sig;
}
cout << "\nTotal de ttulos: " << NumTitulos
<< "\nTotal de libros en existencia: " << NumLibros;
}
}
//--------------------------------------------------------------------------//
void ConsultarDatoEnPila()
{
char item[20];
clrscr();
if(Cima==NULL)
cout<<"No hay libros en la Pila";
else {
cout<< "Digite el nombre del libro que desea buscar: ";
gets(item);

148

struct PILA *p;


p = Cima;
while(p && CompararCadenas(item,p->Datos.Titulo)!=0)
p=p->sig;
if(!p)
{
cout<<"No encontrado";
}
else
{
cout << "\nTiene el cdigo: " << p->Datos.Cota
<< " un valor de $" << p->Datos.CostoLibro
<< " y hay " << p->Datos.NumeroEjemplares << " ejemplares";
}
}
getch();
}
//--------------------------------------------------------------------------//
void ListaInversaPila(PILA *p) // se efectan invocaciones recursivas
{
if (p)
{
clrscr();
ListaInversaPila(p->sig);

// invocacin recursiva

cout << setiosflags(ios::left) << setw(20) << p->Datos.Titulo


<< setw(15) << p->Datos.Autor
<< setw(10) << p->Datos.Cota
<< setiosflags(ios::right | ios::showpoint | ios::fixed)
<< setprecision(2) << setw(15) << p->Datos.CostoLibro
<< setiosflags(ios::right) << setw(6) << p->Datos.NumeroEjemplares
<< endl;
}
}
//--------------------------------------------------------------------------//
void CargarDesdeDiscoPila(){
fstream Archivo;
Datos Registro;
Archivo.open(NombreArchivo,ios::in|ios::binary);
if(Archivo){
Cima = NULL;
while(Archivo.read( (char *)&Registro, sizeof(Registro) ) )
MeterEnPila(Registro);
Archivo.close();
}
}
//--------------------------------------------------------------------------//
void GrabarPilaEnDisco(){
fstream Archivo;
Archivo.open(NombreArchivo, ios::out|ios::binary|ios::trunc);
if (!Archivo)
cout << "Error en la apertura del archivo \a";
else{

149

struct PILA *p, *q;


p = Cima;
while ( p ) {
Archivo.write((char *)&p->Datos, sizeof(p->Datos));
q = p;
p = p->sig;
delete(q);
}
Archivo.close();
}
}
//--------------------------------------------------------------------------//
void GraficarInfoPila(){
int ManejadorGrafico = DETECT, ModoGrafico;
int izquierda, arriba, ancho, abajo, profundidad;
int NumeroTitulos=0;
float porcentaje, SumaNumeroEjemplares=0;
PILA *p;
initgraph( &ManejadorGrafico, &ModoGrafico, "c:\\tc\\bgi" );
setbkcolor(BLUE); cleardevice();
setcolor(WHITE); rectangle(0, 0, getmaxx(), getmaxy());
if (Cima){
p = Cima;
while (p){
SumaNumeroEjemplares += p->Datos.NumeroEjemplares;
NumeroTitulos++;
p = p->sig;
}
ancho = (int)( (getmaxx()) / ((NumeroTitulos * 2 ) + 1) );
abajo = getmaxy() - 30;
profundidad = (int) (ancho / 8);
izquierda = ancho;
setcolor(YELLOW); settextstyle(1,0,10);
outtextxy(getmaxx()/8, getmaxy()-10 , "TITULOS");
p = Cima;
while(p){
porcentaje =(float) p->Datos.NumeroEjemplares / SumaNumeroEjemplares;
arriba = 30;
arriba = (abajo) - ( (int)(porcentaje * (abajo-arriba) ) );
setcolor(RED); setfillstyle(SOLID_FILL,MAGENTA);
bar3d(izquierda, arriba, (izquierda + ancho), abajo, profundidad, 1);
setcolor(CYAN);
settextstyle(SMALL_FONT,1,0);// (tipo letra, direccion, tamao )
outtextxy(izquierda+ancho/2, arriba, p->Datos.Titulo);
izquierda += (ancho * 2);
p = p->sig;
}
}
else{
setcolor(RED);
settextstyle(GOTHIC_FONT,0,8);
outtextxy(10, getmaxy()/2 , "NO HAY DATOS");
}

150

getch();
closegraph();
}
//--------------------------------------------------------------------------//
void main(){
int opcion;
CargarDesdeDiscoPila();
for(;;){
ListarLibrosEnPila();
cout << "\n\nMeter Sacar

Consultar Recursin Graficar Terminar: ";

opcion = AMayuscula( getch() );


switch (opcion) {
case 'M' : CapturarDatos();
break;
case 'S' : SacarLibroDePila();
break;
case 'C' : ConsultarDatoEnPila();
break;
case 'R' : ListaInversaPila(Cima);
getch();
break;
case 'G' : GraficarInfoPila();
break;
case 'T' : GrabarPilaEnDisco();
return;
}
}
}
PROGRAMA A REALIZAR COMO EJERCICIO
Con el programa de CONCENTR.CPP como modelo y herramienta, muestre mazo de cartas
arrumado en forma de pila. Al colocar cada carta, generada al azar, sobre una
mesa, se debe ir almacenando en una estructura de datos Pila (implementada como
una lista enlazada y en memoria dinmica), para cuando se quiera ser retirada de
encima del maso de cartas la ltima puesta en l.

151

COLA COMO UNA LISTA ENLAZADA


1. INTRODUCCIN
Como ya hemos visto una cola es una estructura de datos en la cual sus
elementos solo pueden ser insertados por un extremo y eliminados por el otro. En
toda cola el primero que llega ser atendido primero. Para la implementacin de
la cola, en este captulo, utilizaremos la estructura de datos lista enlazada en
memoria dinmica.
La definicin de la estructura de datos estar dada por:
typedef struct INFO INFO; // informacin que se colocar en cola
typedef struct COLA COLA; //Cada nodo de la cola
struct INFO{
char Nombre[20];
int Edad;
float Altura;
}
struct COLA{
INFO Info; // informacin en espera en la cola
COLA *Atras; //siguiente nodo de cada elemento en cola
} *Frente = NULL, *Final=NULL;
Se mantendrn en memoria RAM dos variables globales, los punteros a COLA:
Frente y Final.
2. FUNCION DE INSERTAR EN COLA
Al inicio del programa la cola estar vaca, as mismo cuando posteriormente
durante la ejecucin del programa podra ser que en algn momento quedar vaca,
en estas dos circunstancias Frente estar en NULL. Para la insercin se presenta
el caso especial siguiente:
if (Frente == NULL){
Frente = new COLA;
La instruccin new efectur lo siguiente en RAM:

Cima

0x2000

0x2000

Datos en cola Info


puntero Atras

A continuacin se debe asignar la informacin del nodo y al campo de puntero


Atras asignarle NULL. Como queda en cola un solo nodo, al puntero Final deberemos
asignarle el mismo valor de Frente, veamos el cdigo y el correspondiente dibujo:
if(Frente == NULL){
Frente = new COLA;
LeerRegistro(&Frente->Info.Nombre);

152

Frente->Atras = NULL;
Final = Frente;
}

0x2000

Vanessa

Final

10

0x2000

1.4

NULL
Puntero Atras

Frente

0x2000

Recuerde que la instruccin new, asigna al puntero Frente, una direccin de


memoria dinmica en RAM, a partir de esta direccin y con un desplazamiento dado
por el tamao en bytes de la struct COLA, ser reservado, y es all donde le
asignaremos valores para cada registro de la lista enlazada que manejar la
estructura de datos cola. Al insertar otro nodo cuando ya existe al menos uno, es
necesario utilizar una vaariable auxiliar que llamaremos *Nuevo:
COLA *Nuevo;
Nuevo = new COLA;
Nuevo->Atras = NULL;
LeerRegistro(&Nuevo->Info);

Frente

0x1500

0x1500

Vanessa

Final

10

0x1500

1.40

NULL
Puntero Atras

0x2000

Marcela

Nuevo

13

0x2000

1.65

NULL
Puntero Atras

Para que este nuevo nodo llegue al final de la cola, debemos codificar las
instrucciones:
Final->Atras = Nuevo;
Final = Nuevo;
Frente

0x1500

0x1500

Vanessa

10

1.40

0x2000

0x2000

Marcela

13

1.65

NULL

Final

0x2000

En resumen el cdigo para inseertar un nodo en una lista enlazada y que


represente la abstraccin de la estructura de datos cola ser:
InsertarEnCola(){
COLA *Nuevo;
if(Frente == NULL){

153

Frente = new COLA;


LeerRegistro(&Frente->Info.Nombre);
Frente->Atras = NULL;
Final = Frente;
}
else{
Nuevo = new COLA;
LeerRegistro(&Nuevo->Info.Nombre);
Nuevo->Atras = NULL;
Final = Nuevo;
}
Observe que es posible hacerle al algoritmo algunas simplificaciones,
reescrbalo usted mismo como ejercicio. Y verifique insertando otro nuevo nodo de
tal suerte que quede la cola como la mostrada a continuacin:

Frente

0x1500

0x1500

Vanessa

10

1.4

0x2000

0x2000

Marcela

13

1.65

0x2500

0x2500

Natalia

0.9

NULL

Final

0x2500

3. FUNCION ELIMINAR DE COLA: ATENDER


Con la funcin Atender se eliminar un nodo de la estructura de datos cola.
Recuerde que para cumplir el requisito de la cola: "El primero que entra el
primero que sale", siempre debemos eliminar el nodo apuntado por la variable
Frente; con la figura anterior tendremos:
0x1500

Vanessa

10

1.4

0x2000

Frente

0x2000

0x2000

Marcela

13

1.65

0x2500

0x2500

Natalia

0.9

NULL

Final

0x2500

cout << "Atendido: " << Frente->Info.Nombre << " del frente de la cola" <<
endl;
Aux = Frente;
Frente = Frente->Atras;
A continuacin el nodo apuntado por
quedando en definitiva toda la funcin as:

Aux,

deber

liberarse

con

delete,

AtenderCola(){
if(Frente){
cout << "Atendido: " << Frente->Info.Nombre
<< " del frente de la cola" << endl;
Aux = Frente;
Frente = Frente->Atras;
delete (Aux);
}

154

else
cout << "Cola vaca";
}
Como ejercicio elimine uno por uno los dos nodo que quedan en el dibujo
anterior, observe que el cdigo sigue funcionando cuando la cola est vaca, est
bien seguro de esto.
4. FUNCION LISTAR ELEMENTOS EN COLA
Aunque estrictamente, siendo dogmticos, solo se debe tener acceso al elemento
del Frente de la cola, a continuacin mostramos cdigo para recorrer la lista
enlazada en la que est la cola:
ListarCola(){
COLA *p;
int N=0;
if(Frente){
p = Frente;
while (p){
N++;
cout <<p->Info.Nombre <<" tiene " <<p->Info.Edad <<" aos" << endl;
p = p->Atras;
}
cout << "En cola existen " << N << " elementos en espera\n";
}
else
cout << "Cola est vaca";
}
Si ha entendido hasta aqu, notar que los algoritmos con listas enlazadas
son mucho ms simples que los correspondientes a los efectuados con vectores.
5. PROGRAMA DE APLICACION DE LA ESTRUCTURA DE DATOS COLA
Programa de estructura de datos cola, implementada como una lista simplemente
enlazada en memoria dinmica. Sehan utilizado las instrucciones tradicionales del
C: malloc, en vez de new, y free(en vez de delete), y as mismo el observe el
manejo de archivos con el archivo a incluir fcntl.h.
//COLALIST.CPP
#include <iostream.h>
#include <stdlib.h> // NULL
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <ctype.h>
#define ARCHIVO "AGENDA.CLT"
typedef struct INFO INFO;
typedef struct NODO NODO;
struct INFO{

155

int edad;
char nombre[25];
};
struct NODO{
INFO info;
NODO *sig;
} *Frente=NULL, *Final=NULL;
const int BytesNodo=sizeof(NODO);
void Insertar (){
NODO *Nuevo;
if ( (Nuevo =(NODO *) malloc(BytesNodo) ) == NULL )
cout <<"No hay memoria suficiente";
else{
cout <<"\n\nDigite nombre: ";
gets(Nuevo->info.nombre);
cout <<"Digite edad: ";
cin >> Nuevo->info.edad;
Nuevo->sig = NULL;
if(!Frente)
Frente = Nuevo;
else
Final->sig = Nuevo;
Final = Nuevo;
}
}
void Eliminar(){
NODO *q;
if (!Frente)
cout <<"\nNo hay INFO";
else{
q = Frente;
Frente = Frente->sig;
cout <<"\nEliminado: "<<q->info.nombre<<" de " <<q->info.edad <<" aos";
free(q);
}
getch();
}
void GrabarColaLista(){
int NArch;
NODO *p, *q;
NArch = _creat(ARCHIVO, 32); _close(NArch);
NArch = _open(ARCHIVO, O_WRONLY);
p = Frente;
while ( p ) {
_write( NArch, (char *)&p->info, sizeof(p->info) );
q = p;
p = p->sig;
free(q);
}
_close(NArch);

156

}
void CargarColaLista(){
int NArch;
NODO *Nuevo;
if ( (NArch = _open(ARCHIVO, O_RDONLY) ) == -1){
cout <<"Archivo no existe \a"; delay(1000);
}
else{
Frente = Final = NULL;
Nuevo = (NODO *) malloc(BytesNodo);
while ( _read(NArch, (char *)&Nuevo->info, sizeof(Nuevo->info) )!=0) {
Nuevo->sig = NULL;
if (!Frente)
Frente = Final = Nuevo;
else
Final = Final->sig = Nuevo;
Nuevo =(NODO *) malloc(BytesNodo);
}
_close(NArch);
}
}
void ListarCola(){
NODO *p;
clrscr();
p = Frente;
while(p){
cout << p->info.nombre << " " << p->info.edad << "\n";
p = p->sig;
}
}

157

void main(){
char op;
CargarColaLista();
do{
ListarCola();
cout <<"\nInsertar
Eliminar
op = toupper(getch());
switch (op){
case 'I':Insertar();
break;
case 'E':Eliminar();
break;
}
} while (op != 'T');
GrabarColaLista();

Terminar: ";

}
A continuacin prueba de
anterior progrma COLALIST.CPP
Frente

Null

Nuevo

1000

Final

Null

1000

13

CAROLINA

NULL

ejecucin

manual

de

la

funcin

Insertar()

del

NODO

info.edad

info.nombre

*sig

Se digitan edad, nombre y se


asigna NULL a nuevo->sig a
continuacin.

a continuacin la instruccin if(!Frente) equivale a if(!NULL) que es verdadero,


la cola est vaca, por esto sigue en:
Frente=Nuevo;
y luego
Final=Nuevo; quedando en memoria y terminando la funcin:

Frente

1000

Final

1000

Nuevo

1000

1000

13

CAROLINA

NULL

En una nueva invocacin, si digitamos edad 21, Nombre TANIA tendremos:

158

Frente

1000

Final

1000

Nuevo

2000

La instruccin if(!Frente)
se pasa a evaluar la parte
quedando en memoria:

1000
2000

13

21


CAROLINA TANIA

NULL

NULL


equivale a if(!1000), el cual es falso, por esto
de else: final->sig=Nuevo, y luego Final=Nuevo;

1000
2000

13

21


CAROLINA TANIA

2000
>
NULL
->Nuevo sig

En una
memoria:

tercera

invocacin,

1000
2000

13

21


CAROLINA TANIA

2000
>
NULL


Final->sig

Frente

1000

digitamos

edad

Nuevo

2000

23

3000

Frente

23

1000
NELCY

NULL
->Nuevo sig

Final

2000

Nombre

NELCY

Final

2000

quedando

en

Nuevo

3000

La instruccin if(!Frente) es falsa, ya hay nodos en la lista, por esto en el


else a Final->sig=Nuevo y luego a Final=Nuevo de la siguiente forma:
Frente

1000

Final

3000

1000
2000
3000

13

21

23


CAROLINA TANIA
NELCY

2000
>
3000
>
NULL

Nuevo

3000

Efecte otras dos


inserciones ms
para estar seguro
que entendi.

Efectuemos una invocacin ahora a la funcin Eliminar(); la instruccin if(!


Frente) es falsa por esto el algoritmo continuar en else{
q= Frente

159

Frente=Frente->sig
q
Frente
Final

1000
2000
3000

1000
2000
3000

13

21

23


CAROLINA TANIA
NELCY

2000
>
3000
>
NULL


siguiendo en pantalla "Eliminando CAROLINA de 13 aos" y la direccin del Nodo a
que apunte q quedando:
q

1000

Frente

2000

2000
3000

21

23


TANIA
NELCY

3000
>
NULL

Final

3000

Ensaye a eliminar los otros dos nodos, mostrando su secuencia.


PROGRAMA A REALIZAR COMO EJERCICIO
Con el programa del captulo anterior sobre pilas, efectuado a partir de
CONCENTR.CPP el cual muestra baraja francesa arrumada en forma de pila. Retire
una carta cada vez y colquela sobre "la mesa" una al lado de la otra con la cara
hacia arrriba y como si estuvieran en cola, claro que debe haber un mximo de
cartas a colocar de esta forma, para luego retirarlas a la manera como se hace en
una cola y devolverlas a la pila.

160

LISTA ENLAZADA ORDENADA


Una lista enlazada es un
por medio de punteros.
variable; esta variable
informacin o datos del
lista. La abstraccin es

conjunto de nodos los cuales entn encadenados entre s


Cada nodo de la lista enlazada es un valor de una
est compuesta bsicamente de dos campos: el campo de
nodo y el campo del puntero al siguiente nodo en la
la siguiente:

INFO

*Puntero

El campo de INFO contendr el nmero de subcampos que se crea conveniente,


dependiendo del sistema de datos a modelar; en las explicaciones siguientes se
considera este campo como de un solo subcampo y de tipo caracter, de esta forma
el registro a representar tendr la siguiente sintaxis:
struct NODO{
char info;
NODO *sig;
} *Cab=NULL;
de esta forma se ha definido una variable puntero, Cab, la cual deber
apuntar a una variable de tipo NODO. Cab es abreviatura de la palabra cabeza, el
inicializarla en NULL(nulo) nos da a entender que la lista enlazada est vaca.
Cab

nulo

la lista est vaca

una de las desventajas de las listas simplemente enlazadas est en el hecho


de que para accesar cualquier nodo de la lista se debe recorrer siempre empezando
por el nodo de cabeza, Cab. A manera de aproximacin veamos una serie de
operaciones las cuales podramos realizar sobre una lista simplememte enlazada y
clasificada por la clave info:
Despus de la insercin de un item D:
2500
Cab

D
2500->
una lista con un solo NODO

nulo

Se inserta un item E:
Cab

2500-->

2500

3000 -->

3000

nulo

una lista con dos NODOS

161

Se inserta un item B:

4000

2500 -->

Se inserta un item M:
4000
Cab

B
4000-->

2500 -->

Cab

4000-->

2500

3000 -->

3000

nulo

2500

3000 -->

3000

4500 -->

4500

nulo

Se inserta un item H:
4000
Cab

B
4000-->

2500 ->

2500

3000 ->

3000

5000 ->

5000

4500 ->

4500

nulo

Eliminacin de un nodo con info E:


Cab

4000-->

4000

2500 -->

2500

5000 -->

5000

4500 -->

4500

nulo

Eliminacin de un nodo con info B:


Cab

2500-->

2500

5000 -->

5000

4500 -->

4500

nulo

ALGORITMO DE INSERCION EN LISTA ENLAZADA CLASIFICADA ASCENDENTEMENTE:


El algoritmo para la insercin de valores en una lista simplemente enlazada y
clasificada en orden ascendente por una clave es el siguiente:
p = nulo;
//punteros auxiliares para recorrer lista
q = Cab;
Nuevo = new NODO;
//se crea un Nuevo NODO

162

Nuevo->sig = nulo;
Nuevo->info = item;
while(q && item>q->info)
{
p = q;
q = q->sig;
}
if(!p)
{
//se inserta de primero el Nuevo NODO
Nuevo->sig = Cab;
Cab = Nuevo;
}
else
{
if(!q)
// se inserta de ltimo el Nuevo NODO
p->sig = Nuevo;
else
{
p->sig = Nuevo; //se inserta intermedio en lista
Nuevo->sig = q;
}
}
Para la explicacin del algoritmo supondremos, por conveniencia, se encuentra en
memoria la siguiente lista enlazada:
Cab

1000->

1000

2000 -->

2000

3000 -->

3000

1500 -->

1500

nulo

1. Se inserta a continacin un item I:


p = nulo;
//punteros auxiliares para recorrer lista
q = Cab;
Nuevo = new (NODO);
//se crea un nuevo NODO
Nuevo->sig = nulo;
Nuevo->info = item;
quedando en memoria RAM segn la siguiente abstraccin:
Cab

1000->

nulo

1000

2000 ->

1000

2000

3000 ->

item

3000

1500 ->

1500

nulo

4000

nulo

Nuevo

4000

p y q son punteros auxiliares con los cuales recorreremos la lista, buscando


el sitio donde debe quedar el nuevo item, 'I' a insertar; y segn el siguiente
cdigo:

163

While ( q && item > q->info)


reemplazando:
1000 && 'I' > 'B'
es verdadero
al ser verdadero el While, se entrar en su mbito y se producir
ejecucin de las instrucciones p=q; q=q->sig, imaginemos la situacin:
Cab

1000->

1000

2000 ->

1000

2000

3000 ->

2000

3000

1500 ->

1500

nulo

item

la

4000

nulo

Nuevo

4000

El flujo del programa se dezplaza de nuevo a la instruccin while:


While ( q && item > q->info )
2000 &&
'I' > 'E'
son verdaderos ambos
A continuacin avanzan los punteros con las instrucciones p=q;
1000
2000
3000
1500
4000
cab

B
E G N
I
1000-->

2000-> 3000 ->1500 ->nulo


nulo

item
p
q
Nuevo

I
2000
3000
4000

q=q->sig;

una vez ms el flujo del algoritmo se traslada a:


While ( q && item > q -> info )
3000 && 'I' > 'G'
verdaderos ambos,
de esta forma p y q avanzarn:
1000
cab

B
1000-->

2000 ->

item

2000
3000
1500

E G N

3000 ->1500 ->nulo

p
q

3000 1500

4000

nulo

Nuevo

4000

nuevamente pasamos arriba al mientras:


while ( q && item > q->info )
1500 && 'I' > 'N'
verdadero && falso
esta conjuncin ser falsa

164

hemos as llegado a la terminacin de la instruccin mientras, observamos que


p apunta al nodo anterior a donde debe quedar el nuevo nodo con info 'I', y q
apunta al nodo que debe quedar despus de l.
La siguiente instruccin if(!p) se evaluar como falsa ya que p tiene
almacenada la direccin de 3000, continuamos en su correspondiente else as:
else
if (!q)
!1500 se evaluara como falso
este if es falso debido a qu q almacena el valor de 1500, por esto nos
desplazamos al siguiente else, y all se inserta el nuevo nodo con las
instrucciones:
else{
p->sig = Nuevo;
Nuevo->sig = q;
}
quedando la lista enlazada as:
cab

1000-->

1000

2000->

item

2000
3000

E G

3000 ->4000

p

3000

1500

nulo <
q

1500

4000

1500

Nuevo

4000

reorganizando nuestro dibujo la abstraccin que tenemos de ella es:


cab

1000-->

1000

2000->

2000

3000 ->

item

3000

4000 ->

3000

4000

1500 ->

nuevo

4000

1500

nulo

1500

Se insertar ahora un item 'A':


5000

nulo

p
nuevo

nulo
5000

nuevo

5000

item

p = nulo;
q = Cab;
Nuevo = new (NODO);
Nuevo->sig = nulo;
Nuevo->info = item;
q

1000

165

1000

2000->

cab

1000-->

2000

3000 ->

3000

4000 ->

4000

1500 ->

1500

nulo

While ( q && item > q->info )


1000 && 'A' > 'B'
Es falso
en consecuencia no entra al while, se observa que el nuevo nodo, con la clave
A, debe quedar de primero. Observe que para esto el valor de Cab tiene que
cambiar a apuntar al nuevo NODO, se sigue en el cdigo:
if(!p){ //!NULL es verdadero. Se inserta de primero el Nuevo NODO
Nuevo->sig = Cab;
Cab = Nuevo;
}
y quedando nuestra abstraccin as:
5000
1000
2000
3000
4000
1500
cab

A B E G I N
5000-->

1000 ->2000 ->3000 ->4000 ->1500 ->nulo



p
nuevo
q
item

nulo
5000
1000
A

Se inserta ahora un item Q:


nuevo

6000

6000

nulo

Observe de lo explicado antes que los


punteros p y q recorrern las siguientes posiciones, hasta que el siguiente
while se vuelva falso:

while(q && item>q->info){


p = q;
q = q->sig;
}
5000
cab

A
5000-->

1000

2000

3000

4000

1500

166

nulo

1000 ->2000 ->3000 ->4000 ->1500 ->nulo



q

5000

el while(q && item>q->info) es verdadero, 'Q' es mayor que 'A', por esto, al
entrar al while, p y q avanzarn:
5000
1000
2000
3000
4000
1500
cab

A B E G I N
5000-->

1000 ->2000 ->3000 ->4000 ->1500 ->nulo



p
q

5000
1000

de nuevo el while es verdadero, q es no nulo y 'Q' es mayor que 'B',


avanzarn p y q:
5000
1000
2000
3000
4000
1500
cab

A B E G I N
5000-->

1000 ->2000 ->3000 ->4000 ->1500 ->nulo



p
q

1000
2000

nuevamente avanzan p y q al ser el while verdadero, q es 2000 y 'Q' es mayor


que 'E':
5000
1000
2000
3000
4000
1500
cab

A B E G I N
5000-->

1000 ->2000 ->3000 ->4000 ->1500 ->nulo



p
q

2000
3000

se evala otra vez el while, siendo verdadero ya que q apunta a un valor no


nulo y 'Q' es mayor a 'G', por esto se modificarn los valores de p y q:

cab

5000->

5000
1000
2000
3000
4000
1500

A B E G I N

1000 ->2000 ->3000 ->4000 ->1500 ->nulo

167

3000

4000

volvemos arriba al while, q vale 4000 y 'Q' es mayor que 'I', es verdadero:

cab

5000->

5000
1000
2000
3000
4000
1500

A B E G I N

1000 ->2000 ->3000 ->4000 ->1500 ->nulo

p

4000

1500

una vez ms el while es verdadero, q es diferente de nulo y 'Q' es mayor que


'N', produciendo lo siguiente como abstraccin en memoria RAM:
5000
1000
2000
3000
4000
1500
cab

A B E G I N
5000->
1000 >2000 >3000 >4000 >1500 >nulo

p
q

1500 nulo

Al volver arriba al while(q && item>q->info) encontramos que se evaluar como
falso, ya que q es igual a nulo, el algoritmo de esta forma continuar,
secuencialmente en:
if(!p){
Nuevo->sig = Cab;
Cab = Nuevo;
}
else {
if(!q)
p->sig = Nuevo;

//este if es falso

//contina en este else


// es verdadero

vemos que el primer if(!p) es falso, ya que if(!1500) equivale a if(!


verdadero) es falso; de esta forma contina en el else, y as se evala el if(!q)
como if(!NULL) es if(!falso) como verdadero, producindose la asignacin p->sig =
Nuevo, y de esta forma la insercin del nodo con la clave Q en la lista enlazada,
as:
cab

5000
1000
2000
3000
4000
1500
6000

168


5000

1000

2000

3000

4000

1500

6000

nulo

p
nuevo
q

1500 6000 nulo

Aunque debiera haber sido lo primero en explicar. Insertemos a continuacin un
nodo cuando la lista simplemente enlazada est vaca. Insertemos un item 'E':
p = nulo;
q = Cab;

// Cab est en nulo

Nuevo = new (NODO);

//se crea un Nuevo NODO

Nuevo->sig = nulo;
Nuevo->info = item;
p

nulo

nulo

nuevo

2000

2000

nulo

cab

nulo

while(q && item>q->info){


al ser q igual a nulo el While es falso, se continuar el algoritmo en:
if(!p){
// se niega algo falso, por esto es verdadero
Nuevo->sig = Cab;
Cab = Nuevo;
}
la situacin en RAM es la siguiente:
p

nulo

nulo

nuevo

2000

cab

2000-->

2000

nulo

De esta forma hemos recorrido las cuatro diferentes casos de insercin de un


nuevo nodo: 1. cuando la lista est vaca, 2. cuando se inserta al inicio de la
lista. 3. cuando se inserta en posicin intermedia. 4. cuando se inserta al final
de la lista simplemente enlazada.
Aunque en nuestro ejemplo no hemos colocado valores a insertar de item
repetidos, esto es posible, y depender solo de la conveniencia del caso en
particular, verifquelo a continuacin usted mismo insertando otro item 'E'.
Cul ser la abstraccin al final?

169

0RECORRIDO RECURSIVO DE UNA LISTA ENLAZADA


Estudiemos a continuacin la funcin recursiva ListaInversa:
void ListaInversa(NODO *p){
if(p){
ListaInversa(p-sig);
cout << endl << p->info;
}
}
Para esto supongamos se encuentra en memoria la siguiente lista simplemente
enlazada:
5000
1000
2000
3000
4000
cab

A B E G I
5000-->

1000 ->2000 ->3000 ->4000 ->Nulo



P

5000
P recibe este valor, Cabeza de lista, al invocarse inicialmente

Se pasa a la instruccin: if(P) es verdadero ya que P vale 5000, sigue el


algoritmo en ListaInversa(P->sig); P apunta al nodo 5000; en el nodo 5000 el
campo sig tiene un valor de 1000, por esto se invoca recursivamente ListaInversa
pasando el permetro 1000, en memoria RAM imaginemos lo siguiente:
ListaInversa(5000)

5000

ListaInversa(1000)

1000

En esta nueva invocacin la instruccin: if(P) P vale 1000 por esto el if es


verdadero, sigue el algoritmo en ListaInversa(P->sig); P apunta al nodo 1000, en
el nodo 1000 el campo sig tiene un valor de 2000, por esto se invoca nuevamente
ListaInversa pasando el parmetro P->sig con el valor de 2000, en memoria RAM,
hasta el momento:
ListaInversa(5000)

5000

ListaInversa(1000)

1000

ListaInversa(2000)

2000

Las siguientes invocaciones recursivas producirn lo siguiente:


ListaInversa(3000)

ListaInversa(4000)

ListaInversa(NULL)

170

3000

4000

NULL

En esta ltima invocacin la instruccin: if(P) es falsa P vale NULL, de esta


forma esta llamada de la funcin terminar, volviendo a la instruccin siguiente
donde fu invocada, quedando en memoria:
ListaInversa(5000)

5000

ListaInversa(1000)

1000

ListaInversa(3000)

3000

ListaInversa(4000)

4000

ListaInversa(2000)

2000

es decir que a continuacin se ejecuta la instruccin de escritura en pantalla:


cout << endl << p->info; mostrando en pantalla el caracter 'I', el ltimo de la
lista y luego terminarse la funcin, para quedar en memoria:
ListaInversa(5000)

5000

ListaInversa(1000)

1000

ListaInversa(2000)

2000

ListaInversa(3000)

3000

estando en la funcin ListaInversa(3000) se escribir en pantalla el valor al


que apunta P, es decir 'G', se terminar la funcin y quedando ahora en memoria:
ListaInversa(5000)

5000

ListaInversa(1000)

1000

ListaInversa(2000)

2000

estando en la funcin ListaInversa(2000) se escribir en pantalla el valor al

171

que apunta P, es decir 'E', se terminar la funcin y quedando ahora en memoria:


ListaInversa(5000)

5000

ListaInversa(1000)

1000

volviendo ahora a la funcin ListaInversa(1000) se escribir en pantalla el


valor al que apunta P, es decir 'B', se terminar la funcin y quedando ahora en
memoria:

ListaInversa(5000)

5000

volvemos ahora a la funcin ListaInversa(51000) se escribir en pantalla el


valor al que apunta P, es decir 'A', se terminar la funcin y volver el flujo
del programa a la instruccin siguiente a la invocacin inicial, observandose en
pantalla la lista simplemente enlazada en orden contrario.
Ver el correspondiente cdigo fuente del la lista simplemente enlazada,
implementada en memoria din mica y clasificada por una clave en el archivo:

LISTADIN.CPP
Ejercicio de Programacin: Utilice el programa ListaDin.cpp anterior- como herramienta para realizar lo propuesto
a continuacin:
1. Colquele un men de conmutadores y manejo del mouse(es decir debe poder moverse con las flechas las
opciones), en forma grfica.
2. A la struct INFO agrguele el campo de Altura de la persona. Efecte modificaciones por esto en las
funciones de captura y de listar.
3. Efecte captura de al menos 10 registros, el archivo binario generado debe entregrmelo en un disquete.
4. Realice funcin la cual muestre en pantalla el nombre de la persona que tiene ms aos y, la que tiene menos
aos, supongamos que es nica en ambos casos.
5. Realice funcin que busqu las personas en el rango de dos estaturas digitadas por teclado. Mostrar en
pantalla y grabar en archivo de texto(Copiarlo en disquete que me entregaran).
6. Realice funcin la cual muestre en pantalla y grabe en archivo de texto, los nombres de cada una de las
personas y la diferencia que tienen cada una con la edad promedio de todas. Por ejemplo, si el promedio de
las 10 personas es 34 aos y Mara tiene 20 aos y Juan 40, debera aparecer en pantalla((observe el negativo
en Mara):
....
Mara 20
-14.
Juan 40
6
....
El promedio de las edades es 34 aos
7. Muestre en pantalla y grabe en archivo de texto(entregrmelo en disquete) los registros clasificados por edad

172

ascendentemente. Para esto defina un nuevo puntero Cab2; debe recorrer la lista en memoria, apuntada
inicialmente por Cab, e ir insertando en nuevas direcciones de memoria cada uno de los registros de las
personas. La falla de hacerlo as es que cada Nodo quedar dos veces. Pero bueno es un simple ejercicio.
8. Muestre en pantalla y archivo de texto(entregrmelo en disquete) los registros clasificados por altura
ascendentemente. Esta vez efecte la clasificacin cambiando el orden que tiene. Es decir que Cab quedar
apuntando al nodo de la persona de menor edad, este nodo apuntar a la segunda de menor edad, etctera.
Utilice al menos dos variables de tipo puntero(NODO *p, *q) con ellos debe ir desplazndose por la lista e ir
intercambiando los nodos. El algoritmo puede ser una versin de la burbuja pero no en vectores, sino
directamente sobre la lista enlazada.
9. Similar a la funcin que graficar barras representando edades(ver ListaDIN.cpp), cambie ahora a las alturas
de las personas(Observe que el cambio es de int a flot. Truco: convierta cada edad en metros a centmetros
multiplicando por 100, y efecte conversin forzada, (cast), de esta forma: AlturaCms = (int) AlturaMetros *
100;
10. Todo el programa ListaDin.CPP, con las modificaciones anteriores, grabarlo en disquete y entregrmelo. En
Word, o similar, contestar el enunciado anterior, insertando en cada caso el cdigo y los resultados
correspondientes, entregarme copia de este archivo tambin. Es decir este archivo (Segundo Parcial
Informtica III.Doc) con sus respuestas. En resumen, deben entregarme en un disquete:

Copia de este archivo con todas las respuestas: Segundo Parcial Informtica III.Doc. Para calificar
solo mirar este archivo. De los dems solo quiero que los coloquen por si veo alguna inconsistencia
y, ayudarlos a corregirla. Entonces debe estar muy bien presentado.
Copia de su versin de ListaDin.cpp (con las funciones que realiz y que corra. Las funciones que
no lo hagan, marcarlas con comentarios.)
Archivo binario con los, al menos, 10 registros capturados.
Archivos de texto de las preguntas 5, 6, 7 y 8( cuatro archivos)
En total 7 archivos.

PROGRAMAS A REALIZAR COMO EJERCICIO de Programacin por grupos


PARA TODOS LOS GRUPOS: incluir al menos lo siguiente:
-

Rehacer enunciado entregado de forma resumida y clara.


Presentar pulcramente el sangrado de todo el cdigo fuente.
Dejar separacin adecuada entre funciones, y colocarle a cada una de ellas su
objetivo.
Utilizar menes adecuados de conmutadores horizontales y verticales en los
submens.
los identificadores que utilice, defnalos autodocumentados, en ningn
momento en clave o abreviaturas que no se entiendan rpidamente.
Defina al inicio del archivo del programa todos los prototipos de las
funciones utilizadas con comentarios que documenten el mismo.
Utilizar operaciones de archivo tanto de lectura como de escritura, con los
registros con los que se trabaje.
No utilizar la librera string.h, en vez de ella construir una librera que
incluya las funciones para manejo de cadenas necesarias.
Presentar niveles de ayuda con la tecla F1 en varias partes del programa,
donde crea necesario.
Presentar estadsticas adecuadas con la ayuda del programa ESTADIST.CPP. As
mismo presente diagramas de barras con variables numricas adecuadas.
Utilizar en algunas funciones paso de parmetros por valor y por referencia a
la manera del C con punteros y tambin del C++ con el operador de direccin
&.
Presentar la informacin adecuadamente tabulada en pantalla, y con los
colores que crea ms agradables. Presentar los registros clasificados por
ms de una clave en pantalla y en papel(presente listado fsico en papel) Se
debe permitir tener la opcin de escoger varios tipos de letra para imprimir
en papel.
Efecte un informe en archivo de Word, de todo su trabajo. Debe contestar

173

cada una de las preguntas efectuadas, mostrando el listado correspondiente.


Para
esto
utilice
los
ejemplos
de
programas
dados
en:ArchivosBinariosYTexto.doc
1. Calcular la cantidad a pagar de matrcula por cada estudiante de la siguiente
forma: El total a pagar es igual a los cargos fijos ms los cargos variables. Los
Cargos fijos son de $100,000. Los Cargos Variables se calculan como un 0.1 del
patrimonio + 0.15% de la renta gravable, tomados estos datos de la
correspondiente declaracin de renta de los acudientes del estudiante. Se debe
calcular el valor de los cargos fijos, los cargos variables y el total a cancelar
por concepto de matrcula.
En cada registro, a leer inicialmente desde teclado y posteriormente grabar
en disco, para luego poder ser recuperados del mismo y de esta forma estar
disponibles en cualquier momento, encontraremos al menos los siguientes campos:
cdigo del estudiante,
nombre,
apellido,
patrimonio y
renta
Representar por medio de nodos de una lista simplemente enlazada los
registros que representan la informacin del estudiante. Debe mantener
adicionalmente una mariable global para el total de registros actuales. El
programa presentar inicialmente un un men principal de conmutadores, el cual
permita invocar funciones que hagan lo siguiente:
CAPTURAR: Leer los campos de cada registro de estudiante por teclado, cada
vez la correspondiente variable global del nmero de registros debe incrementarse
en uno.
LISTAR: presentar en pantalla un submen el cual permita listar la
informacin clasificada por las claves: cdigo del estudiantes, por apellido. El
listado debe obtener una impresin por impresora de cdigo, estudiante, renta,
patrimonio, cargos fijos, cargos variable y total de matrcula.
BUSCAR: se debe presentar un submen el cual permita invocar sendas funciones
las cuales permitan:- Digitar el cdigo del estudiante y a continuacin, y si
existe, debe aparecer en pantalla toda su informacin sobre la matrcula. Digitar el nombre de un estudiante y a continuacin, y si existe, debe aparecer
en pantalla toda su informacin sobre la matrcula. Digitar un apellido o nombre
y a continuacin presentar todos los nombres completos de estudiantes que lo
contengan.
TOTAL MATRICULA: submen que permita presentar en pantalla y escrito en
papel. Presentar listado de el total de matrculas, totalizando al final.
ESTADISTICA: presentar estadsticas de el total de matrcula, con la ayuda
del programa ESTADIST.CPP.
2. En una encuesta de un indeterminado nmero de jefes de hogar, se les pregunta
a cada uno Cul es su ingreso mensual? Cul es la renta que paga por su casa de
habitacin?. Presentar algoritmo pulcramente con sangrado adecuado en lenguaje C+
+. Debe utilizar operaciones de archivo.
ESTADISTICA: Presente submen con las cuatro opciones siguientes: presentar
estadsticas sobre los ingresos mensuales y sobre el pago de renta y el nmero de
hijos. y cuarta opcin que permita calcular y mostrar el salario promedio por
hogar, dividiendo la sumatoria de los ingresos mensuales entre el nmero de jefes

174

de hogar. Se debe calcular cantos hogares tienen ingresos superiores a tres


salarios mnimos, cuntos mayores o igual al mnimo y menores a tres salarios
mnimos y cuntos tienen ingresos inferiores al mnimo.
CAPTURA: leer los campos Cdula jefe de hogar, salario, renta, nmero de
hijos y efectundo ciclo repetitivo capturar la edad de cada uno de sus hijos,
acumularlas, para
finalmente asignar a campo de edad promedio su respectivo
valor.
LISTADOS: En submens presente listados
promedio de hijos y cdula de identificacin.

clasificados

por

salario,

renta,

BUSCAR: Submens que permitan encontrar los ciudadanos que estn en cada uno
de los rangos de salario mnimo sealados anteriormente; a partir de una cdula
mostrar los datos de la correspondiente persona. Digitar un valor de renta y
mostrar todos los registros que cumplen con que la de ellos en mayo o igual.
3. Una editorial tiene un conjunto de registros para cada uno de los ttulos de
libros existentes, cada uno de los cuales contiene: cdigo del libro, ttulo de
la obra, nombre completo del autor, nmero de pginas, y si es en rstica o de
lujo, existencia en bodega de cada ttulo. Efectuar funciones que permitan:
CAPTURAR: la captura de estos registros y mantenerlos en memoria en la lista
enlazada.
PRECIO UNITARIO: A partir de digitar el cdigo de un libro, efectuar su
bsqueda y mostrar su precio teniendo en cuanta lo siguiente: El precio bsico de
un libro es de $2.000, ms 35 pesos por pgina; empero, si el nmero de pginas
excede de 300, el precio sufrir un recargo adicional de $10; si el nmero de
pginas excede de 550, el precio se incrementar $8, y esto debido al mayor costo
de la compaginacin y empastado. Si la edicin no es en rstica, es decir es de
lujo el precio calculado hasta el momento se aumentar en un 60%.
LISTAR: Por medio de un submen mostrar en pantalla o en papel lo siguiente.
Calcular e imprimir el cdigo y el precio para cada uno de los libros,
clasificados por el cdigo del libro. Imprimir el total, en pesos, del inventario
de libros. Mostrar el mismo inventario de libros clasificados por autor. Mostrar
tambien clasificado por ttulo.
BUSCAR: Por medio de submens conteste cada uno de los siguientes
interrogantes: Se debe digitar un cdigo de libro y si existe en el inventario
decir su precio. Digitar un valor de libro y listar a continuacin todos los
libros que tienen igual o mayor precio. Digitar el nombre de un autor y a
continuacin mostrar todos los libros que le pertenescan de entre el inventario.
Digitar un ttulo de un libro y a continuacin decir cuantos ejemplares de ese
ttulo hay en existencia en el momento. Digitar un apellido o nombre y a
continuacin presentar todos los nombres completos de autores que lo contengan.
Digitar una palabra y mostrar en pantalla todos los ttulos que la contengan.
CLASIFICAR: Por medio de submenus clasificar por: cdigo, valor de cada
libro, titulo y autor. Escoja al gusto si prefiere ordenes descendentes o
ascendentes.
ESTADISTICA: presente estadsticas de el valor de los libros, con la ayuda
del programa ESTADIST.CPP
4. Cierta Universidad est interesada en saber estadsticamente la calificacin
promedio de los estudiantes que recibieron matemtica durante un semestre. Desea
saber tambin el nmero total de estudiantes y el nmero de estudiantes

175

reprobados, en matemtica, por plan y en total.


CAPTURAR: Calcular lo anterior teniendo en cuenta que se leen: la
calificacin definitiva de matemticas, cdigo y nmero de plan, de todos los
estudiantes que cursaron matemtica. La informacin de los registros debe
permanentenete estar clasificada por el nmero del cdigo de cada uno de los
estudiantes.
LISTAR y CLASIFICAR: Listar por mdio de submens, informacin clasificada por
plan de estudios, y dentro de cada plan de estudios listar clasificado por cdigo
de cada estudiante, como clave secundaria.
BUSCAR: Se digita un cdigo y a continuacin se muestra la nota de el
estudiante correspondiente. Se digita un plan de estudios y a continuacin se
muestran todos los estudiantes que corresponden a ese plan y su promedio de nota
en matemtica.
GRABAR Y CARGAR: Todos los registros deben estar en disco.
ESTADISTICA: presente estadsticas de las calificaciones de matemtica, con
la ayuda del programa ESTADIST.CPP, tambin efecte grfico de barras.
5. Una compaa le encarga un informe para comprar mercanca, y por esto le
entreg unos registros con los siguientes datos, los cuales debe capturar por
teclado y posteriormente mantener en disco:- Cdigo del artculo (clave).- Nombre
del artculo.- Existencia actual en inventario, en unidades.- Existencia mnima
en unidades.(Cantidad de reorden).- Valor unitario.
LISTAR: Debe producir un informe de los artculos que hay que comprar de
acuerdo a las siguientes condiciones: - Listado de artculos con existencia menor
a la existencia mnima.
- Cantidad en pesos($) del total de artculos a
comprar.- Listado de artculos sin existencia en inventario.- Listado de
artculos con existencia superior a un 50% de la existencia mnima. Mostrar el
total del inventario representado en pesos($). Permitir la impresin en cada
oportunidad en papel.
BUSCAR: por medio de submens contestar lo siguiente: Digitar un cdigo de
artculo y mostrar la informacin correspondiente a l, si es que existe. Digitar
un nombre de artculo y contestar con su cantidad en inventario, si es que
existe. Digitar una palabra y a continuacin mostrar todos los nombres de
productos que la contienen.
CLASIFICAR: Por medio de submens. Mantener clasificado por la clave Cdigo
de artculo. Clasificar por medio de la clave nombre de el artculo.
ESTADISTICA: presente estadsticas de el existencias multiplicadas por el
valor unitario de cada artculo, y con la ayuda del programa ESTADIST.CPP.
Tambin grafique diagrama de barras.
6. Se debe elaborar un informe de cartera con base a una serie de registros con
los datos de: cdigo, nombre del cliente, Nmero de factura, valor original de la
factura, plazo del crdito para cancelar la obligacin; y los cuales hay que
capturar por teclado, y mantener adecuadamente actualizados en disco.
LISTAR: Utilizando submen listar en pantalla adecuadamente y por impresora
en papel utilizando diversas claves de ordenamiento.
BUSCAR: Utilizar submens para contestar lo siguiente:

176

Se debe elaborar un informe a nivel de cliente teniendo en cuenta que si el


plazo es hasta de 30 das se liquida 1% de interes; si el plazo esta entre 30 y
60 das se liquida un 2%; si el plazo est entre 60 y 120 das se liquida un
2,5%; y para plazos mayores de 120 das se liquida un 3%.
Digitar el nombre de un cliente y a continuacin mostrar todas las facturas
que tiene pendientes de pago, con el plazo correspondiente en das.
Digitar un nmero de factura y mostrar toda la informacin disponible y por
calcular de la misma.
ESTADISTICA: presente estadsticas de el total de las facturas, con la ayuda
del programa ESTADIST.CPP
7. La Secretara de Trnsito decidi cobrar multas por exceso del lmite de
velocidad as: Una cantidad de dinero llamada "Multa bsica" ms la
multiplicacin del nmero de kph en exceso sobre el lmite de velocidad por un
factor dado en la siguiente tabla de tarifas, as:
-

Lmite de velocidad de 60 kph en avenidas. Por cada kilmetro de exceso se


le cobran $2,000 adicionales.
El lmite de velocidad en calles es de 40 kph. Por cada kilmetro de exceso
se le cobran $3,000 adicionales.
El lmite de velocidad en autopista es de 80 kph.
Por cada kilmetro de
exceso se le cobran $4,000 adicionales.

Se desea saber cuntos autos han sobrepasado cada lmite en un determinado


tiempo de muestreo y cunto pagan de multa en total.
CAPTURAR: Se deben leer los siguientes campos por cada registro de vehculo
infractor: Placa del carro, Velocidad del vehculo infractor, tipo de va. Se
deben tener en disco actualizados los registros.
LISTAR: Presentar por medio de submen las multas de todos los infractores, y
clasificada por el nmero de placa. Presentar tanto en papel como en pantalla.
BUSCAR: Por medio de submen. Digitar un tipo de va y mostrar a continuacin
todos los registros de multa que coincida con l. Digitar un nmero de placa y
mostrar en pantalla el registro de multa correspondiente, si es que existe.
Digitar un real que representar kph y a continuacin mostrar todos los registros
que tengan infraccin por este kilometraje y mayor.
CLASIFICAR: Presentar listados en pantalla y en papel clasificados por tipo
de va, placa de carro, y de velocidad de infraccin.
ESTADISTICA: presente estadsticas de el total de multas cobradas, con la
ayuda del programa ESTADIST.CPP. Grafique en forma de barras
8. Un banco quiere calcular los intereses que tiene que cobrar al final del ao a
sus clientes con base a los datos de: Cdula y Nombre del cliente, Valor del
prstamo, Tasa de inters
convenida en %, nmero del da del ao en que fue
hecho el prestamo(del 1 al 365). Se deben capturar los anteriores datos y
mantenerlos tanto en RAM como posteriormente ser almacenados en disco.
Para el clculo de los intereses a cancelar al final del ao se aplica la
siguiente frmula: Valor intereses es igual al valor prestamo * (interes/100) *
(360 - da del prestamo)/360. Se debe imprimir el valor del inters pagado por
cada cliente y el total para todos ellos. Este listado debe aparecer clasificado
por la clave Cdula.

177

BUSCAR: Por medio de submen mostrar lo siguiente: Digitando un nombre de


cliente debe aparecer el registro correspondiente con la cantidad de intereses a
cancelar. Digitar cdula y de igual forma aparecer en pantalla toda la
informacin del cliente correspondiente. Digitar un nombre o apellido y mostrar
en pantalla todos los nombres completos de clientes que lo contienen.
CLASIFICAR:
utilizando
ascendentes y descendentes
prestamos, tasas de inters.

submens
por las

mostrar
en
pantalla
claves: cdula, nombre

clasificaciones
cliente, valor

ESTADISTICA: presente estadsticas de el total de intereses a cancelar, con


la ayuda del programa ESTADIST.CPP
9. Se requiere condensar algunas estadsticas sobre los estudiantes de la
Universidad.
Para cada registro se tiene: Cdigo, Edad, Sexo(Masculino,
Femenino), y Facultad (Psicologa, Ingeniera, Comercio), los cuales deben
capturar y mantener almacenados en disco.
LISTAR: Se debe calcular e imprimir en pantalla y en papel: Promedio de edad
de los estudiantes, porcentaje de hombres y mujeres por cada facultad y en la
Universidad. Mantener clasificado por Cdigo de estudiante.
BUSCAR: Digitar un cdigo y a continuacin debe aparecer el registro
correspondiente de es estudiante, si es que existe. Digitar un sexo y mostrar
todos los registros que coinciden con l. Digitar un nombre de facultad y a
continuacin digitar todos los registros que la contengan. Digitar dos edades y a
continuacin mostrar todos los registros que estn en el correspondiente
intervalo de edades.
CLASIFICAR: utilizando submen presente listados clasificados por edad, sexo
y de facultad, en forma ascendente y descendente.
ESTADISTICA: presente estadsticas respecto a la edades, con la ayuda del
programa ESTADIST.CPP
10. La Compaa AXZ tiene un registro por cada empleado con: Cdula de
identificacin, edad, meses trabajados en la compaa, cantidad en dinero a
cancelar por hora trabajada, horas regulares trabajadas, horas extras(se cancela
50 adicional sobre el valor regular), los cuales debe capturar y mantener en
disco.
LISTAR: Por medio de submen. Se desea saber si los nuevos empleados(menos de
un ao) tienden a trabajar ms horas extras que los antiguos. Se desea saber qu
cantidad de empleados tienen menos de un ao en la compaa, de uno a menos de
tres aos, de tres a cinco aos, de cinco a diez aos y ms de diez aos. Por
cada grupo se desea saber el promedio de horas trabajadas por empleado. Mantener
clasificado por el nmero de cdula al mostrar lo anterior. Mostrar la cantidad a
cancelar a cada uno de los empleados.
BUSCAR: Utilizando submen. Se digita cdula y de debe mostrar el registro
correspondiente si es que existe, incluyendo la cantidad total que hay que
cancelar a este empleado. Digitar dos edades y a continuacin mostrar todos los
registros que estn en el correspondiente intervalo de edades. Digitar dos
enteros que representarn meses y a continuacin mostrar todos los registros que
estn en el correspondiente intervalo de meses.
CLASIFICAR: Mostrar en pantalla clasificado por cdula de identidad, edad,
meses de antiguedad en la compaa en ordenes ascendentes y descendentes.

178

ESTADISTICA: presente estadsticas de el total pagado a cada empleado, con la


ayuda del programa ESTADIST.CPP
11. En un almacn de cadena se tienen unos registros de inventario con los
siguientes datos: cdigo del almacn, cdigo del departamento, cdigo del
artculo, saldo anterior, entradas, salidas, stock mnimo y costo unitario, los
cuales se debe capturar por teclado y mantener adicionalmente en disco.
LISTAR: Se debe imprimir un informe en donde se muestre por cada registro el
valor y cantidad del saldo actual con su stock mnimo y un aviso de "Compra",
cuando el saldo actual sea inferior al stock mnimo y un aviso de "alerta" cuando
el saldo vare en un 40% por encima del stock mnimo. Deben darse totales de los
valores por cada departamento de almacn, por cada almacn y para toda la cadena.
BUSCAR: digite un cdigo de almacen y a continuacin mostrar todos los
registros que lo contengan. Lo mismo para el cdigo del departamento. y
finalmente igual para el cdigo de artculo.
CLASIFICAR: Por las claves cdigo de departamente, de almacen y de artculo
en forma ascendente y descendente.
ESTADISTICA: presente estadsticas de el valor de las mercancas en
inventario, teniendo en cuenta que para cada item de inventario, su total est
dado por el saldo anterior ms las entradas, menos las salidas y, este guarismo
resultante, multiplicado por el costo unitario, con la ayuda del programa
ESTADIST.CPP
12. Una asociacin de universidades est interesada en elaborar una relacin de
estudiantes que sean casados y que trabajen. Se tienen registros con los datos de
la ciudad,
Universidad,
Facultad, nombre del
estudiante, edad, estado
civil(casado, soltero), situacin laboral (trabaja, no trabaja) y Cantidad que
cancela de matrcula, campos estos que deben ser capturados y mantenidos en
disco.
LISTAR: Debe presentarse un listado clasificado por Ciudad como primera
clave, Universidad como segunda clave, y Facultad como tercera clave, para lo
cual los datos deben mantenerse clasificados de esta forma en memoria RAM.
enlazada.
BUSCAR: Digitar nombre de estudiante y a continuacin mostrar los
correspondientes campos del registro correspondiente. Digitar nombre de
universidad y mostrar a continuacin todos los registros de estudiantes que la
contienen. Digitar nombre de ciudad y a continuacin mostrar todos los registros
correspondiente.
CLASIFICAR: Mostrar listados por separado clasificados por edad, estado civil
y situacin laboral.
ESTADISTICA: presente estadsticas de edades de los estudiantes de las
universidades, con la ayuda del programa ESTADIST.CPP. Idem para el pago de
matrcula.
13. PROGRAMA PARA UNA LINEA AEREA: Una lnea area desea controlar las reservas
de vuelo de un avin. El nmero de cupos disponible para el vuelo es de MAX
sillas. Representar en memoria por medio de una lista enlazada en memoria
dinmica. Cada registro en la lista representa una silla, habr un nmero
prefijado de sillas. Cada registro debe tener al menos los siguientes campos:

179

Nombre pasajero,
edad,
telfono,
cdula,
estado de la silla(Vaca, Reservada, Ocupada)
Nacionalidad
Representar globalmente mediante lista enlazada y variable que cuente las
reservas efectuadas. Al iniciar el programa debe inicializar los campos que
corresponden al estado de la silla con vaco (podra ser un cero o una letra V).
A continuacin, presentar un men principal de conmutadores, el cual permita
invocar funciones que hagan lo siguiente:
RESERVAR CUPO: En caso de estar llenos los cupos que aparezca el aviso "CUPO
COMPLETO. POR FAVOR CIERRE EL VUELO". En caso de haber disponibilidad se le
asigna el nmero de silla marcando como "Reservada" en el campo "Estado de la
silla". De esta forma el nmero de reservas aumentar en una cada vez que sea
invocada esta funcin.
CANCELAR RESERVA: Se pide al pasajero el nmero de silla que tiene reservada,
y se debe dejar marcada como "vaca" en el campo "Estado de la Silla"
correspondiente. De esta forma el nmero de reservas se decrementar en una.
CONFIRMAR RESERVA: Cuando el pasajero se presenta al aeropuerto se le debe
solicitar el nmero de silla(se supondr que se la sabe) y marcarla como
"ocupada".
LISTAR: presentar en pantalla un submen el cual permita listar la
informacin clasificada por: cdula, y otro por apellido, y otra opcin que
permita imprimir en papel.
CERRAR EL VUELO(y terminar el programa): Cuando el avin vaya a despegar,
producir un listado con la siguiente estadstica:

Nmeros de sillas ocupadas y sillas vacas (las vacas son las marcadas como
"vacas" ms las reservadas que no viaj nadie en ellas).

Listado de todos los nombres de pasajeros clasificados en orden alfabtico,


con su respectivo telfono y cdula.

Estadsticas de
ESTADIST.CPP.

Los pasajeros que sean de nacionalidad satanizada por los Estados Unidos,
imprimirlos en papel, con todos sus datos.

las

edades

de

los

pasajeros,

con

la

ayuda

del

programa

Todo lo anterior se debe manejar a partir de mens de conmutadores grficos


adecuados y en ventana el dibujo como abstraccin de los puestos del avin. Cada
cambio que ocurra en la situacin de ls sillas debe observarse, inmediatamente en
este grfico.

180

LISTA DOBLEMENTE ENLAZADA


//El siguiente programa implementa una lista doblemente enlazada.
#include
#include
#include
#include
#include
#include

<stdio.h>
<fstream.h>
<iostream.h>
<conio.h>
<ctype.h>
<dos.h>
//delay()

// LISTADOBL.CPP

#define ARCHIVO "Agenda.LD"


typedef struct INFO INFO;
typedef struct NODO NODO;
struct INFO{
int Entero;
char Cadena[25];
};
struct LISTADOBLE{
INFO Info;
LISTADOBLE *sig;
LISTADOBLE *ant;
}*Cab=NULL, *Fin=NULL;
const int BytesReg = sizeof(INFO);
int Insertar (INFO);
void Eliminar(LISTADOBLE *);
LISTADOBLE *Encontrar(INFO);
void Listar();
void ListaDesdeElFinal();
void GrabarLista();
void CargarLista();
void GrabarLista();
int Insertar (INFO item){
LISTADOBLE *p, *q, *nuevo;
p = NULL; q = Cab;
while (q != NULL && item.Entero > q->Info.Entero){
p = q;
q = q->sig;
}
if (item.Entero == q->Info.Entero) // elemento repetido
return 0;
if ( !(nuevo = new(LISTADOBLE) ) ) {
cout << "No hay memoria suficiente"; return(0);
}
nuevo->Info = item;
nuevo->sig = q;
nuevo->ant = p;
if ( !p && !q)
// lista esta vaca, el nodo quedar
Cab = Fin = nuevo;
else

como el primero

181

if (!p && Cab){


// va antes del primer nodo, quedando al inicio
q->ant = nuevo;
Cab = nuevo;
}
else {
p->sig = nuevo;
if (p && !q)
// el nodo quedar en la ltima posicion
Fin = nuevo;
else{
// caso general, se inserta en medio
nuevo->sig = q;
q->ant = nuevo;
}
}
return(1); // insertado
}
void

Eliminar(LISTADOBLE *p){
LISTADOBLE *q;

if (p == Cab){ //eliminar el primer nodo de la lista doblemente enlazada


Cab = p->sig;
Cab->ant = NULL;
}
else {
q = Cab;
while (q->sig != p)
q = q->sig;
if (p == Fin){
//Eliminar el ltimo nodo de la lista doblemente enlazada
Fin = q;
q->sig = NULL;
}
else{
//Caso general Eliminar en medio de la lista doblemente enlazada
q->sig = p->sig;
p->sig->ant = q;
}
}
delete(p);
}
LISTADOBLE * Encontrar(INFO item){
LISTADOBLE *p;
p = Cab;
while (p != NULL && item.Entero != p->Info.Entero)
p = p->sig;
if (item.Entero == p->Info.Entero)
return p;
else
return NULL;
}
void

Listar(){
LISTADOBLE *p;
if (!Cab)
cout << "Lista vaca \a\n";
else {

182

p = Cab;
while ( p ){
cout << p->Info.Cadena << "
p = p->sig;

" << p->Info.Entero << endl;

}
}
}
void

ListaDesdeElFinal(){
LISTADOBLE *p;
if (!Fin)
cout << "\n\nLista vaca \a\n";
else {
clrscr();
p = Fin;
while ( p ){
cout << p->Info.Cadena << "
p = p->ant;
}
}
delay(2000);

" << p->Info.Entero << endl;

}
void

GrabarLista(){
LISTADOBLE *p;
ofstream out(ARCHIVO);
if (!out){
//out es una funcin de la clase ios que est en fstream.h
cout << "No se puede abrir el archivo \a\n"; delay(2000); return;
}
p = Cab;
while ( p ) {
out.write( (unsigned char *)&p->Info, BytesReg );
p = p->sig;
}
out.close();

}
void

CargarLista(){ //Se supone los datos est n en orden de la clave en disco


INFO registro;
ifstream in(ARCHIVO);
if (!in){ //in es una funcin de la clase ios que est en fstream.h
cout << "No se puede abrir el archivo \a\n"; delay(2000);
}
else {
Cab = Fin = NULL;
while (in){ // in ser
0 cuando llegue a EOF
in.read( (unsigned char *)&registro, BytesReg );
Insertar(registro);
}
in.close();
}

}
void main(){
char op;
INFO item; LISTADOBLE *p;

183

LISTADOBLE Lista;
CargarLista();
do{
clrscr(); Listar();
cout <<"\n\nInsertar Borrar

Encontrar Lista_Inversa Terminar: ";

switch (
op = toupper( getch() ) ){
case 'I':
cout <<"\nDigite entero: ";
cin >> item.Entero;
cout <<"\nDigite Cadena: ";
gets(item.Cadena);
if ( ! Insertar(item) ){
cout <<"\nRepetido \a\n"; delay(2000);
}
break;
case 'B':
cout <<"\nDigite Entero a eliminar: ";
cin >> item.Entero;
if (p = Encontrar(item))
Eliminar(p);
else{
cout <<"\n\nNO encontrado en lista\a\n";
delay(2000);
}
break;
case 'E':
cout <<"\nDigite Entero a encontrar: " ;
cin >> item.Entero;
if (p = Encontrar(item))
cout <<"\nEncontrado en lista con Cadena: "
<< p->Info.Cadena;
else
cout <<"\n\nNO encontrado en lista\a\n";
delay(2000);
break;
case 'L': ListaDesdeElFinal();
} //switch
} while (op != 'T');
GrabarLista();
}

184

AGENTE APRENDE A RECORRER LABERINTO


/*El siguiente programa permite, por medio de las teclas del teclado, ensear a
agente a recorrer un laberinto.
Para el almacenamiento de las posiciones de los movimientos, se utiliza una
lista doblemente enlazada.
*/
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<graphics.h>
#include<ctype.h>
#include <ConIO.H> //getch();
#include <dos.H>
//**************************************************************************
const int DesActivo=0, Activo=1, Arriba=1, Abajo=0, Der=77, Izq=75,
Entrar=13, MaxOp=2, ESC=27, Margen=9, FilaMenu1=450, Abj=80,
Arb=72,MaxOpH=6, MaxOpV=3,MaxopH=4, MaxOp1=4, Xo=50, y0=10,
Ancho=22,
Alto=22, Fila=19, Col=25;
//**************************************************************************
struct PuntoXY{
int x;
int y;
};
struct LABERINTO{
struct PuntoXY info ;
struct LABERINTO *Sig;
struct LABERINTO *Ant;
}
*Cab=NULL, *Final=NULL;
int N=0;
int Matriz[Fila][Col]={
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,1,
1,0,1,1,0,1,0,1,0,0,1,0,1,0,1,0,1,1,0,1,0,1,0,0,1,
1,0,0,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,
1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,
1,0,0,1,0,1,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,
1,0,1,1,0,1,0,1,0,1,1,0,1,0,0,0,1,1,0,1,1,1,1,1,1,
1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,1,1,0,1,0,0,1,0,1,
1,1,0,0,0,1,0,0,1,0,0,1,1,0,1,0,1,0,0,1,1,0,1,0,1,
1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0,0,0,1,0,1,
1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,1,0,0,1,
1,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,0,0,1,0,1,0,0,1,1,
1,1,0,1,1,1,1,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,0,1,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,1,0,1,1,
1,0,1,1,1,1,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,0,0,0,1,
1,0,1,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,1,1,
1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};

185

//**************************************************************************
// COMIENZAN FUNCIONES PARA EL MANEJO DEL MOUSE CON INTERRUPCION 33 DEL DOS
//**************************************************************************
int IniciaMouse( int &BotonMouse){
union REGS entra,sale;
entra.x.ax = 0x0000;
int86( 0x33, &entra, &sale);
BotonMouse = sale.x.bx;
return ( sale.x.ax );
}
//**************************************************************************
void MuestraMouse( void ){
union REGS entra, sale;
entra.x.ax = 0x0001;
int86 ( 0x33, &entra, &sale );
}
//**************************************************************************
void EscondeCursorMouse( void ){
union REGS entra, sale;
entra.x.ax = 0x0002;
int86( 0x33, &entra, &sale);
}
//**************************************************************************
int LeerTeclaXYMouse( int &x, int &y){
union REGS entra,sale;
entra.x.ax = 0x0003;
int86( 0x33, &entra, &sale );
x = sale.x.cx;
y = sale.x.dx;
return(sale.x.bx);//Botn: 0=no pulsado; 1=izquierdo; 2=derecho;4=central.
}
//**************************************************************************
void MarcoVentana(int X1, int Y1, int X2, int Y2, int ArbAbj)
{
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
if (ArbAbj == Arriba)
setcolor(15);
else
setcolor(DARKGRAY);
line(X1, Y1, X1, Y2);
line(X1,Y1, X2,Y1);
if (ArbAbj == Arriba)
setcolor(DARKGRAY);
else
setcolor(WHITE);
line(X2,Y1, X2,Y2);
line(X1,Y2, X2,Y2);
}
//**************************************************************************
void Cursor(int X,int Y,char *Cad,int Oprimido){
register int AltoCuadro,LargoCuadro;
char c[2];
settextstyle(DEFAULT_FONT,
HORIZ_DIR,1);
AltoCuadro=textheight(Cad) + 7;
LargoCuadro= X + textwidth(Cad) + 7;
EscondeCursorMouse();
if (!Oprimido) {
MarcoVentana(X,Y,LargoCuadro,Y+AltoCuadro,Arriba);
setcolor(DARKGRAY);

186

}
else {
MarcoVentana(X,Y,LargoCuadro,Y+AltoCuadro,Abajo);
setcolor(WHITE);
}
outtextxy(X+5,Y+5,Cad);
c[0] = Cad[0];
c[1] ='\0';
setcolor(RED);
outtextxy(X+5,Y+5, c);
MuestraMouse();
}
//**************************************************************************
/* Funcion : PulsadoCuadro
*/
/* Objetivo : Realiza Cursor con una cadena centrada en su
*/
/*
interior y da la sensacion de que se oprime.
*/
/**************************************************************/
void PulsadoCuadro(int X,int Y,char *Cad)
{
Cursor(X,Y,Cad,DesActivo);
delay(100);
Cursor(X,Y,Cad,Activo);
delay(100);
Cursor(X,Y,Cad,DesActivo);
}
//**************************************************************************
void OVNI(int X,int Y){
int Radio =7;
setfillstyle( SOLID_FILL, BLUE); fillellipse(X,Y, Radio, Radio-1);
setfillstyle(SOLID_FILL, YELLOW);
fillellipse(X,Y+2,6,1);
setcolor(LIGHTRED); line(X+4, Y-2, X+5, Y-6); line(X-4, Y-2, X-5, Y-6);
fillellipse(X+6, Y-8, 3, 4); fillellipse(X-6, Y-8, 3, 4);
fillellipse(X-6, Y-8, 2, 2); fillellipse(X+6, Y-8, 2, 2);
}
//**************************************************************************
void Bloque(int x,int y){
setfillstyle(1, BLUE); bar(x,y,x+Ancho,y+Alto);
setcolor(LIGHTMAGENTA);
line(x,y,x+(Ancho-4),y);
line(x,y,x,y+(Alto-4));
line(x+3,y+3,x+Ancho,y+3);
line(x+3,y+3,x+3,y+Alto);
line(x+6,y+6,x+6,y+(Alto-6)); line(x+6,y+6,x+(Ancho-6),y+6);
line(x+(Ancho-3),y+6,x+(Ancho-3),y+(Alto-3));
line(x+6,y+(Alto-3),x+(Ancho-3),y+(Alto-3));
}
//**************************************************************************
void DibujarLaberinto(){
int c, f;
clearviewport();
for(f=0;f<Fila;f++)
for(c=0;c<Col;c++)
if(Matriz[f][c]==1){
Bloque(Xo+c*Ancho,y0+f*Alto);
}
else
if(Matriz[f][c]==0){
setfillstyle(SOLID_FILL, BLACK);

setcolor(DARKGRAY);

rectangle(Xo+c*Ancho,y0+f*Alto,Xo+c*Ancho+Ancho,y0+f*Alto+Alto);
}
return;

187

}
//**************************************************************************
void InsertarEnListaDoble(int x,int y){
LABERINTO *nuevo, *p;
nuevo= new LABERINTO;
nuevo->info.x=x;
nuevo->info.y=y;
if(!Cab){
Cab=nuevo;
nuevo->Sig=NULL;
Final =nuevo;
nuevo->Ant=NULL;
}
else{
nuevo->Ant=Final;
Final->Sig=nuevo;
nuevo->Sig=NULL;
Final=nuevo;
}
}
//**************************************************************************
void EnsenarAlAgenteMoverseEnLaberinto(){
int x=Xo+1.5*Ancho, y=y0+1.7*Alto;
int c,f;
N=0;
OVNI(x, y);
InsertarEnListaDoble(x,y);
N++;
do{
c = getch();
if (c == 0 ) {
c = getch();
switch (c) {
case Der: if(Matriz[(y-y0)/Alto][(x-Xo)/Ancho+1]!=1){
setfillstyle(SOLID_FILL, BLACK);
bar(x-9, y-12, x+(Ancho-13), y+(Ancho-16));
x+=Ancho;
InsertarEnListaDoble(x,y);
OVNI(x,y);
N++;
if((y-y0)/Alto==8 && (x-Xo)/Ancho==Col-1){
delay(500);
setfillstyle(SOLID_FILL, BLACK);
bar(x-9,y-12, x+(Ancho-13),
y+(Ancho-16));
x = Xo+2*Ancho;
y = y0+7*Alto;
OVNI(x, y);
sound(440); delay(100); nosound();
}
else
sound(2500); delay(20);
sound(1500);delay(10);nosound();
}
break;
case Izq: if(Matriz[(y-y0)/Alto][(x-Xo)/Ancho-1]!=1){
setfillstyle(SOLID_FILL, BLACK);
bar(x-9, y-12, x+(Ancho-13), y+(Ancho-16));

188

x-=Ancho;
InsertarEnListaDoble(x,y);
N++;
OVNI(x, y);
sound(2500);delay(20);
sound(1500);delay(10);nosound();
}
break;
case Abj: if(Matriz[(y-y0)/Alto+1][(x-Xo)/Ancho]!=1){
setfillstyle(SOLID_FILL, BLACK);
bar(x-9, y-12, x+(Alto-13), y+(Alto-16));
y+=Alto;
InsertarEnListaDoble(x,y);
N++;
OVNI(x, y);
sound(2500);delay(20);
sound(1500);delay(10);nosound();
sound(2500);delay(5);
sound(15);delay(10);nosound();
sound(2500);delay(5);
sound(1500);delay(10);nosound();
sound(2500);delay(10);
sound(15);delay(5);nosound();
}
break;
case Arb: if(Matriz[(y-y0)/Alto-1][(x-Xo)/Ancho]!=1){
setfillstyle(SOLID_FILL, BLACK);
bar(x-9,y-12,x+(Alto-13), y+(Alto-16));
y-=Alto;
OVNI(x, y);
InsertarEnListaDoble(x,y);
N++;
sound(2500);delay(5);
sound(15);delay(10);nosound();
sound(2500);delay(5);
sound(1500);delay(10);nosound();
sound(2500);delay(10);
sound(15);delay(5);nosound();
}
break;
default: sound(440); delay(10); nosound();
}
}
} while (c!=27);
}
//**************************************************************************
void ListarHaciaAdelante(){
LABERINTO *p,*q;
p=Cab;
q=NULL;
while(p){
q=p;
p=p->Sig;
OVNI(p->info.x,p->info.y);
setfillstyle(SOLID_FILL, BLACK);
bar(q->info.x-9,q->info.y-12 ,
q->info.x+(Ancho-13), q->info.y+(Ancho-16));
setfillstyle(SOLID_FILL,14); fillellipse(q->info.x,q->info.y-4,4,4);

189

delay(100);
sound(1350);delay(10);sound(1150);delay(5);nosound();
sound(1150);delay(5);sound(1350);delay(10);nosound();
}
}
//**************************************************************************
void ListarHaciaAtras(){
LABERINTO *p,*q;
p=Final;
q=NULL;
while(p){
q=p;
p=p->Ant;
OVNI(p->info.x,p->info.y);
setfillstyle(SOLID_FILL, BLACK);
bar(q->info.x-9,q->info.y-12 ,
q->info.x+(Ancho-13), q->info.y+(Ancho-16));
delay(100);
sound(3500);delay(10);sound(1500);delay(5);nosound();
sound(1500);delay(5);sound(3500);delay(10);nosound();
}
}
//**************************************************************************
void main(){
int i, c, pos=0, Invocar=1;
char *Opcion[MaxOp1] = {"Ensear","Auto","Revez","Salir"};
int PosX[MaxOp1], TotalAnchoCaracteres=0, TeclaMouse=0, x, y;
int ManejadorGrafico = DETECT, ModoGrafico;
initgraph( &ManejadorGrafico, &ModoGrafico, "\\tc\\bgi" );
setbkcolor(LIGHTGRAY);
DibujarLaberinto();
for(i=0;i<MaxOp1;i++)
TotalAnchoCaracteres += textwidth(Opcion[i])+Margen;
PosX[0] = (getmaxx()-TotalAnchoCaracteres)/2;
for(i=1;i<MaxOp1;i++)
PosX[i]=PosX[i-1]+textwidth(Opcion[i-1])+Margen;
for(;;){
if(Invocar){
for (i=0; i<MaxOp1; i++){
Cursor(PosX[i], FilaMenu1, Opcion[i],DesActivo);
}
Cursor(PosX[pos], FilaMenu1, Opcion[pos],Activo);
Invocar=0;
}
MuestraMouse();
do{
TeclaMouse = LeerTeclaXYMouse(x,y);
} while (!kbhit() && !TeclaMouse);
if(!TeclaMouse){
c = getch();
if (c == 0) {
c = getch();
switch (c) {
case Der: Cursor(PosX[pos], FilaMenu1,

190

Opcion[pos],DesActivo);
pos++;
if (pos == MaxOp1)
pos=0;
Cursor(PosX[pos],FilaMenu1,
Opcion[pos],Activo);
break;
case Izq: Cursor(PosX[pos],FilaMenu1,
Opcion[pos],DesActivo);
pos--;
if (pos == -1) pos = MaxOp-1;
Cursor(PosX[pos],FilaMenu1,
Opcion[pos],Activo);
break;
case 45:
return; //Alt-X
}
}
else {
if(c==ESC)
return;
c=toupper(c);
i=0;
while( c!=Opcion[i][0] &&
i<MaxOp1)
i++;
if(i<MaxOp1){// Se digit letra inicial de opcin
pos = i;
Invocar=1;
}
if (c==Entrar )
Invocar = 1;
}
}
else{ //Se digit tecla en el mouse
if(y>=FilaMenu1 && y<=FilaMenu1+textheight("H")+Margen){
Cursor(PosX[pos],FilaMenu1,Opcion[pos],DesActivo);
i=0;
while(i<MaxOp1 && !(x>PosX[i] &&
x< PosX[i]+textwidth(Opcion[i])+10) )
i++;
if(i<MaxOp1){ // Se hizo "click" en recuadro del mena
pos=i; Invocar=1;
}
else
TeclaMouse=0;
Cursor(PosX[pos],FilaMenu1,Opcion[pos],Activo);
}
}
if(Invocar){
PulsadoCuadro(PosX[pos],FilaMenu1,Opcion[pos]);
switch (pos){
case 0 : EnsenarAlAgenteMoverseEnLaberinto();break;
case 1 : ListarHaciaAdelante();break;
case 2 : ListarHaciaAtras();break;
case 3 : return;
}
}
}
}

191

192

LISTA DE LISTAS
/*El siguiente algoritmo implementa una lista simplemente enlazada en la cual
de cada uno de sus nodos se puede desprender una sublista simplemente enlazada.
En cada uno de los nodos de la lista principal, tenemos la informacin de un
mdico: Nombre, Telfono y Honorarios por hora. En cada una de las sublistas que
se pueden desprender de los nodos anteriores, tendremos los pacientes de cada
uno de los mdicos, con informacin de Nombre Paciente, Horario de su cita y su
telfono.
*/
//LISTALIST.CPP
#include <IOStream.h>
#include <IOManip.h>
#include <FStream.h>
#include <ConIO.h>
#include <StdIO.h>
#include <DOS.h>
#include <String.H>
#include <CType.H>
char NombreArch[20] = "Citas.Dr";
fstream Archivo;
typedef
typedef
typedef
typedef

struct
struct
struct
struct

INFOLISTA INFOLISTA;
LISTA LISTA;
InfoSubLista InfoSubLista;
SubLista SubLista;

struct InfoCitas{
char Horario[20];
char Nombre[25]; // del paciente
char Telefono[10];
};
struct SubLista{
InfoCitas Info;
SubLista *Sig;
};
struct INFOMEDICO{
char Nombre[25]; //permite hasta 24 caracteres
char Telefono[10];
float ValorHora;
};
struct LISTA{
INFOMEDICO Info;
SubLista *Cab;//Apunta a cada sublista desde cada nodo de la lista
principal
LISTA *Sig;
} *CAB=NULL;
LISTA *InsertarLISTA (INFOMEDICO item){
LISTA *p, *q, *nuevo;

193

nuevo = new(LISTA);
if ( nuevo == NULL ) {
cout << "No hay memoria suficiente";
return(NULL); // No insertado
}
p = NULL;
q = CAB;
while (q != NULL && strcmp(item.Nombre, q->Info.Nombre)>0){
p = q;
q = q->Sig;
}
if (q && strcmp(item.Nombre, q->Info.Nombre)==0){
delete(nuevo);
return (NULL); //repetido,
}
nuevo->Info = item;
nuevo->Sig = q;
nuevo->Cab = NULL;
if ( p == NULL)
CAB = nuevo; //era el primero de la lista
else
p->Sig = nuevo; //"caso general"
return(nuevo); // insertado
}
int EliminarLISTA(LISTA *p){
LISTA *q;
if (p == CAB)
CAB = p->Sig; //eliminado el primer LISTA de la lista
else {
q = CAB;
while (q->Sig != p)
q = q->Sig;
q->Sig = p->Sig;
}
delete(p);
return 1;
}
LISTA* EncontrarLISTA(INFOMEDICO item){
LISTA *p;
p = CAB;
while (p && strcmp(item.Nombre,p->Info.Nombre)>0)
p = p->Sig;
if(p && strcmp(item.Nombre,p->Info.Nombre)!=0 )
p= NULL;

// No encontrado

return p;
}

194

void ListarLISTA(){
if (!CAB)
cout << "Lista vaca \a";
else {
LISTA *p = CAB;
int i=0;
while ( p ){
cout << setiosflags(ios::right) << setw(8) << i++ << "
"
<< setiosflags(ios::left) << setw(25)
<< p->Info.Nombre
<< setiosflags(ios::right) << setw(3) << p->Info.Telefono
<< setiosflags(ios::right | ios::showpoint | ios::fixed)
<< setprecision(2) << setw(15) << p->Info.ValorHora << endl;
p = p->Sig;
}
}
}
void CapturarLISTA(){
INFOMEDICO item;
cout << "\n\nDigite Info a InsertarLISTA: ";
cout << "\n\Nombre del mdico: ";
gets(item.Nombre);
cout << "\n\nTelfono: ";
cin >> item.Telefono;
cout << "\n\nHonorarios por hora: ";
cin >> item.ValorHora;
if ( InsertarLISTA(item) == 0 ){
cout << "\n\nRepetido \a";
getch();
}
}
void BorrarLISTA(){
INFOMEDICO item;
LISTA *LISTA;
if (CAB == NULL)
cout << "Lista vaca \a";
else{
cout << "\n\nDigite Nombre del mdico a borrar: ";
gets(item.Nombre);
LISTA = EncontrarLISTA(item);
if (LISTA)
EliminarLISTA(LISTA);
else {
cout << "\n\nNo encontrado en lista";
getch();
}
}
}
void EncontrarEnLISTA(){
INFOMEDICO item;
LISTA *p;
if (CAB == NULL)
cout << "Lista vaca \a";

195

else{
cout << "\n\nDigite Nombre del mdico a encontrar: ";
gets(item.Nombre);
if (p = EncontrarLISTA(item))
cout << "\n\nEncontrado en lista y tiene el telfono "
<< p->Info.Telefono;
else
cout << "\n\nNo encontrado en lista";
}
getch();
}
// ===========================================================================
//
A CONTINUACION LAS FUNCIONES PARA MANEJAR CADA SubLista
// ===========================================================================
SubLista *InsertarEnSubLista (InfoCitas item, SubLista *Cab){
SubLista *p, *q, *nuevo;
if ( (nuevo = new SubLista ) == NULL ){
cout << "No hay memoria suficiente";
return NULL;
}
p = NULL;
q = Cab;
while (q != NULL && strcmp(item.Nombre, q->Info.Nombre)>0){
p = q;
q = q->Sig;
}
nuevo->Info = item;
nuevo->Sig = q;
if ( p == NULL)
Cab = nuevo; //era el primero de la lista
else
p->Sig = nuevo; //"caso general"
return(Cab);
}
SubLista *EliminarEnSubLista(SubLista *p, SubLista *Cab){
SubLista *q;
if (p == Cab)
Cab = p->Sig; //eliminado el primer nodo de la lista
else {
q = Cab;
while (q->Sig != p)
q = q->Sig;
q->Sig = p->Sig;
}
delete(p);
return Cab;
}
SubLista* EncontrarEnSubLista(InfoCitas item, SubLista *Cab){
SubLista *p;
p = Cab;
while (p && strcmp(item.Nombre,p->Info.Nombre)>0)

196

p = p->Sig;
if (p && strcmp(item.Nombre,p->Info.Nombre)!=0)
p=NULL;
return p;
}
void ListarSubLista(SubLista *Cab){
SubLista *p; int Cliente=0;
if (!Cab)
cout << "No tiene citas \a\n";
else {
p = Cab;
while ( p ){
cout.setf(ios::left);
cout << setw(2) << ++Cliente << ": "
<< setw(25) <<p->Info.Nombre;
cout << setw(15) <<p->Info.Telefono;
cout << setw(20) <<p->Info.Horario << endl;
p = p->Sig;
}
}
}
SubLista *CapturarSubLista(SubLista *Cab){
InfoCitas item;
cout << "\n\nDigite datos del paciente a insertar: ";
cout << "\n\Nombre: ";
gets(item.Nombre);
cout << "\n\nTelefono: ";
cin >> item.Telefono;
cout << "\n\Horario de la cita: ";
gets(item.Horario);
Cab = InsertarEnSubLista(item, Cab);
if ( !Cab ){
cout << "\n\nNo se pudo insertar: se lleno la memoria\a";
getch();
}
return Cab;
}
SubLista* BorrarSubLista(SubLista *Cab){
InfoCitas item;
SubLista *Nodo;
if (Cab == NULL)
cout << "Lista vaca \a";
else{
cout << "\n\nDigite Nombre de paciente a borrar su cita: ";
gets(item.Nombre);
Nodo = EncontrarEnSubLista(item, Cab);
if (Nodo)
Cab = EliminarEnSubLista(Nodo, Cab);
else {
cout << "\n\nNo encontrado en lista";

197

getch();
}
}
return Cab;
}
void EncuentraSubLista(SubLista *Cab){
InfoCitas item;
SubLista
*p;
if (Cab == NULL)
cout << "Lista vaca \a";
else{
cout << "\n\nDigite Nombre de paciente a encontrar: ";
gets(item.Nombre);
if (p=EncontrarEnSubLista(item, Cab))
cout << "\n\nEncontrado en lista y tiene el telfono "
<< p->Info.Telefono;
else
cout << "\n\nNo encontrado en lista";
}
getch();
}
void SubListaEnlazada(){
char op;
INFOMEDICO item;
LISTA *q;
if(CAB){
clrscr();
cout <<"Nombre del Mdico a encontrar y colocarle las citas: ";
cin >> item.Nombre;
q = CAB;
while (q && strcmp(item.Nombre, q->Info.Nombre)!=0)
q = q->Sig;
if (!q)
cout << "No se encuentra ninguna persona de Nombre "
<< item.Nombre;
else{
do{
clrscr();
cout << "Estos son los pacienticos de "
<< q->Info.Nombre << endl;
ListarSubLista(q->Cab);

cout << "\nMENU DE SUBLISTA: Insertar Borrar Encontrar Terminar: ";

op = toupper(getch());
switch (op){
case 'I': q->Cab=CapturarSubLista(q->Cab); break;
case 'B': q->Cab=BorrarSubLista(q->Cab);
break;
case 'E': EncuentraSubLista(q->Cab);
break;
} //switch
} while (op != 'T');
}
} else
cout << "Lista de mdicos vaca\a";
}
//===========================================================================

198

void GrabarLISTA_y_SubListas(LISTA *P){


SubLista *p;
int n;

// funcion recursiva

if ( P ) {
Archivo.write((char *)&P->Info, sizeof(P->Info));
p = P->Cab;
n = 0;
while(p) { n++; p=p->Sig; } //Cuenta # nodos en lista enlazada
Archivo.write((char *)&n, sizeof(n)); //Graba en disco # nodos
p = P->Cab;
while(p) {
Archivo.write((char *)&p->Info, sizeof(p->Info));
p=p->Sig;
}
GrabarLISTA_y_SubListas(P->Sig);
}
}
void Grabar(){
Archivo.open(NombreArch, ios::out|ios::binary|ios::trunc);
if (!Archivo)
cout << "Error en la apertura del archivo \a";
else{
GrabarLISTA_y_SubListas(CAB);
Archivo.close();
}
}
void CargarLISTA_y_SubListas(){
INFOMEDICO registro;
LISTA *p;
int n;
InfoCitas reg;
SubLista *Cab;
CAB = NULL;
Archivo.open(NombreArch,ios::in|ios::binary);
if (!Archivo){
cout << "No se puede abrir el archivo \a\n";
}
else {
while(
Archivo.read( (char *)&registro, sizeof(registro) ) ){
p = InsertarLISTA(registro);
//p es puntero a donde se inserto en lista
Archivo.read( (char *)&n, sizeof(n) );
//n es el nmero de nodos en lista enlazada
p->Cab=NULL;
for(int i=0; i<n; i++){
Archivo.read( (char *)&reg, sizeof(reg) );
p->Cab = InsertarEnSubLista(reg, p->Cab);
}
}
Archivo.close();
}
}
void main(){

199

char op;
unlink(NombreArch);
//Habilite si quiere borrar NombreArch
clrscr();
CargarLISTA_y_SubListas();
do{
clrscr();
ListarLISTA();
cout<<"\n\nMENU PRINCIPAL:Medicos Borrar Encontrar Citas Terminar:";
switch ( op = getch() ){
case 'm': ; case 'M': CapturarLISTA();
break;
case 'b': ; case 'B': BorrarLISTA();
break;
case 'e': ; case 'E': EncontrarEnLISTA(); break;
case 'c': ; case 'C': SubListaEnlazada(); break;
}
} while (!(op == 'T' || op == 't' ));
Grabar();
}

200

EL CDIGO ASCII
El cdigo ASCII(American Standard Committed for Information Interchange), es el
cdigo con el cual operan los microcomputadores que trabajan bajo el sistema
operativo MS-DOS y Windows. Se compone de un conjunto de caracteres de control,
y caracteres imprimibles, numerados del 0 al 255. Ocupa cada uno de ellos un
Byte de memoria, es decir ocho bit.
Tabla de Caracteres ASCII imprimibles.
32
42 *
52 4
62 >
72 H
82 R
92 \
102 f
112 p
122 z
132
142
152 _
162
172
182
192
202
212
222
232 F
242
252 _

33
43
53
63
73
83
93
103
113
123
133
143
153
163
173
183
193
203
213
223
233
243
253

!
+
5
?
I
S
]
g
q
{

34
44
54
64
74
84
94
104
114
124
134
144
154
164
174
184
194
204
214
224
234
244
254

"
,
6
@
J
T
^
h
r
|

a
W

35
45
55
65
75
85
95
105
115
125
135
145
155
165
175
185
195
205
215
225
235
245
255

#
7
A
K
U
_
i
s
}

36
46
56
66
76
86
96
106
116
126
136
146
156
166
176
186
196
206
216
226
236
246

$
.
8
B
L
V
`
j
t
~

37
47
57
67
77
87
97
107
117
127
137
147
157
167
177
187
197
207
217
227
237
247

%
/
9
C
M
W
a
k
u

p
f

38 &
39 '
40 (
41 )
48 0
49 1
50 2
51 3
58 :
59 ;
60 <
61 =
68 D
69 E
70 F
71 G
78 N
79 O
80 P
81 Q
88 X
89 Y
90 Z
91 [
98 b
99 c 100 d 101 e
108 l 109 m 110 n 111 o
118 v 119 w 120 x 121 y
128 129 130 131
138 139 140 141
148 149 150 151
158 _ 159 160 161
168 169 _ 170 171
178 179 180 181
188 189 190 191
198 199 200 201
208 209 210 211
218 219 220 221
228 S 229 s 230 m 231 t
238 e 239 240 241
248 249 250 251

201

A continuacin se presentn los cdigos de exploracin de varias teclas y


combinacin de teclas. Las combinaciones de teclas o teclas las cuales tienen un
0 en primer lugar en realidad producen dos cdigos los cuales deben ser ledos
adecuadamente, por ejemplo al pulsar simultneamente las teclas ALT y M se
produce un cdigo 0 el cual es ledo inicialmente y el siguiente cdigo 50 es
dejado en el buffer de memoria del teclado, sino es ledo con otra instruccin
de lectura, l 50 se perder, veamoslo con un pequeo fragmento en C:
cout << "digite Combinacin de teclas: ";
c = getch();
supongamos el usuario hasta aqu digita ALT M, para ver que qued en c:
cout << " la variable c tiene el valor de " << c;
se presentar el valor de 0. Para leer el cdigo
extendido, el cual se conserva en el buffer del teclado:

siguiente

cdigo

c = getch();
cout << " el cdigo extendido es " << (int) c;
se coloca el reforzador de tipo, (int), para evitar que nos escriba en
pantalla el ASCII correspondiente al 50
Teclas que producen cdigos extendidos al digitarlas solas:

HOME
FLECHA ARRIBA
PAGE UP
FLECHA IZQUIERDA
FLECHA DERECHA
END
FLECHA ABAJO
PAGE DOWN
INSERT
DELET
F1 al F10
F11
F12

0
0
0
0
0
0
0
0
0
0
0
0
0

71
72
73
75
77
79
80
81
82
83
59 al 0 68
133
134

Cdigos extendidos de teclas al pulsarlas simultneamente con la tecla de


cambio SHIFT:
SHIFT

A a la Z
F1 al F10
F11
F12

65 al 90
0 84 al 0 93
0 135
0 136

202

A
continuacin
los
cdigos
extendidos
de
teclas
simultneamente con las teclas CTRL y ALT respectivamente:
CTRL
A
...
Y
F1
...
F10
IZQUIERDA
DERECHA
END
PAGE DOWN
HOME
PAGE UP
F11
F12
ARRIBA
+
ABAJO
INSERT
DELETE
/
*

ALT
1
...
25
0 94
...
0 103
0 115
0 116
0 117
0 118
0 119
0 132
0 137
0 138
0 141
0 142
0 144
0 145
0 146
0 147
0 149
0 150

al

ser

pulsadas

ALT
ESC
RETROCESO
Q
W
E
R
T
Y
U
I
O
P
ENTER
A
S
D
F
G
H
J
K
L
;
'
`
\
Z
X
C
V
B
N

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

1
14
16
17
18
19
20
21
22
23
24
25
28
30
31
32
33
34
35
36
37
38
39
40
41
43
44
45
46
47
48
49

M
,
.
/
F1...F10
1
2
3
4
5
6
7
8
9
0
=
F11
F12
HOME
FLECHA ARRIBA
PAGE UP
FLECHA IZQUIERDA
FLECHA DERECHA
END
FLECHA ABAJO
PAGE DOWN
INSERT
DELETE
TAB
ENTER

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

50
51
52
53
104-113
120
121
122
123
124
125
126
127
128
129
130
131
139
140
151
152
153
155
157
159
160
161
162
163
165
166

...
Despus de tntas y de tan pequeas
cosas, -busca el esprit mejores aires,
mejores aires.
Toda aqusa gentuza verborrgica
-trujamanes de feria, gansos del capitolio,
engibacaires, abderitanos, macuqueros,
casta inferior desglandulada de potencia,
casta inferior elocuenciada de impotencia-,
toda aqusa gentuza vervorrgica
me causa hasto, bascas me suscita,
gelasmo me ocaciona:
mejores aires,
-busca, busca el espritu mejores aires-.
... "

203

"RELATO DE GAZPAR" en "LIBRO DE RELATOS".


LEON DE GREIFF
Primera Parte

Segunda Parte

Tercera Parte

204