Sie sind auf Seite 1von 118

Algoritmos y su Codificacin enC++

Volumen 2
Csar Liza A vila
Grupo.
Creadores
lV/nTllJnn.r1n tu naturaleza Creativa
w


.. .. .... .
. .... .
.:
/ Datos de catalogacin bibliogr:;
Liza A vila, Cesar
Algoritmos y su Codificacin en C++. Volumen 2
Editorial Creadores .
Trujillo, Per, 2002
Tema: Programacin de computad'0ras
Formato: 14.5 x 20.5 Pginas: 234
Algoritmos y su Codificacin en CH. Vol 2.
Primera Edicin, Agosto 2002
El contenido de esta obra esta protegido por ley. Queda prohibida la
Jeproduccin total o parcial de este libro, por cualquier medio, sin permiso
escrito del autor.
2002, Derechos Reservados por Csar liza Avila.
Distribucin y Ventas
Editorial Creadores
Av. Amrica Norte 401 - Trujillo.
Telfono (044) 221363
e-mail: creadores@hotmail.com
Web Site: li?-
j
DEDICATORIA
A mis padres:
Dr. Csar Liza Ortz y Nery Avila Acosta por el esfuerzo
constante en la formacin de sus hijos.
Sin su ejemplo y apoyo nunca hubiera llegado a ser un
profesional de xito y mucho menos haber publicado algn
libro.
A mis amigos y colaboradores:
LoudesDaz, limar Goicochea, Kevin Llontop y Alfredo del
Castillo, por su importante crtica y aporte en el contenido
del libro. A mi querido amigo, que ya no est con nosotros,
Rogelio Briceo.
A mi modelo, amiga y futura colega:
Ana Luisa Doig Ascate, que adorna nuestra portada con
sus lindos ojos y bella sonrisa.
Al fotgrafo y amigo:
Vctor Torres Garca, por captar la belleza de nuestra
modelo.
Al diseador de la portada:
Javier Asmat, mi gratitud por su amistad y el buen gusto en
el diseo de la portada.
1
DILE NO A LA PIRATERA
Escribir un libro cuesta muchas horas de
esfuerzo intelectual. Publicarlo y distribuirlo
. constituye un esfuerzo econmico muy
grande donde no se espera obtener grandes
ganancias econmicas.
Si copias este libro cometes un delito y
adems matas la difusin del conocimiento
tcnico contribuyendo a que nuestro Per
siga siendo subdesarrollado.
NO COPIES MIS LIBROS
Hemos detectado que debido al gran xito
alcanzado por nuestros libros, stos se
encuentran fotocopiados y anillados listos
para su VENTA ILEGAL en muchos
"centros de fotocopiado" frente a
Universidades e Institutos.
Cuando menos lo esperen, los
visitaremos cayndoles con todo el peso
de la ley
PRESENTACION
f:sta obra es la continuacin de "Algoritmos y su Codificacin en
C++", y viene a completar el vaco que exista respecto a temas que no
tratamos en ella. Manejo de caracteres, arreglos bidimensionales,
estructuras, uniones, enumeraciones, manipulacin de bits, generacin de
nmeros aleatorios, simulacin, punteros, asignacin. dinmica de
memoria, y archivos, son tratados mediante ms de 81 ejemplos
completos de' programacin. Asimismo, encontrar ms de 140
ejercicios propuestos que le serviran para practicar lo aprendido, y que
sern de valiosa ayuda para los docentes en la elaboracin de prcticas y
exmenes.
Para la compilacin de los programas' presentados en este libro,
utilizamos el Microsoft Visual C++, en aplicaciones en modo consola,
pero puede utilizar otros compiladores haciendo pequeas modificacions
al cdigo.
En este segundo volumen, no utilizamos los diagramas N/S, pues
consideramos que el programador tiene la suficiente madurez lgica y
puede estructurar la solucin al problema para luego pasar a su
codificacin.
El primer captulo, trata sobre las cadenas de caracteres, que
son implementadas en C/C++ como arreglos, donde cada uno de sus
elementos es un carcter. Es importante su estudio puesto que el hombre
se comunica con palabras ms que con nmeros, y la computadora solo
utiliza nmeros para todo, inclusive para representar cada una de las
letras, ya sea mediante el cdigo ASCII o su sucesor el UNICODE.
Los arreglos bidim'Emsionales o matrices, constituyen un
elemento importante en matemticas pues permiten resolver un amplio
conjunto de problemas con muchsimas aplicaciones reales, as como
almacenar datos que necesitan 2 dimensiones para ser identificados. El
segundo captulo, aborda este tema mediante numerosos ejemplos.
I
/1
Las estructures, uniones '1 enumeraciones son tratadas en el
tercer captulo. Las estructuras son construcciones en C/C++, que
permiten agrupar un conjunto de atributos de diferentes tipos de datos, en
una nica variable; las estructuras constituyen los predecesores de las
clases. Las uniones definen en una misma zona de memoria uno o ms
elementos, permitiendo su ahorro; mientras que las enumeraciones hacen
mas claro nuestro programa, ya que podemos usar nombres en vez de
nmeros.
En el cuarto mostramos cmo g,enerar filmems
con distribuciones tales como ?oisson,
V Normal; abordando problemas mediante la tcnica conocida como
Simulacin Montecarlo.
la manipulacin de bits, la tratamos en el quinto captulo, y es
uno de mis favoritos, pues en l, mostramos cmo la computadora
almacena y procesa internamente los datos operando sobre bits; adems
existen muy pocos libros que traten adecuadamente este tema, y lo tratan
con escasos ejemplos. Este libro es la excepcin pues mostramos diversas
e interesantes aplicaciones.
Los datos que usamos y los programas que ejecutamos en una
computadora, ocupan memoria. Mediante los punteros podemos acceder
a cualquier zona de memoria asignada a nuestro programa. Asimismo,
mostramos como usar la asignacin dinmica, para reservar la memoria
necesaria segn como la vayamos necesitando. Estos temas son tratados
en el sexto captulo.
En el stimo y ltimo captulo, mostramos cmo hacer
persistentes nuestros datos en archivos; as como, analizar e interpretar
os diversos formatos de almacenamiento, abrindonos la puerta a un
mundo de aplicaciones.
Espero que la presente, supere la acogida que tuvo el primer
volumen. Le rogamos que cualquier crtica, sugerencia, o inquietud, la
. dirija a la siguiente direccin electrnica: creadores@hqtmail.S;.QI!L que
gustosos la responderemos con el nimo de mejorar cada da. Asimismo,
le invitamos a visitar nuestra pgina web www.geocities.com/cesarJi;;:a.
Csar Liza Avila
I
"-'-,
CONTENIDO
Presentacin"."., ... , .................................. ' .... , .. ,." .. , ............ , ............. ', . , "" 7
CAPITULO 1: Cadenas de Caracteres ..................................... " ..... 15
i .1 Muestre la tabla de cdigos ASCii
1.2 Programa que muestre el uso de las secuencias de escape
1.3 Convierta una palabra en maysculas a minsculas
1.4 Muestre la suma de verificacin de un mensaje
1.5 Dada una cadena numrica obtenga el nmero que representa
1.6 lea una frase y mustrela palabra por palabra
1.7 Cree su propia funcin para ingresar caracteres desde teclado
1.8 Encripte una cadena sumando sus ASCII con los dela clave
1.9 Encripte una cadena con una tabla de equivalencia
1.10 Diga como es alfabticamente, una palabra respecto a otra
1.11 Programa que utiliza las macros y funciones provistas en ctype.h
1.12 Uso de las funciones estndar provistas en el archivo string.h
1.13 Diga si una palabra es palndroma
CAPITULO 2: Arreglos Bidimensionles ......................................... 41
2.1 Lea una matriz con f filas y c columnas y iuego la imprmala
2.2 Encuentre la transpuesta de una matriz
2.3 Genere una matriz identidad de orden n
2.4 Dada una matriz diga si sta es una matriz triangular superior
2.5 Dada dos matrices obtenga la matriz ampliada
2.6 Inserte un vector en una columna determinada de una matriz
2.7 Cul es la produccin mensual de un grupo de fbricas?
2.8 Posiciones a las que se mueve la reina en un tablero de ajedrez
2.9 Suma de dos matrices
2.10 Producto de dos matrices
2.11 Determinante de una matriz
2.12 Resuelva un sistema de ecuaciones simultneas
2.13 Inversa de una matriz
2.14 Programa que juega "tres en raya"
2.15 Lea un conjunto de palabras en una matriz y ordnelas
t
CAPITULO 3: Estructuras Uniones y Enumeraciones ........ 00 oo 89
3.1 Suma de dos nmeros complejos
3.2 A cunto debe venderse cada kilo para no ganar ni perder?
3.3 Encuentre el valor numrico de un polinomio f(x)
3.4 Busque una fecha y diga cul fue su temperatura
3.5 Gestione los datos de un conjunto de alumnos
;3.6 Programa que permita al usuario resolver un crucigrama
3.7 Defina, en una misma zona de memoria, un entero y un flotante
3.8 Pida un nmero de da de la semana, y muestre el nombre del da
3.9 Lea una moneda y diga a cuntos cntimos equivale
CAPITULO 4: Manipulacin de 8Its ........................................ 00 115
4.1 Muestra el uso de operadores a nivel de bits: -, &, I , ", y
4.2 Lea un nmero, muestre sus bits tal como se ven en memoria
4.3 Encripte un mensaje por manipulacin de bits con XOR
4.4 Programa que genera una baraja de cartas. Use campos de bits
4.5 Programa que lee una hora y obtiene el nmero que la representa
4.6 Lea un nmero que represente una fecha vlida y obtenga la fecha
4.7 Lee una hora y da el nmero que la representa. Campos de Bits
4.8 Muestre cada bit de un punto flotante de simple precisin
4.9 Estndar IEEE 754 de un flotante de simple precisin
CAPITULO 5: Generacin de Nmeros Aleatorios y Simulacin ...... 143
5.1. Genera nmeros aleatorios por el Mtodo Congruencial Lineal
5.2. Genera aleatorio discreto en [O, RAND_MAX], [O, a-1], y [a, b]
5.3. Genera aleatorio en el intervalo continuo entre [0,1] Y [a, b]
5.4. Caminata aleatoria de borrachito, a igual distancia de casa-cantina
5.5. Ley Fuerte de los Grandes Nmeros
5.6. Calcule la integral definida de una funcin f(x), por simulacin
5.7. Calcule el valor de PI, por simulacin
5.8. Obtenga los nmeros ganadores del siguiente sorteo de la Tinka
5.9. Genera aleatorios con Distribucin Poisson y media lambda
5.10. Genera aleatorios con Distribucin Exponencial y media 1/1-1
5.11. Genera aleatorios con Distribucin Normal
5.12. Genera una permutacin aleatoria (mezcla) de n elementos
5.13. Genera combinacin aleatoria de n elementos, en grupos de r
CAPITULO 6: Punteros y Asignacin Dinmica de Memoria ........... 173
6.1 Declare variables y muestre sus direcciones de memoria
6.2 Funcin que intercambia dos valores
6.3 Lea coordenadas cartesianas, y convirtalas a polares
6.4 Direcciones de memoria que ocupan los elementos de un arreglo
6.5 Usando arreglos y punteros, lea n elementos y ordnelos
6.6 Lea una palabra y reemplace una letra por otra
6.7 Determine si una palabra es palndroma
6.8 Concatene 2 palabras
6.9 Ordene los elementos de arreglo, usando un arreglo de punteros
6.10 Funcin que lee n empleados, usando un puntero a una estructura
6.11 Arreglo dinmico de n flotantes
6.12 Puntero a funcin
6.13 Funcin que intercambia dos valores. Use referencias
CAPITULO 7: Archivos ............................................................... 201
7.1 Lea una serie de caracteres y cree un archivo con ellos
7.2 Lea el nombre de un archivo y muestre su contenido por pantalla
7.3 Lea un archivo y cpielo hacia otro
7.4 Divida un archivo en otros, similar al Hacha
7.5 Lea una serie de registros y gurdelos en un archivo
7.6 Construya un Visor Hexadecimal
7.7 Comprima un archivo por reduccin de caracteres repetidos
7.8 Lista los archivos comprimidos en *.ZIP
7.9 Dada una carpeta, muestre los directorios y archivos que contiene
Acerca del Autor
Otras Obras del Autor.
Distribucin y Ventas
l
Cadenas de
Caracteres
m
Cadena de Caracteres 15
Solucin:
Es conocido que las computadoras son capaces de almacenar solo CEROS
y UNOS, es decir nmeros en binario. Pero el humano adems de nmeros
utiliza smbolos, por lo que fue necesario codificarlos, para que sean
almacenados en las computadoras. Por ejemplo, podramos decir que si
almacenamos el nmero en binario 0100 0001 (equivalente a 65 en
decimal) estaremos almacenando la letra 'A'. Otro grupo de programadores
pudo haber definido como cdigo de 'A' el nmero 0000 0000, esto trajo,
all por la dcada del 60, la necesidad de definir un estndar.
Este estndar se llama Tabla de Cdigos ASCII (American Standar Code
for /Ilformation /nterchallge, Estndar Americano de Codificacin para
el Intercambio de Informacin), la cual nos proporciona una lista de
cdigos a los que se les ha asociado un smbolo, que permite que los
equipos y programas puedan intercambiar informacin con otros equipos y
programas.
La Tabla de Cdigos ASCII original contiene 128 cdigos (del O al 127),
puesto que este es la mxima combinacin de valores que se puede obtener
con un byte (8 bits) sin ocupar el bit del signo (2
7
). Posteriormente, se
ampli esta tabla para ms smbolos como los caracteres con tilde, a esta
tabla se le conoce como Tabla de Cdigos ASCII Extendida y consta de
256 smbolos (del O al 255), pues esta es la mxima cantidad de valores que
se pueden conseguir con un byte (2
8
) usando inclusive el bit del signo.
Como es de esperarse los 128 primeros caracteres de la Tabla ASCII
Extendida son los mismos que la Tabla ASCII original.
En la Tabla ASCII los 32 primeros caracteres (del O al 31) son caracteres
de control, esto es; realizan una accin, en vez de mostrar un smbolo.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
16 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Tabla de Cdigos ASCn

Cadena de Caracteres f7

IDee Hex IChal: Ji)'ee lBIex Clluil: IDee lBIex I;hal: IDee ex I:har

128 80 r; 160 AO 192 CO
,-
22"1 EO ex
129 81 161 Al i 193 Cl
1..
225 .1\1
e,
130 82 162 A2 194 C2
T
226 E2 r
131 83 a 163 A3 195 C3 .. 227 E3 n
132 8"1 a 164 A4 196 C4 228 E4 E
133 85 a 165 AS 197 C5
+
229 ES CJ
134 $6 a 166 A6
.
198 C6

230 E6 11
135 87 C;
167 A7
o
199 C7

231 E7
136 88 168 AS 200 CS
I!. 232 E8
137 89 e 169 A9 r 201 C9
IF
233 E9 (')
138 SA e 170 AA
.., 202 CA
,!!:
234 EA Q
139 8B i 171 AB 11 203 CB
'ir
235 EB !J
1"10 BC i 172 AC 1,.,; 20"1 CC
Ir
236 EC
""
141 8D i 173 AD i
205 CD 237 ED 0
1"12 .8E ii. 174 .II.E 206 CE
JL
23S EE
lr
1"13 8F A 175 AF 207 CF
,b
239 EF n
1"14 90 176 BO
.:.;.:
...
208 DO
lL 240 FO -
145 91 <e 177 B1
209 Di
T
241 n
1"16 92 lE 178 B2
11
210 . D2
"Ir
242 F2

147 93 179 B3
I
211 D3
IL 243 F3
148 94 ti . 180 B4
i
212 D4
b 244 F4
r
149 95 6 181 B5

213 D5
F
245 F5
J
150 96 ti 182 B6
il
214 D6
Ir
246 F6
151 97 u 183 B7
11
215 D7
t
247 F7
152 98 Y
184 B8
'1
216 D8
+-
248 F8
153 99 o 185 B9 {I 217 D9
J 249 F9
154 9A 186 BA
11
218 DA
r
250 FA
155 9B e 187 BB
il
219 DB
I
251 FB '
156 9C f. 183 BC JI 220 DC
lW
252 FC
157 9D Y 169 BD
.u
221 DD

253 FD
158 9E E. 190 BE
d 222 DE

254 FE
159 9F :f 191 BF
1
223 DF
l1li
2.5.5 Ff o
------_.-
Podemos generar el smbolo a partir de su cdigo ASCII, usando el teclado
numrico. Esto lo conseguimos pulsando simultneamente la tecla Aj +
Cdi.go ASen ingresado con el teclado numrico.
Csar Li(:a Av!a. Mis libros son econmicos. IZO ha.\" razn para (oliarlos.
18 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza Avila
Para mostrar cada cdigo ASCII, nuestro programa genera nmeros del O al
255, imprimiendo el cdigo i, y el smbolo (char) i. Note el uso de la
conversin tipo casi que usamos para forzar a la computadora a mostrar el
smbolo en vez del nmero. Una conversin casi, consiste en colocar el tipo
de dato deseado, entre parntesis, delante de la variable a la cual queremos
cambiarle de tipo solo para la operacin actual.
Hay gente que practica el "ASCn Art" (Arte ASCII), que consiste en
disear figuras utilizando nicamente caracteres ASCII, se realizan reidos
torneos internacionales para premiar la mejor creacin ASCII. Puede
buscar en www.google.com "Arte ASCII", inclusive encontrar programas
en donde se ingresa una imagen y sta sale en caracteres ASCII.
Adicionalmente, el lector debe saber que, debido a la necesidad de
incorporar al juego de caracteres otros smbolos y alfabe"tos de otros
idiomas, y que stos rebasan la capacidad que puede almacenarse en
variables de un byte (tipo char en DOS), se ampli este juego de caracteres,
denominndose a este nuevo estndar UNICODE en donde cada cdigo
ocupa 2 bytes por lo que puede tener un mximo de 65,536 cdigos (esto es
i
6
), es por ello que en los sistemas que lo utilizan, como Windows, cada
variable de tipo char ocupa 2 bytes.
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Cadena de Caracteres 19
Solucin:
Ya sabemos que los primeros 32 caracteres de la Tabla ASCII son
caracteres de control. Con el fin de poder represet1tarlos en el cdigo
fuente, se recurri al artificio de utilizar la barra invertida ( \ ) seguida de
una serie de caracteres; estas son las llamadas Secuencias de Escape o
caracteres de barra invertida, las cuales representan un carcter que
realiza una accin y estn precedidos siempre por \ (back slash).
Adicionalmente, como para su representacin se utilizan los caracteres " \ Y
", se hizo necesario crear secuencias de escape que permitan mostrar estos
caracteres.
Secuencias de Escape
Cdsar Liza A vita. Mis libros son econmicos, no hay razn para copiarlos.
20 Algoritmos y su Codificacin en e + +. Volumen 2.
Csar Liza A vila
Nuestro programa imprime cada una de las secuencias de escape
deseada, mostrando su efecto. Note como podemos utilizar directamente el
cdigo ASCII en vez de la secuencia de escape, y como usamos las
comillas simples', en vez de las dobles ", pues las secuencias de escape
representan un nico carcter.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Solucin:
,
Observando la Tabla de
Cdigos ASen notamos
que las maysculas van
desde el 65 (carcter A)
hasta el 90 (carcter Z) y
que las minsculas van
desde el 97 (carcter a)
hasta el 122 (carcter z)
Es decir, que para convertir
un carcter de mayscula a
minscula se le suma 32
(97 -65), mientras que para
convertirlo de minsculas a
maysculas se le resta 32.
La cadena de caracteres o el
arreglo de caracteres cad[ ]
sirve para almacenar cada
carcter de la frase
ingresada.
Cadena de Caracteres 21
.. -.
..... ,'. :COD1FIGAdNitNC++
. . . .
. ':
Yoi,dcadT91l'lin(chrUJ;
,', ';;e ',: ......... ;:
[LM]i . . ',,{.,-
'. -'
, .. ,....:
;' :cout}'la qil.denaeq' lililissulases

. < .... ,yv ....

.. >
.< ','.;4," .:. e "
La funcin cadToMin( ) aprovecha el hecho que las cadenas de
caracteres siempre terminan en NULL. Esta funcin toma uno a uno los
caracteres y si estn en maysculas, esto es su cdigo est entre 65 y 90, les
suma 32 para convertirlas a minsculas (cad[i] = cad[i] + 32).
Recuerde que, todo cambio que haga una funcin sobre un arreglo,
ser conocido por el resto del programa, por ello no es necesaria la
sentencia return para devolver la nueva cadena. Esto es, debido a que los
arreglos se pasan a las funciones por referencia. Comprender ms sobre
ello en el captulo sobre punteros.
Csar Liza Avila. Mis libros son econmicos, 110 hay razn para copiarlos.
22 Algoritl1lo.! y su Codi/icllt"in en C++. Volumen 2. Csar Liza A vi/a
Solucin:
.Las sumas de verificacin, son tcnicas no criptogrficas que permiten
detectar errores en la transmisin de mensajes. Consiste en calcular un
valor (checksum) a partir de una serie de caracteres. Cuando enviamos un
mensaje, tambin enviamos su checksum, el destinatario puede entonces
calcular el cbecksum al mensaje y compararlo con el checksum recibido,
si fueran distintos habr un error en la transmisin del mensaje. Un ejemplo
de sumas de verificacin son los CRC's o Cdigos de Redundancia
Cclica, como el CRC-32, o el Protocolo de Datagrama de usuario UDP,
entre otros. Un algoritmo sencillo para calcular el checksum es sumar los
cdigos ASCII (o UNICODE) y obtener la suma como residuo de 2
32
, es
decir para el caso que la suma sobrepase el lmite de los enteros (4 bytes
32 bits) la suma de verificacin contendr el residuo respecto a 2
32

. . La sentencIa ,>'
cm.gethne(cad, LlM) lee caracteres . .
desde el teclado y los
en frase hasta un mximo de
LIM. El ingreso termina cuando
se presiona enter y, a diferencia
de cin, ste ltimo adems
termina la lectura, con el primer
espacio en blanco o con la tecla
tab, por lo que cin no puede
usarse para ingresar una frase.
La funcin checkSum(
), toma cada carcter ( for (i=O;
frase[i]; i++) ) calculando la
suma de sus cdigos ASCII,
(s+=frase[i] ) esto es a pesar
que frase[i] es de tipo charo
- En C/C++/C# no debemos preocupamos por obtener del residuo
respecto a 2
32
, puesto que para tipos unsigned, cuando rebasamos este
lmite, automticamente se regresa la cuenta a cero.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Cadena de Caracteres 23
Los algoritmos de suma de verificacin estn persados para la transmisin
de mensajes por canales no maliciosos, pues es fcil alterar el mensaje sin
que vare el checksum. Los llamados CCV (cryptographic check values)
evitan esto, y son simlares a las sumas de verificacin con la diferencia
que usa una funcin hjlsh para
que dos mensajes diferentes no
tengan el mismo checksum.
Estos algoritmos son de
dominio pblico, no hay claves
y cualquiera puede cal,?ularlas.
Entre ellos podemos resaltar:
SHA-l (Secure Hash Algorithm),
RIPEMD-160, MDS (Message
Digest A 19orithms) , de ellos el
.,.,.
" ..... ,
..
ms usado es el MD5 implementado, por ejemplo, en el MD5Summer
(www.md5summer.org). en el fileAlyzer (http://www.safcr-nclwOrking.org/es/
downJoadlindex.html, de paso le sugiero descargar en la misma pgina el Spybot -
Search & Destroy excelente software detector de spywares o software espa).
Muchas pginas en Internet muestran los MD5 qe los archivos, con el fin
que el usuario al descargarlos compruebe que no han sufrido alteraciones
(por ejemplo, la pgina de descarga del Spybot - Search & Destroy usa los MD5).
Programas como los antivirus, usan un CCV para actualizarse, otros 10
crean para archivos ejecutables y notar si han sido alterados. El uso comn
hace que tanto los checksum como los CCV sean llamados solo
checksum, pero usted ya conoce las diferencias.
Para autenticar el emisario, se usan los llamados MAC (Cdigos de
Autenticacin de Mensajes). En ellos tanto el emisor como el receptor
comparten una clave, lo que permite al recept9rverificar si el documento es
autntico y que fue enviado por quien dice enviarlo. Es similar a una
funcin hash, es decir se aplica a un mensaje y genera un valor MAC, pero
las hash no tienen claves, mientras que las MAC si. Entre ellos destaca
CBC-DES, HMAC, UMAC, PMAC.
Una tcnica an ms poderosa son las firmas digitales, que permiten al
receptor verificar la autenticidad e integridad del mensaje, es decir el
emisor no puede negar la autora del mensaje, pues es el nico poseedor
de la clave, a diferencia de las MAC donde la clave es compartida por
varias entidades. Ejemplos de algoritmos para firmas digitales tenemos:
RSA, ESIGN (Efficient digital SIGNAture), MacEliece, entre otros.
Csar Liza A vilo. Mis libros son econmicos, no hay razn para copiarlos.
\1
24 Algoritmos)! su Codificacin en C+ +. Volumen 2.
Csar LiGa A ]lila
Solucin:
Cada carcter de la cadena ingresada, por ejemplo "581", es un smbolo
que representa un nmero, pero no es el valor del nmero. As '8' es el
carcter ocho, y no el valor 8. Nuestro programa debe lograr que a partir de
la cadena "581" de tipo mar I ], obtengamos el valor de 581 de tipo Ini.

48 'O'
49 '1 '
50 '2'
51 '3'
Para ello nos apoyamos en el subconjunto mostrado de la
Tabla ASCII, del cual deducimos, que si deseamos el
valor numrico correspondiente al "carcter nmero",
necesitamos restar 48 a cada ASCn que represente el
nmero.
52 '4'
53 '5'
La cadena "581" se representara como:
1'5' I '8' 1 '1' I NULL I
Pero internamente se almacenar como:
54 '6'
55
56
57
'7'
'8'
'9'
Si restamos 48 a cada cdigo y lo multiplicamos por su
valor posicional correspondiente tendremos: (53-
48)xl0x10 + (56-48)xl0 + (49-48) = 581
\
Esto es lo que hacemos en
nuestro programa. La funcin
cadTolnt( ), procesa cada
carcter ( while (cad[i) !=
NULL), recuerde que toda
cadena termina en NULL )
restndole 48 (cad[i]-48), y
va acumulando el resultado
no sin antes aumentar un
valor posicional al resultado
anterior (nro*10).
".' ........ CODIFIcCtoNEN'++ "' ..
;..'
'".' {,J.:, ;:'
-:},>' ,t(:;} "'';'. ";".,,".; .
" ".; . '
irttc(lT
o
l*Ccr<tt ;cadf n
.{
. \yhi1 e(cad[i] !;'NULt)'
{oro;= nm,*l (J +
<9 Csar Liza A vila. No mates la produccin intelectual, /lO copies ste libro.
:.pal(kj'=3 NUL,L;

"
Cadena de Cara(:teres 25
iniciamos una
palabra haciendo que la siguiente palabra tenga cero caracteres (k=O).
Csar Liza Avila. Mis libros son econmicos, 110 IllIr razn para copiar/os.
1
26 Algoritmos y su Codificacin en C++. Volumen 2.
Solucin:
La funcin leerFrase( ),
hace lo pedido. En ella el
mtodo cout.flush( ), obliga
a mostrar por pantalla todas
las salidas que an no han
sido impresas. El bucle do{
}while (fraseri-l]!=l3); se
repite mientras el carcter
ingresado no sea ENTER
(ASCII 13). Dicho carcter
es ledo en frase[i]= (unsigned
char) getch( ); la' funcin
getch( ), devuelve el entero
correspondiente al ASCII de
la tecla pulsada y su
prototipo se encuentra en
conio.h, razn por la cual lo
incluimos al inicio del
programa. S i pulsamos
cualquier tecla diferente de
BackSpace (BS, ASCII 8),
entonces lo imprnmmos
hacindolo parte de la frase
(i++), De haber sido BS,
eliminamos el ltimo
carcter (i--), siempre y
cuando exista (i>O).
Csar Liza Avila
modificar nuestra funcin leerFrase( ), para permitir slo el
mgreso de nmeros, slo letras, slo maysculas, o minsculas, es decir un
control de los caracteres cuyo ingreso aceptamos, inclusive cuando
mgresemos un password podemos mostrar el carcter que deseemos.
@ Csar Liza Avila. No males la produccin intelectual, 110 copies ste libro.
-, w-
SoluCin:
Este tipo de
encriptamiento consiste
en cambiar un carcter
por otro, utilizando la
tabla ASCII. Para ello
reemplazamos cada
carcter por otro
ubicado a una distancia
igual al ASCII de la
clave utilizada.
Nuestra funcin
encriptar( ), toma cada
carcter mientras no sea
CERO o NULL, esto
se escribe de manera
simplificada en el for,
como frase[i], que
equivale a escribir
frase[i]!=NULL. A
cada carcter le
sumamos el cdigo
ASCII de la clave,
transformndolo en otro
cdigo y por ende en
otro smbolo.
Cadena de Caracteres 27
El proceso de desencriptado es similar, pero ahora desencriptar( ) resta a
cada carcter el cdigo ASCII de la clave, retornndola a su cdigo
original.
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
28 Algoritmos y su Codificacin en C++. Volumen 2. Csar Uza A vila
i.
Solucin:
Dado que la tabla ASCII es estndar, el algoritmo de encriptamiento del
problema anterior (2.8) tiene algunas desventajas. Sin embargo, podemos
mejorarlo definiendo nuestra propia tabla de caracteres a reniplazar.
La cadena (arreglo de caracteres) tablal contiene los caracteres que
deseamos sean remplazados por otros, aqueUos que no estn en esta tabla
no sern remplazados. La cadena tabla2, contiene los caracteres de
reemplazo, observe que la tabla2 debe tener la misma cantidad de
caracteres que la tablal, no debe tener caracteres repetidos y es posible que
tenga cualquiera de los 256 caracteres ASCII, a excepcin del NULL, que
es usado como terminador de cadena.
Note como
inicializamos tablal,
tabla2 y cad, en lugar
de ingresarlas desde
teclado.
}
'i;; '
--
"I ....
(.) ("psar Liza Avila. No Illllfes la produccin intelectual. 110 copies t5ste libro.
La funcin encripta( ),
toma cada carcter de la
cadena a encriptar cad[i]
y lo busca en la cadena tl
( ir (cad[i] == HU] ), si lo
encuentra lo reemplaza
con el carcter asociado
(cad[i] = t2[j]) Y sale del
bucle ms intemo
(break), para tomar el
siguiente carcter a
encriptar.
La funcin desencripta( )
es similar, nada mas que
ahora busca el carcter en
la t2, y lo remplaza por su
carcter correspondiente
en tl.
Cadella de Carac,tere.\ 29
Aunque es valido inicializar la cadena tal como se muestra, es
recomendable encriptar las tablal y tabla2 y mejor aun, inicializarlas
usando sus cdigos ASCII en vez de los caracteres. Esto es as, puesto que
con un editor
hexadecimal
es posible ver
las cadenas
definidas
como
constantes
dentro de
nuestro
ejecutable; tal
como se
puede
observar al
utilizar el
FileAlyzer.
na.
3A2:000GO ('DOOOOOO 43i,164GE. .... f e
6E6.s";29 ,07461':4 61'202021) .3.t.2 1)OO
__

,)(!OCOOOOO OClOODOOO r-07S420 8('1 ':4C:I)Ct -.- ... _L..:.l' .:;-r,j:
oonOO(Jf)O 20;f,4?OQ -;OUA!)(:O
000:)(:000 f:rSOGI)(!O 696F7:37<\ f<.t?IS.E.6?
.textOOO . .. " ,,'
... J.:.sttini
(i;) Char Liza Avila. Mis libros son econmicos, 110 ha,- ra;::n para ("Ol/illrlo\'.
...:J
30 Algoritmos y su Codificacin en C+ +. Volumen 2.
Solucin:
La funcin
mayorPalabrn( ), toma
cada carcter de cada
cadena y los compara.
Si son diferentes retorna
la diferencia de los
cdigos ASCII del
carcter de la primera
cadena, con el carcter de
la segunda.
. Si esta diferencia es
mayor que O, la primera
palabra ser
alfabticamente mayor
que la segunda.
Si retorna menor que O,
la primera palabra ser
alfabticamente menor.
En caso de no ser ni
mayor ni menor pasamos
a probar el siguiente
carcter (i++).
De haber' analizado todos
los caracteres, salimos del
buclewhile, y retornamos
O indicando que son
iguales.
Csar Liza Avila
ID Csar Liza Avila. No mutes la produccin intelectual, 110 copies ste libro.
Cadena de Caracteres 3 J
Solucin:
La librera estndar ctype.h, contiene un conjunto de macros y funciones,
que nos permiten saber si un carcter es un dgito, una letra, convertirla a
maysculas o minsculas, si s un signo de puntuacin, entre otras.
El programa adjunto hace uso de esta librera.
, . "."
. " 1.' . ",,,
,,:;5,,:" thf;:: ;
, !,., '
, 1"' 1
Recuerde, si una funcin devuelve un valor siempre podr usarlo en una
expresin condicional
ir ( isdigitCl ') ) cout"Es dgito";
else cout"No es dgito";
Csar Liza Avila. Mis libros son ecof/rni('us, no hay razn pam copiar/os.
,1
:1
:1
32 Algoritmos y su Codificacin en C+ +. \lo/limen 2. Csar Liza A vila
Solucin:
Debido a que el e, no cuenta con el tipo base string, lo implementa como
un arreglo de tipo char, en donde el fin de cadena es indicado por el
terminador NULL y, siendo tan frecuente su uso, es que los compiladores
del lenguaje e, proveen el archivo string.h, el cual contiene las
declaraciones prototipo de funciones para manejo de cadenas, algunas de
las cuales mostramos en el siguiente cuadro.
strcmp( )
strupr( )
strncat( )
strcpy( )
strncpy( ) rmrnpr,,< caracteres de una
strstr( )
strchr( ) un carcter (car) dentro de la
). Si lo encuentra devuelve UIl puntero a
sino devuelve NULL.
if(stremp(el, (2)==0)
{ ,"
strupr(ead)
strlwr(ead)
stmeat(el, e2, n)
strepy(e 1, (2)
strnepy( el, e2, n)
strstr(el, c2)
strchr( el, car)
(i':l Csar Liza A vila. No la pruducn intelectual. /lO copie.\ ste libro.
Cadena de Caracteres 33




"." .. "'

strcat(
cot "Ahora lil,c;adJ, '" .,;
Csar Li::.a A vila. Mis libros son econmicos, /lO ha" razn para CflJliarlos.
34 Algoritmos y su Codificacin en e + +. Volumen 2.
. Csar Liza A vila
Le sugiero probar el uso d ~ las funciones strncmp( ), strstr( ),
strchr( ), strrchr( ), entre otras, que no han sido utilizas en este programa.
Otras funciones interesantes para el manejo de cadenas se
encuentran en stdlib.h, y mostramos su uso en un pequeo ejemplo
adicional.
# inclllde <iostream.h>
# inclllde <stdlib.h>
void main(void)
{
int entero = atoi ("123");
double doble = atof.("567.45");
long largo = atol ("1234567890");
char cad[IOO];
int base = 2;
itoa (722, cad. base);
cout"cadena a entero :" entero endl;
cout"cadena a doble :" doble endl;
cout"cadena a long :" largo endl;
cout"Entero a cadena en base dada: " cad endl;
L
' \
1\
(0 C.l(lr Li;:a Avila. No m a t e ~ la produccin intelectual, /'lO copies ste libro.
fe,.
Cadena de Caracteres 35 .
Solucin:
Nuestro algoritmo consiste en:
Tomar el prmer carcter y compararlo con el ltimo,
Tomar el segundo carcter y compararlo con el penltimo,
Tomar el tercer carcter y compararlo con el antepenltimo,
y as sucesivamente. Si alguna vez los caracteres han sido diferentes
retomar CERO, o sea falso, no es palndroma, pero en caso de haber
evaluado todos los caracteres retomaremos 1, indicando que es
palndroma. Para obtener la cantidad de caracteres que tiene una palabra
usamos la funcin strkn( ), cuyo prototipo se encuentra en string.h, razn
por la cual la incluimos al inicio del programa.
Csar Liza A vi/a. Mis libros son econmicos. no hay razn para copiarlos.
l,
36 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza A vila
i. Escriba una funcin que devuelva la posicin de la primera
de un carcter dentro de una cadena. Por ejemplo, la przmera
ocurrencia de 'a' en "ulala" esta en la posicin 2. Si no existe que
devuelva -l. No use strchr( ).
2. Escriba una funcin que reemplace todas las ocurrencias de un
carcter por otro. ,., .,
3. Dados dos palabras muestre las letras que estan en la
4. Escriba un pequeo corrector ortogrfico que haga lo slgUlente: SI la
palabra termina en "don" agrguele el tilde
5. A una cadena se le ha cambiado los caracteres de las pOSICIOnes pares
por las impares. Obtenga la cadena original. Por ejemplo, si .ingresa
use pirro debe obtener superior. Sugerencia: use un algorztmo de
intercambio.
6. Convierta una frase de minsculas a maysculas.
7. Escriba una funcin que permita ingresar un password, mostrando
asteriscos *, para cada carcter. El password ser
dentro del programa, para que 110 pueda ser VIsto por algun edaor
hexadecimal.
8. Diga si una frase es palndroma, esto es leda de izquierda a derecha
es lo mismo que de derecha a izquierda. Sugerencia: Lea la frase con
gets( ), cill.getline( ) o con nuestra funcin del p:oblema
1.7, luego elimine los espacios en blanco y determme Si es palmdroma.
Por ejemplo, "Abajo me mojaba" y "Anita la gorda lagartona no
traga la droga latina" son frases palindromas.
9. Lea un nmero entero y escriba una funcin que obtenga una cadena
COIl el nmero. Por ejemplo, para el entero 384 debe obtener la cadena
"384". No use itoa( ).
i O. Lea una cadena que representa un nmero con punto decimal y
transfrmela a nmero Por ejemplo, la cadena "183.59" ser el
nmero 183.59. No use ato/( ).
i 1. Lea un nmero con punto decimal y obtenga una cadena. Por ejemplo,
si el nmero es 38.72, la cadena ser "38.72".
12, Escriba un programa que verifique si un mensaje ha sido alterado.
Sugerencia: use un checksum.
@ Csar Liza Avila. No mates la produccin intelectual, 110 copies ste libro.
Cadena de Caracteres 37
13. Lea una frase y convierta cada letra inicial a maysculas. Por ejemplo,
"juan prez mamani" ser "Juan Prez Mamani".
14. Escriba un programa que diga cul es la palabra ms Larga de una
frase indicando el nmero de letras.
15. Obtenga una subcadena empezando desde una posicin inicial hasta
otra final. Por ejemplo, dada la cadena "La belleza est en los ojos del
que ama", la subcadena desde la posicin 3 hasta la 10 es "belleza".
Usted debe realmente obtener la subcadena no imprimir desde esos
subindices
16. Escriba ufJa funcin que concatene dos cadenas. Por ejemplo: las
cadenas "ojitos" y "lindos", concatenadas ser "ojitoslindos': No use
strcat( ). Usted realmente debe concatenar las cadenas y no slo
imprimirlas juntas.
17. Lea tres enteros que representen las horas, minutos y segundos y forme
una cadena. Por ejemplo: h= 10, m=20 y s=45, la cadena ser
"10:20:45".
18. Escriba su propia funcin que busque una cadena dentro de otra. No
use strstr( ). .
19. Cuntas letras diferentes tiene una palabra ingresada por teclado?
20. Una forma de encriptar un mensaje con clave de varios caracteres es
repetir la clave hasta tener el tamao del mensaje a encriptar y luego
sumar cada ASCII del mensaje con cada ASCII de la clave. Por
ejemplo:
Mensaje = "Arriba Per"
Clave = "abc."
Sera:
lA', r 1 r b a I pie l. r NULL
I a I b I c I a I b I c I a lb' UiJILNULL I
Luego debemos sumar los cdigos ASCII de 'A' con 'a', 'r' con 'b',
'r' con 'e' y as sucesivamente, obteniendo el mensaje eniptado. Para
desencriptalo tendramos que ingresar nuevamente la clave, repetir la
clave hasta tener el tamaiO del mensaje y luego restarlos del ASClI de
cada carcter del mensaje encriptado.
@ Csar Liza Avila. Mis lihros son econmicos, /10 hay razn para copiarlos.
;1'
~ " :
I
,
J
Arreglos
Bidimensionales .
Arreglos Bidimensionales 41
Solucion:
Una matriz o arreglo bidimensional es
un conjunto de nmeros dispuestos en
f filas (lneas horizontales) y c
columnas (lneas verticales). Se dice
que la matriz es de orden fxc, mientras
, que si tuviera igual cantidad de filas y
columnas sera una matriz cuadrada.

aO,1 a 0,2 ... a O,c-I


al,O al,1 31.2 .. a l,<:1
A= az.o a2,1 a2,2.1 .. 32,e_1
aCIJ) al'_I,1 ar-I,2'" ar-l,c_1
fxc
Cada elemento aij, queda identificado mediante su fila i, y colunma
j en la que se encuentra. En CIC++ y C# los subndices empiezan desde
cero y se indican encerrados entre corchetes. As por ejemplo, el elemento
que se encuentra ubicado en la tercera fila, segunda columna es el a[2](l].
Definimos dos constantes
simblicas FIL y COL, que
indicarn la cantidad mxima de
filas y columnas que contendr
nuestro arreglo, en este caso 50.
Una matriz en CIC++ se declara
indicando el tipo de dato, seguido
de las dimensiones mximas para
las filas y colunmas encerradas
entre corchetes ( nt m[FIL][COL] ),
como todo arreglo esttico, stas
dimensiones deben' ser constantes,
ya sea que usemos constantes
simblicas (# define FIL SO),
simplemente constantes ( const int
FIL=50; ) o colocando
directamente el valor ( int
',' 6IFlACONEN c++ '
#jcltqe<isttealn,h?; ",'
'"
#defille COL 50',:';'>
void 'lerMatdz(rit[ J [COL1,iht; nt);
YOi(i,ir6pMatrz'(iit[][CoJ:Jtillt, lnt); ,',"
, "'"" ", .. " .." 0.'", . -",>;;'."' _', - """"" .. ' ,"o":.
'i.' ;"Jj
v614ffiiWCyptd),t'F .:; ",'

,:-iriJhc; '"

miMatdz(a f;,ey':'" ',o,"
} I,lfinm,<llfl()':";",

m[50][50] ). Luego de ingresar la cantidad mxima de filas y cobmmas que
realmente tendr nuestra matriz leemos sus elementos invocando a la
funcin leerMatriz( ), y los imprimimos invocando a impMatriz( ).
Csar Liza A vilcl, Mis libros son econmicos, no hay razn pam copiarlos.
...
42 Algoritmos y su Codificacin en C+ +. Volumen 2.
La funcin leerMatriz( ) acepta 3
argumentos. El primero, de ellos
(m[ )[COL]), es la matriz en
donde deseamos ingresar los datos
(en realidad es la direccin de
. memoria a partir de la cual se
almacenan los elementos). El
segundo, la cantidad de filas que
deseamos leer; mientras que el
tercer argumento indica la
cantidad de columnas de la
matriz. Esta funcin utiliza dos
bucles para poder leer todos los
elementos de la matriz. La
variable j representa las columnas
y controla el bucle ms interno
Csar Liza A vla
poi lo que Ilumenta ms que las filas; esto significa que el ingreso se
har fila por lila y dentro de cada fila se leern cada una de sus columnas.
De manera similar, la' funcin impMatriz( ) toma cada elemento
imprimindolo.
Cuando pasamos como parmetro un arreglo (m), lo hacemos
indicndole su nombre ( leerMatriz(m, f, c) o impMatriz(m, f, c) ), pero al
declarar el argumento es necesario indicade a la funcin la cantidad .
mxima de columnas que'tendr (void leerMatriz(int m[ ][COLJ. int f, int c) o
void impMatriz(int m[ ][COLJ, int f, int c) ), pues el computador LOma esta
cantidad (COL), para calcular la direccin de memoria donde se encuentra
primer elemento de cada fila; y es que, un arreglo bidimensional se
almacena en memoria de manera lineal y consecutiva, esto es se almacena
como si fuera un arreglo unidimensional!, pero sabe cuntos elementos'
debe avanzar (COL) para obtener la siguiente fila.
Al pasar arreglos de cualquier dimensin a una funcin, lo que
realmente se pasa es la direccin de inicio del arreglo y no sus valores. Es
por ello que el paso de arreglos es un paso de parmetros por referencia y
no por valor. As los cambios que se hagan al arreglo dentro de la funcin
sern reconocidos por maine ), sin de una sentencia return,
siendo las funciones leerMatriz( ) e impMatriz( ) de tipo void.
(O Csar Liza Avila. No mates la produccii'i intelectual. no copies ste libro.
(
Arreglos Bidimensionales 43
Solucin:
A de f filas y e columnas, la de A se denota por
A, Y se obttene colocando las filas (o columnas) de A como columnas (o
filas)en Al. I
Por ejemplo,
matriz
A= G n
3x2
su transpuesta ser
Es decir tomamos cada
fila y la convertimos en
columna, o lo que es lo
mismo cada 'elemento
de la matriz original mij
ahora ser mji'
La nueva matriz tendr
e filas y f columnas.
Csar Liza A vila. Mis libros son econmicos, no hay raz.n para copiarlos.
44 Algoritmos y su Codificacin en C++. Volumen 2.
La funcin transpuesta( ), necesita
conocer la matriz original (m), y la matriz
donde se almacenar su transpuesta (t),
adems de la cantidad de filas (f) y colurrmas
(e). En ella usamos los bucles para tomar cada
uno de los elementos de la matriz m,
cambiando sus filas en columnas (t[j][i] =
m[i][j]).
Csar Liza A vila
~ ; ) Csar Liza Avila. No mates le produccin intelectual, no copies ste libro.
Solucin:
Una matriz identidad
tambin llamada unidad o
unitaria, es aquella cuyos
elementos son todos ceros
excepto aquellos que.
pertenecen a la diagonal
principal que son unos. La
diagonal principal de una
matriz esta formado por los
elementos en los que i=j (su
contraparte es la diagonal
secundaria en la cual i+j=n-
1), esto es:
nxn
Por ejemplo la matriz
identidad de orden 4 ser:
En una matriz identidad se cumple:
1 + 1 + 1 + ... (p veces) = p.l
A.I = LA = A
n = 1
Arreglos Bidimensionales 45
Csar Liza Avila. Mis libros son econmicos, no Izav razn para copiarlos.
1
46 Algoritmos y su Codificacin en C++. Vvlwnen 2.
Csar Liza Avila
Solucin:
Una matriz triangular superior, es aquella matriz cuadrada, cuyos elementos
debajo de la diagonal principal son todos ceros, es decir aij = O, para todo
i>j.
a 0.0 aO.1 aO.2' aO.n-1
O a 1.1 a 1.2' .. a I.nl
A= O O a 2.2 .. a 2. n r
O O O ... an-I.n-I
nxn
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
I
En la funcin esTriangular( ), recorremos
todos los elementos preguntando por la
condicin i>j, y si alguno de stos
elementos es diferente de cero, entonces
no es matriz triangular superior (return O).
De recorrer todos los elementos y no
haber encontrado algn valor igual a cero
entonces ser triangular superior (return 1).
Arreglos Bidimensionales 47
Mafr=:i.i Ingresada: ~
1 2 3 41
O 5 6 7
O U 8 9
O O O 10
Es t r ~ a n c ~
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
48 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila
Solucin:
Dadas dos matrices A de orden mxn y B de orden mxp, o sea con el mismo
nmero de filas (m), se denomina matriz ampliada o aumentada a la matriz
resultante de unir ambas, en una nica matriz de orden mx(n+p).
Es decir:
a 0,0 ao,1 a 0,2 a o, n1
a 1,0 a 1,1 al, 2 al, n1
A
= a 2,0 a 2, 1 a 2,2 a 2, n1
am.I,O am.I,1 a mI,2 ,. am-!,n-I
mXn
[,,"
b o, 1 b 0,2
b."]
b 1,0 b 1,1 bl,2 b I,p-I
B b 2,0 b 2, I b 2,2 b 2, p-I
bm-I,O ' bm.I,1 b m-I,2" . bm_l,p.1
mxp
I
a o, 1 a n. 2 a o, n1 :
al,1 a 1. 2 ... a 1. n-I :
I
a 2, I a 2,2 ... a 2, n-I :
I
I
am_I,1 a m.I,2 .am-I,n-I I
I
bo,o b
o
.
1
b
O
,2'" bO,P_I]
bl,o bl,1 bI,2 ... b l,p-1
b 2, o b 2, I b 2, 2 ... b 2, p1
bm-I,o b m-l.1 b m- I,2" .bm-I,p-I
mx(n+p)
C9 Csar Liza Avda. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 49
Nuestro programa obtendr la matriz aumentada solo si ambas matrices
tienen la misma cantidad de filas (f1==f2).
C9 Csar Liza Avila. Mis libros son econmicos, no hav razn para copiar/os.
50 Algoritmos y su Codificacin en C++. Volumen 2.
La funcin matAumentada( ) toma
cada elemento bij y lo aade a partir
de la primera columna libre (el) de
la matriz a ( a[i][c1+j] = b [i]U] ).
Csar Liza A vila
Csar Liza A vi/a. No mates la produccion intelectual, no copies ste libro.
Arreglos Bidimensionales 51
Solucin:
Sea A una matriz de fxc y V un vector, o ms propiamente dicho un vector
columna pues tiene f filas y 1 columna (tambin existen los vectores fila
compuesto por 1 fila y e columna).
a 0.0 a 0.1
r
col
["
aO.2" .aO.n-1
a 1.0 a 1.1 a 1.2" a I.n-I VI
A= a 2.0 a 2.1 a2.2 a2,n.1
'.'
an-I.O an-I.I an-I.2 an-l.n_1 Vn_1
fxc fxl
Si deseamos insertar el vector columna V en la columna col de la matriz A,
tendremos:
col
'ao.o aO.1 aO.2 ... aO.n_1
al.O al,l VI al.2 .. al. n_1
A= a2.0 a2.1 V2 a2.2 .. a2.n_1
, an-I.O an_I,1 Vn_1 an_I.2_ <In-I.n-I
fx(c+l)
Es evidente que para lograr esto debemos "hacer en la matriz,
para poder colocar el vector columna. Esto lo conseguimos desplazando
cada columna de la matriz, empezando desde la ltima (n-1) y hasta l
columna col, luego podemos colocar en dicha columna el vector dado.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos_
52 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Liza A vila
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
En agregaColumna( ), tomamos la ltima
columna (c-l) y copiamos todos sus
elementos hacia la columna siguiente (
m[iJU+l] = m[i][j] ), continuamos con la
columna anterior (j--) hasta la columna en la
cual se insertar el vector (j>=col). En este
punto la columna col y col+ 1 tendrn los
mismos elementos. Finalmente, el ltimo
bucle reemplaza los elementos de la
columna col por los elementos del vector.
Arreglos Bidimensionales 53
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
54 Algoritmos y su Codificacin en C++. Volumen 2.
Solucin:
Si cada fila representa una
fbrica y cada columna un
mes, podremos almacenar
lo que produce cada fbrica
por mes en una celda de
prod[ilu], donde i indica la
fbrica y j el mes de
produccin.
La produccin de todas las
fbricas para un mes
determinado esta dado por
la suma de todos los
elementos de cada columna.
A diferencia de los
programas anteriores, la
matriz prod[ ][ l, es
definida como tipo float,
por lo que las funciones
deben contemplar este tipo.
Luego de leer la cantidad de
fbricas (filas), la cantidad
de meses (colunmas) y de
leer la produccin (matrii')
mostrndola, invocamos a
sumaColumnas( ).
Csar Liza A vi/a
Csar Liza Avda. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 55
En sumaColumnas( ),
tomamos cada columna
(mes) e inicializamos la
suma a cero, recorremos
cada una de sus filas
(fbricas) acumulando cada
valor m[i][j] (produccin de
la fbrica i en el mes j),
luego imprimimos el total
de cada columna (mes).
Note como las filas deben
aumentar ms rpido que
las colurrmas es por esto
que i controla el bucle ms
interno, note adems la
necesidad de inicializar
sumaCol a cero cada vez
que cambiamos de columna.
r,)ntc)

Observe que la funcin sumaColumnas( ),
imprime los resultados. Si hubiramos
deseado que fuera maine ) quien los
imprima, deberamos aadir como
argumento un arreglo unidimensional a
sumaColumna( ), declarado con tamao
mximo COL, pero que contendr e
elementos con la suma de cada columna,
luego como el arreglo (z) es pasado por
referencia, los cambios sobre l hechos por
sumaColumnas( ), sern conocidos por
maine ).
void sumaColumnas(float m[ J[COL), float z[ ) in! f, int e)
( inl i, j;
)
float sumaCol;
for (j=0; j<c; j++)
( z[j) = O;
for (i=O; id; i++) z[j) += m[i)[j);
J
i
Ingrese .Matriz I
Nro de Fabricas?: 3
Nro. de Meses?: 4
Ingrese producciJ(n mensual
Fabrica 0 .
m[O][O]= 1
m[O]U]= 2
m[O][2]= 3
m[OH3]= 4
Fabrica 1
m[ll 101= 5
m[1l111" 6
m[ll [21= 7
m[lH3]= 8
Fabrica 2
m[2][0]= 7
mI2][11= 6
m12] [21= 5
m[2]131= 4
1 2 3 4
5 6 7 8
7 6 5 4
Mes 0 se ha producido 13
Mes 1 se ha producdo 14
Mes 2 se ha producdo 15
Mes 3 se ha roduci o 16
a_
Csar Liza Avila. Mis libros son econmicos, no hay razn para cOJ} ia rlos.
56 Algoritmos y su Codificacin en C++. Volumen 2.
Leemos la posicin
de la reina dentro del
tablero (x, y) e
invocamos a
posiciones( ), para
marcar con 1, los
casilleros a las cuales
s.e puede mover la
reina.
La funcin
inicMatriz( ), llena
de ceros la casilla del
tablero de ajedrez.
Mientras que
impMatriz( ) ha sido
ligeramente
modificada para dar
la impresin de ser un
tablero.
Csar Liza A vila
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 57
Si colocamos la reina en la fila x, columna y, entonces podr moverse en su
misma columna: for 0=0; kMAX; i++) if(i!=x) m[i][y]=l;
o en su misma fila for G=O; j<MAX; j++) ifG!=y) m[x]1=l;
o en diagonal hacia atrs \
restando 1 a la fila y 1 a la
columna
i=x -1 ; j=y-l ;
while(i>=O && j>=O)
{ m[i][j]=l;
i--; j--; }
o avanzando
/
i=x+l;j=y+l;
while(kMAX && j<MAX)
{ m[i][j]=I;
i++;j++; }
o en diagonal hacia adelante /
i=x-l; j=y+ 1;
while(i>=O && j<MAX)
{ m[iJU]=l;
i--;j++; }
i=x+l; j=y-l;
while(i<MAX && j>=O)
( m[i](j]=I;
i++; j--; }
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
1
58 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Solucin:
Para sumar 2 matrices es necesario que ambas tengan la misma cantidad de
filas y columnas, esto se conoce como concordancia de matrices. Sean A y
B dos matrices:
['o
a 0,1 a o, 2 a O,c-1
a 1,0 al,! a1,2 al, c-1
A= a 2,0 a 2,1 a 2,2 a 2,c-1
ar-!,o ar-l.l ar-l,2 ... ar-!,c-l
fxc
["
b 0,1 b 0,2
b.
o
] b 1.0 b 1.1 bu b l,e-1
B = b 2,0 b 2,1 bu b 2, e-I
br-I,o br_I,1 b tCI,2 br-Ie-I
fxc
La suma de ellas nos da otra matriz e con la rrusma cantidad de filas y
columnas (fxc) en donde cada elemento de la m ~ t r i z suma es cj ;;:: aij+bj,
esto es:
C=A+B=
ao.o + b 0,0
al,o+bl,o
a2,o+b 2,o
ao,l+bo,1
a 1,1 + b 1,1
az,l+b 2,1
ar-I,o + bf-I,o 3r_I,1 + br_I,1
aO,2+ b O,2
a 1,2 + b 1,2
a + b 2.2 2, Z
a o, n-I + b o. e-I
a I,n-I + b O,e-I
a 2,n-1 + b O,c-I
af-1,2 + br_I,2 . ,. ar_l.c_1 -1- b r-I;e-I
fxc
Si deseamos obtener la diferencia de matrices solo debemos cambiar el
signo + por el signo - en cada trmino.
Realizamos la suma solo si las matrices son concordantes (f1==f2 &&
c1==c2).
Csar Liza A vila, No mates la produccin intelectuui, ,tu wpies ste libro.
Arreglos Bidimensionales 59
Csar Liza Avila, Mis libros son econmicos, no hay razn para copiarlos.
60 Algoritmos y su Codificacin en C++. Volumen 2.
En sumaMatrices( ) los dos primeros argumentos (a
y b) son las matrices a sumar, mientras que el tercero
(s), es la matriz que contendr la suma y los dos
ltimos son la cantidad de filas y columnas de las
matrices a sumar. Recorremos cada uno de los
elementos i, j de ambas matrices y los sumamos,
colocando dicha suma en el correspondiente elemento
ij de la matriz suma (s[il] = a[i]] + b[iJU]).
Csar Liza A vila
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 161

Sean dos matrices A de orden ifllxcJl y B de orden if2xcZ, entonces el
pwducto AxlB solo se puede realizar si d es igual a--n; esto es, si la
cantidad de columnas de la primera matriz, es igual a la cantidad de filas
de la segunda. Dicho producto es otra matriz 1[1' de orden irbc2, (el orden
est dado por la cantidad de filas de la primera matriz y la cantidad de
columnas de la segunda) tal que cada demento !Pij es igual a:
k=c1-1
Pi.i::: L aik bkj
k=O
donde:
pO,o == aa,O bo.o + ao,! bl,o + aO,2 bz,o + ... + ao,c1-1 bcJ-I,o
PO,I :::: ao,o bo,1 + 30,1 bu + 3o,z bz,1 + ... + 3o,c1-1 bcl-1,1
PO,2 = aa,o bo,2 + 30,1 bu + aO,2 bz,2 + ... + ao,ci-2 bcl - I,2
P i,j = a,O bo,j + ai,l bl,j + a ,2 bz,j + ... + a,cl-2 bcl-1,j
Esto es, cada uno de los elementos de una fila se multiplica con sus
correspondientes elementos de la columna y luego se suma. Por ejemplo:
r; 2 3 41: = U
1

156 l? 6 7 liX1+6X5 5x2+6x6 5x3+6)(7 5x4+6xS 35 46 57 6:1
L - 3x2 3x4 ::J3x3
cada elemento se obtuvo aS: c[ in j] = a[i][k]. b[k][j] + a[i][k].b[kUj]
c[O][O] = a[OJ[O]. b[O][O] + a[O][I].b[lJ[O] == Ixl + 2)(5 == H
c[O][IJ = a[O][O]. b[O][l] + a[O][1].b"[l][!] '" Ix2 + 2x6 = 1[4
c[O][2] = a[O][O]. b[O][2] + a[O][1].b[l][2] = Ix3 + 2x7 = 17
c[0][3] == a[O][O]. b[O][3] + a[O](l].b[1][3] :: lx4 + 2x8 =
c[lJ[O] := a[l][O]. b[l][O] + a[l][l].b[l][O] '" 3x1 + 4x5 = 23
c(IJ[l] == a[l][O]. b[I][l] + a[l][l].b[l](l] == 3x2 + 4)(6 = 30
c[1][2] == a[IJ[O]. b[IJ[2] + a[1][1].b[1][2] = 3)(3 + 4x7 = 37
c[I][3] :: a[l][O]. b[l][3] + a[1J[1].b[1][3] = 3x4 + 4x8 = 44
c[2][O] == a[2][O]. b[2][O] + a[2][I].b[1][O] == SxI + 6x5 = 35
c[2][1] == a[2][O]. b[2][1] + a[2J[1].b[1][1] == 5x2 + 6x6 == 46
c[2][2] = a[2][O]. b[2][2] + a[2][1].b[1][2] == 5x3 + 6x7 = 57
c[2][3] = a[2][O]. b[2][3] + a[2][1].b[1][3] = 5x4 + 6x8 = 68
La multiplicacin no es conmutativa, es decir A.B i B.A.
Csar Liza Avda. Mis libros son econmicos, no hay razn para copiarlos.
62 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
En nuestro programa, luego de ingresar las matrices, comprobamos J.a:
conformidad respecto a la multiplicacin (c1==f2), de serlo, mostramos las
matrices, procedemos a multiplicarlas e imprimir la matliz producto.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
La funcin multMatrices( ), acepta las
dos matrices a multiplicar (a y b), Y la
matriz producto p, adems de la cantidad
de filas y columnas de cada matriz, pero
comoc1 es igual a f2, solo pasamos fl, el
Y c2 como parmetros. En esta funcin
tomamos cada elemento de la matriz
resultante de orden flxc2, con el fin de
calcularlos, de ah la necesidad de los dos
primeros bucles i, j.
Arreglos Ridimensionules 6J
El tercer bucle (k), es el encargado del clculo, acumulando la suma de los
productos respectivos en p[i]U], es por eso la necesidad de inicializarlo a
cero (p[ilUl=O).
Csar Liza Avila. Mis lihms son econm.icos, no ha\' rm.tI1IJara copiar/os.
64 AIF,ormos y su Codificacin en C+ +. Volumen 2. Csar Lim A vilo
Solucin:
Cada matriz cuadrada tiene un nmero importante llamado determinante,
que refleja algunas propiedades. Una de ellas es determinar si un conjunto
de ecuaciones simultneas tiene solucin nica, como veremos ms
adelante,
La determinante de la matriz A de orden n, se denota por det(A) o
tambin IAI y se define como: IAI = I () a,Oaj,tak,2, 000 , ar,n_; donde la
sumatoria se hace sobre todas las permutaciones de los primeros subndices
de a, y se toma el signo +, si la permutacin es par y - si es impar.
Por ejemplo para una matriz de 2x2 tenemos:
IAI :::: I aoo
alO
Para una matriz de 3x3, la determinante ser:
aoo <101 a02
IAI = alO al1 a12
a20 a21 a22
= aOO all an + alO a21 a02 + a20 aOI an
- aoo a21 al2 - aJO aOI a22 - a20 a)) <102
Sin embargo, la obtencin de la determinante de una matriz de
orden mayor a .., no resulta tan fcil, ya que la cantidad de permutaciones
crece rpidamente. Para una matriz de 2 x 2 ser 21 = 2 trminos, para una
de orden 3 ser 31=6 trminos, para una de 5 ser 51 = 120 trminos y
siempr,e hay que calcular productos, por lo cual no es un mtodo prctico
cuando el orden es mayor que 3.
Existen otros mtodos para obtener la determinante, entre ellos
tenemos la Regla de Sarrus que se ensea en el colegio y sirve para
obtener determinantes de matrices de 3x3, el clculo de la determinante por
menor complementario, por el adjunto de un elemento y por los cofactores
que se puede implementar fcilmente usando una versin recursiva que
calcule la determinante de una matriz de orden n-}. La recursin se trata
extensamente en mi libro Estructuras de Datos con C/C++. Asimismo
podemos aplicar la descomposicin LV, () la eliminacin de Gauss en su
Csar Liz.a Avila. No mates la produccin intelectual, no copies ste libro.
ArreF,los Bidim.ensiollales 65
etapa de eliminacin hacia adelante. Este ltimo mtodo nos 'parece ms
conveniente de implementar en computadoras y; adems, nos servir para
resolver un sistema de ecuaciones lineales homogneo y calcular la inversa
de una matriz, las cuales se vern en los siguientes problemas.
La eliminacin hacia adelante consiste en aplicar operaciones
fundamentales como suma, resta y multiplicacin sobre las filas de la
matriz, para transformarla en una matriz triangular superior equivalente.
Esto es a partir de
debemos lograr
A
[
a o. o
a 1,0
a 2.0
a n_1.0
aO.1
a 1.1
a 2, I
an-u
aO, o aO.1
O a'!. 1
A'=: O O
[
' ,
O O
a 0.2
a 1,2
a 2,2
an1,2
a'O,2
a'1.2
a'2,2
o
ao,n_l]
al, ni
... a 2.n.1
, . , an l,n1
nxn
a,o,n.l]
a'I,n.1
a'2, n-I
a".I,n.1
nxn
Cada elemento a'jj, donde i=j se denomina pivote. El elemento
pivote es el mayor elemento (en valor absoluto) de la columna en la cual se
est haciendo ceros los coeficientes debajo de a'ij. Usar pivote en la
eliminacin haca adelante, tiene dos ventajas: Primero, superar la
dificultad que presentan los coeficientes nulos en la diagonal, si esto ocurre
debemos intercambiar las fijas para que el pivote sea diferente de cero;
cuando encontramos ceros en la diagonal no se pueden eliminar el resto de
elementos de esa columna, asimismo cuando tratamos de encontrar la
solucin de un sistema de ecuaciones lineales o la inversa no es posible
pues el algoritmo exige que se divida entre este nmero, al ser cero esa
divisin no se puede realizar. Segundo, cuando escogemos el pivote como
el mayor elemento en valor absoluto de la columna; nos permite reducir los
errores de redondeo en los clculos.
Una vez conseguida la matriz triangular equivalente, la
determinante estar dada por el producto de todos los trminos de la
diagonal principal, la cllal estar afectada por el signo - si se hizo un
nmero impar de intercambios, o + si se hizo un nmero par ae
intercambios
Csar Liza A \'la. Mis libros son econmicos, 110 hay razn para copiar/os.
66 Algoritmos y su Codificf/cil1 en CH'. Volumen 2. Csar Liza A vila
Si por ejemplo desearnos obtener la determinante de la matriz
l
-3 1]
-1 1 -3
-4 5 2
Para la primera columna
a) Buscamos la fila pivote, es decir la fila con el mayor elemento en
valor absoluto de la primera columna. El mayor entre 2, -1 y -4, en
valor absoluto, es -4, ubicado en la tercera fila.
Intercambiamos la primera fila (es la que estamos procesando) con
la tercera fila, obteniendo:
b) Mediante operaciones elementales hacemos cero todos los
elementos de la primera columna, pero sin alterar la primera fila.
Para hacer cero la primera columna de la segunda fila,
multiplicamos la primera fila por --(-1/-4) esto es, el elemento
actual (-1) entre el pivote (-4), y le sumamos a la segunda fila,
colocando el resultado en la segunda fila:
[
4 5 2J
O -114 -7/2
2 -3 l
Para hacer cero la primera columna de la tercera fila, multiplicamos
la primera fila por -(2/-4) esto es, el elemento actual entre el
pivote, le sumamos a la tercera fila, colocando el resultado en la
tercera fi la:
[
4 5 2J
O -1/4 -7/2
O -112 2
<l) Csar Liza Avila. No mates la produccin intelectual, 110 copies ste lihro.
ArreRlos Rlimetlswnales 67
'lomamos la siguiente columna
a) Buscamos la fila pivote, es decir la fila con el mayor elemento en
valor absoluto de la segunda columna (pero excluyendo el
elemento de la primera fila, pues ya lo procesamos). El mayor entre
-1/4 y -112, en valor absoluto es -112, ubicado en la tercera fila.
Intercambiamos la segunda fila (es la que estamos procesando) con
la tercera fila, obteniendo:
[
4 5 2J
O -1/2 2
O -1/4 -7/2
b) Mediante operaciones elementales hacemos cero todos los
elementos de la segunda columna, pero sin alterar la primera y
segunda filas.
Para hacer cero la segunda columna de la tercera fila,
multiplicamos la segunda fila por -(-1/4/-1/2) esto es el elemento
actual (-1/4) entre el pivote (-1/2); le sumamos a la tercera fila,
colocando el resultado en la tercera fila:
[
4 5
O -1/2
O O
Como ya conseguirnos mediante operaciones elementales convertir
la matriz original en una matriz triangular superior equivalente,
podemos calcular fcilmente la determinante multiplicando los
elementos de la diagonal y adems como hicimos dos intercambios
entonces la determinante estar dado por (-1) 1 (-4)(-1/2)( -9/2) () sea
-9.
Csar Liza Avda. Mis libros son econnic,'s, no ha.'" raen para copiarlos.
68 Algoritmos)' su Codificacin en C++. Volumen 2.
C>sar Liza A vila
En el programa, una vez ingresada la matriz obtenemos su matriz t;iangular
equivalente mediante eliminaAdelante( ), la cual el de
intercambios realizados durante el proceso de elmunaclOn, luego
imprimirnos dicha matriz.
La determinante la calculamos multiplicando todos los elementos de la
diagonal principal (det::det*m[i][i}), Y si se realiz un nmero impar de
intercambios ( if(nIntercambio%2==1) ) afectaremos a este producto con el
signo menos (det=-det).
.. ,,,,' ,
'#incl
,,', "" "'"
",# delne ,,'"
1 [Co.q ,il,1t;'jri;t) , '
[][CpL),inf,jpt);i' " '., "
";, ',' " irt,dollbJe'( ,
[C8
L
]); "'j',:;:,: '
'/jI """. ',,'
',' "'iC" ."
(jet::,!; .
': int i: ti, ,

, ,..;. .
...
del;
} :
(e) Clsar Uz.,a Avifa. No mates la produccin intelectual, /lO copies ste libro.
..
La funcin pivote( ), se
encarga de encontrar la
fila (piv) que contiene el
elemento de mayor valor
absoluto de una columna
determinada (i), pero a
partir de la fila i, en este
caso i es tanto la fila
como la columna inicial,
a partir de la cual se
lmclar la bsqueda
(for(j=i+l; j<n; j++)).
La funcin
intercambiaFilas( ),
tiene como tarea
intercambiar la fila i, con
la fila pivote, pero como
los i primeros elementos
son cero,
necesario su
es por
no ser
intercambio,
ello que
el empezamos
intercambio desde
for(j=i; j<n; j++) ).
(
(El algoritmo de
intercambio, fue explicado
en el problema 1.1 de mi
libro Algoritmos y su
Codificacin en C++
Volumen 1).
Arrexi(IS Bidimensionales 69
U\[ J[COL],nt f, intc)
Csar Liza Avila. Mis lihro.1 son econmicos, 110 hay m,:n para copiarlos.
70 Algoritmos y su Codificacin en ('+ +. Vofwnen 2. Csar Liza A vila
La funcin central del nuestro problema es eliminaAdelanle(), la
cual reCOITC cada C01UlllJll buscando la fila pivote, esto es la fila con el
elemento de mximo valor absoluto para la columna deseada. Si esta fila es
diferente que estamos procesando (piv!:::i) entonces realizamos el
intercambio de la fila i con la fila piv aumentando la cuenta
. (nrolnlercamb++). Los bucles para j y k, permiten realizar la resta entre
dos filas, y como empezamos a partir de i+ 1, el elemento m[j][i] lo
hacemos cero, ya que es el elemento que deseamos eliminar.
([) Csar Liza Avila. No mates fa producci i/efectual, no copies ste libro.
Arreglos Bidimen\lflfLulcs 71
Solucin:
Un sistema de ecuaciones de n incgnitas tiene la forma:
flo.axa + aa,lxl + flo,2Xz +
al.OXO + al,lxl + aUx} +
donde a.j' son los coeficientes, Xi las incgnitas, y y son los trminos
independientes. Debe cumplirse que el nmero de incgnitas es igual al
nmero de ecuaciones y que al menos uno de los trminos independientes
sea distinto de cero, para que sea considerada un sistema no homogneo,
pues es el nico tipo de ecuaciones en donde se puede aplicar la
eliminacin de Gauss para resolver el sistema. Este mtodo consiste en 2
etapas: la eliminacin hacia adelante y la eliminacin hacia atrs,
Primero, tomamos los coeficientes del sistema de n ecuaciones simultneas,
y le aumentamos el vector columna formado por los trminos
independientes, formando una matriz de orden n x (n+ 1),
a 0.0 aO.1 a 0.2 a 0.11-1 Yo
a 1.0 a 1.1 al "2 a 1.11-1 YI
a 2.0 a 2.1 a 2.2 a 2.11-1 Y2
a,,_1.0 an_!.1 an- I .1 . , , a,,l.n_1 Y,;-I
nx{n+ 1)
Mediante el proceso de eliminacin hacia adelante, explicado en el
problema anterior, convertimos esa matriz a una matriz triangular superior.
a 0.0 a 0.1 a o. 2 .. a o, n.2 a O,n-I Yo
O a 1.1 al. 2 .. a 1,11-1 a I.n-I YI
O O a 2."2 a 2. n-2 a 2,11-1 Y2
O O O an_ 2.11-2 an_2,,,.1 Yn2
O O O O anl.n_1 Yn 1
-
Tlx(fH 1)
Csar Uza A vi/o. Mis libros son ecollmico,\', no Iza)' razn fHl/"II ("o/liarlos.
72 Algoritmos)' su Cod!tiraCn en C+ t. Volumen 2.
Csar Lizo A vila
En esta ltima matriz, aplicamos el procedimiento de eliminacin hada
atrs, que consiste en robteniendo las races desde la ltima fila hacia la
primera.
De la ltima fila obtenemos la incgnita Xo-I. pues:
a
o
.l,o.] ,Xo-I = Yo-]; de donde Xo-l = Yn-JI an-l,n-l
La penltima fila obtenemos la incgnita Xn-2 haciendo:
a
o
-2.0-2 ,X
o
-2 + a,,-2.0 .. 1 .Xo.J =: Yo-2; de donde Xo-2=( Yn-2 - a o-2,0-1 .Xo-I )Yn-l
l
a
o
-.2,0-2
y as para el resto de incgnitas.
..

,. . . . ",31' -'\ .. ,,'::"0'; ... ....
,leerM;ittti?i( [][eOb];int, lnt);', :.;: ... 'y).
, .v6id ( m::oL), jnt, inl}i' ..,.- ,:.f,,{.; oc;;
': ]Jf(}lJ12.;; ....i.r:
I
'::";\" ,)
il.lt,int; ..
. [][CCJ'r:;l, tnt);' . ". .
;voidelimlnaAtrs(dOuble. [ ][COL1: ni);' .
-> ,-J; "'.' i:.' . ',v.ce .,' '.':" '" ....... ",
'.'
C vol main(void}' ." .....
.'
,'in.t n; . . ." ..... ..
. ... Lcut"N
. . ..
.........
".e;: cout'::<et1l"Mattiz;!iia
a
ulat: .......<"'M'i.1I"
/:\ ;;,;;S.. .
;; >minaArras(Irt n)'" . ';'
\: ; .. :''',' o.. ':' '" : ," : ..\
'1'.: >:,j;
Ce:) Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales B
La funciones leerMatriz( ) e impMatriz( ) ya las hemos usado en varios
programas anteriores, mientras que pivote( ) e intercambialmas( ), son las
mismas que el problema anterior.
Csar Liz,o A vila. Mis libros son econmicos, no hav Tacn para copiarlos.
\
74 Algoritmos y su Codificacin en C+ + Volumen 2.
Bsicamente la funcin
eliminaAdelante( ), es
la misma que la usada
al calcular la
determinante
(problema 2.11), solo
que el intercambio ya
no se hace solo de la
matriz cuadrada de
coeficientes sino que
incluye la columna de
los trminos
independientes (
intercambiaFilas(i, piv, n+ 1 ,m)
) y las operaciones de
reduccin o eliminacin
tambin afectan a esta
columna ( for(k=i+l;
k<n+l; k++) ).
A diferencia del
problema anterior
(clculo de la determinante),
ahora no nos interesa el
nmero de
intercambios, por lo que
la funcin ser tipo
void.
Csar Liza Avila
En eliminaAtras( ), calculamos el valor de cada incgnita, tomando cada
fila a partir de la ltima ( for (i=n-l; i>=O; i--) ) y obtenemos el valor del
trmino independiente ( t = m[i][n] ), al cual debemos restar la sumatoria de
todas las otras incgnitas multiplicadas por sus coeficientes ( for(j=i+l; j<n;
j++) t = t- m[i][j]*x[j]; ).
El ltimo bucle imprime cada incgnita.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 75
Solucin:
Sean A y B dos matrices cuadradas de orden n, tales que AB = BA = 1,
donde 1 es la matriz identidad. Se dice que B es la matriz inversa de A y se
denota como B = A't, o lo que es lo mismo A es la inversa de B esto es A =
B-
I
.
Una matriz posee inversa cuando es cuadrada (filas = columnas) y la
determinante de la matriz es diferente de cero ( IAI ::f:. O )
Para obtener la matriz inversa, tomamos la matriz original, una
matriz identidad del mismo orden, y con ellas formamos la matriz
aumentada. Luego procedemos a realizar eliminaciones hasta conseguir que
la zona ocupada por la matriz original se convierta en una matriz identidad.
La matriz inversa estar dada por la zona donde se ubicaba en un
la matriz identidad.
Por ejemplo, sean las matrices A y su matriz identidad correspondiente 1:

Para la primera columna:
a) Busco el mayor elemento, en valor
absoluto, resulta ser el3
b) Intercambio las filas
3 4 O 1
1 2 1 O
c) Divido la primera fila entre 3
1 4/3 O 1/3
1 2 1 O
d) Multiplico la segunda fila por 1 y resto
segunda fila menos la primera, y coloco el
resultado en la segunda fila
1 4/3 O 1/3
O 2/3 1 -1/3
i 1 O]
: O 1
I
Para la segunda columna:
a) Busco el mayor elemento, en valor
absoluto a partir de la fila siguiente i+ 1,
res.ulta ser 2/3
b) Inte.rcambio las filas. Como solo tengo una
se realiza el intercambio consigo mismo
1 4/3 O 1/3
O 2/3 1 -1/3
c) Divido la segunda fila entre 2/3
1 413 O 1/3
O 1 312 -1/2
d) Multiplico la segunda fila por -4/3, sumo
. ambas filas y coloco el resultado en la
primera fila
1 O -2 1
O 1 3/2 -112
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
1,
\
I
76 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Liza Avila
Como era una matriz
de 2x2 solo
necesitbamos
.procesar 2 columnas,
obteniendo la matriz
identidad en la mitad
izquierda, y la matriz
inversa en la mitad
derecha, la cual ser:
[
-2 1 ]
3/2 -112
Observe que los
arreglos son de tipo
double puesto que
realizamos varias
multiplicaciones y
divisiones.
Ya en nuestro
.jJrograma, leemos la
matriz, e invocamos a
la funcin illversa( ).
, ~ ~ " : " ' - : - " , . . . . . . . . . . , . ' : " ~ - ' : ' - - - : ~ ~ . . . , . . . ~ - ' - ~ - ~ ~
'<CODIFlIGACtONENCH
Csar Liza Avila. No mates la produccin intele<"fual, no copies ste libro.
,.
Arreglos Bidimensionales 77
La funcin pivote( ), es invocada por inversa( ) acepta como primer
argumento la fila (y columna) que queremos eliminar.
La primer bucle, obtiene el elemento con mayor valor absoluto (un
conocido algoritmo nuestro de bsqueda del mayor). Si el elemento mayor
resulta ser cero significa que un elemento de la diagonal principal ser cero
y como se tratar de una matriz triangular superior entonces su
determinante dada por el producto de los elementos de la diagonal principal
es cero, por lo que no existir la inversa.
El siguiente bucle hace el intercambio de la fila que contiene el mayor valor
absoluto y a la vez divide cada elemento entre el pivote con el objeto de
hacer 1 el elemento.
, I
Csar Liza Avila. Mis libros son econmicos, no hay razn pum copiarlos.
78 Algoritmos y su Codificacin en C+ +. Volumen 2.
Esta funcin, es
invocada desde
main( ), la
variable i es la
fila donde
queremos
obtener el 1, j
es la columna
cuyos
elementos
queremos
hacerlos ceros,
y k es cada una
de las columnas
de la fila que
queremos
restar.
Csar Liza A vila
Finalmente, la funcin llena la matriz inv[][] , con los elementos
correspondientes a la inversa.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
.]-
I
Solucin:
El popular "tres en raya", "triqui" O
"michi", se juega con dos
jugadores, cada uno de los cuales
a su turno marca una casilla
originalmente vaca, con un X o
un O. El primer jugador que logre
colocar su smbolo *
'11 X X
en tres caSI as ya
sea horizontal, O
vertical o diagonal, X
gana.
Este juego se puede almacenar en
una matriz de 3x3 (# define TAM 3).
Los casilleros libres se marca
como O (# define NADIE O). Las
casillas elegidas por el humano se
marcan como 1, (# define JUGADOR
1), mientras que las tomadas por el
computador se marcan con 2 (#
define COMPUTADOR 2).
En main( ), invocamos a
inicMatriz( ), la cual toma cada
casilla y la marca como no
utilizada (m[ilU1 = NADIE). Esto es
necesario puesto que cuando
declaramos un arreglo cada
elemento contiene el valor que en
ese momento se encuentre en
memoria. Luego entramos a un
bucle infinito (do{ } while(l) ) el
que terminar cuando haya un
ganador ( if ( hayGanador (a) ) break; );
A rreglos Bidimensionales 79
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
------_._-----------_ ....... _ - - - - - - - - - - - - - - ~ - - - - - - - -
..
80 Algoritmos y su Codificacin en C++. Volumen 2.
La funcn jugador( ),
permite ingresar la jugada del
humano. Debe indicar una fila
y una columna vlidas, de no
ser as repetir el bucle desde
el inicio (continue); adems,
. verifica si la casilla est
desocupada, en cuyo caso se
marcar como utilizada (
m[f][c]= JUGADOR ). Si ha
logrado marcar la casilla
deseada entonces saldr del
bucle (break).
El movimiento de la
computadora es bastante
simple slo escoge la primera
casilla libre y. la marca.
Existen diversos mtodos para
que la computadora elija la
mejor jugada posible; por
ejemplo examinando todas las
posibilidades aplicando
bsqueda exhaustiva,
recursin, backtracking,
programacIOn dinmica,
estrategia minimax, poda alfa-
beta y rboles o usando
alguna heurstica. Dichos
rtodos y tcnicas estn
fuera del alcance de este libro
y algunos de ellos se ven en
mi libro Estructuras de
Datos con C++.
La funcin hayLibres( ),
Csar Liza A vila
busca si existe algn casillero no ocupado, retomado 1 (verdadero) si existe y
O (falso) en caso de que todos estn ocupados. Esta funcin es utilizada por
hayGanado:r(), para determinar si hay empate.
Csar Liza Avila. No mares la produccin intelectual, no copies ste 'libro.
'.
Arreglos Bidimensionales ln
La funcin hayGanador( ), recorre todas las
filas verificando que sean iguales pero diferentes
de NADIE. De igual manera recorre todas las
columnas, la diagonal principal y la secundaria.
Esta funcin imprime el ganador o si hubo
empate y retoma un valor (O 1) para que el
bucle dentro de maine ) contine o finalice.
Csar Liza Avla. Mis libros son econmicos, no hay razn para copiarlos .
82 Algoritmos y su Codificacin en e + +. Volumen 2.
Csar Liza A vila
Solucin:
En este programa utilizamos una matriz de caracteres, debemos resaltar el
hecho que cada palabra se almacena en una fila de la matriz, y que solo es
necesario utilizar un nico subndice p[i].
(i:) Csar Liza Avi/a. No mates la produccin intelectual, /lO copies ste libro.
Arreglos Bidimensionales 83

n,; p[ ltceL))
{,&,.:' ,.,''';,i,;L;i:;J\:
Por ejemplo, si ingresamos las palabras "uno, "dos", "tres" y "cuatro", la
matriz quedar como:
(
COL
)
'u' 'n' 'o' '\0'
'd' 'o' 's' '\0'
FIL 't' 'r' 'e' 's' '\0'
'e' 'u' 'a' 't' 'r' 'o' '\0' ...
oo. 00' oo' oo. oo. oo' o
Cada palabra es referenciada por un nico subndice, mientras que cada
carcter con dos subndices. En realidad la representacin anterior es una
representacin lgica, puesto que en computadoras la memoria es ms bien
lineal, tal como se muestra a continuacin:
COL *ziseof(char) COL *ziseof(char) COL *ziseof(char) COL *ziseof(char)
'A. ,r -A.. '\
Es por ello la necesidad de pasarle el valor de COL, en la invocacin de
funciones que usen matrices.
Csar Liza A vila. Mis libros son econmicos, 110 hay razn para (olarios.
84 Algoritmos y su Codificacin en e + +. Volumen 2. Csar Liza Avila
l. Dado una matriz, obtenga el mayor elemento de cada fila.
2. Muestre aquellos elementos que no pertenecen a la diagonal principal.
3. Una matriz ir;mgular inferior es una matriz cuadrada cuyos elementos
encima de la diagonal principal son todos ceros. Escriba una funcin
que diga si una matriz es triangular inferior.
4. Se tiene una matriz con el total de emergencias en un hospital por cada
hora y por cada da de la semana. a qu hora ocurre la mayor
cantidad de emergencias? qu da hay ms emergencias?
5. Una matriz diagonal es una matriz cuadrada que son ceros todos sus
elementos que no pertenecen a la diagonal principal. Escriba una
funcin que diga si una matriz es diagonal.
6. Obtenga el promedio de cada columna en una matriz.
7. Se almacena la historia de los recorridos de n automviles durante una
semana. Aquellos que ha recorrido ms de k kilmetros necesitarn un
mantenimiento, qu automviles necesitarn mantenimiento al final
de la primera semana? '
8. Se tiene una matriz en la cual las filas indican los articulos, mientras
que las columnas son el nivel de ventas por cada da de la semana.
Qu artculo tiene el mejor promedio de ventas?
9. Lea dos matrices y diga si son iguales.
10. Una matri?- cuadrada A se dice que es simetrica si A(i,j)= A(j,i) pra
i,. j dentro de tos limites de la' matriz. Escriba un programa que
dIga SI una matriz es simtrica.
11. Dada una matriz, escriba una funcin que permita eliminar unafila.
12. tiene una matriz de ordenfxc y un vector columna (de ordenfxI). Se
pIde, remplazar una columna determinada de la matriz por el vector
columna.
13. Ordene ascendentemente los elementos de cad,a columna de una
matriz. .
14. Muestre todos los elementos que estn debajo de la diagonal.
15. Dada una matriz aumntele una fila cuyos elementos contenga la suma
de todos los elementos de la cada columna, y aumntele una columna
que contenga la suma de todos los elementos de cada fila. Finalmente,
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Arreglos Bidimensionales 85
complete la matriz llenando la esquina inferior derecha con la suma de
todos los elementos de la matriz original.
16. Se tiene. una matriz que contiene todos los elementos iguales excepto
que tiene algunas bombas, y un premio mayor. Tiene que descubrir
elida casillero, hasta obtener el premio mayor o tocar una bomba.
17. Se tiene un arreglo bidimensional de caracteres, dada una letra
muestre las letras que lo rodean.
18. Encripte un mensaje por transposicin. Este mtodo consiste en
intercambiar las letras de un mensaje segn algn patrn. Por
ejemplo, podemos usar una matriz para transponer los caracteres del
mensaje, as: si la frase es "hola mundo cruel" y utilizamos una
matriz de 3 columnas, tendremos:
ha 1
a m
und
ocr
u e 1
y el mensaje encriptado por transposicin ser hauouo ncelmdrL
Sugerencia: Si fuera necesario llene los espacios no ocupados de la
ltima fila con NULL.
19. Lea un conjunto de palabras, almacene cada en una fila de
una matriz de caracteres, luego invierta cada una de ellas de tal
manera que cada fila contenga la palabra original pero con sus
caracteres al revs.
20. Defina una matriz cuadrada donde tenga n pares de elementos iguales.
Luego juegue a "memoria ", deber descubrir 2 elementos y si son
iguales dejarlos descubiertos, en caso contrario volverlos a cubrir. Al
final 4eber indicar el nmero de jugadas y cuntos a'ciertos tuvo.
Sugerencia: Utilice una matriz auxiliar que contenga 1 si el element,o
ha sido descuHierto y O si aun no lo est.
Csar Liza A vila. Mis libros son econmicos, no hav razn para copiarlos.
_._-"---
Estructuras,
Uniones y
Enumeraciones
, ,
Estructuras, Uniones y Enumeraciones 89
Solucin:
Dentro del campo de los nmeros reales no es posible obtener la raz
cuadrada de un nmero negativo. Por ejemplo, si deseamos obtener la raz
cuadrada de -9, sta no existe en IR. As, se hizo necesario idear una raz
imaginaria tal que elevada al cuadrado resulte -1. Dicha raz se representa
como i y equivale a -Vol, de tal manera que Z = -1. As -v-9 es igual a 3i.
Pero los nmeros imaginarios acostumbran a venir en pareja con un nmero
real, razn por la cual se les conoce como Conjunto de Nmeros
Complejos. Un nmero complejo, es pues un nmero que tiene una parte
real y una parte imaginaria, por ejemplo 3 + 2i es un nmero complejo.
Estos nmeros aparecen con frecuencia cuando deseamos resolver una
ecuacin de segundo grado: ax
2
+ bx + e = O, cuya raz es:
- b --J b
2
- 4ac
x = --------------------
2a
En donde, si la discriminante D = b
2
- 4ae, es
negativa, entonces las races de la ecuacin sern
complejas.
Sean los complejos el = a + bi Y e2 = e + di
Suma = el+ e2 = (a + e) + (b+d)i
La suma de dos complejos se obtiene sumando la parte real del primero con
la parte real del y la parte imaginaria del primero con la parte
imaginaria del segundo.
Diferencia = el - e2 = (a - e) + (b-d)i
Es una suma donde solo cambiamos el signo + por el -. \
Producto = e1.e2 = (ae - bd) + (ad + be)i
La multiplicacin resulta un poco ms complicada,
(a+bi)(c+di) = ac+adi + bci+bdi
2
= (ac-bd) + (ad+bc)i
Cociente = (ac+bd)/(c
2
+ d
2
) + (bc-ad)i/(c
2
+ d
2
)
La divisin de complejos es aun ms complicada, pues hay que multiplicar
el numerador y el denominador por su conjungada
a+bi (a+bi) (e-di) (ac+bd) +(bc-ad)i (ac+bd) (bc-ad)i
-------- = ----------------- = ----------------------- = ---------- + .-----.---
c+di (c+di) (e-di) c
2
+ d
2
c
2
+ d
2
e
2
+ d
2
Ce) Csar Liza Avila. Mis libros SO/1 econmicos, /lO hay razn para copiarlos.
1
\
90 Algoritmos V su Codificacin en C++. Volumen 2. Csar Liza Avila
En nuestro programa definimos una estructura (strud cClmplie.lo) ya que
todo nmero complejo es una nica entidad que consta de dos partes. Debe
tratar a struct complejo como un nuevo tipo de dato; as, puede declarar
variables de ese tipo, pasar variables de ese tipo a funciones, retomar el tipo
struct complejo e igualar variables de ese tipo. Puede escribir simplemente
complejo en vez de struct complejo; sin embargo, preferimos ste ltimo
para recordamos que se trata de un struct.
En main( ), usamos la funcin leeComplejo( ) para leer un nmero
complejo, y sumaComplejo( ) para la suma. Ambas funciones, devuelven
un valor del nuevo tipo de dato. Finalmente, invocamos a impComplejo( ),
para que se muestre el resultado por pantalla.
Csar Liz.a Avila. No mates la produccin intelectual, no copies ste libro.
Estructuras, Uniones y Enumeraciones 91
12n leeComplejo( y, observe como usarnos el opendor . para acceder a cada
parte de la estructura, y como retomamos los valores ledos como una
entidad del tipo struct complejo, mientras que en sumaComplejos( ),
pasamos como argumentos dos variables del tipo struct complejo y
retomamos una entidad del mismo tipo.

r;: >:y .... .... .;l:\bi:;".':;:".,.\.,
stru<;:tcom:li
c6t<i:"Wgt

,
.. ' ".' /":: .:/""


sttct co
('
Finalmente, en impComplejo( ), para
determinar el signo hacemos uso del operador
ternario ? Este operador determina si la
condicin c.imaginaria>O es cierta, en cuyo
caso el signo ser '+', Y en caso contrario ser
espacio en blanco" (ASCII 32) puesto que el
signo negativo sera parte de c.imagil1aria.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos,
92 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza Avila
Solucin:
Sea Pi el precio unitario de compra y c la cantidad de kilos comprados,
entonces en cada compra el gasto ser PiCj.
En n compras tendremos:
monto gastado:: poco + PCl + P2C2 + .,. + P .. -ICn-l
Por otro lado, el total de maz adquirido es
Co + Cl + C2 + .. , + Cn-l
si cada kilo lo vendemos a X soles entonces:
monto de venta = X (eo + Cl + C2 + ... + Cn-l)
Para no ganar ni perder debe cumplirse:
monto de venta == monto gastado
X(co + Cl + C2 + .,. + Cn-l) = Poco + PICl + P2
C
2 + ... + pn-1Cn-l
esto es:
i
poco + p]C] + P2C2 + '" + pn-]Cn-I
X = -----------------------------------------
Ipc
X ""' --------------
Co + C] + C2 + .. , + Cn 1
LC;
Es decir que para no ganar ni perder en la venta del maz, debemos
venderla al precio promedio ponderado.
Csar' Liza A vila. No mates la produccin intelectual, no copies ste libro.
?or cada compra tenemos:
el precio unitario y la
cantidad comprada; los
que unimos en la
estructura compra. Como
tenemos varias compras,
usamos un arreglo (maiz)
donde cada elemento
almacena una compra.
Luego de leer el nmero
Estructuras, Uniones V Enumeraciones 93
de compras, invocamos a
leeCompras( ), para
ingresar cada uno de los
elementos del arreglo.
Preste especial atencin a i
como indicamos el
elemento i y cada una de
sus partes (c[il.precio y
c[i].cantidad).
.} ., :'1".< ." .... " .' .'\ >",/'
void I:eCotTIpias{iut Ui struet compra 9[ n ,',
En caJculaPonderado( ),
obtenemos cada sumatoria
y retornamos su cociente
de acuerdo con la frmula
del promedio ponderado.
Note la inicializacin a
cero de spc y sc en una
sola lnea y el uso del
operador += , para . los
acumuladores spc y sc.
Escribir, por ejemplo:
sc+=c[i].cantidad;
equivale a:
sc=sc+c[i].cantidad;
pero se prefiere usar la
primera forma, pues da un
toque ms profesional.
{ . , '
if+)" ," . ';':';;><'
. ',... ,. {
..' .... " .'.
Gin;:':>;;[i].cantidad;
} .; .'.
} .:":',..".".... >, .
fIoat ti, itruet cqp.pra e( D
{ .' ...... ,: "'? " .; ..,. ,'., . '.' ...

{
'."'.-" , j \
Csar Liza A vila. litis libros son econmicos, no hay raz. para copiarl,os.
<.
\
94 Algoritmos y su Codificacin en C++. Valumen 2.
Csar Liza A vilo
Solucin: . .
S I l
. f( ) o I Z ,,-1
ea e po morrno y= x = aox + alx -+- 3zX -+- -1- a,,_I X
cada uno de sus elementos resulta ser un monomio, los cuales tienen 2
partes: el coeficiente y el exponente; por lo que nuestra estructura ser:
struct monomio
{
};
float coeficiente;
int exponente;
como son varios trminos debemos almacenarlos en un arreglo; stlruct
monomio polinomio[MAX].
Para calcular el valor numrico de un polinomio f(x) , necesitamos el valor
que toma la variable x (cinx) y luego calculamos el valor de cada
trmino acumulndolos; s = s + 3X
i
, por lo dems el programa es
autoexplicativo.

: /.: ' ..
o
':;{,
. "{o:,"
. o, .. [J,;.flq(l.tJ;.;
,_.::...._ ..;;.. .';. .' '::'Iv.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
I
Estructuras, Uniones y Enumeraciones 95
Csar Liza AvUa. Mis libros son econmicos, no hay razn para copiarlos.
96 Algoritmos y su Codificaci6n en C++. Volumen 2.
Solucin:
. Primero, definimos la
estructura fecha, la
que es anidada dentro
de struct medicion.
Como tomamos la
temperatura de varios
das necesitamos un
arreglo capaz de
almacenar la fecha y
la temperatura de esa
fecha (struct
medicion x[MAX]).
En main( ), una vez
ingresadas las fechas
y sus temperaturas,
leemos la fecha (f)
cuya temperatura nos
interesa.
El nmero de das
(n), la fecha (f) cuya
temperatura deseamos
y los datos de las
fechas y temperatura
(x) son pasadas como
parmetros a
buscarFecha( ), la
cual devuelve la
temperatura del da
pedido en caso de
encontrar la fecha,
-1 en caso de no
encontrarla.
Csar Liza Avila
CsarLiza A vila. No mates la produccin intelectual, no copies ste libro.
Estructuras, Uniones y Enumeraciones 97
En leeDias( ), observe como se referencia a carla parte de las estructura
anidada. Por ejemplo en x[i].f.dia, representa el miembro da de la fecha (f)
de la medicin xci]. El doble. lo usamos porque f es una estructura anidada
dentro de otra.
En buscarFecha( ), no es posible comparar toda la estructura con una sola
"
instruccin, por ejemplo no podemos hacer if(x[i] ""= f), (aunque esto lo
podramos hacer en C++/C#, sobrecargando el operador =::::); es por ello
que comparamos cada una de sus partes ii' (x[i].f.d.ia == f.dia &&
x[i].f.mes == f.mes && x[i].f.allnio == f.mmio ).
En caso de encontrar la fecha pedida, retornar su temperatura. Si termina
de recorrer todos los elementos sin encontrar la fecha retornamos -1.
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
98 Algoritmos v su Codificacin en C++. Volumen 2. Csar Liz.a Avila
Estructuras, Uniones y Enumeraciones 99
Solucin:
Este conjunto de
operaciones
histricamente se les
conoce
mantenimiento
como
d.e
registros y en la
actualidad se le conoce
como CRUD (create,
read, update, delete).
El programa usa un
struct fecha, para
almacenar fechas y un
struct alumno para los
datos del alumno. Note
como esta ltima
estructura es capaz de
almacenar notas de
varios trabajos para un
mismo alumno, para
esto usa el arreglo
trabajo[ ].
El bucle infinito
(while(l){ n, permite
que siempre regresemos
al men a menos que la
elijamos opcin 6.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
En caso de seleccionar ingreso (case 1) comprobamos que no rebasemos la
cantidad mxima de elementos en el arreglo (n<MAXALUM), invocamos
a ingresa( ) para leer los datos de un alumno y aumentamos la cantidad de
alumnos ingresados (n++).
Si deseamos consultar (case 2), validamos que el nmero de registro
deseado este dentro del intervalo vlido (nreg>O 11 nreg>n) antes de
invocar a consulta( ).
De igual manera para modifica( ) y elimina( ), aunque esta ltima funcin
puede cambiar el nmero de alumnos y por ello retoma un nuevo valor para
ll.
Las funciones ingreso( ), y consulta( ), se explican por si solas.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
- - - - - - - - - - - - - - - - - - - - - - - - - - ~ - - - - - - - - - - - - - - - -
100 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza Avila
En modifica( ) es recomendable mostrar los datos actuales, por ello
invocamos a consulta( ); y luego, sobrescribimos el nmero de registro
deseado mediante la funcin ingresa( ).
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
------------_ .._ ~ - - - - - - - - -
Estructuras, Uniones y Enumeraciones 101
De manera similar en elimina( ), debemos mostrar el registro que deseamos "
eliminar para que el usuario tenga la ltima oportunidad de arrepentirse, en
caso de confirmar la eliminacin, debemos desplazar cada elemento del
arreglo una posicin hacia atrs, sobrescribiendo el elemento a eliminar.
Evidentemente, tendremos un elemento menos (n--) debiendo comunicar a
maine ) el cambio mediante return n.
La funcin listado(), no necesita mayor explicacin.
Csar Liz.a Avila. Mis libros son econmicos, no hay razn para copiarlos.
102 Algoritmos y su Codificacin en C++. Volumen 2.
Solucin:
Cada elemento
crucigrama es
palabra que se
despliega a partir de
una posicin (fil, col)
y hacia una direccin
(vertical, horizontal).
Asimismo, tendr una
descripcin que ser
usada como pista para
determinar la palabra,
y por ltimo el estado
que indica si la
palabra ha sido
descubierta o no. Para
englobar todos estos
atributos definimos el
struct palabra.
Las palabras
por adivinar las
colocarnos en el
arreglo leyenda.
Observe el clculo de
nroPreg, en base al
operador sizeof( ),
dividiendo la cantidad
de bytes . de todo el
arreglo entre la
cantidad de bytes de
cada elemento. Esto
es recomendable
Csar Liza A vi/a
puesto que podernos reducir o aumentar el nmero de palabras y el
programa automticamente calcular cuntas filas tendr el arreglo.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
l")or otro lado, es necesario
el patrn del crucigrama;
es decir, qu casillas
podrn contener letras y
que casillas no. Esto lo
indicamos en cruci[ ][ ]
usando y el
respectivamente. Luego,
calculamos el nmero de
filas n = sizeof( cruci)/
COL. Usamos el
operador sizeof( ), para
poder alterar la
inicializacin de cruci[ ][
], sin preocupamos de
cambiar el nmero de
filas.
El programa entra en un
bucle que termina cuando
todas las palabras han
sido descubiertas while(
verEstado(nroPreg,leyenda) ).
Ya dentro del bucle
mostramos el crucigrama,
imprimimos la leyenda y
permitimos al usuario
elegir la pregunta.
La funcin verEstado( ),
recorre cada fila de
leyenda preguntando si
hay alguna palabra sin
descubrir. Observe el uso
del tipo bool no existente
en e, pero si en C++/C#
(recuerde que en e, o
significa falso, mientras
que diferente de cero
significar verdadero).
Estructuras, Uniones y Enumeraciones 103
Csar Liza Avila. Mis libros son econmicos, /la hay razn paro copiarlos.
..
104 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila
Las funciones impCruci( ) e impLeyenda( ), no necesitan mayor
explicacin.
Al elegir la opcin
debemos mostrar si
es vertical u
. horizontal, y la
descripcin para
que el usuario nos
de su respuesta. Si
sta es correcta
entonces
cambiamos el
estado, y llenamos
el crucigrama con la
palabra. Si la
direccin es
horizontal
avanzamos las
columnas llenando
letra por letra la
palabra. En caso
contrario, ser
vertical y debiendo
avanzar por filas.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Estructuras, Uniones y Enumeraciones 105
Solucin:
Una union, es una forma de organizar nuestros datos, similar a una
estructura, pero a diferencia de stas, los miembros de la union comparten
la misma zona de memoria.
Como sabe, los miembros de una estructura se almacenan uno detrs de
otro, en posiciones consecutivas de memoria, pero en una union, sus
miembros se almacenan empezando en la misma posicin de memoria, esto
es, se solapan en memoria. En otras palabras, en un determinado momento
solo puede existir uno de los miembros de la union, mientras que en una
estructura existirn todos sus miembros. Esto tiene la ventaja del ahorro de
memoria cuando las variables que definimos solo tomarn algn grupo de
atributos y otros no.
El tamao de memoria que ocupa una union, s ~ r el tamao de la variable
ms grande. Al igual que con los miembros de una estructura, para acceder
a los miembros de una union se usa el operador punto.
Por ejemplo, si modelamos el caso que algunos trabajadores ganan por hora
y otros ganan un sueldo fijo, tendremos:
Usando una estructura:
struct pago
{ fIoat pagoxhora;
double sueldo;
} ;
Usando una union:
union pago
{ fIoat pagoxhora;
double sueldo;
} ;
[1111 111111 ,
~
. pagoxhora sueldo
WIIIIII
"-v--'
pagoxhora
'---y---I
sueldo
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos .
106 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Liza Avila
El programa hace lo pedido. Definimos en una misma zona de
memoria un entero y un flotante; esto es, ambos ocupan 4 bytes (en
compiladores de 32 bits) y, en este caso, toda la unin ocupa 4 bytes.
Al leer un entero (cinx.entero) le indicamos a la computadora
que lo ingresado lo almacene en 4 bytes, usando el formato de entero.
Luego stos mismos 4 bytes los mostramos (coutx.flotante), pero
interpretndolos con formato de punto flotante de simple precisin (IEEE
754). Los mismos 4 bytes los interpretamos de dos formas diferentes!
En la segunda parte del programa hacemos lo mismo, leemos un
flotante, almacenndolo en 4 bytes, luego mostramos esos mismos bytes
como enteros.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Estructuras, Uniones y Enumeraciones 107
Sohlldn:
es un tipo de dato formado por un conjunto conocido de
constantes enteras a las cuales se le ha dado un nombre. Las enumeraciones
proporcionan claridad en el cdigo puesto que es mejor leer su descripcin
en lugar de un nmero.
Se definen de manera parecida a las estructuras pero en vez de struct
usamos la palabra enum.
Por defecto, el primer elemento de la enumeracin es 0, numerndose
consecutivamente, aunque se puede especificar el valor de cada uno de los
elementos de la enumeracin.
El programa muestra la definicin de una enumeracin que contiene el
nmero de das, as como la utilizacin de dicha enumeracin. As, dom=O,
lun=l, . '" sab=6. Podramos haber escrito los nmeros en vez de los
nombres, case 4, equivaldra a case jue, pero evidentemente resulta ms
claro el programa cuando colocamos nombres en lugar de nmeros.
Csar Liza Avila: Mis libros son econmicos, no hay razn para copiarlos.
------- --- -
108 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Solucin:
Las enumeraciones, pueden tambin tomar valores diferentes de nmeros
consecutivos, tal como observamos en este ejemplo:
Note que, a diferencia de las estructuras y uniones, los elementos de un tipo
enumerado se separan con comas.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Estructuras, Uniones y Enumeraciones JW9
1. Calcule la suma de dos fracciones. Simplifique lafraccin antes de dar
la respuesta. Use estructuras.
2. Se tiene una lista de personas con dni, nombres y apellidos. Muestre
aquellas personas que son homnimas. Homnimos son personas que
tienen los mismos nombres y apellidos.
3. Se tiene la siguiente estructura:
struct alumno { char nrocarnet[ 11 ],
char nombre[25],
float prom;
} ;
Escriba un programa que lea n alumnos. Luego diga cul es el
promedio general. Quin(es) tiene(n) el mejor promedio y quin(es) el
peor?
4. Se tiene un conjunto de datos, se desea obtener una tabla que muestre
cuntas veces se repite cada elemento. Use una estructura.
5. La moda de un conjunto de datos es el elemento que ms se repite.
Encuentre la moda y cuntas veces se repite. Considere el caso en que
existan varias modas. Sugerencia: use una estructura que contenga el
valor y el nmero de veces que el elemento se repite.
6. En un almacn, calcule el monto total de inversin y diga qu artculo
es el que tiene mayor inversin. Considere la estructura:
struct articulo { char descripcin[ 30};
float preciounitario;
int cantidad;
}; \
7. Se tiene un polinomio y=f(x) se pide obtener su integral y su derivada.
8. Calcule el valor numrico de un polinomio f(x, y). Sugerencia: use un
arreglo donde cada elemento es del tipo estructura con atributos: el
coeficiente del trmino, el grado de x, y el grado de y.
9. Se tiene un arreglo con los resultados de los encuentros de un
campeonato de ftbol (equipo local, equipo visitante, goles equipo
local, goles del equipo visitante). Dado un equipo diga cul es su
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ~ - . - - ~ -
no Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila
puntaje. El equipo ganador obtiene por partido ganado 3 puntos, si
hay empate cada equipo obtiene 1 punto.
JO. Se desea gestionar una lista de articulos considerando atributos como:
cdigo, descripcin, cantidad en stock y costo. Defina una lista
utilizando estructuras y arreglos donde cada elemento representa un
artculo y haga un men que invoque a las siguientes funciones: (a)
ingreso de artculo, (b) mostrar todos elementos de la lista, (e)
modificar los datos de un artculo, (d) eliminar, (e) bsqueda y (f)
salir. Use un tipo enumerado para cada opcin del men. Por ejemplo
case 1, sera case ingreso. .
11. Se tiene la siguiente estructura:
struct articulo { float precio Venta;
int cantidad Vendida;
};
que almacena datos de venta de un determinado producto. Escriba un
programa que ajuste los datos histricos de venta a la recta de
regresin y= ax + b; luego, estime la cantidad de artculos (y) para
precio dado (x). Sugerencia: use las frmulas de regresin lineal que
aparecen en el Captulo 7 de mi libro "Algoritmos y su Codificacin
en C++", Volumen 1.
12. Se tiene la siguiente estructura:
struct alumno { chal' nombre[40];
int promedio;
};
Escriba un men para (a) leer alumno, (b) ordenar los alumnos por
nombre; (c) ordenar los alumnos por promedio, y (d) listar los
alumnos. Use una enumeracin para cada opcin del men.
13. Cree una enumeracin con los estados del agua. Luego lea n
temperaturas del agua y determine el porcentaje en que el agua estuvo
en cada uno de sus estados.
14. Una fbrica produce pernos. Cada perno debe tener un dimetro d y
una longitud 1, pero se permite un error de 0.5 mm para el dimetro
y 1 mm para la longitud. Lea una serie de pernos y muestre aquellos
que son defectuosos. Se considera como defectuosos aquellos que no
cumplan alguna de stas condiciones. .
15. Lea un mes y un ao y determine cuntos das tiene ese mes, considere
los aos bisiestos. Use una enumeracin para los meses.
16. Cuntos das hay entre dos fechas? Use un struct y un enum.
Csar Liza AviLa. No mates la produccin intelectual, no copies ste libro.
17.
18.
Estructuras, Uniones y Enumeraciones] 11
Un punto se representa mediante por una abscisa (x) y una ordenada
(y). Lea 2 puntos y determine sus coordenadas polares, la distancia
entre ellos y, la ecuacin de la recta que pasa por esos dos puntos.
Un volumen de una biblioteca puede ser fihro o revista. Esrr.iba un
programa que permita ingresar un volumen y mostrar sus datos.
Cualquier volumen tiene cdigo, mio, fipo (libro O revista). Si es una
revista tendr adems un lSSN, nombre, y un mes de publicacin.
mientras que si es un libro tendr un !ISBN. autor y el nmero de
captulos. Sugerencia: use estructuras y uniones.
struct volumen
{ chal' codigo[JO};
int annio;
chal' tipo;
unon detalle v;
J;
struct revista
{ char ISSN[ll];
chal' nombre[30];
int mes;
};
unan detalle
{ struct revista;
struct libro;
J;
struct libro
{ charlSBN/ll];
chal' autor/30};
int nroCap;
};
19. Una variante de las uniones fue introducida en el C++ y es llamada
union annima. Una union annima, declara un conjunto de
miembros que se inician en la misma direccin de memoria, pero que
no se les da un nombre y se puede acceder directamente a sus
elementos. El siguiente enunciado sugiere el uso de una unin
annima:
En una empresa trabajan empleados y obreros. Los empleados tienen
un sueldo fUo, mientras que los obreros ganan por hora. Lea los datos
de n trabajadores y luego lstelos mostrando el mOlltopagado a cada
uno y el total pagado por la empresa. Sugerencia: use las estructuras
mostradas.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
r
112 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Al/ita
struct trabajador
{ char codigo[6];
int anniolngrpso;
char tipo;
};
unton { struct empleado;
struct obrero;
J;
struct empleado
{ char puesto[20};
float sueldo;
};
struct obrero
{ float valorHora;
int horasTrab;
};
20. Se tienen las siguientes figuras geomtricas: circunferencia (radio),
cuadrado (ladlJ) y rectngulo (2 lados). Escriba un men en el que el
usuario escoja unafigura geomtrica y calcule su rea. Use una union
y una enumeracin.
Csar Liza A vi/a. No mates la produccin intelectual, no copies ste libro.
Manipulacin de
Bits
\
Manipulacin de bits] 15
Solucin:
Antes de presentar el programa necesitamos comprender como se
almacenan los nmeros enteros.
Almacenamiento de nmeros enteros
El formato de almacenamiento de enteros reserva el ltimo bit (el bit ms
significativo, esto es el bit ms a la izquierda) para indicar que el nmero es
negativo. Si el ltimo bit es O, el nmero ser positivo, si es 1 ser
negativo.
A manera de ilustracin tomaremos el tipo short nt (16 bits).
Por ejemplo, si el nmero es a = 239, entonces se almacenar corno:
a = 0000 0000 1110 1111
Los nmeros negativos se almacenan, por cuestiones de eficiencia, como
complemento a dos. Para calcular el complemento a dos, tomamos el
positivo del nmero, invertimos sus bits y luego le sumamos 1.
Por ejemplo, si el nmero es -240, y tomamos su positivo, tendremos:
240 en binario es : 0000 0000 1111 0000
invirtiendo sus bits: 1111 1111 0000 1111 +
le sumamos 1 0000 0000 0000 0001
tendremos 1111 1111 0001 0000
es decir el short nt -240 se almacenar como 1111 1111 0001 0000. Note
como el bit ms significativo es 1, con lo cual el nmero se interpreta como
negativo, y por ende estar almacenado como complemento a dos.
Csar Liza Avila .. Mis libros son econmicos, no hay razn para copiarlos.
116 Algoritmos y su Codificacin en C++. Volumen 2, Csar Liza Avila
La razn para que las computadoras usen el complemento a dos es para
calcular fcilmente una diferencia, como si fuera una suma. Asf,
240+
~ 240
o
0000 0000 1111 0000 +
1111 1111 000 1 0000
7' I 0000 0000 0000 0000
el desbordamiento
se pierde
OPERADORES A NIVEL DE BITS
Los operadores a nivel de bits trabajan sobre cada uno de los bits de la
variable, y los operandos deben ser de algn tipo entero (char, short, int,
long y sus combinaciones con signed y unsigned).
Para entender como se obtiene cada resultado, necesitamos mostrarlos a
nivel de bits.
Tomemos por ejemplo, a= 239 y b=3, que en binario sern:
a = 0000 0000 1110 1111
b = 0000 0000 0000 0011
Veamos cada una de las operaciones sobre sus bits:
Csar Liza A vUa. No mates la produccin intelectual, no copies ste libro.
NEGACION-
Los bits O se pasan al, Y los bits 1 pasan a ser O.
Si
a= 000000001110 Illl
-a= 1111 1111 00010000
Manipulacin de bits H 7
como el negado de a, tiene el ultimo bit en 1, se interpreta como
complemento a dos, o sea:
si negamos
tendremos
le sumamos 1:
1111 1111 0001 0000
0000 0000 1110 1111
----------------------.".---
0000 0000 1111 0000
que en decimal ser: 2
7
+ 2
6
+ 2
5
+ 2
4
= 240, como tena el bit del signo en 1,
entonces ser -240.
CONJUNCION &:
Si los dos bits estn en 1, entonces la conjuncin
resultar 1, en los defils casos dar O. .. I
Si a= 239 y b=3, entonces su conjuncin a nivel de
bits ser:
a = 000000001110 1111 &
b = 0000 0000 0000 0011
a & b = 0000000000000011
que en decimal ser: 2
1
+ 2 ::: 3
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
\
H8 Algoritmos y su Codificacin en C++. Volumen 2.
DISYUNCIONI
Si los dos bits son 0, entonces la disyuncin
resultar 0, en los dems casos resultar 1.
Si a= 239 y b=3, entonces su disyuncin a nivel de
bits ser:
a = 0000 0000 1110 1111
b = 0000 0000 0000 0011
alb= 0000000011101111
EXCLUSION A
Si los dos bits son diferentes, entonces la
exclusin resultar 1, en los dems casos
resultar J.
Si a= 239 y b=3, entonces su exclusin a nivel de
bits ser:
a = 0000 0000 1110 1111 1\
b = 0000 0000 0000 0011
a 1\ b = 0000000011101100
que en decimal ser: 2
7
+ 2
6
+ i + 2
3
+2
2
= 236
Csar Liza A vila
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Manipulacin de bits 119
DESPLAZAMIENTO A IZQUIERDA
El operador desplaza los bits de un nmero, una cantidad de posiciones
a la izquierda, haciendo que los bits ms significativos (los ms a la
izquierda) desaparezcan y los bits menos significativo se rellenen con O.
Si a= 239 y b=3, entonces:
a = 000000001110 1111
a b = 00000111 0111 1000
que en decimal ser: 2
10
+ 2
9
+ 2
8
+ 2
6
+2
5
+2
4
+2
3
= 1912
Note que desplazar una posicin a la izquierda equivale a multiplicar el
nmero por 2 (en el ejemplo 239*2
3
= 1912).
DESPLAZAMIENTO A DERECHA
El operador desplaza los bits de un nmero, una cantidad de posiciones
a la derecha, haciendo que los bits menos significativos (los ms a la
derecha) desaparezcan y los bits ms significativo se rellenen con o.
Si a= 239 y b=3, entonces:
a = 0000 0000 1110 1111
a b = 0000 0000 0001 1101
Note que desplazar una posicin a la derecha equivale a dividir el nmero
entre 2 (en el ejemplo 239/2
3
= 29).
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
___ ---" ________________________ _
120Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza A vila
El programa muestra el resultado de aplicar cada uno de los
operadores a nivel de bits, comprelos con los resultados obtenidos en la
explicacin anterior.
Hemos utilizado el tipo snort ini: (16 bits) solo pues cuestiones didcticas,
bien podramos haber utilizado cualquier tipo entero. Debe recordar que los
operadores a nivel de bits solo pueden ser usados con tipos enteros.
No debe confundir los operadores y cuando se usan con con! o con
el ciD, para evitar confusiones en el programa anterior usamos los
parntesis.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Manipulacin d(' bits j 21
Solucin:
Antes de resolver el problema hablemos un poco sobre los nmeros
hexadecimales y su relacin con los nmeros binarios.
Nmeros Hexadecimales
En base 16, son vlidos los dgitos 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, R, e, D, E Y
F; donde A=lO, B=11, C=12, D=13, E=14 Y F=15.
En programacin de bajo nivel (cercana a la mquina) se acostumbra a
utilizar la base 16, en lugar de la base 2, ya que presenta un equivalente
directo con la base 2, pero al contrario de sta ltima, es mucho ms fcil
de manejar. En base hexadecimal cada 4 dgitos binarios equivalen a un
dgito hexadecimal.
Por ejemplo:
El nmero en base 2: 0001 1111 equivale a lF en hexadecimal.
El nmero en base 16: A2 equivale a 10100010 en binario.
En C/C++/C# los nmeros hexadecimales van precedidos de Ox, as lF se
escribir OxlF, mientras que A2 se escribir OxA2.
Note que:
Un byte usar 2 dgitos hexadecimales
Dos bytes usar 4 dgitos hexadecimales
Cuatro bytes usar 8 dgitos hexadecimales
As el entero 1 (de tipo int o sea 4 bytes) ser en hexadecimal OxOOOOOOOl
Un valor en base lOse puede imprimir en hexadecimal dentro de un
programa mediante hex, por ejemplo couhex28, imprimir le.
Las direcciones de memoria se acostumbran a mostrar en hexadecimal.
Csar Liza A vi/a. A1is libros son econmicos, /10 hay razn para cO/liar/os.
J 22 AI;oritmos v su Codificacin en C+ + Volumen 2,
Csar [,iza /lvi/a
Ya en nuestro programa leemos un entero (32 hits) e invocamos a la
funcin impBits( ) con el positivo y el negativo del valor ledo.
En impBits( ), se define una mscara en la cual solo 1 bit est encendido
1000 0000 0000 0000 0000 0000 0000 0000, sabiendo que 4 dgitos
'binarios equivalen a un dgito hexadecimal tendremos: 80000000, que en
C/C++/C# se representara como Ox80000000.
El impresin se basa en tomar la mscara y hacer un AND a nivel de bits
(&) con cada bit de 11, para ver cuales estn en 1. Es necesario que la
mscara sea del tipo unsigned puesto que si fuera int, el ltimo bit se
reservara para el signo y, por lo tanto, no podra almacenar un nmero tan
grande como Ox80000000 arrojando la inicializacin un error pues estara
fuera del rango vlido de enteros.
Luego de asignar 1 al bit ms
significativo ( mask =
Ox8000000 ), mediante un bucle
recorremos de izquierda a
derecha, cada uno de Jos 32 bits
de n, haciendo un AND con
cada uno de ellos. Slo en caso
que n tenga el bit
correspondiente en 1 se
imprimir 1, en caso contrario
se imprime 0, para luego
desplazar el bit encendido de la
mscara una posicin a la
derecha y evaluar el siguiente
bit de 11.
La comprobacn j %4==0 solo
sirve para colocar un espacio
cada 4 dgitos binarios.
conIlCACloN EN'C+.. ,
' oo. ..'
# includ.
.\lbig inlpBits(int);
, \:,oid
{ int ni ." ." ....
cout"ilgr,esenro: ";.' cinn.;
imPBits( n)) ..
cut<:<:-ni;= "; i!J'1pBitS{"I1); ..
} . ,.. .
void impBits(in.f ti),
{
ft ",,0;]<32;j++).' . . .... >,
{ i(d%4;:=0) Ollt"'''r "
if o & rnsk) > O) cOllt<:< 1;
else CQLit O;
rnask 1); , '.
cout<<:end!;
}
Csar Li'.a A vi/a. No mates /a produccin intelectual, no copies ste libro.
Manipulacin de hiTS 123
Por ejemplo, si ingresamos 79 en binario ser
79(10\ 0= 1001111(2)
Sin embargo, para obtener la representacin de -79 en 32 bits tendremos:
79 en binario es:
lo negamos
le sumamos 1 :
0000 0000 0000 0000 0000 0000 0100 '111 1
11111111111111111111111110110000
1
-79 se almacena como: 11111111111111111111111110110001
valores que son correspondientes con la salida del programa:
Csor Liza Avila, Mis libros son econmicos, 110 hay mz:n para copiarlos.
124 Algoritmos)' su Codifical'i6n en C+ +. Volurnen 2. Csar Liza A vila
. Solucin:
La exclusin a nivel de bits XOR tiene la propiedad que al ser aplicado dos
veces se obtiene el valor originaL Por ejemplo:
Bits originales 01010101 XOR
Clave 0000111l
Resultado 01011010
Aplicando nuevamente XOR
Resultado
Clave
01011010 XOR
00001111
Bits originales 01010101
En el programa ingresamos la
palabra y la clave. La funcin
encripta( ), toma cada uno de
los caracteres del mensaje y le
aplica un XOR con la clave
reemplazndolos. As, cada
caracter es cambiado y, al ser
un arreglo, main( ) reconoce
los cambios hechos sobre l.
Para desencriptarlo,
aprovechamos la propiedad
del XOR discutida lneas
arriba, volviendo a aplicar el
XOR con la misma clave,
obteniendo el mensaje
original.
r' ."" '

cina '0.
cncripta(il,t,.a);o
,cout"Enc,ripid;
o" .. .' .....
.
}
foJ' (fIlt i""O; l-f:n; 1++)
x[i],=:x[iJAclaye; ..
Csar Liza Avda. No mates la produccin intefectual, no copies ste libro.
MmufJulaci6n de bits !25
Es fcil modific:lr el programa para que imprima lo que ocurre cada Ve!
que aplicamos el XORy darnos cuenta de cmo va trabajando la
computadora. El lector deber intentar producir esta salida modificando
este programa y la funcin impBits( ) del Problema 402. Tenga en cuenta
que ahora los datos son tipo char, esto es 1 byte .
Csar Liza A vila. Mis libros son econmicos, no hay razrn para copiarlos.
i26 !\l;oritmos v su Cod(jil'acin en e + +, Volumen 2.
Chal U,;a Avila
Solucin:
Podemos utilizar una estructura para especificar la cantidad de bits que
ocupar cada miembro, llamndose a este tipo particular de estructura
campos de bits.
Sintaxis: struct nombreCampoBits
{ <tipo> nomb1: nroBitsl;
<tipo> nombN: nroBitsN;
};
El tipo solo puede ser integral (int, unsigned, short, char, o una
enumeracin) Los campos de bits permiten una mejor utilizacin de la
memoria al guardar directamente los datos en los bits que deseamos.
Ya pensando en nuestro programa, si deseamos almacenar los datos de
una carta, razonaremos as:
Cada carta tiene un palo, los posibles palos son 4: espadas, diamantes,
trboles, corazones, por lo que necesitarnos
log2 4 = 2 bits
Cada palo tiene 13 valores por lo que necesitaremos
log213 = 3.7 bits;::: 4 bits
Cada carta puede tener 2 posibles colores por lo que necesitamos
log22 = 1 bit
Entonces nuestro campo de bits ser:
struct carta
{ unsigned palo: 2;
unsigned valor: 4;
unsigned color: 1;
};
Observe como con solo 7 bits almacenamos las caractersticas de cada
carta, pudiendo usar el bit restante para indicar si la carta ya sali.
As, struct carta o simplemente carta es un nuevo tipo de dato,
por lo que podramos pasar como argumento de funciones o retornar un
valor del tipo carta, o manejar arreglos del tipo carta, e inclusive igualar
dos variables tipo carta.
Csar Liza Avda. No mates la produccin intelectual, no copies ste libro,
En m2!liJrn( J, definimos un
arreglo de 52 elementos,
generamos la baraja e
imprimimos las cartas.
En gene!l"a( ), tomamos cada
palo, y para cada uno de ellos
generamos valores del 1 al 13 y
su color.
La impresin no necesita mayor
explicacin.
Manipulaf'n de hits 127
CODIFICAcmN EN eH
#iBcJude <:iosiream.h> ..
# <iomanip.h>
strUCt carta
unsjgned palo :2; '.
. ,upsignep valor:4;'
.llflsignedcolbr:l;
1: ........ " ......... ' ...
s#ia(]}; ....
[J);
Yoid lJlaiil(vQid). -. .
' ... oaraJa[52J;
";;cgt!n,ra(ha.raja); ..........
I!npt:i 1l!ir(bataJa);,
lO! .' ... >",


JL.}'Zi ..,. .. .... , .....
mt.k.,.,Q,..., .......'
Jo;( iM pis\='=Q;PctLOs4;palo*+) .. ,
,. '. for( i valor=J ; vlokH.:
.. .,...... ,. ,
...
.h(k].c,019r ,fPa!()%2;
::,;;< r
k
++; ,.
...
cout"PCl1l .va19fSolot"<<;:endJ'
, . f91'( ". ":
-'cut setw(2lb[ij.plo
setw(6jh!i).vaor
< <;b,[iJ.colorendl;
Csar Li2.:a Avda. Mis libros son econmicos, no hay razn para copiarlos,
128 Algoritmos y su Corjficaci6n en C++. Volumen 2. Csar Liza A vila
Solucin:
Los archivos que tenemos en nuestros discos tienen como' uno de sus
atributos la hora de grabacin y; adems, en el caso del Windows, la hora
de la ltima modificacin. Para su almacenamiento .el DOS y el
WINDOWS, y muchos programas como el WinZip, que almacena las
horas de sus archivos comprimidos, utilizan un mismo formato para
almacenar la hora, el cual explicaremos a continuacin.
Cmo almacenan la hora los Sistemas Operativos
Es conocido que existen 24 horas al da, cada hora tiene 60 minutos, cada
minuto tiene 60 segundos. Entonces:
HH MM SS
00 00 00
23 59 59
24 x 60 x 60 = 86,400 combinaciones
Luego para almacenar las 86,400 combinaciones necesitamos IOg2 86400
=16.3987 bits, esto es ms de dos bytes.
Sin embargo, no es necesario almacenar la hora de grabacin de un
archivo con la precisin de 1 segundo, ya que nuestra reaccin a la accin
de grabar tardar al menos ese segundo, por lo que ser suficiente
almacenar la hora de grabacin del archivo con al menos 2 segundos de
diferencia, por lo tanto:
(1.) Cesar Liza A vi/a. No mates la produccin intelectllOl, no copies ste Ubro.
______________ =_ .. c . ~ . - .. ~ . ~ - . - ..
Manipulacin de bits .129
HH MM SS
00 00 00
23 59 29
24 x 60 x 30 = 43,200 combinaciones
por lo que necesitamos IOg2 43200 =15.3987 bits, esto es menos de dos
bytes, entonces para almacenar la hora con precisin de dos segundos
necesitaremos a lo ms 2 bytes.
Como en nuestra codificacin cada minuto tiene 30 seg, cada hora tendr
60x30 = 1800 segundos. Entonces:
Si cada segundo equivale a seg/2 tendramos:
La hora 00:00:00 equivaldra a O
La hora 00:00:01 equivaldra a O
La hora 00:00:02 equivaldra a 1
La hora 00:00:03 equivaldra a 1
La hora 00:0 1:01 equivaldra a 31
La hora 22:3 1 :08 equivaldra a 22(1800) + 31 x 30 + 8/2 = 40534
Es decir la hora 22:31:08 se almacenara en dos bytes como 40534, pero en
computadoras, es preferible hablar en potencias de 2, as en vez de utilizar
los factores 2, 30 y 1800; utilizamos los factores 2, 32 y 2048 con los
cuales obtendremos el nmero que representa a la hora.
Nmero = Horas*2048 + Minutos*32 + Segundos/2
Por lo que su representacin en memoria es ms adecuada y quedara en 2
bytes como:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 o
'-____ .....,...._---J '----------v------......' ' - - - - - - - - - v - - - - - ~
horas minutos seg/2
Csar Liza A vi/a. Mis libros son econmicos, llO har Tazn para copiarlos.
130 Al[?oritmos y su Codificacin en (>++. Volum.en 2. Csar Liza A vila
Por ejemplo: para la hora 22:31:08 el nmero sera en realidad:
22*2048+31 *32+8/2 = 46052, que se almacenara como:
" ---_./
'---...".------- --------'---y-
horas minutos segl2
De esta manera se puede obtener el nmero a partir de la hora, o .hora a
partir del nmero, realizando rpidamente .2 utIlIzando
desplazamientos de bits hacia la derecha, y multIplIcacIOnes por 2
utilizando desplazamientos de bits hacia la izquierda.
Leemos las horas minutos y
segundos.
Las horas deben ocupar los
5 bits ms altos, por lo que
hay que desplazar el valor
ledo 16 -5 = 11 posiciones
a la derecha (h.h 11).
Los minutos se ubican
desde el 6to bit por lo que
hay que desplazarlos 5
posiciones (h.m 5).
La cantidad de segundos
ingresados debe guardarse
por la mitad, por ello 10
dividimos entre 2, mediante
el desplazamiento de una
posicin a la derecha.

\, v ,i'
Cnr Liz.a Avila. Nu mates la produccin intelectual, no copies stf' lil"!ro.
Manipulacin de bits 131
Solucin:
Los archivos que tenemos en nuestros discos tienen como uno de sus
atributos la fecha de grabacin y; adems, en el caso del Windows, la fecha
de la ltima modificacin. Para su almacenamiento el DOS y el
WINDOWS, y muchos programas como el WinZip que almacena las
fechas de sus archivos comprimidos, utilizan un mismo formato para
almacenar la fecha, el cual explicamos a continuacin.
Cmo almacenan la fecha los S.O.
Como los das slo pueden ser della 31, sern necesarios 5 bits,
pues log2 (31) ::::: 5 (2 elevado a la 5 es 32)
Como los meses slo pueden ser 12, entonces necesitamos 4 bits,
pues log2 (12) ::::: 4 (2 elevado a la 4 esl6)
Como en 2 bytes hay 16 bits de los cuales ya utilizamos para el da
y el mes 5+4=9; nos quedan 7 bits con los cuales podemos
representar hasta 128 aos (2 elevado a la 7).
15 14 13 12 11 10 9 8
7 6 5 4 3 2 O
'---------v---------' '-------y-,---
ao
mes da
La primera PC (Personal Computer) fue presentada en otoo de 1981 por
IBM, y por lo tanto en una PC no pueden existir archivos anteriores a esta
fecha. Por esto el DOS y Windows toman como ao de referencia a 1980,
y cuando creamos un archivo se almacena solo la diferencia respecto a este
ao.
Csar Liza Avila. Mis lihros son econmicos. no hay ra2:I1 para capiar/os,
1.12 Algoritmos y su Codificacin en e t +. Volumen 2. Csar Liza A. vilo
De esta manera podramos manejar como mximo con este formato y a
nivel de almacenamiento de archivos, fechas del sistema desde 1980 hasta
2108 (1980+ 128); sin embargo, la Jtima fecha posible de manejar con
estos sistemas operativos es 31/12/2099.
Para almacenar la fecha Da/Mes/Ao se almacenar un nmero de 2 bytes
dado por:
NroFecha = (Ao-1980)*512 + Mes*32 + na
El factor 32 (2 elevado a la 5) se incluye porque hay que desplazar 5 bits al
mes (el da ocupa los primeros 5 bits y no podemos sobreescribirlos).
El factor 512 (2 elevado a la 9) se incluye porque hay que desplazar 9 bits
al ao (el da ocupa los primeros 5 bits, el mes los 4 siguientes y no
podemos sobreescribirlos).
Por ejemplo, para almacenar la fecha 25 diciembre de 2005, se almacenar
el nmero entero sin signo:
NroFecha = (2006-1980)*512 + 12*32 + 25 = 13721
Da
Mes
Ao -1980
Dec Bin
25 11001
12 1100
26 11010
15 14 13 12 11 10 9 8 7 6 5 4 3 2 O

'--.---"y"'------..../'--------..y-------..--/
ao mes da
Todos los sistemas compatibles con DOS y WINDOWS y con su forma de
almacenar archivos FATo VFA T, utilizan 2 bytes para almacenar la hora y
2 bytes para la fecha.
Csar Liza Avila. No mates la produccin intelectual, no copies ste lihro.
Una vez ledo el nmero
de dos bytes
(cinnroFecha)
tomamos solo los bits que
necesitamos para obtener
el da, el mes y el ao ..
Para el da, sabemos que
se almacena en los 5
primeros bits, por lo tanto
aplicaremos un AND con
una mscara de 0000
0000 0001 111] que
equivale en hexadecimal
a OxOOlF.
Manipulacin <ir' bit; B3
...
CODIFICCIONiN en
#ifl6tide<iostream.h>,

t:
.
voi(f!laih( voig)
. ' ..', ",'.' ,
sh$rt .... ',
.. ";
i: '::
. &:pxOlaO)'>'?5;.
t 19$0;.
e
";;." ,,; .. . ',.0. , ... e
En el caso del mes, debemos determinar el valor de los bits nombrados
como 5, 6, 7 Y 8, para esto aplicaremos un,a mscara de 0000 000 J 1110
0000, que en hexadecimal eqllivale a Ox01EO, pero hay que desplazarlo 5
posiciones a la derecha para obtener su verdadero valor decimal.
Finalmente, el ao ocupa los 7 ltimos bits por lo que aplicaremos un AND
con mscara 111 1 1110 0000 0000 que equivale a OxFEOO en hexadecimal.
Dicho valor debe desplazarse 9 posiciones a la izquierda para obtener su
verdadero valor decimal y adems hay que aadirle el ao base, 1980.
N:mero Que representa fecha? 137211
Dva:25 .
- .. .'1

Mes: 12 .
fho:2006
Csar Liza A vila. Mis libros son econmicos, !lO hav razn para copiar/os.
------------------------------- -_ .... _-_ ..
134 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar tiza A vila
Solucin:
Este es el mismo problema que
el 4.5, pero implementado
usando campos de bits, con
ellos podemos acceder
directamente al conjunto de bits
definidos, ahorrndonos el
trabajo con desplazamientos, y
la mscara, pero no podemos
evitar la divisin entre dos
(s1) para almacenar slo los
segundos pares.
Leemos las horas, minutos y
segundos y los llevamos al
miembro (hora) de la union
horaUnion hora, como son
campos de bits, se alinearn en
los bits apropiados, luego
accedemos a los mismos bits
pero ahora interpretados
un unsigned
(hora.nroHora)
como
short
u!Sn MialJnihl10r;
lffh, m,s;,_c' '. . .....
'otit"lfCi."a>. ':',1.. cinh' ....
. c.,o.u. :.M. inUf.5. :,.;.;.,< ....
. v
. hora.hora.h.=c h; .........
hra.hora.m = ... ' .
hr.hQt.:s == '. l/divide, por 2
9ut"NlTIem la hora:" .
. .
(c) Csar Liza A vila. No mates la I'rodw"cin inlelectual, no copies sre lihro.
Soludn:
Tanto los flotantes como los
enteros ocupan" bytes (en
compiladores de 32 bits),
por lo que bastar llenar el
miembro flotante (f) de la
union e imprimir los bits
del miembro entero.
Por ejemplo, si ingresamos
el flotante -123.75,
tendremos:
Manipula!'n de bits J 35
-------'-=---,---
,# inch.ide<ostteal11.h> .
llniotttlotante ...

vojdifrip:B,'its(mt);, .
m!lbiC ..
{utli;l
oUt .

Pero usted se preguntar cmo esos O y 1 se interpretan para formar un
nmero con decimales? En el siguiente problema darnos la respuesta.
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
36 Algoritmos y su Cod(ficacin en C+- +- Volumen 2. Csar Liza A vila
Solucin:
El formato IEEE 754, ocupa 4 bytes, es 32 bits los cuales son
distribuidos de la siguiente manera:
3130292827262524 2322212019181716 1;:' 14131211109 8 7 6 5 4 3 21 o

signo exponente mantisa
Por ejemplo, de acuerdo al problema anterior, para el nmero -123.75 los
bits sern:
1100 0010 1111 O III 1000 0000 0000 0000
signo : 1
exponente: 100001 Ol
mantisa 11101111000000000000000
Signo:
Como est en 1 el nmero ser negativo.
Exponente:
En decimal ser: 2
7
+ 2
2
+ 2 = 133
Pero como est sesgado a 127, hay que restarle este valor 133-127 = 6, que
viene a ser el verdadero exponente.
Este sesgo es necesario para poder tener negativos, por ejemplo
si los bits almacenados fueran 120, entonces el exponente sera 120-127 = -
7.
Csar Liza Avda. No mates la produccin inte1ectual no copies ste fibra .
Manipulacin de bits 137
Mantisa:
Cuyo valor en bits es 11101111000000000000000, se interpreta como la
parte fraccionaria, por lo tanto ser:
1 1 1
fraccin = --- + --- + --- + O + --- + --- + --- + --- + O
2 2
2
2
3
2
5
2
6
2
7
2
8
= (2
7
+ 2
6
+ 2
5
+ 2
3
+ 2
2
+ i + 2 ) /2
8
Obtencin del nmero:
Por defecto todo nmero en este formato tiene un 1 implcito, que hay que
sumar a la parte fraccionaria, luego lo multiplicamos por 2 elevado al
exponente obtenido (6), y aadirle el signo, por lo que el nmero ser:
nro = - [ 1 + (2
7
+ 2
6
+ 2
5
+ 2
3
+ 2
2
+ i + 2 ) / 2
8
)* 2
6
= _ (2
8
+ 2
7
+ 2
6
+ 2
5
+ O +2
3
+ 2
2
+ 2
1
+ 2 ) / 2
2
= -(256 + 128 + 64 + 32 + 8 + 4 + 2 + 1) /2
2
= -495/4
= - 123.75
El programa usa el
struct simplePrecision,
para indicar los bits
que forman cada parte
del formato flotante.
La union es
necesaria, puesto que
nro sirve para
almacenar el flotante
ledo, pf reparte lo
ledo, segn los bits
del formato y, n sirve
para imprimir los bits,
puesto que los
operadores de bits
solo pueden ser
usados con tipos
enteros.
Csar Liza A vila. Mis libros son econmicos, no hay razn pora copiarlos.
.
138 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Liza Avila
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Manipulacin de bits 139
l. Haciendo uso de operadores a nivel de bits, escriba una funcin que
diga si un nmero entero eS negativo o positivo. Si el ltimo bit esta en
1 el nmero se considera negativo, y estar expresado como
complemento a dos.
2. Lea un mensaje y usando una funcin encrptelo por negacin de bits.
Luego desencriptelos.
3. Escriba una funcin que divida un entero entre una potencia de 2, y
otra funcin que multiplique un entero por una potencia de 2.
4. Lea un entero y diga los valores de los bits pares.
5. Se desea codificar n posibles valores Cuntos bits son necesarios?
Muestre todas las combinaciones a nivel de bits posibles.
6. Dado una variable tipo char muestre cada uno de sus bits. I
7. Lea una variable tipo double y muestre cada uno de sus bits.
Sugerencia: en algunos compiladores una variable long int ocupa 8
bytes de tal manera que' usando una unin podra leer un double y
mostrarlos como un long int, sin embargo en VC++ y Dev-C++, un
long inl ocupa solo 4 bytes (32 bits), de tal forma que no podr tomar
los 64 bits que ocupa el double, para solucionar esto podra usar un
arreglo de tipo unsigned inl con dos elementos.
8. Dada un nmero que representa una hora obtenga las horas minutos y
segundos.
9. Dada una fecha, obtenga el nmero que la representa en elformato de
codificacin del DOS y Windows.
10. Se sabe que para convertir una letra minscula en mayscula se resta
32, es decir si el (/0 bit (2
5
=32) esta en 1, entonces debemos convertirlo
a O. Utilizando esta idea convierta una letra minscula a otra en
mayscula.
11. Un artculo tiene un cdigo numrico almacenado en 8 bits, los 3
primeros indican la famUiq, los 2 siguientes la subfamilia, mientras
que los 3 ltimos son un nmero correlativo. Dado un nmero que
representa el cdigo, diga ClI;l es sufamilia, subfamilia y correlativo.
12. Dados dos bytes, coloque l ~ ~ 4 bits superiores del primer byte junto a
los 4 bits inferiores del seguhdo byte, y los 4 bits inferiores del primer
byte, junto a los 4 bits superiores del segundo byte.
Csar Liza A vila. Mis libros son econmicos, no hay razit'para copiarlos.
R410 AIRorilmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
.13. Lea una matriz de 8x8 caracleres que solo ceros y unos y
almacnelos en 8 bytes.
14. En un uw;signed ch,al!' intercambie los 4 bits inferiores con los
superiores.
J 5. Se tiene el siguiente mensaje encriptado char msje! J ={ 12, J 7, 29, 22,
11, 88, 77, 88, 8, 12, 23, 11, NUIL}; se sabe que ha sido encriptado
con el mtodo de XOR con clave de un carcter y que dicho caracter
es una letra. Cul es el mensaje original? Cul es la dave?
16. Se sabe que las letras del cdigo ASCII, van del 65 al 92 para las
maysculas y del 97 al 122 para las minsculas, es decir siempre son
menores que 128 o sea que solo son necesarios 7 bits para enviar un
mensaje de texto. Podemos entonces almacenar 8 caracteres en 7
bytes, pues como en cada byte solo utilizamos 7 bits nos sobra J bit y
en 7 bytes nos sobraran 7 bits los que podemos utilizar para almacenar
un carcter ms. Lea 8 caracteres y almacnelos en 7 bytes. Note que
esta forma de almacenar los datos nos produce una compresin del
orden 1/8 =: 1.2.5%.
17. Implemente el siguiente algoritmo de encriptamiento. Lea 8 bytes que
forme en mensaje. Tome los bits O de cada byte y tendr el primer byte
encriptado, tome los bits 1 de cada byte y tendr el segundo byte
encriptado, tome los bits 2 de cada byte y tendr en tercer byte
encriptado y as sucesivamente hasta completar los 8 bits de cada byte.
18. Encripte y desencripte un mensaje por rotacin de bits a la izquierda
por ejemplo, si el carcter es 01000001 y rotamos 2 veces a la
izquierda tendremos el nuevo carcter 00000101. A diferencia del
desplazamiento, en una rotacin los bits que salen se insertan por el
otro lado.
19. Encripte y desencripte un mensaje por inversin de sus bits, esto es
colocarlos en orden inverso al que se encuentran. Por ejemplo, si el
carcter es 00001010 luego de la inversin ser 01010000. No se
confunda con la negacin de bits.
20. En modo consola una variable tipo char ocupa 1 byte mientras que
una de tipo unsigned short in! ocupa 2 bytes. As, es posible leer 2
char y colocarlos en un entero sin signo. Escriba una funcin que
dados 2 chars los coloque en un unsigned short int, y otra funcin que
dado un unsigned short nt obtenga los charo
Csar Liz.a Avila. No mates la produccin intelectual, no copies ste libro.
Generacin de
Nmeros
Aleatorios y
Simulacin
Generacin de Nmeros Aleatorios y Simulacin 143
Solucin:
Un nmero aleatorio es un nmero que es seleccionado al azar, por lo que
es imposible que las computadoras, donde tod esta predeterminado,
generen verdaderos nmeros aleatorios; sin embargo, pueden generar
secuencias de nmeros que estadsticamente sean aleatorias, es por ello
que se denominan "nmeros pseudoaleatorios", Esta secuencia debe
cumplir con dos propiedades importantes. Primero, la Uniformidad, es
decir que todos los nmeros tengan la misma probabilidad de ser escogidos.
Segundo, la Independencia, esto es, dos nmeros de la serie no deben
tener correlacin. Existen pruebas estadsticas que comprueban la
Uniformidad, entre las ms usadas tenemos los test de Kolmogorov-
Smirnov y Ji-cuadrada (chi-square). Mientras que, para probar la
Independencia, tenemos el test de corridas y el test de Poker.
Adems, es deseable que el generador de la secuencia aleatoria ,tenga un
periodo largo, es decir que genere una cantidad grande de aleatorios antes
que la secuencia se repita; asimismo, debe ser un algoritmo rpido y que
sea capaz de volver a generar la misma secuencia de pseudoaleatorios con
el propsito de depurar programas.
Antes de las computadoras, los nmeros aleatorios se generaban utilizando
ruedas giratorias, lanzando dados, tomando una carta, etc. Tcnicas ms
"modernas" consistan en imprimir unas tablas de nmeros, uno apuntaba
con un lpiz y donde ste caa sera el ~ m e r o escogido.
Hacia 1946, Jhon Von Newman con su mtodo del cuadrado central (ver
ejercicio propuesto 5.1), abri el camino para permitir que las
computadoras generen nmeros pseudoaleatorios. Hacia 1951, Lehmer,
propuso el Mtodo Congruencial Lineal basado en la ecuacin Xi= (a.xi.]
+ c) % m. donde a, e, y m, son valores que deben ser elegidos con cuidado
para que pueda ser considerado un buen generador. Note que los nmeros
generados bajo este esquema sern enteros desde O hasta m-l. Como se
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
144 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
tiene una serie finita de valores que pueden producirse (O, ... , m-.1), despus
de haber generado una serie aleatoria, alguno debe repetlfSe y por
consiguiente toda la serie empieza a as es. debemos encontrar
valores de a, m y e, tales que para cualqUIer valor inIcIal de x (xo llamado
semilla del generador de nmeros aleatorios), el de
aleatorios que se puedan generar antes que empiece a repet1fse la sen e sea
grande. Un criterio es que m debe ser un nmero primo grande, tal como
2
31
_1 = 2147483647 (para 32 bits). Unos valores adecuados son c:= O ya:::::
7
5
=16807. .
Todos los lenguajes de programacin modernos, incluyen mtodos para
generar nmeros aleatorios que han ,ido cuidadosamente probados, de tal
manera que, podemos suponer gil, producen secuencias
aleatorias. Sin embargo, aun podemos verificar la calidad de la secuenCIa
generada usando las pruebas estadsticas ya mencionadas.
En la funcin
IinealCongruencial( ), enviamos
un valor inicia] a la frmula,
dicho valor es conocido como
semilla (seed). La variable
semilla al ser de tipo static,
solo se inicializ la primera
vez que se ejecuta la funcin,
en las siguientes llamadas
toma el valor que tuvo en la
ltima invocacin de la
funcin. Los valores de
a=32719, c=3 y m=32749,
son para obtener aleatorios de
16 bits y han sido usados por
algunos compiladores, su
periodo, es decir la cantidad
de nmeros generados antes
que se repita la secuencia, es
32748, que es suficiente en la
muchos casos pero no en
simulaciones de gran
envergadura.
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 145
Solucin:
Cuando hablamos de un intervalo discreto nos referimos a generar nmeros
enteros dentro de ese intervalo. Adems se trata de generar nmeros con
distribucin uniforme, esto es que todos tengan la misma probabilidad de
salir elegidos.
Como ya se explic, para generar una secuencia aleatoria es necesario
inicializar la semilla del generador de nmeros aleatorios. En C/C++ se
delega esa tarea a la funcin srand( ), cuyo prototipo esta en stdlib.h, la
cual acepta un entero sin signo para, a partir de ese nmero, empezar a
generar la serie pseudoaleatoria. Es evidente que si la semilla es la misma,
generar la misma secuencia de nmeros aleatorios. Sera muy tedioso que
el usuario fuera el que ingrese siempre la semHhi, lo ms conveniente es
que la computadora la escoja. Pero cmo logramos que la computadora
cambie la semilla cada vez que se ejecute un programa? Para esto,
tomamos la hora del sistema. La funcin time( ), incluida en el archivo
time.h, devuelve el tiempo transcurrido, medido en segundos, desde las O
horas O minutos y O segundos del tiempo universal coordinado (GMT)
del lro de enero de 1970. Esta medida se llama el "tiempo de
calendario". Como time( ) devuelve un long y srand( ) necesita un
unsigned inl es necesario que hagamos la conversin de tipos, de ah el uso
del cast (unsigned).
La funcin encargada de generar un aleatorio comprendido dentro del
intervalo de O y RAND_MAX (en VC++ 6.0 es Ox7FFF 32767) es rand( ),
cuya declaracin prototipo se encuentra en stdlib.h.
Por ejemplo
haramos:
s quisiramos simular el lanzamiento de una moneda
srand( (unsigned) time (NULL) );
d = rand( ) % 2;
ya que solo devolver 2 valores (O 1).
Csar Liza Avda. Mis libros son econmicos, no hay razn para copiarlos.
146 Algoritmos y su Codificacin en C++. Volumen 2.
Si quisiramos generar varios aleatorios debemos hacer:
srand( (unsigned) time(NULL) );
for (i = O; i< n; i++)
cout< <rand( );
Csar Liza A vi/a
Es necesario que la inicializacin de la semilla se haga fuera del bucle,
puesto que si se ejecuta dentro la semilla (el tiempo), no cambiar durante
un segundo, produCiendo siempre el mismo valor durante ese segundo.
En el programa, la funcin
rand( ), usa la semilla
inicializada con srand( ), y
calcula, mediante su
frmula interna, el primer
aleatorio.
La expresin rand( ) % a
obtiene un aleatorio entre O
y a-l, pues este es el
intervalo posible de
residuos que podemos
obtener al dividir cualquier
entero entre a. Si queremos
obtener un aleatorio entre O
y a debemos hacer rand( )
%(a+l).
La expresin a + rand( ) %
(b-a+ 1), obtiene un
aleatorio entre a y b
inclusive, ya que si el
residuo es O, entonces el
limite inferior es a, mientras
que si el residuo es boa,
entonces el superior ser a +
b-a,estoesb.
Csar Liza Avila. No mates la produccin intelectual, no copies ste lihro,
Generacin de Nmeros Aleatorios y Simulacin 147
Solucin:
Un intervalo continuo significa que dentro de dos nmeros siempre existir
otro. Esto en computadoras no es debido al de
almacenamiento para
flotantes el IEEE 754, no
es posible representar los
infinitos nmeros reales, de
ah que se hable de
precisin.
Ya en el cdigo, luego de
inicializar la semilla con
srand( ), generamos un
aleatorio entre O y 1, como
el valor que puede producir
rand( ) est entre O y
RAND_MAX, si lo
dividimos entre
RAND_MAX el cociente
estar entre O y ]. El cast
(double) es necesario para
convertir el nmero
generado a double y luego
dividirlo con un entero
dando como resultado un
double.
La expresin a + (b-a)*(double)rand( )/RAND_MAX, genera un aleatorio
dentro de los nmeros reales y en un intervalo continuo desde a hasta b,
puesto que (double)rand( )/RAND_MAX, es un numero entre O y 1, cuando
vale O entonces el aleatorio ser a + (b-a)*O = a, mientras que cuando es 1,
ser a + (b-a) = b, cualquier valor intermedio produce una fraccin de (b-a),
que sumado con a dar el valor requerido.
Csar Liza Avila. Mis lihros son econmicos, no hay razn para copiarlos.
-----------------------------------------------------
148 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vla
Solucin:
Este es un clsico ejemplo de Cad<eaa de Markov, y se denomina paseo
aleatorio. Debe saber que la probabilidad de que llegue a cualquiera de los
destinos es del 100%.
Podemos colocar a nuestro amigo borrachn, sobre el origen del eje X,
e iniciamos la
caminata
un
aleatorio O 1. De
ser 1 avanzamos
un paso a la
derecha en
direccin a su casa
(x++); en caso
contrario ir a la
izquierda, en
direccin a la
cantina Esto
se repetir
mientras no llegue
a la coordenada -k
k.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 149
Solucin:
Si generamos n nmeros aleatorios
dentro de mi intervalo, (por ejemplo
entre O y 1) donde n es un nmero
grande, entonces la suma de los n
elementos ser aproximadamente n/2,
y el promedio ser muy cercano a 0.5.
Esto es llamado la "ley fuerte de los
grandes nmeros" que se puede
describir como "con toda certeza
(probabilidad 1) el promedio de una
sucesin de variables independientes e
idnticamente distribuidas converger
a su media".
Una forma en que se manifiesta esto
es cuando se lanza una moneda
muchas veces, la cantidad de sellos
que salgan ser aproximadamente
igual a la cantidad de caras.
El los casinos, siempre' cada juego
tiene probabilidades a favor de la
banca. La "ley fuerte de los grandes
nmeros" nos asegura que aunque
ganemos en un determinado momento
(suerte), si seguimos jugando,
perderemos inevitablemente.
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
1,
\.

150 Algoritmos y su Codificacin en C++. Volumen
Solucin:
Sea [(x) = x
3
+ 2x - 3,
integral entre a y b ser:
. b
b 4 2
J(x
3
+2x-3)dx::: X /4+ x /2-3xl
a a
por definicin la integral es:
b
lm I f(x)
t:\x-? o a
a X b
Mientras ms rectngulos
tomemos, ms cerca estaremos
al verdadero valor del rea.
Si tomamos n rectngulos
entonces por lo que:
b b
Csar Liza A vila
lm I f(x) = lm I f(x) (b-a)/n = (b-a). Hm I f(x) / n
t:\x-? O a
o-? 00 a
Si tomamos una gran cantidad de alturas (n) de manera aleatoria, entonces
I f(x) I n, debido a la ley fuerte de los grandes nmeros, converge al
promedio de las alturas de f(x) y (b-a).I f(x)/n converge por lo tanto al
rea pedida. .
Aqu, usamos la simulacin para determmar
integral de una funcin fcilmente integrable; sm
embargo, la verdadera utilidad se da cuando la
funcin no es integrable por mtodos manuales,
como puede ser la Distribucin Normal vista ms adelante.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
I
Generacin de Nmeros Aleatorios y Simulacin 151
Solucin:
Dibujemos una circunferencia inscrita en un cuadrado.
La relacin entre las reas de la circunferencia y del cuadrado ser:
Area o 1t*radio*radio 1t 1t
, ,
---------
=
----------------- - ----------,------------r =
AreaD lado*lado )*(2*n}fo) 4
4*Area o
de donde: 1t
=
-----------
AreaD
Si aleatoriamente escogemos muchos puntos dentro del cuadrado, algunos
caern dentro del crculo y otros fuera de l. La razn de los puntos que .
caen dentro del circulo respecto al total de puntos tomados, es
aproximadamente igual a la relacin entre sus reas, es ms tambin lo es
a la probabilidad que un punto tomado.al azar caiga en dichas reas; es
decir:
Area o #ptos. dentro del o Probo que caiga en o
1t = 4. --------- = 4. -----------------------.. = 4. --------------------------
AreaD #ptos. dentro del D Probo que caiga en j
,"
Csar Liza Avila. Mis libros son econmin)s, no hay raznll para copiarlos.
152 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza A vila
Podemos generar puntos aleatoriamente dentro de un cuadrado de radio 1 e
ir contando todos aquellos que caen dentro de la circunferencia. Para esto
d 1
., d [ . e . 2 2 2
hacemos uso e a ecuaClOn e a Clrcunlerencra x + y = r .
El valor de 1t se obtiene
dividiendo el nmero de
puntos que caen dentro del
crculo, entre el nmero de
puntos que caen dentro del
cuadrado y, multiplicando
este cociente por 4.
El mtodo es ms exacto
cuantos ms puntos tomemos,
esto debido a la ley fuerte de
los grandes nmeros, ya
explicada.
Este mtodo, puede aplicarse
para calcular reas de figuras
irregulares y que son difciles
de medir directamente como
por ejemplo la superficie de
nuestro beUo pas! Los
cartgrafos tomaran las
coordenadas de los hitos y
con ellos haran un mapa a escala.
interior del mapa, sera pintada de un
parte exterior de otro, luego muchos
puntos dentro del rectngulo y preguntamos su
color, la relacin de puntos de un color respecto
al total de puntos ser proporcional a las reas.
Csar Lizo Avifa. No mates la pn"frtel'll intelectual, no copies sre libro.
Generacin de Nmeros Aleatorios y Simulacin 153
Solucin:
Hasta ahora hemos visto como generar nmeros aleatorios, tanto enteros
como reales, con distribucin uniforme, donde todos los nmeros tienen
la misma probabilidad de ser escogidos. Pero qu pasa si algunos nmeros
tienen mayor probabilidad de salir, pues cumplen con una determinada
distribucin de probabilidad ya sea discreta o contina? Por ejemplo si una
moneda est cargada de tal manera que pueda salir cara con mayor
probabilidad, evidentemente ya no ser uniforme. En este y en los
siguientes ejemplos veremos como generar un nmero aleatorio con
distribuciones no uniformes, a partir de un nmero aleatorio con
distribucin uniforme, para esto haremos uso del mtodo de la
transformada inversa.
Transformada Inversa para valores discretos
Supongamos que tenemos la . g
ruleta mostrada, las "**''''' I
probabilidades que salga cada 4 2
nmero se muestran en la tabla. 3
3 0.125
4 0.125
A partir de esta tabla se obtenemos la siguiente:
:V:ill:,
! 0.500 0.500 [0.000,0.500> Luego, generamos un
2 0.250 0.750 [0.500,0.750> nmero aleatorio
3 0.125 0.875 [0.750,0.875> uniformemente
4 0.125 1.000 [0.875, 1.000] distribu ido entre O y 1, Y
buscamos el intervalo al cual pertenece, obteniendo el valor. que le
corresponde. Este valor ser el aleatorio deseado. Si por ejemplo,
generamos un aleatorio entre O y 1, y resulta 0.6111 entonces el valor
pedido es 2. Note como a partir de un nmero aleatorio con distribucin
uniforme obteriemos un aletorio con distribucin no uniforme.
Csar Liw A vila. Mis libros SO/1 econmicos. /lO hav rm:n pora copiarlos.
154 Algoritmos y su C"d(ficacin en +. Volumen 2. Csar Liza Avila
E"te mtodo lo podemos usar para simular el resultado del siguiente sorteo
de la Tinka a partir de los datos histricos. La siguiente tabla muestra cada
bolita y el nmero de veces que ha salido (hasta la fecha en que escrib este
programa, dirjase a para datos ms actualizados).
(P ;1i. ;;,:,:rJt;;I\QI(;::-;\;'
Para obtener cada

[ 0.00 - 0.02 :::..
124 0.05 [0.02 - 0.05 > una de las bolitas
185 0.07 [ 0.05 - 0.07 >
que saldrn en el
240 0.10 0.07 -0.10 >
289 0.12 0.10-0.12> siguiente sorteo,
339 0.14 [0.12-0.14>
generamos un
408 __ .Q:.!2.-. 0.14-0.172 _
464 0.19 nmero aleatorio
511 0.21 0.19-0.21 >
entre O y 1
0.24 0.21 - 0.24 >
0.26 [0.24 - 0.26-';:- distribuido
684 0.28 0.26 - 0.28 >
uniformemente,
743 0.31 0.28 - 0.31 >
815 0.34 0.31 -0.34> buscamos en la
871 0.36 [ 0.34 - 0.36 >
ltima columna el
934 0.39 0.36 - 0.39 >
intervalo el cual 1005 0.42 0.39 - 0.42 > en
1073 0.45 0.42 - 0.45 >
se encuentra, y nos
1127 0.47 [ 0.45 - 0.47 >
dirigimos la

0.50 0.45 - 0.50 > a
1245 0.52 [ 0.50 - 0.52 >
primera columna y
1294 0.54 0.52 - 0.54 >
vemos a qu nmero
1356 0.57 [ 0.54 - 0.57 >
1419 0.60 [0.57 - 0.60 >
corresponde.
1479 0.62 0.60 - 0.62 >
Esto lo hace
1530 0.64 0.62 - 0.64 >
es que
1579 0.66 [ 0.64 - 0.66 >
el siguiente
1635 0.69 0.66 - 0.69 >
programa, . el cual
0.70 0.69 - 0.70 > 1676
0.70 - 0.73 >
datos de
1735 0.73
toma como
1796
---.75
[0.73 - 0.75 >
entrada, el nmero
1861 0.78 0.75 - 0.78 >
1924 0.81 0.78 - 0.81 >
de veces que sali
1971 0.83 [0.81-0.83>
cada bolita.
2024 0.85 [ 0.83 - 0.85 >
2096 0.88 0.85 - 0.88 > Por sencillez, el
2127 0.89 0.88 - 0.89 >
programa no verifica
2158 0.91 0.89 -0.91 >
2203 0.93 0.91 - 0.93 > si las bolitas se
2236 0.94 [0.93 - 0.94 >
repiten. Esto tendr
2262 0.95 [0.94 - 0.95.?
2295 0.97 0.95 - 0.97 > que aadirlo el
2324 0.98 [ 0.97 - 0.98 >
lector.
2340

[0.98 - 0.99 >
2364 ____ 1.00 [0.99 - 1.00 J
@ Csar Liza Avila. No 11laleS la produccin intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 155
I
I
I
I
Csar Liza Avila. Mis libros son econmicos, no fUlv razn para copiarlos.
156 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza Avila
Solucin:
La Distribucin de Poisson aparece en muchos fenmenos y es una
distribucin discreta; esto es, el mmero de ocurrencias es un nmero
entero. Una variable aleatoria X, 'lile sigue una Distribucin Poisson,
significa que en cada unidad de tiempo es posible que ocurra una cantidad
entera de eventos, como la llegada de un cliente, bajo los supuestos a) los
eventos ocurren de manera independiente de otros eventos, b) los eventos
no ocurren simultneamente, c) la tasa promedio de eventos es constante.
El nmero de eventos en un tiempo determinado es entonces una variable
aleatoria de Poisson con parmetro A. Una e .i. Af
variable aleatoria X con stas caractersticas tiene Pi = P{X =i} = ~ _____ _
la funcin de densidad de probabilidad (fdp)
mostrada, donde i = O, 1,2, .... , ye = 2.71828.
.,
l.
En otras palabras sta frmula nos dice que si la tasa media en que ocurren
los eventos es A, entonces la probabilidad que ocurra:
O eventos es: Po:::': e'; 2
%
!
1 eventos es: PI:= t") 2
1
/1!
2 eventos es: P2 ~ . ; e . 2212!
y as sucesivamente.
Observe que:
La probabilidad de que ocurran i eventos es: Pi = e

;'}i!,
La probabilidad de que ocurran i + 1 eventos es: Pi+l = e Ie A,i+lCi+ 1)1
La razn entre dos trminos consecutivos ser:
Pi+1 e'AA,i+ll(i+l)! A,
= - - - - - - - - - - ~ - ~ - ~ = ~ =
Pi e 'A 'A,i i! i + ]
factor que usaremos en nuestro programa para facilitar los clculos.
Podemos demostrar que es una verdadera distribucin de probabilidad
pues: PO+P+P2+ ... = e i, 2
%
! + e" ).//1! + e .J. 2212! + ...
= e i. (2
%
! + }///! + 2212! + ... )
= e .'.e!.
= /
Csar Liza A Fila. No mates la produccin intelectual, 110 copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 157
!)i deseamos simular cuntos eventos (i) OCUlTen en una unidad de tiempo,
haremos uso del "Mtodo de la Transformada Inversa", esto es
generamos un nmero aleatorio r uniformemente distribuido entre O y 1 Y
buscamos el valor de i correspondiente al intervalo en donde se encuentra r.
La funcin poisson(), genera
un nmero entero aleatorio
que cumple una Distribucin de
Poisson con parmetro lambda.
Primero, generamos un
nmero aleatorio (r)
uniformemente distribuido
entre O y 1, e iniciamos la
bsqueda de i. Si i=O,
entonces la probabilidad
correspondiente p es e .,1 (pues
A,=l y 0!=1) Y la probabilidad
acumulada F es igual a p.
Debemos ir acumulando las
probabilidades hasta encontrar
el primer valor de
probabilidad acumulada que
sea mayor a r, cuando esto
ocurra terminar el bucle y el
valor de i ser la cantidad
buscada. Observe el uso del
factor Iambda/(i+1) para el
clculo de las probabilidades
de 2 nmeros consecutivos.
Csar Liza A vila. Mis libros SOIl econmicos, no hay razn para copiarlos.
158 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Solucin: ,
. Antes de mostrar el programa, veamos como utilizamos el metodo de la
transformada inversa para valores continuos y luego hablemos sobre la
distribucin exponencial.
Transformada inversa para valores continuos .
Note que el mtodo de la transformada inversa para dIscretos,
consiste en ir sumando las probabilidades de cada valor. SI dIchos valores
son continuos entonces la sumatoriase transforma en una integral.
Si X es una variable aleatoria continua, y p(x) es la probabilidad de cada
resultado x, entonces las probabilidades acumuladas estn dadas por:
x
F(x) = J p(x) dx
o
si generamos un valor aleatorio r, uniformemente distribuido, .e.ntonces nos
debemos preguntar para que valor de x, la suma de las probablhdades da r.
Entonces debemos resolver la ecuacin:
x
r = I p(x) dx
o
resolviendo la ecuaCIon, el valor de x, ser el aleatorio generado que
cumpla con la distribucin p(x).
La Distribucin Exponencial . .
Es una distribucin continua que est completamente defmIda cuando se
conoce la media de la distribucin 1IJ.l. Est dada por f(x) = J.l.e""X, donde e
es la base de los logaritmos neperianos e = 2.718281828, J.l es el .valor
esperado (tasa media), 1/J.l es la media de la Una. propIedad
importante de la Distribucin Exponencial, es que no tIene memona; esto es,
lo que ocurra en el futuro no depende de lo ocurrido anteriormente
independientes) y la mayora de sus valores son de .la
esperada (1/,..). A diferencia de la Distribucin de POIsson, la Dlstnbuclon
('sar Liza Avila. No mates la produccin intelectual, no copies ste libro.
(
"1
Generacin de Nmeros Aleatorios y Simulacin 159
Exponencial, es una distribucin continua, por lo que puede tomar valores
fraccionarios.
La Distribucin Exponencial es una verdadera distribucin de probabilidad
pues:
'" '"
F(x) = f /le"'" = e-"x lo = 1 - e""'" = 1
o
Para simular una variable aleatoria (x) con distribucin exponencial,
haremos uso del "Mtodo de la Transformada Inversa". Empezamos generando
un nmero aleatorio (r) entre O y 1 uniformemente distribuido y nos
preguntamos que valor de x, hace que la funcin de densidad acumulativa
(fda) sea igual a r. Siendo una distribucin continua, la funcin de
densidad acumulativa (fda) desde O hasta x, ser:
x x
F(x) = f /le'''' = e-J.Ix lo = 1- e""X
o
Esta expresin debe igualarse al nmero aleatorio generado: r = 1- e -"x. lo
que equivale a: e""x = 1 - r, aplicando logaritmos neperianos para despejar x
tenemos: In(e""X) = In(1-r), esto es: -J.l.x.ln e = In(l-r), puesto que In e =1,
tendremos:
x = -In(l-r)/ J.l
En otras palabras si generamos un nmero aleatorio r distribuido
uniformemente entre O'y 1, aplicando la frmula anterior podremos obtener
un nmero aleatorio x distribuido exponencialmente.
La grfica de una Distribucin Exponencial se
muestra en la figura adjunta. Aqu poderhos
observar el valor medio 1/J.l y el rea r
encerrada bajo la curva f(x) y los lmites O y x.
y
r
X
1/11 x
Csar Liza Avila, Mis libros son econmicos, no hay razn para copiarlos,
I
I
1
l'
160 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza A vi/a
La distribucin exponencial, es muy usada en la simulacin de lneas de
espera (colas) para generar el tiempo de atencin; en la teora de
confiabilidad, para estimar el tiempo entre fallas de los componentes
elctricos; as como en la desintegracin de partculas radiactivas, como por
ejemplo para calcular la edad de los fsiles mediante el carbono 14.
Existe una estrecha relacin entre la Distribucin Exponencial y la Distribucin
de Poisson, puesto que si la distribucin exponencial modela el tiempo
(continuo) entre dos eventos, para un tiempo t habrn ocurrido una cantidad
entera de eventos que estar dada por la Distribucin de Poisson.
La funcin exponencial( ), se
encarga de generar una
variable aleatoria que sigue
una Distribucin Exponencial.
Aqu, generamos un nmero
aleatorio (r) uniformemente
distribuido entre O y 1, para
luego aplicar directamente la
frmula y obtener la variable
aleatoria distribuida
exponencialmente.
Note que si r es un nmero
aleatorio uniformemente
distribuido entre O y 1,
entonces 1 - r tambin lo es,
por lo que podramos haber
optimizado el programa y
escribir -Iog (r) en vez de -
log (l-r). Recuerde que en
C/C++ la funcin log( )
obtiene el Logaritmo Natural
o Neperiano, mientras que el
f
l[' Logaritmo Decimal o de
Briggs lo podemos obtener
Generacin de Nmeros Aleatorios JI Simulacin 161
Solucin: .
La Distribucin Normal, llamada tambin campana o curva de Gauss, es
una distribucin continua muy utilizada en estadstica, pues muchos
fenmenos naturales se comportan en forma normal. Esto es evidente
puesto que la mayora de caractersticas de los fenmenos presentes en la
natura)eza son similares y cercanos a la media, algunos poco se desvan de
ello. Por ejemplo, las tallas y pesos de los seres vivos, el efecto de una
dosis de algn frmaco, las notas de los alumnos, errores de medicin, la
demanda de productos, etc.
(X-I1- )'
I
I( x) = -----::.:::::--- e
uY2n
J1 = valor medio
u = desviacin estndar
2 .
U = vananza
n = 3.1415 ...
x = valor de la abscisa
e = 2.717282818
La Distribucin Normal, esta definida por dos parmetros su 'media y su
desviacin estndar; N(I-l, u)
Caractersticas:
Puede tomar cualquier valor (- 00, +00).
Son ms probables los valores cercanos al valor medio.
Conforme nos separamos del valor medio, la probabilidad va
decreciendo de igual forma a derecha e izquierda (es simtrica).
Conforme nos separamos del valor medio, la probabilidad va
decreciendo de forma ms o menos rpida dependiendo de un
parmetro cr, que es la desviacin estndar. .
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
~ - ~ ~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - ~ - - ~ . - - - ~ _ . - ~ -_o -
f"
'"
';
.
162 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Para generar una variable aleatoria que siga una DistribuCin Normal,
podramos hacer uso de la transformada inversa, pero como se habr dado
cuenta dicha integral no es calculable por mtodos manuales, debiendo
hacer uso del clculo y de los mtodos numricos, o de la misma
simulacin, tal como se mostr en el Problema 5.5.
Una forma ms fcil de generar esta variable aleatoria, se basa en el
Teorema del Lmite Central: la suma de variables aleatorios tiende a una
distribucin cuando la cantidad de variables es grande.
Segn este teorema, si los valores "o, Xl. . . ., X
n
estn distribuidos
independientemente con media J.l y varianza ci entonces la variable
(XO+XI+" .+xn) - nJ.l
Zn = ---------.--.---.-------
... (n 0'2)
est aproximadamente distribuida en forma normal con media O y varianza
1, cuanto mayor sea el valor de n mejor ser la aproximacin.
Sabiendo que una variable aleatoria x que sigue una distribucin uniforme
de O a 1, tiene una media 1/2 y una varianza de 1/12, si generamos n
nmeros aleatorios uniformemente distribuidos entonces, la expresin
anterior se transforma en:
(XO+XI+" .+xn) - 012
Zn = ------------_.-.-------.
... (n /12)
y puede usarse para calcular para calcular una variable aleatoria normal
estndar con media O y varianza 1.
Esta frmula funciona bien para valores pequeos de n, por lo general se
escoge n=12 para eliminar la raz cuadrada, quedando como:
n=11
Zn = :Ex- 6,
i=O
donde Xi es un aleatorio distribuido uniformemente, Zn es la variable
aleatoria Normal Estndar, por lo que si deseamos una variable aleatoria
Z con Distribucin Normal, con media J.l y varianza 0'2 usamos el
resultado anterior haciendo:
Z= J.l+O'Zn
relacin que utilizamos en nuestro programa.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 163
(
Csar Liza Avila. Mis libros son econmicos 110 hay ra ' . 1
. ., zon para Coptar.os.
I
10..,
164 Algoritmos y su Codificacin en C++. Volumen 2.
Solucin:
Si tenemos 3 elementos {I, 2, 3}
al mezclarlos podemos obtener 3!
= 6 resultados diferentes que son:
{ 1, 2, 3}, (l, 3, 2}, {2, 1, 3}, {2, 3,
l}, {3, 1, 2}, {3, 2, l}; ha esto se le
conoce como permutacin, si de
todas estas posibles formas de
ordenar los elementos tomarnos
una al azar, estaremos hablando de
una permutacin aleatoria.
Como recordar (hablamos de
permutaciones en mi libro
Algoritmos y su Codificacin en
C++, Volumen 1), la cantidad de
permutaciones crece rpidamente,
por esto no es recomendable
obtener todas las permutaciones
para elegir una. Es mejor aplicar
el siguiente mtodo: Tomemos el
primer elemento e intercambimoslo por
olro ubicado en una posicin aleatoria.
Tomemos el segundo elemento ti
intercambimoslo por otro ubicado en una
posicin aleatoria, y as sucesivamente-
Csar Liza A vila
hasta el ltimo elemento. Esto es lo que hace la funcin permutaAleatoria( ).
Note que no se repite ningn elemento, puesto que solo los cambiamos de
lugar aleatoriamente.
Podemos necesitar una permutacin aleatoria en varias situaciones: al
barajar las cartas, para determinar el orden en que llegarn los caballos en
una carrera donde todos tienen la misma probabilidad de ganar, el orden en
que llegarn los alumnos al saln de clase; es decir, en todas aquellas
situaciones en donde necesite mezclar un conjunto de elementos.
Csar Lizo Avila. No mates la prodUlocilI intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 165
Solucin:
La cantidad total de combinaciones o formas diferentes de agrupar n
elementos tornados de r en res:
n!
c
n
r =
(n-r)! r!
Si tenemos 3 elementos { 1, 2, 3} podemos escoger 2 de ellos de:
3!
C
3
2 = ----------- = 3 formas diferentes
(3-2)! 2!
al igual que con las permutaciones, obtener todas las combinaciones y
escoger una de ellas, resulta computacionalmente costoso.
Sin embargo, podemos modificar ligeramente el algoritmo del problema
anterior:
Tomemos el primer elemento e intercambimoslo por otro ubicado en una posicin
Tomemos el segundo elemento e intercambimoslo por otro ubicado en
una posicin aleatoria, y as sucesivamente hasta el elemento r-simo.
Como notar la nica diferencia, es que solo llegamos hasta el elemento r y
no procesamos el resto de elementos. Esto es lo que hace la funcin
combAleatoria( ).
Las combinaciones aleatorias estn presentes en muchas situaciones, por
ejemplo, si tengo n individuos y deseamos tomar una muestra de r
elementos, escogida al azar, en la generacin de una cartilla de Bingo en
donde para cada columna debemos escoger 5 nmeros dentro de J 5
posibles; en el popular juego de la Tinka, si deseamos simular que bolitas
saldrn en el sorteo cuando todas tienen la misma probabilidad de salir,
pues de 45 bolitas sacamos 6 sin que se repitan, entre otras situaciones.
Csar Liza A vda. Mis libros son econmicos, no Iza,. f"CI;::Il para copiarlos.
166 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Liza Avila
A propsito la Tinka puede producir:
45!
C456 = ____________ = _______ = 8' 145,060 resultados diferentes
(45-6)! 6! ,3'9! * 6*5*4*3*2
de los cuales solo uno es el ganador del premio mayor, esto es la
probabilidad de sacarse la Tinka es 1 entre 8'145,060, o sea: 0.000000123
Liza Avila. No mates la produccin intelectual, no copies ste libro.
I
Generacin de Nmeros Aleatorios y Simulacin 167
l. Un generador de nmeros aleatorios desarrollado por Jhon Von
Neumann hacia 1946, y que mostr el camino para generar nmeros
aleatorios por computadora, es conocido como "mtodo del cuadrado
central". Consiste en elevar al cuadrado el anterior aleatorio
generado y extraer los dgitos centrales. El valor inicial es conocido
como semilla y el usuario lo ingresa o lo toma de la computadora a
partir del reloj interno. Por ejemplo, si la semilla eS 121, la elevamos
al cuadrado tendremos 14641, extraemos sus 3 dgitos centrales se
obtiene 464, a partir del cual se obtendr el siguiente aleatorio.
Genere n aleatorios con este mtodo. Aunque no es un mtodo
adecuado, pues genera secuencias muy cortas de nmeros y parece
existir correlacin entre ellos; tiene un valor histrico, puesto que fue
el primer mtodo implementado en computadora y nada menos que por
el creador de la arquitectura en la que se basan las computadoras
modernas.
2. Genere aleatoriamente una fecha vlida. Considere los aos bisiestos.
3. Genere aleatoriamente un entero y luego permute sus dgitos.
4. Se coloca una reina en un tablero de ajedrez vaco, muestre una
caminata aleatoria de la reina.
5. El volumen de una esfera es v=4/3 nr
3
, supongamos que no conocemos
la constante C=4/3, estime por simulacin el valor de C sabiendo que
la ecuacin de la esfera es x
2
+l+l=1. Sugerencia: extienda el
Problema 5.7, dado en dos dimensiones, hacia el espacio
tridimensional.
6. Genere una baraja de cartas y luego mzclelas.
7. Genere aleatoriaf1!-ente una cartilla de Bingo.
8. En que orden llegarn n alumnos a unflula de clases. Considere el
cdigo y el nombre del alumno. Sugerencia: Use una permutacin
aleatoria de un arreglo de estructuras.
9. Se desea emparejar n hombres con m mujeres pero de manera
aleatoria, muestre una forma en que pueden emparejarse. Quines
quedan sin pareja? Sugerencia: Use una permutacin aleatoria.
10. Coloque en una matriz de nxn los nmeros del 1 al n
2
aleatoriamente,
sin que se repitan. A esto se le llama Cuadrado Latino.
Csar Liza Avila. Mis libros son econmicos, no hay rqzn para copiarlos.
l8 Algoritmos y su Codificacin en C++. Volumen 2.
Csar Li:Ci A vila
l. Se desea realizar un estudio mdico paro comprohar la efectividad de
un nuevo medicamento. Para ello se divide a los voluntarios en dos
grupos, uno llamado grupo de control, al cual solo se les dar un
plarebo (una sustancia que no causa ningn efecto) y al otro se le
aplica el nuevo medicamento. Si tenemos iJl voluntarios selecone
aleatoriamente un grupo de n/2 personas, ai cual se va a aplicar el
nuevo medicamento. Sugerencia: use una combinacin aleatoria.
12. Se tiene m carreras con 11 caballos en cada carrera, todos los caballos
tienen la misma probabilidad de ganar. Muestre el orden en que
llegarn en cada carrera e indique cuntas veces va ganando cada
caballo. Sugerencia: use una permutacin aleatoria por cada carrera.
13. Genere n elementos de un arreglo, luego elimine todos los elementos
aleatoriamente. Muestre el orden en que se van eliminando.
14. Un dispositivo incluye dos componentes. La probabilidad que uno de
ellos falle es p, el dispositivo deja de funcionar si los dos componentes
fallan. Escriba un programa que simule el encendido del equipo 11
veces y diga cuntas veces falla.
15. El juego Memoria contiene n pares de figuras diferentes y consiste en
descubrir dos figuras; si son iguales, stas se retiran y se contina
escogiendo otra pareja. Escriba un programa que permita jugar
memoria. Sugerencia: llene un arreglo de nxll elementos con n
2
f2
pares de elementos iguales, y fuego mzclelos.
16. Muestre a un cuerpo que se mueva aleatoriamente, dentro de los
lmites de una matriz, y una casilla a la vez. Debe verificar los lmites
de la matriz. Este movimiento aleatorio se llama movimiento
Browniano y representa el nwvimiento de una partcula muy pequea
(dimetro inferior de una milsima de milmetro) en un fluido debido al
impacto de los tomos o molculas del fluido sobre la partcula. Por
ejemplo el humo que se dispersa por el aire o la tinta que se difunde en
el agua o los granos de polen en el agua.
17. Un Bull o Diana contiene n crculos concntricos cada
uno de radio conocido, se lanza un dardo que cae en
alguno de los crculos, cada uno de ellos tiene un
puntaje definido. Simule el lanzamiento de d dardos en
el Bull y muestre el puntaje total obtenido. Sugerencia:
Genere dos nmeros aleatorios dentro del intervalo continuo desde
cero hacia el radio mayor, use la ecuacin de la circunferencia
X2 +l=r
2
, para determinar dentro de qu crculo cay.
Csar Liza A vi/a. No mates la produccin intelectual, no copies ste libro.
Generacin de Nmeros Aleatorios y Simulacin 169
18. Se tiene una cerradura compuesta de tres dgitos (del O al 9). Se
ingresa la clave, pero sta se olvida. Si generamos claves al azar En
cuntos intentos habremos logrado abrir la cerradura? Asegrese de
no repetir una combinacin ya probada.
19. Se realiza un minicampeonato deftbol con 6 equipos: A, B, C, D, E Y
F; en el cual cada equipo juega 5 partidos. Se desea simular los
resultados de dicho campeonato generando aleatoriamente el nmero
de goles que consiguen y recibe cada equipo. El puntaje es 3 puntos
para el ganador y 1 punto para cada uno, si empatan. El Campen
ser aquel que tenga el mayor puntaje, o si hay empate la mejor
diferencia d goles. Asuma que en un partido no puede haber ms de
12 goles en total ya sea recibidos o anotados por ambos equipos.
20. Una empresa de carga, dispone de un camin y est considerando
comprar otro camin. En la actualidad alquila los camiones
adicionales necesarios a 250 soles al da. El camin de la empresa
ocasiona un gasto de 150 soles al da se use o no. La compra de un
nuevo camin ocasionara el gasto de 175 soles al da. De los datos
histricos se sabe que el nmero de camiones requeridos sigue la
siguiente distribucin:

O 0.10
1 0.40
2 0.35
3 0.15
Realice una simulacin para decidir si es conveniente la compra de un
nuevo camin.
Csar Liza Avda. Mis libros SOI1 econmicos, no hay razn para
!
Punteros y
Asignacin
Dinmica de
Memoria
i
l
b
Punteros 173
oludn:
La memoria puede verse como una serie de casilleros consecutivos que
tienen un nmero que las identifica, llamado direccin de memoria, cada
casillero ocupar byte. Estas direcciones de memoria se acostumbran a
escribir en hexadecimal.
Cmo se almacenan las variables en memoria?
Si declaramos las variables: int a = 50;
char b = 'M';
fioal e = 3.75f;
double d = 2.1;
se almacenan en memoria tal como se muestra:
OxOO12FF6B L-
OxOO12FF6C c= d
0,00"'1'60 ~
OxOOl2FF6E
OxOOl2FF6F 2.1_
OxOOl2FF70
OxOOl2FF71 [
OxOOI2FF72
c=
OxOO12FF73
c::-=:-
OxOO12FF74
, " OxOOl2FF75
OxOOl2FF76
OxOOI2FF77
I
OxOOi2FF78
~ b
OxOOl2FF79
' ~ : " , . ~ / . /,- "
OxOOI2FF7A
OxOOJ2FF7B
Primer byte
OxOO12FF7C
libre de
OxOO 12FF7D ~
memoria
OxOOl2FF7E ~
;". OxOOI2FF7F
I
}
Los 3 bytes
quedan libres,
pues las variables
se alinean a un
mltiplo del
tamao de la
palabro del
sistema (32 bits)
Csar Liza Avila. Mis libros son econmicos, no hay razn para copwrlos.
174 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avila
Es decir la computadora almacena las variables primero en las posiciones
ms altas de la memoria, alinendolas al inicio del tamao de la palabra. En
nuestro caso la primera direccin de memoria libre fue Ox0012FF7F, pero
puede variar para usted, pues depender de la gestin de su sistema
operativo.
Si tenemos el nombre de la variable, podemos obtener fcilmente la
direccin de memoria en la cual se inicia. Para esto usamos el operador &
colocado delante de III variable. No debemos confundir con el AND a nivel
de Bits. Si declaramos la variable int a=50; podemos mostrar su direccin
de memoria de la siguiente manera: cout&aendl;
Al imprimir la direccin de una variable char, tal como b, nos sale la
direccin de memoria pero en decimal, por lo que tuvimos que imprimirla
en hexadecimal mediante hex.
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
I
Punteros 175
En muchas ocasiones necesitamos almacenar una direccin de memoria, es
por ello que surgen variables capaces de hacerlo. A este tipo de variables se
les conoce como punteros. .
Qu son punteros?
Son variables como cualquier otra. Pero NO almacenan un valor sino que
almacenan una Direccin de Memoria
p
Ox0012FF70
una variable comn
una variable puntero
Declaracin de punteros
Se declaran como cualquier variable pero se coloca un asterisco (*) antes
del nombre de la variable:
int *p; 11 p guardar una direccin de memoria, en dicha direccin habr un entero
double *r; 11 r guardar una direccin de memoria, en dicha direccin habr un doble
El tipo de dato nos dice que si vamos a la direccin de memoria
almacenada en la variable puntero, en esa zona encontraremos un valor del
tipo declarado.
El Operador Direccin: &
Ya dijimos que un & (ampersand) colocado delante de la variable, nos da la
direccin de la memoria de la variable. En la declaracin anterior, p y r son
variables (que almacenan direcciones de memoria), y por lo tanto tambin
ocupan memoria, cuya- direccin de inicio podemos obtener mediante &p y
&r.
Por ejemplo:
int *p, x;
cout&x;
cout&p;
1/ p es un puntero, x es un entero
II imprime la direccin de memoria la variable x
II imprime la direccin de memoria la variable p
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
176 Algoritmos y su Codifiracn en C+ +. Volumen 2.
Csar Liza A vila
Podemos hacer: p = &x;
puesto que &x es ua direccin de memoria y p es una variable capaz de
almacenar una direccin de memoria.
El Operador Indireccin: *
Nos da el contenido de la direccin de memoria almacenada en la variable
puntero.
Por ejemplo:
float x=5, *z;
z == &x
cout*z;
En la ltima lnea el * aplicado a una variable puntero z, significa "ve a la
direccin de memoria que almaceno y toma el valor que encuentres".
No confundir el * en las declaraciones de un puntero (como en float *z),
con el operador * en las instrucciones (obtn el contenido de, como en
cout*z), ni en las operaciones aritmticas donde * es el signo de
multiplicacin.
Como vemos, cada variable ocupa una direccin de memoria. Esto es cierto
para otros elementos, as las funciones tambin tienen una direccin de
inicio, los arreglos de igual manera, y cualquier tipo de dato definido por el
programador como las estructuras, y las enumeraciones. Asimismo, se
puede declarar una variable que almacena una direccin de memoria en
cuya celda hay otra direccin de memoria, o sea un puntero a un puntero.
Recuerde:
Todo puntero debe ser inicializado antes de ser utilizado, sino se tendr un
puntero que apunta a una direccin desconocida.
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Punteros j 77
Solucin:
Aunque las funciones puedan contener varios retum, no es posible para una
funcin devolver ms de un valor. Para que la funcin "devuelva" ms de
un valor se debe usar punteros.
dos formas de pasar parmetros a funciones. La primera es el paso de
parame.tros por valor, en donde el valor de la variable se coPia a la zona de
memOrIa aSIgnada a la funcin. Todo cambio que se haga en esta zona, solo
afectar a la funcin, y no ser conocida por maine ). La segunda forma, es
el paso por referencia, en donde a la funcin, se le enva la direccin de
memoria de las variables, de tal manera que la funcin pueda acceder a esa
zona de memoria y modificar su contenido, para esto se usan los punteros y
su operador & para obtener la direccin y * para obtener el contenido.
,que arreglo se pasa por referencia, es por ello que cuando
una funclOn modIfIca los datos del arreglo, main( ) conoce los cambios.
Podramos escribir el siguiente programa:
# include <iostream.h>
void swap(int, inO;
void main(void)
{ int a, b;
cout"Ingrese a: "; cina;
cout"Ingrese b: "; cinb;
swap(a, b);
couk<"a= " a endl;
cout"b== " b endI;
void swap( nt a, nt b )
{ int t;
t == a;
a == b;
b == t;
esperando que funcione correctamente, sin embargo, no se producir
ningn cambio. Veamos por que ocurre esto:
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
178 Algoritmos y su Codificacin en C++. Volumen 2, Csar Liza A vila
Cuando se enva parmetros por valor a una funcin, significa que se copia
el valor que actualmente tiene la variable, hacia otra zona de memoria
asignada a la funcin que se invoc.
b) 1 1 1 1 t 1 d
t = a
a =b
b = t
termina el cdigo de
la funcin y por lo
tanto la memoria
asignada a esta, se
libera, perdindose
los cambios locales.
]
maine )
maine )
maine )
swap( )
swap( )
swap( )
swap( )
,
a b t
'"
f'
20 20 llY

.","
?
Para que no se pierdan los cambios realizados, la funcin debe ser capaz de
modificar los datos en las direcciones de memoria que correspondan con las
variables de main( ). Esto solo se puede hacer cuando se realiza el paso de
parmetros por referencia, es decir mediante el uso de punteros.
Csar Liza Avila. No mates la producrin intelectual, no copies ste libro.
(
Punteros 179
Consideremos que en main( ), las variables a y b son de tipo int, mientras
que en swap( ), sus variables locales a y b son punteros a enteros int *, y
mostremos grficamente lo que debemos hacer:
Se invoca a la funcin
envindole las
direcciones de memoria
de las variables
swap(&a, &b)
maine ) swap( )
Una forma comn de representar las variables punteros locales de swap( ) a
y b, es usar una flecha, que significa "el a local de swap( ), apunta a la
direccin de memoria donde se ubica el a de main( )" y "el b local de
swap( ), apunta a la direccin de memoria donde se ubica b de main( )"
a-de swap( ), apunta a
a de main().
b de swap( ), apunta a
b de main().
t = *a
*a = *b
*b = t
maine ) swap( )
IQNi I $r--r-:--;r 1'-------'
maine )
swap( )
maine ) swap( )
1 1 1
------
maine )
swap( )
..
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
'1
....
180 Algoritmos y su Codificacin en C++, Volumen 2.
Se libera la memoria
asignada a swap( ), y
main( ) conoce los
cambios
main( )
Csar Liza Avila
swap() , .....
r[FrJ
De esta manera, los cambios, que hicimos en la funcin swap( ), sobre el
contenido de a y b, afectan a main().
El programa que hace esto, se muestra a continuacin:
@ Csar Liza A vi/a. No mates la preduccin intelectual, /lO copies ste libro.
Punteros 18J
Solucin:
Sea el punto (a, b) del sistema de coordenadas cartesianas.
y
b (.,b)
/'
P/
./
;Z
lA 1
V,U
a
x
las coordenadas polares estn dadas por un ngulo (9), y la distancia del
punto al origen (p).
Matemticamente:
8 = arctg(b/a)
p = ...JCa
2
+ b
2
)
. relaciones que usaremos en nuestro programa.
Como la funcin debe ser capaz de cambiar ms de un valor, entonces
debemos usargl pasQ por referencia/,es decir
La invocacin a LeeCartesianasC&x, &y), indica que se le enva las
direcciones de me1f1oria correspondientes a las variables a y b, que maine )
conoce, de tal manera que la funcin pueda realizar los cambios al
contenido de esas direcciones.
La invocacin aPolares(x, y, &a, &b), indica que x yy, se pasan por valor,
es decir los cambios que haga sobre estas variables la funcin aPolares( ),
no sern conocidas por maine ); mientras que a y b, se pasan por
referencia, es decir los cambios que haga la funcin aPoJares( ), sern
conocidos por maine ).
@ Csar Liza A vi/a. Mis libros son eronmicos, no hay razn para copiarlos.
182 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vi/a
La funcin LeeCartesianas( ), lee la abscisa y ordenada, ya travs de los
punteros, cambia los valores en la zona de memoria correspondiente a
main( ), de tal manera que cuando se libere la memoria asignada a
LeeCartesinas( ), los valores ledos, sean conocidos por main( ).
En aPolares( ), x y y no deben ser cambiados por la funcin,entonces se
pasan por valor, mientras que el ngulo y la distancia calculados en
aPolares{ ), se pasan por referencia, puesto que se debe modificar los
valores conocidos por main(). .
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Punteros 183
Solucin:
Existe una estrecha relacin entre punteros y arreglos, lo primero que
debemos recordar es que el nombre del arreglo indica la direccin de
memoria a partir del cual se almacenan sus elementos, y que estos se
almacenan en posiciones consecutivas de memoria. Es decir si hacemos:
int x[] = {lO, 20, 30};
cout x endl;
imprimiremos una direccin de memoria, osea x es un puntero, pero como
este valor es asignado por la computadora y, es el punto de entrada a un
conjuntwde elementos, no podemos cambiarlo a nuestro gusto, por ello se
dice que el nombre de una arreglo es un puntero constante.
Para mostrar el valor contenido en ese puntero usamos el operador
indireccin esto es cout*x, por lo que *x ser el valor del primer
elemento o sea 10
Si deseamos el segundo elemento, tendremos que sumar a la direccin x la
cantidad de bytes que ocupa el primer elemento. Esto lo hace
automticamente la computadora utilizl).ndo aritmtica de punteros, basta
con hacer *(x+l). As, la direccin de memoria del elemento x[i] ser (x+i),
mientras que el valor ser *(x+i).
Aritmtica de punteros
Suma
Al incrementar un puntero, se suma a la direccin almacenada, la cantidad
de bytes que tiene el tipo del puntero. Por ejemplo:
double x[] = {1O.1, 20.3, 5.7};
double *p = x;
cout p endl; /1 imprime la direccin de 1er elemento (equivale a imprimir x)
cout*p endl; II imprime 10.1 (equivale a usar 'x)
p++; /1 p=p+ 1; avanza al siguiente elemento tipo double (suma 8 bytes)
cout p endl; /1 imprime direccin del2do elemento (equivale a imprimir x + 1)
cout*p endl; /1 imprime 20.3 (equivale a imprimir '(x+ 1) )
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
184 Algoritmos y su Codificacin en e + + Volumen L Csar Liza Avila
El programa sabe cuntos bytes debe sumar a la variable puntero, pues
toma los bytes del tipo declarado p<1ra el puntero, en este caso dmib!e, le
sumar 8 bytes. No es posible sumar i,a cantidad de bytes que deseemos,
sino que el compilador suma la canti(i:ld de segn el tipo del puntero.
Por ejemplo, en: !11 :: P -1- 2;
suma 2*8 =16 bytes a p, pues p apunta <1 01,1
o sea apuntar al tercer elemento ppr lo que *p ser 5.7, (tambin pudimos
haber usado *(x+2) ).
La diferencia entre usar x y usar p, es que x, al ser el nombre de un arreglo,
es un puntero constante, es decir no podemos cambiar su valor, mientras
que p es un puntero, es decir pode1I
1
os cambiar su valor. Por ejemplo, no
podramos hacer x++, pero si p++.
Resta
Al decrementar un puntero, se resL) a la direccin almacenada, la cantidad
de bytes que tiene el tipo del puntero. Por ejemplo:
float x[] = {lO.lf, 20.3f, 5.7f};
fIoat *p = x+2;
cout p endl;
cout*p endl;

cout p endl;
cout*p endl;
// imprime direccin del ltimo elemento
11 imprime 5.7
II resta 4 bytL, apunta al elemento anterior
// imprime dimrcin del penltimo elemento
11 imprimA ;n J
El programa sabe cuntos bytes deh' restar a la variable puntero, pues toma
los bytes del tipo declarado para e, puntero, en este caso float, restar 4
bytes. No es posible restar una cantidad de bytes que deseemos, sino que el
compilador resta la cantidad de bytes segn el tipo del puntero.
Por ejemplo:
p = p - 2; II resta 2*4 =8 bytes a p, pues p apunta a un float
Recuerde tener cuidado en NO acceder a una zona de memoria que no
ha sido asignada a alguna de las variables del programa. Esto era posible
en Modo Real (DOS), pero no es posible en Modo Protegido (Windows).
@ Csar Liza A vila. No mates la I'mduccil1 intelectual, no copies ste libro.

Cmo se almacena un arreglo?
Si declaramos un arreglo y un entero:
int x[] = {65, 66, 67, 68};
int n=4;
Punteros 185
se almacenan en memoria tal como se muestra
Primer byte
libre de,
memoria

OxOO12FF6C
OxOO12FF6D
OxOO12FF6E
OxOO12FF6F
OxOO12FF70
OxOO12FF71
OxOO12FF72
OxOO12FF73
OxOOI2FF74
OxOO12FF75
OxOO12FF76
OxOO12FF77
OxOO12FF78
OxOO12FF79
OxOO12FF7A
OxOO12FF7B
OxOO12FF7C
OxOO12FF7D
OxOO12FF7E
OxOO12FF7F
La memoria se
asigna desde las
posiciones ms altas,
pero el primer
elemento del arreglo
se asigna desde la
ms baja
Aqu est el programa
pedido. Para cada
elemento del arreglo,
slo mostramos las

,
yoid'
rl1
a1?(Void): .' ..' .' '., ....
.{
.
direcciones de
memoria y sus
contenidos, as como la
direccin de n.
.\ edntehido"tldl'.'
"f,'{ ,t'::::(:i);';;,;''';\J ".",'. ' . ,", . .'
Ofv.tn J""J,J,)<: -rOl"., .,', '
'''"' " . ','

Csar Liza Avda. Mis libros son econmicos, no hay razn para copiarlos .
186 Algoritmos y su Codificacin en C++. Volumen 2.
y qu ocurre si declaramos n antes que x?
. int n=4;
int x[ ] = {65, 66, 67, 68};
Primer byte
libre de
memoria
>
OxOOl2FF6C
OxOOl2FF6D
OxOO12FF6E
. OxOOl2FF6F
OxOO12FF70
OxOOI 2FF7 1
OxOO12FF72
OxOO12FF73
OxOO12FF74
OxOO1 2FF75
OxOO12FF76
OxOO12FF77
OxOO12FF78
OxOO12FF79
OxOOI2FF7A
OxOO12FF7B
OxOO12FF7C
OxOO12FF7D
OxOO12FF7E
OxOOI2FF7F
Csar Liza A vila
o sea que si leemos x[4]
sobre escribiramos el
valor de n!
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Solucin:
El programa usa la
notacin puntero,
para indicar cada
elemento. Por lo
dems es similar al
mostrado en el
captulo sobre
arreglos de mi libro
"Algoritmos y su
Codificacin en
C++", Volumen 1.
Note que en la
funcin int *p, es
equivalente a escribir
int p[ ]. Ahora puede
entender porque,
cuando una funcin
hace cambios sobre
un arreglo, main ( )
conoce los cambios,
pues en realidad se
pasa un puntero en
IngresoDatos(n, x),
donde x es el nombre
del arreglo, es decir la
direccin de inicio del
arreglo. Recuerde que
todos los arreglos se
pasan por referencia.
Punteros 187
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
..,
188 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila

. Si ingresamos la palabra "lhloN", el carcter a buscar C:f!lJr "" H, Y el carcter
de reemplazo entonces podramos representar la memoria ocupada,
como:
memoria asignada a maine )
palabra I h I o 11 I a I NULL I
car [2J
memoria asignada a reemplazar( )
p
car [2J

El bucle while(*p ), recorre cada
letra hasta encontrar el terminador
NULL. Si la letra es igual a la
buscada (*p==car), se reemplaza
por otra (*p=c). En cada vuelta
siempre se avanza hacia la
siguiente direccin de memoria
(p++).
Csar Liza A vda. No mates la prodUCcin intelectual, no copies ste libro.

Para resolver este problema debemos
colocar dos punteros al inicio de la
cadena: char *r;
r=p;
LBJ E I e I 01 N I o I e E R I NULL 1

avanzamos uno de ellos.hasta que apunte
al ltimo elemento:
while (*r)
r++;
r--;
IRIElclolNlolclEIRINULO
rb
p
cJ,
Comparamos el contenido apuntado por
r y p, avanzando un elemento y mientras
p < r:
I R I E I e I o I N I o I e I E I R I NULL]

Punteros 189
en caso de encontrarse en el camino con contenidos de r y p diferentes
entonces retornar O. De haber terminado el bucle entonces ser
palndroma, retornando 1. Esto es lo que hacemos en el programa.
Note que el p de maine ) es constante y no puede cambiar pero el p de
EsPaJindroma ( ) es una variable puntero por 10 que podemos modificarla.
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
190 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila
Solucin:
Coloquemos un puntero a cada palabra:
p
J lo 11 I al NULL I
Imlu In Id lo I NULL I
q
rrf
A vanzamos hasta la primera posicin libre
de la primera palabra.
1m lulnldlolNuLLI
qm
a partir de la poslclOn actual de p,
empezamos a copiar cada letra apuntada
por q, (*p=*q), y avanzamos p y q una
posicin (p++, q++)
I h I o I 1 I a I mi u In I d I ~ I p
I m I u I n I d I 01 NULL I
q[iJ
Finalmente, colocamos el NULL, que toda cadena debe tener (*p=NULL).
Ih lo 11 la Imlu In Id lo I NULLt"W
p
Note que pal1[ ], debe tener el tamao suficiente para almacenar las dos
palabras.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
- - - - - - - - - - - - - - - - - - - - - ~ - - - ~ - - - - - ~
Solucin: _
Leemos un arreglo
x[ J, de n elementos
mediante
IngresoDatos( ). Cada
una de las
direcciones de
memoria de los
elementos de x[ J,
los asignamos a un
arreglo de punteros
(p[ D, mediante
lIenaArregloPunteros( ).
Los punteros
almacenados en p[
J sern los que
cambiaremos, para
que apunten a los
elementos de tal
manera que se
muestren
ordenados.
Punteros 191
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
192 Algoritmos y su Codificacin en C++. Volumen 2.
La funcin
), asigna
la direccin de memoria de
cada elemento del arreglo
(fjll+i), en cada elemento del
arreglo de punteros
(y[i]=p+i).
La funcin
IOrdenaDatosPunteros( ), usa el
mtodo de la burbuja y
compara los valores del
arreglo ( *pU-l] > *p[i] ),
pero hace el intercambio en
el arreglo de punteros. El
equivalente eliminando la
notacin de arreglos es:
if ( **(p+j-l**(p+j) )
{
temp == *(p+ j-l);
*(p+j-l)= *(p+j);
*(p+j) == temp;
puesto que p + j - 1 es la
direccin del elemento al
aplicarle un * obtendremos
un puntero, y al aplicarle el
segundo * obtenemos el
valor al cual apunta. Sin
embargo, en esta funcin,
hemos preferido dejarlo en
su notacin como arreglo,
para resaltar el hecho que
estamos trabajando con un
arreglo de punteros.
Csar Liza A vila
En ImprimeOrdenadoPunteros( ), tomamos cada elemento del arreglo de
punteros y mostramos su contenido, es decir mostramos el arreglo de datos
ordenados segn lo indicado en el arreglo de punteros.
Csar Liza A vi/a. No mates la produccin intelectual, no copies ste libro.
Solucin:
Este ejemplo, pretende
explicar el uso de punteros a
estructuras.
Recordar que cuando
tenemos una estructura como:
struct empleado emp;
codigo sueldo
emp I I
y queremos acceder a uno de
sus miembros usamos el
operador ., cada miembro
puede ser accedido mediante
emp.codigo y emp.sueldo
Pero si tenemos un puntero a
una estructura tal como:
struct empleado *q;
.
codigo sueldo
. I
y queremos acceder a uno de
los miembros de la estructura
al cual apunta, usamos el
operador o>, as sus miembros
sern q->codigo y q->sueldo.
Esto es lo que hacemos en el
programa, solo que el puntero
avanza t.omando cada elemento
del arreglo. Note que pudemos
usar p[iJ.codigo (p+i)->codigo
Punteros 193
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
194 Algoritmos y su Codificacin en C++. Volumen 2.
Solucin:
. Cuando definimos un arreglo, le
indicamos la mxima cantidad de
elementos que puede contener. Esta
. cantidad puede ser demasiado grande
para los datos que utilicemos trayendo
como consecuencia el desperdicio de
memoria, o lo que es peor, puede
quedamos demasiado corta, teniendo
que ir al cdigo "fuente modificarlo y
volverlo a compilar. A esta forma de
trabajar la memoria, se denomina
esttica, y el tipo de enlace con sus
elementos se denomina enlace esttico o
temprano (antes de compilar). Es por
ello que se ide un mecanismo que, en
tiempo de ejecucin, llamado tambin
enlace tardo o dinmico, el usuario
pueda decirnos cunta memada
requerir. Esta forma se llama asignacin
dinmica de memoria, y consiste en pedirle a
la computadora que nos de una zona de
memoria capaz de almacenar la variable
que le pidamos. Esta nos devolver un
puntero a la -zona de memoria asignada.
Para ello usamos el operador new,
mientras que para liberar la memoria
asignada usamos delete, tal como se
muestra en el programa.
Csar Liza A vila
La asignacin dinmica de memoria y los punteros a estructuras son usados
ampliamente cuando trabajamos con listas enlazadas. Este tema lo tratamos
en mi libro "Estructuras de Datos con C++".
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Solucin:
Las funciones tambin tienen una
direccin de inicio en memoria, y
por lo tanto podemos almacenar
esa direccin en un puntero. Al
igual que los arreglos el nombre
de la funcin nos da la direccin
de InICIO asignado por la
computadora, el cual no se puede
cambiar, por lo que no est
permitida la aritmtica de
punteros.
En el programa declaramos un
puntero a una funcin que recibe
dos argumentos enteros y que
devuelve un entero int (*ptr)(int,
int); es necesario escribir (*ptr),
puesto que, si eliminamos los
parntesis, diramos al compilador
que ptr es una funcin que
devuelve un puntero a un dato
tipo int, que no es lo deseado. La
direccin de inicio de la funcin
suma es asignada a ptr
(ptr=suma), luego leemos los
valores a operar e invocamos a la
Punteros 195
funcin, mediante el puntero ptr(x, y ). Como la funcin suma( ) retoma
valor hacemos s=ptr(x, y). De manera similar para la funcin resta( )
Invocamos a ptr(x, y), e imprimimos el resultadQ. '
El uso de punteros a es .un mecanismo muy potente, ya que podemos
tener arreglos de p.unteros a funcIOnes y hasta podemos usar funciones como
argument?s de funcIOnes. En los lenguajes ms recientes los punteros a funciones
se denomman delegados.
Csar Liza A vila. Mis libros son econmicos, no hay razn para
]96 Algorilnlo" \. su Cod(ficacin en C+ +. Volumen 2. Csw Li"a A vilo
oRucin:
Trabajar con punteros suele ser muy
delicado, puesto que podemos acceder
inadvertidamente a zonas de memoria y
cambiar sus datos, provocando la cada
del sistema. Es por este motivo que
pensando en una forma ms fcil de
trabajar con direcciones de memoria se
ide las referencias. No debe confundir la
referencia con el paso de parmetros por
referencia, que aunque son conceptos
relacionados directamente pues, para pasar
parmetros por referencia, se puede usar
un puntero o una referencia, las
referencias son una forma de ocultar el
trabajo con punteros.
Cuando definimos una referencia,
estamos dicindole a la computadora que
le de un nombre alternativo a la misma
zona de memoria asignada a otra variable.
Grficamente podramos representarlo as:
b
.-,-....,..,,.,...,...-_ ....._---_._._-_.-....

#fuclllde ..
v{Mswap(int &, iriti;); .'
vianlii)(Yoid)
int a=5;
nt &b=a;
La misma zona de memoria tiene 2
nombres a y b, si modificamos b,
estaremos modificando a, y viceversa
en este caso b es una referenci, y se declara anteponiendo el signo &
(ampersalld) delante de la variable. En realidad b es un puntero a la
direccin de memoria ocupada por a, pero con la ventaja que ocultamos la
complejidad eliminando los *. Las referencias fueron introducidas con el
C++. Los lenguajes de programacin ms recientes, dicen no usar punteros
pero si referencias, pero como ve, las referencias son "punteros
encubiertos" .
El programa que presentamos es el mismo que el ejemplo 6,1, pero usando
el operadOl' I"t'fercnda.
@ Csar Liz:u A vi/a, No mates la produccin intelectual, no copies sfe libro.
PUllteros 197
l. Escriba una funcin que acepte un puntero x de lal manera que rada
vez que se llame a la funcin duplique su valor. Llame a esa funcin
varias veces y muestre los valores de x.
2. Escriba una funcin de tipo void que reciba un entero positivo y
obtenga la suma de todos los nmeros hasta dicho entero. El resultado
deber imprimirlo desde maine ).
3. Escriba una funcin que debe ser invocada como mximo II veces y
cada vez que se invoque, sta debe mostrar cuntas veces le queda por
ejecutarse. La funcin debe restar el contador.
4. Escriba una funcin que lea los tres lados de un tringulo y, otra
funcin que determine qu tipo de tringulo es segn sus lados
(issceles, escaleno, equiltero). Las funciones deben ser invocadas
desde maine ), y el resultado impreso desde maill( ). Note que la
primera funcin necesita 3 punteros y la segunda ninguno.
5. Lea dos fracciones y calcule su su/na, el resultado debe ser mostradc'
como una fraccin simplificada. Use una funcin que lea el numerador
y denominador, luego una funcin que los sume y otra que simplifique
la fraccin. Las funciones deben ser invocadas desde mallO y el
resultado impreso en mallO.
6. Escriba una funcin que lea las horas, minutos y segundos, y otra que
le sume una cantidad de segundos. La nueva hora deber ser impresa
desde maill( ).
7. Escriba una funcin que lea los coeficientes (a, by c) de una ecuacin
de 2do grado (ax
2
+ bx + c)y otra funcin que "devuelva" sus races
reales. Las races deben ser impresas desde maine ). Considere que las
races podrn tener parte imaginaria.
8. Escriba una funcin que calcule la parte entera de cualquier nmero
real y tambin la parte decimal del mismo.
9. Escriba Ulla funcin que lea una fecha y otra que tome como
parmetros el da, mes y ao y obtenga la fecha del da siguiente. La
fecha debe imprimirla desde maillO.
10. Se tienen 3 valores a, b y e, cada vez que se invoca a la funcin, a fnma
el valor de c, b toma el valor de a, y e el de b. Escriba una funcin que
haga este trabajo, luego imprima desde maine ) los valores de a, b y c
Csar Liza Avila. Mis libros son econmicos. no hay razn para copiar/os.
198 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza Avi/a
cada vez que se invoque a la funcin. La funcin se invocar 3 veces.
Por ejemplo, si a, b y e son 1, 2 Y 3, en las tres llamadas debe imprimir
312, 231 Y 123.
11. En qu direccin de memoria se encuentra el menor elemento de un
arreglo y cul es el valor? Deber imprimir esta direccin y el valor
desde maine ). Sugerencia: Escriba una funcin que busque el menor
elemento y retorne un puntero. Ya en maine ), imprima el puntero y su
contenido.
12. Usando punteros, escriba una funcin que calcule la longitud de una
cadena. Muestre los resultados desde maine ).
13. Usando punteros, escriba su propia funcin que determine que cadena
es mayor. Muestre el resultado desde maine ).
14. Se tiene un arreglo con valores desde a hasta b. Se pide llenar en otro
arreglo las direcciones de memoria de los nmeros primos en el
intervalo dado. Luego mustrelos desde maine ).
15. Escriba una funcin para invertir los elementos de' una cadena.
Muestre la cadena final desde maine ).
16. Lea dos cadenas de caracteres e intercale sus caracteres, esto es la
cadena resultante tendr un carcter de la primera cadena, seguida de
un carcter de la segunda, a continuacin otro carcter de la primera,
seguida de otro carcter de la segunda, y as sucesivamente, hasta
terminar las cadenas. La cadena resultante deber imprimirse desde
maine ).
17. Escriba unafuncin que genere aleatoriamente un arreglo dinmico de
n elementos tipo char, con las letras del abecedario, y otra funcin que
mezcle sus elementos. Deber imprimir el resultado desde maine ). Use
punteros.
18. Se tiene un conjunto de datos, y se desea mezclarlos pero sin alterar el
arreglo original. Para esto, se crea un arreglo de punteros, los cuales
se mezclan. Escriba un programa que haga esto.
19. Cree un arreglo de caracteres de manera dinmica, luego usando
punteros y funciones lea n caracteres, imprima todos los caracteres, y
muestre sus direcciones de memoria.
20. Escriba un programa en el que maine ) invoque a una funcin que lea
la cantidad de filas y columnas de una matriz; luego, asigne memoria
dinmicamente para almacenar la matriz, invoque a una funcin que
lea los datos y finalmente, imprima las direcciones de memoria de
cada elemento de la matriz.
(f) Csar Liza Avila. No nw!es la produccin intelectual, no copies ste libro.
Archivos
i
l
J
An:hivos 201
Solucin:
Hasta el momento solo hemos almacenado datos en memoria, ya sea
cuando utilizbamos variables, arreglos o estructuras. Cada dato 10 leamos
desde el teclado o lo asignbamos dentro de nuestro programa. Sin
embargo, tambin podemos leer los datos desde un archivo, mejor an
hacer persistentes los datos y resultados de nuestros programas
almacenndolos en archivos. Existen diversos mtodos para manejar
archivos. Nosotros hablaremos solo de la forma estndar, y dentro de ellas
el acceso byte x byte y en bloques. No hablaremos de los objetos stream
para manejo de archivos, ni sus mtodos pues esto implicara una
explicacin adicional sobre programacin orientada a objetos, la cual
tratamos en otra obra. En su lugar utilizaremos las funciones estndar
provistas por el archivo de cabecera stdio.h, y eventualmente en io.h.
Qu es un flujo o corriente?
Son canales de comunicacin entre el archivo y el programa. El C/C++/C#
ve cada uno de los archivos simplemente corno un grupo de secuencia de
bytes sobre los cuales hay que abrir una corriente o flujo (stream). El flujo
de entrada estndar (stdin) permite que un programa lea datos desde el
teclado, el flujo de 'salida estndar (stdout) permite que un programa
imprima datos en la pantalla, rtentras que un flujo se relaciona con un
archivo utilizando una operacin de apertura fopen( ), y se desliga del
archivo con una operacin de cierre felose(). Todos los archivos terminan
con un marcador de fin de archivo, dado por la constante EOF o por la
funcin feof( ).
Formas de apertura de archivos
Podemos abrir archivos en dos diferentes formas:
Texto: Utiliza conversiones de algunos caracteres. Es decir, puede no haber
correspondencia entre lo que se enva al flujo y lo que se escribe o lee en el
archivo. Por ejemplo: el salto de lnea en archivo se representa por 2
caracteres: retorno de carro (ASCII 10) y salto de lnea (ASCII 13).
Csar Liza AvUa. Mis libros son econmicos, no hay rt.l,:Il para copiarlos.
202 Algoritmos y su Codificacin en C++. Valumen 2. Csar Liza A vila
Binario: Tiene una correspondencia directa entre lo que se enva y lo que
se escribe en el archivo, es decir los bytes que lees (o escribes) son
idnticos a los que estn almacenados en disco.
Sugerencia: Si usa un archivo .txt utilice el modo texto en caso contrario
use el modo binario.
feof( ) Devuelve verdadero si fin del if( !feof(pfich) )
archivo
Modo de Apertura de archivos
Un puntero a un dato tipo FILE, nos permite leer y escribir un flujo o
corriente (stream). Este tipo es una estructura definida en stdio.h.
Sintaxis: FILE * fopen(char *f, char *modo);
Ejemplo: FILE *pfich=fopen("c:\\a.txt", "w");
____ __
"w" "wt" : Abre para escritura modo texto. Si archivo no existe se crea.
, existe se crea de nuevo
.... .................._.' .. ' . . ........_ .........." , .. ............. ,-_ .........._ . '" .. . ...
"a
tl
Itat" ; .. ... ... .. .. ... ... .. ... existe se crea.
"rb" ..... .
"wb" Abre un archivo binario para escritura. Si el archivo no existe se
.1 ... . .........
"ab" : Se abre un archivo binario para escribir al final de l. Si el archivo
i no existe se crea.
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Nuestro programa hace
lo pedido. La funcin
crearArchivo( ), abre
una corriente ( fopen( )
) para grabar en modo
texto ("wt") y usa la
macro getchar( ),
definida en stdio.h, para
capturar el carcter
pulsado y mostrarlo por
pantalla, dicho carcter
es colocado hacia el
fichero ( putc(car,
fichero) ). Esto se repite
mientras este no sea el
final del ingreso
(while(car!=EOF)).
El terminador del
ingreso se puede
producir mediante el
teclado, presionando la
tecla F6, o en su defecto
con la combinacin de
teclas Ctrl + Z, seguida
por la tecla ENTER.
Finalmente, cerramos la corriente con fclose( ).
Contenido del archivo {
El ingn'sn termina
prcsinmllldo F{i
Archivos 203
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiarlos.
204 Algoritmos y su Codifiracin en C++. Volumen 2, .
Solucin:
. La funcin verArchivo( ), abre un
archivo para lectura en modo
texto ( fopen(arch, "rt") ), cuyo
camino y nombre se almacena en
arch. El flujo que nos dirige hacia
el contenido del archivo lo indica
el puntero de tipo FILE llamado
pfich. En caso de no encontrar el
archivo, sonar un pitido na'),
mostrar el
correspondiente y retornar a
maine ). En caso contrario, toma
cada carcter ( caracter=getc(pfich) )
y lo muestra en pantalla.
Algunas funciones y macros tales
como getc( ), devuelven -1,
cuando detectan el fin del archivo,
ya que la constante EOF que
indica el final de un archivo ha
sido definida en stdio.h como -1.
Esto lo utilizamos para termiriar la
lectura.
Finalmente, cerramos el camino
hacia los bytes del archivo con
fclose( ).
Csar Liza Avila
(J Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
Solucin:
En la funcin
copiaArchivo( ), abrimos el
archivo de origen en modo
de lectura en binario ("rb"),
pues deseamos una copia
idntica, sin que haya una
conversin de caracteres. El
archivo destino tendr que
ser abierto para escritura
("wb").
El bucle simplemente toma
cada byte de un archivo y
los enva hacia otro.
En vez de usar la constante
EOF, pudimos haber usado
la funcin feof( ), para
detectar el final del archivo,
tal como se
continuacin:
while( !feof(pfich 1) )
{
Finalmente
archivos
fcIose( ).
cerramos
abiertos
Archivos 205
Csar Liza A vila. Mis libros son econmicos, no hay razn para copiar/os,
206 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Uza A vila
Solucin:
@ Csar Liza Avila. No mate,', . produccin intelectual, no copies ste libro.
-
Luego de abrir el
archivo e indicar la
cantidad de bytes que
contendr cada uno de
los archivos finales, y
ya entrando al bucle,
debemos generar el
nombre del primer
archivo destino, que
tendr el mismo nombre
que el archivo origen,
pero agregndole la
extensin ".0", es por la
necesidad de las
instrucciones
itoa(nro, eNro, 10);
strepy(destino, origen);
streat( destino, ". ");
streat( destino, eN ro);
la funcin itoa( ), cuyo
prototipo se encuentra
en stdlib.h, toma el
primer argumento
entero y lo convierte en
una cadena que
almacenaremos en el
segundo argumento. El
tercer argumento indica
la base en la cual se
expresar el resultado.
Una vez generado el nombre del
archivo lo abrimos para grabar en
binario.
El bucle for( ), toma n caracteres del
archivo origen (car=getc(pf y si no se
llega al final de archivo ( if (feof(pt) ),
lo colocamos en el archivo de salida
actual ( putc(car, ps) ).
Archivos 207
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
I
208 Algoritmu,\ y su Codificacin en C++. Volumen 2.
Para unir los archivos
debemos ingresar el primer
archivo en que fue dividido
el archivo original, o sea el
de extensin "Jl". La
funcin Unir( ), abre
primero este archivo y copia
cada uno de sus bytes hacia
el archivo destino, luego
toma el archivo con
extensin ".1", copia sus
bytes, toma el archivo con
extensin ".2" y as
sucesivamente, hasta ya no
encontrar ms archivos
correlativos.
La creacin de los n o m b r e ~
correlativos, 10 hace las
instrucciones:
nro++;
itoa(nro, cNro, 10);
strcpy(origen,origenO);
strcat(origen, ".");
strcat(origen, cNro);
El bucle while(l),
muestra el archivo que esta
siendo procesado, tomando
cada uno de los bytes
(while(!feof(pf) ) y los
guarda en el archivo de
salida, luego intenta abrir el
siguiente archivo, si no lo
encuentra sale del bucle (if
(pf==NULL) break;)
Csar Liza Avila
Csar Liza A vila. No mates la produccin intelectual, no ('opies ste libro.
Archivos 209
Solucin:
En este programa usamos dos nuevas funciones: read( ) y write( ).
Funcin fl'cad:
Sintaxis: size_t fread(void puntero, size_t tamao, size_t nregistros, FILE fichero);
Trabaja con registros de longitud fija. Lee desde un fichero uno o varios
registros de la misma longitud ya partir de la posicin actual en el archivo.
El valor de retomo es el nmero de registros ledos, de tipo size_t que
est definida como tipo unsigned nt. Sus parmetros son:
Un puntero a la zona de memoria donde se almacenarn los datos
ledos
El tamao de cada registro
El nmero de registros a leer
Un puntero a la estructura FILE del fichero del que se har la lectura
Funcin fwritc
Sintaxis: size_t fwrite(void puntero, size_t tamao, size.J nregistros, FILE fichero);
Trabaja con registros de longitud constante y forma pareja con fread.
Escribe uno o varios registros de la' misma longitud hacia un fichero. El
valor de retomo es el nmero de registros escritos, de tipo size._t que est
definida como tipo unsigned int Sus parmetros son:
Un puntero a la zona de memoria donde se encuentran los datos
El tamao de-eada registro
El nmero de registros a grabar
Un puntero a la estructura FILE del fichero del que se grabar
Dentro de un archivo un conjunto de bytes pueden representar un registro.
Csar Liza A vi/a. Mis libros son econmicos, no hal' rm,n para copiarlos.
1
210 Algoritmos y su Codificacin en C++. Volumen 2.
El programa guarda los datos
en c:\datos.txt. En fopen( ),
son necesarios las 2 barras
invertidas \\, pues una barra,
indica un carcter de escape.
Luego, leemos n elementos de
tipo struct registro y los
guardamos en el archivo
c:\datos.txt, mediante fwrite(
), como el primer argumento
debe ser la direccin de
memoria donde se encuentran
los datos hacemos &reg. El
segundo argumento, es el
tamao en bytes que debemos
tomar a partir de esa direccin
de memoria; el tercer
argumento, indica cuntos
bloques de ese tamao vamos
a grabar y, el cuarto y ltimo
argumento, es el stream, al
cual dirigimos nuestros bytes.
Ahora procedemos a leer los
datos del archivo y mostrarlos
por pantalla. La funcin
fread( ), lee bloques de bytes
desde el stream indicado. El
primer argumento es la
direccin de memoria a partir
de la cual se llenarn los datos; el segundo, es el
tamao en bytes de cada bloque, en este caso es el
tamao del registro; el tercero, es el nmero de
bloques a leer, en este caso leemos de registro en
registro por lo que ser 1, Y el cuarto argumento, es
el stream desde donde vienen los datos.
En base a este programa, podemos escribir las funciones
para grabar y leer en disco, y combinarlas con las
funciones del Problema 3.5 para obtener una base de datos.
Csar [,iza A vi/a
Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Solucin:
La funcin verArchivoHexa(
), luego de abrir el archivo
para lectura en binario,
lee en bloques de 16 bytes
mediante fread( ), y
mientras no sea fin de
archivo. Esta funcin
toma 4 parmetros, el
primero, es la zona de
memoria en donde se
almacenar lo ledo; el
segundo indica el tamao
de cada elemento, el
tercero la cantidad de
elementos que sern
ledos; el cuarto y ltimo
argumento el stream
desde donde sern ledos
los datos.
La funcin fread( ),
intenta leer un bloque de
bytes de tamao conocido
(en este caso 16), y
devuelve la cantidad de
elementos
ledos.
realmente
Archivos 211
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
212 ALgoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vila
El primer bucle for, imprime cada byte ledo en 3 espacios y en
hexadecimal.
La expresin setw( 3*(16-bytesLeidos) + 2) permite dejar una
cantidad de espacios en blanco adecuada entre los cdigos ASCII impresos
en hexadecimal y sus respectivos smbolos. Esto es particularmente
necesario en el ltimo bloque ledo, puesto que los bytes tomados pueden
ser menores que 16, debiendo imprimir varios espacios en blanco' '.
El segundo bucle for, imprime los smbolos, para esto pregunta si
el cdigo ASCn del carcter es mayor que 31, en cuyo caso ser un
carcter imprimible procediendo a mostrarlo; mientras que, en caso
contrario, ser un carcter de control por lo que solo imprime un punto (.).
Finalmente, cerramos la corriente mediante fdose( ).
<r) Csar Liza A vila. No mates la produccin intelectual, no copies ste libro.
Archivos 213
Solucin:
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.
214 Algoritmos y su Codificacin en C+ +. Volumen 2.
La funcin comprimir(
), toma cada carcter y
lo compara con el
anterior (ir
(carAnt==carAct) ), en
caso de ser el mismo
'aumenta la cuenta de
caracteres iguales
(Iargo++), si esta
cantidad es ms que
255, lo grabamos
puesto el nmero
mximo que podemos
almacenar en un byte es
255. Si dos caracteres
consecutivos son
diferentes, y la cantidad
de veces que se repite
carAnt es mayor que 3,
entonces los guardarnos
codificados. Si no es
mayor que 3 (1 2) los
guardamos sin ningn
tipo de codificacin. Al
salir del bucle
while.(carAct!=EOF),
nos aseguramos grabar
los ltimos caracteres,
es por ello la repeticin
fuera de while del
bloque if else.
Finalmente, cerramos
todos los archivo
mediante fcIoseall( ).
Csar Li:a Avila
Csar Liza A vilo.. No mates la produccin intelectual, no copies ste libro.
Archivos 215
Si por ejemplo, tenemos el archivo a.txt en la unidad C:, cuyo contenido se
muestra con el Notepad. I
y ejecutamos el programa,
resultar
el cual en realidad ya no es un archivo de texto puesto que contendr
caracteres no imprimibles que no se presentan en los archivos de texto. As
que nos ayudamos de nuestro Visor Hexadecimal (Problema 7.5), para
uedara el archivo mido.
Por ejemplo, las repeticiones del carcter a, han sido codificados como OxO,
Ox8 y Ox61, donde O es el indicador de codificacin, 8 es la cantidad de
repeticiones, y Ox61 o sea 6*16+1 = 97 en decimal, es el cdigo ASCII del
carcter 'a', los 3 espacios en blanco Ox20 (32 en decimal) no se codifican,
pues codificados ocuparn tambin 3 bytes.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.
'1
216 Algoritmos y su Codificacin en C++. Volumen 2.
La funcin
descomprimir(), es
bastante simple, lee
un byte y pregunta si
es O, en caso de serlo
pregunta por el
siguiente byte, el cual
indica la cantidad de
veces que se repite el
carcter siguiente, y
luego lee el siguiente
byte que es el
carcter a repetir.
Mediante el bucle
for, graba el carcter
tantas veces corno se
indique.
En caso de no ser O,
entonces el carcter
se coloca
directamente en el
archivo destino.
Csar Liza Avila
Csar Liza Avda. No mates la produccin intelectual, no copies ste libro.

Archivos 217
Solucin:
Para mostrar los datos de un archivo guardados con algn formato
comercial, es necesario conocer dicho formato.
El Formato ZIP
Todo archivo .zip consta de 3 zonas bien definidas: La Data, el Directorio y
el Control.
La Data
En esta zona, se almacena cada uno de los comprimidos. Para cada
h' "1 1 d 1 bl arc IVO, eXIste una estructura SUTIl ar a a mostra a en a ta a sIgUIente:
Byte O 1 2 3 4567 8 9 10 11 12 13 14 15 16 17 18 192021 22232425262728 29 30 ... 1
Carac 80 75 03 04 ? ? ? ? M ? H H F F C C C C T T T T I I I I L ? ? ? NomArch Dalos
Compr
Bytes O al 3: Contienen los caracteres P (ASCII 80) Y K (ASCII 75),
seguidos por los ASCII 03 Y 04 que confirman el inicio de un archivo
comprimido.
Byte 8: indica el mtodo de compresin utilizado. Si contiene el ASCII O,
no se utiliz ningn mtodo, solo se almacen el archivo porque es muy
pequeo y no necesita compresin. El Winzip utiliza el ASCn 8, para
indicar su mtodo de compresin.
Bytes 10 y 11: Guarda el nmero que representa la hora de
almacenamiento del archivo original y como es costumbre en la familia PC
utilizan el almacenamiento inverso; es decir, el byte signado como 10, es el
menos significativo, mientras que el ms significativo es signado como 11.
De esta manera, el nmero que representa la hora ser: NroHora = (byte
11)*256 + (byte 10)
Adems sabemos, por lo descrito en el Capitulo 4 sobre manipulacin de
bits, que: NroHora = Horas*2048 + Minutos*32 + Segl2
Por lo tanto si conocemos NroHora, podemos obtener las horas como la
parte entera resultante de dividir NroHoras/2048. Esto lo conseguimos por
corrimiento de bits.(un corrimiento de un bit a la derecha es una divisin
Csar Liza Avda. Mis libros son econmicos, no hay razn para copiarlos.
218 Algoritmos y su Codificacin en C+ +. Volumen 2. Csar Liza A vila
entre 2), lo mismo es vlido para obtener los Minutos y los Segundos. En
lenguaje C/C++/C#, sera Horas:: NroHora]], pues 2048 es '.'2 <eHeva<Illo a
na 11" Minutos:::: NroHora&Ox07fl'>5, pues ahora slo nos mteresa los
nme;os menores o iguales a 2047 (07FFh, en hexadecimal) pero divididos
entre 32 o sea "2 elevado a la 5", Y finalmente Segundos == (NroHoras&
Ox001F)*2, ya que ahora solo nos interesa los nmeros menores o iguales
. que 31 (001Fh, en hexadecimal) pero multiplicados por 2.
Bytes 12 y 13: Almacenan el nmero que representa a la .fecha en la que se
cre el archivo, siempre en formato inverso, es decIr el menos
significativo es el nombrado como 12. De esta manera el numero que
representa la fecha ser: NroFecha == (byte 13)*256 + (byte 12) . .
Recordar( por el estudio sobre manipulacin de bits q.ue hIZO en el
Captulo 4, que los 2 bytes de NroFecha, con sus 16 bIts,
desde la derecha significan: los 5 primeros bits representan el dJa (0-32),
los 4 bits siguientes el mes (0-16), y los 7 bits restantes el ao (0-128). Para
toda la faulia IBM= PC, los aos se cuentan a partir de 1980, por lo cual
conociendo NroFecha podemos 9btener el da, mes y ao de la siguiente
forma:
Da = (NroFecha &Ox001F);
Mes = (NroFecha& Ox01EO) 5;
Ao = (NroFecha & OxFEOO) 9 + 1980;
Bytes 14, 15, 16 y 17: Estos bytes almacenan el o suma de
comprobacin (tambin llamado Cdigo de RedundanCIa Clcltca o
los cuales son una serie de bytes que se generan durante la compreslOn e
identifican al archivo en prevencin de alguna alteracin. Cuando .se intenta
descomprimir el archivo, se vuelve a calcular estos SI
diferentes de los almacenados, entonces el archivo compnmldo ha sufndo
alguna alteracin y no podr ser descomprimido.
Bytes 18, 19, 20 y 21: Guardan el tamao original del archiv.o .en
usando el almacenamiento inverso. De esta manera el tamao ongmal sera:
TamNormal = (Byte21)*256*256*256 + (Byte20)*256*256 + (Byte19)*256 + (Byte18)
o tambin: TamNormal = (Byte21)<<24 + (Byte20)16 + (Byte19)8 + (Byte18)
Bytes 22, 23, 24 y 25: Almacenan el tamao en bytes del archivo
compriudo en formato inverso, esto es:
TamComprim ,,;, (Byte25)*256*256*256 + (Byte24)*256*256 + (Byte23)*256 + (Byte22)
o tambin TamComprim = (Byte25)24 + (Byte24)16 + (Byte23)8 + (Byte22)
Csar Liza Avila. No mates la produccin intelectual. no copies ste libro.
.
-----l
Archivos 219
Byte 27: Almacena la longitud en bytes de la ruta yel nombre del archivo.
Byte 30 y siguientes: Guardan la ruta y el nombre del archivo.
Bytes despus del nombre del archivo: Inmediatamente despus del
nombre del archivo, se encuentra el contenido del archivo, pero
I
compriudo.
EL DIRECTORIO
Es una zona muy similar a la DATA, pero sin los datos comprimidos,
adems contienen algunos bytes adicionales.
Leyendo esta zona, podemos obtener rpidamente el listado de todos los
archivos comprimidos, lo cual es realizado por nuestro programa. Para cada
archivo comprimido, existe una estructura como la mostrada en la figura
si uiente, ubicados una a continuacin de otra.
El CONTROL
Bytes O a 3: Se inician con los caracteres P y K, seguidos por los ASCII 05
Y 06 que confirman el inicio del Control.
Bytes 8 y 9: Indican el nmero de archivos comprimidos contenidos en el
archivo ZIP, como siempre en almacenauento inverso.
Bytes 10 y 11: Contienen Una copia de los bytes 8 y 9. Esta redundancia se
coloca con fines de recuperacin.
Bytes 16, 17, 18 y 19: Contienen el byte de inicio del EL DIRECTORIO
del archivo comprimido, almacenado inversamente. El byte de inicio de EL
DIRECTORIO ser:
ByteInicio = (Byte 19)*256*256*256 + (Byte 18)*256*256+ (Byte 17)*256 + (Byte 16)
o tambin: ByteInicio = (Byte 19)24 + (Byte 18)16+ (Byte 17)8 + (Byte 16)
Este byte nos servir de punto de entrada a nuestro programa, pero antes de
mostrarlo, necesitamos conocer algunas nuevas funciones:
Csar Liza A vila. Mis libros son econmicos. no hay razn para copiarlos.
~ .
220 Algoritmos y su Codificacin en C++-. Volumen 2. Csar Liza A vila
Funcin fseek:
Sintaxis: int fseek(FILE *fichero, long in! desplazamiento, in! origen);
Ubica el cursor del fichero para leer o escribir en una posicin deseada.
Retoma cero si tuvo xito, y diferente de cero si hubo error.
Parmetros:
Puntero tipo FILE del fichero cuyo cursor de lectura/escritura
deseamos mover
el valor del desplazamiento
el punto desde el que se calcular el desplazamiento
El parmetro origen puede tener tres posibles valores:
SEEK_SET se desplaza desde el principio del fichero. El primer byte del
fichero tiene un desplazamiento cero.
SEEK_CUR el desplazamiento se cuenta desde la posicin actual del
cursor.
SEEK_END el desplazamiento se cuenta desde el final del fichero.
Funcin ften:
Sintaxis: long int ftell(FILE *fichero);
Nos da la posicin actual del cursor de lectura/escritura de un fichero
El valor de retomo ser la posicin actual, o -1 si hay algn error.
El parmetro de entrada es un puntero a una estructura FILE del fichero
cuya posicin deseemos.
El programa lo presentamos a continuacin, cada lnea est debidamente
comentada por lo que no necesita mayor explicacin.
Csar Liza Avila. No mates la produccin intelectual. no copies ste libro.
Archivos 221
Csar Liza A vi/a. Mis libros son econmicos, no hay razn para copiarlos.

222 Algoritmos y su Codificacin en C++. Volumen 2. Csar Liza A vi/a
c::t'''c:\fJO(uments: <11m '" -, '< .,,"]
Ingrese archIvo c:\z.zip El
MultMatrlces.exe 23/7/2005 2:5:26 192583 bytes 38089 bytes 94
MultMatrices. cpp 2317/2005 2: 9: 58 1493 bytes 531 bytes dc
a.txt 19/11/2005 2:57:4 18 bytes 18 bytes e55belde
Press any key to continue
Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.

Archivos 223
Solucin:
El ingreso y salida de bajo nivel, est provisto en io.h, y en direct.h,
algunas de sus funciones las mostramos aqu.
Csar Liza Avila. Mis libros son econmicos, 110 hav razn para copiarlos .
224 )' su Codifi,'acn f!n C++, Volumen 2,
('sar Uza A vila
El programa lee una carpeta, y nos cambiarnos a ella mediante
3hdr( ), para luego poder listar cada entrada de este directorio.
En Iist.aDir( ), definimos una variable del tipo struct _finddata,
definida en o.h, puesto que para cada archivo tenemos un conjunto de
'propiedades a los cuales podemos acceder.
La funcin _ndfirst( ), obtiene el primer archivo cuyo nombre
cumpla con el patrn indicado, en este caso "*. *", todos los archivos; y
coloca sus datos a partir de la direccin de memoria indicada por el
segundo argumento, en nuestro caso &archivo. Esta funcin devuelve un
entero largo, que servir como manejador o handle (nuestra variable listo),
para las futuras referencias.
Si listo, es diferente de cero, significa que encontr algn archivo
con el patrn indicado, procediendo a mostrar sus datos. Si es un directorio
(archivo.attrib ==_A_SUBDlR), se indicar como <DIR>, luego se procede a
buscar el siguiente archivo que cumpla con el mismo patrn de la primera
bsqueda, ahora indicada por listo, mostrando su nombre y hasta no
encontrar ms archivos.
Aqu, slo mostramos el contenido de un directorio especfico, pero
es posible recorrer todos los archivos del disco, incluyendo todos sus
subdirectorios, para ello necesitar usar recursin, terna que es tratado
extensamente en mi libro Estructura de Datos con C++.
Csar Liza Avila, No mates la produccin intelectual, no copies ste libro.
.
Archivo:; 225
1. Lea un carcter y muestre todas las posiciones dentro del archivo en
las que se encuentra.
2. Lea un archivo y guarde la suma de verificacin en otro archivo. La
suma de verificacin (cltecksum) es una serie de bytes que
al archivo, existen diversos algoritmos, lo ms fcil, aunque no muy
recomendable, es sumar los UNICODE de cada carcter del archivo.
3. Lea 2 archivos y nalos hacia un tercer archivo.
4. Dos archivos parecen ser iguales. Encuentre los bytes que son
diferentes indicando su ubicacin dentro del archivo.
5. Cuntas lneas y espacios en blanco aparecen en un archivo de texto
determinado?
6. Busque todas las ocurrencias de una palabra dentro de un archivo.
7. Se desea esconder un mensaje corto dentro de un archivo (esta tcnica
se conoce en general como esteallografa). Para ello se elige el
siguiente algoritmo: lea el mensaje y coloque cada una de sus letras en
las posiciones dadas por los nmeros primos, el resto de posiciones
sern dadas por el contenido del archivo original. Escriba una funcin
que haga esto y otra que muestre el mensaje oculto. Por ejemplo si el
mensajefue "hola mundo", en e/archivo se almacenara como:
8. Una forma de encriptamiento muy utilizado es sustituir cada carcter
por otro. El programador puede definir una tabla que contenga el
carcter original y otra tabla que contenga el carcter por el cual se
va a sustituir. Escriba un programa que permita encriptar y
desencriptar un ARCHIVO por SUSTITUCION con una tabla de
equivalencia definida por el programador.
9. Un virus es identificado mediante una cadena caracterstica extrada
de su cdigo. Un antivirus inspecciona los ficheros en busca de
cadenas asociadas a virus. Escriba un programa que lea una serie de
cdigos ASCII correspondientes al cdigo viral y los busque en un
archivo.
Csar Liza Avda. Mis libros son econmicos, no hay razn para copiarlos.
226 Algoritmos y su Codificaci6n en C++o Volumen 2. Csar Liza A vilo
10. Cuntos caracteres de cada tipo hay en un archivo dado?
Sugerencia: defina un arreglo de 256 elementos, el subndice indicar
el valor ASCII del carcterleido
11. Escriba un programa que dado un archivo diga que software lo cre.
Su programa debe identificar al menos 5 formatos. Sugerencia: Lea
los primeros bytes del archivo y busque algo que identifique a todo el
conjunto de archivos creados con el mismo programa. Por ejemplo, los
archivos creados con WinZip empiezan con PK, todos los ejecutables
empiezan con MZ, ya que al salir el DOS 2.0 Mark Zbikowski le puso
su siglas a los ejecutables.
12. Cree un archivo que contenga una cabecera que ocupe 15 bytes. La
cabecera est formada de la siguiente manera: los 3 primeros para las
iniciales de la empresa que creo el software, los 2 siguientes para las
iniciales del software, los 2 siguientes la versin del software, los 4
siguientes el ao, los 2 siguientes el mes y finalmente los 2 siguientes el
da de lanzamiento. Luego de los 15 bytes aparecen los datos
almacenados. Lea un archivo cualquiera y verifique si tiene el formato
definido, en cuyo caso muestre su cabecera.
13. Un archivo en formato DBF (F oxPro, Visual F oxPro, Dbase, F oxBase,
Clipper, etc.) tiene una cabecera de 32 bytes (O al 31) al inicio del
archivo, que indica lo siguiente: "
Bytes con subndice 7, 6, 5 y 4: cantidad de registros de la tabla
Bytes con subndices 9 y 8: byte a partir del cual se inician los datos
Bytes con subndices 11 y JO: longitud del registro, incluyendo la
marca del borrado.
Escriba un programa que lea un archivo DBF y muestre la cantidad de
registros, el byte de inicio de los datos, la longitud de cada registro.
Recuerde que los nmeros se almacenan en formato inverso, tal como
se vio en el Problema 7.8.
14. Es costumbre que cada sistema tenga un archivo de usuarios, cada uno
de los cuales tiene un password. Sin embargo, dicho password no se
guarda en disco, sino que en su lugar se almacena un valor hash, o
similar. Cree un archivo que contenga los ID de usuario y la firma del
password (un hash, checksum o un CCV). Luego lea login y el
password y diga si es un usuario registrado.
15. El formato WAV de Microsoft para almacenar sonidos, tiene una
cabecera de 44 bytes y contiene el tipo y organizacin de las muestras
de sonido.
@ Csar Liza Avila. No mates la produccin intelectual, no copies ste libro.
+
Archivos 227
Bytes O, 1,2,3 contiene la palabra "RIFF"
Bytes 4, 5, 6 7 tamao total del archivo en bytes menos 8 (esto es
porque no incluye los primeros 8 bytes)
Bytes 8, 9, JO, 11, 12, 13, 14 y 15 contiene la palabra "WAVEJ1nt "
note que hay un espacio despus de la t.
Bytes 16,17,18 y 19 Formato para PCM vale 16
Bytes 20, 21 Fonnato para PCM vale 1
Bytes 22 y 23, si es 1 es mono, 2 es estreo.
Bytes 24, 25, 26 y 27, frecuencia de muestreo puede valer 11025,
22050 44100.
Bytes 28, 29, 30 y 31 indica el nmero de bytes por segundo que se
debe intercambiar con la tarjeta de sonido para una grabacin o
reproduccin.
Bytes 32 y 33, nmero de bytes por captura 1, 2 4.
Bytes 34 y 35, nmero de bits por muestra, 8 16
Bytes 36, 37, 38 y 39 contiene la palabra "data"
Bytes 40,41,42 y 43, nmero total de bytes que ocupan las muestras.
Lea un archivo WA Vy muestre los datos de su cabecera
16. Escriba una funcin que grabe hacia un archivo los alumnos
aprobados y en otro los desaprobados (cdigo, apellido paterno,
apellido materno, promedio)
17. Escriba un programa que lea los datos de alumnos almacenados en un
archivo, los ordene alfabticamente (cdigo, apellido paterno, apellido
materno, promedio) y los guarde ordenados en otro archivo.
18. ~ e tiene un cdigo de libro char(5), un ttulo de libro char(30), y una
~ l s t a ~ ~ palabras clave char(70) que indican aquellas palabras que
Identifican al contenido de un libro. Cree un archivo con varios
registros y luego dada una palabra diga en que libros se encuentra.
19. Escri?a una funcin que elimine lgicamente un registro (cdigo,
apellldo paterno, apellido materno, estado J, de un archivo. Luego,
escriba una funcin que empaquete un archivo que almacena los
registros de n alumnos, Empaquetar significa crear un archivo con
todos aquellos alumnos que no han sido eliminados lgicamente.
Sugerencia: use el estado para indicar si esta o no eliminado.
20. Cree su propio formato que permita almacenar la definicin de la
estructura de registro (nombre del campo, tipo de dato, longitu.d, etc.),
luego lea n registros y gurdelos a un archivo usando suformato.
Csar Liza Avila. Mis libros son econmicos, no hay razn para copiarlos.

Acerca del Autor
Csar Liza Avila, es un reconocido Creador de Software, investigador
neto y difusor del conocimiento tcnico. Tiene doble forrnacin universitaria: Ing.
Industrial (UNT) e In9. de Computacin y Sistemas (UPAO), las cuales estudi
en forma simultnea, y sin convalidaciones, obteniendo en ambas meritorios
lugares. Debido a ello, es que combina los conocimientos adquiridos en ambas
carreras, en la mejora de la productividad de la organizacin mediante
herramientas automatizadas, trayendo como consecuencia la simplificacin de
procesos y el ahorro derivado de ellos.
Ha recibido varias distinciones, por haber ocupado los primeros puestos
en diversos concursos. As, obtuvo el 1er. Puesto en el examen de ingreso UNT,
en la Carrera Profesional de Ingeniera Industrial y el 3er. Puesto en el Cmputo
General entre ms de 17,000 postulantes" el 4to. Puesto en el examen de ingreso
Ing. de Computacin y Sistemas UPAO. Otras distinciones obtenidas son: 2do.
Puesto en el 11 DESAFIO DE BOLSA NIVEL REGIONAL, ("1990), 'ler. Puesto a
Nivel Regional del 11 DESAFIO NACIONAL DE BOLSA Y el 3er. Puesto a Nivel
Nacional en el mismo .concurso (1994). Adems en Octubre del 2001 recibi el
reconocimiento pblico del Colegio de Ingenieros del Per - Filial Trujillo, por su
destacada labor de investigacin y difusin del conocimiento tcnico.
Es un experto programador en C++, una muestra de ello son sus
programas publicados en la revista "Slo para Creadores", revista especializada
en difundir la creacin tcnica de software. En ella muestra la sencillez didctica de
su cdigo y su efectividad para realizar tareas que nos parecen tan misleriosas
como: reparar una Boa! Record, implementar esquemas de proteccin contra
copias, recuperar datos en discos duros que no tienen Boot, FAT o directorios,
visualizar archivos en diversos formatos como los ZIP, redefinicin de caracteres
en modo texto, entre algunos otros. Otros lenguajes en donde presenta gran
dominio son Assembler, FOXPRO, Pascal y Visual C#.
Es autor del .libro "El error del milenio", y de los programas 81082000
(escrito en eH), que verifica si una computadora es compatible con el ao 2000 y
SOL2000 (escrito en Assembler) que resuelve el problema de compatibilidad de
las computadoras respecto al ao 2000, y cuyos cdigos fuentes fueron incluidos
en el libro y publicados por la revista Soluciones del Diario Expreso, con el
objetivo de contribuir a un mejor conocimiento del problema y que la comunidad
informtica lo enfrente con xito. Este libro ha recibido elogiosos comentarios de
autoridades universitarias de Trujillo y de la Capital, mereciendo sendos artculos
en La Industria (Trujillo) , Diario Expreso (Lima), Diario OJO (Lima), entre otros .
L
Ha desarrollado sistemas de informacin en diversas instituciones tales
como: Escuela de Ingeniera Industrial y Sistemas-UNT, Carroceras Morillas,
Universidad Privada "Antenor Orrego", Municipalidad Distrital "El Porvenir",
Municipalidad Distrital Gran Chim - Cascas, Consorcio Pesquero Cal'Olina.
Asimismo, a realizado a sistemas de informacin en instituciones como
la Municipalidad Distrital "El Porvenir", e ITOS-SHELL No slo es un experto
en la construccin tcnica de sistemas de informacin, sino de software de
. propsito general como un utilitario para la verificacin la integridad de archivos
DBF (VERDBF.EXE) que es ms rpido y ms verstil que el FileFix de las
Utilidades Norton y el NPACK.EXE un software de compresin de datos utilizado
por el Sistema Compuleg de Editora Normas Legales, ambos programados en e
y Assembler.
Ha ocupado diversos cargos como Jefe de Sistemas del Convenio UNT-
MDP, responsable de Sistemas del Area Contable de la Universidad Privada
"Antenor Orrego", Director de Proyectos de Sistemas de Informacin en Mastersoft-
Per, Director de la revista Slo para Creadores. Se ha desempeado como
asistente de ctedra en los cursos de Software de Aplicacin I y Software de
Comunicacin en Universidad Privada "Antenor Orrego"; ha dictado los cursos
Lenguaje de Programacin y Manejadores de Base de Datos en la Unidad de
Tecnologa de la Informacin y de Sistemas UTISYS (Ex-Centro de Cmputo de
Ingeniera Industrial de la Universidad Nacional de Trujillo); asimismo, los cursos de
Anlisis y Diseo de Sistemas, y Lenguaje de Programacin 111, en el 1ST
ABACO-Trujillo; tambin, cursos como: Algoritmos, Tcnicas de
Programacin, Estructura de Datos Avanzados y Programacin Orientada a
Objetos en la Universidad Privada del Norte, entre muchos otros. Ha sido
expositor en ms de 30 eventos a nivel nacional destacando entre ellos el VII
CONEIS realizado en septiembre de 1999 en Cajamarca con el tema: Principios
d Construccin de Software y el Error del Milenio; y el '11m realizado
en agosto de 2000 en Trujillo, con el tema: Esquemas de Pro(eccn Contra
Copia. Tambin ha expuesto el Lenguaje Unificado de Modelado en diversas
ciudades como Trujillo, Chimbote, Chiclayo, entre otras.'
Actualmente, se dedica a la construccin de software a medida, a la
asesora en sistemas y a la difusin del conocimiento tcnico mediante artculos y
dictado de clases. Puede comunicarse con l a la siguiente direccin electrnica:
creadores@hotmail.com o visitar su pagina web: www.geoclties.com/cesaciz<l.
I
I
!
l
.... y SU CODIFICACION EN C++-.
Este libro nace con la idea de servir como texto introductorio a un curso de programacin.
Tiene caracterfsticas importantes dignas de resaltar que'lo diferencia de otros. Contiene
abundantes ejemplos divididos por temas en donde la complejidad va gradualmente en
aumento, con explicaciones detalladas de la
lgica utilizada, diagramas Nassi-Schneiderman
(N/S) y codificacin en C++. Sus 109 problemas
resueltos y 121 propuestos hace que esta obra
sea eminentemente prctica y por la manera
como est estructurado el libro podr detenerse
en cualquier momento, para reflexionar sobre lo
aprendido y tomar un merecido descanso con la
certeza que al retomar su lectura no habr
perdido la secuencia del. mismo.
Contenido:
1. La estructura secuencial
2. La estructura condicional simple
3. La estructura de seleccin mltiple
4. La estructura repetitiva mientras
5. La estructura repetitiva hacer mientras
6. La estructura repetitiva para
7. Arreglos unidimensionales
8, Funciones definidas por el usuario
ALGORITMOS Y SU CODIFICACION EN C++
Las Estructuras de Datos son un tema fundamental en la formacin de los estudiantes de
Ingeniera de Sistemas, Computacin e Informtica, y afines, pues nos dan un conocimiento
tcnico para elegir la mejor y ms eficiente forma de organizar nuestros datos para la solucin
de problemas de uso comn en prog;amacin. En
este libro encontrar ms de 85 ejemplos
completo:> 'de programas y ms de 140
ejercidos propuestos que sin duda, sern de
valiosa ayuda, tanto para los estudiantes como
de lo:; docenfes, y constituirn fuente inagotable
par3 la eld::eralJn d;; prctica:; y exmenes.
Toda:: aquella:> 'opc;ones de scftw3re .que usted
programador, siempre q!Jiso i:nplementar
son puestas a su alca,Ice y de manera en
estGcbra.
Conteaido:
1. Recursividad
2. Ordenamiento
3. Blsqueda
4. Listas Enlazadas
5. Pilas
6. Colas
7. Arboles Binarios de Bsqueda
Otras obras del Autor
MODELANDO CON UML. Principios '1 Apiicadcmes.
El Lenguaje Unificado de Modelado (UML) es un
lenguaje simblico para representar sistemas, Y es
de uso obligatorio a nivel mundial. Todos los
profesionales en Tecnologas de Informacin
utilizarlo Y dominarlo. Este libro le permltlra
aprender rpidamente los conceptos del y
sobre todo aplicarlos. A diferencia de otros libros
sobre el tema, aqu encontrar ms de 7ll ejemplos
desarrollados Y ms de 15 ejercicios propuestos que
le irn guiando en el aprendizaje del UMl.
Contenido:
1. Introduccin al UML
2. Diagramas de Casos de Uso
3. Diagramas de Clases
4. Diagramas de Secuencia
5. Diagramas de Colaboracin
6. Diagramas de Estado
7. DiagramasdeActividad
8. Diagramas de Componentes
9. Diagramas de Despliegue
EL ERROR DEL MILENIO
Este libro adems de contener una descripcin completa del Problema Informtico del Ao
2000, aporta con soluciones, incluyendo un diskette con 01 programa para verificar si su
computadora es compatible con el ao 2000, Y 02 programas para resolverlo, entregando el
CODIGO FUENTE de los programas. '
La gran cantidad de divertidas lustraciones Y el
lenguaje sencillo utilizado hacen amena su lectura,
siendo de sumo inters para cualquier persona que
est inmersa en el mundo moderno, pues es
imposible que no tome alguna accin respecto a
este problema, ya sea que tenga
en ;:;Iguna empresa o como un simple usuario.
Contenido;
1. Descripcin del Y21<.
2. Sistemas no informticos
3. Costos y aspectos jurdicos del Y2K
4. Queslamoshaciendo?
5. Problemas con el hardware
6. Problemas con el software
7. Tcnicas de solucin
8. Curiosidades del milenio.
Distribucin y Ventas
Ventas al por mayoH::
Sra. Serafina Pari de AqtH9nO
Av. Wilson # 1122. Telfono 4243986.
librera Nueva fErra
Jr. 195 (Frente a la UN!). Telfono 3813219. lima-Per.
Sra. Al'ltoi1lia Titl)
# 426 (Frente al Campo Ferial de Libros). Tlf. 4262280. lima-
CreaSoft
Av. Amrica Norte # 401. Telfono (044) 221363. Trujillo-Per.
Ventas al por menor:
A NIVEL NACIONAL:
UBUN
En sus tiendas de todo el Pen.
liMA:
Av. Wilson
En los puestos de venta libros de toda la Avenida
Puestos Frente a la UNI
En los puestos de venta de libros ubicados frente a la UNI
( .
TRUJILlO:
Librera El Retablo. Av. Espaa # 2116
Librera IDEAL (Stock). Jr. Orbegoso y'Francisco Pizarro #624.
CHIMBOTE: . .
Fer!a de Libros. Av. Pardo # 765y # 637. Telfono 327155
Ma!10lo. Av. Pardo # 673. 342991.
librerla UniVersitaria. Jr. Ellas Aguirre# 32B. Telfoilo 344713Z.
, CHICLAYO:
Feria de Libros. Elias Aguirre # 413
Librera Nuevo Mundo. .
Libreras de la Plazuela Elias Aguirre.
PIURA:
C&J Representacion:s. Centro Comercial Tres

Das könnte Ihnen auch gefallen