Вы находитесь на странице: 1из 527

, ,, =-;;II;".

==i
rr u7#'r.*if*rl ]
M." TeresL---v=,---{r: *- Lena Atonso
^

lsidoro Hernn Losada


Raquel Martnez Unanue
Francisco Javier Nava Garca
Juan Jos Pantrigo Fernndez
Maximitiano Paredes Vetasco
Antonio Sanz Montemayor

lntroduccin CT

a[a programaclon:
probtemas
resuettos
en Pascat


IIC

/\ firorial universitaria

H
E Ramn Areces
u Servicio
de
Publicaciones

-'
f::
U
Cu "
\--{ 3

M4 TERESI coNzLEZDE LENAALoNSo -Li'.li da


rsrDoRo uBnNN LoSADA I
RAeUEL uanrNez UNANUE
FRANCISCo JAVIER NAVA cARce
JUAN os pANTRTGo ppRNNpBz
MAXIMILIANO PAREDES VELASCO
ANTONIO SANZ MONTEMAYOR
Profesores de Lenguajes y Sistemas Informticos (URJC)

II.{TRODUCCTX A LA PROGRAMACIN:
PROBLEMAS RESUETTOS EN PASCAL

CANIPtiS l)l : \'lC'A l'Vi\lt( )


/f .:-].\
.
c i:. - V
,-*
il.
!, (t- r.

[tiiri ]ittl' ,-'A


n. 6\.lr'l
Pr'o':. L
l<- it. a" Jf/ 88
R.
E
E. t0oo
,,

s{*
universitaria
@airotial
-g Ramn Areces
Uil::."",
Indice

ndice de figuras xxi

ndice de tablas xxlu

Prlogo xxv

1 Conceptos de programacin 1
1.1 Computadora u ordenador 1

1.2 Problemas, algoritmos y programas 1

1.2.1 Problema I
1.2.2 Algoritmo 2
1.2.3 Problemas, algoritmos y programas 4
I .3 Lenguajes'y paradigmas de programacin 4
1.3.1 Lenguajes de programacin 1
1.3"2 Evolucin de los lenguajes de programacin . 6
1.3.3 Paradigmas de programacin . 8
1.1 Ingeniera del software 8

2 Elementos bsicos de Pascal l1


2.1 Historia y caractersticas de Pascal 11

2.2 Tipos de datos bsicos 12


2.2.1 Tipo entero (integer) IJ
2.2.2 Tipo real (real) 14
2.2.3 Tipo carcter (char) 15
2.2.4 Tipo booleano (boolean) . . . 11
2.3 Operadores relacionales o de comparacin . t8
2.4 Expresiones t9
2.4.1 Precedencia de operaciones l9
2.4.2 tipo ae dato de una expresin 19
2.5 Sobrecarga de operadores y lunciones t9
2.6 Conversin de tipos 20
2.6.\ Conversinimplcita 20

v1l
Nurcn
20
2.6.2 Conversin exPlcita
21
2.1 Elementos bsicos del lenguaje
21
2.1.1 Vocabulario
23
2.1 .2 Constantes Y variables
23
2.7 .3 Instrucciones bsicas: asignacin. escritura y lectura
26
2.1 .1 Estructura de un Programa
29
2.8 Cuestiones de tiPo test
29
2.8.1 Enunciados
30
2.8.2 Soluciones
32
2.9 Problemas
32
2.9.1 Expresiones
32
2.9.2 Tipo y valor .

32
2.9.3 Sintaxis
2.9.1 Escritura -1 -)

34
2.9.5 Lectura
34
2.9.6 Algoritmo radianes Y grados
31
2.9.1 Programa radianes Y grados
35
2.9.8 Segundos
35
2.9.9 Cilindro
35
2.9.10 Ecuacin de segundo grado
35
2.9.1 1 Hern de Aleiandra .

35
2.9.12. Carrera de caballos
36
2.9.13 TransPortes
36
2..9.11 A mayscultrs
36
7.t0 Soluciones
36
2.10.1 Expresiones
31
2.10.2 Tipo y valor .
31
2.10.3 Sintaxis
39
2.10.4 Escritura
39
2.10.5 Lectura
39
l. 10.6 ,\lgoritmo radianes Y grados
40
1.10.7 Programa radianes Y grados
.11
2.10.8 Segundos
12
1.10.9 Cilindro
_tl
1.10.10 Ecuacin de segundo grado
13
1 Hern de Alej andra
1 . 1 0. 1
44
1.10.12 Camera de caballos
47
1.10.13 Transportes
48
2.10.14 A maYsculas

L
Nnrcr ix

Instrucciones estructuradas 49
3.1 Instruccincompuesta Iu
3.2 Instrucciones de seleccin 19
3"3 Instrucciones de iteracin 52
3.4 Recomendaciones {1
3.5 Cuestiones de tipo test 55
3.5.1 Enunciados 55
3.5.2 Soluciones 51
3.6 Problemas 51
3.6.1 Nivel medio de ruido 51
3.6.2 Clculo del prstamo bancario 58
3.6.3 La calculadora 58
3.6.4 Esquema de recorido 58
3.6.5 Esquema de bsqueda 58
3.6.6 La hora cada diez minutos 58
3.6.7 El mximo comn divisor 59
3.6.8 El nmero perfecto 59
3.7 Soluciones 59
3.7.1 Nivel medio de ruido 59
3.7.2 Clculo del prstamo bancario 60
3.7 .3 La calculadora 61
3.1.4 Esquema de recorrido 62
3.7.5 E,squema de bsqueda 62
3.1.6 La hora cada diez minutos 63
3.7.7 El mximo comn divisor 64
3.7.8 El nmero perfecto 65

Subprogramas: procedimienos y f"unciones 67


4.1 Diseo descendente 67
1"2 Subprogramas 6B
4"2.1 Declaracin de subprogramas en el programa principal 69
4.2.2 Diseo de subprogramas ov
4.3 Frocedimientos y funciones . 1A
4.3.1 Deflnicin de una funcin y un procedimiento '7t
4"3.2 Llamada a una funcin o a un procedimiento 72
4.4 Parmetros 13
1.4.1 Parrnetros por valor 14
4.4.2 Parmetros por referencia o por variable 74
-'
+.5 Bioques 15
1.6 Tipos de identificadores 15
1.1 Vigencia o vida de un objeto 76
4.8 mbito o visibilidad de un objeto 76
Nrcn
76
1.9 Et'ectos laterales
16
-1.10 Cuestiones de tiPo test
16
4.10.1 Enunciados
80
1.10.2 Soluciones
82
4.1 1 Problertas
82
4. I l.lToro .

B3
4.11.2 Otro toro
83
4.1 I .3 Nuevo toro
83
4.1 1.4 Traza y comPrensin
84
4- I 1.5 Mtodo Cesar .
85
4.11.6 Emores
81
4.11.1 Nmeros romanos
8B
4.11 .8 Multiplicacin con Lpiz y papel
89
4.11.9 Palndromo
.+.1 1 .10 Nmero de la suerte
90
90
4.l 1.l 1 Calculaclora
91
4.ll.l2 Calculadora de comPlejos
91
4.1 1.l3 Primalidad
92
t 4.1 1 .14 Sucesiones
92
4.1 1.15 Trayectoria
93
4.1 1.16 Funcin seno aProximada
93
1.ll.ll Suma de nmeros Prlmos
93
4.r1.l8Pi
93
4.1 1.19 Capica
93
94
4.t2
94
4.12.1 Toro .

96
4.12.2 Otro toro
9B
4.12.3 Nuevo toro
101
4.12.4 Traza y comPrensin
103
4.12.5 Mtodo Cesar .
106
1.12.6 Errores
107
1.12.1 Nmeros romanos
111
-t. 12.8 Multiplicacin con lpiz y papel
113
1.12.9 Palndromo
4.12.10 Nmero de la suerte
tt4
4.t2.ll Calculadbra fi6'
TL7
4.12.t2 Calculadora de cornPlej os
126
4.12.13 Primalidafl
I2B
4.12.14 Sucesione
131
4.12.75 Trayectorib
IJJ
4.12.16 Funcin selro aProximada

f.
xrcr ri

4.l2.l1Suma de nmeros primos 136


4.r2.18Pi 138
4.12.19 Capica r39
4.12.20 Rotar l+0

Introduccin a Ia Recursin en PASCAI 143


5.1 Subprogramarecursivo 143
5.2 Recursin en PASCAL 143
5.3 Proceso de la llamada al subprograma recursi\,o 144
5.1 Estructura de un subprograma recursivo 146
5.5 Recursin infinita 146
5.6 Recursividadlineal 141
5.1 Recursividad linal t47
5.8 Recursin mltiple (o no lineal) t41
5.9 Transformacin de recursin a iteracin r48
5.10 Claridad versus eficiencia 153
5.11 Recomendaciones generales 154
5.12 Recursin mutua (indirecta) 154
5. l3 Cuestiones de test 155
5.13.1 Enunciados 155
5.13.2 Soluciones 156
5.14 Problemas t51
5.14.1 Camino entre dos puntos 151
5.14.2 Las tomes de Hanoi 157
5.14.3 Paridad de un nmero 1<7
5.14.4 Funciones recursivas 158
5.14.5 Funciones iterativas LSg
5.14.6 Calculo recursivo de los polinomios de Hermite isg
5.14.7 Caiculo recursivo de los vaiores de la funcin de Ackerman 159
5.14.8 CIculo recursivo de la potencia de un nmero 159
5.14.9 Invertir un nmero entero 159
5.14.10Nmero de dgitos de un entero isg
5.14.11 Lanecesidaddeuncasobasebiendelinido i5g
5.14.12 El algoritmo de Euclides recursivo 160
-5.14.13 Cambio de base 160
5 "14.14 Ctrculo recursivo de intereses bancarios I60
S.l4.lCaliejero !.... 160
5.14.16 De viaje por el desierto 16i
5.14.17 Mismas cifras . 161
5.15 Soluciones a los problemas t62
5.15.1 Camino entre dos puntos 162
5.15.2 Las torres de Hanoi t63
r xii Norcn
164
5.15.3 Paridad de un nmero
5.15.4 Funciones recursivas 165

5.15.5 Funcionesiterativa 165

5.15.6 Calculo recursivo de los polinomios de Hermite 170

5.15.7 Calculo recursivo de los valores de la funcin de Ackerman 17t)


5.1-5.8 Clculo recursivo c1e la potencia de un nmero 117
5. i5.9 Invertir un nmero entero
ll l
5.15.10Nmero de dgitos de un entero lll
5.15.1 1 La necesidad de un caso base bien definido t'72
172
5 . l5 . 12 El algoritmo de Euclides recursivo

5.15.13 Cambio de base 113


5.15.14 Clculo recursivo de intereses bancarios 113
5.15.15 Callejero 114
t'7 5
5.15.16 De viaje por el desierto
5.15.17 Mismas cifias . t76

Tipos simples y conjuntos 179


6.1 Defrnicin de tipo de datos t79
6.2 Tipo enumerado 181

6.3 Tipo subrango .


182
183
6.4 Tipo conjunto
6.5 Tipos annimos 186

6.6 Compatibilidad de tiPos .


186
187
6.1 Cuestiones de tiPo test
6.1 .l Enunciados t87
6.1 .2 Soluciones 190
6.8 Problemas 191

6.8.1 Conversin de formato de fecha 19t


6.8.2 El mejor transporte t9r
6.8.3 EI semforo t9r
6.8.4 LetrasmaYsculas t9l
6.8.5 Reparto de la baraja 192
6.8.6 Comparando dos Palabras 192
6.8.7 Estadsticas de una frase lg2n
6.8.8 El juego de piedra, papel o tijera . 192
6.9 Soluciones 192
6.9. i Conversin de formato de fecha r92
6.9.2 El rnejor transPorte 191
6.9.3 El semforo 196

6.9.-+ Letrasmaysculas 191

6.9.5 Reparto de la baraja 198

6.9.6 Comparando dos Palabras 20]1


NorcB riir

6.9.7 Estadsticas de una fiase l(,j


6.9.8 El juego de piedra, papel o tijera . l(r-i

Los tipos de dato array y string 207


1.1 Descripcin del tipo de dato array 201
7.l.l Defrnicin de tipos y declaracin de variables arrays 208
1 .1.2 Acceso a las componentes individuales de un amay 209
1 .2 Operaciones con arrays 209
1.2.1 Procesamiento de las componentes de un array 209
1.2.2 Arrays como parmetros de subprogramas . 2Il
"7.2.3 Arays parcialmente llenos 211
7.3 Descripcin del tipo de dato string 212
1.3.1 Definicin de tipos y declaracin de variables de tipo string . 212
1.3.2 Acceso a las componentes individuales de un string 213
1.4 Operaciones con strings 213
1.4.1 Strings como parmetros de subprogramas ... .213
1.4.2 Operaciones, funciones y procedimientos predefinidos para el
manejo de strings 214
1 .5 Cuestiones de tipo test 2t6
7 .5.1 Enunciados 2t6
7.5.2 Soluciones 2t8
1.6 Problemas 2t9
1.6.1 Acceso a los elementos de un array unidimensional 219
1.6.2 Recorrido de un aray unidimensional 2t9
1.6.3 Encontrar elementos en una coleccin unidimensional 219
1.6.4 Desplazar elementos en un vector 219
7.6.5 Separar elementos de un vector siguiendo un criterio 2t9
7.6.6 Acceso y recorrido de un array bidimensional . 2t9
7.6.1 Un cuadrado mgico 220
1.6.8 Encontrar elementos en una coleccin bidimensional 220
1.6.9 Una calculadora bsica de matrices 220
7.6.10 Dibujar un histograma 220
7.6.11 Encontrar y sustituir vocales en una frase 22t
1.6.12 Contando en frases 22t
7.6.13 Palndromos 221
7.6.14 Cdigo Morse 221
1.6.15 Simulando strings con arays 221
1.6.16 Frmula qumica 222
7 .6.17 El juego del ahorcado 223
7.6.18 Las cuatro en raya 223
1.6.19 Validacin de la lectura de datos numricos 223
1.1 Soluciones 223
r xiv xorcn

7.7.1 Acceso a los elementos de un array unidimensional 223

1.7.2 Recorriclo de un aray unitlimensional 224


1.1.3 Encontrar elementos en una coleccin unidimensional 225
7.1.4 Desplazar elementos en Lln vector 226
1.1.5 Separar elementos de un vector siguiendo un criterio 221
1.1.6 Acceso y recorrido de un amay bidimensional . 229
1 .7.1 Un cuadrado mgico 230
1.1.8 Encontrar elementos en una coleccin bidimensional 233
1 .1.9 Una calculadora bsica de matrices 234
1 .1.10 Dibujar un histograma
LJI

1.1.11 Encontrar y sustituir vocales en una frase 240


'7.1.12 Contando en frases 24t
a,l1
1 Palndromos
.'7.13
1.1.14 Cdigo Morse 243
1 .1 .15 Simulando strings con atrays . 244
1;1 .16 Frmula qumica 216
1;1.11 Eljuego del ahorcado . 248
7.1 .18 Las cuatro en raya 250
't.1 .19 Valiclacin de la lectura de datos numricos 254

Algoritmos de bsqueda y ordenacin 257

8.1 Algoritmos de bsqueda ?57


8.1.1 Bsqueda secuencial o lineal en colecciones no ordenadas 258
8.1.2 Bsque<la secuencial o lineal en colecciones ordenadas 259
8. i.3 Bsqueda binaria o dicotmica .
260
i
o
Algoritmos de ordenacin .
26t
8.2.1 Ordenacin por seieccin directa 262
8.2.2 Orcienacin por insercin directa 263
I

8.2.3 Ordenacin por intercambio directo 265


I
8.2.4 Mergesort 266
I

8.3 Cuestiones de iipo test 268


8.3.1 Enunciados 268
8.3.2 Soluciones .r' 270
8.4 Problemas 27r
8.4.1 Bsqueda secuencial en un array ordenado 27t
8.4.2 Bsquedabinaria 211
8.4.3 Representacin grfrca de una bsqueda binaria 212
8.4.4 Representaci1n grfrca del algoritmo de la burbuja 272
17)
8.4.5 Versin mejorada del algoritmo de la burbuj a'
8.4.6 Representacin gfica del algoritmo de seieccin directa 272
8.4.7 Representacin grfica del algoritmo de insercin directa 272
8.,+.8 Listn telefnico 273
urcB \\-

8.4.9 Representacin grtica del algoritmo mergesort lll


8.5 Soluciones l;.1
8.5.1 Bsqueda secuencial en un affay ordenado -,.1
8.5.2 Bsquedabinrria 271
8.5.3 Representacin grf,ca de una bsqueda binaria 17 1

8.5.4 Representacin grfica del algoritmo de la burbuja 217


8.5.5 Versin mejorada del algoritmo de la burbuja 278
8.5.6 Representacin grfica del algoritmo de seleccin directa 279
8.5.7 Representacin grfica del algoritmo de insercin directa 281
8.5.8 Listn telefnico 282
8.5.9 Representacin grfica del algoritmo mergesort 284

Registros 287
9.1 Descripcin del tipo registro 281
9.2 Operaciones 288
9.2.1 Acceso a los campos de un registro 288
9.2.2 Asignacin 289
9.3 Registros como parmetros 29o
9.4 La instruccin WITH 29t
9.5 Registrosvariantes 292
9.6 Arrays parcialmente llenos 293
9.7 Cuestiones de tipo test 293
9.7.1 Enunciados 293
9.1.2 Soluciones 295
9.8 Problemas 296
9.8.1 Declaracin de un tipo registro simple 296
9.8.2 Declaracin de un tipo registro con pafte variante 296
9.8.3 Visualizacin del contenido de un registro 297
9.8.4 Correccin de erores 297
9.8.5 Clases de aerobic 29',|
9.8.6 Mensajes en un telfono mvil 298
9.8.7 Evitando la recursividad 299
9.9 Soluciones 300
9.9.1 Declaracin de un tipo registro simpie 300
9.9.2 Deelaracin de un tipo registro con parte variante 300
9"9.3 V'isualizacin del contenido de un regisiro 301
9.9"4 Crrreccin de emores 307
9.9.5 Ciases de aerobic 309
9"9.6 Mensajes en iln teldfono mvii .1 I I

9.9"7 Evitando }a recursividad 326


I xvi

10 Ficheros
xorcn
331
10.1 Ficherooarchivo? . . . 331
10.2 Deflniciones . 332
10.3 Nombre lgico y nombre fsico de un fichero J 1/.
10.4 Tipos de ficheros en Pascal -r -1 -)

10.r1.1 Ficheros de texto 334


10.:1.2 Ficheros binarios 338
10.5 Ficheros como parmetros J+J
10.6 Control de errores de entrada./salida i++
10.7 Cuestiones de tipo test 345
10.7.1 Enunciados 345
10.1.2 Soluciones 341
10.8 Problemas 348
10.8.1 Copia de ficheros de texto 348
10.8.2 Sustitucin y recuento de vocales 348
10.8.3 Encontrar los ms jvenes 348
10.8.4 Visualizar fichero con imagen 348
10.8.5 Panicin de un fichero binario 349
10.8.6 Fusin de licheros binarios 350
10.8.7 Ordenacin de un fichero por mezcla directa 3s0
10.8.8 Ordenacin de un flchero por mezcla natural 351
10.8.9 Asistente para crear pginas web . 352
10.8.10 Bsqueda binaria o dicotmica en un fichero binario 354
1 0.8. 1 1 Rupturas de control 354
10.9 Soluciones . 355
10.9.1 Copia de ficheros de texto 355
10.9.2 Sustitucin y recuento de vocales 358
10.9.3 Encontrar 1os ms jvenes -tot,
lA.9 "4 Visualizar fichero co* imagen 362
10.9.5 Farticin de un fichero binario 365
10.9.6 Fusin do f,cheros binarios 369
10.9.7 Ordenacin de un fichero por mezcla directa 31t)
10.9.8 Ordenacin de un f,chero por mezcla natural 1t3
10.9.9 Asistente panacreur pginas web . 376
10.9.10 Bsqueda binaria o dicotmica en un fichero binario -) -)
10.9. 1 1 Rupturas de control JO

.393
Pnnteros y estructuras de datosdinmicas
11.1 Punteros . . i. 393
11.1.1 Manejo de memoria dinmica 395
11.1.2 Simulacin de paso por referencia 396
11.2 Estructuras de datos dinmicas 397
NnrcB xVrt

Il.2.l Listas enlazadas


-195
11.2.2 Pllas l()1
11.2.3 Colas +01
11.3 Cuestiones de tipo test
405
11.3.1 Enunciados 40s
11.3.2 Soluciones 411
I I.1 Problemas
1t4
Il.4.l Simulacin de tipo srring 414
11.4.2 Funcin contadora iterativa 4r4
11.4.3 Funcin contadora recursiva 414
| 1.4.4 Ordenacin ascendenre 4t4
1 L,+.5 Interseccin de listas 411
11.4.6 Unin de listas 4r5
1l .4.7 Sucursales de venta 415
11.4.8 Visualizacin inversa 415
11.4.9 Suma de polinomios 415
11.4.10 Sala de espera
4t6
I 1 .4.11 Cambio de sentido del rren
416
11.4.12 Almacn de arrculos
471
1I .4.13 Balance de parntesis .
418
11.5 Soluciones .
419
1 1.5.1 Simulacin de tipo string
419
11.5.2 Funcin contadora iterativa ,
421
t 1.5.3 Funcin contadora recursiva
423
11.5.4 Ordenacin ascendente ,t-tl
+L-\
11.5.5 Interseccin de listas +lft
11.5.6 Unin de listas 434
11.5.7 Sucursales de venta 431
1 1.5.8 Visualizacin inversa ,135
11.5.9 Suma de polinomios 441
1 1.5.10 Sala de espera
415
1 1.5. 1 1 Cambio de sentido del tren 449
ll.5.l2 Almacn de artculos AJL
1i .5.13 Balance de parntesis .
455

12 Unidades en T'urbo Pascal


459
12.1 Estructura 459
12.2 Creacin de una unidad 46A
12.3 Uso de una unidad 462
12.4 Cuestiones de tipo test 463
12.4.I Enunciados 463
12.4.2 Soluciones +b4
7
xViii Norcr
12'5 Problemas 464
12.5.1 Ejemplo de una unidad 464
12.5.2 Algoritmos de ordenacin 464
12.5.3 Suma de polinomios 165
12.5.4 Operaciones sobre un registro 165
12.5.5 Calculadora para nmeros complejos 465
12.5.6 Lista con registros 465
12.5.1 Ptla de datos 465
12.5.8 Guardar 1os datos de una cola en un fichero 465
12.6 Soluciones . 166
12.6.1 Ejemplo de una unidad 466
12.6.2 Algoritmos de ordenacin 480
12.6.3 Suma de polinomios 483
12.6.4 Operaciones sobre un registro 481
12.6.5 Calculadora para nmeros complejos 494
12.6.6 Lista con registros 491
12.6.1 Pila de datos 499
12.6.8 Guardar los datos de una cola en un fichero 501

13 Diseo formal de algoritmos 511


1 3. I Especificacin fbrmal con precondiciones y postcondiciones 51 1

13.2 Lgica de predicados 513


13.2.1 Leyes de equivalencia de predicados 514
13.2.2 Conceptos bsicos 515
13.3 Introduccin al diseo de algoritmos 518
13.3.1 Definiciones 518
13.4 Diseo de algoritmos iterativos 519
13.4.1 El sistema formal de Hoare 519
13.4.2 Derivacin formal de algoritmos iterativos 522
13.4.3 Verificacin fbrrnal de algoritmos iterativos 528
13.5 Verificacin formal de algoritmos recursivos 533
13.5.1 El principio de induccin sobre los nmeros naturales 533
13.5.2 Principio de induccin noetheriana 534
13.5.3 Lenguaje para algoritmos recursivos 535
13.5..1 Pasos para la veriflcacin formal de algoritmos recursivos 537
13.6 Cuestrones de tipo test 541
13'6 i Enuncia<los 541
13.5.2 Soluciones 550
j. " Probien1As 555
. 555
13.7.2 Clcu1o de rrecondiciones 555
l:1.7.3 Ordenacin de predicados 556

\.
unrcr xix

13.7.4 Formalizacin
-i-57
13.1.5 Especificacin tbrmal de funciones 5-i 8
13.1.6 Verif,cacin de un bucle s5B
13.1.1 Derivacin formal de un bucle 558
13.7.8 Suma de los trminos de una sucesin s59
13.1.9 Vector Alvanzado I 559
13.7.10 Nmero Perfecto -5-59
I
l3.7.11Horas trabajadas 559
13.1.12 Vector Cimitbrme 560
f3.1.13 Las Dobles Parejas -560
l3.l.l4Horastrabajadas2 ... 560
13.7.15 Dif'erencia entre nmero de valores positivos y negativos de un
vector 56t
13.7.16 Suma de los divisores estrictos de un nmero 561
13.7.11 Vector Alvarizado 2 .. 561
13.8 Soluciones a los problemas
562
13.8.1 Enunciados lgicos 562
13.8.2 Clculo de precondiciones 562
13.8.3 Ordenacin de predicados 564
13.8.4 Formalizacin 564
13.8.5 Especificacin formal de funciones 565
13.8.6 Verificacin de la invarianza de un bucle 568
13.8.7 Derivacin fbrmal de un bucle 569
13.8.8 Suma de los trminos de una sucesin 570
13.8.9 Vector Alvarizado 1 5tt
13.8. 10 Nmero Perfecro 574
13.8.1 1 Horas trabajadas 1.. . 578
13.8. 12 Vector Cimiforme 581
13.8.13 Las Dobles Parejas 583
13.8.14Horas trabajadas 2 .
. . 585
13.8.15 Diferencia entre nmero de varores positivos y negativos de un
vector 586
i3.8.16 Suma de los divisores estrictos de un nmero 5gg
l3.B.lTVectorAlvarizado2 .. .590

Bibliografa 594

Anexo I Norrnas de estilo 597


Indice de figuras

1.1 Modelo de computadora 2


1.2 Paradigmas y lenguajes de programacin 9

2.1 Los 127 primeros caracteres de la tabla ASCII t6

3.1 Instrucciones compuestas anidadas. 50

4.1 Estructura sintctica de un programa y de los subprogramas en pascal 7l


4.2 Semntica de la llamada a un procedimiento 13

6.1 Tipos de datos en Pascal. 180

1.1 Ejemplos de objetos que se pueden modelar con arays: (a) tablero de
ajedrez, (b) vector en el espacio 208
1.2 Acceso a los elementos de un array: (a) bidimensional de dimensiones
MxN, (b) unidimensional 2Og
7.3 Array parcialmente lleno 2ll
7 .4 El juego de "las cuatro en raya" 222

8.1 Bsqueda en coleccin no ordenada 258


8.2 Bsqueda en coleccin ordenada de un elemento que no pertenece a la
coleccin 259
8.3 Bsqueda binaria 26l
8.4 Ordenacin por seleccin directa 262
8.5 Ordenacin por insercin directa 264
8.6 Ordenacin por intercambio directo 265
8.7 Ordenacin con el algoritmo mergesort Z6j

9.1 Evitando la Recursividad 2gg

11.1 Puntero que contiene la direccin de memoria ficticia 215 corespon-


diente a una variable entera con valor 2 . . . 395

xxi
xxli xotcp DE FTGURAS

l1 .2 La asignacin de un puntero a otro no duplica la informacin. ambos


punteros quedan apuntados al mismo dato 398
11.3 Lista c1e nodos. implementada como registro con campo informacin y
enlace a1 nodo siguiente 398
1 1.4 Ejemplo de pila, el nico elemento accesible es el que hace de cima
401
I t.5 Cola como particularizacin de una lista enlazada simple donde la inser-
cin es por el frnal de la estructura y la extraccin por cabecera 402
1 1.6 Cola como registro con punteros cabecera y final para facilitar la
inser-
cin y la extraccin de elementos 403
11.7 Cola cloblemente enlazada como registro con punteros cabecera y flnal
para facilitar la insercin y la extraccin de elementos 404

t,
l

t
Indice de tablas

2.1 Operadores sobre nmeros enteros 13


2.2 Funciones sobre nmeros enteros 14
2.3 Operadores sobre nmeros reales 14
2.4 Funciones predeflnidas sobre nmeros reales
15
2.5 Funciones predefinidas sobre caracteres
15
2.6 Operadores sobre valores booleanos
I7
2.1 Tabla de la verdad de los operadores (T=TRIIE, F=FALSE) . 17
2.8 Funciones sobre booleanos
11
2.9 Operadores relacionales
18
2.10 Precedencia de operadores 19
2.tt Funciones para conversiones explcitas 20
2.r2 Lectura 34
2.13 Lectura
40

1.1 Toro 82
4.2 Trazay comprensin B5
4.3 Mtodo Cesar 85
4.4 Problema sobre errores 87
4.5 Equivalencia de nmeros romanos 88
4.6 Trazay comprensin 103
4.1 Problema sobre errores 106

5.1 Ilustracin del clculo del factorial de 4 145

6.1 operaciones que se pueden realizar con conjuntos (conjA=[rojo, verde,


azull, conjB=[rojo, azul] y e=rojo). 185
6.2 Precedencia entre los operadores (el nivel ms precedenie es ei 4). 186

1.1 Funciones predefinidas para cadenas de caracteres 214


7.2 Frocedimientos predefinidos para cadenas de ca::acteres 215

xx1ll
Prlogo

Nos es grato presentar esta obra, que nace con el nimo de complementar los conteni-
dos tericos expuestos en el aula en las asignlturas universitarias de introduccin a la
programacin.
El texto est dirigido fundamentalmente a alumnos. pero tambin a prof-esores. de
asignaturas relacionadas con la introduccin a la programacin estructurada y modular
que utilizan el lenguaje Pascal. La motivacin inicial fue 1a de apoyar las asignaturas de
programacin de los primeros cursos de las ingenieras informticas de la Universidad
Rey Juan Carlos, donde los autores imparten docencia. Sin embargo, gran parte de los
contenidos expuestos son comunes a las asignaturas de introduccin a la programacin
de otras titulaciones cientfico-tcnicas.
E,stas asignaturas poseen un carcter marcadamente prctico, de fbrma que el alumno
no slo debe limitarse a coleccionar en su memoria una serie de conceptos tericos, sino
tambin aplicarlos a la resolucin de problemas. Es decir. no es suficiente con conocer
v comprender los aspectos metodolgicos, lbrmales y de diseo de la programacin
estructurada. sino que adems, es absolutamente necesario saber cmo aplicarlos a casos
prcticos. S1o en ese momento cobran sentido y utilidad las hemamientas conceptuales
aprendidas.
Los autores son profesores del rea de Lenguajes y Sistemas Infbrmticos del De-
partamento de Infbrmtica, Estadstica y Telemtica de la Universidad Rey Juan Carlos
de Madrid. Todos ellos tienen experiencia docente en las asignaturas de pro-eramacirn
de los primeros cllrsos de dicha universidad. En concreto, en Metodologa y Tecnolo-ea
de la Programacin de la titulacin de Ingeniera Tcnica en Infbrmtica de Sistemas e
Ingeniera Tcnica en Informtica de Gestin, y en las asignaturas de lntroduccin a la
Programacin, Estructuras de Datos y Metodologa de la Programacin de la titulacin
de lngeniero en Infbrmtica. Las cuestiones y ejercicios planteados en este texto estn
ertrados. en su mayora, de los ejercicios, prcticas y exmenes propuestos en dichas
titulaciones.
Los contenidos estn dedicados fundamentalmente a afianzrr los contenidos tecno-
1gicos de la introduccin a la programacin. Sin embargo, los autores han considerado
necesario complementarlos con la inclusin de algunas cuestiones metodolgicas. como
1a especificacin, derivacin y verificacin fbrmal de algoritmos. El libro se organiza
por captulos, y cacla uno de ellos se dedica a un concepto relevante de la programacin
xxvi Pnloco

estructurada. En cada captulo, se han organizado los contenidos en tres secciones bien
dif-erenciadas: teoro, cuestiones tle test y troblemeu.
En la seccin de teora se exponen muy brevemente y a modo de recordatorio los
principales conceptos metodolgicos y tcnicos necesarios para abordar los problemas
del tema. acompaados de algunos ejemplos. Es necesario aclarar aqu, que este texto
no tiene vocacin de libro autosuficiente para el aprendizaje de la programacin, silto
que su objetivo es servir de complemento prctico.
Las cuestiones de tipo tsl tienen como objetivo qLle el alumno compruebe y valore
sus conocimientos tericos. no slo en un nivei puramente memorstico, sino haciendo
especial hincapi en las dificultades relacionadas con la comprensin de los conceptos.
Un uso adecuado delas cuesticnes de tipo test ayudarir al lector a detectar sus carencias
en cuanto a 1o que sabe c no sabe, pero tambin en cuanto a 1o que entiende y no entiende.
La seccin de probLemas constituye la parte ms extensa de cada captulo. Est de-
dicada a la propuesta, resolucin y discusin de una amplia coleccin de problemas. Un
uso adecuado del material presentado en esta seccin est supeditada a la participacin
activa del lector. En este sentido, para el coffecto aprovechamiento del libro, es necesa-
rio que, en primer lugar, el lector se esfuerce en resoiver los problemas que se proponen.
El uso de las soluciones propuestas slo tiene sentido una vez que el alumno ha detec-
taclo carencias en sus eonocimientos o para cotejar o comparar sus soluciones con las
propuestas.
El lenguaje Pascal ha sido. y sigue siendo, uno de los lenguajes de alto nivel preferido
por muchos prof-esores de introduccin a la programacin. Fue creado por Niklous Wirth
(1934-). Coino lenguaje de programacin imperativa, cubre todos sus aspectos funda-
mentales de una manera sencilla y limpia. Tiene un sistema rgido de comprobacin de
tipos, una entrada/salida simple, una sintaxis reducida y condiciona al programador a
organizar el cdigo. A su vez, permite la declaracin de tipos definidos por el usuario y
el uso de punteros. En versiones extendidas se aaden conceptos abstractos tales como
unidades o mdulos precompilados y soporte para programacin orientada a objetos.
Desde su concepcin, Pascal es un lenguaje pensado para la enseanza de la pro-
gramacin estructurada, y como tal, para este libro se ha hecho uso de 1. Los autores
de este libro son conscientes de que el lenguaje Pascai ha sido criticado duramente. La
ms famosa crtica corri a cargo del coautor del lenguaje C. Brian W. Kemighan, en
su artculo "Wl' Pttscal Is Nrt My Favourite Programming Lunguage" (1981). Sin em-
bargo. estos ataques no estaban dirigidos a la adecuacin de Pascal como lenguaje para
ensear a pro-qramar. De hecho. la mayora de las quejas formuladas se basaban en las
limittcione-s cosmticas de Pascal. como las restricciones sobre ia codifrcacin de los
progr-antas. pero qlle necesarialnente obligan al programador novel a concentrarse en los
algoritmos.
En dehnitit'a. presentamos este texto con la esperanza y el deseo sincero de que sea
til a nriestros alumnos y a todos aquellos que se acerquen a 1.
[,o.s autrres
Captulo 1

Conceptos de programacin

Para aprender a programar es necesario tener claros ciertos conceptos generales y espe-
cficos de todo 1o que envuelve el proceso de la programacin. En este captulo se trata
de dar una visin general de la programacin y alavez exponer los conceptos clave para
la resolucin de problen-ras por medio de 1a computadora u ordenador.

1.1 Computadora u ordenador


Una computadora se puede ver como un sistema, en el que se introducen unos datos
(datos de entrada), el sistema los procesa, operando cin ellos y a veces transformndolos,
y devuelve el resultado de ese procesamiento (datos de salida). La figura 1.1 muestra
grficamente una cornputadora elemental. De esta definicin infbrmal se puede deducir
un modelo computacional y describirlo dando los datos de entrada que admite y las
operaciones bsicas que va a poder efectuar con dichos datos.
La programacin consiste en escribir 1o que debe hacer la computadora para resoiveL
un problema concreto utilizando un lenguaje de programacin.

1.2 Problemas, algoritmos y programas


En este apartado se introducen algunos conceptos bsicos sobre los elementos que invo-
Iueru la programucin.

1.2.1 Problema
Un problema es una proposicin encaminada a averiguar el modo de obtener un resul-
tado. cuando se conocen ciertos datos de partida.
Los problemas se pueden dividir en tres tipos, dependiendo de las soluciones que
lenBa. que son:
7

CoNcnptos DE PRocR.u,cr,

!t1rgrilil

tr{E},I-;}ll-{

flnf r,ir ile *trtlil,.l;'r I.i;,rtrrs rle slir l:r

FI{ i. ii.'E -,r,,Iir, r}1,

Figura 1.1: Modelo de comPutadora

Sin solucin o irresolubles: esos problemas no pueden ser solucionados con los me-
dios disponibles. Por ejemplo, el clsico problema de la cuadratura del crculo:
"Daclo un crculo. construir un cuadrado de igual rea que el crculo utilizando
solamente regla y comps" (la mencionada regla es no graduada y solo sirve para
trazar rectas ).

Determinados: los problemas tienen solucin y adems es nica. Por ejemplo, encon-
trar un nmero natural x que resuelva la ecuacin 2x=4.
Indeterminados: estos poseen un nmero indelinido de soluciones. Por ejemplo, hallar
dos nmeros enteros x. y que cumplen el siguiente sistema de ecuaciones: 2x-y=l;
iLv-)v=
,,-.J -)'

Para 1a correcta resolucin de un problema se cleben seguir los pasos siguientes:

l. Antisis del problenta; consiste en establecer con precisin qu se plantea.

2. Especi.ficcrt.irirt del problema: consiste en dar una descripcin precisa del problema
con los datos cle partida y el resultado. Esta descripcin se puede hacer con len-
guaje natural. que con frecuencia es ambiguo, o con lenguajes fbrmales, como las
mate 1nticas o 1a lgica.

1.2.2 Algoritmo
Eristert varias definiciones para el concepto de algoritmo. Entre ellas destacan:

Definicin 1: descripcin precisa de los pasos que nos llevan a la solucin de un pro-
ble na planteado.
Pnonr,Bnrls, ALGoRITMoS y pRoGRAMAS

Definicin 2: rntodo tal, que partiendo de los datos apropiados, conduce sistemti.r-
mente a los resultados requeridos en la especificacin del problema.

La defrnicin de un algoritmo describe:

o 1os datos de entrada.

o el proceso y operaciones que se pueden rcalizar y


o el resultado o datos de salida.

Propiedades de los algoritmos

Deben especificar sin ambigedad:

El orden de los prsos u operaciones que han de llevarse a cabo.


o Qu se realiza en cada paso.
Los algoritmos deben ser deterministas, o 1o que es lo mismo, deben responder de
i-eual rnodo ante las mismas condiciones y los mismos datos. Adems Ia secuencia de
pasos que se especifica debe ser finita , debe poder realizarse en tiempo finito.
Ejemplos de algoritmos son las instrucciones para ir de una ciudad a otra por carre-
tera, cmo montar un mueble que viene en kit o una receta de cocina.

Lenguajes algortmicos

Sirven para describir un algoritmo. Son ms precisos que el lenguaje natural, pero me-
nos rgidos (o fbrmales) que un lenguaje de programacin. Se les considera lengua-
.jes intermedios y tienen cierta independencia de los lenguajes de programacin y del
computador donde se escribir el programa. Ejemplos de lenguajes algortmicos son e1
pseudocdigo. los organigramas y los diagramas de Nassi-Schneiderman (N-S) tambin
conocidos por diagramas de Chapin. Estos dos ltimos son representaciones grficas de
n algoritmo.
El tseudocridigo es una variacin del lenguaje natural en el que se han elirninado
1us posibles ambigedades mediante el uso de un vocabulario restringido y unas reglas
;intcticas de construccin de sentencias. Este ser el recurso utilizado para verificar y
derivar programas en el captulo 13.

.\spectos de un algoritmo

Debe cumplir una serie de caractersticas obligcrtorias como son:

o Correccin: respetar al pie de la letra Ias especificaciones del problema.


o Complejidad: economizar los recursos que necesita. En mquinas secuenciales,
debe ahorar tiempo y memoria. aunque la mayora de las veces son propiedades
inversamente proporcionales.
CoNcnpros DE PRocRauacru

Tambin es deseable que tenga las siguientes caractersticas:

o Generalidad: servir para la clase de problemas 1o ms amplia posible.

o Eficiencia: ser lo ms ehciente posible en la medida que necesita de menos pasos


para solucionar el mismo problema.

1.2.3 Problemas, algoritmos y programas


Los algoritmos indican como solucionar los problemas. Algunos problemas tienen dis-
tintas soluciones algortmicas. Por ejemplo. haliar el mximo comn divisor de dos
nmeros. Otros problemas no tienen solucin algortmica, por ejemplo el problema de
la parada (encontrar un algoritmo que determine si otro algoritmo finaliza o no con unos
determinados datos de entrada).

Programa: es un conjunto de instrucciones precisas, en un lenguaje "entendible" por


la computadora. Hay que notar que el ordenador solo comprende directamente el
lenguaje mquina.

Programacin: se denomina programacin a todo el proceso que conlleva la construc-


cin de progralnas.

Para construir un programa hay que seguir un mtodo. La ingeniera del software se
encarga del estudio y la aplicacin de los distintos mtodos existentes para desamollar
,-ompletamente aplicaciones informticas. En eI apartado 1.4 se da una explicacin ms
anpiia de la ingeniera del software.

1.3 Lenguajes y paradigmas de programacin

En este apafiado se definen los lenguajes de programacin, se muestran sus caractersti-


casprincipaies y su evolucin. Tambin se da una pequea introduccin a los paradigmas
r .e define el usado en este libro: el paradigma imperativo.

13.l Lenguajes de programacin

Un lenguaje de programacin es un lenguaje artificial, diseado para representar algorit-


mos de forma inteligible para las computadoras.
Existen muchos lenguajes de programacin, pero el nico que entiende el ordenador
directamente. como se ha comentado anteriormente, es el lenguaje mquina, cuyas ins-
tmcciones estn codificadas en forma de secuencias de ceros y unos (bits). El resto de
lensuajes necesitan traducir o interpretar las instrucciones al lenguaje mquina.

L
LnNcu,tJps y pARADTGMAS DE pRocRAuRcrN

Comparacin entre el lenguaje natural y los lenguajes de programacin

Los lenguajes de programacin son ms tbrmales y rigurosos que el lenguaje natural.


Esto es debido a que sus instrucciones no son ambiguas y por 1o tanto no permiten dis-
:rntas interpretaciones. Todas las personas que lean una instruccin saben perf-ectamente
qLr hace (si conocen el lenguaje de programacin).
Los lenguajes de programacin son ms simples en su sintaxis y en su semntica
que los naturales. Las reglas de formacin de instrucciones (sintaxis) son rgidas, al
ontrario que los ienguajes naturales en los que una misma fiase se suele poder escribir
:ambiando el orden de ciertos elementos. El signiflcado de las instrucciones viene cla-
:ilmente delinido en los lenguajes de programacin en contraposicin con los lenguajes
.'rrrturales en los que existe ambigedad semntica.
Algunas caracterslicas importantes de los lenguajes de programacin son:

Sintaxis: son reglas de fomacin de todas 1as estructuras de un programa, desde


cmo construir el esqueleto de un programa entero a cmo esta formada una ins-
truccin. Por 1o tanto, especifica inequvocamente cmo estn construidos los
programas elaborados con un lenguaje de programacin.

Existen varias fbrmas de especificar la sintaxis. Entre ellas destacamos las gram-
ticas (BNF o Backus-Naur Form) y los diagramas sintcticos.

Semntica: la semntica asigna un significado a cada tipo de construccin de un


lenguaje de programacin. Existen diversas formas de especiflcacin:

Ejemplos (y contraejemplos): el signiflcado viene dado por un ejemplo.


Tambin se suelen useu contraejemplos para especificar en caso de duda lo
qLle no significa.

Definicin formal: se usa un lenguaje formal para dar signifrcado a la cons-


truccin.

Traduccin y ejecucin: todos los lenguajes de programacin que no son ien-


guaje mquina ha de traducirse al lenguaje de Ia mquina. A1 programa escriro en
un lengtraje de programacin se le denomina cdigo o programo.fhente. Existen
dos formas puras de traduccin del lenguaje de programacin a cdigo mquina:

I . Compilacin: todo el cdigo fuente se traduce a cdigo objeto. Esta traduc-


cin la hace una aplicacin especial denominada compilador. Por 1o tanto el
cdigo objeto es el resultado del proceso de compilacin. Dependiendo del
compilador este cdigo puede ser directamente ejecutable.
2. Interpretacin: este proceso se realiza por repeticin de las siguientes fases:

- Se traduce una instruccin del cdigo fuente.


- Se ejecuta dicha instruccin.
I

CoNcrpros DE PRocRlntRcrN

Por 1o tanto, Ia ejecucin de un programa escrito en un lenguaje de programa-


cin interpretado consiste en traducir y ejecutar una a una cada instruccin
del programa fuente.

Entre 1as ventajas de la compilacin frente a la interpretacin se pueden citar las


siguientes:

- Un programa compilado tarda menos en ejecutarse qlle uno interpretado,


debido a que el proceso de traduccin se ha realizado previamente.
- En la compilacin se pueden hacer optimizaciones lpor ejemplo, eliminar
instrucciones que no se ejecutan nunca) debido a que el compilador puede
ver el programa completo. En la interpretacin no se realizan.
- Una vez que un programa se ha compilado y se ha generado el cdigo ejecu-
ttrble, no es necesario la presencia del compilador. En eI progrlma interpre-
tado, es necesario el interprete para la compilacin y para ia ejecucin.

Los traductores de Pascal generalmente son compiladores.


Errores: cuando se escribe un programa, pueden surgir erores. Dependiendo de
cuando aparezcan se distinguen dos tipos:

Errores de compilacin: aparecen a la hora de compilar o interpretar el cdigo


tuente. Estos errores son fciles de coregir debiclo a que generalmente los
traductores dan indicaciones del tipo y el lugar del error. Ejemplos de este
tipo de errores son: los sintcticos (como escribir mal una instruccin). los
errores de tipo (por ejemplo intentar asignar un valor de un tipo de dato a
una variable de trpo distinto), etc.
Errores de ejecucin: slrrgen al ejecutar el cdigo ejecutable. Son difciles de
cletectar y hacen que el prograrna termine de una forma no prevista. Ejemplos
cie estetipo de error son la realizacin de operaciones ilegales (divisin por
cero). errores lgicos. etc.

13.2 Evolucin de los lenguajes de programacin


El lenguaje de programacin ms cercano a la computadora es el lenguaje o cdigo
mquina. En este lenguaje las instrucciones y los datos estn codiflcadas en sistema
Lrinario )' no es necesario la traduccin. Entre las caractersticas del lenguaje mquina
--ahen destacar:

o Es dependiente de los recursos de la computadora, por lo tanto, para programar, el


programador debe conocer la arquitectura sobrella que programa.
o El pro-eramador se errcatgade verificar que no existen errores sintcticos, pues no
eriste compilador.
o El programador trabaja directamente con direcciones de memoria.
--"1

LBNcU.TJBS y pARADIGMAS DE pRocRAvucru

l--.ttto evolucin natural surgi un nuevo lenguaje llamado ensamblador, donde a tlr
.:uencia de ceros y Llnos se le asocia un nombre nemotcnico. Estos nombres necesitun
.:Juccin. que se realiza mediante un proglama que se llama como el lenguaje: ensam-
:Lldor. Aunque lue un gran avance, todava es necesario conocer cmo est constituida
. .11r recursos tiene la computadora.
\{s tarde se fueron asociando nombres a conjuntos de instrucciones que realizaban
-.nt tarea compleja determinada, y a programar de manera independiente a la compu-
..rJora dinde se iba r ejecutar el cdigo. A los lenguajes que incluyen estas caractersti-
- . se les denomina lenguajes de alto nivel, porque se encuentran ms cercano a la forma
-l: pensar de los humanos que al lenguaje que entiende la mquina.
Los lenguajes de programacin han ido evolucionando gracias a cuatro causas o
rr,rrtores que impulsan esta evolucin, que son:

\bstraccin: proceso mental por el que el ser humano extrae las caractersticas esen-
ciales de algo, e ignora los detalles superfluos. Es esencial para modelar el mundo
real. En un principio se hacan programas pensando como una computadora. En
la actualidad se solucionan los problemas sin conocer la mquina doncle va a ser
ejecutado el programa.
Encapsulacin: proceso por el que se ocultan los detalles de las caractersticas de una
abstraccin. En pro-gramacin es esencial para reutilizar cdigo. Si se ocultan
los detalles de cmo est hecho Lln programa pero se conoce el modo de funcio-
namiento, se puede utilizar en cualquier otro programa sin ms qlle respetar su
especifrcacin.
\Iodularidad: proceso de descomposicin de un sistema en un conjunto de elementos
poco acoplados (independientes) y cohesivos (con significado propio). Es esencial
para abordar 1a resolucin de problemas extensos o complicados.

Jerarqua: proceso de estructuracin por el que se organizan un conjunto de elementos


en distintos niveles. atendiendo a determinados criterios (responsabtlidad. cornpo-
sicin. etc.)

A medida que se fueron aadiendo estas caractersticas fueron surgiendo 1os si_suien-
r'. estilos de programacin:

Programacin estructurada: se aade a la programacin en cdigo mquina la abs-


traccin de datos e instrucciones.
Programacin modular: se aade a la programacin estructurada la modularidad.
Programacin con tipos abstractos de datos (TAD): se aade a la programacin mo-
dular la encapsulacin.
Prttgramacin orientada a objetos: es la ms completa. pues rene todas las propie-
dades que impulsan la evolucin de los lenguajes.
Coucnptos DE PRocR.ulcrN

son:
Las ventajas de aadir estas propiedades a los lenguajes de programacin
o Mejor comPrensin del Programa.
r Mejor legibilidad.
o Mayor facilidad en el mantenimiento del programa'

Disminucin de los costes de desarrolio de una aplicacin inf'ormtica'

1.3.3 Paradigmas de Programacin

Definicin: Los paracligntas progratnacin son una coleccin de patrones concep-


cle
tuales que moldean la fbrma de razonar sobre problemas, de
formular algoritmos
y. a la larga, de estructurar programas'
En este libro se va
Existen varias fbrmas (paradigmas) de enfrentarse a 1os problemas'
a seguir el paradigma imperativo, utilizando programacin
estructurada y modular' En
los paradigmas y los
la ligura 1.2 se muestra un grfico ilustrativo de la relacin entre
lenguajes cle programacin'
Lrprogr"rracin imperativa o de flujo de datos se basa en el modelo von
Neumann

de un computador, doncle la mquina es de propsito


general (permite tealizar cualquier
tarea computacional)y el programa que contiene las rdenes o instrucciones se encuentra
de operaciones primiti-
almacenado en memoria. Este programa contiene un conjunto
una detrs de otra, en e1 orden
vas. que se van ejecutando de manera secuencial, es decir.
son abstracciones de
en que estn escritas. Las variables, expresiones e instrucciones
consiste en declarar los
las tareas y los datos que se usan. Programar en este paradigma
de instrucciones (asigna-
datos (variables) necesarios y disear una secuencia adecuada
Ejemplos de lenguajes de
c.iones) controlando el flujo mediante instrucciones de control.
programacin que soportan este paradigma imperativo son: Pascal'
c. Ada, Modula2"'

L.4 Ingeniera del software


El desarroilo de programas realiza siguiendo uncls mtodos. La ingeniera del soflware
se

se encarga del estudio de todo el proceso que envuelve


la realizacin de las aplicaciones
informticas 1'se puede definir como sigue:
de la in-
Definicin-l (tsauer, 1969)z el establecimiento y uso de principios robustos
y que funcione
seniera a hn de obtener econmicamente software que sea fiable
ehcientemente sobre mquinas reales'
disciplinado y
Deflnicin-2 (IEEE, 1993): La aplicacin de un enfoque sistemtico,
del software'
cLlantihcable hacia el desarrollo, operacin y mantenimiento
para el desarro-
Antb.rs dehniciones se basan en la aplicacin de mtodos de ingeniera
y seguiremos el
ller t1e programas. Existen varios mtodos pero nosotros nos lijaremos
siguientes o pasos:
denomrnaclo ciclo cle vida clel sofiware que consiste en las
f-ases
IqcrurrnA DEL soFTwARE 9

Frog. orie,,td,*da
c ajefns
Prog. LIP
Funcional Hope
(P.Dsclarativa)

Prog.
Lgica Prolog
(P.Declarativa)

C Ada
Smalltalk
Prog. pAscAL
Pasca] FC
Delfi
C++
Imperativa Fortan
Java Eiffel

Figura 1.2: paradigmas y lenguajes de programacin

Planificacin

:: -rllificar es determinar
las necesidacles de programacin, estimar la cantidad de recur-
' '1
\ Se&fl tcnicos como humanos necesarios para el desarrollo, predecir de manera
:|Ll.\imada el coste y el tiempo que llevara realizarlo y por
ltimo, determinar si el
-:.nollo del software es viable econmicamente.

rnlisis de requisitos

-:' esta fase se definen detalladamente las funciones de


cada mdulo. de acuerdo con
' deseos del cliente, el trabajo conjunto de los distintos
mdulos, as como se esta-
- los criterios y sistemas de valiclacin para comprobar que
.' 'Jen se han cumplido los
del cliente' En este paso tarnbin se redactan las especificaciones
'reses detalladas
--:, iirncionamiento general del software.

Diseo

-.-Lr se disea el conjunto de bloques o mdulos en los que


se ha diviclido la aplica-
' '.. y a su vez se dividen en paftes o tareas que se asignan a equipos de trabajo, que
- :terio,-nente las desamollarn y probarn independientemente del
resto.
f
10 CoNcBpros DE PRocRlmlcrN

Codificacin
En este paso se escriben los algoritmos de los distintos mdulos en el lenguaje de pro-
gramacin elegido. Una vez que se han implementado se integran las partes para que
fbrmen un programa completo.

Validacin

Consiste en aplicar el sistema de pruebas descrito en la fase de anlisis de requerimien-


tos. Los mtodos de validacin son pruebas, inspecciones y la verificacin formal. Estos
mtodos se han de aplicar a todos los objetos de validacin que son: los mdulos de
programa. las conexiones entre ellos (integracin) y finalmente a la aplicacin entera.

Mantenimiento
Aqu se redacta la documentacin actualizada de todos los pasos. Se inicia la explota-
cin del software, ponindolo en funcionamiento real. Se detectan y subsanan errores
cometidos en etapas anteriores y si es necesario se adapta la aplicacin a nuevos requi-
sitos.

I
Captulo 2

Elementos bsicos de Pascal

Una vez conocidas las nociones bsicas sobre algoritmos, se pasa a presentar cmo se
reizan programas sencillos siguiendo el paradigma imperativo. Para ello se utiliza el
lenguaje de programacin denominado Pascal, debido a que fue diseado para la ense-
anza de la programacin. Es esencial aprender a programar de manera correcta, legible
y eflciente. Si se adquieren unos buenos hbitos, el paso a otro lenguaje de programacin
imperativa es sencillo. En este captulo se aprendern los elementos bsicos del lenguaje
y se har hincapi en la metodologa parala corecta construccin de programas senci-
llos.

2.1 Historia y caractersticas de Pascal

Niklaus Wirth, cientfico informtico y profesor del Instituto Politcnico de Zurrich, en


1968 cre un lenguaje de programacin, basndose en otro lenguaje denominado AL-
GOL 68. El nuevo lenguaje incorporaba las mejores caractersticas y evitaba los pro-
blemas y defectos de muchos de los lenguajes existentes. Lo denomin Pascal en honor
a Blaise Pascal (1623-1662) que fue un matemtico francs que invento la primera m-
quina de calcular.
En 1910 hizo el primer compilador totalmente completo. Desde entonces, se han
se
construido muchos compiladores y estn disponibles para diferentes mquinas. El libro
"Pascal User Manual and Report" publicado por With y Kathleen Jensen en 1974 ha
servido como estndar de facto de todas las versiones. Sin embargo, muchas compaas
han desarrollado versiones con extensiones del lenguaje.
Las versiones que desarrollan nicamente la especiflcacin estndar se denominan
PASCAL estndar. Las que lo extienden se llaman PASCAL extendido. Ejemplos de
estas ltimas son TurboPascal, Macintosh Pascal, VAX Pascal y QuickPascal. Los pro-
gramas de este libro se implementan usando el compilador TurboPascal.

11
t2 Elrurrros sisrcos os P.r,sc.-r.l-
Caractersticas de Pascal

Entre las principales caractersticas de este lenguaje se pueden citar:

o Es un lenguaje de alto nit,el. Los lenguajes de alto nivel son aquellos en los que
las instrucciones o sentencias son escritas con palabras similares a las de los len-
guajes humanos (en la mayora de los casos, el ingls). Esto f'acilita la escritura y
comprensin del cdigo aI programador.
o Es de protsito generolya que es aplicable a una gran cantidad de problemas de
diversa naturaleza: matemtica. fsica. de gestin, de ocio,...
. Es strltcturado en los datos y en el control del flujo de los datos.
o Es modular, ya que permite dividir los problemas en partes. que se pueden resolver
mediante mdulos o subprogramas independientes entre s.
o Es c:orupcrclo y t'ic:il de aprencler debido a que posee muy pocas instrucciones
bsicas.
La mayora de los traductores son compiladores, lo que 1o hace un lenguaje corn -
pilado.
Fue diseado para \a enseanzct de Ia programacin. Es un lenguaje fuerternente
tipado lo que implica que no va a permitir mezclar expresiones de distintos tipos.

2.2 Tipos de datos bsicos


lJn dctct es una representacin de un objeto mediante smbolos manejables por el orde-
nador. Los programas manipr-rlan datos. Casi todos los lenguajes disponen de tipos de
datos bsicos que sirven para definir ciertas caractersticas del objeto que se va a lnane-
jar. Existen tipos llamados preclefindos o estndcLr que sirven para manipular nmeros
enteros. nmeros reales, objetos booleanos (qr-re s1o pueden tener dos valores, gene-
ralmente verdadero o falso) y objetos alfanumricos denominados caracteres. Al igual
que en matemticas, cuando se estudian los nmeros naturales se explica eI rango de
valores que pueden tomar y las operaciones que se pueden realizar con ellos, en progra-
rracin un tipo de dato especiflca el rango o dominir de valores que pueden tomar, las
rtperuciortes que pueden utilizar y cmo se construyen erpresiones.

Tipos ordinales

Entre 1os tipos c1edatos bsicos se pueden distinguir dos grupos: los ordinales y los
reu1e., Se cienomjnan ordinales porque pueden enulnerar sus dominios asignando a sus
elL'1rel.rto\ un nrrnero de posicin y todos sus posibles valores poseen un elemento si-
Surente r. un eler.nento anterior (excepto el primero y el ltimo). Los tipos integer,
:.-... \ 'i. - -=,.,. que se estudiarn a continuacin, cumplen esa propiedad. Poseen fun-
cior.r.'. predehnidas en el lenguaje para saber su posicin y el valor siguiente y anterior.
Trpos DE DATos rsrcos t3

La funcin ord(x), que es propia de estos tipos de datos, devuelve eI nmero de posicin
del argumento x en su dominio. Las funciones pred(x) y succ(x) son tambin exclusi-
vas de los tipos ordinales y devuelven el predecesor y el sucesor de x respectivamente.
Por ejemplo, pred(2)=1 y succ(2)=1.

2.2.1 Tipo entero (integer)


En Pascal para expresar que un dato variable es de tipo entero se utiliza la palabra pre-
deflnida inLeqer.
Su rango debera ser el de los nmeros enteros. pero debido a las limitaciones de
representacin en la computadora el dominio est acotado. En TurboPascal est Iimitado
por la constante predefinida denominada MAXINT. El rango es [-(MAXINT+l),MAXINT]
que traducido a nmeros es [- 32768, 321611.
Los nmeros enteros se escriben sin espacios ni puntos entre sus cifias y el signo, si
aparece, precede aI nmero. Ejemplos de nmeros enteros son el +123. el - 26. el 0, el
I I 231, etc.
Entre los operadores que actan con nrmeros enteros se distinguen los operadores
binarios y los unttrios. Los binaric,s tienen dos operandos enteros, devuelven un valor
entero y se escriben en notacin infija, es decir, el operador va entre los operandos.
Los ttnarios o tttonctrios slo tienen un operando entero, devuelven un valor entero y se
escriben en notacin infija. La tabla 2.1 muestra los operadores sobre nmeros enteros.

@peredor Explieacin Ejemplo


+ Suma 5+3+8
Resta 5-3=:+2
Multiplicacin J*lal
div Divisin entera. Devuelve la parte entera del -5div3+1
cociente
mod Resto de la divisin entera. Devuelve el l- 5 mod 3 ....+ 2
timo resto de la divisin
Cambio de signo -l-lt-++l
Tabla 2.1 : Operadores sobre nmeros enteros

Las funciones que actan sobre enteros y devuelven un nrmero entero se pueden
\.er en la tabla 2.2. Las tres ltimas funciones y los operadores +, - y * estn lirnitados
por el rango de integer. por 1o que hay posibilidad de desbordamiento si el valor que
Jevuelven supera el lmite superior o inferior.
t4 ELEMENTOS BSICOS DE PASCAL

Funcin Explicacin Ejemplo


abs(n) Devuelve el valor absoluto del nmero abs(- 3) 3 3

sqr(n) Devuelve el cuadrado del nmero sqr(- 3) 3 9


pred(- 3)
pred(n) Devuelve el predecesor del nmero -; - 4
succ(n) Devuelve el sucesor del nmero succ(- 3) ---+ - 2

labla2.2: Funciones sobre nmeros enteros

2.2.2 Tipo real (real)


Para expresar en Pascal que un clato variable es un nmero de tipo
real se utiliza la
palabra predeflnida rea1.
de
Su rango debera ser el de los nmeros reales. pero debirlo a las limitaciones
representacin el clominio est acotado. El mayor nlmero (en magnitud) es
aproxim^a-

u-"nt" el _t 1.7 * 1038 y el menor distinto de ce.o es aproximadamente el 12'9 x 10-3e'

Latrecisin est entre ll y 12 cifras significativas'


Existen dos formas de representar nmeros reales:

o En coma fija e] nmero tiene una parte entera y una parte tiaccionaria separadas
con
por un punto. Puede estar prececlido por el signo. Ejemplos de nmeros reales
esta notacin son el 3.25, el - 3.0 y el + 666'414'

o En notacin cientfica o coma flotante el nmero posee un exponente entero,


ejem-
cuyo significarlo es que se multiplica por 10 elevaclo al exponente. Algunos
coma flotante son 0'2E3 (que equivale
plos de nmeros reales con esta notacin en
, o.zrto,), 4E-2 (equivale a 4.0x10 2),6.0238+23 (equivale a 6.023x1023).
un valor
Los operadores que actan con nmeros reales como operandos y devuelven
real son expuestos en la tabla 2.3.

Operador Explicacin Ejemplo


+ Suma 5.0+3.23$.1
Resta 5.0-3.2+ 1.8
,t
Multiplicacin 5.0*3.2+16.0
Divisin 5l3 + 1.6666666
Cambio de signo -(3.0)3-l.Q
Tabla 2.3: Operadores sobre nmeros reales

nmero
Lits funciones aritmticas que operan sobre un nmero real y devuelven un
real se lnllestran en Ia tabla 2.4.
pascal carece cle algunas funciones estndar matemticas. Para hallarlas se pueden
r-rti i i z ar 1 i'rs func iones predefini das anteriores.
Trpos DE DATos Bsrcos 15

Funcin Explicacin Ejemplo


abs(x) Valor absoluto del nmero. abs(- 3.0) + 3.0
sqr(x) Cuadrado del nmero sqr(- 3.0) + 9.0
sqrt.(x) Raz cuadrada sqrt(9.0) 4 l.Q
sin(x) Seno. Angulo x en radianes sin(Pli2;e 1.9
cos(x) Coseno. Angulo x en radianes cos(PU2)3 g.g
arctan(x) Arcotangente. Angulo en radianes arctan(1.0)e Q,l$l!$
rn(x) Logaritmo neperiano. Base el n- 1n(2,718281 8)---; 1 .0
mero e (de Euler)
exp(x) Exponencial en base e. Eleva el n- exp(1)3 2,718281
mero e al nmero dado

TablaZ.4: Funciones predefinidas sobre nmeros reales

2.2.3 Tipo carcter (char)

Para expresar que un dato variable es de tipo carcter se utiliza la palabra char.

EI rango de los caracteres, que se denotar por C, es el juego de caracteres disponi-


bles en el ordenador. Se deduce de la frase anterior, que el dominio de C puede cambiar
de un ordenador a otro. Generalmente, los ordenadores siguen un estndar denominado
ASCII donde vienen expresados 1os caracteres que contiene y el nmero de orden que
le corresponde a cada carcfer (ver figura 2.1). El juego de caracteres ASCII de 8 bits
contiene 256 caracteres distintos, numerados del 0 al 255.
Un carcter se escribe entre apstrof'es (comillas simples), por ejemplo 'h','A','@'.
E1 carcter ""' al ser especial se escribe de la siguiente manera: "".

En Pascal no existen operaciones que acten sobre caracteres y devuelvan un carcter


pero s que tiene funciones predefinidas que operan sobre un carcter y devuelven un
carcter. Se muestran en la tabla 2.5.

Funcin Explicacin Ejemplo


pred(c) Devuelve el carcter anterior (cdigo AS- pred('f') 3's'
r).
succ(c) Devuelve el carcter siguiente (cdigo succ('A ) ===+ 'B'
ASCrr).

Tabla 2.5 : Funciones predefinidas sobre caracteres


l6 ELEMENTOS BSTCOS DE PASCAL

Dec EEx Cbar


D NUII 3Z ttt sFaEB ++E ! 6rl
1 L-l1 StBrt rf headirll 9f 61 a
3 Eitatl c't te1 3+ Z?. 6r, { E

3 l En':l ot tEr{t
# ri? 4:l Il 9tr l ,:
+ + End trasrrit 6rl ++ D Itlll { '1
'lf
5 05 Enquir! aa 'f q t 6! ,I5 E 1tl1 65 E
rj l:16 ,cknD$,|dgE J tr & Trl 4 E 10? 66 t
? [T ,qudilrlE h*ll t! 1 77 t? E 1r:r3 6? ,J
Backsl:ate 4n .]Fl 1a' 49 H 1rl+ EE h
'
! [l!] Horir':'rrtaltall dl lta 1 ?3+rr 1n5 6r i
1ll llA Lirre f ee,l t H ?{+AJ 1DE EA -l
11 E !/,=rti'],?ltEtr +:J E + ?5+EH 1tl? 68 k
13 0f Fr'rtrr feed { 'Jt- ?6 {rl L
13 tlt (:rriirl rtrturn 45 ZI] ?? {tr H 1ll9 ED fil
1{ l:lE Shift rrLlt {b lE ?F +E I,] 11L-r r5E rl
15 L-]F ljhift in
ra 'rF ! ?!r 4F O 111 6F ,:,
1 6 1! DHt,e link esrpe 48 l {l E0 str F 11? ?D p
1f 11 []eviEe'llrntr'll 1 {9 1 I 11 81 51 t 11f ?1 q
1E LZ [,,:\]ice t:,:,ntrol i 532Z 11{ ?? r
M3 DE\r,ic r:r:lrrtrol 3 ,]I JJ ;' tt tJ =
Z tl 1+ [],l,iLlB ,::nntr,:,| 4 52 3+ 4 { 54 T 116 ?{ r
?7 15 l,lEl]. a|:[,:rrLl\rvler]gr-' 5 35 5 E5 55 LI 1l? ?5 u
ZZ 16 5r:|1uridle 5,1 16 6 tr 6 .56 U 118 ?6 r/
3 1T End tranr hl,l,ll': :' J i I E? 5? 1 l1r '?'l r
v AU iJ
4 1B CEncel }E JI' EI

5 1!1 End
':t
mrliurrr 5? :l-1 I 89 5!r T 171 ?q r

!:r-l 5L Z i a,i, tL
3 r lA SuhBtitl{tion
1E q1 5F r 13 ?E {
3 ? EraF,l
r: 3C -; a qr \ ra aT I
ZB 1C Fil Bpart,lr

X tr 1Ij rirs1 :.epar'atr DI JD 33s!l


:l r:r 1E FicErd spBrBtr 6J ;]E } !+ ,5E 1e6 ?E
]F :] rra tr n
i :i 1 1F Unrt EEI]fllEtr E]
I
I

Figura 2.1: Los 127 primeros caracteres de la tabla ASCII


I
I
I

I
I

I
I
I

I
I

I
I
I
I

I
I

t
Trpos DE DATos nsrcos 17

2.2.4 Tipo booleano (boolean)


Para expresar en Pascal que un dato variable es de tipo booleano se utiliza la palabra
predefinida boolean.
Estos datos pueden contener nicamente uno de los dos valores predelinidos: TRUE y
FALSE. Los operadores que actan con valores booleanos y devuelven un valor booleano
se muestran en la tabla 2.6.

Operador Explicacin Ejemplo


AND Devuelve el valor de la conjun- TRUE AND FALSE + FALSE
cin lgica (y-lgica)
OR Devuelve el valor de la disyun- TRUE OR FALSE + TRUE
cin lgica (o-lgica)
NOT Devuelve el complemento 1- NOT TRUE + FALSE
gico

Tabla 2.6: Operadores sobre valores booleanos

En la tabla 2.7 se da la tabla de la verdad de estos operadores. Para obtener el


resultado basta con saber el valor de los operandos. En la linea corespondiente a esos
valores se obtiene el resultado del operador.

Operador AND Operador 0R NOT


I'
^l\Tn
E- + E' F OR F+F
F OR T+T NUl ------' -L

.F tr r, tr T \Jlf
^nF\m r ------' J- NOT T+F
^t\Tn
T' .F + rF
T uI( -L -------7 -L
^\TTl

Tabla2.7: Tabla de la verdad de los operadores (T=TRUE, F=FALSE)

Las funciones predef,nidas que operan sobre un valor booleano y devuelven un valor
booleano se pueden ver en Ia tabla 2.8.

Funcin Explicacin Ejernplo


pred(b) Del.uelve el valor anterior a b. Pred (TRUE)9 P5
succ(b) Del.uelve eI valor siguiente a b. SUCC (FALSE) + TRUE

Tabla 2.8: Funciones sobre booleanos


r
18 Er,rnmNros BsICos DE PAScAL

Evaluacin perezosa

Cuando el compilador se enfrenta al proceso de evaluacin de una expresin con un


nico operador booleano (AND u oR), halla el resultado del operando izquierdo y luego
del derecho. Si conociendo el valor del operando izquierdo se conoce el resultado de la
expresin (por ejemplo FALSE AND x siempre devuelve FALSE, independientemente de
lo que contenga x; o TRUE OR x siempre devuelve TRUE independientemente del valor
de x), el compilador puede optar por no hallar el valor del operando derecho. En tal
caso, este tipo de evaluacin se denomina evaluacin perezosa, debido a que no tealiza
esfuerzo en calcular uno de los operandos. Los compiladores de Pascal estndar realizan
una evaluacin completa, sin embargo el compilador de Turbo Pascal hace evaluacin
perezosa.
Por ejemplo, sean dos nmeros enteros denominados num y den y supongamos que
den:=O. Laexpresin ((den <> 0) AND (num DIV den = 0)) conevaluacinpere-
zosa (ciclo corto) devolver el valor FALSE (Turbo Pascal realizaeste tipo de evaluacin).
Sin embargo, con la evaluacin completa (ciclo largo) se producir un effor en tiempo
de ejecucin (en Pascal estndar) al dividir por cero, ya que ese es el valor de den.

2.3 Operadores relacionales o de comparacin

Estos operadores sirven para comparar nicamente elementos del mismo tipo y devuel-
ven un valor booleano como resultado de la comparacin. Son operadores binarios y se
escriben en notacin infija. En la tabla 2.9 se muestran todos los operadores relacionales
de Pascal estndar.

Operador Explicacin Ejemplo


Comparacin de igualdad. Igual que =3FALSE
Distinto que 5<>6+TRUE
Menor que 5<6-_:TRUE
<= Menor o igual que 5<=6+TRUE
Mayor que ; FALSE
>= Mayor o igual que 5>=6-FALSE
Tabla 2.9 : Operadores relacionales

Es importante notar que Pascal no acepta comparaciones entre elementos que no


tengan el mismo tipo de dato, con la nica excepcin de los nmeros reales y enteros.
ExpnBSIoNps l9

2.4 Expresiones
LIna expresin puede estar formada por constantes, variables. funciones aplicadas a una
expresin y operaciones entre expresiones o una combinacin adecuada de estas. El
concepto de variable y constante se define en el apartado 2.7 .2.

2.4.1 Precedencia de operaciones


Las operaciones se aplican segn la precedencia dada en la tabla 2.10 y en caso de
igual precedencia la asociatividad es de izquierda a derecha, es decir, se evalra la que se
encuentre ms a la izquierda de la expresin. Las funciones se aplican a sus parmetros
entre parntesis.

Precedencia Operadores Denominacin


1(mxima) o Parntesis
2 _, NOT Negacin (monarios)
-l *, /, DIV, MOD, AND Multiplicativos
4 +t -, 0R Aditivos
5 (mnima) Relacionales

Tabla 2.10: Precedencia de operadores

2.4.2 Tipo de dato de una expresin

Cada expresin tiene un tipo de dato que depende de los operandos, operadores, funcio-
nes, etc., que componen la expresin. El tipo de la expresin correctamente formada se
halla evaluando eI tipo de cada subexpresin y funcin de acuerdo a la precedencia de
1as operaciones. Si el argumento de una funcin o del operando de un operador es una
expresin, entonces el tipo de dato de la expresin ha de coincidir con eI tipo de dato
requerido para el argumento. Como nica excepcin tenemos la conversin autom-
tica de nmeros enteros a nmeros reales. En el proceso de compilacin, el compilador
comprueba la correccin de tipos y avisa si se produce un error.

2.5 Sobrecarga de operadores y funciones


Ciertas funciones y operadores se pueden :utllizar con distintos tipos de datos. Se dice
que esos operadores o funciones estn sobrecargados. Por ejemplo la operacin + puede
actuar sobre dos nmeros enteros, o sobre dos reales, o sobre dos caracteres. La funcin
succ(x) puede aplicarse sobre un nmero entero, o sobre un carcter o sobre un valor
booleano. Tambin todos los operadores relacionales estn sobrecargados.
20 ELEMENTOS BSICOS DE PASCAL

2.6 Conversin de tiPos


y las realiza-
Existen dos tipos de conversin: las automticas o conversiones impicitas
<las por el programador o conversiones explcitas'

2.6.1 Conversin imPlcita


de un nmero
Pascal realiza automticamente (siempre que sea necesario) la conversin
entero a un nmero real ya que el conjunto cle nmeros enteros es un
subconjunto de
reales. Por lo tanto, si hace operaciones que mezclen nlneros enteros con
los nmeros
y se opera' La
reales, primeramente se realiza la conversin de enteros a reales despus
pues
conversin inversa (de real a entero) no es posible hacerla de manera automtica,
otra conversin de manera
se pierde infbrmacin. Ntese que Pascal no realiza ninguna
autnoma" Los siguientes ejemplos ilustran este hecho:
Ejemplo a): 12 + 3.2:-', 12.0 + 3.2:+ 15'2
Ejemplo b): 9.0 1y I 3 Se procluce un error de compilacin, pues DIV solo
admite
de Pascal no
operandos enteros y 9.0 es real. Como ya se ha comentado, el compilador
evidente realizarla)'
realiza la conversin cle real a entero (aunque en este caso parezca

2.6.2 Conversin exPlcita


de ellas
Para realizar conversin entre tipos existen funciones predefrnidas' Algunas
estn descritas en la tabla 2.1 l.

Conversin Funcin Descripcin Ejemplo


Real a Entero trunc(x) Devuelve la pafte entera trunc(7.a 7
dex
Reai a Entero round(x) Del'uelve el entero ms round(7.6)3 3

prximo a x
Carcter a Enteri ord(c) Devuelve el no de orden ord('A )4 65
en la tabla ASCII del ca-
rcter c
Entero aCarctet chr(n) Derrrelve el carctet chr(72)3'+r'
correspondiente al no rz

en la tabla ASCII
- =rr r FniPrn ord(b) Demelve el nmero de ord(tnun)e 1

orden del valor booleano

T abla 2. I t : Funciones para conversiones explcitas


Er,punNros nsrcos DEL LENGUAJE l1

2.7 Elementos bsicos del lenguaje

Los lenguajes de programacin. al igual que el lenguaje natural, tiene palabras, cada una
con un significado. Afortunadamente los lenguajes de programacin poseen un conjunto
pequeo de palabras, lo que facilita su aprendizaje y comprensin. En esta seccin
se muestra el vocabulario del lenguaje Pascal as como las instrucciones bsicas para
empezar a realizar programas sencillos.

2.7.1 Vocabulario
Palabras reservadas

Las palabras reservadas de Pascal son aquellas que tienen un significado predefinido en
este lenguaje de programacin. Por orden alf'abtico tenemos para Pascal estndar:

AND, ARRAY, BEGIN, CASE, CONST, DIV, DO, DOWNTO, ELSE, END, F]LE,
FOR, FORWARD, FUNCTION, GOTO, IF, IN, LABEL, MOD, NIL, NOT, OF,
OR, PACKED, PROCEDURE, PROGRAM, RECORD, REPEAT, SET, THEN, TO,
TYPE, IINTIL, VAR, WHILE y W]TH.

Turbo Pascal como es una extensin de Pascal aade: IMPLEMENTATION, STRING,


INTERFACE, UNITy USES.
A medida que se necesiten las palabras reservadas se ir explicando su signif,cado y
su comportamiento (si son instrucciones).

Identificadores

Son nombres que se asocian a dif-erentes elementos de un lenguaje (dispositivos, tipos


de datos, constantes y variables). Existen dos clases de identificadores: los predefinidos
y los definidos por el usuario.
Identificadores predefinidos: tienen asociado un significado concreto y se encuen-
tran definidos en el lenguaje. Se ira explicando su signifrcado a medida que se vaya
necesitando. Algunos identificadores predefinidos asociados a ciertos elementos son:

Archivos estndar: input, output.


Constantes: FALSE, TRUE, MAX]NT, PI.
o Tipos: boolean, char, integer, real, ....
c Funciones: abs, arctan, chr, cos, ln, odd, pred, round, sin, sqr, sqrt, succ,
Lrunc, ....
o F:ocedirnientos: dispose, new, read, readln, reset, rewrite, write,
wrrceln. ....
22 Er-nupNros ssrcos or Pasc'r'

los nombres que el programa-


Identificadores definidos por el programador: son
Los identificadores empiezan con una
dor va clando a los elementos de un programa.
y un identificador correcto se siguen
letra, seguida por letras y citias. Para elegir escribir
las siguientes reglas:

o No se permiten caracteres especiales (excepto "-" en Turbo Pascal)'

o No se permiten letras especiales (p'e': ' ' ' ' ')'

oNosedistingueentreletrasmaysculasyminsculas'Porejemplo.Casaesel
mismo identificador que CASA y que cAsA'
pri-
oLalongitudmximaesdel2TCaracteres.deellossolosonsignificativoslos
meros 63.

Smbolos esPeciales
concreto para el lenguaje los si-
Se consideran smbolos especiales con un significado
guientes:

Literales

Sonconstantesannimas,quenoposeenunnombrecomo'porejemplo'lascadenasde
caracteres (que son secuencias de caracteres
delimitados por apstrof'es ""')' los nme-
predef,nidas. Ejemplos de literales son
ros, 1os caracteres y las constantes booleanas ,d,y
,Esto es una cadena de caracteres,,'Los 256 caracteres ASCtrI,, FALSE' 3.1654,
-45.

Cornentarios
fuente con objeto de aclarar su
Los comentiuios son texto intercalado en el programa
contenido.Sonnecesariosparaelprogramadoryposeenlassiguientescaractersticas:

no se traducen ni generan cdigo


o Son ignor-ados por el cornpiiador por 1o tanto
ei ecutabie.

Plrl escr.jbir.un corxentario es necesario ponerlo entre 1os caracteres "1x" , "*)"
entre { } "i" Ejemplosdecomentariosson:
*:s:3 es un comentario*)
::--::anbin es un comentario)'
o\tr:epueclenanidar,esdecir,nopuedehaberuncomentariodentrodeotro'
Elnmruros ssrcos DEL LENGUAJE 23

2.7.2 Constantes y variables


Para almacenar datos en un programa se deben utilizar elementos cotTstatltes ylo vcrria-
bles. Depender de las necesidades elegir una u otra.

Constantes

Son elementos que no cambian su valor a lo largo de la ejecucin de un programa. El


valor se conoce antes de la ejecucin del programa. Las constantes facilitan el manteni-
miento del programa. Existen tres tipos:

o Annimas: se ponen de manera literal. Por ejemplo: 5, 3.14, 'a' (son literales).
o Predefinidas: su valor viene dado por el lenguaje: pI , MAXINT, TRUE, FALSE.
o Definidas por el programador: El programador se encarga de darles un nombre
y un valor.

Variables

Son elementos que pueden cambiar su valor a lo largo de la ejecucin del programa. Son
definidas por el programador y el valor o valores que pueden contener depende del tipo
de dato con el que se define.

Constantes definidas por el programador y variables

Las constantes definidas por el programador y 1as variables se caracterizan por tener las
si guientes caractersticas :

o Un identificador por el que se nombran, es decir, un nombre.


o Un tipo de daios que determina su dominio y las operaciones permitidas sobre
o los datos qlie va a almacenar. IJna vez defrnido el tipo perrnanece constante
etr
durante toda la ejecucin.
Las operaciones perrlitidas sobre etr o los datos que va a almacenar.
o Un vatror. Si es rtna variable este ralor es desconocido inicialmente y habr que
definirlo en el cuerpo del programa. Si es una constante, hay que darlo al definir el
nombre (el tipo de dato se le asigna automticamente dependiendo rlel valor que
se le asocie).

2.7.3 Instrucciones tlsicas: asignacin, escritura y lectura


Las instrucciones son elementos que representan acciones del programa. Sirven para dar
rdenes a Ia computadora.
En esta seccin se estudian tres tipos de instrucciones: la asignacin, las instruc-
ciones de entrada (tambin denominadas de escritura) y las de salida (lectura). A estas
),,1
LA ELEMENTOS BSICOS PASCAL

de entrada'/salida (de fbrma


dos ltimas se les denomina genricamente instrucciones
abreviada instrucciones de E/S).

Asignacin
variable' La sintaxis
La instruccin de asignacin sirve para dar o cambiar el valor
a una

de esta instruccin tiene la siguiente forma:

nombreDeVariable : = expresron

Pascal y expresin es una ex-


Donde nombreDevarrable es un identificador vlido en
-ver en el captulo 6 el apartado
presin del mismo tipo (o de tipo asignacin compatible
cada asignacin solo es
6.6 de compatibilidad de tipos) que el nombreDeVariable.
de ":=" aparece siempre
vlida puru rnu nica variable, por 1o que en la parte izquierda
una sola variable. Ejemplos de asignaciones son:

base : = 10.0
altura : = 20.0
area := base * alLura I 2
contador := contador + I
x := (--b + sqrt(sqr(b) -- 4 *a* c) ) / (2 * a)

primero se evala la ex-


Cuando en tiempo de ejecucin se realiza una asignacin,
en la variable de ia pate
presin de la parte derecha y despus se almacena el resultado
izquierda.
al iniciarse e1 programa
En pascal estndar una variable presenta un valor indehnido
y valorar si es
(valor "basura"). Por 1o tanto el programador deber tenerlo en cuenta
necesario asignar a las variables un valor inicial'
DiferenCia entre aSignacin ":=" e igUaldad "=":la asignacin ":=" eS una ins-
"=" es un operador relacional
truccin que asigna un valor a una variable y la igualdad
Debe tener cuidado de
que se usa dentro de expresiones y devuelve un valor booleano.
no confundirlas.

Escritura
de datos' La salida podr ser a
Las instrucci.ones de escritura son instrucciones de salida
un dispositivo de salida
panralla. a impresora o a fichero en disco. Se asume por omisin
estndar l,fit'hero oLttpltt) que suele ser el monitor'
E stas instrucciones son en realidad procedimientos
predefinidos (ver el captulo '! de
subproqramas ). Tienen el siguiente formato:

,\rr:e ,l:l:*ficadorFichero, expri, expr2 exprn)


urrr:e-: rien:ificadorFichero, exprl , expr2 exprn)
Er,BuBNros nsrcos DEL LENGUAJE 25

Si se omite identif icadorFichero, la salida se produce por el dispositivo estndar


(flchero output o monitor). Cuando la computadora se encuentra esta instruccin acta
de la manera siguiente:

o write: evala sus argumentos y escribe el resultado en el fichero especificado (o


en el estndar).

o writeln: acta igual que write pero cuando termina de escribir el resultado
aade un salto de lnea.

Escritura formateada: para darle fbrma a la salida se puede utilizar una serie
de parmetros junto con los argumentos (expresiones) de los procedimientos write y
writeln.
write(expresion:m, .. .)
writeln(expresion:m, . .. )

El parmetro m indica el espacio en el que se justilicar el resultado de evaluar la expre-


sin. Hay que tener en cuenta qlle:

o La justificacin se hace por la derecha. Pclr ejemplo:

writeln(12 5, 123:4') + bbb12b123 (b indica espacio en blanco)


x : = 6.1284900000E+2;
writeln(x:25) 3 bbbbbbbbb6. 1284900000E+02
wri te ln('Hola':7) ===. SffH(]l
o La salida puede rebasar el espacio reservado por m. Es decir, no oculta informa-
cin. Por ejemplo:
writeln(l2jj2:2; _- 12332

Solo para expresiones reales: por omisin, Pascal muestra los nmeros reaies en
notacin cientfica. Si quiere ver ios nmeros en coma fija (con coma decimal) debe
formatear la salida. Para ello hay que aadir un nuevo modifrcador.

write(expresion:m:n, . . . )

writeln(expresion:m:n, . .. )

Ei parinetro m tieire ia funcin explieada anterior-rnente y n indica el nmero rle


rlecin-lales ql"le se quieren mostrar. En etr caso de que existan ms decimales que n, la
computadora mueslra el vatror dei ciecimal n redondeado al entero ms p.rximo. Advir-
tase que no camhia el vaior de la expresin, solo la muestra de un modo determinado"
So muest:a un ejemplo de salida formateada coil redondeo:
x := 6.1284900000II+2; r,vriteln(x:10:2) + bbbil6l2.85
26 Er,ptrpNros nsrcos oB P'scar,

Lectura
Las instrucciones de lectura son instruccin de entracla de datos'
La entrada de datos
o por det-ecto
podr ser por teciado o tlisco. Se asume un dispositivo cle entrada estndar
(fichero input) qu'e suele ser el teclado.
(ver el captulo 4 de
Estas instrucciones son en realiclad procedimientos predefinidos
subprogramas). Tienen el siguiente formato:

read(identificadorFichero, var1, var2, ' ' ', varn)


readln(identificadorFichero, var1, var2, ' ''' varn)
(fichero in-
Si se omite identiJicado rFichero, la entrada es por el clispositivo estndar
de la manera
put o teclado). Cuando la computadora se encuentra esta instruccin acta
siguiente:
input)
o read: el ordenaclor lee los valores almacenados en el fi.chero (o en el fichero
y los asigna a las variables expresadas como argumentos'
o readln: funciona igual que read pero una vez ledos sus argumentos ignora el
y
resto de valores que existan en la misma linea (si los hubiera) se sita
en el
primer valor de 1a siguiente lnea.

Ejemplo:

VAR
a: char;
.i r1-aaav.
fl . rlruuYu!/

BEGIN
writeln ('rntroduzca una letra' ) ;
readln(a); {si ef usuario pulsa p e INTRO - -2 a.- P l - -.-l^/\

writeln ('InLroduzca un nmero' ) ;


readln(n); {Si ef usuario pu}sa 128 e INTRO --> n:=128)

2.7.4 Estructura de un Programa


un prctgrama contiene las siguientes partes ordenadas segn aparecen: encabezamiento,
estructura de un
clehniciones Y cleclaraciones y por ltimo el cuerpo del programa. La
programa bsico en Pascal es:

:F.al:;,, ;ientif icadorPrograma ; {Encabezamiento}


Propsito:
Entrada:
Salida:
ElnvrcNros rsrcos DEL LENGUAJE 21

CONST {Declaracin de constanLes}


CONSTANTE =

VAR {Declaracin de variables}


variable: tipo;

BEGIN {Programa principal}


Instruccinl;
Instruccin2;

lnst rucc 1onN


EiNlJ. t Programa prrnclpal )

Encabezamiento

El encabezamiento sirve para establecer la identihcacin del programa y los elemen-


tos externos con los que intercambia informacin (archivos estndar input, output y
otros). Es obligatorio en un programa en Pascal. En Turbo Pascal se puede omitir los
elementos externos, por 1o que tiene la siguiente forma:

PROGRAM identif icadorPrograma ;

Declaraciones y definiciones

Se deben declarar los objetos que se van a utilizar y que no estn predefinidos en el
lenguaje. Si no se va a utilizar ningirn objeto esta parte puede omitirse del programa.
Entre los tipos de objetos que se pueden aadir estn las unidades, las constantes, las
variables, los procedimientos y las funciones.
Las declaraciones permiten al compilador reservar espacio de memoria para cada
identificador, asociar un tipo de datos (si es necesario) y veriflcar el comecto uso de los
objetos dentro del programa. El equivalente en notacin matemtica a una declaracin
es: "Sean n Entero, x R, Pi=3.14..."
Cada uno de 1os objetos se declara de la siguiente manera:

o Unidades: las unidades son mdulos ya compilados que contienen procedimien-


tos y funciones tiles. Su declaracin permite utilizarlas en un programa. Su uso
no es posible en Pascal estndar. La forma de declararlas es la siguiente:

USES
ident i f i cadorUnidadl ;
ident i f i cadorUnidad2 ;
ErntrnNtos nsrcos r P'q'scA'r'

clon<leidentifrcadorUnidadeselnombredelrnduloquesevaautilizar'Se
puedenponervariosidentiflcadoresenlamismalneaseparadosporComa'','..Se
12'
estucliaran con mayor detalle en el captulo

o Constantes: las constantes se declaran como sigue:

LUI\
^^nf-m D I
identif icadorConstantel = valorl ;
= vator2

:1:".ttt",dorConstanLe2

es el nornbre de la constante y valor puede ser una


identificadorconstante
por el programador o una ex-
constante literal, predeflnida, defrnida previamente
que tendr durante todo el programa'
presin con valor constante que le da el valor
Laexpresinhadepoclercalcularseantesdelaejecucin.Eltipodedatosdeuna
Por ejemplo si el valor es un nmero
constante se flja cle acuerdo al valor dado'
entero. la constante ser de tipo integer'
y tipo. Se declaran de la siguiente
Variables: las variables tienen un nombre un
manera:

VAR
identif icadorVariablel : tiPol ;
identif icad'orVariabl e2 : LtPo2 ;
ia;1t:-ticadorVariable4' idVariable5 : tipo3 ;

es el nombre de la variable y tipo es el tipo de dato


identificadorvariable
quepuedealmacenar.Comoyasehacomentado,eltipodedatosdeunavariable
es fijo durante toda la eiecucin. El valor
asociado a una variable es desconocido
,,basu.u"j, por lo que tendr que ser tenido en cuenta por el progra-
a priori (valor
maclor.Comos"p,"d"ou,".,u,esposibledeclararvariasvariablesdelmismo
tipo es 1a misma linea, separndolas por comas'
Procedimientos y funciones: se estudiarn en el captulo '1'

Cuerpo
que se van a ejecutar. EmPieza con
El cuerpo del programa contiene ias instrucciones
END y un Punto ".". Un
h paia reservada BEGrN y finalrza con la palabra reservada Las instrucciones (si haY
prog.*u en Pascal debe contener obligatoriamente esta parte'
ar O" una) se separan con el carcter
";"'
Cursrrours DE TrPo rEST 29

BEGIN
Instruccin1;
Instruccin2 ;

END.

El programa empieza ejecutando la primera instruccin, luego la segunda y as su-


cesivamente hasta llegar a la ltima.

2.8 Cuestiones de tipo test


2.8.1 Enunciados
Las siguientes cuestiones pueden tener una o ms respuestas correctas.

l. Cul/es de las siguientes expresiones son de tipo real?

(a) (2+3) Drv 2 * s


(b) (2+3) DIV 2 + 1.5
(c)Bls
(d) (7 MoD 5) > 4.3
2. Culles de las siguientes expresiones devuelve TRUE?

(a) \20 < 4) <> TRUE -l

(b) Nor rRUE oR FALSE <= FALSE '{


(c)6DIV2<L
(d) ORn('a') + 10 > 500

3. Cul de estas afitmaciones nos indica la forma correcta de actuar cuando hay un
error?

(a) Modificar el programa aleatoriamente hasta que funcione.


-r (b) Examinar la sucesin de estados de cmputo (para entradas concretas) para
delimitar el eror.
(c) Cambiar los datos de entrada para obtener la salida esperada.
(d) Si hay un error es, generalmente, debido a que hemos dejado un archivo
abierto, por lo tanto, basta cerrario con la instruccin cl-ose.

4. Ei resultado de la siguiente expresin si valor = TRUE, es:

2*3+374 DIV 7- (ORD(valor) *4)


r-
30 ErBunNtos ssrcos DE PASCAT'

(a) No tiene solucin, produce un error en tiempo de ejecucin'


r."G) 46'
(c) 41.
(d) No tiene solucin, produce un efror en tiempo de compilacin.

5. El operador = es:

- .{a) Un operador binario y sobrecargado.


(b) Un operador que solo acta sobre numeros y devuelve un valor booleano'

.- 1c) Un operador que tiene notacin infija y es sobrecargado'


(d) Un operador que sirve para asignar valores a variables'

6. Los tipos ordinales se caractertzan por que:

(a) a todos sus elementos se les puede aplicar la funcin elevado al cuadrado
(sqr ( ) ).
(b) a todos sus elementos se les puede aplicar la funcin sucesor (succ 0 ), ex-
cePto al ltimo.
(c) todos sus elementos tienen un predecesor y un sucesor'
(d) a todos los elementos se les puede asociar un nmero de orden.

7. El tipo de datos define:

(a) nicamente los nmeros y caracteres del teclado'


(b) ios valores booleanos TRUE y FALSE.
*lc) un rango de vaiores y las operaciones que se pueden realizat con elios.
(d) Ias funciones predefinidas que se pueden utilizar en Pascal.

2.8"2 Soluciones
l. La (b) y la (c) son correctas. La (a) es de tipo integer ya que por las prioridades
de los operadores

(3+2) - 5,
5 DIV 2 = 2,
2*5=10

que es un nmero entero. De otra manera,


(integer+integer) 3 intsgs,
integer DIV intege 4 intsgsr,
CursrroNps DE TrPo rEsr 31

integer * integer In6gs.


-
La (b) es de tipo real ya que
(integer+integer) : intggs,
integer DIV intege ==} fnlsgs,
integer + real ==; s].
La (c) int.eger / integer =:$ sl ya que el operador I acfita sobre reales (se
producen dos conversiones integer a real) y da como resultado un nmero real.
La expresin (d) es de tipo boolean.
2. La(a) y la (b) son correctas. La (a):
(20<4) + FALSE Y

FALSE<>TRUE =+ TRUE.
La (b):
NOT TRUE + FALSE.
FALSE OR FALSE =3 p-,{lp y
FALSE <= FALSE:=+ TRUE.
La (c) es falsaya que 6 DIV 2 + 3y 3 < 1 + FALSE. La (d) es falsatambin.
ya que ORD('a') < 25-5 (nmero de snbolos en ASCII) y 255 + l0 > -500..+
FALSE.
3. La (b) es correcta.

4. La (b) es correcta. De acuerdo con las prioridades de los operadores


(2*3)=6,
(314 DIV l')=44,
ORD(valor)=1.
l*4=4 y
6+44-1=46.
5. La (a) y la (c) son correctas. El operador = en Pascal sirve para comparar dos
expresiones del mismo tipo. Est sobrecargado porque acta sobre varios tipos de
datos. Es capaz de comparar enteros. reales. caracteres y booleanos. Y los datos
se encuentran a ambos lados del operador. por lo que tiene notacin infija.
6. La (b) y la (d) son correctas. La (a) es incorrecta ya que la funcin sqr0 solo
admite operadores de tipo real e integer y el tipo real no es ordinal. Adems no
admite operandos de tipo carcter o booleanos. La (c) tambin es incorrecta ya
que el primel'elemento no posee antecesor y el ltimo elemento no posee sucesor.

7 . La (c) es correcta. Ver seccin 2.2.

,.1
-rl Br-Brrnxros ssrcos on P.sc'r-

2.9 Problemas

2.9.1 Expresiones

1.x=y
2. odd(k) 0R odd(succ(k))
3.P = rRue
4.10DIv3=10/3
5.p , succ(p)
6.p=qORr
7. odd(n* (n-1) )

8. ord('b') - ord('a') > 0

2.9.2 Tipo y valor


Calcule el tipo de datos y el valor que devuelven las siguientes expresiones (si son coffec-
tas):

1. MAXINT _ (I{AX]NT + 1)
2. t5 Drv 2

3. 15 MoD 2

4.7s I 2

5. abs (-MAXINT)

6.sqrlsqrt(23 + 2))
-. :::: -sq:{sqrt (23 + 2))
i. -:: s:,sqr(2))
lr.:::'l:,./5-6*3+10)
__
," _ r =*r;pf3))

si,nucticos del siguiente programa:


PRoBLEMAS 33

{r} PROGRAM erroR


{z {'Esto es un ejemplo BEGIN UNO,}
f: VAR
IJ
It a1pha, Beta, Rho
{s :real;
{o Ietra : char;
{t Suma, Resca, mult, div: inceger
{e CONST annno i=L776;
igi BEGIN
{ro Mult: =3 . 14,.l.
11 readl-n(div) ; ,. ,..) !r,,.,- i..:j"i r'.r
72 ALPkr+.'=3; -\'rl\f.-_-,
13 Beta:=alpha + 1;
t4 Rho:= Beta mod 3;
15 writeln ('EI valor Alphu:3:l-);
L6
".'
writ.eln ('Gamma es negativo,);
{tt wrise* (mult:3 :1) ; u '1-'':',;'',
{re letra:='5' ;
{rs suma: =letra+45; X- ?"
{zo anno:= annO+1;
{zt END,

2.9.4 Escritura
Qu observar en pantalla cuando se ejecuten por separado los siguientes fragmentos
de cdigo?

1. a : = 23 .456; Ltn C i ! .,{.

writeln (a:8:2) ,.J, t'*'"

2. writeln\'Esta frase se mostrar por pantalla,);,


write (,y est.a tambin,) ; f ( ,, "r.4
write('Final' :6) ; "7 i1 e:\o [or'*'o'f-; Ht':'u1
^ /f3
.'!' , f\ it t
r r'-
r' f.
!-/ 1.,/ {/
3. writeln (6 * 7 + 3:41; r,ift'Qb l,( \''
write (4e-3:2:4) ; 1- - t- t'.'
writeln (71:8) ,WVV:\VYq\ - '; yctroo4W
d := 37.5;
writeln (d) ; ,,.,
Lr> *iz
34 Er.nmnuros nsrcos or P.scnr-

2.9.5 Lectura
Sea el siguiente programa en Pascal. Realice una traza
completando las columnas vacas
de la tabla 2.1 2 teniendo en cuenta las entradas que
introduce el usuario.

PROGRAM Test;
VAF
d, b, c: integer;
d: real;
1, m, n: char;
BEGIN
{ii
t-l read(}, a);
{ii }
L -- l
readln (b, d, m) ;

t, {iii} read(n, c) ;
{ i"} readln;
{"} readln(a, b, c);
{"i } read (d) ;

END.

Instr a b c d I m n Entrada Salida


'l ..| ) :'l .t l
0 'l
(r' 'l L' l,' (,' l,
i 5 a a5 l5 <'
ii hola <--
iii 31 43 57 .-
iv
10 20 80,-
v1 0.3e4 <-

Tabla2.l2: Lectura

2.9.6 Algoritmo radianes Y grados


en radianes a grados
Escriba un algoritmo que convierta medidas angulares expresadas
sabiendo que 1 raclian = 360/(2"|J) grados. Escriba otro
algoritmo que realice la conver-
sin inr ersa.

2,9.7 Programa radianes Y grados


expresadas en radianes
Escriba un progralra en Pascal que convierta meclidas angulares
otro programa que realice
a grados sabiendo que 1 radian = ool(z"D grados. Escriba
la conversin inversa.
Pnonr,BnrRs 35

2.9.8 Segundos
Escriba un algoritmo y un programa en Pascal que calcule el nmero de segundos que
hay en una edad expresada en aos. das, horas, minutos y segundos.

2.9.9 Cilindro
Escriba un algoritmo y un programa en Pascal que calcule el rea y el volumen de un
cilindro que tiene de radio y altura dos nmeros enteros introducidos por teclado.

2.9.10 Ecuacin de segundo grado


Escriba un algoritmo y un programa en Pascal para resolver una ecuacin de segundo
grado. Deber permitir leer desde el teclado los coeficientes a2. at y a6 de un polinomio
de segundo grarlo a2x2+ a1x *o y despus debe escribir por pantalla el polinomio con los
coeflcientes. A continuacin debe pedir un valor para x y escribir el valor del polinomio
para esa x. Se supone Que a2, al Y a son enteros. Un ejemplo de1 flncionamiento del
programa es el siguiente:

Escribe los coeficientes t 2 3 (INTRO)


El polinomio es Lx^2 + 2x + 3
Dame un valor para x: 2 (INTRO)
P(2) = 11

2.9.11 Hern de Alejandra


La siguiente frmula (de Hern de Alejandra) expresa el valor de la superficie S de un
tringulo cualquiera en funcin de sus lados a.b,c.

afb*c / ctib*r'
2 t, (2.t)

Escriba un algoritmo y un programa en Pascal para obtener la superficie a partir de


esa fiirmula evitando el clculo repetido del semipermetro.

2.9.12 Carrera de caballos


Las apuestas en las cafferas de caballos se efectan casi siempre segn el sistema de
apuesta mutua en el que el total del dinero apostado, menos un porcentaje para los admi-
nistradores y el gobierno, se divide entre los que apostaron a los tres primeros caballos
ganadores en proporcin a las cantidades apostadas.
Antes de que el dinero se distribuya a los ganadores, el gobierno se queda con un
l4Vo y los operadores del hipdromo con ungVo; la bolsa (el dinero restante) se divide
entre los apostantes ganadores como sigue: 50% se reparte entre los que apostaron al
Er,rtrnuros nsrcos n P.sclr-

que lleg segundo y 207c a los que


caballo ganador, 30% alos que apostaron al caballo
se paga en proporcin
uporr".on al que lleg tercero. Dentro de las anteriores categoras
a las cantidades que apostaron. Para poder hacer
el clculo de los resultados se debe
(la recaudacin) y la cantidad
conocer (datos e entrucla) el total del dinero apostado
el programa pedir tambin
total apostacla a cada uno de los caballos ganadores. Aparte
para presentar los resultados'
los nmeros de identificacin de los 3 caballos ganadores
el importe que se deber
Escriba un algoritmo y un programa en Pascal que calcuie
tres primeros caballos ganadores'
pagar a un apostador que apueste 20 euros a uno de los
caballos ganadores as como la
se debe generar una lista con el nmero de los tres
caballo'
cantidad a pagar por cada 20 euros apostados a cada
"razonables" (cantidades apostadas
Se supondr que el usuario introduce canticlacles
a los tres caballos ganadores'
positivas, importe total apostado > suma cle las apuestas
etc. ).

2.9.L3 TransPortes
para repartir sus productos' En
una empresa de transporte posee una flota cle camiones
en kilmetros. los litros de -oasolina
cada viaje. el concluctor anota la distancia recorrida
del camin' Para realizar
usados. el coste de la gasolina y los costes de mantenimiento
para cada camin y para cada
la contabilidad, eI controlador necesita calcular y registrar
viaje y el coste por kilometro'
viaje. los kilmetros recon'idos por litro, el coste total clel
para un camin y un viaje
Realizar Lln programa en Pascal que lleve a cabo estos clculos
adecuado a las salidas)'
y los presente de manera fcil de entender (clando el fbrmato

2.9.14 A maYsculas
y el programa imprima
Realice un programa que picla al usuario una letra minscula
dicha letra en mayscuias. Se suponclr que el usuario
introduce una letra coffecta (en
minscula y sin acento).

2.10 Soluciones

2.10.1 Expresiones
Carac-
l. Es corecta si ios tipos de datos que se comparan son: Boolean=Boolean'
Entero=Real. El valor ser
ter=Caracter.Real=Real, Entero=Entero, Real=Entero,
lilfsilasclosvariablescontienenelmismovaloryFALSEenelcasocontrario.
l. E,ccorecta si k Entero. El resultado es siempre TRUE'
Es correcta si p Boolean y el valor es TRUE si p vale
TRUE'
l.
-1. La expresin es correcta y el valor es FALSE'

5.EscorectasipBooleanopCaracteropEntero,elresultadoesFALSE.

L
Sor-ucrouns JI

6. En Pascal estndar es correcta si p, q y r Boolean. El valor resultante es TRU: sr


p vale TRUE y q o r valen TRUE, o bien si p vale FALSE y q y r valen FALSE. Y el
resultado es FALSE en el resto de casos'
Es comecta si n Entero y el resultado es FALSE.

Es comecta y el resultado es TRUE.

2.10.2 Tipo y valor


1. La expresin es errnea ya que se produce un desbordamiento del rango de los
enteros (1,axtt'lt + t).

2. La expresin es entera y el valor que devuelve es 7'

J. La expresin es entera y el valor que devuelve es 1.


4. La expresin es real y el valor que devuelve es 7.5.

5. La expresin es entera y el valor que devuelve es l4MlNT.

6. La expresin es real y el valor que clevuelve es 25'0.

1. La expresin es errnea debido a que el operador pred solo acta sobre tipos
ordinales y la expresin ( -sqr (sqrt (23+2) ) ) es de tipo real'
8. La expresin es entera y el valor que devuelve es I 7.

9. La expresin es real y el valor que devuelve es -12.0'

10. La expresin es real y el valor que devuelve es 6.0.

2.10.3 Sintaxis
{r} rnocnaM erroR
Contiene un error ya que falta ; aI final.

lz) l'Esto es un elemplo BEGIN END'l


Es correcta.

{ri
L'l
rnp
Es correcta.

{+) alpha, Beta, Rho


lf t .vn1.
IJJ
Ambasson correctas. 0bservac in : No se produce error pero sera
una mala prctica de escritura.

{e} tetra:char;
Es correcta.
r38 ELEMENTOS BSICOS DE PASCAL

{r} Resta, muIt, div: integer


Suma,
Contiene dos errores: div no es un identificador v1ido y
falta ; al final de Ia linea.

{e} cottsr anno =Ll76;


Es errnea ya que Ias constantes se definen con el signo ='
Debera haberse definido antes que las variables/ pero no
produce error de compilacin por cambiarse eI orden'

f o \ orr:rrr
l, J ulurr!
Es correcta.

{ro} uurt --3.L4;


Contiene un error. Mult es una variable entera y se est
intentado dar un valor real.

tr } readln (div) ;
{
Es errnea ya que div no es un identificador vIido. Si se
hubiera cambiado por otro identificador vlido Ia instruccin
sera correcta.
T, ^
j rl I 1

ALPna: =:;
Es correcta.

{ t: } Beta: =alpha + 1;

{ r+ } nno: = Beta mod 3 ;


Errnea ya que mod solo acta sobre valores enteros y
eLd etj redr.

{t } writ-eln t'EI valor es , Alpha:3:1) ;


Es e::::rea -va que no Se cierra con e} apstrofe finat la cadena
'--- -;a-cr s. La forma correcta sera:
:-- --=-:-L 'Et valor es',Alpha:3:1)
-,.:
.

{r6} writeln ('Gamma es negativo') ;

Es correcta.

{rz} writenl (mult:3:1) ;


Contiene dos errores . l^[riteln esta ma1 escrita y adems mult
SolucroNBs

es entera y no puede tener ese formato. La correcta sera:


writeln(muIt:3);
f ro1 f aFr.-,R/.
.- J
Iruj t

Es correcta.

{ rl } suma: =letra+45;
Es errnea. La expresin letra+45 es errnea, ya que intenta
sumar un carcter y un nmero.

i20-| anno:= anno-1;


Contiene un error al intentar cambiar el valor de una constante.

{zr} ruo
Contiene un error. Falta un punto final.

2.10.4 Escritura
Si el carcter b representa un espacio en blanco, se mostrar por pantalla:

l. bbb23 .46

Est.a frase se mostrar por pantalla


y esta tambin Final

3. bb4 5

0.004Obbbbbb77
3.7500000000E+01

2.10.5 Lectura
La tabla 2. 13 est completa con los resultados de la traza del programa propuesto.

2.10.6 Algoritmo radianes y grados


Una posible solucin es la siguiente:

RAD]ANES A GRADOS
VAR]ABLES
Grados: numero real;
Radianes: numero real;
IN]CIO
40 ELEMENTOS BSICOS DE PASCAL

I m n Entrada Salida
Instr a b c d
'l :') :') 'l
(r'
;'l ')
b'
;'l
(J'
0 (r' (J'
b' L'
,,) :'l
(,' ;'l ,a, J
'
..)
Ll a5'7 5 +'
I 5 l,' (J'

a i) 5.0
,a, +J 'l hola .-
5 (,' (J'
l1
5 1 1 5.0
,a, J 31 43 51 *'
111
,a, J
lV 5 1 1 5.0
5.0
,a, J 10 20 80 +-
10 20 80
80 0.3e4 'a' +r -) 0.3e4 +-
Vi 10 20

Tabla 2.13: Lectura

Leer radianes; lI
grados=radianes* 18o / i
Calcular grados equivalentes {

Mostrar grados
FIN

GMDOS A RADIANES
VARIABLES
Grados: numero reaf;
Radianes: numero rea];
INIClO
Leer grados; . "^- ,- - al
Calcularradianesequivalentes{radianes=grados*PIl180}
Mostrar radianes
FIN

2.10.7 Programa radianes Y grados


el algoritmo anterior a
para pasar de radianes a grados, basta traducir (implementar)
Pascal:

PROGRAM Radianes2Grados ;

VAR
grados, radianes: real;

BEGIN {Programa PrinciPal}


readln (radianes) ;

grados := radianes * 360 I Q * Pl);


grados, )
writeln(radianes:10:3,, radianes Son,,grados:8:3,,
;

END. {Programa PrinciPal}

i
Sor,ucroNrs 41

Y para pasar de grados a radianes:

PROGRAM Grados2Radianes ;
VAR
grados, radianes: rel;

BEGIN {Programa principal}


readln (grados) ;
radianes ;= grados * 2 * PI I 360;
writeln (grados:10:3, ' grados son ' , radianes: B:3, ' radianes');
END. {Programa principal}

2.f 0.8 Segundos


Algoritmo:

VAR]ABLES
Aos, dias, horas, minutos, segundos: numeros enteros;

IN] C IO
LCCI :no.

^] -^
Leer UI4D, -

LECI horas;
Leer minutos;
LCCI segundos;

Calcular el numero de segundos;


{s egundos =segundos +minutos * 6 0 +horas * 3 6 O 0 +
dias* 3 6 O 0*24 +aos*3 6 5* 3 6 O0*24 )
Mostrar segundos
F'IN

El programa se har pasando este algoritmo a Pascal.

PROGRAM Convers ionAsegundos ;


VAR
anios, dias, horas, min, seg: real;
{oasnnvacrN' Todas las variables se declaran como reales para
que no haya petigro de desbordamiento)

BEGIN {Programa principa}}


writeln('Expresa una edad en aos, das, horas, minutos y',
42 EtBnlnNtos ssrcos or Pa'sclr

' segundos: ') ;


readln(anios, dias, horas, min, seg);
dias := dias + anios * 360;
horas := horas - dias * 24;
min := min + horas * 60;
SeQ := seg + min * 60;
writeln(' son', seg:15, ' segundos');
END. {Programa principa}}

2.10.9 Cilindro
Algoritmo:

CONSTANTES
PI = 3.14;
VARlABLES
Radio: Nmero entero;
A1tura: Nmero entero;
at.'-r^
AI ed : I\ Ll..rCI U ra:'
! Eo- .
7

Volumen:Nmero real-;

]NICIO
Leer eI valor del radio;
Leer eI valor de Ia altura;
Calcular eI area; {area=2*PI*radio*altura}
Mostrar el valor del area;
CaIcular el volumen; {volumen= PI*altura*radio2}
Mostrar e1 valor del volumen;
FIN

Programa en Pascal:

PROGRAI{ Ci L:-ndro;
-: l::-::r:-re PI esta predefinida en eI lenguaje por lo que no
:a:: :a-:a declararla de nuevo)

-:-:
:ij- - alcura: inceger;
-.:aa , ,.:olumen: real ;

:I:::l ;l-lrama PrinciPal]


eI valor deI radio: ')
',,,,'r:itein 'introduce ;
Sor,ucrouBs 43

readln (radio) ;
writeln('Introduce el- valor de la altura:
readln (altura) ;
area := 2 * PI * radio * altura;
writeln('EI area es: ', area:0:0);
volumen := PI * altura * sqr(radio);
writeln('El volumen es: ', volumen:0:0);
ENIJ . tPrograma prlnctpal J

2.10.10 Ecuacin de segundo grado


Algoritmo
VARIABLES:
d2, al, a0: numeros reales;
x, resultadc: numero real;
IN] CIO
Leer los coeficientes a2, aL, a0;
Escribir el polinomio con los coeficientes;
Leer el valor de x;
Calcular el resultado iresultado:=a2*x*x+al*x+aO)
Escribir eI resultado
FIN

El programa se har pasando este algoritmo a Pascal.

PROGRAM PolinomioGrado2 ;
VAR
1, d2, a0, p, x: integer;
BEGIN {Programa principal}
writeln ('Teclea 3 valores enteros correspondientes a los
'3 coeficientes de un polinomio de grado 2: ') ;
readln(a0, d1, a2\;
writeln('EI polinomio es ', d2, 'x^2+' , aI, 'x+' , a0);
write('Teclea un valor entero para x: ');
readln (x) ;
p:=a2 *sqr(x) +a1 *x+a0;
writeln(' E] valor de P(', x,') es: ', p);
END. {Programa principal}

2.l0.ll Hern de Aleiandra


El algoritmo es el siguiente:
-r-- ET.NUBqTOS SSTCOS DE PASCAL
44

VARIABLES
, b, ct s/ aux:numeros reales;
INICIO
Leera,bYc;
Calcular aux;
J",,--/:+h+c)
"' l2
esLe valor se d'enomina semipermetro)
ldu^-\ur!
Calcular S;
(vaux* (aux-a) * (aux-b) * (aux-c) ) }
,

{S= naiz cuadrada


Mostrar S;
FIN

El Programa en Pascal:

PROGRAM SuPerf icieDeTriangulo ;

VAR
- 1^ qeminerimetro, superficie: real;
<tt Pt u, uuLLr!.!'

F,trcrN { Proqrama Prrnc iPa} )


a"
write('Escrrbe tres longitudes correspondientes
' los tres lados de un tringulo: ' ;
)

readln\?, b, c\;
semiperimetro := (a + b + c) I *
(semiperimetro - a) *
superficie: = sQrt (semiperimetro *
- b) (semiperimetro
(semiperimetro
11:3 ) ;
writeln ('La superficie es: ' ' superficie:
END. {Programa PrinciPa}J

2.10.12 Carrera de caballos

Algoritmo:

CONSTANTES
e1 14%)
PARA_GOBIERNO=0.14; {UI gobierno se queda con
PARA_HIPODROMO = 0.09; {rr nipoaromo con ef e%)
PARA GANADOR = 0'5; {lara
el ganador un 50%}
i*"-ttr = o.r, in"' eI sesundo un un
3o%)

PARA TERCERO = 0.2; ie"u eI


tercero 20?)

apUusfa = 20; {eara eI calculo de


dinero por cada 20 eurosJ

VARIABLES
LotalAPostado, totalPrimero, totalsegundo'

\
T
Sorucroqus 45

totalTercero: numeros enteros;


apPrimero, apSegundo, apTercero: nmeros enteros;
{apuescas a los caballos}
paraRepartir: numero real;
numPrimero, numSegundo, numTercero: nmeros enteros;
{ttmero de los caballos ganadores}
ganaPrimero, ganaSegundo, ganaTercero : nmeros reales;
{Oinero que ganan los apostantes a los caballos ganadores}

-NICIO
Leer rotalApostado;
Leer numPrimero y apPrimero;
Leer numSegundo y apSegundo;
Leer numTercero y apTercero;
Calcular el dinero que se reparte;
{paraRepartir: = totalApostado - tota}Apostado*PARA GOBIERNO
totalAposLado* PARA_HI PODROMO i
Calcular el dinero para los que han apostado al prmero ;
{totalerimero := paraRepartir * PAM_GANADOR}
Calcular eI dinero para los que han apostado al segundo ;
{totalsegundo := paraRepartir * PAM_SEGUNDO}
Calcular el dinero para 1os que han apostado aI tercero ;
{total.Tercero := paraRepartir * PARA_TERCERO}
Calcular el dinero que gana una persona que haya apostado 20
euros al primero;
{ganaPrimero := totalPrimero*APUESTA/aplrimero} ;
Calcular eI dinero que gana una persona que haya apostado 20
euros a1 segundo;
{ganaSegundo : = totalsegundo*APUESTA/apSegundo} ;
Calcular el dinero que gana una persona que haya apostado 20
euros aI tercero;
{ganaTercero := totalTercero*APUESTA/aptercero} ;
Mostrar numeros de caballos ganadores, {numPrimero,
numsegundo, numTercero) y Io que gana cada caballo
{ganaPrimero, ganaSegundo, ganaTercero}
FIN

Programa en Pascal:

PROGRAM ApuestasCabal los ;

{Untrada: dinero total apostado, los nmeros de identificacin


de los 3 caballos ganadores y J-a cantidad apostada a cada uno)
46 EIruBNros ssrcos DE PASCAL

{Onetivo: calcular eI importe que se deber pagar a un


apostador que apueste 20 euros a uno de los Lres primeros
caballos ganadores. Antes de que eI dinero se distribuya a 1os
ganadores, eI gobierno se queda con un L4% y los operadores
del hipdromo con un 9?; Ia bolsa (e1 dinero restanLe) se
divide entre los apostadores ganadores como sigue: 50? a los
que apostaron al caballo ganador, 30? a 1os que apostaron a1
caballo que lleg segundo y 202 a los que apostaron al que
tleg tercero. Dentro de las anteriores categoras se paga en
proporcin a las cantidades que apostaron.)
{satiaa: La salida ser una lista de los tres caballos y Ia
cantidad a pagar por cada 200 euros apostadas a cada caballo)

CONST
PARA_GOBIERNO = 0.14; {eI gobierno se queda con e1 14?}
PARA*HIPODROMO = 0.09; {rf nipOaromo con eI 9?}
PARA_GANADOR = 0.5; {nara eI ganador un 5O?}
PARA*SEGUNDO = 0.3; {fara el segundo un 30%}
PARA_TERCERO = 0.2; {lara el tercero un 2O?;}
APUESTA = 200;

VAR
totalApostado, premios, apuestaPrimero: real;
paraPrimero, apuestaSegundo, paraSegundo,
apuestaTercero, paraTercero : real ;
premioPrimero , premioSegundo, premioTercero : real ;
idPrimero, idSegundo, idTercero: integer;

BEGIN {Programa principal}


write('escribe el total del dinero apostado: ');
readln (totalApostado) ;

write ('escribe la identificacion para e1 7,2,3: ') ;


readln (idPr:-mero) ;
:=al-: - r-::;undo\ ;

:=r:-:- _jlercero) ;
,,,--:= '=::ribe la cantidad apostada a cada uno: ') i
: =, : -:-
': ::staPrimero / apuesraSegundo, apuestaTerCero)
*
;
:i:.:-.s := totalApostado - totalApostado PARA_GOBIERNO -
totalApostado * PARA_HIPODROMO;
:::al:-:::19 1= premios * PARA_GANADOR;
c=:=:=:*:jc ;= premios * PARA SEGUNDO;
ia:a-..:=re '= premios * PARA TERCERO;

\
Sor,ucroNBs 11

premioPrimero := paraPrimero * APUESTA / apuescaPrimero;


*
premioSegundo := paraSegundo APUESTA / apuestaSegundo;
premioTercero := paraTercero * APUESTA / apuestaTercero;
writeln('Por cada',APUESTA,' euros, e1 que ha apostada d',
idPrimero:2, ' recibe: ' , preml-oPrimero l :2) ;
writeln('Por cada',APUESTA,'euros, eI que ha apostado ',
idSegundo:2, ' recibe: ' , premioSegundo :1 :2) ;
writeln('Por cada ',APUESTA,' euros, eI que ha apostado d',
idTercero:2, ' recibe: ' , premioTercero :7 :2) ;
readln;
LNIJ. t Programa prlncrpal i

2.10.L3 Transportes
Se necesita saber:

o Litros de gasolina consumidos en el viaje.


o Distancia en km. recoridos en todo el viaje.
o El dinero que ha costado los litros de gasolina.
o El dinero gastado en mantenimiento.
Los resultados que se esperan obtener:

o Los km. recoridos por litro de combustible.


o El coste total del viaje.
o El coste por km recorrido.

PROGRAM EmpresaCamiones ;

{fntrada: distancia recorrida en km., litros de gasolina


gastados en el viaje, coste de los litros de gasolina,
cosles de mantenimientc de1 camin)

{Proceso: calcular para cada camin y cada viaje, los km.


por litro, el coste total de} via'je y e1 coste por km.)

{SafiAa: La saliCa ser una lista que muestre los km. por
litro, el coste total y el coste por km.)

11 D

distanciaTotal, costeMantenimiento, costeGasoiina: real;


litros, kmlitro, costeTotal, costeKm: real;'
BEGIN {Programa principal}
ELEMENTOS BSICOS DE PASCAL

write('Escribe la distancia total recorrida:


readln (distanciaTotal) ;

write('Escribe los litros de gasolina usados


readln (Iitros) ;
write('Escribe e} gasto en gasolina: ');
readln (costeGasolina) ;

write ('Escribe el gasto en mantenimiento: ' ) ;


readln ( costeMantenimiento ) ;
kmlitro := distanciaTotal / Iitros;
CosteTota]:=Costecasolina+costeMantenimiento;
costeKm := costeToLa,l I distanciaTotal;
writeln ('El camin recorre ' , kmlitro:0:2 '
' kilometros Por litro ') ;
writeln ('EI coste total deI viaj e es ' ' costeTocal :0 :2
'
' euros' ) ;
writeln 'EI coste por kilometro es ' ,
( costeKm: 0:2
'
' euros' ) ;
-o.ll n.

END. {Programa PrinciPa}}

2.10.14 A maYsculas
PROGRAM CambioMaYusculas ;
{Ontrada: una letra minscu1a}
a mayscu1a}
{Proceso: Cambiar una letra minscula
{satiaa: La salida ser la leLra mayscula}
CONST
DIFERENCIA = ord('a') - ord('A');
VAR
mnuscula, maYuscula: char;
BEGIN {Programa PrinciPal}
write('Escribe Ia letra en minscula: ');
readln iminuscula) ;
:lt-"-s--:-a := chr(ord(minusculal - DIFERENCIA) ;
',';:r::-: '-a letra en mayscula es: ' ' mayuscula) ;

-- - - i - -

:l:1. l::g:ana PrinciPaI)


Captulo 3

Instrucciones estructuradas

De fbrma simplificada se puede ver la escritura de un programa como Ia especificacin


de una secuencia de instrucciones. Hasta ahora, las instrucciones que se han visto estn
centradas en procesar datos y no permiten que el programador especifique varios flujos o
caminos de ejecucin. A menudo. se necesitan describir varios bloques de instrucciones.
y dependiendo del estado de la mquina en tiempo de ejecucin, elegir un bloque u otro.
Los lenguajes de programacin proporcionan instrucciones que permiten controlar el
flujo de ejecucin del programa. En este captulo se estudiar las instrucciones que per-
miten: agrupar varias instrucciones en un bloque (instruccin de composicin), redirigir
la ejecucin del programa a Lln bloque en concreto (instruccin de seleccin) y redirigir
la ejecucin a un bloque durante un cierto nmero de veces consecutivas (instruccin de
iteracin).

3.1 Instruccincompuesta
La instruccin compuesta permite describir un bloque de instrucciones. En Pascal em-
pieza por la palabra BEGIN, seguida de una secuencia de instrucciones separadas por
e1 carcter ";" y flnaTiza con la palabra END. Esta instruccin se suele utilizar en com-
binacin con instrucciones de seleccin y de iteracin (que se vern en las siguientes
secciones de este captulo). La figura 3.1 muestra dos bloques anidados, donde el bloque
I .1 es una instruccin compuesta que forma parte del bloque 1.

3"2 Kaasa:nxce&Eaes de seeeax?

Este tipo de instrucciones son estructuras de ccntroi que perrniten eiegir ciinmieameilte
(en tiempo de ejecucin) entre ciil'erentes secuencias de instrucciones. Fascal propor-
ciona dos instrucciones de este tipo: IF' y CASE.

49
50 INSTRUCCIONES ESTRUCTURADAS

bloque 1: 4 instruccianes
BEGIN {bloque 1}
wrrte{'Introduzca x. y');
readln(x, y).
BEGIN {L,lcque 1 1}
AUX,=X, _= _.-I
"'
Y.=OU i
END; {bloque I 1}
writeln{'x, Y =',x,',',Y)
END; {bloque ll- |

iul"q*rc
Figura 3. 1 : Instrucciones compuestas anidadas.

La instruccin IF
La sintaxis de esta instruccin es la siguiente (las expresiones entre corchetes son opcio-
nales):

IF <Expresin Booleana> THEN


< Inst rucc in1 >
IELSE
< Instrucc in2 >l
El comportamiento del programa en tiempo de ejecucin ser el siguiente: si <Expre-
sin_BooIeana> tiene un valor TRUE se ejecuta la <Instruccin1>, en caso contrario
se ejecuta <Instruccin2>. El siguiente fragmento de cdigo muestra un ejemplo de
una instruccin IF, donde se evala la expresin x>y y dependiendo del resultado se rea-
liza una instruccin compuesta u otra.

:!GIN
-=aJ--- ^t I t

I
::--_-,
,. -t.

',,,':-:ein ('El mximo es ' , max) ;

at,- -:.,
: -s:
::: -:.
I
I tl
i;:r:e-n('81 mximo es ', max);

I
i:

t
INsrnuccroNES DE snrBccrN 51

uun lnrcnl
END;

La instruccin CASE

La sintaxis de Ia instruccin CASE es la siguiente: comienza con la palabra reservada


CASE, seguida de una expresin de tipo ordinal y la palabra 0F y termina con END. Entre
OF y END se especifica una secuencia de etiquetas e instrucciones.

CASE <expresin_selectora> OF
<etiquetal> : <Instruccin1>;
<etiqueta2> : <Instruccin2> ;

<etiquetaN> : <InstruccinN> ;
IELSE
< InstruccinELSE> ;l
END {CASE}

El comportamiento del programa en tiempo de ejecucin ser el siguiente: compa-


ratelresultado de evaluar <expresin_sefecEora> con los patrones especif,cados en
<eLiqueLal> ,.., <eLiquetaN> y si hay coincidencia con alguno de ellos se ejecutar
su coffespondiente instruccin y finalizar la instruccin CASE. Si no hay coincidencia
con ningn patrn se ejecutar <InstruccinELSE>.
Las expresiones selectoras deben ser de tipo ordinal (integer, char, boolean o
enumerado) y las etiquetas tienen que tener un valor constante (constantes, literales,
listas de constantes o subintervalos). La parte opcional eLSs de esta instruccin (entre
corchetes) slo se puede uittlizar con compiladores que acepten la especificacin Turbo
Pascal. El siguiente ejemplo muestra una insuccin CASE donde se especiflcan rangos,
una constante y una lista de constantes en el patrn de la etiqueta, y se usan cuatro
instrucciones simples y una compuesta.

CASE opcion OF
1. .15: writeln ('Primera Quincena' ) ;
76 t writeln ('Primera Prueba') ;
l1 . .29: BEGIN
writeln ('EsLo es una instruccin compuesta') ;
writeln ('Segunda Quincena' )

END;
30,31: writeln ('segunda Prueba' ) ;
ELSE
writeln('valor erroneo' ) ;
END icASE)
52 INSTRUCCIONES ESTRUCTURADAS

3.3 Instrucciones de iteracin


de una instruccin o bloque
Este tipo de instrucciones permiten describir la ejecucin
dependiendo de una
de instrucciones durante un cierto nmero cle veces consecutivos
condicin. Estas instrucciones se componen de:

condicin del bucle: es la expresin que determina el nmero de iteraciones'

se repiten en cada iteracin'


cuerpo del bucle: son las instrucciones que
las instrucciones del
Con la palabra iterar se denota la accin de ejecutar repetidamente
stos pueden ser de tres tipos:
cuerpo del bucle. Atendiendo a la conclicin del bucle'
WHILE. REPEAT Y FOR.

Instruccin WHILE

La sintaxis de esta instruccin es la siguiente:

WHILE <exPresin-booleana> DO

< instruccin>

sea cierta
La semntica de esta instruccin es: mientras que <expresin-booleana>
se ejecuta <instruccin>. Este tipo de bucles se
denominan bucles preprobados (son
el cuerpo) y permiten la
bucles que primero se er,ala la condicin y luego se ejecuta
(si la primera vez que se evala la
posibilidad de que su cueryo no se llegue a ejecutar
el clculo de la suma de
condicin es falsa). El siguiente fragmento de cdigo muestla
los n primeros nmeros meciiante un bucle WHILE. La
variable suma almacena la suma
el nmero a sumar'
parcial en cada iteracin rlei bucle y 1a variable contador almacena

BEGrN ibroqueJ
::eacln iir :

-.:-aa):: := -;
,:-- E concador <= n D0

--Il-\r
SUmA "= SUTL -' COnCadOr;
contador := conLador + -L

:1,: : ' ,l^iHILE)


:,;:---=i:r (suma) ;
. ^dl .^ \
a,i! ---!ue1
IusrnuccroNES DE rrnucrN 53

Instruccin REPEAT

La sintaxis de esta instruccin es la siguiente:

REPEAT
<instruccin1>;

<instruccinN>;
L\ITIL <expresin booleana>
La semntica de esta instruccin es que se ejecutarn las instrucciones del cuerpo del
bucle hasta que <expresin_booleana> sea cierto. Este tipo de bucles se denominan
postprobados (son bucles que primero ejecutan las instrucciones de su cuerpo y luego
comprueban su condicin de finalizacin) y aseguran que su cuerpo se ejecutar siempre
(como mnimo una vez). A continuacin se muestra un fragmento de cdigo que utiliza
esta instruccin.

BEGIN {nroque}
readln (n) ;
qllm: '= n'

contador : = 1;
REPEAT
Suma := stlllld + contador;
conLador := contador + 1
UNTIL contador > n;
writeln ( suma)
eND {b}oque}

Instruccin FOR
La sintaxis de esta instruccin es la siguiente:

FOR contador:= <expresin inicial> TO <expresin final> D0


< instruccin>

El comportamiento del programa en tiempo de ejecucin ser el siguiente: al comenzar


1a ejecucin del bucle se inicializa la variable contador con el valor de <expresin_ini -
cial>. En cada iteracin se ejecuta <instruccion> y a la variable contador se le
asigna su valor sucesor (succ (conLador ) ). La ejecucin del bucle termina cuando el
valor de la variable coniador es igual a <expresin_f inal>. El siguiente fragmento
de cdigo muestra ei uso de 1a instruccin FOR para calcular la suma de los nmeros de
1an.
BEGIN t0loque-l
-^-.1't - /-
ruuurrr \rrl\ ,
54 INSTRUCCIONES ESTRUCTURADAS

.- n.
bULllA -_ u,
FOR contador := 1 T0 n D0
suma := suma + contador;
writeln (suma)
END; {nfoque}
Las expresiones <expres in-ini -
La variable contador slo puede ser de tipo ordinal'
de la variable
cial> y <expresin_fina1, deben sei tipos compatibles con el tipo
contador.
PascalproporcionaunaversindeFoRqueenlugardeincrementarlavariable
la siguiente (note que cambia
contador en cada iteracin la decrementa. Su sintaxis es
la palabra reservada TO por DOWNTO):

FOR indice:= <expresin-inicial> DOWNTO <expresion-final> DO

< instrucc in>

3.4 Recomendaciones
a la hora de utiltzar instrucciones
Algunas recomendaciones prcticas que se proponen
estructuradas son:

1. Sangrar las instrucciones dentro de cada rama de


la instruccin rF y del cuetpo
delosbucles.Elcompiladorignoraestossangrados,perolaclaridadquesegana
para la interpretacin del programador es notable'
(especialmente til cuando 1a longitud
2. comentar el fin de la instruccin compuesta
del bioque sobrepasa el tamao de la altura de la
pantalia)'
ramas de 1a instruccin IF'
3. No repetir instrucciones coillunes en las clistintas
de valores trooleanos: se asigna 1a
4. No utilizar instrucciones trF para la asignacin
expresin booleana directamente a la variable'
CASE cuando 1a decisin depende de una misma
expresin
5. Utilizar instrucciones
haya aiternativas mlti-
selectora. Se utiiizarn instrucciones rF anidadas cuando
ples que dependan de selectores diferentes'

6.Elegirlainstrucciniterativaadecuadasiguiendolassiguientesreglas:

o Si se conoce a' priori ol nmero


^''in,i el rle-veces que se va a eJe(lutar el cuerpo del
nrmern de
bucle, se utilizar una instruccin FOR'
o Si no se conoce el nmero de veces que seI va a ejecutar el cuerPo del bucie
se utilizar una
pero s se sabe que colrlo mnimo se va a ejecutar Ltna vez,
instruccin REPEAT.
o En e1 resto de los casos se utilizar una instruccin WHILE'
Cunstro{Bs DE TIPo TEST 55

3.5 Cuestiones de tipo test

3.5.1 Enunciados
Las siguientes cuestiones pueden tener una o ms respuestas correctas:

1. La Instruccin2 del siguiente cdigo se ejecuta:

IF Condicin1 THEN
IF Condicin2 THEN
Instruccin1
ELSE
InsLruccin2

(a) Cuando Condicin1 se evale a f aIse, independientemente de lo que valga


la Condicin2.
(b) Cuando Condicin1 se evale a true y Condicin2 se evale a false.
(c) No se ejecuta nunca porque produce un error de compilacin (faltan el punto
y coma despus de la Instruccin1).
(d) Cuando Condicinl y Condicin2 se evalen a false.

2. Se pretende que el siguiente fiagmento de cdigo multiplique un cierto nmero de


veces el valor de una variable. Qu ocurrir si ejecutamos el cdigo?

VAR
varResul: -nLeger;
varlndi : r:e I;

BEG]N
varRes.rl . - 1,
FOR varindi := 1 T0 3 D0
varR.esul := varResul * 2;
writeln (va.rResul ) ;
END.

(a) Iinprimir por pantalla el nrnero E.


(b) l{o imprimir por pantaiia ningn restiltado por que ia instruccin FOR cons-
tifuye un bucle inXinito"
(c) Xmprimir por pantaila el res.iliado de la expresin varResul * 2, el cual
ser 2 ya que varRe su1= l.
(d) No irnprimir nada por pantaila ya que no se podr ejecutar porque ei com-
pilador dar un error.
56 INSTRUCCTONES ESTRUCTURADAS

de instruccin iterativa' dejando al


3. El compilador de Pascal admite varios tipos
criteriodelprogramadorlaeleccindelamisma.Cuandosesabedeantemanoque
eicuerpodelbuclehadeejecutarsea[menosunaVeZ.unabuenarecomendacin
tcnica es:

(a) Debo usar una sentencia REPEAT'


(b) Debo usar una sentencia WHILE'
(c) Debo usar una sentencia FOR'
(d)Siademsselnodevecesquesevaaejecutarelbucle,entoncesdebousar
la sentencia FOR'

4. ,Cuntas veces se ejecuta


el siguiente bucle?

-'.- ,,
WHILEA<5DO;:
a := a + 1;
(a) 5.
(b) 3.
(c) lnfinitas'
(d) Ninguna.

5. Cuntas veces se ejecuta la Instruccinl del siguiente cdigo?


t\
*? '7
FOR i := 1 TO 5 DO
]F (i > ) THEN \,
IF(i+2*3>B)THEN
Instruccin1

(a)SlounaVeZdebidoaqueelsegundolFestf'ueradelbucleFORy,porlo
tanto, se tealiza una nica vez'
(b)NoseejecutanuncaporqueproduceunelTordecompilacin(faltaBEGINy
:l'T al bucle FOR).
r ) Se ejecuta
c dos veces'
(d) Se ejecuta tres veces'

6. Qu muestra por
pantalla el siguiente cdigo?

I"IAR

a. integer;
char;
Pnosr,rN{as 57

BEGIN
i := 10;
FOR c := 'd' DOWNTO 'a' D0
BEGIN
- := i - i;
write(i:3)
END
END.

(a) Imprimir por pantalla nicamente el nmero 9.


(b) No imprimir por pantalla ningn resultado debido a que la variable conta-
dora c empieza por 'd' y como 'd'>'a' no se ejecuta nin-{una vez la instruc-
cin write.
(c) bb9bb8bb7bb6 (siendo b un espacio en blanco).
(d) No irnprimir nada por pantalla ya que no se podr ejecutar porque el com-
pilador dar un eror.

7. Cul de estas afirmaciones acerca de la instruccin REPEAT es FALSA?

(a) Modela ciclos postprobados y se ejecuta un nmero variable de veces.


(b) Siempre puede ser sustituida por una instruccin WHILE.
(c) Cuando la condicin es cierta termina el bucle.
(d) Se puede sustituir por una instruccin FOR.

3.5.2 Soluciones
Las respuestas correctas son:
1.b.
2.d.
3.a y d.
4.c. Notar que el cuerpo del bucle I/HILE est vaco.
5.c.
6.c.
7.d.

3.6 Problemas
3.6.1 Nivel medio de ruido
Para calcular el nivel de ruido de una calle de una ciudad se realizan 4 medidas, una cada
8 horas, en un punto concreto. Si la media de las medidas del nivel de ruido supera la
mxima admitida (por ejemplo, MAXIMA = 4) signif,ca que el ruido es nocivo para la

J
58 I,{srnuccroNES ESTRUCTURADAS

salud. Escriba un programa que calcule el nivel medio de ruido de una calle y determine
si el nivel de ruido es nocivo o es admisible.

3.6,2 Clculo del prstamo bancario

Un banco antes de conceder un prstamo a 20 aos comprueba los ingresos del solici-
tante. Si los ingresos son superiores a 12000 euros anuales el crdito se concede. Si
los ingresos son inferiores a 12000 euros anuales pero superiores a 10000 euros y est
soltero el crclito se concede. Tambin se le concede si tiene ingresos entre 12000 y
10000 euros y est casado sin hijos. Escriba Lrn programa que pida los ingresos anuales,
el estaclo civil del solicitante y si tiene hijos y diga si se 1e da el crdito o no.

3.6.3 La calculadora
Implemente un programa que simule una calculadora. Mostrar el men siguiente:
l. Sumar
2. Restar
3. Multiplicar
4. Dividir
0. Terminar

El programa deber verificar que se introduce un nmero vlido (del 0 al4). Si se


introduce un nmero errneo nos avisar 1' volver a mostrar el men. Si se lntroduce
un 0 el programa terminar. Si se elige una opcin entre el I y el 4 pedir dos nmeros.
mostrar el resultado dependiendo de nuestra eleccin y volver a mostrar el men.

3.6.4 Esquema de recorrido

Escriba un programa que imprima los 20 primeros numeros impares y sus cuadrados.

3.6.5 Esquema de bsqueda

Escriba un pro-srama que lea y sume hasta que haya sumado 10 valores de datos o hasta
que lea un valor negativo, cualquiera que sea el primer valor.

3.6.6 La hora cada diez minutos


De,sarrolle un programa que imprima la secuencia de todas las combinaciones de hora y
minlltos de un da. La secuencia se comienza a la 1:00 A.M. y terminan a las l2:50 P.M.
La hora se imprime en intervalos de 10 minutos y se debe presentar en forma de tabla de
seis columnas con 24 fllas.
Sor,ucroNBs 59

3.6.7 El mximo comn divisor


Escriba un programa para hallar el mximo comn divisor de dos enteros positivos. El
programa comprobar que son no negativos. Si alguno de los dos es negativo se mandar
un mensaje de aviso y volver a pedirlos hasta que los dos sean positivos.
NOTA: tenga en cuenta la propiedad: m.c.d (A, B) = m.c.d (8, A) y el algoritmo de
Euclides para hallar el m.c.d. de dos nmeros, Dividendo y Divisor, que es el siguiente:

Si Dividendo >= Divisor entonces


m.c.d. (Dividendo, Divisor) = rlr.c.d. (Divisor, Resto)
Si uno de los nmeros es 0 entonces
m.c.d. (Num, 0) = Num
donde Resto es el resto de la divisin entera de Dividendo entre Divisor. Por ejemplo:
mcd(45,130) = mcd(130,45) = mcd(45,40)= 6.140.5) = mcd(5,0) = J.

3.6.8 El nmero perfecto


Se dice que un nmero es perfecto si verifica que la suma de sus divisores (excluido l)
es iguala1. Porejemplo, el nmero 6 es perfecto porque 6:1*2+3, sin embargo
el 16 no1o es porque 16 * 1 +2+ 41 8. Se desea escribir un programa en Pascal que
muestre por pantalla los nmeros perfectos que hay desde eI i al 200.

3.7 Soluciones
3.7.1 Nivel medio de ruido
PROGRAM NivelRuido;
{Ca1cu1a el nivel de ruido y determina su peligrosidad}
{uNtRana, 4 medidas del nivel sonoro}
iSALIDA: Si el nivel es nocivo o admisiblei
I _ ___
-_

CONST
NIVELMAXIMA = 4;
VAR
ruidol , ruido2, ruido3, ruido4 : reI;
media : real;
BEGIN {Programa Principa}}
writeln ('Escribe 1a primera medida: ');
readln (ruidol);
writeln ('Escribe 1a segunda medida: ' ) ;
readln (ruido2);
writeln ('Escribe Ia tercera medida: ');
readln (ruido3);
60 INsrnuccroNEs ESTRUCTURADAS

writeln ('Escribe la cuarta medida: ');


readln (ruido );
media:= (ruidol + ruido2 + ruido3 + ruido4) I a;
writeln ('El nivel med'io de ruido es ', media:0:2);
IF media > NIVELMMIMO THEN
writeln ('Nivel de ruido nocivo')
ELSE
writeln ('Nivel de ruido admisible')
END. {Programa PrinciPaI}

3.7.2 Clculo del prstamo bancario

PROGRAM Banco;
{catcula si se concede un prestamo}
{rurntoa, sueldo, estado civi1, n" hijos}
{salrna, Concesin o denegacin}
CONST
INGRESOS= 12OOO; {ingresos sufic:-entes}
INGRESOSMIN= lOOOO; {lngresos mnimos imprescindibles}
VAR
sueldo: real; {rngresos brutos anuales}
casado: boolean; {estado civi'l),
hijos: integer; {Nmero de hijos)
letra: char;

BEGIN {Programa PrinciPat}


writeln (' sueldo: ' ) ;
readln (sueldo) ;
IF (sueldo > INGRESOS) THEN
writeln ('Se Ie concede eI crdito')
ELSE
IF (sueldo > INGRESOSMIN) THEN

iT,GtI\
':--'e-n ('EsLado civit (s-Soltero' c-casado) ');
::acrn (letra);
.-:,saio : = (Ietra='c' ) OR (letra = 'C') ;
-: l;CT casado THEN
'",:lteln ('Se le concede eI crdito')
:-S E
:r l:ll
writeln ('Numero de hij os I ') ;

:eadlnrhrjos);
Sor,ucroNns 61

rF rhijos = o) THEN
writeln ('Se le concede el prstamo')
ELSE
writeln ('Crdito denegado' )

END {EIse Casado}


END {ELSE IF sue}do}
ELSE
writeln ('CrediLo denegado') ;
readln
END. {Programa principal}

3.7.3 La calculadora
PROGRAM Calculadora;
{Simula una calculadora con las 4 operaciones bsicas}
{ullrnaoa: operacin y operandos}
{Salroa, resultado de Ia operacin}
VAR
vPr
^^^.i^-.
JUrr . ^1"--.
urrq! ,

operl, aper2: real;

BEGIN {Programa principat}


REPEAT
writeln ('1. - Sumar ') ;
writeln ('2.- Restar ');
writeln ('3.- Multiplicar') ;
writeln ('4.- Dividir') ;
writeln ('0. - Terminar ') ;
readln (opcion);
CASE opcion 0F
'!'..' 4': BEGIN
writeln ('Primer operando ') ;
readln (oper1);
writeln ('Segundo operando ') ;
readln (oper2);
END;
' 0' : writeln ('Final' ) ;
ELSE
writeln ('Opcin no es viida');
END; {Case}
CASE opcion OF
' 1' : wriLeln ('La suma es ' , operl+oper2 A:4) ;
INsrnuccroNBS ESTRUCTURADAS

'2',: writeln ('La resta es operl-oper2:0:4);


"
'3': writeln ('La multiplicacin es', operl*oper2:0:4)
'4'i IF oPer2 <> 0 THEN
writeln ('La divisin es i ' , operl/oper2:0:4)
ELSE
writeln ('No se puede dividir por cero');
END; {Case}
UNTIL (oPcion = '0');
-orrl ln .

END. {Programa PrinciPa}}

3.7.4 Esquema de recorrido

esquema algortmicp de rec:crrijo asegura que se procesan todos los


datos de una
El
recor:rido
coleccin. -Bn este problema se ha aplicado un diseo basado en esquema de
porque se necesita procesar todos los elementos de la coleccin (calcular el cuadrado
a

ios 20 nmeros impares). Se ha utilizado un bucle FOR porque se sabe a priori el nmero
exacto de iteraciones (no cambia en tiempo de ejecucin)'

PROGRAM ImPares;
{uscribe los 20 primeros impares y sus cuadrados
usando}
inNtRaoa, i
{sarroa, 20 primeros impares y sus cuadradosi
VAR
cont: integer;
BEGIN {Programa PrinciPa-i
writein ('Nmero, Cuadrado') ;

FOR cont:=0 TO 19 D0
writeln(!*gont+1:4, sqr(2 * cont + 1) :9);
read.ln;
:'-'.J . Progran, princrPa- )

3.7.5 Esquema de bsqueda

El esqtremn algortmico de bsquedapermite localizar un elemento con una ciefiacarac-


terstica en una coleccin sin tener que procesar obligatoriamente todos los
elementos'
procesar
En este problema se ha utilizado un esquema de bsqueda porque no se necesita
los 10 primeros nmeros
todos los datos de 1a coleccin. Es decir, no se necesita sumar
nmero (por 1o
obli-eatoriamente ya que podra haber alguno negativo antes del dcimo
procesar el
que se dejarade sumar). S ettTlizaun bucle REPEAT pofque siempre se debe
primer nmero.
Sor,ucroNns 63

;!.OGRAM SumaNumeros;
Suma los 1-0 primeros numeros o hasta que se introduzca
.rn numero negativo)
:NTRADA: Ios nmeros)
:ALIDA: La suma de los nmeros)
--D

cont, daro/ suma: integer;

::G-LI\ t Programa prlnclpal )


._ n,
.nf .- n'
REPEAT
writeln ('Introduzca Ia cantidad nmero', conL+1,' :');
readln (dato);
IF dALO >= O THEN
BEGIN
Cont := ConL - 1;
Suma := SUITI - dato;
END;
LINTIL (cont >= 10) OR (dato < 0);
writ.eln ('Hay',cont,'numeros y su suma es : ,,suma);
r ed u1ll ;

:-\lJ . tPrograma prrnclpal ,|

3.7.6 La hora cada diez minutos


La variable mediodia indica si la hora es P.M o A.M. El primer bucle tr{HILE imprime
loce horas y se ejecuta dos veces (una para las horas P.M. y otra para A.M.) El segundo
nucle WHILE recoffe los minutos de diez en diez (variable minutos).

:-ROGMM HorasyMinut.os ;
,'rmprimir las horas del da de 10 en 10 minutos)
iuurntna' )
iSalfOa: una tabfa con todas las posibles horas y 10 minutos
del da agrupados en 6 columnas. )
CONST
llopAMAY- ',t .
'
MINUTOSMM= 60;
VAR
hora, minutos: integer;
mediodia: char;
64 INSTRUCCIONES ESTRUCTURADAS

BEGIN {Programa PrinciPal}


hora : = 1;
mediodia := 'A' ;

WHILE (hOTA <= HORAMAX) DO

BEGIN
minutos : = 0;
WHILE minutos < MINUTOSMAX DO {escribe una hora)
BEGIN
write (hora:2,':');
IFminutos=0THEN
write ('00' )
ELSE
write (minutos) ;
write (' ' ,mediodia' ' .M. ');
minutos := minutos + 10;
END; {minutos}
writeln;
hora := hora + 1;
IF (hora > HORAMAX) AND (mediodia='A') THEN

BEGIN
hora: =1;
n'.edrodia:='P'i
END;
END; iwurlnJ
readln;
END. {Programa PrincrPal}

3.7.7 El mximo comn divisor


dividendo
los nmeros son positivos' En la variable
Con el bucle REPEAT se asegura que las sucesivas
realizar
se asigna siempre *uyor de lls dos nmeros. El bucle WHILE
"1 sea cero'
divisiones hasta que uno de los dos nmeros

PROGRAM Mcdiv;
algoriLmo de Euclides}
eI
{ttallar el m.c.d. mediante
inn'tnora, dos enteros Positivos) nmeros)
ir*roo, eI no m.c'd' de los dos
VAR
dividendo, divisor, resto: integer;
auxiliar: integer; {eara hacer el ntercambio}
BEGIN {Programa PrinciPal}
REPEAT {Co*p.'eU' que los dos
son positivos}
SolucroNns 65

write ('Primer numero : ') ;


readln (dividendo) ;
write ('segundo numero : ');
readln (divisor);
rF (dividendo <= 0) 0R (divisor <= 0) THEN
writeln (' deben ser positivos ') ;
LINTIL (dividendo > 0) AND (divisor > 0) ;
IF dividendo < divisor THEN
BEGIN
auxiliar := dividendo;
dividendo := divisor;
divisor : = auxiliar
ulln; {rr}
WHILE divisor <> 0 D0
BEG]N
resto := dividendo mod divisor;
dividendo := divisor;
divisor : = resto
END; {wHiLE }
wrireln 1'EI m. c. d. es: ' , dividendol ;
readln
- NlJ.
tPrograma prrnctpal |

3.7.8 El nmero perfecto


Lr variable indice
(contador del primer bucle FOR) recorre los posibles candidatos a ser
ntmero perfecto que hay del 1 al 200 (comienza en el 2 porque el I sabemos que no es
perf'ecto). Para cada candidato, la variable indiceDiv (contador del segundo bucle FOR)
"-omienza en el
posible divisor mayor excluido 1 mismo y se va decrementando hasta
lle-uar al menor divisor. La variable suma almacena las sumas parciales de los divisores
para cada candidato.

PROGMM NumPef ecto;


icalcular los no perfectos (e} que es igual a la suma d.e sus
divisores excluido l mismo) que hay desde 1 at 200]
lENTRADA: el lmrte de n")
{Sarrna: los no que son perfectos}
CONST
tr4AX= 200; ienrrada)
VAR
indice, indiceDiv, suma: integer; {para conLrol de
bucles y suma parcial)
66 INSTRUCCIONES ESTRUCTURADAS

RrcTN {Proqrama PrinciPali


writeln('los no perfectos de 1 aI ' son: '\

FOR iNdiCC : = 2 TO MAX DO BEGIN "MAx'


{calcular suma de sus divisores}
SUma: =0 ;

{comienza en e1 Posible
divisor mayor excluido 1i
FOR indiceDiv := (indice div 2)
+1DOWNTO1DO
if (indice mod indiceDiv = o) THEN

suma := stl1lld + indiceDiv;


)c
II /e,,m2
\DuLrrq -- indice)
THEN
writeln ( indice) ;
END;
readln;
END. {Programa PrinciPal}
Captulo 4

Subprogramas: procedimientos y
funciones

Se han estudiado las instrucciones bsicas de Pascal: instrucciones de entrada./salida, la


asignacin e instrucciones de control de flujo. Con estas rdenes se forman los progra-
mas. El problema surge cuando hay que enfrentarse a un problema relativamente difcil
o con una solucin extensa. Se puede intentar abordarlo de dos maneras:

o Resolverlo todo alavez. Enseguida se ver desbordado por la cantidad de dis-


tintos subproblemas que se plantean, de las relaciones entre ellos, de detalles que
impiden centrarse en la resolucin global, etc. Si finalmente consigue hacerlo,
tendr un programa principal con cientos o miles de instrucciones, 1o que har que
una simple bsqueda de una variable o de una instruccin sea difcil. Encontrar
un effor o intentar seguir el funcionamiento ser una tarea tediosa.
o Ir paso a paso, utilizando tn
mtodo de diseo descendente, que consiste en des-
componer el problema en partes ms pequeas y sencillas (subproblemas). IJna
vez dividido, se solucionan los subproblemas de forma independiente al resto.
Cuando tenga todos resueltos, se utilizan de manera adecuada y se consigue tener
el problema completamente solucionado. Est tcnica es la ms extendida para
abordar un problema extenso o complejo.

4.1 Diseo descendente


El diseo descendente consiste en la elaboracin de algoritmos por niveles de abstrac-
cin, pasando de una solucin general a los detalles de cada fase. Es decir, el problema
original se divide en varios subproblemas ms simples y si es posible, independientes
entre ellos. Cada subproblema, al ser independiente del resto, se puede solucionar utili-
zando la misma estralegia, es decir, dividindolo en varios subproblemas. Este mtodo
de refinamiento sigue hasta que los subproblemas son lo suf,cientemente simples como
I

61
68 SunpnocnAMAS: PRocEDrMrENTos Y FUNCToNES

sucesivos)'
para hallar un algoritmo sencillo que los solucione (mtodo de refinarnientos
algorit-
Una vez llegado a este punto se escriben subprogramas que implementn estos
para resolver el problema ori-
mos y se cornbinan de manera adecuada en un programa
cada
ginal. Este mtodo se combina con el diseo modular, que consiste en solucionar
un problema
iubproblema de manera independiente al resto, para hallar la solucin a
complejo y/o extenso.
para realizar de manera correcta el diseo descendente y modular de un programa se
han de seguir los Pasos siguientes:
que
l. Escribir un algoritmo, posiblemente con pasos c1e alto nivel de abstraccin,
resuelva el problema. Este algoritmo ser el programa principal'
paso complejo ser
2. Descomponer catla paso complejo en otros ms simples. Cada
un subprograma.
3. Descomponer sucesivamente los pasos ms simples (tambin sern subprogra-
Pascal (o
mas), hasta que la traduccin de los pasos sea "inmediata" al lenguaje
a

cualquier otro lenguaje).


con el pro-
Ntese que los subprogramas se comunican (intercambian informacin)
otros subprogramas. Es esencial definir claramente qu datos se
grama principal o con
van a intercambiar.
stevens w.P., Myers G.J. y connstantine L.L. introdujeron
los conceptos de acopla-
miento y cohesin como mtricas de calidad clel software. Se define
el acoplamiento
entre los distintos mdulos'
como la caracterslica que da e1 grado cie interdependencia
de un m-
La cohesin es la medicla de la fuerza o relacin funcional de los elementos
que lo componen'
clulo, entendiendo por elementos a la sentencia o grupo de sentencias
Los subprogramas deben
a las defrniciones de cirtos o a las llamadas a otros mtlulos.
tener un alto nivel de cohesin y entre ellos un bajo nivel de acoplamiento.

4.2 Subprogramas
para facilitar
La utilizacin de subpoglilmes nos permite agrupar y ocultar infbrmacin
realizar estas tareas
el clesarrollo Y el mantenimiento c1e un programa. Para que se puedan
se cleben curnplir 1os siguientes princrpios:

Principio de mxima localidad: los objetos particulares y necesarios para un


subpro-
(ver apartado 4'6)'
.rr,.,-,,, respecialmente las variables) deben ser locales al mismo

Principio de autonoma de los subprogramas: la comunicacin con el exterior


debe
los subpro-
realizarse exclusivamente mediante parmetros, evitndose dentro de
glIllll\todaref.erenciaaobjetosglobales(verapartado4.6).

Si al hacer e1 cliseo del programa se cumplen esos principios se obtienen muchas


ventaias. entre otras:
SunpnocnAMAS 9

o Dotar al programa principal de una estructura fcil de leer y de entender per-


mitiendo que eI proceso de depuracin y mantenimiento sean ms sencillos de
reaTizar.

o Evitar escribir ttn mismo conjunto de instrucciones en varias zonas del programa
principal.
o Poder trabajar en equipo.
o Verificar la correccin de un subprograma, independientemente del resto de sub-
programas y del programa principal.

Se puede asociar el concepto de subprograma a una agrupacin de instrucciones que


:ienen una tarea comn, que es resolver un subproblema, y que posiblemente se utiliza
:n varios sitios del programa principal o de otros subprogramas.

1.2.1 Declaracin de subprogramas en el programa principal


Los subprogramas se declaran justo despus de la declaracin de variables.

. :.OGRAM NombrePrograma ;

]]NST
{neclaracin de const.antes} ;

-'- 5

{Dec}aracin de variab}es} ;

--eclaracin de procedimientos y funciones) i

:EGIN {Programa principal}


,
:NlJ. lPrograma prrncrpal i

1.2.2 Diseo de subprogramas


Para disear un subprograma se deben seguir los siguientes pasos:

1 . Pensar y escribir qtt va a hacer. es decir, definir el ob.ietivo del procedimiento.

2. Responder a las siguientes pregunta\:

,Vo a necesitar deos que se han obtenido previamente'!

o Si la respllesta es s, entonces necesita datos externos. Estos datos se deno-


minan datos de entrada o simplemente entrada. El paso de esta informacin
se realiza a travs de parmetros (de entrada). Los parmetros de entrada se
SuspnocnAMAS: PRocEDIMTENToS Y FUNCIoNES

pueden ver como variables propias de los subprogramas (locales), que se van
a utilizar para guardar temporalmente los datos que se reciben.
o si la respuesta es ilo, entonces los datos que necesita se obtienen dentro del
subprograma. bien por teclado, o bien por clculos internos. se declaran
como variables locales.

posteriorttrcnte se use en otra parte del pro-


va a clevolver algn dao pctra cltte
gratna (Jera del subProgramo)?

o si la respuesta es afirmativa, el subprograma va a exportar datos al exterior.


Pua enviar rlatos fuera del subprogranla. es necesario hacerlo mediante el
que van a
uso de parmetros (de salicla). Estos parmetros contienen valores
ser utilizados por el programa principal y/o otros subprogramas'
o si la respuesta es negativa, el subprograma simplemente va a realizar una
tarea y los clatos que genere no se van a utilizar en otro lugar'. Estos datos
sern variables locales.

Al final de este paso est en condiciones de escribir las cabeceras de los subpro-
gramas.
pensar qu
Una vez que se tienen claros los plllltos primero y segundo' se pasa a
instruc-
pasos o qr inrtru..iones se tienen que ejecutar en el subprograma. Estas
ciones constituyen el llamado ('ue rpo del subprograma'

Estructura sintctica de los subprogramas en Pascal


La estructura de los subprclgramas es la siguiente:

o Encabezamiento de subPrograma'
o Declaraciones.
o Cuetpo del subPrograma.
las siguientes
Bsicamente (r,er figura.1. I ) es como la estructufa de un programa, con
diferencias:

o El e ncabezamiento empieza por otra palabra reservada'


o L'n programa termina con el carcter ".", mientras que los subprogramas terminan
con el carcter ";".

-1.3 Procedimientos Y funciones


Pascal perrnite dos tipos de subprogramas'. frmciones y procedimientos'
Unas definicio-
nes inlormrles de elios son:
PnocprtuENTos Y FUNCIoNES 1l

Ettc;t 1.,*zluturlltrl Elltlr l.ez;nl]r.rr rtr.r Elt," ;r l-,:z;u1*ltii.r


rl* I'lr.tl;tlllit r-l* Ptt,rc:r lrt:ttlli rl* Ftutcrr-ut

I,itcllrl;rct*-ut:s fi,:clu;tci,.ul*; i ]:clrrlrli*s

t-'111ii.r,l* i.,'11,:lIrs:r ,-ll i.'U*ll.i, t ilt


]1tttlt'L t*"rtl,:; It tsttlt(ilt.rl1,:s histnlctt.tlt.s

Figura 4.1: Estructura sintctica de un programa y de los subprogramas en Pascal

Funcin: es una clase de subprograma que se caracleizapor realizar clculos similares


a las funciones matemticas y tener un nico dato de salida de tipo simple que va
asociado al nombre de la funcin. Desde otro punto de vista, la funcin puede
verse como una expresin def,nida por el programador. Aunque Pascal permite
que una funcin devuelva ms de un dato mediante el uso de parmetros por re-
ferencia, es recomendable que la funcin tenga nicamente un solo dato de salida
(que est asociado al nombre de la funcin).

h,ocedimiento: es un subprograma que puede tener cero, uno o ms datos de salida.


Desde otra perspectiva se puede ver como una instruccin que el programador
def,ne.

.1.3.1 Definicin de una funcin y un procedimiento


:,:ril uflo funcin se sigue la siguiente sintaxis:

:,]iCTION <IdenFunc> t( [VAR] lidenLPara:tipo,...l ;...) I tipo; :

ieclaraciones )
:IGIN {idenrunc}
{cuerpo de insLrucciones }
:liD; {idenrunc }
Para un procedimiento se sigue la siguiente sintaxis:

:ROCEDURE <IdenProc> t ( [VAR] lidentPara:tipo, . . .] ; . . . ) t;


,Ceclaraciones)
\,
'.L,,.,'
vs;"
SuspnocnAMAS: PROCEDIMIENTOS Y FUNCIONES

_l
BEGIN i }denProc ]
{cuerpo_l de instrucciones}
END; tldenProcJ

les asocia a la funcin y al


donde IdenFunc e ldenProc son los nombres qlre se
vlidos en Pascal'
proceclimiento respectivamente y deben de ser identificadclres
cle los subprogramas' La
Identpara:Lrpo son las declaraciones de los parmetros
E'l tipo de la ftrncin
forma detallada y su signifrcaclo se estudiarn ms adelante'
FUNCTION Nombre t...)
'tipo inclica el tipo del valor que la funcin va a devolver como
parte de declaraciones del pro-
resultado. La parte de declaraciones es idntica a la
de constantes, de variables
grama principal, es decir, llevar su seccin de clehnicin
iclntico a la parte del
y de subprogramas locales. El cuerpo de instrucciones es
para realizar una tarea
.u",po de instrucciones del programa principal. Est diseado
una instruccin que d valor
especfica. En el caso de la funcin. debe incluir a1 menos
una asignacin de la forma
al nombre cle la funcin, por 1o tanto debe tenet' al menos
<IdenFunc> : = expresin'

4.3.2 Llamada a una funcin o a un procedimiento


realizar una llamada o invocacin
Para utilizar una funcin o procedimiento es necesario
a ese subprograma. Para ello basta escribir su nombre
y entre parntesis la lista de

parmetros que necesite. La lista de parmetros de la


llamada cleben coincidir en nmero'
de tipos) con la lista de
orden y tipo (r,er captulo 6 apartaclo 6.6 de compatibilidad
parmetros de la declaracin.
La sintaxis cle la llarnada es la siguiente:

IdenFuncin [ (l,istaparmetros) ]

IdenProc [ (ListaParmetros) ]
de una expresin' Cuando
La llamaria de tnafunciir se realiza generalmente dentro
llamada a una funcin' se de-
un programa (o s,bprgrama) en Prscai se encuentra una
y se inicia la ejecucin de
tiene cle manerr temp.',ial (1a ejecucin se queda suspendida)
clescle e1 BEGIN del cuerpo de la
1a tnncin. La fnnciln ejecuta iockts las instrucciones
es el ltimo valor dado al
funcrrin hasta que encuentra el END. El valor que devuelve
la funcin devolver valores ba-
nontbre de Ia tuncin. si no se le asocia ningn valor.
de la funcin' se sustituye
sllrir (\ elttles desconociclos). Una vez terminada la ejecucin
principal (o subprograma) de
1 lluntada por el'nalor clevuelto y continua el programa
m i-1n e l i,i l-tt-,ttll a1.
como una lnstrucclon en
Lr, Llrladr a tn p1tceclimientt (ver figura 4.2.) se tealiza
pascrl. en un1 lnea el programa (t). Cuando el pro-erama encuentra una llamada a un
proce drnriento. eI programa principal se queda suspendido y se inicia 1a ejecucin del
desde el BEGIU hasta
p.oc.-,,1i,li.nto (2). El procedimiento ejecuta toclas las instrucciones
Plnurrnos -1
t-)

l END. Una vez terminada la ejecucin (3), el programa principal recupera el control y
continua normalmente.

trRGR}I,1
de*laraci<:nes
FE*EOF.E P tparametr&l l
I
decLara*i<:n*s I t
I 1
BEIt'l
tli I t
instru*ci.an*s I I
* 1
1 i1.]
BEGIH
{jJ 1
t
I
P{};- ---}

END.

Figura 1.2: Semntica de la llamada a un procedimiento

1.4 Parmetros
Los parmetros son el medio natural de paso de infbrmacin entre subprogramas. Siem-
tre que se requiera algn dato externo al subprograma o que se vayan a exportar datos
hay que hacerlo mediante el paso de parmetros. Estos elementos esenciales en la pro-
_sramacin modular se pueden clasiflcar segn varios criterios. Si la divisin se hace
.Ltendiendo al h"rgar donde se encuentren se tienen:

o Parmetros formales o ficticios: si est.{n en la cabecera del subprograma.


o Parmetros actuales o reales: si se encuentran en la llamada.
Si se agrupan dependiendo del flujo de informacin:

o Parmetros de entrada: aportan datos al subprograma. Si no se dice lo contrario,


los parmetros son de entrada por def'ecto.
o Parmetros de salida: exportan datos al exterior del subprograma. No existen en
Pascal.

o Parmetros de entrada/salida:realizan ambas funciones. Para declararlos se an-


tepone la palabra reservada VAR en la cabecera del subprograma.
Y FUNCIONES
14 SUSPNOCRAMAS: PROCEDIMIENTOS

En Pascal los parmetros se clasiflcan como:

o Por valor: coresponden a los parmetros de entrada'


de entrada/salida'
o Por referencia o por variable: corresponden a los parmetros

4.4.1 Parmetros Por valor


datos al subprograma (clatos de en-
Este tipo de parmetros se utilizan para importar
son:
trada). Dependiendo de donde se encuentren

oEnlallamada:pueilenservariables,Constantesoexpresionesdelmismotipo
(vercaptulo6apartado6.6deCompatibilidaddetipos)queelparmetroCorres-
pondienteqo",""n.,"ntraenlacabecera.SihayvariosvanseparadosporComas.
las variables:
o En la cabecera del subprograma: se declaran igual que

identificadorParametro : tipo

Sihayvariosparmetrosdedistintostiposvanseparadosporpuntoycoma',;''
Comosemuestranenestascabecerasdesubprogramas:

Ftil\CTION Calculo (num2 : real; letra: char) : boolean;


PROCEDURESacaT(precio:rel;peso:integer);

pueclen separarse por "'" como:


Si los parmetros son del mismo tipo

FUNCTION Eiemplo(b, letra: char; saldo' reint: re1): real;


PROCEDURE Imprimir (x1, x2, grado: integer);

reales son evaluados y sus valores


cuando se produce la llamacla los parmetros
se irsi.gnan a los parm"t,o, fo,,,oles de
acuerdo al orden establecido (el primer
etc')' E'l subprograma
I'alor primer por*",ro, el segunclo al segundo parmetro,
a1
ejecucin y una vez terminada'
utiiiza los r,alores de estos parmetros duiante la
I0Sparmetrosfbrmalesdesaparecen.Esimportantenotarquelosparmetros
ell cISo de que sean variables' no sufren modificacin'
reL1e:.

{.1.2 Parmetros por referencia o por variable


de
datos fuera del subprograma (datos
Esre tipo t1e parmetros se utilizan para exportar de
porque Pascal no posee parmetros
entrada./sriida). Estos datos son de entradisada
son:
sahda. Dependiendo de donde se encuentren
Br.oeups 75

En la llamada: deben ser variables de tipo idntico (ver captulo 6 apartado 6.6
de compatibilidad de tipos) que el parmetro correspondiente que se encuentra en
la cabecera. Si hay varios van separados por comas.
[:. En la cabecera del subprograma: igual que las variables, pero ante-
se declaran
cedidos de la palabra reservada VAR.

I :n- VAR identificadorParametro : Tipo

Ipo Si hay varios parmetros de distintos tipos van separados por punto y coma ";"
hr..t-
como por ejemplo:
B[:'r1S.

PROCEDURE Calcular x1:integer; VAR x2:real);


(VAR
PROCEDURE Incrementar (VAR precio, compra:real) ;

Como se observa en el segundo ejemplo, si los parmetros son del mismo tipo van
E-: . separados por coma ",".

Cuando se produce la llamada se crea un sinnimo o alias de los parimetros reales en


los parmetros flcticios, es decir, ambos parmetros se refieren al mismo espacio en
memoria donde se almacena el parmetro real. E1 subprograma utiliza los valores de
estos parmetros durante la ejecucin y seguramente los modif,ca. Una vez terminado,
los sinnimos desaparecen, quedando nicamente los parmetros reales. Es importante
notar que los parmetros reales pueden ser modificados, ya que los cambios producidos
dentro del subprograma se realizan tambin sobre estos parmetros.

4.5 Bloques

i' -Lores Se considera bloque al fragmento de cdigo que est entre la cabecera del programa y el

|
-,,,-t .. final del programa, o al fragmento que se encuentra entre la cabecera del subprograma
f =,.*u y el flnal del subprograma. Por 1o tanto, existen tantos bloques como subprogramas ms
:r.rda, el bloque del programa principal.
[
ts- tros

4.6 Tipos de identificadores


Los identificadores son nombres, generalmente significativos acorde a 1o que representan
)m-..os
de o a la accin que realizan, que se les dan a todos los objetos (tipos, constantes, varia-
L.:os de bles, subprogramas) en cualquier lenguaje de programacin. Dependiendo de donde se
'declaren sern:
Y FUNcIoNE's
76 Suspnoc;nAMAS: PRocEDIMIENTos

oldentiflcadoresglobales:seencuentranenlapartededeclaracionesdelprograma
princiPal.
se encllentran o en la
cabecera o en
o Identificadores locales a un subprograma:
subprograma'
la parte de declaraciones del
oldentificadoresnolocalesaunsubprograma:estosidentiflcadoressoloexisten
cuandoseproduceuniu*i"ntodesubprogranras(un^subprogramaSeencuentra ex-
qu" cleclaratlos en un subprograma
dentro de otro). Los identificaclores "rin interno'
no locales al subprograma
terno son identificatlores

4.7 Vigencia o vida de un objeto

fina1 de1 bloque donde


Sedicequeunobjetotienevigenciaenunbloquesiexisteenesebloque.Lavigenciade
desde la lnea en la que est eclarado, hasta el
abarca
un objeto

" ni;l'LT"o,o" es vigente.destle la'1Y 1*11:"rlu o""u'ado hasta el rrnal del


los bloques interiores a
1'
bloque clonde V en tJdos
'"'i"'

4.8 mbito o visibilidad de un objeto


Urrobjetoesli:ibleenunbloquesiexisteysepuedeaccecleral.Sepuedeaccedera
su valor'
de leer' usar o modificar
un obeto si se es capaz ha declarado hasta el
un objeto ubur." desde la 1nea donde se
Regla: El mbiio cle
interiores existe un objeto
con el
excepto J* bloques
ftnai del bloque donde reside. "t interno oculta al objeto externo'
identificador. Si ocune esto, se i." qo" el oteto
mismo

4.g Efectos laterales

el paso de parme-
Serlicequesehaproducidounefectcllateral.o*d::".l'ovocauncambioenunao
subprograma sin utilizar
o no locares a un
r.arias r,ari.bies globales valores a variables
tros. por 1o ranro solo ocurren
denrro;;';" ;";p;grama al asignar
.\ternas a este subprosrama
ou
'u'iui"'
et""^r"'l::::*:T:'#,"1,""it"3t:'::
se usan siempre paral
.rrnsisue si cientro e un subprograma
:ubPrtr clallla'

-1.10 Cuestiones de tiPo test


-1.10.1 Enunciados
LasslguientesCLlestionespuedentenerunaomsrespuestasCorrectas.
CunSrrONS DE TIPO TEST 11

1. Las recomendaciones acerca del correcto desarrollo de procedimientos preconizan


que:

(a) Todas las variables que se manejen en el procedimiento deben ser globales.
(b) Todas las variables que se manejen en e1 procedimiento deben ser locales al
mismo.
(c) La comunicacin del subprograma con el exterior se debe realizar exclusiva-
mente mediante parmetros.
(d) Slo deben utilizarse parmetros si hay conflictos de nombre con los varia-
bles globales.

2. Las recomendaciones acerca del correcto desarrollo de subprogramas preconizan


que:

(a) Algunas variables que se manejen en el subprograma pueden ser globales


por motivos de eflciencia.
(b) Todas las variables que se manejen en el subprograma deben ser locales al
mismo.
(c) La comunicacin de una funcin con el exterior se debe realizar a travs del
valor que devuelve su nombre y mediante parmetros de entrada, de salida o
de entrada/salida.
(d) Slo deben utilizarse parmetros si hay conflictos de nombre con las varia-
bles globales.

3. Los subprogramas:
(a) Sirven nicamente para complicar ia programacin.
(b) Se deben poder verificar. probar y depurar independientemente.
(c) Siempre tienen, al menos. un parmetro, ya sea por ref-erencia o por l'alor.
(d) La llamada a los subprogramas se realiza siempre en el programa principal.
1. Si se quiere realizar un subprograma que reciba dos cantidades enteras y depen-
diendo del valor de una variable booleana pasada como parmetro. sume o reste
a la primera cantidad la segunda, y devuelva esta primera cantidad actualizada. ia
cabecera ms apropiada ser:

(a) PROGRAM Banco(vAR saldo, cantidad: integer;


ingreso: boolean);

(b) PROCEDURE Banco(vAR saldo: integer; cantidad: integer;


lngreso: boolean);
Y FUNCIoNES
78 SuspnocRAMAs : PRocEDII\IIENTos

boolean)
saldo(cantidad: integer; ingreso:
;
(c) FUNCTION

(d) PRocEDuRE Banco'Hl


i:il::":'*:?::,,,l""nu''
es (son) correcta(s)?
5. 1as siguientes afirmaciones
Cul(es) de

(a)Lavigenciadeunavariablecorrespondealbloqueenelquesehadefinido.
y exteriores a 1'
y a todos uqoJlo' bloques interiores
(b)E1mbito(lavisibilidad)deunavariablecorrespondealbloqueenelque
l que no contengan
se ha definid"l V i".r
quellos bloques interiores a
" un objeto con el mismo nombre'
una declaraciOn e
(c)Lavigenciadeunavariablecorrespondealbloqueenelquesehadefinido.
exteriores a l'
y a todos aquellos bloques
(d)E,lmbito(lavisibilidad)deunavariablecorespondealbloqueenelque
bloques interiores a 1'
se ha deflnido, y u too' aquellos
(son) correcta(s)?
siguientes afirmaciones es
6. Cul(es) de las

(a)Lavigenciadeunavariablecorrespondealbloqueenelquesehadefinido.
(b)Elmbito(lavisibilidad)deunavariablecorespondealbloqueenelque
a 1, independientemente
se ha definiio; o ioo, aquellos bloques inreriores
delidentificadordelosobjetosqu".nnt"nganlosbloquesinteriores.
siempre coinciden'
(c) La vigencia y el mbito de una variable
(d)Eimbito(lavisibilidad)cleunavariablecorespondealbloqueenelque
seha<lefinido,siempreycuandonoexistaotravariabledefinidaenunbloque
exterior a 1'
de una variable coinciden
cuando:
7. La vigencia y ei mbito
(a)LavariableestarleflnidaenunbloquequenoContieneningnbloqueinterior
a 1.
que puede-contener otros bloques
(b) La variable esta definida en un bloque
interioresal,yestosnocontienen,nu".tu.u.indeunidentificadorigual.
(c t SiemPre'
ld) Nunca'

E. Contemple el siguiente subprograma:

??CCEDURE lncrementarC ;

. .= succ(c) ;
CuBsrroNBS DE TrPo rEST

END;
:(
\
(a) Es un procedimiento sintcticamente correcto y evita los efectos laterales.
(b) Es un procedimiento incorrecto y lo detecta el compilador'
(c) Se produce un efecto lateral al modiflcar una variable no local'
(d) Puede ser incorrecto si c es una variable entera y tiene un valor negativo'

9. Se recomienda el uso de un procedimiento cuando,:- R-

(a) Un subprograma no devuelve ningn valor.


_ _ *
. t'y'
-.

(b) Un subprograma tiene parimetros de entrada y un nico panimetro de salida'-


I1":Ji -
(c) Un subprograma devuelve ms de un valor.
(d) un subprograma tiene un nico valor de salida de tipo ordinal.
10. Cul es el efecto de la llamada Pro (4 ) , dado el siguiente subprograma?

PROCEDURE Pro (VAR c: integer) ;

BEGIN
write (c) ;
C := C + 1
END;

(a) Se escribe 4 en pantalla, y el valor del parmetro actual correspondiente a c


en el programa princiPal es 5.
(b) Se escribe 4 en pantalla y no hay cambios en las variables del programa
principal.
(c) Se escribe 4 en pantalla y despus 5'
(d) La llamada produce un error, porque el parmetro actual es una constante.

11. Dado el siguiente fragmento de cdigo:

PROCEDURE Ejercicio (n: integer; k: real);


BEGIN
k := k * n;
END;
BEGIN {Programa Principal )
q- ._
.- a"
zt
-L .-
.-
?
).
tr.
J t

erclclo (a, r)
El
write (a, r) ;
, rl
END. {Programa Prfnclpar I
Y FUNCIONES
80 SUBPROGRANIAS: PROCEDIN,IIENTOS

ercicio (n k)
(a) La llamada a E ercicio es incorrecta' Debera ser: Ej '
'

(b) a = 2yr = ??. Porquenoleasignamosningnvalordentrodelprocedi-


miento.
local al
(c) a = 2 y r = 3.5' Porque los valores slo se modifican de forma
procedimiento.
es sintcticamente lnco-
(d) E,ste cdigo no compila porque el procedimiento
rrecto.

correcta/s:
t2. Seale la/s afirmacin/es que sean
a un procedimiento los parmetr"'t"".t":.::: sustituidos por
(a) En una llamada por los de
los parmetros lbrmaies y 1os parme"o' po' valor son sustituidos
referencia.
(b)Enunallamadaaunprocedimientotodoslosparmetrosrealessonpasados
por valor.
parmetros pueden ser por valor o
(c) En una llamada a un proceclirniento los
por referencia'
los parmetros por valor son copiados
a
(t1) En una llamada a un procedimiento
tlna nueva zona de memoria'

13. Las varirbies no-locales a


un subprograma:

(a) Nunca proclucen ef-ectos laterales'


mismo subprograma'
(b) Son aqtiellas que estn declaradas en el
de subprogramas'
(c) Si existen. puede ser debido a que hay anidamiento
(d) Siempre se pueden usar en el bloque del programa principal'

14. Los efectos laterales:

(a)Sonmuyconvenientesporquemejorannotablementeladepuracinyverifl.
cacin de Programas'
(b)Seproducenalasignarvaloresavariablesglobalesono-localesaunsubpro-
grar]1a dentro del subPrograma'

{C)ocurrensiemprequeserealiceunallamadaaunatuncindesdeelcuerpo
de un Procedimiento'
td)Ocurrencuandounsubprogramainfluyedirecmmenteenelestadodecmput,.
deotrossinqueestosef'ectosseanproducidosporelpasodeparmetros.

1.10.2 Soluciones

l.Larbi'la(c)soncortectas.La(a)estotalmentecontrariaalasrecomendaciones.
(b) evita ios ei-ectos laterales" por io tanto
\ a qrl. produce et'eetos laterales. I-a
CuBsrroNBs DE TrPo rEST 81

es cor:recta. La (c) garantiza que los subprogramas sean autnomos, por lo que es
correcta. La (d) es errnea, ya que el uso de parmetros no depende de que existan
o no conflictos de nombre. sino del intercambio de informacin.

2. La (b) es correcta. La (a) es totalmente contraria a las recomendaciones, ya que


produce efectos laterales. Nunca hay que usar variables globales en un subpro-
grama. La (b) evita los efectos laterales, por 1o tanto es correcta. La (c) es falsa,
ya que las funciones no deben tener parmetros de entrada-salida. La (d) es er-
nea, ya que siempre deben utilizarse parmetros para intercambiar informacin
con el exterior.

3. La (b) es correctI. La (c) es incorrecta porque pueden existir subprograrnas que


no necesitan intercambiar informacin mediante parmetros. La (d) es talsa de-
bido a que se pueden realizar llamadas a subprogramas desde otros subprogramas
(incluso desde el mismo subprograma) y por lo tanto no siempre han de hacerse
desde el programa principal.

4. La (b) es cor:recta. La (a) es falsa porque los subprogramas nunca empiezan por la
palabra reservada PROGRAM. La (c) es errnea debido a que la funcin solo recibe
una cantidad entera (cantidad) y segn el enunciado debe recibir dos. La (d) es
poco apropiada ya que que todos los parmetros son por referencia. lo que indica
que todos van a ser modifrcados 1o cual, segn el enunciado, es falso.

5. La (b) es colTecta. La (a) y la (c) son errneas debido a que una variable no esta
siquiera definida en los bloques exteriores. La (d) es falsa, ya que una variabie no
es visible dentro de un bloque interno que contenga otra variable o un parmetro
con el mismo identificador.

6. La (a) es corecta. La (c) es errnea debido a que la vigencia y el mbito coinciden


cuando no existen bloques interiores o si existen no hay duplicidad de identilica-
dores.

7 . La (a) y la (b) son correctas. La (c) y la (d) son errneas ya que existen casos en
Ios que coinciden y tambin existen casos en los que no.

8. La (c) es correcta. La (a) falla porque no evita los efectos lateraies al modificar
una variable que no es local. La (d) es falsa debido a que si la variable c es entera,
el procedimiento es correcto para cualquier valor de c negativo.

9. La (a) y (c) son correctas. I-a (b) y ia (d) son incorrectas porque justamente
1a
en el caso de que el subprograma tenga un rnico parmetro de salida (indepen-
dientemente de su tipo, excepto para tipos compuestos o complejos todava no
estudiados) se r:ecomiencla el uso de una funcin.

10. La (d) es correcta. EI procedimiento Pro posee un parmetro por referencia, por
1o que en la llamada debe ser hecha con una variabie. En la trlamada Pro (4 ) , el 4
es una constante, por lo que el compilador al realizar la comprobacin 1o detecta
SuspnocnANIAS: PRoCEDIN{IENTos y t t\cIoNES

y dar un en'or en tiempo de compilacin. Por lo tanto. e1 pro-erama no se puede


ejecutar.

11. La (c) es correcta. El procedimiento n j ercicio posee nicarnente parmetros por


implica que se pasa una copia de los parmetros actuales. Los cambios
'u,alor. Esto
en las copias no af'ectan a los parmetros de la llamada. La llamada es correcta,
ya que usa la variables del programa principal y el pro-erama es sintcticamente
cor:recto.

t2. La (c) y la (d) son correctas. La (a) es errnea ya que los parmetros por valor no
se sustituyen por los parmetros por referencia. La (b) falla. pues los parmetros
pueden ser por valor y por referencia, pero no nicamente por valor.

13. La (c) es correcta. Las variables no-locales a un subprograma surgen cuando hay
anidamiento de subprogramas. Estas variables se pueden usar entre otros sitios,
en el bloque en las que estn declaradas, 1o que hace a (d) falsa. Pueden causar
ef'ectos laterales si se modiflcan dentro del subprograma sin paso de parmetros.
Por lo que (a) es errnea.

t4. La (b) y la (d) son coruectas.

4.ll Problemas

4.11.1 Toro
Implemente un programa en Pascal que escriba por pantalla la siguiente palabra: TORO.
La palabra debe aparecer en vertical:
T
o
R
o
y cada letra debe estar compuesta por el carcter 'O' segn la tabla 4.1

T o R o
00000 000 0000 000
0 00 0 0 00
0 o0 0000 o0
0 oo 00 00
0 000 0 0 000

Tabla 4.1: Toro


PnosLptrls 83

4.LL.2 Otro toro


Implemente un programa en Pascal similar al ejercicio anterior que escriba por pantalla
las palabras OTROTORO. Las palabras debe aparecer en vertical

4.11.3 Nuevo toro


Implemente un programa en Pascal similar al ejercicio anterior que escriba por pantalla
Ia palabra TORO, pero esta vez, que sea el usuario e1 que elija el carcter con el que
quiere que se lbrmen las letras. Las palabras debe aparecer en vertical. Por ejemplo,
si el usuario escoge la'X'. este programa mostrar cada letra formada con el carcter
elegido.

4.11.4 Traza y comprensin


Dado el siguiente programa:

PROGRAM Secuencial;
{Onletivo: Probar procedimientos}
VAR
=
4t
1-,. i--^^^-.
p.

result: integer;
PROCEDURE Primero (VAR suma: integer; num, num2:integer);
{Onjetivo: Devolver l-a suma de num - r,,-rl
{eRn, uinguna}
{losr: suma=num+num2}

BEGIN {erimero}
_ SUma := num + nUm2;
END; { erimero}

PROCEDURE Segundo (num:integer) ;

{OUietivo: Mostrar por pantalla un mensaje indicando el valor del


nmero incrementado en una unidad]
{lRu, uinguna}
{lOSf: Por pantatla: El resu}tado incrementado es igual a num}
VAR
aux: integer;
BEGIN {segundo}
_ aUX := nUm + 1;
_ writeln ('El resultado incrementado es igual a ' , aux) ;
END; {Segundo}
SuspnocnaMAS: PROCEDIMIENTOS Y FUNCTONES

BEGIN {Programa Pr:-nciPaI}


wriceln'Inrroduzca dos nmeros enteros ') ;

read-Lnia, D);
*^-,,1r .- L,
Segundo (result) ;
writeln (result) ;
Primero(resuit, a, b)
writeln (result) ;
END. {Programa PrinciPal}

o a) Numere por orden de ejecucin todas las instrucciones'


o b) y qu instrucciones son llamaclas a procedimientos definidos por el
Cuntas
usuario?
o c) ,Cuntas instrucciones no son llamadas a procedimientos'J
od)Qumostraraporpantallaelprogramasiseintroducen5y14comodatos
para a y b'?

r la llamada a Primero con los


e) cul es eI valor de resultado antes de producirse
datos del aPartado d)?
de resultado antes de producirse la llamada
a Primero si in-
o f) cambia el valor
troduce otros datos Para a Y b?
(resultado b) por
o g) Qu ocuffe si cambia la instruccin Primero ' a'
Primero (a+b, a, b) 'J
o h) Rellene la tabla 4.2 con 1os valores de 1as variables. Si el valor es desconocido
ponga?.silavariablenoexiste,dejeelespacioenblanco.Laprimeralineaes
de ejemplo Y est cornpieta'

4.11.5 Mtodo Cesar


infbrmacin que se emple
una de las primeras tcnicas criptogrficas para encriptar primera
cifrado pof este mtodo consiste en sustituir la
fue el lla1nacio Mtodo Cesar. El
por 1a (n+1) Ietra, 1a tercera por la
letra rlel alfabeto por 1a ensima letra, 1a segunda
que despus de
(n+r r r as sucesivamente" Se supone que e1 alfabeto es cclico, es decir"
r:ama clave de cifradrt' observe
ia .ilrin-ra letra viene la primera. El valor de n se conoce
igual a 5
1a ru'oia 1.3 para la equivalencia entre letras para una clave de cifrado
.._i, "n"on,rul.
iil-- r.

Couoejemplo,lapaiabraEXAMENcifradaconesaclaveesltsEQiR'
para 1a resolucin simplihcada del problema se supondr que todas las
letras irn en
atfabtico'
ma'sculas v no habr ningn smbolo que no sea
Pnonr,Buls 85

Ins a b result suma num num2 aux Entrada Salida


1 'l
(,' ;'l
(,' (r). lntrod...
2 -1 8 38<--
--)

. ..,
4 4 4 L!
5
6
1
B

9
10

T abla 4.2: Tr aza y comprensin

A B C D E F U V w x Y Z
E F G H I J Y Z A B C D

Tabla 4.3: Mtodo Cesar

a) Realice un subprograma llamado Cifrar, que reciba una letra y la clave de cifrado
y devuelva la letra codificada.
NOTA: Puede ser til implementar una funcin llamada sucesor para que dada una
letra devuelva su sucesora en orden alfabtico, siendo el sucesor de'Z' la' A .

b) Realice un subprograma llamado Descifiar. que reciba una letra codificada y la


clave de cifiado y devuelva la letra decodificada.
NOTA: Puede ser til implementar una funcin llarnada Antecesor para que dada
una letra devuelva su antecesora en orden alfabtico. siendo el antecesor de' A |a'Z' .

c) Realice un programa que pida la clave de cifrado/descifrado (un nmero entero,


positivo) y a continuacin presente el siguiente men:

o Cifiar una letra.


o Descifrar una letra.
o Finalizar.

Y dependiendo de la opcin escogida. deber rcalizar la tarea adecuada.

4.11.6 Erreres
Dado el siguiente prograrna incompleto:
86 SunpnocnAMAS: pRocEDrMrENTos y FUNCToNES

ir) PROGRAM Errores;


2 VAR
3 lal
ruu, w
1!, \/ u. ir1-aaor.
flluuYu!,
It
4 letra: char;
5 FUNCTION Cambio(col: integer) : char;
6 BEGIN {cambio}
I ^L-^^
1 -LCLId. : = CUA;
8 END; {Cambioi
{g} FUNCTION Continuar(a: integer) : boolean;
{ro } BEGIN {Continuar}
{rr }Continuar := (a DIV 2) > x;
{tz} END; {Continuar}
{r } PROCEDURE Externo(VAR a, b: inLeger);
{r+ } VAR
i nr aaav .
{rs } rlruuYu! /

{ro } PROCEDURE Interno (aa: integer; VAR bb: integer);


{tz } BEGIN { interno}

{ra } END ; {interno}


{rg} BEGIN {externo}

{zo} Interno(a, 0);

{zr} frrt"rrro(7, b) ;

{zz} EINJJ; t extelno -|

{z: } BEGIN {Programa principal}


{z+} readln(1et);
{zs} letra := Cambio;
..
{zel Interno {,x, y) ;

{zt} l,lilrrU Continuar (y) DO BEGIN{I\IHILE}

{ze} trliD; {WHf fn }

{zgll z , = nxterno (x, y) ;


i:o) m := x * y;
^.-h.i ^ /-\
{r} rslr(!.v\^7 ,

i:z) - -,- . tPrograma prrnclpa_t ,l


Pnonr,Bnras 87

El programa contiene etrores, que pueden ser tanto sintcticos, semnticos o referentes a
la pragmtica y recomendaciones dadas en el libro. La siguiente lista def,ne los posibles
tipos de "errores":

1. Uso de una variable global en un subprograma.

2. Uso de una variable local fuera de su mbito.

3. Llamada a una funcin como si fuera un procedimiento.

4. Llamada a un procedimiento como si fuera una funcin.


5. Parmetros actuales de la llamada inconsistentes para el tipo de paso de parme-
tros.
6. Asignacin incompatible.
7. Llamada a un subprograma sin los parmetros actuales correspondientes.

8. Llamada a un subprograma desde fuera de su mbito de llamadas.

Utilice la tabla 4.4 pararelacionar el nmero de cada sentencia incorrecta con el tipo
de error que contienen (ver lista de arriba), justiflcando brevemente (en una frase) su
decisin. Por supuesto, a la hora de identif,car las sentencias incorrectas slo se pueden
tener en cuenta las declaraciones e instrucciones explcitas.

No de sentencia Error/es Breve explicacin

Tabla 4.4: Problema sobre errores

4.11.7 Nmeros romanos


Escriba un programa que muestre un men con las siguientes opciones:

e Cambio de numeracin romana modificada a arbiga.


o Comprobacin de un nrnero rofflano.
c Finalizar.

E1 prograrna mostrar este rnen, realizando las operaciones cot:respondientes hasta


que se escoja ia opcin de Finalizar.
Las dos primeras opcicnes consistirn en leer caracteres hasta encontrar un punto o
que el nmero de caracteres sea 15 o superior que representan un nmero romano.
Las reglas para comprobar que un nmero romano es correcto y que se van a usar
para este programa son las siguientes:
t'

88 SUNPNOCNAMAS: PROCEDIMIENTOS Y FUNCIONES

Las letras M. C. X. I no pueden aparecer ms de 3 veces en el nmero.


o La,s letras D. L y Y no aparecen rns de una vez en e\ nmero.

o Stilo son r'rlidas las letras M. D, C, L, X, V I.

El cambio de sistema romano a arbigo consiste en hallar el nmero arbigo corles-


pondiente al nmero romano introducido e imprimirlo por pantalla. Se supondr que se
introduce un nmero romano correcto segn Ias reglas dadas en el prrafb anterior.
Para hallar el nmero equivalente en numeracin arbiga se tendr en cuenta lo si-
guiente:

o Si una cifia es menor que la siguiente su valor se resta al de la siguiente y este


proceso es nico para cada par de cifras.
Ej: IX. = 10-1=9 ; CM. = 1000- 100= 900 ;

o Si una cifra es igual o mayor que la siguiente su valor se suma.


Ei: CCV. = 100 + 100 + 5 =205;
CLXK. = 100 + 50 + l0 + 10 + I = 111.
XXIII=10+10+l+l+I=23:'
CMIL. = 1000 - 100 + 50 - 1 = 949;
o Solo se pueden restar cifras potencias de 10. es decir, C, X, I.

Tener en cuenta la tabla 4.5 de equivalencias entre los nmeros romanos y arbigos.

M D C L x v I
1000 500 100 50 10 5 1

Tabla 4.5: Equivalencia de nmeros romanos

Recomendacin: Estructurar el programa de manera que se descomponga en sub-


problemas e ir procesando cada cifra teniendo en cuenta el valor de la siguiente.

-1.11.8 \Iultiplicacin con lpizy papel


Se dese a realizar un programa que permita obtener el producto de dos nmeros enteros
po:itir rrs .\ r' B formados por nl y n2 dgitos, respectivamente. Como el ordenador
qu. renemos disponible no tiene implementada la multiplicacin, vamos a realizar una
aolr;acitin que permita reahzar dicha operacin. Nos basamos en la multiplicacin que
hice nros "con lpiz y papel".
P,rr eienrnkr. 3152 x 486 = 3752x4 + 3752x80 + 3'l52x4AA =2251.2 + 300160 +
'---'-'-r_.-'_.-
1500t00 = 1813.i72
Pnonr,Buls 89

Como es una labor complicada, otros programadores han realizado parte de la tarea.
Estos trabajadores dan los siguientes subprogramas, que funcionan de manera correcta
y que usted puede utilizar:

FIINCTION NumeroCifras (num: longint) : integer;


Iopr.. --l l
{lOSt:NumeroCifrs = nmero de cifras de num}
{Untrada: un nmero entero largo}
{SaflAa: el nmero de cifras del nmero}
{fjempto: NumeroCifras (8765) --, 4}
{rjempl-o2: NumeroCifras (486) --, 3 }

FUNCTION Desplazalzquierda(num: longint; nveces: integer) : real;


{PRE: nvecesr=o}
{lOSf: Desplazalzquierda = flurr} con nveces ceros aadidos por
la derecha i
{rntrada, ,rr rr*"ro entero largo, el cual va a ser desplazado
a Ia izquierda nveces)
{Satiaa: Un nmero real- que es igual al numero entero
desplazado a 1a izquierda nveces)
ittora, Devuelve un nmero real para evitar errores de rango)
{fjemplo: Desplazalzquierda(15008,2) --> 1500800i
{UjemptoZ: Desplazalzquierda(30016, 1) --> 300160}
{ejemp1o3 : Desp}azalzquierda (22572,0) --> 225L2}

FUNCTION Multj-plica(num: longint; digito: integer) : longint;


{enr:aigito >= o y dgico <=9}
{POst: Multiplica = num*digito}
{nntrada: un nmero entero y un dgito entre O y S}
{Satiaa: La multiplicacin de num y dgito}
ItlempIo: lvlultip]ica(234, 3) --> ?02)
Se pide solucionar el problema utilizando los subprogramas dados. Para ello deber
desarrollar eI programa principal, con las variables correspondientes y las cabeceras de
ios subprogramas dados (so1o las cabeceras).

4.11.9 Pa{ndrorno
Considere ei siguiente mtodo:
Dado un nmero, se suma a su reverso. Si esta suma es un palndromo o capica,
entonces parar'; si no, repetir el proceso con el nmero obtenido de dicha suma, hasta dar
con un palndromo.
7

90 SunpnocnAMAS: PRoCEDIMIENToS Y FUNCIoNES

nmero polndromo o capica es un nmefo que se lee igual de


izquierda a
un
derecha que de derecha a izquierda. Por ejemplo 21312 o
4334'
a su reverso (95)
Ejemplo del mtodo: Suponga que se parle del nmero 59; lo suma
(451) es 605' Por
y ottl.n" 154. Repite la operacin con 154; la suma con su reverso
I 11. Se pide:
ltirno. al sumar 605 a su reverso (506) obtiene un palndromo 1
(a) Escribir un subprograma que calcule el reverso de un nmero'
(b)Escribirunsubprclgramaquedeterminesiunnmeroesunpalndromo.
pida un n-
(c) Escribir un plograma que' utilizando los subprogramas anteriores,
llegar a un nmero paln-
mero entero por teclado y muestre la secuencia de sumas hasta
dromo.

4.11.10 Nmero de la suerte


Se quiere realizar un programa en Pascal que halle el
nmero de la suerte de cada per-
nacimiento' E1 mtodo
sona. El nmero de la suerte se halla a partir de la fecha de
del da, las cifras del mes y las cifras del ao y a continua-
consiste en sumar las cifras
estructurado' iterativo y
cin reducirlo a un nico dgito. El programa tendr que ser
utili zar subPro gramacin'
2004 el nmero de la
Por ejemplo, si la fecha de nacimiento es el 29 de enero de
suerre es Qglollzoo4): 2+9=11, 0+1=1, 2+0+0+'.1=6 -
* 11 + I + 6 = 18 ----+ I + 8 =
ejemplo, si la fecha es el 4
9 que es e1 nmero de la suerte de los nacidos ese da. otro
(0411211975): 4, l+2=3,1+9+l+5=22
de Diciembre de 1975 el nmero de la suerte es
A
+ f J Tt11
''1 -L -?o-
- -/
11 --' 1+ 1=2queeselnmerodelasuertedelos
2+9=
2002 el nmero de la
nacidos
- ese da. otro ejemplo, si la f'echa es el 1 de Febrero de
suerrees (o!lo2l2oo2l: l. U.2+0+0+2=4 ---+ 1+ 2+4=7
quees elnmero delasuerte
de los nacidos ese da'

4.1l.ll Calculadora
deber tener los si-
Escriba un programa que simule una calculadora. Este programa
guientes procedimientos :
disponibles'
MostrarMenu: Sacar por pantalla el menu con las operaciones
el resultado de sumarlos'
Sumar: Recibir dos nmeros reales y mostrar por pantalla
el resultado de restarlos'
Restar: Recibir dos nmeros reales y mostrar por pantalla
multiplicacin'
\lultrpLcar: Recibir dos nmeros reales y mostrar por pantalla su
el resultado de divi-
Dir ir,1ir: Recibir dos nmeros reales y mostrar por pantalla
segundo nmero es
dirlts. Antes de utilizar este procedimiento se comprobar que el
drstrnto de 0.
que sern dos nmeros reales'
Lee rDosNumeros: Tendr dos parmetros de salida,
Elprogramaprincipaldebermostrarelmen,pedirunaopcinydependiendodela
Esto se repetir
opcin escosida. eecuiar los procedimientos descritos corespondientes'
hasta que el usuario decida terminar el programa'
Pnosr,rN,rls 9t

4.11.12 Calculadora de complejos


Un nmero complejo es un nmero de la forma a+bi, donde a y b son nmeros reales e
i2= l. Escriba un programa dirigido por un men que lea dos nmeros complejos (a+l
se introducir como un par de nmeros reales a y b) y permita al usuario seleccionar
la ejecucin de la suma, resta, multiplicacin o divisin. Estas operaciones se debern
implementar mediante subprogramas y el resultado se mostrar en la forma a+bi. Las
cuatro operaciones se definen de la siguiente manera:

o (a+bi) + (c+di) = (a+c) + (b+d)i


o (a+bi) - (c+di) = (a-c) + (b-d)i
o (a+bi) x (c+di) = (ac-bd) + (ad+bc)i
o (a+bi) / (c+di) = (ac+bd) l(c2+d2) + ((bc-ad)/ 1c2+d2 i
El programador debe cerciorarse antes de realizar la divisin que c y d no valen simul-
tneamente cero.

4.l1..l3 Primalidad
Considere las siguientes propiedades relacionadas con la primalidad de un nmero:

o Un entero superior a2 no puede ser primo si es par.

o Un.entero n superior a 3 slo puede ser primo si verifica la propiedad:

n2 mod24 = 1.

o Un entero positivo n es primo si y slo si no tiene divisores ente 2 y lsqrt(n))


(est funcin equivale a la parte entera delaraz cuadrada de n).

y basndose en ellas, escriba los siguientes subprogramas:

1. Uno que indique si un entero verifica la propiedad siguiente:


nz mod24 = l.
2. Uno que indique si un entero tiene algn divisor entre2y lsqrt(n)).
3. Uno que indique si un nmero es primo o no, descartando primero los pares, com-
probando luego la propiedad n2 mod24 = l, y flnalmente comprobando que no
tiene divisores entre 2y lsqrt(n)).

Realice un programa que pida al usuario que introduzca un nmero entero y le devuelva
un mensaje avisndole si el nmero introducido es primo o no utilizando los subprogra-
mas anteriores.
92 SUSpnOCNAMAS: PROCEDIMIENTOS Y FUNCIONES

4.11.14 Sucesiones

Considere las sucesiones cuyos trminos estn def,nidos de1 siguiente modo:
i. : 9l+

l),,=l'.,t l -
,, t1, : -Vn -3

Se observa, que para avanzar a travs de sus trminos, basta con hacer rodar dos de
ellos consecutivos. Por ejemplo, si se toman como los dos primeros trminos 2 y 3, se
obtienen los siguientes 2,3,2,1 ,1,2,3,... que, slo por casualidad, son todos nmeros
enteros. Por otra parte, es fcil verihcar que, para dos trminos iniciales cualesquiera de
9t*, la sucesin generada mediante la relacin recurrente anterior es cclica,
V by.b2 9t+, !peN: V n ) 1,b,,+p=b,,
Es decir, considerando los trminos consecutivos cl y c2 (con valores iniciales b1 y
b2), basta con hacerlos aYanzaf hasta que se tenga, nuevamente , c,, = bt Y cn+1 = bz, Y el
perodo p ser el nmero de avances efectuados. Se pide:

1. Escriba un subprograma que calcule el perodo de una sucesin dados sus dos
primeros elementos.

2. Escriba un subprograma que halle la suma de los n primeros trminos de dicha


sucesin.

3. Escriba un programa que permita hacer los clculos implementados en los dos
subprogramas anteriores mediante un men de opciones.

4.LL.l5 Trayectoria
Se quiere impiementar un programa para calcular la trayectoria de una pelota de tenis en
un sistema de referencia bidimensional, donde el eje x son las abcisas (eje horizontal) y
el eje y son las ordenadas (vertical). Supngase que en t = 0 segundo, la pelota de tenis
es lanzada desde la posicin inicial dada por el punto (xo, )o) con una velocidad inicial
cuya magnitud es Ve (m/seg) y formando un ngulo de 0 grados con la horizontal. Las
ecuaciones para la posicin de la pelota para cualquier tiempo t (siendo G=9,8 m/seg2
la aceleracin de la gravedad terrestre) son:
\rtr =,rr-r + V0 * COs (0) * t;
\ir -r, , + Vo x sen (0) * t- ll2 (g*r2);
S: pi.le:
.r Reelizar un subprograma que vaya generando la trayectoria x(t) e y(0 para inter-
..
- . . re rLempo de 0,5 segundos y devuelva la distancia mxima recorrida por la pelota
D r e,:r:ntpo(t)queestenel aire,dadoslaposicininicial(xo,)o), lavelocidaddelan-
zan-Lienro \i ngulo 0 expresado en grados. (La distancia mxima (x) se alcanza
v e1
euando 1a peiota cae al suelo (y<=0)).
Pnonrnntas 93

b) Realizar un subprograma que vaya generando la trayectoria y(t) para intervalos de


tiempo de 0,5 segundos y devuelva la altura mxima (y) que alcanza la pelota, dados la
posicin inicial,1,6, la velocidad de lanzamiento Vs y el ngulo 0 medido en grados.
c) Realizar un programa que pida al usuario los datos del lanzamiento (posicin
inicial (xo, -yo), vekcidad inicial Vs y ngulo de lanzarniento 0 en grados, y muestre por
pantalla la distancia mxima que la pelota alcanza, el tiempo que est en el aire y Ia
altura mxima.

4.ll.16 Funcin seno aproximada


Escribe un programa que permita determinar el valor de sen(x) (mediante un subpro-
grama ) a partir de la siguiente serie:
sen(x)-Iil o{-t)'-,]; l, :r-+-+-
El programa deber pedir elnmero de trminos y el valor de x.

4.11.L7 Suma de nmeros primos


Escribe un programa que dado un nmero entero positivo mayor que dos que pedir por
teclado y realice una llamada a un subprograma que recibir eI nmero y devolver si
existen o no dos nmeros primos cuya suma sea dicho nmero. En el caso de que existan
el subprograma los devolver. El programa mostrar un mensaje con los dos nmeros
primos si existen.
Ejemplo, si el nmero es 12,12=5+1.

4.11.18 Pi
Escribe un programa que permita calcular el valor de t mediante las siguientes series:
n = ll2 sqrt(2zl+ 24122+ 24132+24142+ ...)
lt = 2* * 413'* 415 . 615 . 6lJ ),1 811 . ...
211 ,r 213
EI programa deber pedir el nmero de trminos que debe calcular en cada serie y
mostrar los resultados respecti\,os.

4.11.L9 Capica
Escribe un subprograma en Pascal que reciba un entero y diga si es capica o no. Escribe
un programa que Lrtilice el subprograma anterior.

4.11.20 Rotar
Escribe un subprograma que reciba tres nmeros enteros y ios devuelva rotados circu-
larmente hacia ia izquierda. Escribe un programa que cornpruebe ei funcionamiento deI
subprograma"
94 SuspnocnAMAS: pRocEDIMIENToS Y FUNCIoNES

Ejemplo: si a=2 b=5 y c=7 ,wta vez ejecutado el subprograma se tiene a=5 b=7 Y
c=2. Y si se ejecuta de nuevo el subprograma para a=5b=7 y c=2 se obtendr a=7 b=2
y c=5.

4.12 Soluciones
4.12.1 Toro
Anlisis del problema: no es necesario ningn dato de entrada por parte de usuario, y
la salida debe ser la que se pide en el enunciado.

Diseo: se sigue el mtodo de diseo descendente. Intente hallar la solucin al pro-


blema inicial, descomponindolo en subproblemas.
Primer paso: el problema se podr resolver si se solucionan los siguientes pasos
(que constituyen el programa principal):
escribir una T,
escribir una O,
escribir una R y
escribir una O.
Si se hace un estudio ms detallado, se observa que basta con: escribir una T, escribir
una O, y escribir una R, ya que escribir una O se repite. Afortunadamente solo se tiene
que crear un nico subprogramapara escribir una O y utilizarlo dos veces.
Segundo paso: Como estas instrucciones (escribir una letra tan grande) no existen
en PASCAL, debe crearlas:
EscribirT: Su tarea es escribir una T como pide el enunciado. Para hacerlo, no
es necesario ningn dato calculado previamente, ni va a aportar ningn dato para su
posterior utilizacin. Por 1o que no es necesario poner ningn parimetro. Por tanto se
usa un procedimiento cuya cabecera es:

PROCEDURE EscribirT; {uo se aade ningn parmetro, ni hace falta


poner parentesis)
,O'
{onjetivo: Escribir una T con caracteres
-_ l
}
. LlrL, N ih^rf, \

l-il: ia:a por pantalla cinco Ineas que representan una T)

Esre procedimiento debe escribir lnea a lnea, en orden adecuado los caracteres 'O'
iriv---.1r',,. i para tbrmar ia letra T. No se necesita ninguna variable local.

escribir ( '00000' );
escribir(' O')
escribir(' o')
escribir(' 0')
escribir(' 0')
Sor,ucronrs 95

Como cada linea tiene una traduccin directa al lenguaje de programacin no hace
falta refinar ms.
Se sigue idntico razonamiento para el resto de subprogramas.

Implementacin:

PROGRAM Escrj-birToro ;
{Onietivo: Sacar por pantalla la palabra TORO escrita en
vertical y con eI carcter 'O')

PROCEDURE EscribirT;
{Uo se aade ningn parmetro, ni hace falta poner
parntes i s)

{Onletivo: Escribir una T con cara^l-oroo /A'l


{nRr: uinguna}
{eOSf: Saca por pantalla cinco lneas que representan una T}

BEGIN {Escribirr}
writeln ('00000, ) ;
writeln (' 0' ) ;
writ.eln (' o') ;
wrireln(' O');
writeln (' o' ) ;
END; {rscribirr}

PROCEDURE EscribirO;
{Onletivo: Escribir una O con caracteres 'O'}
{eRr: uinguna}
{nOSf: Saca por panta}Ia cinco Ineas que
representan una O)

BEGIN {rscribir0 }
writeln (' 0OO') ;
writeln ('o 0, ) ;
writeln ('0 o' ) ;
writeln ('0 O' ) ;
writeln (' OOO' ) ;
END; { uscribirO }

PROCEDURE EscribirR;
tUOletIVo: Escrrblr una R con caracteres 'O')
T ^. ,
SUNPNOCNAMAS: PROCEDIMIENTOS Y
FUNCIONES
96

{eRu, Ninguna)
{eOst:Saca por pantalla
cinco }neas que

representan una R)
, " _),
RtrGTN i ESCrrblTR i
writern ('oooo' )
writeln ('0 o'
wrrteln ('0000' )
writeln ('o 0' )
writeln ('o o'
. .. ' .\
END; {Escrrbrrxl
todos }os subprogramas' puede
{Una vez que ha escrito
usarlos de manera adecuada en ef programa principal)

BEGIN {Programa PrinciPal}


{ReaIiza las Ilamadas a los
subprogramas}
FscribirT; iNo tiene parmetros' con 1o cual no es
necesario Poner Parntesis)
EscribirO;
EscribirR;
EscribirO;
END. {Programa PrinciPal}

4.12.2 Otro toro


dato de entrada por parte de usuario'
y
Anlisis del Problema: no es necesario ningn
la salida debe ser la que se pide en el enunciado.

Intente hallar la solucin al Pro-


Diseo: se sigue el mtodo de diseo descendente'
blema inicial, descomponindolo en subproblemas'
si se solucionan los siguientes pasos
Primer paso: El problema se podr resolver
(que constituyen el programa principal):
escribir una O,
escribir una T,
escribir una R,
escribir una O,
escribir una T,
escribir una O,
escribir una R Y
escribir una O.
'Y\

Sor,ucroNrs 91

hace un estudio ms detallado, se observa que basta con: escribir una T, escribir
Si se
una O. y escribir una R, ya que escribir una O, escribir T y escribir R se repiten. Igual
que en el ejercicio anterior solo se tiene que crear un nico subpro-qrama para cada letra
y utilizarlo las veces que haga falta.
Segundct paso: Como estas instrucciones (escribir una letra tan grande) no existen
en PASCAL. debe crearlas. La forma de disear los subprogramas es idntica a la ex-
presada en el ejercicio anterior por 1o que se omite.

Implementacin:

PROGRAM EscribirOtroToro ;

{Onetlvo: Sacar por pantalla Ia palabra OTRO TORO escrita en


vertical y con el carcter 'O')

PROCEDURE EscribirT; {llo se aade ningn parmet.ro, ni hace


falta poner parntesis)
{OnSetivo: Escribir una T con caracteres 'O'}
{nnn, Ninguna}
tPOST: Saca por pantalla cinco 1neas
I ^ ^-
-
que
representan una T)

BEGIN {Escribirt}
writeln ('O0OOO' ) ;
writeln (' o') ;
writeln (' o') ;
writeln (' o') ;
writeln(' O');
END; {Uscribirt}

PROCEDURE EscribirO;
{Onietlvo: Escribir una O con caracteres 'o' )
{enn' uinguna}
tPOST: Saca por pantalla cinco 1neas que representan una
I _ ^
-_
O)

BEGIN {Escribiro}
writeln (' OO0' ) ;
writeln ('0 O' ) ;
writ.eln('O 0');
wrireln ('0 0' ) ;
writeln (' ooo' ) ;
I

98 SuspnocnaMAs: pRocEDrMIENTos y FUNCToNES

END; {uscribirO}

PROCEDURE EscribirR;
LOber--ro: Escribrr una R con caracteres '0'-|
: N Inguna
t rRE
\
J

ipcsr: Saca por pantalla cinco Ineas que


representan una R)

BEGIN {EscribirR}
writeln ('0000' ) ;
writeln ('o o' ) ;
writeln ('0ooo' ;
writeln ('0 O' ) ;
writeln ('0 0' ) ;
END; {EscribirR}

iuna vez que ha escrito todos los subprogramas, puede


usarlos de manera adecuada en el programa principal)

BEGIN {lrograma principal}


{Realiza las llamadas a los subprogramas}
EscribirO; {mo tiene parmetros, con lo cual no es
necesario poner parntesis)
EscribirT;
L d^r hr rD.

[ ^7 h rl].

!'^vi
!Uul h vrl'.
v!! ,

EscribirO;
E s cribi rR;

!ur Mrw i

ENIJ . t Programa prrnc rpal -}

>
En este e.jercicio se pueden observar las ventajas de la subprogramacin: Evita la dupli-
cidad de cdi_so. clarifica el programa principal y facilita el mantenimiento (debido a que
<i re equivoca al escribir una letra. solo tiene que mirar el subprograma que se encarga
Je e 1l.i ,.

1.12.3 \uevo toro


\nlisis del problema: es necesario conocer el carcter con el que el usuario quiere
irrrnrur la palabra TORO. La salida debe ser dicha palabra escrita con el carcter elegido.
Sor,ucroNrs 99

Diseo: se si-eue el rntodo de diseo descendente. Intente hallar la solucin al pro-


blema inicial, descomponindolo en subproblemas.
Primer paso: El problema se podr resolver si se solucionan los siguientes pasos
(que constituyen el programa principal):
pedir al usuario que introduzca el carcter escogitict.
escribir una T con dicho carcter.
escribir una O con dicho carcter,
escribir una R con dicho carcter y
escribir una O con dicho carcter.
Si se hace un estudio ms detallado, se observa que basta con: escribir una T, escribir
una O, y escribir una R, ya que escribir una O se repite. Afortunadamente solo se tiene
que crear un nico subprograma para escribir una O y utilizarlo dos veces.
Segtrndo paso'. Como estas instrucciones (escribir una letra tan grande) no existen
en PASCAL. debe crearlas:
EscribirT: Su tarea es escribir una T corno pide el enunciado. Para hacerlo, es ne-
cesario conocer el carcter elegido por el usuario. No va a aportar ningn dato para su
posterior utilizacin. Por 1o que es necesario pasar al procedimiento un carcter que se
har por medio de un parmetro de entrada (por valor). El subprograma debe ser un
procedimiento cuya cabecera es:

PROCEDURE EscribirT (caracter:char) ;


{OUletivo: Escribir una T con el carcter pasado en carcter}
{ eRn t'tinguna
' }
{nOSf: Saca por pantalla cinco Ineas que representan una T}
Este subprograma escribe linea a linea, en orden adecuado los caracteres necesarios
para fbrmar la letra T. No se necesita ninguna variable local.

escribir(cinco caracteres iguales) ;


escribir(tres espacios y un carcter)
escribir(tres espacios y un carcter)
escribir(tres espacios y un carcter)
escribir (tres espacios y un carct.er)
Idntico razonamiento para el resto de subprogramas.

Implementacin:

PROGRAM EscribirToro2 ;
{Onletivo: Sacar por pantalla la palabra TORO escrita en
vertical y con el carcter elegido por el usuario)
VAR
Iecra: char; {Para almacenar eI caracrer}
SunpnocnAMAS: PRocEDTMIENToS Y FUNCIoNES

EscribirT (caracter:char) ;
'?,OCEDURE
,CbjeLivo: Escribir una T con el caracter)
l
lPRhl : Nrnguna.l
inOSf, Saca por pantalla cinco 1neas que representan una
T)

BEGIN tEscrlbrr.L')
writeln (caracter, caracter, caracter, caracter, caracter) ;

writel-n (' ' , caracter) ;


writeln (' ' , caracter) ;

writeln (' ' , caracter) ;


writeln (' ' , caracter) ; ..r,1

END; iEscrlblr'.1' ] ip
PROCEDURE EscribirO (caracLer: char) ;
{onietivo: Escribir una O con caracteres} ..

{tRu' Ninguna} .i

{lOSt: Saca por pantalla cinco Ineas que representan una O} ':
BEGIN {Escribiroi =
writeln (' ' , caracter, caracter, caracter) ;
:
writeln (caracter, ", caracter) ;
writeln (caracter, ' ' , caracter) ;
writeln (caracter, ' ' , caracter) ;
writeln (' ' , caracter, caracter, caracter) ;
END; {uscribirO}

PROCEDURE EscribirR (caracter:char) ;


{ofietivo: Escribir una R con caracteres}
{lRu: llinguna}
ieosr:Saca por pantalla cinco lneas que representan una
R)

BEGIN {uscribirn}
writeln ( caracLer, caract.er, caracLer, caracter) ;
writeln(caracter, ",caracter) ;
writeln (caracLer, caracLer, caracter, caracter) ;
writeln (caracter, ", caracter) ;
r+riteln (caract,er, ",caracter) ;
E{l; {uscribira}
iuna vez que ha escrito todos los subprogramas, puede
usarlos de manera adecuada en eI programa principal)
Sor,ucroNBs 101

BEGIN {Programa principal}


writeln ('Introduzca una letra para formar 1a palabra ,) ;
readln ( letra) ;
{nealiza las }}amadas a los subprogramasi
EscribirT (1etra) ;
(letra) ;
EscribirO
(letra) ;
EscribirR
(letra);
EscribirO
END. {Programa principal}

1.12.4 Traza y comprensin


Apartado a)

Las instrucciones se empiezan a ejecutar a partir del ercrl\T del programa principal.
Cuando en el programa se encuentra una llamada a un subprograma, el programa se
suspende temporalmente y pasa e1 control al subpro-grama. El subprograma funciona
como un programa. empezando a ejecutarse a partir del sClN del subprograma y fina-
iizando en el END; . una vez terminado el subprograma, el programa se reanuda en Ia
siguiente instruccin donde se detuvo. Por 1o que el orden de ejecucin queda:

PROGRAM Secuencial;
{Onetivo: Probar procedimientos}
VAR
a, b: integer;
resultado: integer;

PROCEDURE Primero (VAR suma: integer; num, num2:integer);


{onietivo: Devolver Ia suma 6ts nsrrrrml \
{eRn' xinguna}
{POSI: suma = num + num2i
BEGIN {lrimero}
_9_ suma := num + num2;
END; { nrimero}

PROCEDURE Segundo (num:integer) ;


{Onletivo: MosLrar por pantall-a un mensaje indicando
el valor del nmero increment.ado en una unidad)
{enr, uinguna}
TPOST: Saca por pantalla: El resuftado
I _ ^ __

incrementado es igual a (valor de num) )


102 SuspnocnaMAS: PROCEDIMIENTOS Y FUNCIONES

VAR
aux: integer;
BEGIN {Segundoi
_5_ aux := num + 1;
_6_ writeln ('El resultado incrementado es igual a ' , aux) ;
END; {Segundo}

BEGIN {Programa principal}


_1_ writeln ('Introduzca dos nmeros enLeros
_2_ readln (a, b);
3 resulcado := 4;
Seguncio tresu-tacio )
-=- writeln(resultado) ;
_1_ ; a

_8_ Primero (result.ado, a, b) ; :


_10_ writeln (resulcado) ;
END. {Programa Principal}

Apartado b)

Hay dos instrucciones que son llamadas a procedimientos definidos por el usuario, r
son: Segundo (resultado) ; y Primero (resultado, a, b) ;

Apartado c)

No son llamadas a procedimientos todas las asignaciones. Es decir, existen tres instruc-
ciones que no son llamadas a procedimientos (se consideran llamadas a procedimientos
las instrucciones de entrada/salida, ya que son llamadas a subprogramas predefinidos en
el lenguaje).

Apartado d)

Sr :e introduce por teclado 5y 11,1os valores de las variables quedan a:=5 Y b:=14. El
l'i :r'.1I1).r Iltr,:lri.rru l() siguiente:

-:--:-i,.::a dos nmeros enteros


.=
:- :==*-:-do incrementado es igual a 5
=
Sor-ucroNBs 103

,{partado e)

Antes de la llamada a Primero. independientemente de 1os valores que le den a las


variables a y b, resultado vale 4, ya que el procedimiento segundo no cambia su
valor.

Apartado f)

Como se comenta en el apartado e). antes de llamar al procedimiento Primero, el valor


de resultado es independiente de los valores de a y b.

Apartado g)

Si se cambia la instruccin Primero (resultado, a, b) por primero (a+b, a, b)


el compilador dar un error de tipos, ya que espera que el primer parmetro sea una
variable, sin embargo recibe una expresin. Por 1o que no se podr ejecutar el programa.

Apartado h)

La tabla 4.6 completa es (siendo ? un valor desconocido o "basura" y un espacio en


blanco indica que la variable no existe):

Ins a b result suma num num2 aux Entrada Salida


1 :)
(,' :)
(r' )
<i' Introd..
2 -) 8 :)
(" 38*-
3 -) B 4
4 --) B 4 4 (,'l.
5 --) 8 4 4 5
6 J 8 4 4 5 El res... 5
1 -) 8 4 4
8 J 8 4 4 -1 8
9 J 8 11 11 J 8
10 J 8 11 11

Tabla 4.6: Traza y comprensin

4.12.5 Mtodo Cesar


Apartado a)

FUNCTION Cifrar(1et,ra: char; clave: integer) : char


{enU: letra es un carcter que est entre fa rrAn y la ilZr}
104 SuspnocnAMAS: PRocEDIMIENToS Y FUNCIoNES

) l.ra--il I
^

{losr: Cifrar devuelve la letra correspondiente a Ia let'ra


inicial desplazada en eI alfabeto,clave" posiciones)

VAR
.l 'l ranar.
f . tlluuYU! /

cifrada: char;

FUNCTION Sucesor(Iet: char) : char;


lrAtr y }arr Z', }
{pRs, Iet es un carcter entre }a
en el alfabetoi
{eOsr: Sucesor devuelve el carcter siguiente
Sr eI carcter es "Z" devuelve fa "A")
BEGIN {Sucesor}
IF (Iet = "7"; THEN
Sucesor : = "4"
ELSE
Sucesor := succllet)
END; {Sucesor}

BEGrN {cifrar}
crfrada := letra;
FOR i := 1 TO (c1ave-l) D0
cifrada := Sucesor(cifrada) ;

Cifrar := cifrada;
END; {cifrar}

Apartado b)

FUNCTION Descifrar(Ietra: char; clave: integer): char;


ttAII y la "Z"}
{eRn, letra es un carcter que est entre Ia
{ v clave'=o }
{fOSf: Descifrar devuelve Ia }etra correspondienLe a Ia letra
inicial desplazada hacia atrs ,,c1ave" posiciones en el alfabeto)
VAR
.l 'l rtaar.
t. rlrLUYU! /

descifrada: char;

-LINCTION Antecesor (1et : char) : char;


ipRs, Iet es un carcter entre la rrArr y la "Z")
{
posr: Antecesor devue}ve el carcter anterior en el alfabeto)
Si et carcter es ttA't devuefve 1 7rr ) rr
SoructoNBs 105

BEGIN {antecesor}
IF (1et = ,'4',
THEN
Antecesor := "Zu
ELSE
Antecesor = pred (1ec )

END; {antecesor}

BEGIN ioescifrar)
descifrada := letra;
FOR i := 1 TO (clave-l) D0
descifrada : = antecesor(descifrada)
Descifrar : = descifrada
END; {Oescifrar}

Apartado c)

PROGRAM Cesar:
VAR
opcion, 1etra, resultado: char;
cfave: integer;

FUNCTION Cifrar(letra: char; clave: inLeger): char;


{ver apartado a) }
FUNCTION Descifrar(letra: char; clave: integer): char;
iver apartado b) )

BEGIN {Programa principal}


writeln (', Cf ave para cif rar/descif rar,') ;
readln (clave);
REPEAT
L7r.iF6lhrt
vv!f Lurlr\ a
u a]F---rr\
Lfrrq! -
/ i
wrireln ( "D- Descifrar', ) ;
wrirelnr "F- Final tzar', ) ;
writeln('Elija opcion: ,, );
readln (opcion);
CASE opcion OF
,,C',, 'r c": BEGIN
wrireln ( ,'Lecra a cif rar: ,, ;
readln (letra) ;
resultado := cifrar(letra, clave)
write (,, La letra cif rada es ,, ) ;
writeln (resultado);
Y FuNCroNEs
-, t( SunpnocnAMAS: PRocEDrMrENTos
-1.12.
END;
trDr It
drr , BEGIN - -rl-il
,
writeln( "l'etra a descifrar: "); - .:I{u
readln(letra); clave)
-;:lL
resultado := descifrar(letra'
;
,.llk
write("La fetra descifrada es ") ; (
writeln (resultado) ; _.-ti
END; _.i
rFrr , rtfrr : writeln ("FIN"); I
.:
ELSE
writeln("Opcin no vlida") ;

END; {cesr}
rrFtr) OR (opcion-rt f 'r )'
UNTIL (opcion =
:ND. {Programa PrinciPali

4.12.6 Errores
La solucin se halla enlatabla 4'7 '
B-reve
expticacin

modifl-
i
tanl" giobul'
da deber ser
El segundo Parmetro
una variable (paso pot tefutencia)' .
ffieunparme-
d mismo
Interno existe Y es vlsl
puede
y-", e*,"*o. Fuera de su mbito no
y debe ser lnvo-
"srnprocedimiento
cado fuera de una expresil
solo de-
29
vuelve valores en 10! i'agmetrgs'
30
3l ffitaldebe
invocada dentro d" ut3jl!t"ti*
errores
Tabla4.7: Problema sobre
Sor,ucroNBs t07

4.12.7 Nmeros romanos


Para realizar el programa de manera correcta, se disean dos subprogramas que se en-
carguen de realizar cada uno la opcin correspondiente. Uno de ellos realizar el paso
de numeracin romana a arbiga y otro realizar la comprobacin de la correccin del
nmero.
Como hasta ahora no se ha estudiado ninguna estructura que pueda almacenar una
cadena de caracteres, con cada opcin habr que leer el nmero romano carcter a ca-
rcter e ir procesndolos a lavez.
El programa principal consistir en un bucle que mostrar el men y pedir la opcin.
[Jna vez conocida, realizar la llamada al subprograma coffespondiente. En el caso que
el usuario escoja finalizar, el programa terminar.
Una implementacin completa que soluciona el problema es la siguiente:

PROGRAM NumerosRomanos ;

{onletivo: Cambiar de numeracin y comprobar la validez de un


nmero romano)
VAR
opcion: char;
num: integer;

PROCEDURE Romano2Arabigo ;
{lee por teclado un nmero romano correcto de menos de 15
cifras y/o terminado en un punto, devolviendo su valor por
pantalla, por 1o que no son necesarios ningn parmetro)

VAR
cont: int.eger; {contador de cifras}
acum: integer; {guarda 1a suma parcial}
ns, nc: integer; {valor del siguiente y del actual}
cart sig: char; {Carcter actual y siguiente}
FUNCTION VaIor(c: char): integer;
{necibe un carcter y devuelve el valor equivalente. Si no
corresponde con ninguna cifra romana devuelve cero.|

BEGIN {va:.or}
CASE c OF
'M' , 'm': Valor := 1000;
'D' , 'd' : Valor := 500;
'C' , 'c' : Valor := 100;
'L' , 'L' : Valor := 50;
108 SunPnocnAMAS: PROCEDIMIENTOS Y FUNCTONES

,Y/ 'x' : ValOf := 10;


q.
'u' , '!' : Va]-or :=
t-t ,.r, : ValOf := 1;
ELSE
Valor : = 0;
END;
)
END; iVaIoI )

BEGIN {Romano2Arabigo)
aCUm = 0;
:

Cont : = 1;
en un Punto ( ' ) ') ;
writeln ('Introduce el ntmero romano acabado
read (car) ;
WHILE (car <> ' '') AND (cont <=
15) DO BEGIN
read (sig) ;
flC := valor(car);
ns := valorrsig) ; hay que restar}
IF (nc < ns) THEN {si el siguiente es mayor
BEGIN
aCUm := acum 1 (nS-nC); los dos}
read(car); {lee otro carcter pues ha procesado
cont := cont + 1; {aumenta e1 contador}
END
o igual}
ELSE {si la cifra siguiente es menor
BEGIN
acum := dCUfil + (nc);
Car := Sig;
END;
cont := conL + 1;
END; {wurlu}
writeln (' equivale a ' , acum'
t
en notacin arbiga') ;

F.ND ; {Romano2Arabigo }

Cc::recto: boolean;
: ,l,CTlCl;
teclado Y comprueba si es correcto
{tee un nmero romano Por enunciado, devolviendo
o no de acuerdo con Ia reglas dadas en eI
TRUE si es correcto Y FALSE en
caso contrario )

VAR
cont, cmr cd, c}, cv, cx, cc' ci : integer;
car : char;
fin : boolean;

t
Solucrours 109

BEGrN {correcto}
Cm:= O;
cd := 0;
cI := 0;
ar .= 0'
v .-

CC := 0;
ci := 0;
nnl- .- T.
writeln ('Introduce eI nmero romano acabado en un punto (.) ') ;
I read (car);
.F.i- - +-'t^^.
!frt .- rafDgi
I^iHILE (car <>'.') AND (cont<=15) AND (UOT f in) D0
BEGIN
CASE car OF
,M,,,M, : BEGIN
.- m r -l .
CM

fin ._ LILL 2
f.
J,

END;
,D,, ,d, : BEGIN
rA .- l r T

trfl .- !u 2 f ,

END;
t (1 t t at
BEG]N
uu .- gL 1.
T r,
fin .= \ 1.
END;
,L" 'I' : BEGIN
el .= l +' 'l
+t

f in .= l : l.
END;
tyt tyl
BEGIN
lY '= eY + "l'
c:-
t-Ll-t := ux > J;
END;
,Y" 'V' : BEG]N
CV := CV + 1;
f in .= r\r : I.
END;
!t : BEGIN
^. .- ^.1 1-
110 SuspnocnAMAS: pRocEDIMIENToS Y FUNCIoNES

fin := ci > 3;
END;
ELSE
fin := true;
END; {casr}
read (car) ;
cont := coflt + 1;
END; {wurlu}
correcto := NOT fin;
END; {Correctoi

FLINCTION Menu: char;


{Muestra eI menu de opciones y devuelve Ia opcin escogida}
VAR
1:r.
BEGIN {uenu}
writeln ('1. - Cambiar de romano a arbigo') ;
writeln ('2. - Comprobacin de un numero romano') ;

writeln ('3. - Fin') ;


rar,4r n l\
\v/ ,

monll '= t'

END; {uenu}

BEGIN {Programa principal}


REPEAT
opcion := Menu;
CASE opcion OF

'1' : Romano2Arabigo;
'2' : IF Correcto THEN
writeln ('El nmero es correct.o')
ELSE
writeln ('El nmero es incorrecto');
,3, : BEGIN
writeln ('fin' ) ;
readln;
END;
:LSE
writeln ('Opcin no vlida' ) ;
,l. oo lj
l!sre
-l:l-- :ccion = '3' ;, ]
:-.- . l::Iama pIlnclpa1
-- J
Sor,ucroNrs 111

4.12.8 Multiplicacin con lpizy papel


En este programa se usa un tipo nuevo de datos denominado longint, que sirve para
ampliar el rango de los integer. Tiene las mismas operaciones y funciones que el tipo
de datos integer.
PROGRAM MuIt ipl icacion ;
{Programa que realiza la multiplicacin de
dos nmeros enteros sin usar el operador *)

VAR
, b, aux: longint; {Numeros a muttipticar}
productoParcial: Iongint; {fara el producto parcial}
suma, productoDesplazado: real;
cont: integer; {contador}
FIr'IJCTION NumeroCif ras (num: Iongint ) : integer;
{uora' Esta funcin no necesita desarrol}arser pero se hace para
que el lector tenga una idea clara de 1o que realiza)
,loon. i
I
{eOSf: NumeroCifras = nmero de cifras de num}
{untrada: un nmero entero l"argo}
{Satiaa: el nmero de cifras del ,imo-^l
VAR
cont : integer;
BEGIN iUumeroCifras)
.-nl .- 1.
WHILE num > 10 D0 BEGIN
Cont := cont + 1;
num := flUII] DIV 10;
END; {WUrlU}
NumeroCifras : = cont;
END; {UumeroCifrasi

FUNCTION Desplazalzquierda (num: Iongint; nveces: int.eger) :rel;


{ttora, Esta funcin no necesita desarro}1arse}
r--_
tPREj: nveCes>=Ui
r- ^ --
iPOST: Desplazalzquierda = num con nveces ceros aadidos por 1a
derecha i
{Untrada: Un nmero entero largo, el cua} va a ser
desplazado a 1a izquierda nveces)
{Satiaa: Un nmero real que es iguai al- nurnero entero desplazado
a la izquierda nveces)
tt2 SuNPNOCNAMAS: PROCEDIMIENTOS Y FUNCIONES

VAR
i : integer;
aUX: real;
BEGIN {oesPlazatzquierda}
aux := num;
FOR i:= 1 TO nveces DO

aux:= aux * 10;


DesPlazalzquierda : = aux
END ; { DesPIazaI zquierda }

FUNCTION Multrplica(num: longint; digito: integer) : longint;


{tlore, EsLa funcin no necesita desarrollarse}
{ene, aigito>= o y digito <=9}
{lost: MultiPlica = num*digito} entre 0 y
inrrtrada: Un nmero entero y un digito
9]
y digit'oi
isrfiar: La multiplicacin de num
ie1"*pfo: Multipli ca(234,3) --> 702)

VAR
acum: Iongint;
i : integer;

BEGrN {t'luftiPfica}
aCUm : = 0;

FOR i := 1 TO digito DO
acum := C1]fl + num;
MuttiPlica : = acum
END; {t'luftlPflca}

BEGIN {Programa PrinciPal}


{liae los nmeros y asegura que son positivosi
REPEAT
'*'::::eln ( ' Introduzca dos numeros enteros positivos' ) ;

::ai-r (a, b) ;
-! a<O)OR(b<0)THEN
-,r:::iteln (' iDeben ser positivos I ') ;
-l:--- a >= 0) AND 1 b >= 0) ;
-:.-::z'--za 1a variables)
ise usa para no modif icar eI segundo
operandoJ
1-::. '.= i;
._ 1.

: :a -:::-- : = i TO NumeroCif ra-q (b) D0 BEGIN


Sor,ucroNns 1r3

tHatta e_L producto parcial]


productoParcial: =MulLiplrca (a, aux MOD 10) ;
{lo desplaza a la izquierda}
productoDespl az ado : =DesplazaI zqurerda productoParc i aI (
,

cont-1);
{Acumula e1 resu}tado}
suma := slr + productoDesplazado;
{Rctualiza eI multip}icando}
aux := aux DIV 10;
END; {ron}
wriLeln(a, , b, ',=', , suma:0:0)i ',*',
END. {lrograma principa}i

4.I2.9 Palndromo
PROGRAIVI Capicua;

{OBJETIVO: Hallar un nmero palndromo mediante


sumas de un nmero con su reverso)
{fNfnaoa: Un nmero entero}
iSALIDA: Secuencia de sumas por pantallai

VAR
numero/ nreverso/ suma: integer;

f ,t*******ADADrf^nn /. I *******x I
L '. l

FUNCTION Reverso(n: integer) : integer;


I ___
L
.'"' . n\-{l
{ -PPLl
"-
t
I _ ^
tPOST: Reverso=
-_
n con las cifras aI revsi
VAR
temp, acumula: inceger;
BEGIN {Reverso}
l-omn .- r.
uuL,u .- 11 ,

acumula := 0;
WHILE (temp > 0) D0 BEGIN
acumula := acumula * 10 + (temp MOD 10);
temp := temp DfV 10;
END; {wHrlr}
ReverSO : = acumula
END; {Reverso}
114 SuspnocRAMAS: PRocEDIMIENToS Y FUNCIoNES

{
********APARTADO (b) ******** }
--
FUNCTION Palindromo(n: integer) : boolean;
^)
{ PRE: n>=u 1
{losr: palindromo= TRUE si n es capica
FALSE en caso contrario)
BEGIN {ealindromo}
palindromo := I1 = reverso(n) ;

END; {palindromo}

{
********4pARTADO (c) ******** }

BEGIN {Programa PrinciPat}


REPEAT
writeln ('Introduzca un nmero entero positivo') ;

readln (numero) ;

UNTIL (numero > 0);


REPEAT
nreverso := Reverso(numero) ;
Suma := numero + nfevefso;
writeln (numero,' +', nreverso, =',guma);
numefo := SUfl]i
UNTIL Palindromo (numero) ;
-a: A'l n .

END. iPrograma princiPat)

4.12.10 Nmero de la suerte


PROGRAIvI Suerte;
{oe,rurrvo: Hallar eI nmero de }a suerte de cada persona
partiendo de su fecha de nacimiento)
{sNrRAoe: Por Leclado, el da, mes y ao de nacimiento (en
forma numrica) i
:------i: [- numero de Ia suerte correspondiente]

::r:: -
:-r_,_:l::- = 3000;

.rj
l-:, :.=s, anno/ numerosuerte: integer;
Sor,ucroNns 115

FU$CTION SumaDigitos (n: inLeger) : integer;


lopu. ---n1
{eOSf:sumadigitos= suma de todos los digitos de n}
VAR
suma, t.emp: integer;

BEGIN {Sumaoigitos}
UULLLP .-
lamn ._ r.
11 ,

SUma : = 0;
WHILE (temp > 0) D0 BEGIN
Suma := Sufll + temp MOD 10;
temp := temp DIV 10;
END; {WUrlU}
SumaDigitos : = suma
END; {SumaDigicos}

BEGIN {Programa principa})


REPEAT
writeln('Da de su nacimiento (deI f al 31) ?,);
readln (dia) ;
UNTIL (dia >= 1) AND (dia <= 31);
REPEAT
writeln('Mes de su nacimiento (del f at 12) ?,);
readln (mes) ;
LINTIL (mes >= 1) AND (mes <= 12) ;
REPEAT
writeln ('Ao de su nacimiento (del 1900 aI 2OO4)?,);
readln(anno);
{Uo es necesario imponer esta restriccin, bastara
comprobar que es positivo)
IINTIL (anno >= 1) AND (anno <= I,IAXANNO) ;
numeroSuerte := sumaDigitos(dia) + sumaDigitos(mes) +
sumaDigitos (anno) ;
WHILE numeroSuerte >= 10 D0
numeroSuerte : = sumaDigitos (numeroSuerte) ;
writeln('Tu nmero de la suerLe es: ', numerosuerte);
readln
END. {Programa principal}
116 SunpnocnAMAS: PRocEDIMIENToS Y FUNCIoNES

4.L2.11 Calculadora
Una posrble solucin es:

PROGRAM Calculadora;

VAR
a, b: integer;
opcion: char;

PROCEDURE LeerdosNumeros(VAR i, j: integer);


BEGIN{ IeerNumero}
write ('Escribe eI primer operando: ' ) ;
readln(i);
write ('Escribe eI segundo operando: ' ) ;
readln (j ) ;
END; {IeerNumero}

PROCEDURE Sumar (n1, integer);


BEGIN {sumar}
writeln ('La suma t n1 rt n?\
L!- I I
T)
l;Nll; { sumar J

PROCEDURE Restar(nl, integer) ;

BEGIN {restar}
writeln ('La resta
,
nT
lla
a\
tlLl I

END; {restari
PROCEDURE Multiplicar (n1, n2 :
'lrllLUYU!
-r^^^?\ / /

BEGIN
writeln (' La multiplicacin es: ' , nL * n2);
1

END; lmultlpllcarl

PROCEDURE Dividir(n1, n2: integer) ;


BEGIN
writeln('La divisin es: ', (nr I n2):0:2) ;

mrD; tdividir)
PROCEDIIRE MostrarMenu ;
BEGIN
writeln;
writeln(' rntroduzca una opcin:
Sor,ucroNns 111

writeln('1.- Sumar');
writ.eln('2.- Restar' ) ;
writeln('3.- Multiplicar' ) ;
writeln('4.- Dividir' ) ;
writeln ('0. - Finalizar ') ;
'.'-i r^1 -.
END; {ttenu}

BEGIN{ Programa principal }


REPEAT
MostrarMenu;
readln (opcion) ;
IF (opcion >= 'L') AND (opcion<='4') THEN
BEGIN
leerdosnumeros (a, b) ;
.^etr ^ion oF
'1': Sumar(a, b) ;
'2' : Restar (a, b) ;
'3' : Muftiplicar(a, b) ;
'4' : IF (b <> 0) TUUU
Dividir (a, b)
ELSE
writeln (' DIVISION POR CERO I I I I ') ;
END; {casu}
urrn / ruI
!r!! Irt J
ELSE TFopcion <> '0' THEN
writeln ('Opcin incorrecta, ) ;
IINTIL opcion = '0' ;
hjNlj. tPrograma prlncrpal i

4.12.12 Calculadora de complejos

Existen varias formas de enfocar el problema. En una de ellas, los subprogramas realizan
la operacin y devuelven el resultado. Se ha tomado este enfbque para realizar 1a primera
solucin propuesta. La segunda solucin se basa en que los subprogramas realizan la
operacin y muestran por pantalla eI resultado. En la tercera propuesta los subprogramas
realizan la operacin y el resultado se devuelve en el primer operando, La diferencia
entre ellas est en el paso de parmetros (y en la consecuente llamada).
Primera solucin propuesta. Los subprogramas guardan el resultado de la operacin
en otro nmero complejo.

PROGRAM Complejosl;
FUNcToNES
118 SurpnocnAMAS: PRocEDrMrENTos Y

VAR
, b, c, d, res1, res2: real;
opcion: char;
error: boolean;

PROCEDURE LeerComplejo(veR r' i: real);


BEGIN{LeerComPIejoi
write ('Escribe Ia Parte real: ' ) ;
readln (r) ;
write('Escribe Ia parte imaginaria: ') ;

readln(i);
END; {LeerComPlej oi

SumaComplejos(ref iml' re2' Im2:


real;
PROCEDURE
VAR resR, resl: real);

{eRn, NingunaJ
Ia suma de dos complejos
{losr: resR = Parte real de de la suma de dos complejos]
resr = Parte imaginaria
BEGIN {SumaComPlejos}
resR := re1 + re2;
resl im1 + im2;
'=
END; {SumaComPlejos}

PROCEDURE RestaComplejos (ref iml ' ' im2: real;


re2
VAR resR, resl: real) ;

{eRr, Ninguna}
fonqr. resR = Parte real de la resta de dos complejos
complejosi
resr = Parte imaginaria de la resLa de dos
BEGIN
resR := re1 - re2
resl := iml - im2;
END; {restaComPlejos}

ProdComplej"' (::1'
ruDr' .'::.,:"'
1i:''-::.,
PROCEDURE
VAK IesK' ruq!' /

j
?P., :;-:guna)
.?:S., :esR = Parte rea} del producto de d.os complejos
:esr = Parte imaginaria del producto de dos
comptejos)

:::-1.
t::?. := (re1 * re2 - im1 * im2);
1^-. trei * im2 + im1 * re2);
:ll-; :::1lc:r-ejosJ
Sor,ucroNss 119

PROCEDURE DivComplejos(re1, iml, Le2, im2: real;


\IAD racD -fSI: feal);
{nRr' uinguna}
{eOSr: resR = parte real de Ia divisin d,e dos complejos
resl = parte imaginaria de Ia divisin de dos complejos)
VAR
temp: real;
BEGIN
temp := sqr(re2) + sqr(im2);
resR := (re1 * re2 + iml * im2) / cemp;
resl := (im1 * re2 - re1 * im2) / t.emp;
END; {divcomptejos}

FIIIICTION Menu : char;


VAR
. n}^,-u .

BEGIN
REPEAT
r^ri 1-o"l -.

writeln(,Introduzca una opcin:, ) ;


writeln(,1.- Sumar,);
writeln(,2.- Resrar, ) ;
writeln(,3.- Multiplicar, ) ;
writeln(,4.- Dividir, ) ;
writ.eln(,0.- Finalizar, ) ;
writeln;
readln (c) ;
r"ritol-,

UNTIL (c>=,0,) AND (c<=,4,);


Menlr .- a.
END; {Nenu}

PROCEDRE Most.rarComptejo (Re, Im: real) ;


BEGIN
wril-e(Re:0:2);
1F (Im>0) THEN
wr_LLe1 + Ji
---^:L-1,

writeln (Im:0:2,,i,) ;
END; {MostrarComplejo}

BEGIN{ Programa principal i


lZ0 SunpRocnAMAS: PRoCEDIMIENToS Y FUNCIoNES

REPEAT
error := FALSE;
opcion : = Menu;
IF (opcion >= '1') AND (opcon<='4') THEN BEGIN
LeerComplejo (a, b) ;
T aarfanmnl
lEE!uvLtryruJv oia
ftv, d\
u/ ,

r-AeF'
vI!!vt/U nnr-i6n QP
, 1, : BEGIN

SumaComplejos(a, b, ct d, res1, res2);


writeln ('El resultado de sumar ')
END;
,2, : BEGIN
RestaComplejos(a, b, c, d, res1, res2);
writeln ('El resultado de restar ' )

END;
,3, : BEGIN
ProdComplejos(a, b, c, d,res1/ res2);
writeln ('EI resultado de multiplicar ')
END;
'4' : BEGfN
IF (c <> 0) OR (d <>
0) THEN BEGIN
DivComplejos(a, b, c, d, res1, res2);
writ.eln ('El resultado de dividir ')
END
ELSE BEGIN
error := TRUE;
writeln (' DrvrsrN POR CERO I I I I ',)
END;
END;
END; {cesE}
IF NOT error THEN BEGIN
MostrarComPlejo(a, b) ;
MostrarComplejo (c, d) ;
writeln ('es : ') ;
MostrarComPlejo (res1, res2) ;
:Yn .

r'-- l rul
-, ]
-*^] t .
utrull ^- - u
^t t
' ' - l
-_ - -.- -...^ ^.yrlnclpa-L
-,.- ---r-a
]

St,?ttndu solLtcin propuesta. Los subprogramas devuelven por pantalla el resultado


de ia operrcin,
Sor,ucroNns t21

PROGRAM Complejos2;

VAR
d, b, ct d: real;
opcion: char;

PROCEDURE leerComplejo(VAR r, i: real);


BEGIN{ }eerN}
write ('Escribe 1a parte real: ') ;
-a..ll-/-\
! uqurll \r / ,

write ('Escribe la parte imaginaria:


readln(i);
END; {IeerN}

PROCEDURE SumaComplejos (a, b, ct d: real);


BEGIN
write ( 'La suma de ' , a:5:2 , ' + (' , b:5:2, 'i)
wlILe\ciaizt - .
,,,^t-^/^ + tt
\ | ,'-li)izt
^.tr.a 'i) es: ');
writeln(a + c:5:2,' + (', l-\ r v.J.-t
^.(.,
,i\/\
Ll I t

END; {sumaComplejos}

PROCEDURE ResLaComplejos(a, b, c, d: real);


BEGIN
write('La resta de ', a:5:2, ' + \', b:5:2, ,i) y ,);
write (c:5:2, ' + l' , d:5:2, 'i) es: , ) ;
writeln(a-c:5:2, ' + (', b-d:5:2, 'i)');
END; {RestaComp}ejos}

PROCEDURE ProdComplejos(a, b, c, d: real);


BEGIN
write('El product.o de ,, a:5:2, , +(,, h.tr.a
p.J.zt /.i\Ll ,,
I
,\
lt -

write(c:5:2, '+\', d:5:2, 'i) es:');


writeln( * 6 - b * d:5:2, , + (,, a * ,'l + h * c.tr.)
v.J.at 'r\').
Lt I I

END; {ProdComplejos}

PROCEDURE DivComplejos(a, b, c d:
BEGIN
write r ,La divisin de , , a:5:2 , '
\^iri rp(e\v.J./"\.) ttt /irLl ac.
\ ^.(., EJ.

write((a o c + b * d) / (sqr(q + + (');


|o writeln((b * c - a * d) / (sqr(g1
END; {divcomplejos}
F',-
t22 SunpnocnAMAS: pRocEDrMIENTos Y FUNCIONES

Te

FUNCTION Menu: char; re


VAR
c: char;
i BEGIN
REPEAT
I
,.,-.lr^ln.
l

,l
writeln (' rntroduzca una opcin: ') ;

* writeln('1.- sumar');
4
wriceln('2.' Restar' ) ;
writeln('3.- Multiplicar' ) ;
$
{t writeln('4.- Dividir' ) ;
$
T]
writeln ('0. - Finalizar ') ;

ral n.
It '.'r.i
YvI!LUr1f,

* readln(c);
'.'r.i ral n.

IF (c < '0') OR (c < '4') THEN


writeln ('opcin no valida ' ) ;
LINTIL (c >= '0') AND (c <= '4') ;
Monr . = .
END; {ttenu}

BEGIN{ Programa principal }


REPEAT
opcion := Menui
IF (opcion >= 'l') AND (opcion <= '4') THEN BEGIN
LeerComplejo (a, b) ;
LeerComplejo(c, d);
CASE opcion OF
'1': SumaComplejos(a, b, c, d); E-t

'2': ResLaComplejos(a, b, c, d);


'3': ProdComplejos(a, b, c, d);
'4'i IF (c <> 0) 0R (d <> 0) THEN
DivComplejos(a, b, c, d);
ELSE
WTiICIN (' DIVISIN POR CERO I I I I ')
:-\J; I f^.t
UAtr J
r --t
1r! I

- -rvIr - v
:"- -. _-.
___ :-
^...- r__,tcrpaI
=-. ^-i, ]
Sor,ucroNBs 123

Tercera solLtcitt propLtesta. Los subprogramas devuelven en el primero operando el


resultado de la operacin, por lo que se pierde el primer operando.

PROGRAM Complejos3;
{ calculadora }

VAR
d, b, c, d, resl, res2: real;
opcion : char;
error: boolean;
PROCEDURE LeerComplejo(VAR r, i: real);
BEGIN{LeerComp}ejoi
write ('Escribe 1a parte real: ,) ;
readln (r) ;
write ('Escribe la parte imaginaria: ,
) ;
readln (i) ;
END; {LeerComp}ejoi

PROCEDURE SumaComplejos(VAR re1, im1: real; re2, im2: real);


BEGIN
re1 := re1 + re2;
iml := im1 + im2
END; IsumaComplejos]

PROCEDURE RestaComplejos(VAR re1, im1: real; r?2, im2: real);


BEGIN
i rel := re1 - re2;
iml := iml - im2
END; {RestaComplejos}

PROCEDURE ProdComplejos(VAR re1, iml: real; re2, im2: real) ;


VAR
resR, resl : real;
BEGIN
resR := (re1 * re2 - im1 * im2);
resl := (re1 * im2 + im1 * re2);
r.a'1 .
= rcqQ.
f ml .- 761.

END; (ProdComplelos)

PROCEDURE DivComplejos (VAR rel, im1: real;re2, im2: real) ;


t24 SunpnocnAMAS: PROCEDIMIENTOS Y FUNCIONES

VAR Bi
lamn.
uUItLy. rarl
!tqf,
vac) roT. r r .

BEGIN
temp := sqr(re2) + sqr(im2);
resR := (re1 * re2 + im1 * im2) / temp;
reSI := (im1 * re2 - re1 * im2) / temp;
ro1 .
= rcqP.
rml .- raq

END; {Divcomplejos}

FIINCTION Menu: char;


VAR
^. -Lr.
BEGIN
REPEAT
','-.i ral n.

writeln ('Introduzca una opcin:


writeln('1.- Sumar');
writeln('2.- Restar' ) ;
writeln('3.- Multiplicar' ) ;
writeln('4.- Dividir', ) ;
writ.eln('0.- Finalizar', ) ;
'.,r.i tal r .

readln (c) ;
IF (c < '0') OR (c > '4') THEN
writeln ('opcin no vlida' ) ;
..'v.i tal n.

UNTIL (c >= '0') AND (c <= '4');


Mcnrr .= t.
f,, I
rt\ui tlvleIruJ

PROCEDURE MostrarComplejo (re, real);


BEGIN
write(re:0:2);
IF (im > 0) THEN
write ('+' ) ;
vrite (im:0 :2, ' i' );
vriteln;
END; {MostrarComplej o}
Sor,ucroNns r25

eecrN { Programa principal }


REPEAT
error := FALSE;
opcion:= Menu;
IF (opcion >='L') AND (opcion <= '4') THEN
BEGIN
LeerComplej o ( a, b) ;
LeerComplejo (c, d) ;
eAqE,
^n^ion 0F
' 1' : BEGIN
SumaComplejos(a, b, c, d);
writeln ('El resultado de sumar ')
END;
, 2, ; BEGIN
RestaComplejos(a, b, c, d) ;
wrteln ('81 resultado de restar ' )

END;
,3, : BEGIN
ProdComplejos(a, b, c, d);
writeln ('El resultado de multiplicar ,)
END;
,4, : BEGIN
IF (c <> O) OR (d <> O) THEN BEGIN
DivComplejos(a, b, c, d);
writeln ('EI resulLado de dividir ,)
END
ELSE BEGIN
error := TRUE;
writeln (' DIVISIN POR CERO I I I I
,)
END;
END;
END; {case}
IF NOT error THEN BEGIN
writeln ('es : ') ;
MostrarComplejo (a, b) ;
END;
END; {tr}
UNTIL opcion = '0' ;
l_
LjNIJ . t Programa prlnclpal -}
{'/
126 SunpnocnAMAs: pRocEDrMrENTos y FUNCIoNES

4.12.13 Primalidad
Una posible solucin es:

PROGRAM primalidad;
{otrjetrvo: Este programa sirve para saber si un numero es primo}
I -^- r I zndolo mediante un algoritmo 'inteligente' i
{rntrada: Un numero entero positivo}
{Satiaa: Mensaje sobre la primalidad del numero introducido)
VAR
numero: integer;

{
********pARTADO 3 ******** }

FU-NCTI0N EsPrimo(n: integer) : boolean;


{ PRE: n>U ) |

{lost: EsPrimo=TRUE si n es primo}


i EsPrimo=FALSE si n no es primoi

FUNCTION EsPar(num: integer) : boolean;


I ___
{PRhl: num>U) }
{posr. trcP:r=rftUE si num es divisible entre 2 )
f P"P:r=F'tr1f, en eI resto de los casos )
BEGIN {rsnar}
EsPar := (num MOD 2) = 0;
END; {esear}

I *********ADADTlnn i ******** 1
t'

FUNCTION Propiedad(numl-: integer) : boolean;


{Ofetivci: Verificar 1a propiedad 1}
{eRn: numl>0) }
{eOSt: Propiedad=TRUE si sqr(num1) mod 24 = 1}
{ eropiedad=FAlSE en el resto de los casos}
BEGIN ieropiedad]
Propiedad := (sqr(num1) MOD 24) = 1;
END; {eropiedad}

i *********ApARTADO 2********** )

FUNCTION TieneDivisores (nu: integer) : boolean;


{enn: nu>0) }
Sor,ucroNBs t21

{lOSr: TRUE si existe algn divisor entre 2 y sqrt(nu) }


{ ralSE en el resto de los casos}
VAR
i, maximo: integer;
BEGIN {Tieneoivisores }
; -- ).
maximo := t.runc (sqrt (nu) ) ;
WHILE (i <= maximo) AND ( (nu MOD i) <> O) DO
i := i + 1;
{nt nucte termina si i>maximo o si encontramos un divi sor )
{si nu MOD i = O ent.onces tiene divisores (TRUE) }
TieneDivisoreS:= lnl vTOl i = nl
END; {Tieneoivisoresi

BEGIN {rsnrimo}
IF (n <= 3) runl {et r, eI 2 y el 3 son primos )
EsPrimo : = TRUE
ELSE IF EsPar (n) THEN {Si es par, no es primo
)
EsPrimo : = FALSE
ELSE IF NOT Propiedad(n) THEN
{Si no cumple Ia propiedad, no es primo}
EsPrimo : = FALSE
jLSE tsr no es par y cumple }a propiedad, miramos
si tiene divisores entre f y sqrt (n) )
Esprimo := NOT TieneDivisores(n);
END; {Uslrimo}

BEGIN {Programa principal}


REPEAT
writeln ('Introduzca un numero posrtivo mayor que cero,) ;
readln(numero);
LINTIL (numero > 0);
write (, El numero , , numero) ;
IF EsPrimo (numero) THEN
writeln (, es primo , )
ELSE
writeln (' no es primo, ) ;
ra-'l -.

END. {Programa principal}


Y FUNCIONES
128 SUNPNOCNAMAS: PROCEDIMIENTOS

4.12.14 Sucesiones

Una posible solucin es:

PROGRAM Sucesiones;
rnxr^rrrn. trcia programa sirve para calcular el periodo y Ia
sucesin dada por ra
l"-;=u""l"r"r"ir1*uros rrminos d.e una
formula recurrente b (n) = ( (n-1) +1) /b
(n-2 ) para n>3 ]
escoger que se quiere calcular'
{untrada: Una opcin para 1a suma' el
los dos primeros trrinos y si va a calcul-ar
numero de trminos)
escogida' el periodo o Ia
{satiaa: Dependie"o a" }a opcin
suma de los i Primero trminos)

VAR
opcion:char; {para elegir e1 calculo}
bt, b2:real; {1os dos primeros trminos de lacalcular la
sucesin)
para suma)
terminos: integer; {numero de trminos

{************* APARTADO 1 ************}

FUNCTION Perodo (n7, n2: real): integer;


{PRE: n1>o Y n2>O) }
efectuados hasta que se tengan
{eOst: Periodo=nlr*",o de avances
nuevamente n1 Y n2 )
VAR
c1, c2 ,: real;
c3
contador: integer;

FUNCTION ComparaReal (a,b:real) :boolean;


{eRu: ninguna} }as 10 primeras
{losr: TRUE s} a y b tienen iguales aI menos
cifras decimales '
FALSE en e] caso contrario)
l:l.sl
EPSILON = 1E-10;
BEGIN {comParaReal}
ComParaRea1 : = (a < b + EPSILON) eND (a > b EPSILON)

B.ID; iComParaneal)

BEGIN ileriodo)
c2:=n\ ;
Sor,ucroNns t29

-l .- n)-
:cntador : = 0;
?,EPEAT
a1 .- ),
') .- 2.
c3 := (c2 + 1) I ct;
contador := contador +

LINTIL ComparaReal (c2 , n1) AND ComparaReal (c3, n2\ ;


Periodo := contador;
r^ , .
:-.-r ; t PeTIOOOJ
)

-:*********** APARTADO 2 ************)

:-liCT10N Suma (num1, num2: real; nterminos: integer) : real;


l?.E: numl>O, num2>0 y a>=2j
?cST: Suma= Sumatorio(b(n)) donde n va de t hasta nterminos)
-_ D

^1 ^a ^) ^^--^l ^_ --- -l
LI, CZ, UJ, PdIUId.I: ICCi-L;

cont: integer;
::GIN {Suma}
{inicialmente parcial va}e la suma de los dos primeros}
parcial := numl + num2;
^1 -.- .,1 .
!r LlUtLtr,
a)
az .-
. - r,,ml
tf uLtL /.

FOR cont : = 3 TO nterminos D0 BEGIN


c3 := (c2 + L) I cL;
n-^'i=l .-
.- n:ri11
ua!uaqa fr 2.
uJ/
Pqrutaa
1 .- ).

.-
. - aa.
gJ,
^a
-L

END; {ron}
Suma := parcial;
:ND; {Suma}

:-tlNCTI0N NumeroTerminos : integer ;


,lRE Ninguna)
'
POST : NumeroTerminos>=3 )

/AR
'irraaar.
f 1!ugYU!,

3EGIN {NumeroTerminos }
REPEAT
130 SurpnocnAMAS: pRocEDIMrENTos y FUNCToNES

writeln('Nmero de trminos que quiere sumar (>2),);


readln (n) ;
IFn<3THEN
writeln ('E1 nmero de trmj-nos debe ser mayor que 2I ,) ;
LTNTIL n >= 3;
NumeroTerminos := fli
END; {NumeroTerminos}
u
FUNCTION MostrarMenu : char ; fr
END
VAR
nn.
vy .
h:r.
elrq! ,
1.12.
BEGIN iMostrarMenu) --na p
writeln ('P.- Periodo de 1a sucesin');
writeln ('S.- Suma los n primeros trminos de la sucesin,); :ROC
writeln ('F. - Finalzar el programa, ) ; UlJu
writeln (' Introduzca la opcin: ' ) ;
readln (op) ;
MostrarMenu := opi i Ent
END; iMostrarMenu)
5a1
PROCEDURE PedirDosTerminos (VAR r1, 12: real); ]ONS
t PRj : nrnguna I G

{eOSf: 11>0 y r2>O} I:


BEGIN {nedirnosrerminos}
-.rAR
REPEAT
wri-teln('Introduzca los dos primeros trminos (>O) :,); x.
readln (r7, 12) ; d_
IJNTIL (r1 > 0) AND (r2 > a) ;
END; {PedrrOosTerminos}

jL,-__\ r Pograma prlncrpal ) PROCI


:.:!IAI
aaa-on: = MostrarMenu; {enr,
l-:-SI opcion 0F {eosr
'?' , 'p' , 'S' , 's': PedirDosTerminos (bL, b2);
'?' , 'f': writeln ('Fin de1 programa,);
:-SE VAR
'riteln ( 'Opcion no valida, ) x,
-" -- l
BEGIN
--l-:: aCl:-On 0F an(
SorucroNns 131

'P' , 'p': writeln ('El periodo es ', Periodo(bl, b2));


,5,, ,S,: BEGIN
terminos : = NumeroTerminos;
writeln ('La suma es ' ,
Suma(b1, b2, terminos) :0:3)
END; {opcion - 'S'}
tr\Tn.
DL\u t
fr,cnl
LINTIL (opcion - 'F') OR (opcion = 'f ');
-^^^t-
I e ciu]- Il
END. {Programa principal}

1.12.15 Trayectoria
Una posible solucin es:

PROGRAM Trayectoria;
{Oe.fnffvO: Conocer datos sobre la trayectoria de una pelota
Ianzada desde una posicin inicial (x0, y0) / con una
velocidad inicial V0 y con un ngulo de salida)
{Enrradas: Posicin inicial, velocidad inicial en m/seg y
ngulo en grados )
.Salidas: DisLancia recorrida, altura mxima y tiempo en eI aire)
]CNST
G= 9.8; {Aceleracin de Ia gravedad en m/s^2}
INCREMENTO = 0.5; {Intervalos de tiempo de cada medicin}

AR
xInic, ylnic, vlnic, anglnic: real;
dist, tiempo: redl;
.-x********** ApARTADO al ************i
.:CCEDURE DistanciaTiempo (x0, y0, vO, ang: real;
VAR disMax, t.Aire: real) ;
ii,E: y0>=0 La altura inicial es no negativa)
.lST: disMax= Distancia recorrida sera: x final - x inicial
tAire = tiempo en ef aire )
r-:.

t', Y , LL : ---redr;
- l

_-_-_ t_
: ---N { JJIStanclaI'Iempo.l
t''
.- q-,y
a^ * ,I
D-
/ IEU; teonverslon a radlanes-|
132 SuspRocRAMAS: PROCEDIMIENTOS Y FUNCIONES

t._
^.
REPEAT
t:=t + INCREMENTO;
y:= y0 + v0 * sin(ang) * 1-L - lal * sqr
\U (t) I z) ;
-t

*
x:= x0 + v0 cos (ang) * t;
TT\TTTT, \t - A-
4.t2.
disMax := x - xo; {oistancia mxima= xfinal-xiniciali
lAirc .= l. i: Ill
- -\J ; i lJIStancla'l-'Iempo t:o\
)
- .:lCi
.r*rx********* ApARTADO b) ************) - gri

l-=i\iCTI0N AlturaMax (y0, v0 , ang: real ) : real ; D.

PRE: y0>=0 La altura inicial es no negativa)


,?OST: AlturaMax= y mxima alcanzada) al -:

-.'AR

y, yAnr,t:real; :.--
3IGIN {alturatvtax} , t-

ang := ang * PI / 180; {Conversin a radianes}


! ._ n.

r
f
.-
'-
rr.
lvt
-:
REPEAT ...

t :=t + INCREMENTO;
-'ll
ynrru ._ )r
y := y0 + v0 * sin(ang) * t (G * sqr(t) I 2) i
UNTIL y a= yAnt;
AlturaMax = yAnt;
END; {alturalvtax}

BEGIN {Programa principal}


r/rite (' x0 (en metros) = ' ) ;
readln(xlnic);
rrite(' Y0 (en metros) = ') ;
readln(ylnic);
Tite(' V0 (en metros/segundo)
readln (vlnic) ;
-r:iie (' Angulo de lanzamiento (en grados) = ') ;
(anglnic ) ;
=eadln
l:scanciaTiempo (xlnic, ylnic, vInic, anglnic, dist, tiempo);
rriteln('Distancia mxima = ', dist:O:2, 'metros');
trriteln ('Tiempo en el aire ', tiempo:0:1,' segundos') ;
SorucroNns 133

wrrte (, La a_Ltura mxima es ,) ;


- ---i L

writ.eln (AlturaMax (yInic, vInic, anglnic) :0:2, , metros,


ro.l l .
);
!equffl - ,

END. {Prcgrama principal}

1.12.16 Funcin seno aproximada


Se muestran dos posibles soluciones al problema. En
la primera se calcula el seno,
aprovechando los trminos calculados anteriormente, lo cual reduncla
en una mejor ef,-
ciencia' En la segunda solucin, el calculo se basa en dos funciones
definidas por el
programador, el f'actorial y la potencia.

P rime ra s oluc: iri n p rop ue s ta:

PROGRAM Senol;
{onjetivo: Este programa sirve para carcurar e1 varor de sen(x)
mediante una serie con n trminosi
{Untrada: Numero de trminos y e1 valor de x en grados}
{Satiaa: El valor de sen(x) calculado por la computadora
y el valor calculado por la serie)
VAR
nt.erminos : integer;
v. ral .

FITAiCTION CalculaSeno (angulo:reI; n:integer) :ral;


{PRll: n>=0 y angulo en radianes}
I _ ^
-_
tpos'.t: CalculaSeno=angulo_angulo"3/3 t+x^5f 5f _...
]
VAR
termino, suma:rea1;
i . rrluuYUr
r. i rla^-.
/
BEGIN {Calcutaseno}
{rnicializacin de1 bucte}
termino: = angulo;
arrma. -n.
pqrLLq.
-u,

fuR r:= 0 TO n-1 DO BEGIN


SUma:= SUma r terminO;
{se calcula el siguiente trmino teniendo en crrtrnr^ d,,a.
-cada iteracin cambia de signo
-el ngu1o se multiplica por el cuadrado del ngulo
-el factorial )
termino:= -termino*sqr(anguto) I (e* (i+1) +1) * (2* ( +t) +2)) ;
-- SuspRocnAMAS: PRocEDlMlENTos Y FLTNCIoNBS

:l,l;
{rOni
la-culaSeno: =suma; BEGIN {
l-
:lI: iCalculaSenoi t InIcra

FOF
:::-l', {Programa PrinciPal }
i;:ite1n ('Introduzca el ngu1o en grados');
r dL
::adln (x) ;
i;riteln ('Introduzca el nmero de Lrminos: ') ; END; {l
::ad.ln (nterminos ) ;
'r;riteln('EI valor de seno(', X:0"2,') eS:'); FT]NCTIC

:.:=P1/180*x; { enn,
f onc.n
',;::-teln('medianLe }a computad,ora ', sin(x) :0:6) ; i ! vu r ,
.

i;riteln('mediante la serie', CalculaSeno(x,nterminos) VAR

:eadln pot:
:l,l . {Programa PrinciPa} }
i: i
BEGIN ]

,\ e gunda s oluc in P rlq ue s t a: t Inlcl


pot r

Seno2; FOR
':.l3RAM
etivo: Este programa sirve para calcular el valor de
1c..1
sen (x) I
mediante una serie con n trminos) IF
::-::ada: Numero de trminos y eI valor de x en grados) I
S,-rda: EI valor de sen(x) calculado por Ia computadora Pot<
y e1 valor calculado Por ta serie) END; {t

--.1:. :IGIN iCa.


:-:erminos: integer; f lnrcIi
ro I . SUma: =1

FOR i:,
:-]:::ION CalculaSeno (angulo: real; n: integer): real-;
l,

.:.:: n>=0 y ngu1o en radianes) tert


.-sl: CaIculaSeno=angulo-angulo"3/31+angulo^5/51- ) sumi
f\Tn . I
.: fI\!, I
:=.':.----)/ SUma: feal; la1cu1,
-: rnteger;
- I
-L ^^^.
I a-
:- - i ILdrr

f
:-]::--ON FacLorial (num: integer): real; t,^ -,
---..

----l L^l
t::: nUm>=O ) ,',1_LLer.
--^^lt
_:durrl -
' -Sl: Factorial=numl )
:.EPEAT

-ac: reaf; wri


- nr r .
Sor-ucroNrs 135

BEGIN {ractorial}
{rniciatizacin deI buc}e}
-^
rqu -_
.'
r.
!t

i := 2 T0 n DO
FOR
fac := fac * i;
Factorial : = fac;
END; {ractoria}}

FUNCTION PoLencia (base: real; exponente: integer) : real;


foor'.
irr\!. - |
I

{losr : Potencia=base^exponente}
VAR
nar . ra
!uuf l
yvL. ,
'l i raaar.
t]]uUY9!,

BEG]N {eotencia}
{rniciatizacin det bucle}
^F . f1 ,.
PUL . --

FOR i:= 1 TO abs(exponente) DO


n^r'- .-
yv" nof
y"" * vqpu
]raqo' /

IF (exponente < 0) THEN


pot := 1 / pot;
Potencia ;= pot;
END; {eotencia}

BEGIN {CaIcuIaSeno}
{rniciatizacin de1 bucle}
crrm. -.

FoR i:=0 To (n-1) DO BEGIN {n trminos )


-.- . )* L
rt Ll .
) -L t

Lermino:= Potencia(-1, j) * Potencia (x, I ) / Factorrar l' ;

suma:= suma + termino;


END; {ron}
CalculaSeno: =sutld i
END; {CalculaSeno}

-I- t- /Proorama principal)


-t _rtroduzca el ngulo en grados,
: );
_ .. :

writeln ('Introduzca el nmero d.e trminos (mayor que cero)


para calcular eI seno: ,) ;
t36 SunpnocnAMAS: PROCEDIMIENTOS Y FUNCIONBS

readln (nterminos) ;
UNTIL (nterminos > O) ;

writeln ('El valor de seno(', x:a:2,') es:') ;


v. -DT /r on*-.
!\._L l/

writeln ('medante la computadora ' , sin (x) :0:6) ;


writeln('mediante Ia serie ' , CaIculaSeno (x, nterminos) :0:6) ;
readln
END. {Programa principal )

4.12.17 Suma de nmeros primos


La estrategia para resolver este problema consiste en empezar con los dos nmeros pri-
mos ms pequeos, a=2y b = 2, e ir comprobando si su suma dael nmero introducido.
Si su suma es menor, se cambia b al siguiente nmero primo (en este caso al 3). As su-
cesivamente hasta que su suma es igual al nmero o hasta que su suma supera el nmero.
En este ltimo caso, se vuelve a iniciar el calculo con los nuevos a y b, que se igualan
al sigLriente nmero primo despus del ltimo valor de a (en la primera iteracin a y b
pasan a valer 3). As sucesivamente, hasta que se encuentran los dos nmeros primos o
hasta que Ia suma supera a1 nmero dado.

PROGRAM NumerosPrimos ;

{Programa que dado un nmero n mayor que dos, encuentra, si


existen dos nmeros primos que sumados dan ni
{nmrnaoa: Un nmero entero mayor que 2}
TSALIDA: Por pancalla si existen, Ios dos nmeros primosi
I ^__ ___ _

VAR
num,priml, prim2: integer;
encontrados: boolean;

PROCEDURE EncontrarDosPrimos (n' integer; VAR p1, p2: integer;


VAR enc: boolean) ;
, Onr. --lt t
lr-l
!t/z
\
I

:-:-: -r- extsten pL,p2


l
---l ,! - -
nUmerOS primos y p1+p2=N enc es TRUE

=-- E- udbu ContfafiO


^.^ ^l
enC ac trnT.QE'l

:-1.:l-CN SigPrimo (numero:integer) :integer;


^l
- -._. -luLLLU!v/v J

?lSl: SigPrimo devuelve eI siguiente nmero primo despus


; - -,,-^-^ \
Sor-ucroNns 13

VAR
a, b : int.eger;

FU-NCTION EsPrimo (num: integer) :boolean;


{PREI: num>0i
-. i {eoSf: EsPrimo TRUE si num es un nmero primo
FALSE en caso contrario)
VAR
i : integer;
BEGIN {eslrimo}
l^

I{HILE ( (num MOD i) <> 0) D0

: Jmeros Pri- i : =i+1;


-:rtroducido' esprimo: = ( i=num)
., -1 l. As su- END; {esPrimo}
:- e1 nmero.
se igualan BEGIN {sigPrimo}
-:
-:*cin a Y b a:=numero + 1;
-:,r: pimos o WHILE NOT EsPrimo (a) D0
: . _:1,]

SigPrimo: =a;
END; {siglrimo}

:IGIN {EncontrarDosPrimos}
{pr y p2 son e1 primer nmero primo excluyendo e} 1}
nl .-
.- ).
't
^a ,_ a.
zt
P' '-
WHILE ( (p1 + p2) < n) D0 BEGIN
{Se aeia p1 fijo y se cambia p2 hasta que p1+p2>=n}
WHILE ((pl + p2) < n) Do
p2 := SigPrimo(p2) ;
- -: -- | {Una vez terminado el bucle, p1+p2>=n}
{Si pf+pZ>n entonces cambia p1 at siguiente nmero primo,
., -^,al-'a ,- a empezar 1nlc1ando p2 aI nuevo valor de p1)

IF ((p1 + p2) > n) THEN BEGIN


pl : = SigPrimo (p1) ;
P2 := P1;
END; {ir}
END; {warlui
enc: = p1+p2=n;
: ' .^:5
:i,); {EncontrarDosPrimos}
138 SuspnocnAMAs: PRocEDIMIENToS Y FUNctoNES

BEGIN {Programa PrinciPa}i


*t':'lT'^t'
wrlteln /''oribe
['trsur- un entero positivo mayor que dos:
read.In (num)
LINTIL (num > 2);
EncontrarDosPrimos (num, Priml prim2,
enconLrados) ;
'
IF encontrados THEN BEGIN
write ('Los nmeros Primos cuya suma es ', num);

writeln(, son: ,, primi, ' Y ', Prim2);


END
ELSE
writeln('No existen dos primos cuya suma es '

readln;
END. {Programa PrinciPalJ

4.12.18 Pi
Una posible solucin es:

PROGRAM CalculaPi;
{Programa que calcula
e} nmero Pl mediante dos series)
mayor que 0 que indica eI nmero de
{uNrnnoa, Un nmero entero
trminos de las series)
-^--:lc>
de }as ser ^^1
{salrna, Por pantalla }os resultados
J

VAR
nTerminos: integer;

{*** g6n la serie Primera ***}


FUNCTION PiSere1 (n: integer): real;
^l
iPRE: n>=u1
de los n primeros trminos de
{eoSr: PiSeriel devuel-ve Ia suma
la serie : tf2*sqrL(24+2412^2+2413^2+24 +^z+''')\
rIND

S'*:.a: feal;
l--ar.
--- -'Ye' /

--:r-'- :- qcriel ]
:-*.::=3;
:-: -:= 1 TO n DO
s*:a := suma + (1/i)*(1/i); que para
.:::: ,1/i)*(1/i) en vez de 1/sqr(i) es debido a 33!24'
- -v.Ft=s de i (i>181) por ejemplo sqr(182) --
SorucronBs 139

se sal_e de1 rango de representacin de los nmeros enteros


y e1 programa da resultados ,extraos, )
suma:= 7/Z * sqrt (24*suma) ;
PiSeriel : =suma.
END; {riserieri
{*** ge la serie segunda ***}
FUNCTION PiSerie2 (num:integer) : real;
{eRn: num>=o}
{nosr: Piserie2=2* (2lL\* (213)* (413)* (415\*... con num trminos)
VAR
i i nl-aa-.
raruuYU! /

numera, den, prod: real;


BEGIN { riseriez }
Prod: =2 ;
FORi:=1 to num DO BEGIN
numera :=((i-1) nfV 2 + L) * 2;
den :=2* (i DIV 2) + 1;
prod := prod * (numera/den);
END; ironi
PiSerie2; =prod;
f-r^l
-1r\u; \pr l

:EGIN {Programa principal}


REPEAT
writeln (,Escribe el nmero de trminos ( > O): ,);
readln (nTerminos)
tllvTIL (nTerminos > 0);
vriteln(,El nmero pI es ,, pI:0:g);
writeln('Con la primera serie es ,, piSeriel (nTerminos) :0:8);
writ.eln('Con la segunda serie es,, piSerie2(nTerminos)
readln
lND. {Programa principal}

1.12.19 Capica
Una posible solucin es:

?ROGRAM Capicua;
.Cbjetivo:
Programa que calcula si un nmero es capica)
ENTRADA: Un nmero entero)
,.SALIDA: Por pantalla si es capica o no)
SuspnocnAMAS: PROCEDIMIENTOS Y FUNCIONES

VAR
num: integer;

FIINCTION EsCapicua (n: integer): boolean;


Jpu. -\I
tP051': Lseaprcua es TRUE
I _ ^ ^-
si n es un palndromo
FALSE en caso contrario)
VAR
suma, : integer;
BEGIN {uscapicua}
'ir ..-- rl.,c /n
qlr\rr/, \

suma:= i MOD 10;


WHILE i>10 DO BEGIN
i:= i Drv 1o;
Suma:= Suma*l0 + i MOD 10;
END;
EsCapicua := (suma = abs (n) ) ;

END; {usCapicua}

BEGIN {Programa Principal}


writeln ('Escribe un nmero entero y dir si es capica: ');
readln (num);
write ('EI nrnero ', , num ) ;
IF NOT EsCapicua (num) THEN
write (' no ' ) ;
writelnl' es capica' ) ;
readln
t- l
ENIJ. t Programa prrnclpa-L i

4.12.20 Rotar
Una posible solucin es:

PROGRAM RoTAr;
{oUjetivo: Programa que pide 3 nmeros enteros y los devuelve
rotados a 1a izquierda)
{ml'rraoa: 3 nmeros enteros}
{sa-lrna, Por pantalla los nmeros rotados}

VAR
tl, 12, 13 : inLeger;
Sor-ucrors t41

PROCEDURE Rotarlzda (VAR a, b, c:integer);


{PRE: a=A, b=B, c=Ci
{lOSr: a=B, b=C, c=A}
VAR
temp : integer;
BEGIN {rotarizda}
lcmn .- :.
""...r.V1
a := bi
h .= .
v .-
. - i-amn
LU'LLP

END; {rotarizda}

BEGIN {Programa Principal}


writeln ('Escribe los tres nmeros: ,
) ;
readln (11, T2, 13);
Rotarlzda (rL,12,13) ;
writeln ('Los nmeros rotados a zquierda son: ,);
writeln (11:3, 12:3, 13:3);
readln
LNIJ. tPrograma prlnclpal ,|
Captulo 5

lntroduccin a la Recursin en
PASCAL

Una definicin se puede hacer de forma directa o de forma recursiva. En la forma


Jirecta, se describe explcitamente lo que se est defrniendo. Por ejemplo, la deflnicin
lirecta del factorial de un nmero / es:
nt-n+ (n- 1)*...*2*1.
En la fbrma recursiva, en la definicin se hace referencia a lo que se est definiendo.
I a defrnicin recursiva del ejemplo anterior es:

ttl
. ( l. sir:0

-
t rx(n-l)l' si rr >0
donde se observa que en la definicin de n/ aparece (n-l)l La representacin del
:lculo de 4! en forma directa sera 4! : 4 * 3 * 2 * | : 24. y en fbrma recursiva:

_l-*?t _aA
2 t-l*r l -a
)l-r*1 I -)
1r=1*01 =1
0l=1

5.1 Subprograma recursiYo


:s un subprograma que contiene una o ms llamadas a s mismo. bien directamente o
rien a travs de otro subprograma.

5.2 Recrrsim em PAC"&,

Su sintaxis es la habitual de ias llamadas a sutrprogramas. No hace i'aita ninguna amplia-


-rn del lenguaje (excepto para Ia recursin mutua, vase e1 apartado 5.12). En cuanto a

t43
t44 INTRoDUCCIN A LA RECURSIN EN PASCAL

la semntica es la que se deduce del mecanismo habitual de llamada a un subprograma,


El cdigo de una funcin piua calcular el factorial de un nmero podra ser el siguiente:

FUNCTION Fact(n: integer): real;


r---- nl
tHre: -1l >= uJ
{Post: Fact. = nl}
BEGIN
IFN=OTHEN
Fact := 1
ELSE
Fact:=n*Fact(n-1)
END; {ract}

Para entender mejor la recursividad en la tabla 5.1 se ilustra la ejecucin del clcuit'
del factorial de 4.
En esa tabla se puede observar que:

1. Cada llamada recursiva genera una nueva copia en memoria de sus datos, como se
puede ver en las dos ltimas columnas de la tabla.

2. Durante la ejecucin de Fact (i) estn tambin activos, en espera de la reanuda-


cin de su ejecucin, Fact (i+1) ... Fact (n)
3. Una vez finalizado Fact (i), su copia desaparece de la memoria y devuelve e .

control de la ejecucin a Fact (i+1)

De la primera observacin, se puede inferir que si el nmero de llamadas al subpro-


grama es muy grande se podra desbordar el tamao de la memoria. Este es un problem.
que se presenta en los subprogramas recursivos, que no tiene su equivalente iterativo
Esto supone que haya que prestar especial atencin aI uso de la recursividad.

5.3 Proceso de la llamada al subprograma recursivo


Los pasos que suceden internamente cuando se realiza una llamada a un subprogram;
recursivo se pueden resumir en los siguientes:

o Se reserva espacio de memoria para almacenar los parmetros y dems objeto.


locales del subprograma llamado.
o ste reciben los parmetros, toma eI control de ejecucin y comienza a ejecutarse
Curndo un subprograma termina la ejecucin:

- se libera el espacio reservado y los identificadores locales dejan de tene:


r-i_uencia,
Pnocnso DE LA LLAMADA AL suBpRocRAMA RECURSTvo t45

Llamada Sentencia ejecutada Subprogramas Estado


(Situacin de la evaluacin) activos n I Fact
Fact(4) ,)
Fact:= nxFact(n-1) Fact(4) 4
(Fact:= .1*Fact(3))
Fact(3) Fact:= n*Fact(n-1) Fact(3) -) ?
(Fact:= 3*Fact(2)) Fact(4) 4 ?
Fact(2) Fact:= num*Fact(n-1) Fact(2) 2 ?
(Fact:= 2*Fact(1)) Fact(3) -l l
Fact(4) 4 ?
Fact( 1) Fact:= n*Fact(n-1) Fact(1) 1 ?
(Fact:= 1*Fact(O)) ,!
Fact(2) 2
Fact(3) -) ?
Fact(4) 4 ?
Fact(0) Fact:= 1 Fact(0) 1 I
(FacL:= 1) Fact(1) 1
,]

Fact(2) 2 ?
Fact(3) -l ?
Fact(4) 4 1
Fact:= n*Fact(n-1) Fact(1) 1 I
(Fact:= 1* 1) Fact(Z) 2 ?
Fact(3) J ?
,l
Fact(4) 4
Fact:= n*Fact(n-1) Fact(2) 2 2
(Fact:= 2xl) Fact(3) -') ?
Fact(4) 4 ?
Fact:= n*Fact(n-1) Fact(3) -1 6
(Fact:= 3*2) Fact(4) 4 'l
Fact:= n*Fact(n-1) Fact(4) 4 24
(Fact:= 4"6)

Tabla 5.1: Ilustracin del clculo del factorial de 4


EN PASCAL
t46 INTRODUCCIN A LA RECURSIN

que provoc su llamada' ste termina


- se devuelve el control al subprograma
q'" la llamada y pasa a ejecutar su siguiente
de ejecutar la instruccin "a's
instruccin.

oEsteprocesoserepite,hastaquesellegueauncasotrivial(cuandoelsubprograma
sin haber hecho una llamada al
propio subprograma)'
termina

5.4 Estructura de un subprograma recursivo


Unsubprogramarecursivoesunconjuntodecasos,entendiendoporCaSoaunacondi-
cinqueloidentificayunasolucin.Dependiendodeltipodelasolucin.loscasosstli
de uno de los dos tiPos siguientes:

l.Casotrivial(base)'Esuncasodonde'enlaexpresindelasolucinnoapafecei
a] suUnro8llTi,t^-l-
Es decir' no se genera una llamda
nombre del subprograma'
devuelveelcontrolalsubprogramaquecauslallamada.LossiguientesSofleJeni-
plos de soluciones triviales: Factorial
:= 1' Encontrado := cierto' Su:'
:= s,Prodesc := a[1]*b[11,F := Factorial(n)l
2.Castnotrivial(recurrente).Eselquenotienelascaractersticasanteriores.E.
ttrbli:q:T:"'..,:-
el nombre
decir, en la expresin de la solucin aparece 9"l
solucing"n",u.,nuomsllamadasrecursivas.Lallamada(ollamadaSfeCUfSl\':
sedebehacerconunosparmetros,pcLrrnefrossucesors,mScefcanosalc..
valores que identilican un caso trivial'
no triviales:
Los siguientes son ejemplos de soluciones
Factorial := n* Factorial(n - 1),Potencia(a, n - 1'
a*s)'

Suma := Suma(v, a, m) + Suma(v, m +


1, b)2

5.5 Recursin infinita


cuando se entra en una sucesin infinita c'
Se clice que se produce recursin infrnita
llarnacias. es decir nunca se llega a un caso
trivial' Por tanto, sta es una caracterstic-
[-Jn ejemplo de recursividad inf,nita I
que no puede tenerun ,rbproirama recursivo.
( - 1) en el ejemplo de 5 '2'
iroducira la llamada ract
sedefinenSonFaCtoIia1'EnContrado.Suma'ProdeSC\.
la seccin de recursit'iti"
r qr,ie ..:::::ia1 no hace una li"rruda iirecta o indirecta a F(ver ms adelante
//i.,1/r,, ', i',1[rc, t,t). y respectlvament'
lsr.rponientlo que los subprogramas clue se clef,nen son FacLorial, Potencia Suma
RBcunsrvrDAD LTNEAL t47

5.6 Recursividadlineal
Un subprograma es recursivo lineal cuando cada llamada recursiva genera como mximo
'tra llamada recursiva.
Las funciones Fact, de 5.2, y sumalenta, cuyo cdigo se presenta a continuacin,
.on recursivas lineales.

(a, b: integer) : integer;


:--NCTI0N Sumalent.a
=re:a=Ayb=ByAr0)
lost: Sumalenta = A+B)
::GIN
rF a = {caso trivial}
O THEN
Sumalenta : = b
ELSE iCaso no triviat)
Sumalenta := Sumalenta(a - 1, b + 1)
:..- t_
iSumalenta |

5.7 Recursividad final


.,nrbin conocida como Recr.rividad por la cola. Es un caso especial de la recursivi-
,,,d lineal. donde no se realizan operaciones con el resultado que devuelve una llamada
-:ursiva, es decir, en cada solucin de los casos no triviales solo aparece la llamada
--.-ursiva. El resultado es el que devuelve la ltima llamada y es el mismo para
todas
-,. llamadas. Fact no es recursivo final, porque el resultado de la llamada recursiva se
.ultiplica por num. Sin embargo Sumalenta si 1o es.

5.8 Recursin mltiple (o no lineal)


-: recursividad mltiple se produce cuando alguna llamada genera dos o ms llamadas
-:Jursivas. La funcin del siguiente ejemplo presenta recursividad mltiple.

j,]::TION Fib(num: int.eger) : integer; {pre: num ,= 0


}
:rst: en Fib quedar eI n-simo nmero de la serie de Fibonaaci.|
: I ^ a\T
_ _-_L\

IF (num 0) OR (num = 1) THEN


Fib 1
ELSE
Fib := Fib(num - 1) + Fib(num - 2)
:r,:; {Fib}
IutnouccrN . r,l RrcunsrN nN PASCAL

5.9 Transformacin de recursin a iteracin


versin iterativa' Un algoritmo
Cualquier algoritmo recursivo tiene su correspondiente
recursivo {rnal da lugar a un algoritmo iterativo de
un solo bucle' Un algoritmo recur-
dos bucles, aunque hay veces que a1
sivo no flnal da lugar a un algoiitmo iterativo con
simplificarlo se puede dejar un solo bucle'
algoritmos recurslvos
En esta seccin. ,. p,","nton los algoritmos para transformar
lineales
3. Los algoritmos para transfbrmar algoritmos recursivos no lineales necesitan
alcance de este libro'
estructuras de datos de tipo pila y quedan fuera del
final a uno iterativo es el si-
Ei algoritmo para trnsformar un algoritmo recursivo
guiente:

la del algoritmo.recursivo renom-


1. Escribir la misma cabecera del subprograma que
entrada (se aconseja que el nuevo nombre sea el
original
brando los parmetros de
del subprograta, se puede
seguido de un sufijo , p.e. Ini). En cuanto al nombre
ejar ef original, o darie otro nombre si se quiere
conservaf el algoritmo recursivo'

2. escribir declaraciones de tantas variables locales


como parmetros de entrada, dn-
doles el nombre original y el tipo de dichos parmetros'
parme-
3. escribir asignaciones a las variables declaradas de sus correspondientes
tros de entrada,
4.escribirunainstruccinWHILEdelaformasiguiente:

o la condicin trivial (tngase en cuenta que esta condicin


es la del caso no
puedequenoestescritaexplcitamentesisehautilizadounainstruccin
IF),
o las instrucciones del cuerpo del bucle son las asignaciones a las variables
localesdelasexpresionesquetenganlossucesoresdesuscorrespondiente.
Parmetros,

si el subprograma es una funcin, escribir una


instruccin de asignacin al nombr-
5.
de la funcin de la expresin que tenga el caso
trivial'

tomando como ejemplo el al-si


se va a ilustrar la aplicacin del algoritmo anterior,
de un nmero n si la llamada -
ritmo de la funcin ractr-nal-, que calcula el factorial
la funcin es FactFinal (n,1) '

FIINCTICN FacFinal(n: integer, f: real): reI;


,
irla:
.\
a >= ui
'' :-o=-' :acFrnal = f
* nli
-
parmetros sucesofes tenga funci
-'So\i los recursivos no frnales en que la funcin para calcular ios
d" duto. de tipo pila y quedan fuera del alcance de e..
opuesta. Los que no Ia tengan necesitan esffuctulas
1ibro.
TRANSFORMACIN DE RECURSIN A ITERACIN 149

3EGIN
IFN=OTHEN
FacFinal : = f
ELSE
FacFinal := FacFinaI(n - 1, f * n)
END; {racrinal}
El siguiente cdigo es el resultado de aplicar el algoritmo de transformacin.

:LINCTION FacFinalIter (nIni : inLeger, flni: real) r real;


'I Pre: nln} >= U^) J

Post : t,'aCf InaI lter = I -Lrl1 x nlni I )


)o*
'irlruuYU!,
ntsaaar.

f . vae l

3EGIN
n : = nlni;
f c-:
I := LII.I-L;
WHILEn>0D0
BEGIN
f := f * n;
n:= fi - 1

END;
FacFinalltr := f
:ND; {FacFinaIfter}

Teniendo en cuenta que, para que ese algoritmo calcule el factorial, el parmetro
iormal nlni debe recibir la constante 1, se ve que dicho parmetro no es necesario si
:e hace que la asignacin inicial sea el valor de esa constante. Tambin se observa
que el primer parmetro, una vez hecha la asignacin inicial no vuelve a aparecer en
ei algoritmo, es decir, que si se renombra dicho parmetro con su nombre original y se
quita la sentencia de asignacin el resultado de1 clculo ser el mismo.
El siguiente cdigo es el resultante de estas simplificaciones

:UNCTION FacFinalIter(n:integer) : real;


^l
lrA. n \- lll

Post:FacFinalIter = nl )
-:l D

F-
!: -^-1.
IEAI,

3EGIN
c1

WHILEn>ODO
BEG]N
150 INrnoruccrN . r-. RncunsrN nN PASCAL

F.-
I.- fI * n.

n:= n - 1

END;
F'aCf ]-nallter := I
END; {FacFinaIIcer}

Si se prefiriese realizar el bucle con una instruccin FOR, el algoritmo equivalente


sera el siguiente

FUNCTION FacFinallter(n:integer) : real;


fp.o. n -= ol
{Post: FacFinatlter = nl }
VAR
'I .i raar.
!. rlruuYUr,
I: ICdI;
BEGIN
! .- r,

FOR i := n DOitlNTO 1 D0
f!.- ._
!
* lti
END;
FacFinallter : = f
END; {FacFinaIIcer}

Teniendo en cuenta la conmutatividad de la multiplicacin, se podra realizar el buc-:


incrementando la variable de control en lugar de decrementarla. El algoritmo resultan :
sera el siguiente:

FUNCTION FacFinallter(n: integer) : real;


{Pre: n >= o}
{Post, FacFinaIIter = n: }
VAR
.l i rraaar.
I. JllUUYu!,
r: reda,'
BEGIN

!
.-
.-
1.
J,

FORi:=1TOnD0
f := f * i;
END;
h'act"]-nal1ter : = I
END; {FacFinalIter}

El algoritmo para transfornar un algoritmo recursivo no f,nal a iterativo es el +


guiente:
TuNsronu,rcrN DE RECURSTq n rrpnncrN 151

1. Igual que el paso 1 de la transfbrmacin de recursivo final a iterativo.


2. igual que el paso 2
3. escribir Ia declaracin de una variable auxiliar, llmese acumuladora, del mismo
tipo que la funcin,
,1. igual que el paso 3,

5. igual que el paso 4,


6. escribir una instruccin de asignacin a la variable acumuladora de la expresin
del caso trivial.
7. escribir una instruccin WHILE de la forma siguiente:

o la condicin es la comparacin por no iguctl de la variable (o variables) que


aparece en la condicin del caso trivial con su correspondiente parmetro de
entrada,
o las instrucciones del cuerpo del bucle son, por este orden:

- la asignacin a cada variable local de las expresin opuesta a la funcin


sucesor de su correspondiente parmetro de entrada,
- la asignacin a la variable acumuladora de la expresin resultante de
sustituir. en la expresin de la asignacin en el caso no trivial, cle la
llamada a la funcin por el nombre de la propia variable acumuladora.

8. escribir una instruccin de asignacin al nombre de la funcin de la variable acu-


muladora.

E,l resultado de aplicar este algoritmo al cle la funcin Fact. cle 5.2, es el siguiente
- ,digo:

j -lrCTI0N Fact.Iter (nIni: ent.ero) : real;


:Ii: I]ltll >= 0]
l:st : Fact= ,.f r-ri i 1

. -i rl-ao- "

resultado: real,;
:: IIN
n : = nlni;
I{HILEn>0DO
n := n-l;
r:esultado : = 1;
hjHILE n <> nini D0
BEGII]
n ;- n + i;
tT

152 INTRODUCCIN A LA RECURSIN EN PASCAL

resultado := resultado * n
END;
Factlter : = resultado
END; {FactIter}

Analizando el primer bucle se ve que no es necesario, si en su lugar se hace 1'


asignacin del valor que ocasiona la terminacin del bucle, que es 0. Tambin se puede
cambiar la operacin de comparacin del bucle, ya que no se puede dar que n > nln-
El resultaclo de esta simpliflcacin es el siguiente:

FIIN-CTION Factlter (nlni: entero) : real;


I Ura. -
Lnt \- ^l
{l)

{ Pcsr
' FacL = nlni I}
VAR
If , f'iraaar.
rlusYU! ,

::esultado: re a1 ;

BEG:N
--1 ._
. - n.
u r

::sultado := 1;
,1iHI-En<nIni D0
BEGIN
n := n+1;
resulcado := resultado * n
END;
Factlter := resultado
END; {FactIter}

Utilizando un bucle FOR en lugar de un WHILE el algoritmo equivalente sera:

FLI\TCTION Factlter (nlni : entero) : real;


{Pre: nlni >= 0}
{lost: FacL = nlnil}
VAR
1I . 'i -ranar.
rlruuYUr /

resultado: reaf;
BEG]N
resultado : = 1;
FOR N : = ]- TO NlNi DO
resultado := resultado * n;
Factlter : = resultado
END; ifactfter)
Se podra, incluso,
Cr,lnrolo vERSUS EFTcTENCTA 153

o renombrar la variable n por la variable i para la realizacin del bucle,


. como consecuencia de lo anterior, volver a renombrar el parmetro de entrada con
su nombre original.

EI cdigo resultante sera:


:la
ede FITTJCTION Factlter (n: entero) : real;
(r^PrP. n \= ^l
ll)
ni.
{Post: 'act = nl}
VAR
j .i
-r ^-^-
trrLUYLr, .

resultado: real;
BEGIN
resultado : = 1;
FOR i := 1 T0 n DO
resultado := result.ado * i;
Factlter : = result.ado
END; {Factfter}

Ntese que el resultado final es el mismo en ambos casos y que es el que nor-
malmente se encuentra en la literatura como ejemplo de algoritmo iterativo para calcular
el factorial de un nmero.

5.10 Claridad versus eficiencia


El diseo y anlisis recursivo de algoritmos es una tcnica muy potente una vez do-
minada. Muchos algoritmos tienen una solucin recursiva natural. En muchos casos
1a programacin recursiva permite resolver problemas de forma elegante, con menos
cdigo y ms fcil de entender que su correspondiente solucin iterativa. Un ejemplo
paradigmtico es eI problema de las Torres de Hanoi (ver el problema 5.14.2).
En cuanto a la eficiencia, hay que tener en cuenta la complejidad aadida por la
recursin debida al nmero de llamadas al subprograma, a la gestin de la estructura
de datos para mantener el contexto de cada cada llamada y, tambin, en algunos casos,
del hecho de llamadas repetidas. Por ejemplo, la llamada Fib(5) de1 e.lemplo en 5.8
desencadenara las llamadas que se ilustran a continuacin:

Fib(5)
Fib(4) + Fib(3)
Fib(3) + Fib(2) Fib(2) + Fib(1)
Fib(2) + Fib(1) Fib(1) + Fib(0) Fib(1) + Fib(0) 1
lib(1)+Fib(0) 1 1 1 1 1
11
154 INrnoouccrN , r-n RncunsrN pN PASCAL

donde se ve que se hacen 2llamadas a Fib(3),3 a Fib(2), 5 a Fib(1) y 3 a


Fib (0 ) . sto hace que se repita su clculo 2,3, 5 y 3 veces respectivamente. Se puede
uno imaginar la cantidad de veces que se repetira el clculo de Fib (10) para calcula,
p.e., Fib (3 7 ) .

5.11 Recomendaciones generales

U ttliza recursividad cuando :

Clarifique el algoritmo y el programa que soluciona un problema.


No haya fuertes restricciones de memoria o tiempo de ejecucin.

Como consecuencia de estos dos puntos, y dado que la transformacin de un algc-


ritmo recursivo a su versin iterativa es un proceso totalmente mecnico, es una buen-
estrategia derivar el algoritmo recursivo y, luego, transtbrmarlo a su versin iteratir *
que siempre ser ms eficiente. Es ms, hay buenos compiladores que generan. de form-
transparente para el programador, cdigo objeto iterativo dado un fuente en recursivo.

5.12 Recursin mutua (indirecta)


Hasta ahora se han mostrado ejemplos de recursividad simple (directa). En la recursi:
simple un subprograma se llama a s mismo. La recursin mutua (indirecta) se produ.,
cuando dos subprogramas se llaman mutuamente. La recursividad en cada subprograr--
se produce indirectamente.

Un subprograma A llama (directa o indirectamente) a otro B.


B llama (directamente o indirectamente) a A.

Recursin mutua en Pascal

En Pascal el proceso de compilacin exige que para poder utilizar un identificador ,',
va est declarado. Esto representa un problema para implementar la recursin mutua. -
que si dos subprogramas se tienen que llamar mutuamente, uno de ellos tendr QUe ::
llamado antes de su declaracin. Para solucionar este problema hay que predeclarar ,
egLrndo subprograma con la palabra reservada FORWARD. La sintaxis es:

:.:-:: =---oorograma(parmetros) ; FORWARO {nredec}aracin de e}


E1 ejemplo siguiente muestra la estructura para poder llamar al procedimiento :
desde el .\. antes de su declaracin.
CupsrroNns DE TEST 155

-la PROCEDURE B(parmetros); FORWARD {Predec}aracin de S}


ede ?ROCEDURE A(parmetros); {oeclaracin de A}
1ar, qncrtrr f I
t.,l
e0;
.*0, lol
?ROCEDURE B (parmetros) ; {Declaracin de B}
3EG]N {B}
A0;
rrTn.
)LrDt Jt
i!j

go-
ena
5.13 Cuestiones de test
iva,
ma
5.13.1 Enunciados
). l. La recursividad por la cola se produce cuando:

(a) La llamada recursiva va al final del subprograma.


. (b) El resultado de la ltima llamada recursiva produce el resultado final.
(c) Se realiza una recursividad infinita.
10n
(d) Se tiene a Ia vez recursividad lineal y recursividad mltiple.
.ma 2. Se tiene la siguiente funcin:

FUNCTION ejemplo (x: integer) : integer;


BEGIN
IFx<>0THEN
ejemplo := ejemplo(x-1)
ELSE
xi= 2;
END;
!ste
.ya
sef Si se hace:

rel
resultado:= ejemplo (a) ;
(resultado) ;
l:]."r"
B,
En pantalla aparecer:
I
r56 Ixrnoouccru a u Rncunsrn nN PASCAL

(a') 4.
(b) 2
(c) No aparece nada porque da lugar a infinitas llamadas recursivas.
(d) Un valor sin sentido, porque en el caso base no hay asignacin al nombre de
1a funcin.
a
Qu es la recursividad por la cola?

(a) Comenzar las llamadas recursivas desde el caso base.


(b) Que un subprograma llame a otro que a su vez llama al primero.
(c) Cuando al llegar al caso base se ha alcanzado el resultado deseado.
(d) Cuando en un subprograma recursivo la llamada recursiva est despus dr
caso base.

4. Seala la(s) respuesta(s) correcta(s):

FLll\CTI0N F (a:integer) :integer;


BEG]N
CASE a 0F
n. G.= T.
1.
t. ._
g.- a-
zt
ELSE G;= 2*F (a-1) ;
END;
END;
1

(a) Es una funcin recursiva con dos casos base. E1


(b) Es una funcin recursiva incorecta porque no contiene una instruccin ..
Ca
lectiva IF'-ELSE.
(c) Es una funcin con recursividad por la cola.
(d) Es una funcin recursiva con effores sintcticos.
s.14

5.13.2 Soluciones -; t3.


-. dil
1. La respuesta correcta es la (b). La (a) es incorecta ya que el ser recursiva i .
: .lSti
no depende de donde est la llamada sino de que su resultado no se combine :
a:Ina
nada para producir el resultado final. La (c) es una caracterstica a evitar. La
Es
es incorrecta porque una recursiva mltiple nunca puede ser recursiva f,nal va - -
el resultado de cada una de las llamadas se combina con los de las del resto.
:"1{.3
i. La respuesta correcta es la (d) ya que el caso base no hace una asignacin c1. -

r alor a la luncin por 1o que el resultado de la ltima llamada y de las anteri, -, :.-'ribi
ser un resultado "basura".
-_:do r

L
Pnonr,nnrls 151

-). La respuesta correcta es la (c). La (a) es incorrecta porque un caso base es que no
tiene una llamada recursiva. La (b) es la def,nicin de recursividad mutua. La (d)
porque el ser recursiva por la cola no depende de donde est la llamada sino
de
que su resultado no se combine con nada producir el resultado
final.
4. La respuesta correcta es la (a). La (b) es incorrecta porque la instruccin GASE
tambin es una instruccin selectiva. La (d) porque el resultado de la llamada se
multiplica por 2. La (d) porque no tiene errores sintcticos.

5.14 Problemas
5.14.1 Camino entre dos puntos
Dadas dos funciones m (x) :2x y r(r) : x I (que no deben ser implementadas).
- Di_
sear un subprograma recursivo que dados dos nmeroS, o ) o y b > 0, encuentre
una
fbrma de llegar desde a hasta b mediante aplicaciones sucesivas de m(x) y r(r). El sub-
programa mostrar por pantalla la secuencia que se produce al pasar desde
a hasta .
Adems, se quiere que:

o se imprima el camino de funciones aplicadas desde el destino al origen,


o se imprima el nmero de veces que se ha aplicado cada tipo de funcin.

Ejemplo para pasar de 2 a 7: En la pantalla deber aparecer:

2 --. 4 ---+ 8 ---+ 7

El no de veces aplicado mha sido: 2 y el no de veces aplicado r ha sido: 1.


camino de funciones aplicadas desde el destino al origen: Aplicado r --+ aplicad o m -)
aplicado nt

5.14.2 Las torres de Hanoi


Latatea planteada a los monjes del templo de Bramah es moverz discos concntricos
de distinto dimetro desde una aguja 1 a otra aguja 3 usando como almacn temporal
la aguja 2 si es necesario. No se puede mover ms de un disco a la vez y nunca ha de
perrnanecer un disco de mayor dimetro sobre otro de dimetro inferior.
Escribir un algoritmo que d la secuencia de movimientos que se deben realizar.

5.14.3 Paridad de un nmero


Escnbir 1as f-unciones necesarias para determinar la paridad de un nmero positivo
utili-
zando recursin mutua.
158 INr:noouccrN . r-l RrcunsrN nN PASCAL

5.14,4 Funciones recursivas


funcioues recursivas' Para los apartad':'
Determine qu se calcula con las siguientes
(1)-(4), suponga Que n >= 0
1. FL\TCTION FaRec(n: integer): integer;
BEGIN
IF (N = O) THEN
Farec : = 3

ELSE
Farec:=n*Farec(n-1)
END;

2. FUNCTTON FbRec(x: reaf; n: integer): reI;


BEGIN
IF 1n = 0) THEN
FbRec : = 0
ELSE
FbRec := x + FbRec(x' n-1)
END;

3. FI,NCTTON FcRec (n: integer) : integer;


BEGIN
IF (N < 2) THEN
FcRec : = 0
ELSE
FcRec := 1 + FcRec(n DIV 2)
END;

4. FIr\TCTTON FdRec(n: integer) : integer;


BEGIN
IF (N = O) THEN
FdRec : = 0
ELSE
Fd,Rec := FdRec(n DIV 10) + n MOD 10;

END;

5. FL'NCTroN FeRec(n: integer): integer;


BEGIN
IF (N < O) THEN
FeRec := FeRec(-n)
ELSE IF (n < 10) THEN
FPa. .
= n
ELSE
FeRec := FeRec(n DIV 10)
Pnosr,nNrls 159

5.14.5 Funcionesiterativas
Escriba versiones no recursivas de las funciones del ejercicio anterior.

5.14.6 Calculo recursivo de los polinomios de Hermite


Escriba un subprograma recursivo para calcular valores de los polinomios de Hermite,
H"(*), dado que:

o Hs(x) : I
o H1(x) :2v
o H"(x) : 2x * Hn r (r) - 2(n - l) * Hn-2(x) para n >l
Se supone que en el programa principal se piden los valores de n (entero no negativo) y
x (real).

5.14.7 Calculo recursivo de los yalores de la funcin de Ackerman

Escriba un programa que incluya un subprograma recursivo que calcule valores de la


funcin de Ackerman dado que:

o Ack(O,n) : nll
o Ack(m,O): Ack(m- 1,1) si m > 0
o Ack(m,n) : Ack(m - I,Ack(m,n- 1)) si m,n ) 0

5.L4.8 Clculo recrsivo de Ia potencia de un nmero

Construya un subprograma recursivo que calcule la potencia de un nmero entero posi-


tivo.

5.14.9 Invertir un nmero entero


Escriba un programa que incluya un subprograma recursivo que escriba los dgitos de
un nmero entero en orden inverso.

5.14.10 Nmero de dgitos de un entero


Escriba una funcin recursiva que devuelva el nmero de dgitos de un entero no nega-
tivo. Escriba un programa que compruebe la funcin del apartado anterior.

5.14.11 La necesidad de un caso base bien definido

Dada la frmula recursiva F(N) : -f (N-2) con el caso base F(0) : 1, cules son
Ios valores de f (a) y r' (6)? Cul es el valor de f (5)?

J
INTRODUCCIN A LA RECURSIN
EN PASCAL
160

5.14.12 El algoritmo de Euclides recursivo


recursivo que implemente el algo-
Escriba un programa que incluya un subprograma El
.Jmn divisor de dos enteros positivos'
ritmo de Euclides para calcular e1mximo
algoritmo cle Euclides recursivo es:

o MCD(A,0) :A
o MCD(A, B) : MCD(B' A mod B)

5.14.13 Cambio de base


recursivo para convertir un nmer
Realice un programa que incluya un subprograma
que 1 < b < 10)'
entero en base 10 a base b (se supone

5.14.14 Clculo recursivo de intereses bancarios


ImplementarunsubprogramaquecalculerecursivamenteenCuantoseconvierteun-.
inters 1' C(/'1) :Cx(I1100)+C(N-
1'1)
pital C al fina1ev ao"s y o "

5.14.15 Callejero
se desea ir de un punto inicial
(A) a un punto r -'
Supngase un barrio con sus calles. Si
(B).Escribaunsubprogramaquecuenteelnmerodecaminosposiblesquehayer..
y en direcc
se puede aYanzar en direccin norte
los dos puntos *uponi"ndo que slo
este. EjemPlo:

l_.

Posibles caminos:

ffiffiffiffiffi
h-nplemente un programa que pida el punto
inicial y el punto final y use el
pare clecidir cuntos caminos posibles hay'
-qrama
Pnonr,nnrls 161

5.14.16 De viaje por el desierto


En un oasis del desierto se encuentra un todoterreno y junto a l hay N bidones de ga-
solina. En eI deposito del todoteneno cabe exactamente un solo bidn y el coche solo
puede transportar otro en su maletero. Adems solo se puede llenar el deposito cuando
est vaco. Con el deposito lleno (un bidn), el todoterreno puede recoffer una distancia
A (en kilmetros).
Implemente un subprograma recursivo que tome como datos el nmero de bidones
que se tienen y la distancia A (en kilmetros) que recorre con un bidn y devuelva la
distancia mxima que puede recoffer el todoterreno (en kilmetros).
Ejemplos:

o Si se tiene 1 bidn recorre A kilmetros.


o Si se tienen 2 bidones recoffe 2A kilmetros.
o Si se tienen 3 bidones recorre 2A + Al 3 kilmetros.
o Si se tienen 4 bidones recoffe 2A + Al3 + Al5 kilmetros.

5.L4,17 Mismas cifras


Existen nmeros naturales que al multiplicarlos sucesivamente por 1,2,3,4... se obtie-
nen nmeros que tienen los mismos dgitos que el original pero en distinto orden (slo al
multiplicar por I se obtiene un nmero con los mismos dgitos en el mismo orden). Se
supone que para el nmero N, se cumple esa propiedad al multiplicarlo por 1, 2, 3..., X.
Es decir, si se multiplica N por cualquier nmero del intervalo [1,X], el resultado ser un
nmero con los mismos dgitos que N, pero en distinto orden. Entonces, se dice que el
"mximo multiplicador cabalstico" de N es X: MMC(N)=X. Ejemplo: MMC( l1285]-)
= 6; Por ejemplo, 142857*5=l14285. Para el nmero 142857 la propiedad se cumple,
adems de para el nmero 5. tambin para cualquier nmero del intervalo [1,6]. NOTA:
Se puede usar un nuevo tipo de dato llamado longlnt, que amplia el rango de los enteros,
v sus variables pueden tomar valores entre (-2147483648,+2141483617). Las opera-
ciones que se pueden realizar con longlnt son exactamente las mismas que los integer.
Teniendo en cuenta la def,nicin anterior, se pide, desarrollar un programa que dado un
entero n > 0 y con todos sus dgitos diferentes (se supondr que el usuario introduce
correctamente el nmero n), hallar su mximo multiplicador cabalstico. Para realizar
dicho programa habr que implementar previamente dos subprogramas: a) Un subpro-
grama recursivo que dado un nmero entero positivo nos devuelva el conjunto de todos
sus dgitos. b) Un subprograma iterativo que dado el nmero del que se desea conocer su
mximo multiplicador cabalstico y el conjunto generado en el subprograma anterior (el
conjunto que contiene los dgitos del nmero), nos devuelva el entero que corresponda
al mayor multiplicador cabalstico. (Ayuda: emplear el subprograma desarrollado en el
apartado a). c) Desarollar un programa que utilice adecuadamente los subprogramas
desarrollados en los apartados a y b.
t62 INTBODUCCIN A LA RECURSIN EN PASCAL

5.15 Soluciones a los Problemas


5.15.1 Camino entre dos Puntos
se pide la funcin recursiva
NOTA: se incluye todo el programa. En este apartado slo

PROGRAM secuencia;
VAR
origen, destino, contm, contr: integer;
FUNCTION m(n: integer): integer;
J pu. I
)

{eOsr:m=2*n}
eEGIN {m}
m: =2*n;
END; {*}

FUNCTION r(n: integer): integer;


foon. l )

{eosr:r=n-1}
nraru
u!u!r! f.J
t- J

f := n - 1;
END; {r}

PROCEDURE recursiva (a,b, cm, cr: integer) ;


{eRu,a>OYbr0}
contadores y los valores
irosr:secuencia de funciones as como los
intermedios, todo elIo por pantalla)
BEGIN {recursivai
write(a:4);
IFa<bTHEN
BEGIN
a := m(a) ;

recursiva(a, b, cm+1, cr);


write ('aPIicado m. ') ;
END
ELSE
-Fa>bTHEN
iaSrN
a := r(a) ;
:ecursiva(a, b, c[, cr + 1);
-*'rrte('aPIicado r.' ) ;
rl\l
SorucroNES A Los pRoBLEMAS t63

ELSE
BEGIN
'.,-i rol -.
writeln(,El nmero de veces aplj-cado m ha sido: ,, cm);
writeln('El nmero de veces aplicado r ha sido: ,, cr);
write('Camino de funciones aplicadas desde eI,,
' desLino a1 origen: ,)
END
EINJJ; t reCurslva -|

BEGIN {lrograma principal}


REPEAT
wrireln ('Incroduzca origen y descino ,
,

' (dos nmeros posirivos)' ) ;


readln (origen, destino) ;
UNTIL (origen > 0) AND (dest.ino > O) ;
contm : = 0;
aarnlr .= n.
recursiva(origen, destino, contm, contr) ;
readln
END. iPrograma principal)

5.15.2 Las torres de Hanoi

Quin encuentra una solucin iterativa a este problema? Sin embargo la solucin recur-
siva es ms abordable: pinsese que el mover n discos entre Ia aguja 1 y la 3 es posible
de la forma siguiente:

1. moviendo n - 1 discos desde la I ala2,


2. moviendo el disco mayor desde la 1 ala3 y
3. moviendo luego los n - 1 discos desde la 2 ala3.

Donde se ve que el problema original se ha dividido en: resolver el mismo problema


pero con un disco menos, larealizacin de un movimiento y resolver el mismo problema
con un disco menos.
Generalizando, el problema de mover n discos desde una aguja, llamada origen, a
otra, llamada destino, utilizando una aguja auxiliar, llamada auxiliar,puede conseguirse
de la forma siguiente:

1. Mover n - 1 discos desde la origen ala auxiliar utilizando como aguja auxiliar la
agtja destino.
2. Escribir'Se pasa el disco', n,'de', origen,'a', destino.
164 INTRoDUCCIN A LA RECURSIN EN PASCAL

3. Mover z - 1 discos desde la auxiliar a la clestino utilizando como aguja auxiliar l.


agttja origen.

El cdigo en Pascai que implementa lo anterior es el siguiente:

PROCEDURE MoverDiscos (n: integer, origen, destino,


auxiliar: char;
Jo-^. - /r
11 nI
vf
l!!u.
(_
{Post: saltda = fmovimientos para pasar n discos de
laaguja origen a Ia aguja destinoJ i
DETIT
D!gll\

IF n = 0 THEN {Caso trivial}


writeln
ELSE
BEGIN {Caso no trivial}
MoverDiscos(n - 1, origen, auxiliar, destino);
write ('se pasa disco' , n, , de, , origen, ,d, , destino) ;
MoverDiscos(n - 1, auxiliar, destino, oriqen)
END;
END; {fin ttoverDiscos}
5.15.3 Paridad de un nmero
PROGRAM EsParEsImpar(input, output) ;
VAR
n: integer; {nmero}

FfINCTION Eslmpar (n: integer) : boolean;


FORWARD; {Predec}aracin del identif icador "EsImpar" )

FI,T'TCTI0N EsPar (n: integer) : boolean;


/D7. - nl

{Post: EsPar = true si n es par y EsPar = false de lo cont.rario)


BEG]N
]FN=OTHEN
Espar := true !--l--l
{Caso Lr r v.l_dr
-r I
J

ELSE
Espar : = Eslmpar (n - 1) {caso no trivial}
END,- {esear}

FUNCTION Eslmpar(n: integer) : boolean;


{Pre, n ,= 0}
{eost: Eslmpar = true si n i -^--
es aL'Lyq! .,
]
SorucroxEs A Los pRoBLE,MAS 165

Eslmpar = false de Io contrario]


]]-TT
Jal\
- -

IFn=0THEN
Eslmpar := false {Caso trivial}
ELSE
Eslmpar := Espar(n - 1) {Caso no triviati
1..-; tEslmpar|

::lIN {Programa principa}}


write (' Introduzca un nmero entero: ,
);
readln (n) ;
IF EsPar(n) THEN {: not Eslmpar(n) }
writeln('EI nmero,, fr, , es par,)
ELSE
writeln(,El nmero , , fr, , es impar,)
:1,-r . {programa principal }

5.15.4 Funciones recursivas


LF(N) =3*Nl
l.F(x,N) =X*N
3. F(N) = Mtalque2M<tt
+. F (N) = Suma de las cifras que componen N

--. F (N) = Primera cifra de N

5,15.5 Funciones iterativa


i: presenta el cdigo de programas completos con la versin recursiva e iterativa para
-.strar la equivalencia de ambas versiones.

1. PROGRAM FuncionA;
VAR
num: integer;

FUNCTION FaRec(n: integer) : integer;


BEGIN
IF (n = O) rHnl
E':Da .- ?

ELSE
FaRec:=n*FaRec(n-1)
END;
sN PASCAL
t66 IN'rnoouccrN 't r'' RncunsrN

Falter (n: integer) : integer


;
FUI'{CTION
VAR
Parcial: integer;
BEGIN
Parcial : = 3;
1 := Ir,
WHIT,Ei>ODO
BEGIN * I;
Parcial := Parcial
r .= i - 1
I .-

END;
r'^TrPr := PafCial
END;

Falter2 (n: integer) :


integer;
FUI\CTION
VAR
Parcial: inLeger;
u l,[, -L N

Parcial := 3;
WHILEN>ODO
BEGIN * n;
Parcial := Parcial
n := n - 1
END;
FaIter ; = parcial
END;

a'cr\l { PrinciPa}}
Proqrama
wriietn('Valor de n: ') i

readln(num);
.."-.i rl n ( 'Recursivo =
FaRec (num) )
r EleTtr (num)
::.:";; " simPliricar
t' rterativo sin
)

EaIter (num) ) ;

;;;;"i; ('tterativo simPriricado= "


readln;
END. iPrograma PrinciPal)

. ,: lGRAM FUNCiONB;
---D

num: integer;
_-^^1 -
Xf: LCdL t
ll'

Sor,ucroNEs a Los PRoBLEMAS t67

FUNCTION FbRec(x: real; n: integer): real;


BEGIN
IF (n = 0) THEN
FbRec : = 0

ELSE
rb(ec := x - fbReC(x, n-I)
END;

FIINCTION FbIter(x: reali n: integer): rel;


VAR
parcial : real;
; 'l -r nar
r1uuYU! .
|

BEG]N
^--^.1 -1
yqrtrar ._
.- n.
v,
i := n
WHILEi>ODO
BEGIN
t - l
Pqrufqr -
".--^] ;- ^--^-
uarurar - ^,
i := i - 1

END;
Fblter; = parcial
END;

BEGIN {Programa principal}


writeln ( 'valor de x: ' ) ;
readln (xr) ;
writeln ( 'valor de n: ', ) ;
readln (num) ;

writeln ('Recursivo= FbRec(xr,num):0:0);


writeln ('Iterativo= "' , I,'-blter (xr, num) : U : U ) ;
/.^t .
END. {lrograma principa}}

3. PROGRAM FuncionC;
VAR
num: integer;

FII1VCTION FcRec (n: integer) : integer;


BEGTN
IF (n < 2) fUt't
FcRec : = 0
168 INrRooucctN a r,, RncunsrN BN PASCAL

ELSE
FcRec := 1 + FcRec(n DIV 2)
END;

FIINCTION Fclter(n: integer) : integer;


VAR
-^^ ^ l
:XpOlleiILe:^ IecrI;
; i nranav.
rlruuYU!,

BEGIN
exPonenLe : = 0;
.t ._
I .-
*.
If ,

WHILEi>=2DO
BEG]N
exponente := exPonente + 1

i := i DIV 2
END;
FcIter := exponente
END;

BEGIN {Programa principal}


writeln('valor de n: ');
readln (num) ;
writeln ('Recursivo= ' I,',cRec (num) ) ; ,

writeln ('rterativo= ' t'clter (num) ) ; ,

-^..t 1 r .

t_ - l
LND. tPrograma prlnclparJ

4. PROGRAM FuncionD;
VAR
num: integer;

FUNCTION FdRec(n: integer) : integer;


BEG]N
IF (N = O) THEN
FdRec : = 0
ELSE
FdRec := FdRec(n DIV 10) + n MOD 10;
:-t,] ;

:-],:l-0N Fdlter(n: integer) : integer;


".'t_:

: r: . 'i nl-oaar.
SoLUCI0NES A LoS PRoBLEMAS 169

i i -ro^o-.

BEGIN
crrml .- n '

i := n
WHILEi>=2DO
BEGIN
suma := sur + i MOD 10
i := i DIV 10
END;
Fdlter : = suma
END;

BEGTN {Programa principal}


wrireln ('Valor de n: ' ) ;
readln (num) ;
writeln ('Recursivo= ' , FdRec (num) ) ;
writeln ('Iterativo= ' , FdIter (num) ) ;
rarll .

END. {Programa principal}

5. PROGRAM FuncionE;
VAR
num: integer;

FUNCTION FeRec(n: integer) : integer;


BEGIN
IF (n < 0) rUUtq
:= FeRec(-n)
FeRec
ELSE IF (n < 10) THEN
FeRec : = n
ELSE
FeRec : = FeRec (n DIV 1-0 )

END;

FLI-NCTI0N FeIter (n: integer) : int.eger;


VAR
primera: integer;
BEGIN
primera := Abs(n)
WHILE (primera >= 10) DO
primera := primera DIV 10;
cr Lct
rtraTFav = pflmefa
.- n
Ir.lrnoouccrN n LA RECURsTN nNI PASCAL

END;

BEGIN {Programa PrinciPal}


writeln('valor de n: ') ;

readln (num) ;

writeln ('Recursivo= ' , FeRec (num) ) ;


writeln ('Iterativo= ' , FeIter (num) ) ;
readln;
END. {Programa PrinciPal}

5.15.6 Calculo recursivo de los polinomios de Hermite


FLIITCTION HermiteRec(x: real; n: integer):
real;
BEGIN
IF (N = O) THEN
HermiteRec : = 1

ELSE
IF (N = 1) THEN
HermiceRec := 2*x
ELSE
HermiteRec :- 2*x*HermiteRec(x, n-1)
2* (rr-1 )*HermiteRec (x, n-2)
END;

5.15.7 Calculo recursivo de los valores de la funcin de Ackerman

PROGRAM Ackerman;
VAR
m, n: integer;

FTINCTION AckermanRec(m, fl: integer) : integer;


BEGIN
IF (M = O) THEN
AckermanRec := n + 1
ELSE
1P (n = 0) THEN
AckermanRec := AckermanRec (m-1, 1)
ELSE
AckermanRec := AckermanRec (m-1, AckermanRec (m, n-1) )

END;

BEGIN {Programa PrinciPal}


Sor-ucroNEs A LoS PRoBLEMAS t7l

writeln ('Dame eI valor dem rr uu


)/
ta n, \/,
rr
readln (m, n) ;
writeln ('81 resulLado e S: I
, AckermanRec (m, n) )

:1,J. tPrograma prlnclpal.|

5.15.8 Clculo recursivo de la potencia de un nmero


r -I,ICTION Potencia(base, exp: integer) : integer;
-t-TtT
_r /^*- _ n\
\u^l./ - u/ THEN
Potencia : = 1
ELSE
Potencia := base*Potencia(base, exp-1) ;
:. --) .

5.15.9 Invertir un nmero entero


;:.CGRAM Inverso;
'--_R

n: integer;
\
'ISCEDURE Imprimirlnverso (n: integer) ;
]]-TIT
_ JII\
-

write (n MOD 10 ) ;
IF (n DIV 10 > 0) THEN
Imprimirlnverso(n DIV 10)

:: -iIN { Programa pr}nclpal


__-___ l_ - l
J

writeln('Dame un numero entero');


readln (n) ;
Imprimirlnverso (n)
:1,J. tPrograma prlnclpal]

5.15.10 Nmero de dgitos de un entero

'ICGRAM NumDigitos;
--- D

r. i nfaaar.
14. tllUuYU! ,

a -I'ICTION NumDigitosRec (n: integer) r integer;


nn PASCAL
t72 IutnouuccrN . r'' RBcunsrn

BEGIN
IF (n DIV 10 = 0) THEN

NumDigitosRec : = 1

ELSE
DIV 10) + 1
NumDigitosRec := NumDigitosRec(n
END;

BEGIN {Programa PrinciPal}


writeln('Dame un numero entero') ;

readln (n) ;
numero de digitos de n' ' es: ''
writeln('Er "
NumDigitosRec (n) ) ;
END. iPrograma PrinciPaI]

5.15.11 La necesidad de un caso base bien definido

Calculando F(4):
t*l-)\ = R
F/r\ - -L*tr()\
- -)*1 -, -).
F(2) = -2*F(0)
F(o) = 1

Calculando F(6):
c+o - -LQ
-J
nt.\ r * P/\
r \o/ - -t* (-)\ = B
n//\ - -*F'f ?\
.*T -)
tr(?) = -2*F(0)
L \ I
-
El0\ = 1

Calculando F(5):
/\
ts l5l -)
r * U/1\
I \J/
=

F(3) - -3*p(1)
F'{rt - -1*1-1)
F(-1) - 1*P(-3)

el caso base'
En este caso nunca se alcanza

5.15.12 Et atgoritmo de Euclides recursivo


.. -..^ l .l lae.
:: -::---. :l!rruuu,
-.1:
.. : : ilteger;
SolucroNES A Los PRoBLEMAS r73

a-TNCTION EuclidesRec (a, b: integer) : integer;


:_ :^
_'J T\T
ar!
rF (b = 0) rusu
EuclidesRec := a
ELSE
EuclidesRec := EuclidesRec(b, a MOD b)
t\Tn .

:EGIN {Programa principal}


writeln ('Dame dos ent.eros: , ) ;
readln (a, b) ;
writeln('E1 de ', a, , y , , b, , es:
MCD ,
,
EuclidesRec (a, b) ) ;
:),TD . {Programa principal
}

5.15.13 Cambio de base


:ROGRAM CamBase;

n, b: integer;

r-ROCEDURE CambioBaseRec (n, b: integer) ;


: ]TIT
_fult!
IF (n >= b) THEN
CambioBaseRec (n DIV b, b) ;
write (n MOD b)
:'Tn .

::GIN {Programa principat}


writeln('Dame un numero entero en base decimal_:,) ,

readln (n) ;
writeln ('Dame la base: , ) ;
readln (b) ;
writeln('Ef numera ,, fr, , en base ,, b, , es: ,);
CambioBaseRec (n, b)
:llD. {Programa principal}

5.15.14 Clculo recursiyo de intereses bancarios


;R0GRAM fntereses;
'rR
.
ut n 'i. int-a.
-!t --r.c$el;
t74 INTRODUCCIN A LA RECURSIN EN PASCAL

FUNCTION CalclnteresRec (c, Il , i: real) : real;


BEGlN
Ttr (n = 0) THEN
CalclnteresRec := C

ELSE
CalclnteresRec := n * i / 100 +
CalclnteresRec (c , fl-L, i)
END;

BEGIN ilrograma PrinciPali


writeln ('Dame un caPital: ' ) ;
readln (c) ;

writeln ('Dame un numero de aos : ' ) ;

readln (n) ;
writeln ('Dame un interes: ' ) ;
readln (i) ;

writel-n('El capital despues de', n, ' aos a un interes "


i, ' es: ', CalcrnteresRec(c'n'i));
1l
END. {Programa PrincPa}}

5.15.15 Callejero
PROGRAM Barrio;
VAR
xlnicial, ylnicial, xFinal, yFinal : integer;

PROCEDURE PedirPunto(VAR x, y: nteger);


BEGIN {eedirrunto}
write ('valor de X : ')

readln (x) ;

write ('Valor de Y : ')


uqstrlIn /rl
r-zl \ _1 /
r}ll ; PedlrPunto J

FUNCTION NCaminos (xlni, YIni, xFin, yFin: integer) : integer;

el Punto inicial Y el
{Cuenta eI numero de caminos entre
Punto
final avanzando nicamente en direccin norte Y estei
BEGIN
rF (xrni > xFin) OR (y]ni > yFin) THEN {Caso base}
__________

Sor-ucroNEs A Los pRoBLEMAS 175

NCaminos : = 0

ELSE IF (xlni = xFin) oR (ylni = yFin) THEN {Caso base}


NCaminos : = 1
ELSE
{easo recursivo}
NCaminos := NCaminos (xlni+1, ylni, xFin, yFin) +
NCaminos (xIni, ylni+1 , xFin, yFin);
lND;

3EGIN {Programa principal}


wrj-teln ('punto inicial: ,) ;
PedirPunto (xlnicial, ylnicial) ;
writ.eln ('Punto final: , ) ;
PedirPunto (xFinal, yFinal) ;
writeln ('EI numero de caminos es i , ,
NCaminos (xlnicial, yIniciaI, xFinal, yFinal) )

::,D. {Programa principal}

5.15.16 De viaje por el desierto


.?OGRAII KmConNbidones ;
'-- D

bidones: integer;
dist.ancia: real ;

:,NCTION DistMax(bid: integer; ds: real) : real;


::-T1T
_ _ Jrl!

IF (brd = 1) Then
DistMax : = dis
ELSE
rF (bid = 2) THEN
Di stMax := 2 * dis
ELSE
DistMax := DistMax(bid - 1, dis)
dis/ (z * bid - 3) ;
:1,);

::lIN {Programa principal}


REPEAT
writ.e ( ,Nmero de bidones:
readln (bidones) ;
UNTIL (bidones > 0);
REPEAT
116 INTNOPUCCTN I LA RECURSTN BN PASCAL

write ('Nmero de km/bidon: ')

readln (distancia) ;
TINTIL (distancia > 0) ;
writeln ('La distancia recorrida con ', bidones,
' bidones es ', DistMax(bidones, distancia) :6:2);
END. {Programa PrinciPali

5.15.17 Mismas cifras


1.
PROCEDURE Descomponer(n: longint; VAR C: TCDigitos);
{enu: n > o}
{eosr: C = conjunto de digitos de n} BEGIN
rF (n >= 1o) THEN {caso recursivo}
BEGIN
C:= C + [n MOD 10] ;
DescomPoner(n DIV 10, C);
END
ELSE
C:= C + [n] ; {caso base}
END; {DescomPoner}

2. FUNCTION Mayor-Mu1ti (n, longint; C: TCDigitos): integer;


{nRr' n > 0 AND C = conjunto de digitos de n}
{eOSf: Mayor_Multi = Maximo Multiplicador Cabalistico de n}

VAR
aux: TCDigicos;
i : integer;
BEGIN {Mayor-Mutti}
I._ I,

REPEAT
aux:= []; {uay que inicializar el conjunto dentro
del bucle, para eliminar Ios digitos
de} numero de la iteracion anterior]
f .- r T l, {Se comienza a probar con 2 Porque 1
siempre es multiPlo cabalistico)
Descomponer (n*i,aux) ;
LrllTIL (Aux <> C) ; {ttasta que los digitos de aux sean
dstintos de los de n)
.,.a1,o::_Mr.r1ti:= i - 1; {eorque i contiene el numero en
eI que se deja de cumPlir la
condicion de multiplo cabalistico)
SorucroNES A Los PRoBLEMAS r77

END; {Mayor_MuIti }

J. PROGRAM MMC; TYPE TDigitos = 0..9;


TCDigitos = SET 0F TDigitos;
VAR
Conjunto: TCDigitos;
num: longinL;
PROCEDURE Descomponer(n: longint; VAR C: TCDigitos);

FUIICTION Mayor Multi(n: Iongint; C: TCDigitos): integer;

BEGrN irronru*u Principal) {rnicia:-izacion}


Conjunto:= [];
REPEAT
write ('Introduzca un entero positvo con sus '
'digitos', diferentes:' \ ;
readln (num) ;
UNTIL num > 0; {Cuerpo del programai
Descomponer (num, Conjunto) ;
write('El mayor multiplicador cabalistico de ',
num/ ' es ') ;
writeln (Mayor_Multi (num, Conjunt.o) )
END. {Programa Principat}
Captulo 6

Tipos simples y conjuntos

- '. tipos de datos permiten modelar la informacin que va a manejar un programa.


-r',sta ahora se conocen tipos de datos predefinidos por
el lenguaje Pascal como son
--':3ger o char. Pero en algunas ocasiones estos tipos de datos predeflnidos no se
- '.LStan a las necesidades del programador y se hacen necesarias nuevas estructuras para
,rdelar con ms precisin objetos del mundo real. La mayora cle los lenguajes
de
-,rgramacin permiten que el programador especilique nuevos tipos de datos. En este
-.:tulo se estudiar tres tipos que puede def,nir el programador y que nos permiten
r ,-',delar:

a dominios de valores que se pueden enumerar (tipo enumerado),

a dominios de valores que son un subconjunto de otros dominios (tipo subrango) y


a dominios de valores que no tienen una relacin de orden (tipo conjunto).

6.1 Definicin de tipo de datos


- n tipo de datos es una expresin que representa tres aspectos importantes de los da-
:: el conjunto de posibles valores para los ejemplares del tipo, las operaciones que
: pueden realizat sobre estos ejemplares y las relaciones entre ellos. En general, estos
-es aspectos construyen un tipo de dato asocindole un identificador o nombre de tipo.
-:endiendo al conjunto de valores, se pueden clasificar los tipos en dos clases:

o Tipo simple: sus valores son atmicos e indivisibles. Dentro de esta clase, se
distinguen dos subclases: ordinal y no ordinal.
o Tipo compuesto: sus valores no son atmicos y se pueclen descomponer en otros
ms simples.

-tendiendo a si el tipo de datos es predefinido o no, se pueden clasificar los tipos de


-:tOS en:

179
180 Trpos SIMPLES Y coNJUNTos

o Tipo predeflnido: el conjunto de valores, operaciones y relaciones, junto con e


nombre del tipo. ya vienen prefijados en el lenguaje.
o Tipo definido por el usuario: el usuario especifica los valores y nombres del tipt
y de manera indirecta las operaciones.

As por ejemplo, el tipo integer es un tipo simple (sus valores son atmicos), es pre-
deflnido (ya viene prefljado en el lenguaje Pascal) y en particular es un ordinal (todc.
tienen predecesor y sucesor excepto el primero y el ltimo). La figura 6.1 nos muestr-
un resumen de los tipos de datos en Pascal.

EWy,
Puntero
I
Ordinal I Array
I Registro
l pr.a.ni.to IL Conprrrto
Ir r...q." Fichero

It
I l Char l- e,"aetinioo
I L- eoor...
L Defi. Proora* u.lo, IL f'"*.
Defi. Programador
I

lL Enunr erado
Subrango

Figura 6.1: Tipos de datos en Pascal.

La sintaxis en Pascal que debe emplear e1 programador para deflnir un tipo de datc,,
es la siguiente:

TYPE
TldentificadorTipo 1 = ExpresionDeTipo 1;

Tldentif icadorTipo_n = ExpresionDeTipo_n;


TTdentifj-cadorTipo_i es el nombre del tipo de datos y ExpresionDeTipo_i es un;
expresin que representa el dominio de los datos del tipo deflnido. El identificador que s;
asigna a1 tipo de datos debe ser representativo del domino de datos. El siguiente ejempl,
muestra 1a def,nicin de dos tipos de datos def,nidos por el usuario, cuyos identificadore,
son l:::ero y TLet.ra, y algunas variables de estos tipos.

.: : ,:;j': I- emploDeTipos;
TY!E
TFniero = integer;
Trpo pNutrERADo 181

nel Tletra = char;


VAR

ipo, i, j: TEnt.ero;

:' .':""u'
Jre-
dos Se vern a continuacin tres expresiones de tipos para describir nuevos
dominios: enu-
stra lnerado. subrango y conjunto.

6.2 Tipo enumerado


El tipo enumerado modela objetos cuyos estados tienen "nombres propios" y por tanto
se
puede enumerar estos estados. Por ejemplo, el objeto "da de la semana"
tiene 7 estados
perfectamente enumerables (lunes, martes,....,domingo). La principal caracterstica
del
tipo enumerado es que todos los valores que representa son listados explcitamente.
En
Pascal la sintaxis para declarar un tipo enumerado es la siguiente:

lrdentificadorTipo = (idevalor_1, idevaror_2, . ., idevalor_n) ;

Entre parntesis se escribe la lista de valores que def,ne el dominio de los datos
sepa-
rados por comas, es decir, los posibles valores que pueden recibir las variables
de tipo
lldentificadorTipo. El tipo enumerado es un tipo ordinal ya que la posicin de un
(idevalor-i) en la lista de la declaracin establece un orden entre
identificador de valor
ellos: el primer identificador est en la posicin 0, el segundo en la 1, etc. Las opera,
'-iones que se pueden realizar sobre ejemplares de tipo enumerado son las propias de
los operadores relacionales y las funciones succ, pred y ord. Los valores
e tipo
numerado se pueden pasar como parmetros reales en las llamadas a funciones y
ItOS pro-
--edimientos.
Pascal no permite realizar operaciones de lectura y escritura sobre variables
de tipo
:numerado. Por tanto, para poder leer y mostrar datos al usuario, el programador
dete
:lacer corresponder los valores de tipo enumerado con los valores que aceptan
los proce-
Jrmientos predeflnidos de lectura y escritura . El siguiente fragmento de cdigo
muestra
:n ejemplo del tipo enumerado que modela das de la semana y cmo la funcin leerDia
:evuelve el da de Ia semana solicitado al usuario. Para ello, en la instruccin
CASE se
lna :stablece una corespondencia entre el tipo de datos TDiasSemana (tipo enumerado)
rse e
-::eger (tipo de datos que utiliza la funcin readln).
p1o
res ; IGRAM LosDiasDelaSemana,.
-:?E
TDiasSemana = (Lun, Mar, Mie, Jue, Vie, Sab, Dom) ;
:jl
dia, hoy: TDiasSemana;
t82 TIPoS SIMPLES Y CONJUNTOS

FUNCTION LeerDia: TDiasSemana;


VAR
numdia: inreger;
BEGIN
REPEAT
write ('Introduzca el nmero del dia: ');
readln(numDia);
UNTIL (numDia >= 1) AND (numDia .= 'l) ;
CASE numDia of
1: LeerDra := Dom;
r^^---l^ - Trr.
z,:
^ LeeLD.ld := rJull;

:/: -reelU].d
--.^ := Sb
hJNJJ; t deI case l 1

END; {t eeroiai

Errores comunes

Un error comn en los programadores noveles es confundir los valores de un tipo en-'
merado con cadena de caracteres. Los valores de tipo enumerado son identificadort
completamente diferentes de las cadenas de caracteres y con restricciones y caracteri''
ticas particulares. No se debe repetir un mismo valor en distintas deflniciones de tip
enumerados y no se deben redefinir palabras reservadas. El siguiente ejemplo mues!:-
declaraciones de tipos de datos errneas.

TYPE
TBoleano = ('verdad', 'falso')
{error: no son identificadores, son cadena de caracteres}
TAmigos=(pepe, juan, pedro, miguel)
TEnemigos= (antonio, pedro, enrique)
{error: se repite el valor pedroi
TNotas = (do, re, mi, fa, so1, Ia, si)
{error: pa}abra reservada do}

6.3 Tipo subrango


Esre tipo de datos modela dominios de valores que son un subconjunto de otros dor:-
nios. Por ejemplo, el dominio "nmero del da del mes" tiene como valores ios nmer.
que \an desde t hasta 31. Estos valores son un subconjunto de los nmeros enter,-
Cuando se define un tipo subrango se indica implcitamente el tipo sobre el que se ba.-
TIPo CoNJUNTo 183

en el ejemplo anterior ste sera el tipo de los nmeros enteros. Este "supertipo" se de-
nomina tipo base o tipo anfitrin y debe ser de tipo ordinal. La sintaxis de Pascal para
declarar un tipo subrango es la siguiente:

l-dentificadorTipo = constlnf .. constsup;


Donde TldentificadorTipo es el nombre del tipo de datos y constlnf y constsup
\on constantes que representan los valores del lmite inf'erior y superior del subrango
respectivamente. Estos valores de constantes han de ser de tipo ordinal, estar en orden
,-reciente y ser ambas del mismo tipo. Las operaciones que se pueden aplicar a los datos
Je tipo subrango son todas las operaciones y funciones que se le pueden aplicar al tipo
nfitrin. Se debe tener cuidado al asignar el resultado de estas operaciones a variables
Je tipos subrango ya que ste puede ser superior a constsup o inferior a constlnf y
r.-asionar un effor de desbordamiento. Este tipo de datos ayuda a documentar el pro-
rrama ya que indica explcitamente el intervalo de valores que tiene sentido en una
. riable (expresan parte de las precondiciones y postcondiciones), y ayuda a depurarlo
e f'acilita la deteccin de errores de desbordamiento si el compilador est debidamente
:,.nfigurado). El siguiente cdigo muestra un ejemplo de uso del tipo subrango.

-- ---r
_ __-

TNumMes = 1..L2;

:
--ICTION LeerNumMes TNumMes;
:

::,
entMes : int.eger;
]: ATIT
_ _ JII!

REPEAT
write ('Introduzca ef mes (formato tt4ytt
) : ') ;
readln (entMes) ;
LIITTIL (entMes >= 1) AND (entMes <= 72) ;
LeerNumMes := entMes;

6,1 Tipo aonjunfo


:, tipo conjunto modela dominios cuyos valores no tienen una relacin de orden. Este
:o de dato representa una coleccin de valores que deben ser del mismo tipo. La
.-rtaxis en Pascal para declarar este tipo de datos es:

-i:ntificadorTipo = SET OF tipoBaseOrdinal;


lt,rnde Tldentif icadorTipo es el nombre del tipo de datos, SET OF son las palabras
':.en'adas que identifican que es un tipo conjunto y tipoBaseOrdinal es el tipo de dato

L
184 TTPOS SIMPLBS Y CONJUNTOS

sobre el que se define la coleccin de elementos que tendr el conjunto y debe ser u:
ordinal. Los valores que describen al conjunto se expresan con la sintaxis:

[] i st.a- elementos l
Donde lista-elementos es una lista (puede ser vaca) de constantes, variables o e'-
presiones del mismo tipo de dato separadas por comas y enceradas entre corchete'
Ejemplos de conjuntos:

TYPE
TColores= (rojo, azu1, verde, amarillo);
TConjuntoColores = SET 0F TColores;
VAR
conjA, conjB, conjC: TConjuntoColores;
BEGIN
conjA:=frojo, azul, verde]; {conjunto de tres coloresi
conjB.= [rojo. .verde, amarillo] ; {conjunto de cuatro colores}
conjC:= [1 ; {conjunto vaco}

En la asignacin a una variable de tipo conjunto los elementos del conjunto deben "
compatibles con el tipo base. La tabla 6.1 muestra las operaciones que se pueden
con valores de este tipo de datos. El nuevo operador IN tiene la mnima prece(
respecto al resto de los operadores estudiados hasta el momento. I-a tabla 6'2 mue'
la precedencia entre operadores incluyendo los de conjuntos. El siguiente fragmentt-
cdigo muestra un ejemplo en el que se construyen los conjuntos de nmeros pafes
impares desde 0 hasta 9.

CONST
ITiIAXNUM=9;
TYPE
TDigitos= 0 . .9;
TConjunto= sET 0F TDigitos;
TRango= 1..}4AXNIIM + 1;
VAR
pares, impares: TConjunto;
i: TRango;
BEGIN
pares := [];
impares := [];
FOR i := 1 to MAXNUM do
IFimod2=0THEN
pares := Pares + [il
ELSE
TIPo CoNJUNTO 185

impares := impares r [i];


t' _

Descripcin Operador Ejemplo Resultado


Pertenencia. De- IN e IN conjA true
vuelve Lrue si un
elemento pertenece a
un conjunto.
Inclusin. Devuelve (=, =) conjA <= conjB, false, true
t.rue si es subcon- conjA => conjB
junto.
Igualdad. Devuelve conjA = conjB fal se
true si son iguales.
Desigualdad. De- conjA <> conjB true
vuelve true si son dis-
tintos.
Unin. + conjA + conjB [rojo,verde,azul]
Interseccin. conjA * conjB [rojo, azul]
Diferencia. conjA - conjB fverde]
..bla 6.1: operaciones que se pueden realizar con conjuntos (conjA=[rojo, verde, azull,
njB=[rojo, az] y e=rojo).

Observar que la variable i de tipo subrango ha sido declarada con el lmite superior
-:-'-NUM + 1 para evitar desbordamiento de valores al finalizar el bucle FOR. Los ele-
3ntos de un conjunto no son accesibles directamente. Es decir, no se pueden leer
-r:ictamente del teclado (con read o readln) ni se pueden escribir directamente (con
---:e o writeln). Para visualizar los elementos de un conjunto:
1. Se toma una variable del mismo tipo base del conjunto.
l. Se asigna a dicha variable el primer valor del tipo base.

,l' Se comprueba si dicha variable pertenece al conjunto (mediante el operador rN),


mostrndolo por pantalla si es cieo.
-1. Se asigna el siguiente valor (mediante la funcin succ) y se vuelve a comprobar
sucesivamente hasta recorrer todos los posibles valores.

. compiladores suelen restringir el uso del tipo conjunto por cuestiones de implemen-
,rn, obligando al programador a reducir la amplitud del domino del tipo base. por
: :rrplo, en TurtloPascal, el elemento mayor de un conjunto no podr superar a1 ele-
rtto con valor ordinal255, el menor no podr ser inferior al que tenga el valor ordinal
. no podr tener ms de 255 elementos.
186 TTpOS SIMPLES Y CONJUNTOS

Operador Nivel de pre-


cedencia
NOT 4
/, *, DIV. MOD, AND --)

+, -r 0R 2
<, <=, =, ), )=, <>, IN 1

precedente es el 4)'
Tabla 6.2: Precedencia entre los operadores (el nivel ms

6.5 Tipos annimos


que ste tenga -'
En Pascal es posible deflnir variables de un nuevo tipo de datos sin
la que se define la variat'-'
nombre (se define la estructura del tipo en la misma lnea en
y las variables i/ ) : -:
En el siguiente ejemplo se declara la variable x de tipo subrango
tipo enumerado.

VAR
x:1..10;
y: (A, B, C) ;
z: (A,B,C) ;

Aunque Pascal 1o p'=-


Esta clase de declaraciones recibe el nombre de tipos annimos.
(tngase en cuenta el pasc' -'
mite es recomendable evitar el uso de los tipos annimos
parmetros en la llamada a subprogramas y la depuracin del programa).

6.6 Compatibilidad de tiPos


vlidas e : ':
La compatibilidad entre tipos establece las reglas que definen las relaciones '

en el moment -
ejemplaies de diferentes tipos. Estas reglas se utilizan por ejemplo
es correcta desde el pu
urignu. una variable u otru y poder determinar si la asignacin
de vista de la compatibilidad de los datos.

Tipos idnticos Y comPatibles

Se definen como tipos idnticos a los tipos no annimos


que presentan una de estas
condiciones:

Untiposedefineexplcitamentecomodeotrotipo.PorejemploTlesidnti.
T3. ya que el identificador T1 es usado explcitamente para definir T3 (lnea -1

\arios identificadores de tipo se declaran en la misma lnea (estn en la mi


lnea de declaracin). Por ejemplo T1 es idntico a T2 (lnea 2)
ya que estn e :
misma declaracin (declaracin separada por el carcter ",")'
Cursrrolrs DE TIpo rEST 187

,t) rYPE
.rl m1 Ta - lr..100;
LLt-
-l
]
') T? = T.l .
-- t
..+) T4 = L..1oo;

T1no es idntico con los dems ya que no es declarado explcitamente con Tl, T2 ni T3.
Dos tipos son compatibles si al menos una de las siguientes declaraciones es verdadera:

o son idnticos,
. uno es subrango de otro o
o ambos son subrangos del mismo tipo base.

un Por ejemplo, los tipos anteriores son compatibles.


e).
de -{signacin compatible

Una expresin e, cuya evaluacin es de tipo t2, se dice que es asignacin-compatible


t1 si ocurre una de estas situaciones:
con una variable de tipo

t1 y t2 son idnticos.
o t1 es real y t2 es entero o un subrango de entero (realmente el compilador hace
conversin automtica y pasa L2 a real).
rer-
de o t1 ) t2 son tipos ordinales compatibles (y para que no haya desbordamiento e es
un valor permitido de1 tipo t1).

Cuando un compilador comienza el proceso de compilacin de un cdigo fuente chequea


dos clases de errores (a grandes rasgos): effores de compilacin y erores en tiempo de
ejecucin. Para que no haya effores de compilacin en expresiones en las que aparecen
ltre involucrados diferentes tipos de datos stos han de ser idnticos y/o compatibles. Para
de que no haya errores en tiempo de ejecucin, los valores y tipos han de ser asignacin-
nto compatibles.
Pascal requiere que en el paso de parmetros por referencia en una llamada a una
funcin o procedimiento los tipos sean idnticos, mientras que en asignaciones y paso
de parmetros por valor es suflciente con ser asignacin-compatible.

dos
6.7 Cuestiones de tipo test
loa 6.7.1 Enunciados
).
Las siguientes cuestiones pueden tener una o ms respuestas correctas:
ima
nla 1. Dada la siguiente definicin de tipos y constantes:
188 TIPOS SIMPLES Y CONJUNTOS

CONST
N = 10;
TYPE
TColor = (amarillo, azul, rojo);
TDigito = 0.'9;
TMinusculas = a..zi
TConiNumeros = SET 0F TDigit.o;
TConjLetras = SET oF TMinusculas;
VAR
n: 1..N + 1;
es correcta:
Decir cul o cuales de las siguientes afirmaciones
se puede declarar --
(a) La declaracin de TMinusculas es correcta porque
subrango del tiPo char'
(b)LadeclaracindeTColoresincorrectaporqueenlugardeparntesisdebe:-
haber corchetes.
(c)Ladeclaracindelavariablenesincorrectayaquenosepuededeclarar--
subrangoconoperacionesaritmticasenlapartededeclaracindevariabl..
de TConj Numeros es correcta ya que
el tipo base es adecua-
(d) La declaracin
y la sintaxis tambin'
ocurrira que:
2. Si el siguiente fragmento de cdigo se compilase

PROGRAM Coche;
TYPE
TCoches= (BMW, Mercedes, Ford, i"lat ) ;
TCamiones = (Ford, Man, Pegaso, Renault, Mercedes) ;

VAR
tuCoche: TCoches;
tuCamion: TCamiones;
BEGIN
writeln ('escribe el nombre de tu coche Y camion') ;

readln(tuCoche, tuCamion) ;
r \Tn

sintcticos'
(a) El bloque de declaracin de variables tiene errores
(b) El bloque de instrucciones presenta effores de compilacin'
(c) El bloque de cleclaracin de tipos es incorrecto'
( d) La cabecera pRocRAM presenta un identif,cador de programa incorrecto'
Cuosrrolos DE TIPO rEST 189

--) . Teniendo en cuenta el siguiente fragmento de cdigo:

PROGRAM ProbO4;
VAR
x2, y2: integer;
--^^t
xJ: lcdr,'
PROCEDURE Procesa(veR x:integer; VAR y:real) ;
BEGIN

END;
BEGIN
Procesa (x2, y2) ;
r,l -_ r,a.
.- ILt
^J
END.

(a) El cdigo es correcto y no presenta ningn error de compilacin.


(b) La llamada al procedimiento procesa (x2, y2 ) presenta un error de compi-
lacin por tipos incompatibles.
(c) La instruccin x3 1= y2 dar un effor de compilacin por incompatibilidad
de tipos.
(d) En la cabecera del procedimiento no se pueden deflnir parmetros de tipo
real por referencia.

4. El siguiente fragmento de cdigo produce:

PROGRAM Ta]]a;
VAR
tallas: SET OF 1. .80;
etiquetas : (' s"' M"' L"' xL"'xxl' ) ;
BEGIN
tallas: = [60] ;
writeln (' int.roduce las tallas' ) ;
readln (tallas) ;
wrir,eln ( ' introduce Ias etiqueLas' );
readln (etiquetas) ;
END.

(a) Error de compilacin de desbordamiento de rango en la instruccin


tallas: = [60] .

(b) En'or de compitracin en operacin de lectura,/escritura.


(c) Enor de compilacin de declaracin de variables.
(d) No da errores de compilacin.
t

190 TTpOS SIMPLES Y CONJUNTOS

5. Dadas las siguientes declaraciones:

TYPE
T1 = 0..33;
ra
LZ
_ 1n
_ IV.,JJI
2?.

VAR
,,1
VI.
. TT
I, .

tr). f),

(a) Los tipos T1 y T2 no son compatibles porque a veces no son asignacir--


compatibles.
(b) Los tipos T1 y T2 si son compatibles.
(c) La asignacin v2: = vL es siempre incorrecta y el emor se detecta en tiemp:

de compilacin.
(d) La asignacin v2;= ,,rl puede ser incorrecta dependiendo del valor de v1.

6. Si NumeroHabitacion es una variable de tipo TRango deflnido como

TYPE
TRango = 1..500;
con NumeroHabi tac ion?
Es la siguiente expresin asignacin-compatible

PRED (NumeroHabitacion DIV 500)

(a) S, pues el resultado de la expresin es un valor que est dentro del domr:
NumeroHabitacion.
de
(b) No, pues el resultado de la expresin es un valor que est fuera del
de NumeroHabitacion.
(c) 1o, pues el resultado de la expresin es un valor real, y TRango es

subrango de los integer.


(d) S, pues aunque el resultado de la expresin es de tipo rea1, Pascal hace
conversin automtica a integer.

6.7.2 Soluciones
Las respuestas correctas son:
I d La declaracin de TMinusculas es incorrecta porque faltan comillas simples a

caracteres "a" y "r".


i.L, 1.c. El bloque de instrucciones es incorrecto porque no se pueden leer tipos
merados desde la entrada estndar. Las declaraciones de tipos de datos son inc
porque har, valores enumerados que se repiten.
Pnonr-Brr.s t9t
:.b. En el paso por ref-erencia los datos deben ser de tipos idnticos. La asignacin
'.: : =y2 es asignacin-compatible.
- b , 4.c. La opcin (a) es falsa porque el tipo base del conjunto [60] (integer) es tipo
-,rmpatible con el subrango 1..80. La declaracin de la variable etiquetas es errnea
:lrrque se especifica una lista de string, y deben ser una lista de identificadores.
iby5.d.
- b. Elresultadodelaexpresinpred(NumeroHabitacion div 500) puedeser-l o0.

6.8 Problemas
6.8.1 Conversin de formato de fecha

>: desea realizar un programa que pida al usuario una fecha en formato DD MM AA,
-,,11o por ejemplo 12 01 01 (dos dgitos para el da, dos para el mes y dos para el ao) y
,: muestre por pantalla con el nombre del mes y con cuatro dgitos del ao. Por ejemplo,
., salida de la fecha anterior debe ser " 12 de enero de 2001 ".

6.8.2 El mejor transporte


l,:alice un programa que determine el medio de transporle ptimo para realizar un viaje
-: acuerdo a las preferencias del usuario. El programa preguntar ai usuario si quiere
.,:jar barato y si tiene prisa. Se determinar el transporte ptimo de acuerdo a las si-
..riente reglas:

Si se quiere un viaje barato y sin prisa se debe viajar en bicicleta.


Si se quiere un viaje barato y se tiene prisa se debe viajar en autobs.
Si se quiere un viaje caro y sin prisa, entonces se usar el coche.
Si se quiere un viaje caro y se tiene prisa se usar el avin.

6.8.3 El semforo
f,:alice un programa que simule el comportamiento de un semforo. Cada vez que se
:ulse la tecla intro cambiar de color. El programa terminar cuando cambie de color n
:ces (por ejemplo n=10). Para realizarlo utilice un tipo enumerado.

6.8.4 Letras maysculas


::criba un programa que lea una fiase y muestre el conjunto de letras maysculas que
.-ne. La fiase acaba cuando encuentra un punto ".". La longitud se supone inferior a
--i-i caracteres.
792 TIPOS SIMPLES Y CONJUNTOS

6.8.5 ReParto de la baraja


a cuatlo lugadotes con algn mtodo
Implemente un programa que Iepafia cuatlo ealtas
que la mrsma carta no se reparte m:
aleatorio. Se utilizarn conjuntos para garantizar
juega con una baraja en 1a que hay 4 palc'
de una vez. se debe tener en cuenta que se
(oros,copas,espadasybastos)yl0cartasencadapalo(de1a1ala10).Lasalidad
jugadores'
cada uno de los 4
programa ser el conjunto de 4 cartas que le ha tocado a

6.8.6 ComParando dos Palabras


acabadas en un punto y muestre -
Escriba un programa que lea dos palabras por teclado
siguiente informacin:

o Las letras que tienen en comn ambas palabras'

a Las letras que tiene la primera palabra y que no estn en la segunda'


en la primera'
a Las letras que tiene la segunda palabra y que no estn

6.8.7 Estadsticas de una frase

Implemente un programa que solicite aI usuario la


introduccin de una frase acabad' ' I

punto y devuelva la siguiente estadstica:

oNmerodeletras(sincontarlosespaciosenblancoysignosdepuntuacin)'
o Nmero de vocales.
o Nmero de dgitos.
o Nmero de smbolos de puntuacin (:;,'i!?)'

6.8.8 El juego de piedra, papel o tijera


Implementeunprogramaquemuestreporpantallatodaslasposiblesjugadasdel-
y jugador escoge L': -
"pi.d.u, papel otijera". En este juego, hay <los jugadores cada
piedra gana a la tije:-
op"ion"s. Segn las reglas, el papel gana a la piedra' la
"ru, Adems' el programa m' ' '
tijera lana al papel. Si los dos coinciden' hay un empate'
en cacla jugada quien es el jugador ganador'

6,9 Soluciones

6.9.1 Conversin de formato de fecha


no pueden trabajar con tipos e :
LLrs subprogramas predefinidos write y readln
-

mes ledo por teclad


rados, La funcrn NombreDeMes transforma el nmero del
Para escribir el nonl:
subrango de entero) a nombre del mes (tipo enumerado). '
Sor,ucrouBs t93

-,:s por pantalla es necesario


transformarlo a una cadena de caracteres (procedimiento
.. :ribeMes).

;l IGRAM ConversionFecha ;
lcnvertir eI formato de una fecha)
INTRADA: Ia fecha en formato dd mm aa]
SALIDA: la fecha en formato dd nombre mes y aaaa)
-:PE
TMes= (ene, feb, mar, abr, may, jun,
juI, 9o, sep, oct nov, dic);
TNumDi-a= 1..31;
TNumAnyo= 0. .99;
TNumMes= L. .L2 ,
- -- f

dia: TNumDia;
MCS: TNumMeS;
anyo : TNurnAnyo;
nombreDelMes: TMes;

=i.CCEDURE LeerFecha(VAR dia: TNumDj-a; VAR mes: TNumMes;


VAR anyo: TNumAnyo);
-iR
entDia, entMes, entAnyo: int.eger;
::GIN {leerfecha}
REPEAT
write ('Introduzca el dia (formato',DD") :' ) ;
readln (entDia) ;
Ln{TIL (entDia >= 1) AND lentDla <= 31);
dia := entDia;
REPEAT
write(,InLroduzca el mes (f ormato ',MM,')
readln (enTMes) ;
UITTIL (entMes >= 1) AND lpnlMeq = 1)\ .

mes : = entMes;
REPEAT
write ('Introduzca el ao (formato rrAAtr. /
)

readln ( entAnyo ) ;
UI\ITIL (entAnyo >= 0) AND (entAnyo <= 99);
anyo : = entAnyo
:-JJJ; t Leerl,'echa i

I-J'ITCTION NombreDeMes (noMes : TNumMes ) : TMes ;


194 TIPOS SIMPLES Y CONJUNTOS

VAR
i: TNumMes;
mesActual: TMes;
BEGIN
mesActual := eflei
FOR i: = 2 TO NoMes DO
mesAcLual :=
SCC(mesActual) ;

NombreDeMes : = mesActuaf
END; {nombreDeMes}

(NOMMCS : TMES) ;
PROCEDURE ESCTibCMCS
BEGIN
CASE nomMes OF
ene: write (' enero' ) ;
feb: write (' febrero' ) ;
mar: write ('marzo' ) ;
abr: wrice i' abril' ) ;
may: write ('maYo') ;
jun: write 1'junio') ;
jul: write ('julio') ;
ago: wriLe (' agosto' ) ;
sep: $rrite(' sePtiembre' ) ;
oct: NriLe(' ocLubre' ) ;
nov: write ('noviembre' ) ;
drc: write (' d'iciembre' ) ;
nNo {Case)
END; {escribeMes)

BEGIN {Programa PrinciPal}


LeerFecha(dia, mes' anYo) ;
write('La fecha es eI dia' ' de ');
EscribeMes (NombreDeMes "(mes) ) ;

writeln(' de ', anYo + 2000)


END. {Programa PrinciPa}}

6.9.2 El mejor transPorte


PROGRAM Transporte;
Ptimo para un viaje)
{Determinar el transporte
eI viaje (rPido Y barato)
iunmaoa, Preferencias sobre
)
(bicicleta, autobs,
{sar,roar vehculo ms aProPiado
coche o avin) )
SolucroNBs t95

IIPE
TMedio= (bicicleta, autobus, coche, avion);
---R

cpcion: char;
prisa, barato: boolean;

:--IICTION MejorTransporte (prisa, baraLo: boolean) : TMedio;


:]1T\T
,_Ja1!

IF barato THEN
IF prisa THEN
Mej orTransporte : = auLobus
ELSE
Mej orTransporte : = bicicleta
ELSE
IF prisa THEN
MejorTransporte := avion
ELSE
MejorTransporte := coche;
r'-f .

.:CCEDURE MuestraTransporte (t : TMedio)


:]lTIT
_ _ JTI\

CASE T OF
bicicleta: writeln ('bicicleta' )

autobus : writeln ('autobs' ) ;


coche: writeln ('coche' ) ;
avion: writeln ('avin' ) ;
END;
t1_1 -

.:3IN{ Programa principat }


writeln('t.iene prisa? (S:s, N:no) ,);
readln (opcion) ;
prisa:= (opcion = 'S') 0R (opcion - ,s,);
writeln (' quiere transporte barato? (S : s, N: no)
readln (opcion) ;
barato:= (opcion = ,S,) 0R (opcion = ,s,);
writeln ( ' E1 mej or transporte es : , ) ;
muestraTransporte (MejorTransporte (prisa, barato) );
readln;
_..- . t Programa prlncrpai )
t96 Tlpos SIMPLES Y CONJUNTOS

6.9.3 El semforo
El estado del semforo es simulado por una variable de tipo enumerado de tres valor-'
(\os tres posrbles co\ores). La tuncrn Darvalor petmite a\ usuario rrrediante 1.I 111er:-
indicar el estado inicial. La funcin Siguiente deduce el siguiente color al que tier.:
que cambiar el semforo mediante operaciones succ (ntese que para el ltimo va1'-
enumerado no se aplica la operacin succ).

PROGRAM Semaforo;
{simulacin de un semforo}
{uutnAoe' estado inicial deI semforo}
isalfoa, cada vez que se pulsa tecla intro
eI semforo cambia de estado)
CONST
N= 10;
TYPE
Tsemaforo= (verde, amarillo, rojo) ;
VAR
s: TSemaforo;
.l i raaav.
I. rtluuYu!,

FUNCTION Siguiente(nr Tsemaforo) : TSemaforo;


BEGIN
-^.,,t1
I Uquf If
,
,

IFn=rojoTHEN
Siguiente: = verde
ELSE
Siguiente: = succ (n) ;

END;

PROCEDURE MostrarValor (n: Tsemaforo) ;


BEGIN
CASE N OF
rojo: writeln{'rojo');
amarillo: writeln(' amarillo' ) ;

verde: writeln ('verde' ) ;


:r1.
:l.l ;

: -l:l- -lN DarValor: TSemaforo;


.,..::.

, -*1-6^ar.
_---!Y!! /
--l:
: --: - ll- :.=:lu : Integer;
Sor,ucroNBs
t9l
VAR
j : integer;
BEG]N {uenu}
REPEAT
writeln(,Escoja una de las tres opciones,)
writ,eln (, 1 . Semaforo en rojo,
);
writeln(,2. Semaforo en amarillo,) ;
writeln (,3. Semaforo en rar^^
vurvu / \
/, -

readtn (j ) ;
Ut\TTrL (j , o) s (j < 4);
Menu:= j;
END; {tvlenu}

:EGIN {tarValor}
i:= Menu;
CASE OF i
L: DarVal_or := rojo;
2: DarVa1or := amarillo;
3: DarVa1or := verde;
END;
lD; {DarValori

:EGIN {nrograma principal}


s := Darvalor,.
MostrarValor ( s ) ;
FOR i := t TO N DO
BEG]N
s := Siguiente (s);
Most,rarValor (s) ;
END;
:ID. {erograma principal}

6.9.4 Letras maysculas

:, T; ;;;;i. ; ; ::::Tffi ,Tl;


ras rerras maysculas Ei programa
.;.i::r:ilHr,i:j1:::".?:,,:: ::1i.,T'"
.
prin_
- : : :::,.,"I:' :""', : :::": ::: l, : I f, ;
"

rI amenfos
.mentos del conjunto
nnni',-r^ realizando
*^-r:-^,-, .
;;;,#;iffiril:
,vvurrrIvtrLU

sucesivas operaciones TN.


uu

$T'
{-.
.:.IGRAM Mayusculas
; :
--star letras maysculas de una frase
)
:NTRADA: una frase t.erminada en un punto)
198 TIPoS SIMPLES Y CONJUNToS

{salrna, las letras escritas en maysculas}


LUN.7
I{AY= l'A' . .'Z') ; {todas las mayscutas}
TYPE
TMayusculas= 'A' .'Z'i
TConjunto= SET OF TMayusculas;
VAR
conjB: TConjunto;
^-
!; ^t^--
llIqr,

PROCEDURE MostrarConjunto (conjC: TConjunto) ;


VAR
I : TMayusculas;
BEGIN
writeln ('Las maysculas son: ' ) ;
FOR I i= 'A' TO 'Z' DO
IF I IN conjc THEN
writeln(l);
END;

BEGIN{Programa principal i
cnniR .=
. l-l
t_)
.
I

writeln('Escriba una frase acabada en punto/);


REPEAT
read (c) ;
]F c IN MAY THEN
conjB := conjB + [c];
T]NTIL C = , .,;
Mostrarconjunco (conj e) ;
END. {Programa principali

6.9.5 Reparto de la baraja


En cuatro conjuntos (variables globales oros, copas, bastos, y espadas) se
1a cuenta de los naipes de cada palo (nmeros del I al 10). El procedimiento repar:
genera aleatoriamente una carta(el palo y el naipe) que no est en los conjuntos c
r-eclimiento guardaCarta Ia almacena en el correspondiente conjunto. El
-'*= -:raCarta imprime por pantalla el palo y el naipe de Ia carta.

PROGRAMRepartirCartas ;
iRepartir cuatro naipes de una baraja a cuatro jugadores
sin repetir naipe)
SolucroNps 199

:lrnonnl
lEU. . 1
-_!f J

:-LIDA:los naipes de cada jugador)


-_ -lE
- --
TPalo= (oro, bast.o, espada, copa);
TNaipe= 1. .10;
TConjNaipe= SET OF TNaipe;
--- D

cros, copas, bastos, espadas: TConjNaipe;


jugador, repartos : inceger;

: IICTION dameUnPalo :TPalo;


:l:Ttl
__JfI\

CASE (Random(4) + 1) 0F
1 : dameUnPalo: =oro;
2 : dameUnPalo: =basto;
3 : dameUnPalo: =espada;
4 : dameUnPafo: =copa;
END i

-- -NCTION dameUnNaipe: TNaipe;


I t^T1r
rt!

dameUnNaipe : =Random ( 10 ) +1 ;
I'in .

:-I\TCTION estaRepetido(oros, copas, bastos, espadas:TConjNaipe;


palo:TPalo; naipe:TNaipe) : boolean;
]f-TIT
_-JAI\

CASE palo OF
oro: estaRepetido := naipe IN oros;
copa: estaRepetido := naipe IN copas;
espada: est.aRepetido := naipe IN espadas;
basto: estaRepetido := naipe IN bastos;
END;
I'Tn .

=LOCEDURE reparteunaCarta(oros, copas, bastos,


espadas : TConj Naipe;
VAR palo:TPalo; VAR nalpe:TNaipe) ;
:IGIN
REPEAT
palo : =dameUnPaIo;
200 TIPoS SIMPLE,S Y CoNJUNToS

naipe: =dameUnNaipe;
L'IiTIL (NOT estaRepetido(oros, copas, bastos, espadas,
palo, naipe) )

END;

PROCEDURE guardaCarta(VAR oros, copas, bastos,


espadas : TConjNaipe;
palo:TPalo; naipe :TNaipe) ;
BEGIN
CASE palo 0F
oro: oros := oros + [naipe];
Copa: copas := coPaS + fnaipe];
espada: espadas := espadas + lnaipe];
basto: bastos := bastos + [naipe];
END;
END;

PROCEDURE muestraCarLa (palo:TPalo; naipe :TNaipe)


BEG]N
CASE palo 0F
oro: wriLel-n (naipe, ', de oro', ) ;
copa: writeln(naipe, ' de copa');
espada: writeln(naipe, ' de espada');
basto: writefn(naipe, ' de basto');
END;
END;

PROCEDURE reparLeCart.a (VAR oros, copas, basLos,


espadas:TConjNaipe) ;
VAR
palo: TPaIo;
naipe: TNaipe;
BEGIN
reparteUnaCarta(oros, copas, bastos, espadas, pa1o, naipe) ;

guardaCarLa(oros, copas, bastos, espadas, paIo, naipe);


:nuestraCarta (pa1o, nape) ;
:l.l;

:: :--. PrOgrama prlnClpallrl


tl
L],
_ tt
.-=."= := t];
Sor,ucroNBs 201

espadas := [];
FOR jugador := 1 T0 4 D0
D DN TIT
DEgf t!
writeln ('Cartas del jugador ' , jugador) ;
FOR reparLos := 1 T0 4 D0
reparteCarta(oros, copas, bastos, espadas) ;
END;
ra:,n I r .

NlJ. t Programa prlnclpal ]

6.9.6 Comparando dos palabras


En las variables conjuntol y conjunto2 se almacenan las letras de la primera y se-
runda palabra respectivamente. Con las operaciones de unin y diferencia de conjuntos
:e determinan respectivamente las letras comunes y dif-erentes de ambas palabras. El
rocedimiento LeerPalabra lee carcter a carcter y si es una letra mayscula o mi-
nscula la inserta en el conjunto. El procedimiento MuestraConjunto realiza un bucle
que extrae letra a letra del conjunto y las muestra por pantalla (hasta que el conjunto se
.lueda vaco).

Palabras;
?ROGRAIvI
compara dos palabras)
,ENTRADA: dos palabras terminadas en punto)
SALIDA: Ietras en comn, letras que slo
-iene la primera patabra y letras que s1o tiene la segunda)
:ONST
LETRAS= l'a'..'z'f + ['A'..'Z');
IYPE
TConjunLoletras= set 0F 'a' ..'z' ;
..iAR

conjuntol, conjunto2 :TConjuntoletras;

?ROCEDURE LeerPalabra (VAR cjto: TConjuntoletras) ;


-.rAR

^]^--.,
L qr . u110!

IEGIN {LeerPaIabra}
ni ta .= ['l
writeln('escriba una palabra acabada en punto y puise INTRO')
read (car);
WHILE (car <> ' .') D0
BEG]N
IF car IN LETRAS THEN
202 Trpos srMpLEs y coNJUNTos

cjto := cjto ' [car];


read (car) ;
END;
v^.^t .

END; {leerealabra}

PROCEDURE Muest raConj unto ( c j to : TCon j untoletras )

VAR
I arr: . nL-.

BEGIN {MuestraConj unto }


I ^L---
.q/

IF (cjto = il) THEN


writeln ('Conjunto vacio' )

ELSE
WHILE (cjLo <> [1 D0
BEGIN
IF (Ietra IN cjto) THEN
BEG]N
write (letra) ;
cjto := cjto - [etra]
END;
Iecra := Succ(letra);
END;
END ; { MuescraConj unto }

BEGIN {Programa principal}


IeerPalabra (conjuntol ) ;
leerPalabra (conjunto2 ) ;
writeln ('Letras en comun: ' ) ;
muestraconjunto (conjuntol * conjunto2 ) ;
'.,ritaln.
writeln('Letras que tiene la primera y no Ia segunda/) ;
muestraconjunto (conunto1 - conjunto2);
'.,- i ol - .

Irriteln('Letras que tiene 1a segunda y no 1a primera') ;


:,-iestraconj unto (conj unto2 - conjuntol);
-.-:-'t .
:_._ _Drograma prlnCrpaI J
Sor-ucroNBs 203

6.9.7 Estadsticas de una frase


En el bloque CONST se declaran cuatro conjuntos: el de todas las letras (consonantes y
iocales), el de slo vocales, el de dgitos y el de caracteres especiales. Por simplicidad
.e decide representar eI conjunto de los dgitos mediante los caracteres del "0" al "9". En
,-uatro variables de tipo entero (numletras, numVocales, numDigitos y numEspe)
.e lleva la contabilidad de Ia aparicin de los dif'erentes tipos de caracteres.

?ROGRAM Frase;
,Hacer estadsticas sobre una frase Lerminada en puntoi
'ENTMDA: la frase a estudiar acabada con un
'.')
.SALIDA, Numero de letras, vocales, dgitos
y signos de puntuacin)
]ONST
TEI-DAq- ltt tzt tLt tVt1.
L s .r 4 )t

VOCALES= l, a, , ,
,
e , , i, ,
, o, ,
,t), , , A, , ,8, , , I, , , O, , ,U, ) ;
DIGITOS= l' A' . .'9') ;
ESPECIALES=I' :',' ;',',',' .',t"t tt?',",' !'7;
-.rAR

numletras, numVocales, numDigitos, numEspe: integer;


r. lnr.

aI,TJCTION Esletra (c:char):boolean;


3EGIN
Es],etra: = c IN T E'I-PAQ.

:ND;

a-JTJCTI0N EsVocal ( c : char) : boolean;


tl^T1T
- lurt\
EsVocal: =c IN VOCALES;
:\]n.

:--INCTION EsDigito (c:char) :boolean;


:IT\T
-!gII\

EsDigito := c IN DIGITOS;
:\Tn.

:-J'IJCTION EsPuntuacion (c :char) :boolean;


: tr TIT
_UII\
EsPuntuacion := c IN ESPECIALES;
:ND;

:-R.OCEDURE Inicializar (VAR nleLras, nVocales, nDigitos,


204 Trpos SIMPLES Y coNJUNTos

nEspe: integer) ;
ENI
BEGIN Mos
rTolr:o .- A. ]ND.
nvccales : = 0;
-ILr!rLVD .- V/
6.9.8
i:na ..- A.
- u/
tr\Tl .
-f,s val
,ncir
PROCEDURE Increment.ar (VAR a:integer) ; :.rn&dO
:_?..
BEGIN
a := a + 1;
END; . ?,OGI
Leal
PROCEDURE MostrarEstadistica(a, b, ct d:inLeger) ;
:NTT
BEGIN :ALl
writeln ('ESTADISTICAS' ) ;
-:PE
writeln('Numero de letras = ' ,a\; T'
-'f
writeln('Numero de vocales = ',b);
-1
writeln('Numero de digitos = ' ,c);
writeln('Numero de signos de puntuacion = ',d);
EINJJ ; tmoStrarestadrstrCa.|
-:=-i
BEGIN {Programa principal} --a

writeln ('Introduzca una frase terminada en punto ' ' .' ' ') ;
:a

read (car) ; --a

Inicializar (numletras, numVocales, numDigit.os, numEspe) ;


l^lHILEcar <> ' .' D0
BEGIN
IF EsLetra (car) THEN
BEGIN
Incrementar (numletras ) ;
IF EsVocaI (car) THEN
Inc rementar ( numVocales )

END
ELSE
IF EsDigico(car) THEN
Incrementar (numDigitos)
ELSE
IF EsPuntuacion(car) THEN
Incrementar (numEspe) ;
:rn IF Esletra)
--^^l ^^--\
:=fU edll;
Sor-ucroNns 205

rND; {wHrlu}
It{ost rarEstadi s t ca numletras,
( numVocale s, numDigi tos, numEspe ) ;
:-.) . t Programa prlnC lpaI
f ^ r l
.f

6.9.8 El juego de piedra, papel o tijera


-s variables globales jt y j2 representan la opcin escogida de cadajugador. La
,Lncin Ganador devuelve un nmero de 0 a 1 que indica cual de los dos jugadores ha
_-nado. El programa principal genera todas las posibles jugadas anidando dos bucles
: ll.

.?OGRAM PiedraPapel;
Realizar todas tas posibles jugadas)
INTRADA: )
-:ALIDA:para cada jugada decir el ganador)
ITPE
TJugada = (piedra, papel, tijera);
--tD

)l , j2: T.Tugada;

Ganador (jugt, jug2 :TJugada) :inLeger;


I-,TICTION
raIlda:
Ganador = 1 si gana eI jugadorl
Ganador = 2 st gana e1 jugador2
Ganador = 0 si hay empate)
:EGIN {Canador}
{comprobar si hay empate}
IF jugl = jug2 THEN
Ganador : = 0

ELSE

{comprobar si gana jugadorl}


IF (jugr = papel) AND (jug2 = piedra) 0R
(jug1 = piedra) AND (jug2 = tijera) 0R
(jugr = tijera) AND (jug2 = papel) THEN
Ganador : = 1
ELSE{gana jugador2 }
Ganador : = 2;
3ND; {Canador}

?ROCEDURE Escribir.Tugada (j :T.lugada) ;


3EGIN {EscribirJugada}
I
r._Abtl
^n ^ I tr_f
^-
206 TIPoS SIMPLES Y CoNJUNToS

piedra: write r' piedra ,) ;


papel: wriLe \' papel ' ) ;
-r-^--
-_-=La : wIILe r r]ia-.
LtJtrlq /\.t;
END;
El.- ; {Escribir.fugada }

BGIN {Programa principal} i*


FOR j1 = piedra T0 tijera DO
FOR 2 := predra T0 Lijera DO BEGIN
write(' si jl = ');
EscribirJugada (j 1) ;
L
writet' y j2 =');
EscribirJugada(j2);
write (' el ganador es el ,, ganador(11,12));
rarl l .

END; {rOn z}
END. {Programa principal}

.,1

.i
: tlli
- .;
--J\

J.
,efO
:asilli
lifere
a

a
I

cl

I
Captulo 7

Los tipos de dato a rcay y s tring


,rlgunas ocasiones puede ser til agrupar un conjunto de datos con caractersticas
para tratarlos de la misma forma. Para procesar cmodamente estas coleccio-
., mavora de lenguajes de programacin de alto nivel disponen clel tipo de dato
'ay. Este tipo de datos pertenece a la familia de los tipos estructurados, denomi-
as por presentar estructura interna. En este captulo se introducen los tipos de
.::ay y string, su descripcin y las condiciones de su aplicacin. Adems se
autilizar algunos procedimientos y funciones string predef,nidas en pascal de
-
-,trtua1.

Descripcin del tipo de dato array


-r:.i\. es una coleccin estructurada de datos del mismo tipo que se guardan bajo
-::rr nombre o identificador. En la figura 7.1 se muestran ejemplos de datos que
describirse como un array. En matemticas, un vector v en el espacio, es una
de tres nmeros reales, donde cada uno representa una componente. un ta-
'': aiedrez se puede ver como un conjunto de 8x8 valores de tipo char, donde las
i acas tienen un espacio en blanco ' ' y el valor de las fichas se representan por
letras. Las caractersticas ms reseables de los arrays son:
. -i:' Puede acceder a cada componente individual a travs de ndices que especifican
'- posicin dentro de la coleccin.
r , &trilyS son estructuras de acceso directo, ya que permiten aimacenar recupe-
)
--: Jatos sin necesidad de recorrer todos los elementos anteriores de la coleccin.
r - : 3ffaYS son estructuras de datos homogneas, es decir, todos sus elementos son
-: nsmo tipo.
r ' .iIraYS son estructuras de datos estticas. Esto signica que el tamao de un
---r' forma fija en la seccin de declaraciones y/o deflniciones, y
se establece de
:uede modif,carse en tiempo de ejecucin.

207
208 LOS TIPOSDEDATO ARRAY Y STRING

t c a d r a C t
p p p p p p p p

P P P P P P P P

T C A D R A C T

(b)
(o)
(o)

Figura7.1:Ejemplosdeobjetosquesepuedenmodelarconarays:(a)tablerode:.
drez, (b) vector en el esPacio

arrays
1.L,1 Definicin de tipos y declaracin de variables

Untipoallaysedef,neentrminosdeuntipondice(qued{serdetipoordinal)r:'
utiliza la siguiente sintaxr'
array" norir" rarray se
tipo base. para definir .rn tipo
TIndiceNl OF TElemento
TArray = array lTIndicel
Losarayspuedentenerdiferentenmerodedimensioio::'Lt""indelnmer'-'
es un tipo ordinal
que exp:'
uru'""";";i" def,nicin' Cada rrndicei de acc'-'
Trndicei 0," ;;;y en esa dimelir y el modo
ro'Inu"
e1nmero . to''pol]""i"t lo" "1
aellas.TElemento"'"ftipobasedelarruyyd"fl'"eltipodeloselementosquec':- que mocl'.:"
datos y declarar variables
aelr1r tipo'it
tituyen la estructura' r"0* forma:
los datos ."pr"ttnt"d*'' en la f,gura 7' 1' de la siguiente

SVDE
T\/etr3D = arra! t1"31 OF real;
d' e' f' g' h);
I VL9UVJ-

TColumnas = (a, t, c,
OF char;
rrFal.r or = array [1 ' ' I , TColumnas]
I Iq!re!v

VAR
vectorl : TVector3D;
vector2 i arra tl-"31 OE real;
tablero: TTablero; iables de ttP
tipo arrav se declaran
L:is i arlables de *i,T]tH-H:: ffit::r.Xi;;
Ii"l:1,*f :Jll'"n'Ii'"i;;;*,."'T"I::,':::]tTili,Tl:
*:il:TT#?:Ti:T:"#J;n:;l*:t'::xi:;'JiJlXlf ;:ffrazono
'
por las
p'"tr", no es recomendable'
TJ#J*T*Hi::irffffi
enlaseccin7 '2'2'
"'
expondrrn
Oprna.croNEs CoN ARRAYS 209

tablero[1,1] tablero[ 1,2] tablero[1,3] tablero[1,N]

tablero[2,1] tablero[2,2] tablero[2,3] tablero[2,N]

tablero[3,1] tablero[3,2] tablero[3,3] tablero[3,N]


vectorl1] vectorl2] vector[3]

tablero[Y,1] tablerolM,2l tablero[4,3] tableroU'],N1

(o) tb)

, i_gura 7.2: Acceso a los elementos de un array: (a) bidimensional de dirnensiones MxN,
r r unidimensional

'.1.2 Acceso a las componentes individuales de un array

-. acceso a los elementos individuales de un array se lleva a cabo a travs del nombre
-.' la coleccin seguido de uno o varios ndices entre corchetes que indican la posicin
,:1 dato dentro del array (ver figura 1 .2). El nmero de ndices necesarios para el acceso
, un elemento es funcin de las dimensiones del array. Por ejemplo, un programa que
,,lcule el mdulo de un vector facilitado por teclado podra escribirse de este modo:

.: IGRAM CalculaModulo
--:_i

vector: TVector3D;
modulo: real;
]]^T\T
, _,-aL\
writeln('Escriba 1as componentes x, y, z del vector');
readln(vector[1], vector[2], vector[3] ) ;
modulo : = sert (sqr (vector [1] ) + sqr (vector [2] )
r^r \ \
- T(.ra
qr \vtruLOI LS) ) I i
writeln('Ef modulo es: ',modulo);
:l:l .

1.2 0peraciones con arrays


:n esta seccin se describen las diferentes operaciones que se pueden realizar sobre
:tos de tipo array.

'.2.1 Procesamiento de las componentes de un array


?ara implementar operaciones sobre todas las componentes de un affay, se puede hacer
*so del esquema de recorrido que ya se conoce. Supngase, por ejempio, que se necesita
:estionar ias visitas recibidas por un museo a 1o largo de una semana. Para almacenar
:stos datos se define e1 siguiente tipo de dato:
210 Los rrpos DE DATD ARRAy y srRrr'rc

TYPE
TDiasSemana (Iun, mar, mie, jue, vie, sab, dom)
=
TArrayDeDias = array ITDrasSemana] OF integer;
VAR
visitasMuseo : TArrayDeDias ;
ora: llJlassemana;

Para recorrer toda 1a coleccin pasando por cada uno de los datos, se puede utilizar ui-
estluctura de repeticin. Por ejemplo, para pedir por teclado las visitas recibidas ca- t12
da de la semana:
_os
FOR dia : = lun T0 dom DO
readln (visitasMuseo [dia] ) ; :d
rbl
El acceso a cada elemento de un amay de 1 dimensiones se realiza a travs d -
:'1
ndices. Supngase, por ejemplo, que se necesita guardar las temperaturas mxir.- -r t
diarias registradas en un conjunto de ciudades durante un mes. Para ello se define -' ,la
tipo de dato como el siguiente:

TYPE
:n
TCiudades = (Soria, Madrid, AviIa, Zamora);
l - -
- t..JLt
.. el
TTabla = array [TDias, TCiudades] OF real;
. -1
VAR
tabla, tablaBackup:
ir
TTabla;
Clu : 'l LluoadeS ;
dia: TDias;
Para leer las temperaturas de todas las ciudades cada uno de los das:

FOR dia := 1 TO 31 D0
FOR ciu : = Soria TO Zamora DO
Readln (tabla Idia, ciu] ) ;
elt
Para leer las temperaturas de todos los das para cada una de las ciudades basta
modificar el orden de anidamiento de los bucles.
\,

]la
-{signacin de arrays completos

Como ocurre con todos los tipos de dato compuestos, no se pueden rcalizar
de entrada/salida con rrays completos. sin embargo, s est permitido asignar
ctnrpletos cuando stos son de tipos idnticos. Por ejemplo, la instruccin:

:a:-a!ackup := tabla;
asigna a --ab-aBackup los datos almacenados en tabla.
OprucroNEs coN ARRAYS 2tt
Porie lleno Poe voco

tope maxamo

Figura 7.3: Array parcialmente lleno

1ar una
ts cada
7,2.2 Arrays como parmetros de subprogramas
Los arrays pueden ser pasados como parmetrs a funciones y procedimientos. Para ello,
:e declaran como parmetro empleando un tipo delinido (no annimo) en la cabecera del
.ubprograma. En el paso de anays por valor y por referencia los parmetros formales y
sdel/ :eales deben ser de tipos idnticos. En Pascal, las funciones no pueden devolver valores
ximas :e tipo arrayi de modo que cuando sea necesario que un subprograma devuelva un
line un rrray, ste debe ser pasado como parmetro por referencia de un procedimiento.
El paso por valor de cualquier variable conlleva la generacin de una copia del valor
:n el parmetro formal. Si pasamos un affay, se copiarn sus elementos en el parmetro
-onnal, lo que supone un gasto sustancial de memoria. respecto al paso por referencia,
:n el que no se genera copia. Por esta razn, los arrays son usualmente pasados por
:et-erencia aunque no se pretenda cambiar el valor de sus componentes. Cuando se lleva
r cabo esta prctica, es necesario prestar especial atencin al uso de los parmetros con
:1 fin de evitar efectos indeseados.

7.2,3 Arrays parcialmente llenos


En Pascal, la reserva de memoria correspondiente a un array es esttica, de modo que
ln atray tiene un nmero fijo de componentes. Sin embargo, en algunas ocasiones el
rmero de datos que contiene una coleccin puede variar durante la ejecucin del pro-
-Jrama. Para modelar estas situaciones existe la posibilidad de utilizar un affay parcial-
rtente lleno (figura 7.3). Para ello es necesario, por un lado, estimar el nmero mximo
Je elementos que el array puede contener (maximo), y por otro, llevar un registro de los
sta con ,mites de la parte ocupada. Para controlar el lmite de la parte ocupada se suele utilizar
.rna variable que marca su extremo superior. De este modo, se reserva urentoria para
:1 mximo nmero de elementos que puede albergar (maximo) y se utillza una variable
-ndicadora del nmero de componentes del array en cada momento (tope). Se podran
Jelinir los tipos para el array parcialmente lleno y para el tope del siguiente modo:
lciones
'affays
PP TMtrPO

ULTIMO
:YPE
rlaEca
2t2 Los trpos DE DATO ARRAy y srRrNc

Tlndice = PRIMERO. .ULTIMO;


TTope = pred(PRIMERO)..ULTIMO; {rope = pred(PRIMERO) indica
que eI array est vaco)
TArrayParcia1 = array lTlndice] OF TBase;

Donde las constantes pRTMERO y uLTTMO y el tipo TBase han sido previamente
Es posible construir un procedimiento sencillo para pedir por teclado un nuevo da:

PROCEDURE Anadir(VAR vector: TArrayparcial; VAR tope: Ttope);


BEGIN
IF (Tope < ULTIMO) THEN BEGTN
tope := succ(tope);
writeln (,Dato No ,, tope, , :,) ;
readln (vector Itope] )

END;
END; {anadiri

7.3 Descripcin del tipo de dato srring


El tipo de dato string est soportado nicamente por Turbo Pascal, que incorp _

ms las funciones y procedimientos necesarios para su manejo. Este tipo de dato


una secuencia de caracteres de longitud dinmica y una longitud mxima corsr: :

tre I .v 255. La longitud mxima se conoce tambin como "longitud fsica", y, e .


en la declaracin de la variable. sin embargo, las variables de tipo string
macenar cadenas de caracteres cuya longitud es susceptible de ser modificada
la ejecucin del programa. A la longitud de los datos guardados se le lrama ,.:
lgica".

7.3.1 Definicin de tipos y declaracin de variables de tipo string


Se pueden deflnir tipos de dato string de un modo sencillo (ver la definicin c.
TMatrj-cula del siguiente cdigo). Adems se contempla la posibilidad de decl.:-'
riables annimas de tipo string. Tpicamente, una variable de tipo string es
con la palabra reservada string seguida de un nmero entre corchetes que indica -
gitud mxima. si no se especifica iongitud mxima, se toma por defecto el val, .

Para defrnir un tipo string de nombre TString se utiliza la siguiente sintaxis:

CONST
MAxIMO
el pa
TYPE
S
Tstring = string tUaXflOl ; ios
OpnucroNrs coN srRrNGS 213

En el siguiente ejemplo se ilustra declaracin de dos variables que guardan


un matrcula
de 7 caracteres, como las utilizadas en Espaa) y una para guardar una frase (con
una
longitud mxima de 255 caracteres):

]3NST
LONGMATRICULA = 7;
. YPE

TMatricula = string ILONGMATRICULA] ;

matricula : TMatricula;
frase: string;

7,3.2 Acceso a las componentes individuales de un string

Se puede acceder a los componentes individuales (caracteres) ile una cadena a travs de
'u nombre seguido de un ndice entre corchetes (de un modo similar a como se procede
.'on las variables de tipo array). Por ejemplo, si se necesita extraer la inicial
de un
rombre. guardado en un st.ring:

.-ROGRAM Iniciales .

nombre: string [20] ;


:iGIN
writeln ( ,Dame un nombre: , ) ;
readln (nombre) ;
writeln(,La inicial de,, nombre, ,es: ,, nombre[1])
:l,lD.

7.4 Operaciones con strings

En esta seccin se describen las dif-erentes operaciones que se pueden realizar


sobre
datos de tipo string.

7.4.1 Strings como parmetros de subprogramas


En el paso por referencia de cadenas de caracteres, los parmetros fbrmales y
actuales
deben ser de tipos idnticos. En el paso por valor de cadenas de caracteres.
basta con
que los parmetros formales y actuales tengan ia misma
longitud.
DE DATo ARRAY Y srRrNG
214 Los rrPos

Sintaxis
Descripcton . .- -
Funcin
orrcatena dos exPresiones
strlng
concat concat (cadena1,
cadena2 )
-.-_.--- (cadenar
length L length )

strinq
pos
1

\.,
]l^.pos (cadenar,
i .in la que comienza 1a cadenal
dentrt'
:

I cadenaz) "r-, Cuando cadenal no est in-


"
"ua""ui.
en cadena2 devuelve el
valor 0' ob-
;ir,
servar que el orden et imP9ttnl9 ---
lttl-
f,etre una suu.'oena de caden'
copy (cadena, c'
copy
^-^:^\
-Ldlitdrrv/ \ ro" o"t camao curacteres a partir
pOSlClOn,
\ posicion
para cadenas de caracteres
Tabla 7 .l :Funciones predef,nidas

para el nr'
funciones y procedimientos predefinidos
7.4.2 Operaciones,
nejo de strings

EnestaseccinSepresentanlasoperaciones,procedimientosyfuncionespredefr
c1e dato string'
para el tratamiento del tipo
en Pascal

Operaciones
strins admite o"
Er tipo de rrato "1": 111T'f::'::,:i::Ttl1":"":,;fl: l,ll"if}'
puede ser una constante' una
::i;i::Jj":="'J;'e';t"", i*u. expresionI ^ +:^^ ^1r. r
cualquiera de1 tipo string o de tipo char'
o rnu
"^pr"rin
VAR
cadenal: string;
cadena2: string [3] ;
BEGlN
,HOLA';
cadenal-
cadenal cadenal [3] ;

cadena2 'Maria';

Eristelaposibilidaddequelalongituddelacadenaresultantedelaevaluaci-
e r presi n s e a mav or ;; ""; t;l;;i"? *'i111 ,1T*:iJ[ll;l
i: :: l"T:f,*nicamente los datos] i .
::1fi:::J::,"J:il;"";;'"""+ "' ejempio'
""" "u'o''" 9"u,'9""
cdigo anterior' la variable
que se ha reservado*"*o'iu' Por "" "l
'

guarda l3 cadena L'tar


0ppnacroNES coN srRrNGS 2t5

I
l
Procedimientr Sintaxis Descripcin
delete delete ( cadena, Borra tamao caracteres de cadena a par-
posicion, tamao) tir de posicion, de modo que la cadena re-
,I-] duce su longitud en el nmero de caracteres
eliminados
tosi- insert insert (cadena1, Insefta cadenal en cadena2 a parlir de
ntro
I
posicion. Como resultado de la insercin,
I

iin- |
posicion) cadena2 aumenta su longitud un nmero de
ool crracteres igual a la longitud de cadenal
str sLr (exprNum, Convierte el valor de exprNum en su repre-

I
l*- l

val
cadena)

VaI (cadena,
valorNumerico,
codigoError )
sentacin como cadena de catacteres y 1o
devuelve en cadena
Conviefte el string guardado en cadena en
su valor real o entero valorNumeri co. Ade-
ms, devuelve en codigoError un valor en-
tero que ser 0 si se puede hacer la conver-
sin, o la posicin del primer carcter que
:l ma- produjo el error en caso contrario

Tabla7.2: Procedimientos predeflnidos para cadenas de caracteres


nnidas

A1 contrario que con los arrays, est permitida la lectura y escritura de variables de
tipo string completas, utilizando los procedimientos predeflnidos read, readln, write
y writeln.
rna ge-
ariable Adems, se pueden utilizar los operadores rglacionales para comparar dos strings.
La comparacin se lleva a cabo carcter a carcter. Si una cadena es ms corta que la
otra, se compara como si la ms corta se rellenara con espacios.
Por ltimo, es posible concatenar dos expresiones cualesquiera de tipo string me-
diante e1 operador "+"" En el siguiente ejemplo se muestra por pantalla la cadena ".luan
Garcia":

rombre := 'Juan';
apellJ-do := ' Garcia' ;
actor := nombre + apellido;
n de 1a writeln (actor) ;
a ltima
para los
:adena2 Se debe observar que el espacio en blanco es aadido explcitamente en la variable
ape I 1 ido.
216 LOS TIPOS DE DATO ARRAY Y STRI,NG

Funciones predefinidas

En la tabla 7.1 se presentan las funciones predefinidas ms comnmente utilizadas. S.


pueden consultar ejemplos de uso de estas funciones en la seccin de problemas.

Procedimientos predefi nidos

Finalmente, en la tabla 7.2 mostrada a continuacin se presentan algunos procedimient'. '


predeflnidos de uso habitual. Se mostrarn ejemplos de uso en la seccin de problemL.

7.5 Cuestiones de tipo test


Las siguientes cuestiones pueden tener una o varias respuestas correctas.

7.5.1 Enunciados
l. Cul de los siguientes tipos de dato NO puede ser ndice de un aruay?

(a) Enumerado.
(b) Subrango.
(c) Conjunto.
(d) Boolean.
2. Cul de las siguientes frases es ciefta?

(a) Las funciones pueden ser de tipo array.


(b) Si un array es un parmetro de un procedimiento que no 1o va a
se recomienda pasario por valor.
(c) En Pascal, las variables de tipo array slo pueden ser pasados por refer.'
cia.
, (d) Todas las anteriores son falsas.

3. Se necesita construir un programa que gestione una cierta cantidad de dato>


puede variar durante la ejecucin y se conoce el nmero mximo de datos qu.
puede llegar a tener. La estructura ms adecuada para almacenar estos datos .

(a) Un array parcialmente lleno.


(b) Un conjunto de arrays.
(c) Un conjunto.
(d) Un array bidimensional.

-i. L na de las siguientes afirmaciones sobre los arrays-es cierta:

t a I E1 nciice de un aray puede ser de cualquier tipo simple.


CunstroNns DE TtPo rEST zt't

(b) Los arrays son tipos de datos estructurados que permiten guardar cualquier
tipo de dato simple excepto los de tipo char, que se guardan en strings.
(c) Un array es una coleccin estructurada de componentes'del mismo tipo.
(d) Los arrays parcialmente llenos son aquellos que permiten modilicar su ta-
mao.

!.,:
5. Si un real necesita 4 bytes. un carcter I byte y un entero 2 bytes, cunta memoria
necesitar una variable del siguiente tipo de dato?

Tvecror = array l'f'..'i', -2..0] 0F real;

(a) 10 bytes.
r (b) 48 bytes.
(c) 40 bytes.
(d) 24 bytes.

6. Dada la declaracin de tipo siguiente:

Tvector = array [1. .10 , 'x' .'z') 0F boo]ean;

(a) Es incorec'.a.
J4U Oectara un tipo de datos para contener 30 elementos booleanos.
(c) Declara un atray bidimensional de l0 elementos enteros y 3 elementos de
tipo char.
i-^-
Ir Jl . (d) Para acceder a sus elementos tendremos que usar dos ndices.

ren-
1 . Cllde las siguientes afirmaciones es (son) conecta(s)'/

(a) Un affay es una coleccin heterognea y estructurada.


(b) Un array es una coleccin heterognea y sin estructura.
que (c) Un array es una coleccin homognea y estructurada.
ie se (d) Un array es una coleccin homognea y sin estructura.

8. Cules de las siguientes afirmaciones referentes a un array son ciertas en Pascal?

(a) El tamao de un aray puede modificarse durante la ejecucin de un pro-


grarna haciendo una llamada a NEW con ei nombre de la vanabie.
(b) El tipo ndice de un aray puede ser de cualquier tipo simple.
(c) Se puede asignar un array a otro si los tipos son idnticos.
(d) No se puede realizar ninguna operacin de entrada./salida con alrays com-
pletos.
218 LOS TIPOS DE DATO ARRAY Y STRING

9. Seale aquellas aflrmaciones que sean correctas:

(a) Los affays son tipos de datos homogneos y no estructutud.o,l'".


(b) El tamao de un array puede modificarse durante la ejeccin'
(c) Un array es una estructura homognea en la que se pueden almacenar dat'
de distinto tipo, siempre que sean ordinales.
(t1) Los ndices de los anays son siempre ordinales simples'

7.5.2 Soluciones
1. La respuesta correcta es la (c). El tipo ndice de un amay debe ser obligatorian-.. -

de tipo ordinal.

2. La respuesta correcta es la (d). Las funciones no pueden ser de tipo


Por otro lado, si las necesidades de memoria as lo exigen, es necesario pa.-
array por referencia a pesar de que no vaya a ser modificado. Sin embargc
puede decirse que sea 1o aconsejable. Finalmente, los arrays en Pascal puede:
pasados tanto por valor como por referencia.

3. La respuesta correcta es la (a). Debido a que la cantidad de datos almacen-


puede variar hasta un lmite mximo, es necesario tener en cuenta el nmer,.
datos contenidos en el array en cada momento. Un array parcialmente lleno. e '
estructura adecuada para modelar estas situaciones.
aray slo puede ser de tipo ord--
4. La respuesta cor:recta es la (c). El ndice de un -
Los arays pueden guardar datos de tipo char. Los arays parcialmente llenc' -

modifrcan su tamao mximo en memoria. Es decir, la reserva se hace en tietl.:


de compilacin. no en tiempo de ejecucin.

5. La respuesta correcta es la (b). Es un anay de 4 filas y 3 columnas. De modo - ,

el aray ocupar en memoria 4 filas x 3 columnas x 4 bytes, es decir 48 bytes


6. Las respuestas correctas son la (b) y (d). Tiene 10 fllas y 3 columnas,luego p... -
almacenar 30 datos. Adems es bidimensional, por 1o que ser necesario espt" "

car 2 ndices para acceder a cada elemento.

7. La respuesta correcta es la (c). Un amay es una coleccin homognea, ya que '


puede almacenar datos del mismo tipo y estructurada, puesto que posee un -
junto de elementos individuales organizados segn una estructura determina-
8. Las respuestas correctas son la (c) y (d).
9. La respuesta correcta es la (d). La primera respuesta es falsa, ya que los
son tipos de datos estructurados y homogneos. La segunda tambin, ]& c.-:
re serva para un array se hace en tiempo de compilacin y no se,puede moc-
en tiempo de ejecucin. Por ltimo, en un array se pueden almacenar datos de
ordir-ra1 no ordinal, por lo que la tercera respuesta es, de nuevo, incorrecta.
Pnonr,nrras 2t9

7.6 Problemas
7.6.1 Acceso a los elementos de un array unidimensional

Implemente un programa que lea un vector de 10 enteros desde el teclado y muestre por
latos
pantalla estos elementos pero en el orden inverso al que fueron introducidos.

7.6.2 Recorrido de un array unidimensional

Disee un programa que pida al usuario un vectorX compuesto porN (N: 10) nmeros
reales {-r1 ,. .. ,xu}. Calcule a continuacin el valor medio (r) y la desviacin estndar
nente (o) de los elementos del vector.

rado. - -r1 *... *r


af un
/
o, no
)n ser

rados
ro de
7.6.3 Encontrar elementos en una coleccin unidimensional

es la Construya un subprograma que pida al usuario un vector de N elementos no ordenados


de tipo real, y que devuelva el valor mximo.

dinal.
os no 7.6.4 Desplazar elementos en un vector
empo
Construya un subprograma que despiace todas las componentes de un vector de N ente-
ros un lugar a la derecha, teniendo en cuenta que la ltima componente se debe desplazar
.o que al primer lugar. Generalice el subprograma anterior para desplazar las componentes k
S. lugares. Utilice los subprogramas construidos para escribir un programa que pida at
puede usuario un vector y un nmero de desplazamientos y que imprima el vector resultante.
recifi- Construya los procedimientos necesarios para permitir el desplazamiento de k luga-
res a la izquierda.

e slo
1 COn- 7.6.5 Separar elementos de un vector siguiendo un criterio
rda.
Dada una lista de elementos enteros, construya un subprograma que devuelva el vector
de los elementos pares y el de los elementos impares contenidos en la lista.

arrays
que la 7.6.6 Acceso y recorrido de un array bidimensional
lificar
Construya procedimientos que permitan:
le tipo
1. Leer una matriz por filas.
220 LOS TTPOS DE DATo ARRAY Y STRING

2. Leer una matriz por columnas.


3. Escribir una matriz por filas.
,1. Escribir una matriz por columnas.

Suponga que la mafriz es de enteros de dimensiones 6x5. Defina explcitamente el ti:,


de datos utilizado para modelar una matriz de este tipo

7.6.7 Un cuadrado mgico -;i

Construya un programa que determine si una matriz es un cuadrado mgico. Se c, -.(


sidera cuadrado mgico aquel en el cual las f,las, columnas y diagonales princip:r,
secundaria suman lo mismo. ]i
,fi
7.6.8 Encontrar elementos en una coleccin bidimensional zq
)el
Escriba un programa que lea rl2 nmeros enteros en una matriz7x6 y que permita realiz*- :n
las siguientes operaciones:

L lmprimir Ia malriz. 7.6,

2. Encontrar el elemento mayor de la matriz. Dad

3. Indicar dnde se encuentra el elemento mayor de la matriz. :YP,


4. Si el elemento mayor est repetido, indicar cuntas veces y la posicin de cac-
-n \T(
elemento repetido.

7.6.9 Una calculadora bsica de matrices


Programe una calculadora de matrices que permita realizar las siguientes operacione ,
sobre matrices 3x3:
Reali
palab
1. Sobre dos matrices: suma, diferencia y producto de dos matrices.
2. Sobre una matriz: traza y traspuesta.
7.6.1
En cada caso deber pedir a1 usuario las matrices necesarias y mostrar por pantalla lo: Defin
resultados. y con

1.
7.6.10 Dibujar un histograma
2.
E:-'rba un programa que pida al usuario una lista de 30 temperaturas. A continuacin.
.!.r.1 dltidir ei intervalo entre la mayor y la menor temperatura en 10 subintervalos r
.Llnstruir un histograma con el nmero de temperaturas que se encuentran en cada uno
J.
de e 11os. Finalmente. se pide imprimir el histograma.
Pnonr,nnrls 22r

7.6.11 Encontrar y sustituir vocales en una frase

Cree un programa que sustituya todas las vocales que encuentre en un texto por el carc-
rer
tt*".

7.6.12 Contando en frases


Cree otro programa que dado una lnea de texto cuente el nmero de veces que se repite
.-ada vocal y el nmero de palabras que la contiene.

7.6.13 Palndromos
Disee una funcin que dada una lnea de texto nos diga si es palndroma. lJna palabra
o liase palndroma es aqulla que se lee igual de izquierda a derecha que de derecha a
rzquierda. Son ejemplos de palndromos "anilina" o "dbale arroz alazorra el abad".
Debe contemplarse adems la necesidad de eliminar los blancos de la frase para que el
nlisis de la misma sea el correcto.

7.6.14 Cdigo Morse


Dado el siguiente array de equivalencia entre letras y smbolos:

IYPE
tSimbolos = string[4];
]ONST
MORSEt arrayl',a',..',z',f = (',.-" ',-..."
OF Tsimbolos
, , ,
'-.-.' , '-..' , ., , ..-., , --., , ...,, , , ,,, , , .--- , ,
,

'-.-' , ' .-..' , '--' , '-.' , , ---, , , .-- ., , , --.-, , , .-., ,


,...-,, ,,-,,, ,-.,-r, ,-.--r, ,--.,r);
'..." '-" '..-,,

Realice un programa traductor a cdigo Morse de tal manera que le introduzcamos una
palabra (en lenguaje natural) y la codilique en cdigo Morse.

7.6.15 Simulando strings con arrays


Deflna un tipo de datos que permita simular strings a travs de arrays. A continuacin,
r con ayuda de ste tipo de dato, se pide construir:
l. Un subprograma que pida, lea desde teclado y devuelva una cadena de caracteres.
2. Un subprograma que muestre por pantalla una cadena de caracteres que se le pasa
como parmetro. Si la cadena es de longitud cero, se debe mostrar un mensaje
advirtiendo est a circunstancia.

3. Un subprograma que concatene dos cadenas de caracteres que se pasan como pa-
rmetro y que devuelva el resultado en otra cadena.
222 LOS TTPOS DE DATO ARRAY Y STRING

(
jr
n
d*!- jggadsr 3 (r
qu* quiarr:e rtrsu*ir t* f cla {l-1}:
"n'fi ul
or

C(

7.

Se

-'o
:iz
.ol
Figura 7 .4: El jtego de "las cuatro ertraya"
1.

-'Ui
4. Un subprograma que extraiga una subcadena de una cadena dada, de una longit -
-s
determinada a partir de la posicin de un carcter inicial.
,. 'c
I.,lo se permite el uso de variables de tipo string en ninguno de los apartados anterior."

7.6.16 Frmula qumica


Realice un programa que pida al usuario una frmula qumica en una cadena de car- .

res. Esta frmula podr tener los siguientes caracteres:

'C', 'H', 'O', 'N' como los elementos bsicos de la qumica del carbono.
. '2','3','4','5' y '6' como ndices posibles de estos elementos.
Se pide analizar esta frmula para:

1. Decidir si contiene algn carcter no vlido, en cuyo caso se deber volver -


dir una nueva frmula al usuario (ejemplos de entradas vlidas seran: CH-': -
H3CCH3, C2H6). Notar que no se pide comprobar que 1a frmula es vLc- -
micamente, sino que contiene los caracteres permitidos.
I En eI caso de que todos los caracteres sean vlidos mostrar por pantalla el n,-
de tomos de cada tipo que contiene la frmula.
-
3. Por rltimo, mostrff por pantalla el peso rnolecular (Pesos atmicos de los e-.
to-s: H=1; C=I2; N=14;0=16).
IE
Sor,ucroups 223

7.6.17 El juego del ahorcado


construya un programa que simule el popular 'Juego del ahorcado,,. En este juego, un
jugador (A) debe adivinar la palabra pensada por el otro (B). para ello, el jugador (B)
va
mostrando en cada turno las letras acertadas y su localizacin en la palabra. El jugador
(A) tiene una cantidad mixima de fallos permitidos. Un fallo consiste pr"grrrt* po,
un carcter que no se encuentra en la palabra pensada por eljugador (B)."n
Eljugador (A)
gana la partida cuando acierfa la palabra. El jugador (B) gana cuando et jugador (A)
consume todos los fallos permitidos.

7.6.18 Las cuatro en raya


Se pide construir una simulacin de "las cuatro en raya". Este juego tiene como objetivo
colocar cuaffo f,chas en lnea vertical, horizontal o diagonal en un tablero colocado ho-
rizontalmente. Las flchas se van depositando en la flla inferior o en una casilla situada
sobre otra ya ocupada. Se pede ver un ejemplo enlafigwa7.4.

7.6.19 Validacin de la lectura de datos numricos


Cuando se espera leer un numero en una variable numrica y, en su lugar, se introduce
alg]n carcter no numrico, se produce un error de ejecucin. El uso del procedimiento
prdeflnido de conversin de cadenas a nmeros permite la comprobacin de errores de
este tipo, evitando que se intemrmpa la ejecucin del programa. Escribe un subprograma
que controle que el contenido ledo por teclado es numrico; por ejemplo, una edad.

7.7 Soluciones
7.7.1 Acceso a los elementos de un'array unidimensional
PROGRAM Arrays0l;
CONST
N=10;
TYPE
Tvector = array t1..Nl OF integer;
VAR
i: integer;
vect,or: TVector;

3EGIN {Programa principal}


FOR i := 1 TO N DO BEGIN
writeln(,deme eI elemento ,, i, , del vector,) ;
readln (vector Ii] )

END;
224 LOS TIPOS DE DATO ARRAY Y STRTNG

,.,-i r^t -.
writeln ('El vector introducido en orden inverso es: ') ;
FOR i := N DOWNTO 1 D0
write (vector [i] , ' ') ;
writeln
ENIJ . t Programa prlnclpal ]

7.7.2 Recorrido de un array unidimensional

PROGRAM Arrays02;
CONST
N = 10;
TYPE
TVector = array t1..Nl OF real;
VAR
vector: TVector;
I
PROCEDURE LeerVector(VAR v: TVector) ; )l
VAR
'i 'i nr anav
l11t!YU!,
.

BEGIN
FOR i: =1 T0 N D0 BEGIN t:
writeln('deme el elemento ', i, ' del vecLor');
readln (v lil )
E\TN .

ENIJ; t LeerVector ]

FUNCTION Media(v: TVector): real;


VAR
.l i nranar.
frlLUYUr,

SUma: real;
BEGIN
SUma : = 0;
FOR i := 1 TO N DO
Suma := SUfll + v[i] ;
Media : = suma/N
:l.l ; it''reaia i

:-l,ll-:N Desv(v: TVector) : reI; ; {r


-.--lj.

|
_-- -
_=:cr
- nnnu
i
. i
l.:f :l-:.: feal;
SolucroNRs 225

:]GIN
f,^rrm
quuLLr , -
.- n.
v,

med : = ttledia (v) ;


FOR i := 1 T0 N DO
acum := acum + sqr(v[i] - med) ;
Desv := sqrt(acum)/(} - fl
:\1J; tDeSvJ

:EGIN {Programa principal}


LeerVector (vector) ;
writeln ('la media es: , , Media (vector) ) ;
writeln ('Ia desviacion estandar es: , , Desv (vector) ) ;
:ND. iPrograma principal)

7.7.3 Encontrar elementos en una coleccin unidimensional

El procedimiento de lectura leervector que se ha utilizado en este problema es el


mismo que se utiliz en el problema anterior y su cdigo se ha omitido por brevedad.

?R.OGRAM Arrays03;
:CNST
N = 10;
IYPE
Tvector = array [1. .N] oF real;
.,'AR

vector: TVector.
IUNCTION Maxlmo(v: TVector) : real;
]/AR
i. irran--.
rrugYUr /

maximoParc: real;
3EGIN
maximoParc := v[1];
FOR i := 2 TO N DO
IF v[i] > maximoparc THEN
maximoparc := v[i] ;
Maximo : = maximoParc
END; {Uaximo}

tsEGIN {Programa principal}


LeerVector (vector) ;
writeln ('El maximo es: , , Maximo (vector) )
226 LOS TTPOS DE DATO ARRAY Y STRING

-t
END. tPrograma prlnclpal-|

7.7.4 Desplazar elementos en un vector


Para desplazar Por brevedad no se lista el procedimiento leerVector. En este prograr -
se han implementado dos procedimientos responsables de desplazar k lugares. El pr
cedimiento DespIazarlD se encarga de desplazar los elementos del vector una posicr -

hacia la derecha. El procedimiento Despl azarKD llama k veces a DesplazarlD.

PROGRAM ArraysO4;
CONST
N = 10; l
TYPE -:,'
TVector = array [1..N] OF integer;
VAR
vector: TVector;
nDespl: integer;

PROCEDURE DesplazarlD (VAR v: TVector);


VAR
aux, i: integer;
BEGIN
aux := v[N] ;
FOR i := N DOWNTO 2 D0
vIi] := vIi-1];
v[1] := aux
END; {nespIazarlD}

PROCEDURE DesplazarKD (VAR v: TVector; k: integer)


VAR
.i 'i -r -^a-
rrruuYU!, .

BEGIN
FOR i := 1 TO k DO
DesplazarlD (v) ;
IND; {DesptazarKD}

PROCEDURE ImprimirVector(v: TVector) ;


VAR
i: integer;
BEGlN
FORi:=1T0ND0
write (v [i] , ' ') ;
Sor,ucro,Bs

writ.eln
END; {ImprimirVector}

BEGIN {programa prncipat}


LeerVector (vector) ;
wrtreln ( ,Deme ef numero
,,.^l!^1-/,^
de desplazamient.os : ,
);
readln (nDespl) ;
DesplazarKD (vector, nDespl) ;
ImprimirVecror vector) (

END. {programa princ:-pal


}

Para desplazar los elementos del vector


k lugares a la izquierda, vamos a deflnir
nuevos procedimientos: textttDesplazarl dos
I y textttDesp lururKI.
PROCEDURE DesplazarlI (VAR v: TVector) ;
VAR
aux/ i: inLeger;
BEGIN
aux := v[1] ;
E'nDi.1m^
-'v := I 1u N-1 D0
-
vIi] := vli+11 ;
v[N] := aux
END; {DesplazarlI}

PROCEDURE DesplazarKl(VAR v: TVector; k: int.eger);


VAR
i . inl-oao-.
+uuYUr /

BEGIN
FOR i := 1 TO k DO
Desplazarll (v) ;
END; {DesplazarKI}

7
'7 '5 separar erementos de un vector siguiendo
un criterio
En este problema se debe asignar valores
a los vectores de nmeros pares e
nmero de elementos que contendrn impares. El
estos vectores en tiempo de ejecucin
los valores que introduzca el usuario. por depencle de
lo tanto, no ," pr"d" ;;;;;;#;;;"
compilacin cul va a ser er nmero
de elemento, .n .u, uJ.r". ,r,
que, como mximo, stos van embargo. s se sabe
a contener er mismo nmero de erementos
el usuario (N). como se vio en la parte que introduzca
de teora der capturo, este tipo de problemas
puede modelar con ayuda de arrays se
parcialmente llenos. por otro lado,
el procedimiento de escritura rmprimrrvector se ha adaptado
para construir rmprimirvectorTope,
228 LOS TIPOS DE DATO ARRAY Y STRING

que permite imprimir por pantalla arrays parcialmente llenos y vuelve a utilizarse el
procedimiento de lectura Leervector.

PROGRAM Arrays05;
CONST
ENI
N = 10;
TYPE
BEG
Tvector = array [1..N] 0F integer;
VAR
vector, IistaPar, Iistalmpar: TVector;
nDespl, LopePar, toPeImPar: integer;

PROCEDURE Leervector(VAR v: TVector) ;


VAR
.l .i raaar.
flluuYU! /

BEGIN
FOR i := 1 TO N D0 BEGIN
writeln('deme el elemento ', i, ' def vector');
readln (v til )

END; ,l
ENL; j LeervectorJ
,]
:

;::::lrJF.E ImprimirVectorTope(v: TVector; tope: integer) ;


r,:lF.
r l---:r.

BEGiN
FOR i : = l- iO tope DO
write(v[r] ,'')
writeln
END; {ImprimrrVeccorTope}

PROCEDURE ConstruirListas(v: TVector; VAR par, impar: TVector;


VAR topeP, copel: integer) ;
i,TAR
'l raar.
f; . rrlLLYUr /

::lIN
:3R i:= 1 TO N D0
-F odd(vtil ) THEN
:EGIN
rnncT
--fur
.=
.- lnneT
uvyul + ',]
!, .

-:roarItopeIJ := vIi]
:::l
Sor,ucroNns 229

ELSE
BEG]N
1-^)
LVIJU! .-
.- 1-^l
uvyEr T 'la/
a

parIcopeP] := vIi]
END
l^ )
-..) ; tUOnStrulrLIStaSJ

::GIN {Programa principal}


Leervector (vector) ;
topePar : = 0;
topelmpar := 0;
ConstruirListas (vector, IistaPar, listalmpar,
topePar, topelmpar);
writeln ('Lista de los elementos pares: , ) ;
ImprimirVectorTope (IistaPar, topePar) ;
writeln ('Lista de los elementos impares: ,
) ;
ImprimirVectorTope ( listalmpar, topelmpar)
t_
tPrograma prlnclpali

'.7.6 Acceso y recorrido de un array bidimensional

, _r,sT
\TFTI, = .

\T'AT
_r!v!
_ J,T.
-

.'- li
lMatriz = array [1..NFIL, 1..NCOL] OF integer;
.::CEDURE LeerMat.rizFilas (VAR m: TMatriz) ;

! . i nlaaa-.

: - ^ rnT
_ i:l\

iOR f := 1 TO NFIL D0
FOR C := 1 TO NCOL DO BEGIN
writeln('Deme eI elemento de la fila ,
, f,
'ycolumnd',c);
readln (m If , c] )

END
:-.- {LeerMatrizFi}as}
.. -:EDURE LeerMatrizColumnas (VAR m: TMatriz) ;
--:.
i . inFaar.
rUUYU!,

[
230 I,OS TIPOS DE DATO ARRAY Y STRING

I
BEGIN
t
FOR C := 1 TO NCOL DO
IYPI
FOR f := 1 TO NFIL D0 BEGIN
f' I
writeln('Deme el elemento de Ia fila
y columna ' , c) ; " AR
I
readln (m If, c] )

END
S
END; {LeerMatrizColumnas }

.ROC
PROCEDURE ImprimirMatrizFilas (m: TMatriz) ; ...,D
VAR
f
f, c: integer; :lT
- Jgf
BEGIN
F
FOR f := 1 TO NFIL D0 BEGIN
FOR C := 1 TO NCOL DO BEGIN
,)
wrice 1m [f , c] , '
END;
writeln
END l\Tn .

END; {ImprimirMaLrizFilas}
-JNC:
:
PROCEDURE ImprimirMatrizColumnas (m: TMatriz) ; -- D
VAR
f, c: integer;
i,
:l^Tn
_ JuaI'
BEGIN
SL
FOR C := 1 TO NCOL DO BEGIN
FC
FOR f := 1 T0 NFIL D0 BEGIN
write(m[f,c] ,'')
Tr
END;
r\Tn .

wriLeln
END
. JI\L 1
END; { ImprimirltatrizColumnas} --, D

i,
7.7.7 Un cuadrado mgico :EGIN

Para resolver este problema, se calcula en primer lugar el valor de


la suma de la diagonal SU

principal (trazadelamatriz) y se compala con el valor de la suma de las filas, columnas


FO

secundaria delamatiz, mientras ocufra que la suma inicial coincide


con 1a-\
1,- Alagonat
qr. ," van calculando. El cdigo necesario para resolver el problema es el siguiente:

PROGRAM ArraYsOT;
CONST
Sor,ucroNrs 23r

]\]F'TT. = ? .

ITAT
t!Lv! _ J?.
- ,

:YPE
TMatriz = array [1..NFIL, 1..NCOL] 0F integer;
-,AR

matriz : TMatriz;
magico: boolean;
sumaref, i : integer;

?ROCEDURE LeerMatrizFilas (VAR m: TMatriz) ;


JAR
+
L ^. i nranar.
rrlusYu!,
t
3EGIN
FOR f := 1 TO NFIL D0
FOR c := 1 T0 NCOL D0 BEGIN
writeln('Deme eI elemento de Ia fila ', f,
' y columna ', c);
readln (m If, c] )

END
iND; {LeerMatrizritas}

II;T'ICTI0N Traza(m: TMatriz) : integer;


-.IAR

i, suma: integer;
3EGIN
SUma : = 0;
FOR i: = 1 T0 NFIL DO
SUma := SUma + m[i,i] ;
rv---
LLALA . - -UtttA

:NlJ; t'1 raza J

IIJITCTION TrazaSec (m: TMatriz) : integer;


-'^D

i, suma: integer;
3EG]N
qrrm: .- 0.
FOR i: = 1 TO NFIL D0
suma := suma + m[i, NCOL + 1 - i];
TrazaSec : = suma
IND; {trazaSec}

IL'IJCTION SumaFil(m: TMatriz; f: integer): integer;


232 Los rrpos DE DATo ARRAy y srRrNG

VAR
i, suma: integer;
BEGIN
.- n.
FOR i: = 1 T0 NCOL D0
Suma := SUIIIa + m[f ,i] ;
SumaFiI : = suma
END; {SumaFiI}

FIINCTION SumaCol (m: TMatri z; c: integer): integer;


VAR
i, suma: integer;
BEGIN
SUma : = 0;
FOR i: = 1 TO NFIL DO
SUma := SUma + mIi,c] ;
SumaCol : = Suma
END; {SumaCol}

BEGIN {Programa principal}


LeerMatrizFilas (matriz ) ;
maglco := l'RUbj ;
{Calculamos 1a traza}
sumaref := Traza(matriz) ;
{Catculamos Ia suma de las filas}

WHILE (magico) AND (i <= :) DO BEGIN


magico := (sumaref = SumaFiI (matriz, i) ) ;
i
.-
.- c,,l.i\ \r/
rquu
END;

iCalculamos la suma de las columnas)

WHILE (magico) AND (i <= 3) DO BEGIN


magico := (sumaref = SumaCol (matriz, i) ) ;
'i .= errli\
-}iD;
{Por ultimo, si aun es magico,
calcufamos la traza de la diagonal secundaria)
-: :agico THEN
:agico := sumaref = TrazaSec(matriz);
: --:-a.nente imprimimos e1 resultado)
f 11!r\
Sor,ucroNrs 233

wriLeln ('Si es cuadrado magico')


ELSE
writeln('No es cuadrado magico')
END. {lrograma principal}

7.7.8 Encontrar elementos en una coleccin bidimensional

Este problema es conceptualmente muy parecido a encontrar un elemento concreto en


un affay unidimensional La nica cuestin novedosa a tener en cuenta es que, en esta
ocasin, necesitamos dos ndices para recoffer la coleccin.

PROGRAM Arrays0S;
:ONST
\TtrTT, = 7.
NCOL = 6;
fYPE
TMatriz = array [1. .NFIL, 1. .NCOL] OF integer;
TVector = array [1. .NFIL*NCOL] 0F inreger;
:/AR

matriz: TMatriz;
maximo, nmax, i: integer;
maximofil, maximocol: TVector;

PROCEDURE LeerMatriz (VAR m: TMatriz) ;


-/AR
.iLt i.). .i-r-^--.
3EGIN
FOR i:=1 TO NFIL D0
trOR i : =1 -O NCOL DO BEGIN
writeln('deme el elemento de Ia fila', i,
' y columna', j, ' :'\;
readln (m Ii, j ] )

END;
IND; {leerruatriz}

?ROCEDURE EncontrarMaximo (m: TMatriz; VAR maximo,


nmax: integer; vAR fil, col: TVector);
r/AR
.l ;. irf aav.
!t I. flluuyu!,

tsEGlN
maximo := m[1,1];
1-
lIttta^ .- f ,
LOS TIPOS DE DATO ARRAY Y STRING

fil[nmax] := 1;
col[nmax] := 1;
FOR i := 1 TO NFIL D0
FoR i := 1 TO NCOL D0
IF (mIi, j] > maximo) THEN
BEGIN
nmax : = 1;
maximo := m[i,j];
fiIlnmax] := i;
collnmax] := j
END
ELSE IF (m[i,j]=maximo) AND NOT
( (i=1) AND (j=1) ) rHEN
BEGIN
nmax := nmax + 1;
maximo := m[i,j];
fiIlnmax] := i;
collnmax] := i
END
END; {EncontrarMaximo}

BEGIN {Programa PrinciPal}


leerMatriz (matriz) ;
EncontrarMaximo(matriz, maximo/ nmax, maximofil, maximocol) ;
writeln ('EI maximo es: ' , maximo) ;
writeln('Y las posiciones donde se encuentr son:'); -:-
FORi:=1 TO nmax D0
writeln('Fila: ', maximofil Ii], ' Columna: ', maximocol --' :

END. iPrograma princiPali -

7.7.9 Una calculadora bsica de matrices E

PROGRAM ArraysO9;
e
CONST
NFIL = 3;
\TAT
L!UV! - 2.
J, :- Jl
-

: il]
TMatriz = array [1..NF]t, 1..NCOL] OF real; l

VAR
matrizl, maLriz2, matriz3 : TMatriz; --. 1
'l raaav. fn
opcion: tlrruYu!,
SolucroNBs 235

.ROCEDURE MostrarMenu(VAR op: integer) ;

:IGIN
REPEAT
writeln ('Elija una opcion: ' ) ;
writeln ('1-sumar' ) ;
writeln ('2-restar') ;
writeln ('3-multiplicar' ) ;
writeln ('4-traza'\ ;
writeln ('5-traspuesLa' ) ;
readln (op)
IJ\ITIL (opr=1) AND (op<=5
:l,D; {MostrarMenu}

.:,3CEDURE LeerMatriz (VAR m: TMatriz) ;


'-:_R

; .i. i-raaar.
!t ). rrruuYu!/
]:1TIT
_JII\
-

FOR i := 1 T0 NFIL D0
FoR i := I T0 NCOL D0 BEGIN
writeln ('deme eI elemento fila' ,

'columna', j, ' :');


readln (m Ii, j ]
)

END;
:1.); {LeerMatrizi

.: ICEDURE Sumar (m1 , m2 : TMatriz; operacion: integer;


VAR mRes: TMatriz)
l_:.
.i ;. .lraaar.
!1 J. rrlLuYur/
: ]: T\T
- _ JII!
FOR i: =1 T0 NFIL D0
F'OR i : =T TO NCOL D0
mRes[i,j] := m1[i,j] + operacion*m2[i,j];
(^
:.,-; tSumarj
l

.:-lCEDURE Multiplicar(m1, m2: TMatriz; VAR mRes: TMatriz);


'-:.
i, j, k' integer;
r: IIN
FOR i := 1 T0 NFIL D0
FoR i := I T0 NCOL D0 BEGIN
mRes[i,j] := 0;
236 Los rrpos DE DATo ARRAy y srRrNe

EOR k := 1 T0 NFIL D0
mRes[i,j] := mRes[1,j] + ml[i,k]*m2[k,j];
END
END; {Uuttipticar}
FUIICTION Traza (m1 : TMatriz): real;
VAR
.i .i
-r^^^-.
rrruuYur /

d.ux: IedI,'
BEGIN

i := 1 TO NFIL DO
FOR
aux := aux + ml[i,i];
Traza : = aux
END; {fraza}

PROCEDURE Trasponer(VAR m: TMatriz) ;


VAR
'i i. ir1-aaar.
fllusyur,
_).
mAux: TMatriz;
DETIT
!L]UiL\

FOR i := 1 TO NFIL D0
:aD r .= 1 T0 NCOL D0
ntAux[i,j] := m[j,i] ;
tr := TAUX;
!\l r. I U--^drt^l^\
LL\U I
'j7.lt

PROCEDURE Imprrmir(m: TMatriz) ; npn


VAR : coll
i i. . .int-aa-. CIfi
) trluuYr! /

BEG]N lo, a
^
f uR r := I -tO NFIL D0 BEGIN
l
n
(
-^rk -'r
l
, TO NCOL DO histr
write(m[i,j] : 5: 2,,,) ; Pal
r.'r.l ral -.
END mi
:-.-; tlmprlmlrJ
l- l
,gri

:lv
::l-ll lPrograma principal)
I _=--:1:Menu ropcion) ;
-: -!CIoI-]<=3,) THEN BEGN
'-'-:=Ir 'matriz 1:');
231
Sor.ucroNss

LeerMatriz (ma[riz1) ;

writeln('matriz 2:');
LeerMatriz (matriz2) ;

CASE (opcion) 0F
1:Sumar(matriz1, maLriz2, 7, matriz3) ;
2:Sumar(matriz1, maLriz2, -1, matriz3) ;

3 :MuItiplicar (matriz , maLriz2 matriz3


L
' )

END;
writeln ('El resultado es: ') ;

Imprimir (matriz3 )

END
ELSE BEGIN
writeln('matriz:');
LeerMatriz (matrizl) ;

CASE (oPcion) OF
4:wrlteln ('El resultado es: ' , Lraza (matrizl) ) ;

5: BEGIN
Trasponer (matrizl) ;

writeln ('El resultado es: ' ) ;


ImPrimir (matrizl)
END
END
END
:l;) . {Programa PrinciPal }

7.7.10 Dibujar un histograma


:n primer lugar, es necesario pedir la lista de temperaturas al usuario' Posteriormente'
i- construye un vector donde cada pareja sucesiva de componentes caracteriza el inicio
. el f,nal de un intervalo. Este vector ser de ayuda para calcular el histograma. Para
10 que guarda en cada componente
:11o, a continuacin se genera otro vector de longitutl
:1 nmero de veces que las temperaturas se encuentran
en cada intervalo' Este Yector es
:1 histograma de las temperaturas.
Para representar grficamente este vector, se utilizar una
matriz de caracteres de
una de columnas de
limensiones 30x10 (nmero de temperaturas x intervalos). cada
Colllo indique el r"eCtor
:sta matriz Se rellenar COn tantos Caracteres'x'tantas VeCeS ' E1 cdigo que
histograma. El resto de componentes se inicializarn al carcter
"
:suelve el problema se muestra a continuacin'

.ROGRAM arraYsl0;
-,I\ I
NTEMP = 30;
238 Los trpos DE DATo ARRAy y srRrNe

NSUBIN = 10; {numero de subintervalos} -t?


TYPE
THisto = array [1..NTEMP, 1..NSUBIN] OF char; :

::J.
TTemp = array [1..NTEMP] OF real;
T

Tlntervalos = array [1..NSUBIN + 1] OF real;


TNum = array [1..NSUBINJ OF integer;
VAR
nl-StO:'.1'Hl_StO;
temp : TTemp;
lntervalos : Tf ntervalos ;
numTemp: TNum;
E

PROCEDURE PedirDatos (VAR t: TTemp) ;


VAR
i..i-^^^-.
r. lrUUYUr,

BEGIN
-
:
FOR i:= 1 TO NTEMP DO BEGIN
writeln(,Dame 1a temperatura ,, i
readln (t til )
END
END; {tediroatos}

?:,CCEDURE Construirlntervalos (t : TTemp; VAR inter: Tlntervalos) ;

"':,R
naximo, minimo, anchura: reali
I I *!^^^--
r; a.1LtrgcI /.

DTT\T
DLUAL\

maximo := t[1];
minimo := t[1];

FOR i:= 2 Ta NTEMP DO BEGTN
IF (t Ii] > maximo) THEN
maximo := t [i] ;
IF (t til < minimo) THEN
minimo:= t[i]
END;
anchura := abs(maximo - mi-nimo)/10;
m
FOR i := 1 T0 NSUBIN + 1 DO
inLer[i] := minimo + anchura*(i {v
- 1)
FO
END; { Construirlnt,erva}os }
cr
PROCEDURE ContarTemperaturas (t: TTEmp; inter: TlnLervalos; -
VAR n: TNum);
Sor,ucrocss 239

i, intervalo: integer;
llT^T
_tgaL!

FORi:=1T010D0
nlil .- n.
FOR i := 1 TO NTEMP DO BEGIN
int.ervalo : = 2;
WHILE (intervalo<NSUBIN+1) alO (t Ii] rinterIintervalo] ) DO
intervalo := inLervalo + 1-;
nIinterva]o-11 := nIinterva]o-11 + 1
END
:)lD; {ConLarTemperaturas}

;ROCEDURE ConstruirHistograma(n: TNum; VAR histo: THisLo) ;


--tD

fil, coI: integer;


:EGIN
FOR col : = 1 TO NSUBIN D0 BEGIN
FOR fil := 1 TO n[col] D0
hisco [fil, col] i= ' *' ;
POR fil := nlcol] + 1 T0 NTEMP DO
histo Ifi], coll i= ' '|

END
:l,lD ; { ConstruirHistograma i

:ROCEDURE DibujarHistograma(interv: Tlntervalos; histo: THisto) ;


"1D

fil, col: integer;


:.T\T
- Jgrl\
{oinu amos el histograma}
FOR fil := NTEMP DOWNTO 1 DO BEGIN
write ('
FOR col : = 1 TO NSUBIN D0
write (histo Ifi1, col] , '
'.'-: f^l -.
END;

{v ef ee de intervalos}
FOR col := 1 TO NSUBIN + 1 D0
write ( interv [col] : 6: 2) ;
writeln
IND; {nlnui arHistograma}
240 LOS TIPOS DE DATO ARRAY Y STRING

BEGIN {Programa Principal}


PedirDaLos (temp) ;
Construirlntervalos (temp, intervalos) ;
ContarTemperaLuras (temp, intervalos, numTemp) ;

ConstruirHistograma (numTemp, histo) ;


Dibuj arHistograma ( intervalos, hisLo)
ENIJ. tt_Programa Prlncrpal1
, - )

7.7.11 Encontrar y sustituir vocales en una frase


En la solucin dada a este problema se ha construido el conjunto constante de voca1.
(VOCALES = ['A','E',' r','o','u']),queeslaformamsprcticadepregu "

tar si una letra es vocal, ya que basta con la sentencia:

EsVocal := x IN VOCALES

Sin embargo, si no se utiliza un conjunto, la sentencia equivalente sera:


EsVocal := (x = ,A,) 0R (x = ,E,) OR (x = ,I,) 0R
(x ='0') OR (x ='U')
que, como se puede apreciar. es una instruccin bastante menos legible.

PROGRA]VI Arraysll;
CONST
VQCALES = 1,A,, ,8,, ,I,, ,O,, ,IJ,l;
VAR
frase: string;
i : int.eger;

FUNCTI0N EsVocal (x: char) : boolean;


BEGIN
x : = upcase (x) ;
EsVocal := x IN VOCALES
END;

BEGIN {Programa principali


writeln ('Introduzca por teclado un texto enLre
comillas simples') ;
readln (frase) ;
ICR i := 1 TO length(frase) D0
IF EsVocal (frase Ii] ) THEN
freoli'J
!!qJe Lrl
.- *t.

.---:_^-_ /a_-^_^\
\!!spu/

:'-- l--- rvrm n-i-^i^.1i


.- - -Y-
Sor,ucrouns 24t

7.7.12 Contando en frases

En este caso no basta con saber si un carcter es vocal o no, sino que es necesario saber
.1u vocal es. Ya no es suficiente un conjunto constante para almacenar las vocales, y
.e debe por tanto utilizar un tipo con estructura interna. El tipo de dato con estructura
.nterna que se conoce es el array. Se puede definir un array de elementos constantes
Je esta forma:

]]NST
NOMBREARRAY: TTipoArray = (valor1 valorN);
Para definir pues, el vector de vocales (VOCALES), bastara con el siguiente cdigo:

- 1PE
TVocales = ARRAY tl..51 OF char;
, -r-L\1
VOCALES: TVOCA1CS = ('A' , 'E' , 'I' , 'O' , 'U') ;

\ continuacin se muestra la solucin completa al problema considerado:

.!.OGRAM Arrays12;
- IPE
TContador = ARRAY [1..5] OF integer;
TVocales = ARMY tl. .51 0F char;
',';R
frase: string;
'i . i rranav.
flluUYU!,

contador: TContador;
_ -r\t
VOCALES: TVOCAICS = ('A' , 'E' , 'I' , 'A' , 'U');
;iOCEDURE Annadir(x: char; VAR numvocales: TContador);
--- D

'l . finr-^^-.
t. lluUYur,
:__gII\
: TIT

WHILE (i <= S) AND (VOCALES[i] <> upcase(x)) D0


r .- rfr,
]F i<=5 THEN
numVocales Ii] : =numVocales Ii] +1;
:-lD; tAnnadlr f

.3OCEDURE ContadorVocales (frase: string;


VAR numvocales: TContador) ;
242 LOS TTPOS DE DATo ARRAY Y STRING

VAR
ri r' uuYu!
i n]-aaav.
/

BEGIN
FOR i := 1 T0 length(frase) DO
Annadir (frase Ii] , numVocales)
END;

BEGIN {Programa Principat}


FOR i := 1 T0 5 DO
contadorIi] := 0; {fnicializa a 0 todas
las componentes del array)
writeln('Introduzca por teclado un texto,,
' entre comillas simples:,);
readln (frase) ;
ContadorVocales ( f rase, contador) ;
FOR i := 1 TO 5 D0
writeln('Numero de ,, VOCALESIi] , , =,, contador[j-] )

END. {Programa Principa}}

7,7.13 Palndromos
PROGRAM Arraysl3;
VAR
frase : string;

PROCEDURE EliminarBlancos (VAR cadena: string) ;


VAR
aux: str j-ng;
i . 'i nrana-.
!ruL:JUr,
BEG]N
rrrv . / t .
-

FOR i := 1 TO length(cadena) DO

aux := aux + cadena[i];


Cadena : = aux
:'-n.

:-l::lION EsPalindromo(frase: string) : boolean;


-,-_:_1

'i l aaar
rrrreYu! .
/
:a: - l;
SolucroNns 243

i .-.= lanarhffrrcai.
aLlrYUlr\!rq-s/
-.1 i
WHILE (i < j ) aNn (f rase Ii] = f rase t-il ) oo BEGIN
i := i + 1;
J .- ) - r
END;
EsPalindromo := (fraseIi] = fraseIi] )

END;

BEGIN {Programa principali


writeln('Introduzca por teclado un texto entre,,
' comilfas simples,);
readln (frase) ;
EliminarBlancos (frase) ;
IF EsPalindromo(frase) THEN
writeln (,Es palindromo, )
ELSE
writeln (,No es palindromo,)
END. {Programa principal}

7.7.14 Cdigo Morse


PROGRAM Arrays14;
CONST
r - a.
N = 20;
TYPE
TSimbolos = stringII];
TPalabra = string [N] ;
TCodigo = string[N*I];
CONST
MORSE: arrayl'a'..'z') OF TSimbolos = (,.-,, ,-...,, ,-.-.,,
t_ I I I I _ ttttttt
1.1.. ' | .. I
ttttttt , t __ I I
tt _t _ I t I t

VAR
palabra: Tpalabra;
Codtgo : '.1 CodIgo;

PROCEDURE Traduccion(pal: Tpalabra; VAR cod: TCodigo);


VAR
ind: integer;
BEGIN
244 Los rrpos DE DATo ARRAy y srRrNc

FOR ind := 1 TO length(pal) DO


cod : = cod + MORSE [pat [ind] I ;
END; {traduccion}

BEGIN {Programa principal}


writeln(, Introduzca palabra:, ) ;
readln (palabra) ;
traduccion (pa1abra, codigo) ;
writeln (codigo)
END. {Programa principal}

7.7.15 Simulando strings con arrays


PROGRAM Arraysl5;
TYPE
TCadena = array [1..255] OF char;
I
TTnno -_ A
v..aJJt,trtr.

VAR
cadenal, cadena2, cadena3, cadena4: TCadena;
tope1, tope2, tope3 , tope4 : TTope;
inicio, longit.ud: integer;
PROCEDURE Leer(VAR cadena: TCadena; VAR tope: TTope);
BEGIN
l^ .-
.- n.
I t
writeln (,dame una cadena de caracteres: ,
) ;
WHILE NOT eoln DO BEGIN
tope := tope +1;
read (cadena Itope] ) ;
END;
readln
END; {leer}

PROCEDURE Mostrar(cadena: TCadena; tope: TTope) ;


I/AR

i: integer;

ltope <> 0) THEN


FOR i := 1 T0 tope DO
ra,rite (cadena Ii] ) lr.
_-1D
ELSE
write('CADENA VACIA, ) ;
Sor.ucroNBs 245

,:iteln
:l{D; {fUostrar}

IROCEDURE Concatenar(cad1, cad2: TCadena; VAR cad3: TCadena;


tope1, Lope2: TToPe; VAR tope3: TTope) ;
.,-AR

i i nianar.
IIruLYu! /

:aGIN
t.ope3 := topel + toPe2;
FOR i : =1 TO topel DO
cad3 [i] : = cadl [i] ;
FOR i := 1 TO tope2 DO
cad3 [i + Lopel] := cad2 [i] ;

:i,); {Concatenari

.:.ICEDURE Subcadena(VAR cadenaout: TCadena; cadenain: TCadena;


VAR topeout: TTope; topein: TTope; inicio, longitud: integer)
'.:
.l .i r aar .
r. rlruuYur,
r: IIN
topeout := longitud;
FOR i := 1 TO longitud D0
cadenaout[i] := cadenain[i - 1 + nicio];
:-:- ; {Subcadena i

::lIN {Programa PrinciPal}


-eer (cadena1, topel) ;
-eer(cadena2, tope2);
loncatenar(cadena1, cadena2, cadena3, tope1, tope2, Lope3)
:t'riteln ( 'El resultadode concatenar: ' ) ;
l'lostrar (cadenal , topel ) ;
i;riteln('Con:');
ilcstrar (cadena2, tope2) ;
:,;riteln('Es:');
l.l:strar (cadena3 , tope3 ) ;
i;riteln('Dame inicio y longitud de la subcadena a exi:ae:::');
:eadln (inicio, longitud) ;
Subcadena (cadena4, cadena3, tope4, Lope3, inicio, Iongj-tud) ;
::cstrar (cadena4, tope4)
: -. {Programa Principali
246 Los upos DE DATo ARRAy y srRrNe

7.7.16 Frmula qumica


La parte ms complicada de este problema es er anlisis de la frmula qumica
I
extraer de ella el nmero de tomos que tiene de cada eremento. En
esta solucin, se Lr
llamado anal-izar al procedimiento que lo resuelve.
supngase que se necesita conocer el nmero de tomos de cada elemento
Que . :-
un compuesto. El procedimiento debera recorrer cada carcter del
string y deciair .
un carcter que coffesponde a un smbolo qumico. Posteriormente, para
saber el nn
de tomos de este elemento, es necesario saber qu hay a continuacin.
Tenemos
posibilidades:

un valor numrico expresa el nmero de tomos del elemento anterior.


un valor alfanumrico indica que el nmero de tomos del elemento orter,- :

Por ejemplo, el resultado de analizar la frmula CH4 anterior tenemos


1 tont
y4deH.
PROGRAM Arraysl6;
TYPE
TFormula = sLring;
TNAtomos = array [1..4] OF integer;
\7AD

rormula: TFormula;
nALomos : TNAI.omos;
i. f'i n1-ona-.
rusYUr,
CONST
NOMBREAT: ARMy [1..4] OF char = ('C' , 'H' , 'O' , 'N');
CARACTERESVALIDOS = [,C,, ,H, , 'O' , 'N', '2' , '3' , '4'
'5" ,6'l ;

FL'IJCTION Valida (formula : TFormula) : boolean;


VAR
i: integer;
valAux: boolean;
BEG]N
I l.
::ND {
'=

valAux : = TRUE.
, l/\n
WHILE (i <= lengrh(formuta)) eln valAux DO BEGIN
IO[
varAux
..^l
n.---
:= rormula[i] IN CARACTERESVALIDOS;
t

:'.- PESOAT

-.'=__da
:= vafAux
!r- --- - r !^ I De SoArr-
,1_ .)d
IT
SorucroNrs 247

?ROCEDURE pedirDatos (VAR formula:


TFormula) ;
:EGIN
REPEAT
writeln(,Dame una formula quimica de la quimica
, de1, ,
carbono, ) ;
readln (formula) ;
IINTIL Valida ( formula)
IND; {teairoatos}

?R.CEDURE Analizar(formula: TFormula; VAR atom: TNA.omos) ;


."AR

i, elemenLo, err, nurnAtomos: integer;


3EGIN
FOR elemento := 1 TO 4 DO
atomIelemento] := 0;
FOR i := 1 TO length(formula) DO BEGIN
elemento : = 1;
WHILE (elemento<5) AND (NOMBREAT[elemento]
<>formula til ) nO
elemento := efemento + 1;
IF (elemento <> 5) THEN {no es un numero}
rF i < length(formula) THEN {no es el ultimo elemento}
CASE (formutati+11) OF
,C, {vemos el caracter siguient}
,,H, ,,a, ,, N,:at.OmfelementO] :=atOmfelementO] +1;
ELSE
BEGIN
val (formula [i+1] , nurnAtomos , err) ;
IF (err = O) THEN
atom Ie]ementol : = atom felemento] +numAtomos;
END
END
ELSE {es el ultimo elemento}
atomIe]ementol := at.omIe]ementol + 1
END {FOR i}
END; {anatizar}

FLI-NCTION pesoMolecular (atom: TNAtomos)


: integer;
CONST
PESOAT: ARRAY [f ..] OF integer = (12, 7, 16, 74);
VAR
pesoAux, i: integer;
BEG]N
I 248 LOS TTPOS DE DATO ARRAY Y sTRING

pesoAux := 0;
FOR i := 1 TO 4 DO
pesoAux := pesoAux + PESOATIi]*atomIi];
PesoMolecul-ar : = pesoAux
END; {PesoMolecutar}

BEGIN {Programa principal}


PedirDatos (formula) ;
Analizar (formufa, nAtomos) ;
i := 1 TO 4 D0
FOR
writeln('El num. de atomos de', NOMBREAT[i], ' es: ',
nAcomos Ii] ) ;
writeln (' Y su peso molecular es: ' , pesomolecular (nAtomos) )

END. {Programa principal}

7,7.17 El juego del ahorcado


PROGRAM ArrayslT;
CONST
T,TMTTtr, = 7.
I\!It!T\]
\TT _ |U
- '4. t

VAR
palabraA, palabraB: string;
I ^r--
rELIa. ^t^-
tllAli -

'i .
fllno.iger; irl-c
.._-
terminado: boolean;

PROCEDURE Imprimir(VAR palabra: string; fallos: integer); BEGIN


'.'-itol-.
wri-teIn (palabra) ;
writeln('Tienes', fa11os,' fallos' ) ;
writeln
END; {rmprimir}

PROCEDURE Comprobar(palA: string; VAR paIB: string; letra: char;


VAR fallos: J-nteger; VAR term: boolean);
-7f,D

:ncontrada: boolean;
n1-aor.
f'i ruuYUr /

3:3-1,
::-:::::ada : = false;
rOF. : : = 1 TO length (palA) D0 BEGIN
Sor,ucroxrs 249

IF (paIAIi] = letra) THEN BEGIN


palBIi] := lecra;
enconLrada : = true
END
END;
IF NOT (encontrada) THEN
fallos := fallos + 1;
IF (paIA = palB) THEN
term := true;
:ND; {Comprobar}

?ROCEDURE InicializarPalabra (VAR palabra: string;


longitud: inreger);
..AR
i: integer;
sEGIN
palabra := ";
FOR i := 1 TO longitud DO
palabraB = palabraB + ,_,
-L\Ui tl- 1nl-claIlzarPaIabraJ

IROCEDURE LimpiarPantalla (nlineas: integer) ;


-,tAR

i. inr-aa-.
auuYrr /

3EGIN
i := 1 TO nlineas
FOR DO
writeln
-ND; {limpiarnantallai

^*^-.- r-
3EGIN iPrograma Principal)
fal1os : = 0;
terminado := false;
wriLe('.Iugador (B) , deme 1a palabra que debe
adivinar eI jugador (A) : ,) ;
readln (palabraa) ;
LimpiarPantal la (NLIN) ;
InicializarPalabra (palabraB, length (palabraa) ) ;
Imprimir (palabraB, fa11os) ;
WHILE ((fa]los <= LIMITE) AND NOT(rerminado)) DO BEGIN
write (',Jugador (B) , introduzca una letra: , ) ;
readln (letra) ;
Comprobar(palabraA, palabraB, letra, fallos, terminado) ;
250 Los rrpos DE DATo ARRAY Y srRrNe

Imprimir(palabraB, fallos) ;

IF terminado THEN BEGIN


writeln('E} jugador (B) ha acertado la palabra. /\
writeln ( 'Ganador: .Tugador (B) ' )

END
ELSE BEGIN
writeln('E1 jugador (B) ha excedido eI numero
maximo de fallos permitidos. ') ; I
writeln ( 'Ganador: .Tugador (A) ' ) V

END. {lrograma Principal}

7.7.18 Las cuatro en raya


Eljuego de las cuatro en raya que sejugar sobre un tablero de 10 fllas
se va a simular EN
7 columnas, que ser simulado a travs de una matriz de caracteres. Para indicar que ur.-
casilla de este tablero est vaca ser rellenada con un carcter en blanco, de modo qL-. PR(
en el inicio del juego, todas las casillas deben guardar este carcter (ver procedimienl VAR
Inic ial izarTablero).
Tambin es necesario imprimir el estado del tablero despus de cada jugada. Par- BEG
este propsito se ha construido e1 procedimiento PintarTablero. Este procedimient i
se encarga de representar en pantalla un tablero cuadriculado, y la ficha que ocupa cad-
casilla, o un carcter en blanco en caso de que ninguna ficha la ocupe.
El tablero se rellenar con fichas numeradas con los caracteres'l' y'2'en carr.. PROC
turno de los jugadores. Para rellenar el tablero, cada ficha introducida en una columr., BEGI]
cae por el efecto de la gravedad, hasta que se apoya al frnal del tablero o sobre ot:- wl
ficha introducida previamente. Para este propsito se ha construido el procedimien: w1
InsertarFicha. wr
Finalmente, se debe detectar cundo la partida ha finalizado. Esto ocurre cuan. !ur
alguno de los jugadores conecta cuatro flchas siguiendo una lnea recta horizontal, re "
wr.
tical o diagonal. Esta tarea est confiada al procedimiento FinDeJuego y a la funci ' cc
NumeroFichas. A continuacin se lista el cdigo necesario para la resolucin de e. , END; {
problema.
?ROCED
?ROGRAM arrayslS; 3EGIN
IF(
ANCHO = c
AITO = ELSE
TYPE C
,1
TFiI = a.
AT,llrA.
./I!lv, wri tr
TCol =
r
^l\]eHA. ; iur
Sor,ucroNns 251
-t

TTablero = array [TFil, TCol] OF char;


VAR
raD_Lero : .L"1ab_Lero;
posf, posc: integer;
i . i n1-ana-.
aauuYU!,
continuar, caracter: char;
acabo: boolean;

PROCEDURE InicializarTablero (VAR tablero: TTab1ero) ;


VAR
posf, posc: integer;
BEGIN
FOR posf : = 1 T0 ALTO DO
posc : = 1 TO ANCHO DO
FOR
tableroIposf,posc] := ' t

END; {fnicializarTalero}

PROCEDURE Limpiarpantalla (nLineas: integer) ;


VAR
i . in1-ana-.
rrrueYur /

BEGIN FOR i nlineas


: = l_ TO DO
writeln
END; {limpiarpantalla}

PROCEDURE Menu(VAR jugada: char);


BEGIN
rrritol-.

writeln (,Elige opcion: ,) ;


writeln (, (c) Continuar, ) ;
wrlteln(, (s) Sa1ir,);
urritol-.

readln(jugada);
END; {Uenu}

PROCEDURE EstablecerTurno(i: integer; vAR caracter: char) ;


BEGIN
IF odd(i) THEN
CaraCt.er t= ,1,
ELSE
caracter := ,2, ;
writeln (,turno de1 jugador , , caracter) ;
END; {fstablecerTurno}
252 Los rtpos DE DATo ARRAy y srRrNG

PROCEDURE pintarTablero (tablero: TTablero) ;


VAR
v rr. 'i nl a^^- .
f:/ I rllLuYsr,

BEGIN
LimpiarPantal-1a ( 10) ;
FOR X : = ALTO DOWNTO ]- DO BEGIN
wrire(, I ,),
FOR v := T TO ANCHO D0
write(tablero[x,y] ,, | ,);
'.,?.ir^l-,
rlralt
wrruu \ l,t t
| t
trAD r' - - T0
. ANCHO D0
--__tL^/, / /\.
w.I.-tLet'--- t t
rrri tal n.
END;
,uriralt
wlrLu\ l\ t
| t

FOR v := 1 TO ANCHO DO
,"-.i+-olt_t\ \t t t ,lr\.
tlt r I Jt
r.',ir^l.

END; {nintartablero}

PROCEDURE InsertarFicha(VAR tablero: TTablero;


VAR posf, posc: integer; caracter:char);
BEGIN
REPEAT {Control de co}umna llena}
REPEAT {Contro} de columna validai
writeln ('columna en la que quieres introducir
d"*' tu ficha (1-' , ANCHO, ' ) :') i
+l'-,rF
-,+o'sh readln(posc);
' -rt'
IF NOT ( (posc >= 1) AND (posc q= ANCHO) ) THEN
writeln('Columna no valida: Intentelo de nuevo')
UNTIL (posc >= 1) AND (posc <= ANCHO); {Control de
columna valida)
^^^+ .-
.- 1.
f,
Pvr
WHILE (posf a= ALTO) AND NOT (tablero[posf,posc] - ' ') Da
posf := succ(posf);
IF (posf <= ALTO) THEN
tablero [posf, posc] : = caracLer
:-SE
ivliteln('Columna llena: Por favor, elija otra')
,l;--- pcsf q= ALTO {Control de columna llena}

&
Sor,ucroNns 253

:i,J; t lnSertarl,'lcha ]

r ,-]\TCTION NumeroFichas (VAR tablero: TTabIero; posFBuscado,


posCBuscado,direcFil, direcCol: integer) : integer;
--- D

fiI, col:int.eger;
buscado: char;
nVeces: integer;
parar: boolean;
]:ATIT
_ _ JII!

buscado := tablero [posFBuscado,posCBuscado] ;


n\/a^a .-
.- 1
tt

fif := posFBuscado;
col := posCBuscado;
parar := FALSE;
I\]HILE (f iI + direcFil <= ALTO) AND (col + direcCol <= ANCHO)
AND (fil + direcFil >= 1) AND (col + direcCol >= 1)
AND (NOT parar) DO
BEGIN
fiI := fiI * direcFil;
col := col + direcCol;
IF (tableroIfi],co]] = buscado) THEN
nVeces := nVeces + 1

ELSE
parar := true;
END;
NumeroFichas : = nveces
:l,D; {ttumerof ichas }

:,NCTION FinDeJuego (VAR tablero: TTablero;


posf, posc: integer): boolean;
'---R

cuentas: array [1..4] OF integer;


masDeCuatro: boolean;
i i ranr.
tllLUYU!,
::^TIT
__Jll\

t HorI zontal l
cuentas [1] := NumeroFichas (Lablero,
posf, posc, 0, 1)
+ NumeroFichas(tablero, posf, posc, 0/ -1) - 7;
{vertical }
cuentas[2] := NumeroFichas(tabIero, posf, posc, 1, 0)
+ NumeroFichas(tablero, posf, posc, -1, 0) - 1;
254 Los rrpos DE DATo ARRAy y srRrNG

{oiagonat r} 3j
cuent.as[3] := NumeroFichas (tablero, posf, posc, 7, 1)
+ NumeroFichas(tablero, posfr posC, -1, -1) 1.

{niagonal z }
cuentas [4] := NumeroFichas (tablero, posf, posc, 1 1\

+ NumeroFichas(tablero, posf, posc, -1, 1) _ 1.


masDecuatro := FALSE;
i

WHILE (i <= 4) ANO NOT masDeCuatro DO BEGIN I


masDecuatro := ,!cyeg!_q.p[i] " f.i; :-ND;
i := i + 1;
END;
FinDe.Juego : = masDecuatro;
END; {f inne,-luego }

BEGIN {Programa principal}


InicializarTablero (tablero) ;
PintarTablero (tablero) ;
continuar := 'C' ;
I .- l.

acabo := FALSE;
WHILE (upcase(continuar) = 'C') AND (NOT acabo) D0 BEGIN
EstablecerTurno ( i, caracter) ;
InsertarFicha (tablero, posf , posc, caracter);
PintarTablero (tablero) ;
acabo := FinDeJuego(tablero, posf, posc);
IF acabo THEN
write (' ENHOMBUENA, JUGADOR (, , caracter,
, I,
) , HAS GANADO EL .JUEGO )

ELSE
Menu (continuar) ;

END;
readln
LNIJ. t Programa prrnctpa_l J

7.7.19 Yalidacin de la lectura de datos numricos


:-1.::ICN PedirEdad: integer;
.,..:_:

:al::aEdad: string[31 ;
ci:i -niian.
,vur:v. ini-aar.
rrtusYsr r
Sor,ucroNns

BEGIN
REPEAT
wri-teln (,Teclea la edad: ,) ;
readln (cadenaEdad) ;
Val (cadenaEdad, edad, codigo)
;
IF (codigo <> 0) THEN
write (chr (z , {ns para que pite}
UNTIL codigo = O;
PedirEdad : = edad;
END;
-!
?l

Captulo 8

\lgoritmos de bsqueda y
ordenacin

:n este captulo se presentan dif'erentes algoritmos para la resolucin de los problemas


- ordeuacin y bsqueda. Estos problemas han sido ampliamente estudiados debido
: ru aplicacin en distintos mbitos, y se han escrito infinidad de algoritmos para
-QrIt
'::,liverlos. A pesar de que las colecciones de datos utilizadas en este captulo son
--1\'s. algunos algoritmos se pueden aplicar a otro tipo de colecciones.

,1 Algoritmos de bsqueda
:'roblema de la bsqueda consiste en la inspeccin de una coleccin de datos para
: ::Illinar si sta contiene un elemento concreto y, en caso afirmativo, indicar el lugar
. : ,rcupa dentro de la coleccin. En esta seccin se presentan los algoritmos de bs-
.J.r ms usuales: bsqueda secuencial (o lineal) y bsqueda binaria (o dicotmica).
: -, ello. se supondr que se busca un elemento al que se denominar elemBuscado
' ..:l array unidimensional de n elementos, cuyo ndice est definido por el intervalo
: .UtTIMOl . El objetivo es construir una funcin que encuentre y clevuelva el
. -l'::R.O.
-3r valor del ndice posicion para el que se cumple que vector [posicrcnl =e jem-
: . : I ic' Si se llega al final de 1a coleccin sin encontrar e l emBus cado. se devolver un
: rdentificativo que est fuera del rango. Sern de utilidad las siguientes definiciones:

-:
-
:: TMF'PO .,.1
--- TTM

a:
-l^m -

--ntervalo = PRIMERO. .ULTIMO;


-Indice = pred(PRIMERO) . .succ(ULTIMO) ;

251
258 Ar-conrrrtos or nsqurDA Y oRDE,ucrN

PASO 1 elemBuscado

ffi
t
PASO 2
elemBuscado lTl

PASO 3 elemBuscado

PASO 4 elemBuscado

Figura 8.1: Bsqueda en coleccin no ordenada t. gura


jn

TVector = array IT]ntervalol OF TElem;


donde se han definido previamente PRIMERO y ULTIMO como ciertas constantes ordii -
IF
y TElem como un tipo base.
I
ELSI
8.1.1 Bsqueda secuencial o lineal en colecciones no ordenadas E

Una bsqueda lineal en una coleccin no ordenada (figura 8.1) consiste er ur recr .
;{B
en e1 que se compara elemBuscado con cada valor de la coleccin. Se comienza .
primera componente y se avanza secuencialmente hasta que se encuentra elemBu=: -
o se llega al final de la coleccin sin encontrarlo. A continuacin se presenta unt Il - .
construida para implementar el algoritmo descrito. En la seccin de problemas del
se presentan otras implementaciones de este algoritmo.

;-l;CTI0N BusqSecNoOrd(v: TVector; elemBuscado: TElem) : Tlndice'


que
rest
posicion: Tlndice;
BEGIN ION
posicion := PRIMERO;
WI{ILE (posicion < ULTIMO) AND (vlposicion] <> elemBuscado) -- -:sicir
Ar,conrruros DE rsqunoa 259

PASO 1 etemBuscad"
E
ffi
t
PASO 2

PASO
ry
3
elemBuscad"

elemBuscad"
E

E
ffi t
PASO 4 elemBuscad"
E
ffi t
Figura 8.2: Bsqueda en coleccin ordenacla de un elemento que
no pertenece a la colec-
cin

poslcron := succ(posicion) ;
IF (v[posicion] <> efemBuscado) THEN
BusqSecNoOrd := pred(pRIMERO)
ELSE
BusqSecNoOrd := posicion
END; {BusqSecNoOrd}

8.1.2 Bsqueda secuenciar o rinear en corecciones ordenadas


Supongamos que se desea realizar una bsqueda lineal en una coleccin
ordenada cle
modo ascendente (ver figura 8.2). En este caso, es necesario recorrer
desde la primera
componente hasta que se encuentra elemBuscado, o se llega a una
cofirponente con valor
mayor que elemBuscado, o se llega al final de la coleccin sin encontrarlo.
EI siguiente
cdigo resuelve el problema de la bsqueda lineal en arrays ordenados:

FUNCTTON Busqsecord(v: TVector; elemBuscado: TEIem) : Trndrce;


VAR
posicion: Tlndice;
260 Ar,conrrrros DE sseuan v ontrNlcrN

BEGIN
posicion := PRTMERO;
WHILE (posicion < ULTIMO) AND (v [posicion] < efemBuscado) D0
posicion := succ(posicion) ;
IF (v [posicion] = elemBuscado) THEN
BusqSecOrd ;= posicion
ELSE
BusqSecOrd ;= pred(PRIMERO)
END; {BusqSecOrd}

E,s importante observar que este algoritmo tiene complejidad lineal.

8.1.3 Bsqueda binaria o dicotmica


La bsqueda binaria o dicotmica es un algoritmo de bsqueda sobre colecciones r.r'
denadas (figura 8.3). Es el mtodo utilizado usualmente para buscar en un diccionar:
gua telefnica, etc. Este algoritmo examina en primer lugar el elemento central de -
coleccin. Si coincide con elemBuscado se termina la bsqueda. En caso contrario. ',
divide la coleccin en dos mitades y se determina en cul de ellas se puede encont:*
elemBuscado. Se contina dividiendo el espacio de bsqueda en mitades hasta enc'. :

trar el elemento o determinar que no est. Podramos expresar el algoritmo comLl


siguiente secuencia de pasos:

1 Comparar elemBuscado con el elemento central de la coleccin.


2 Si coinciden, terminar la bsqueda.
3 Si no. dividir la coleccin en dos partes y seleccionar la mitad adecuada:

a La primera mitad si elemBuscado < vector lcentral]


a La segunda mitad si elemBuscado > vector [central]

4 Repetir el proceso desde el paso I con Ia mitad elegida.


El siguiente cdigo muestra una implementacin del algoritmo de la bsqueda b. "

ria como una funcin en Pascal:

FIINCTION BusqBin(v: TVector; elemBuscado: TElem) : Tlndice;


-TND

extlnf, extsup, central: Tlndice;


:ncontrado: boolean;
:a:-ll
::.::Inf := PRIMERO;
=x:-:'*p := ULTIMO;
e:-r::---:alc : = FALSE;
Atconrtuos DE onorNRcrN 261

PASO 1 elemBuscado

ffi
PASO elemBuscad,
E

%
PASO 3 etemBuscado
E

Figura 8.3: Bsqueda binaria

WHILE (NOT enconLrado) AND (extsup >= extlnf) O BEGIN


central := (extlnf + extsup) div 2;
IF (vIcentra]l = elemBuscado) THEN
encontrado : = TRUE
ELSE
IF (,r[centra]l < e]emBuscado) THEN
extlnf : = succ (central )
ELSE
extSup ;= pred(central)
END; {wHrlr}
IF (encontrado) THEN
BusqBin : = central
ELSE
BusqBin ;= pred(PRIMERO)
:ND; {eusqein}

La estrategia de bsqueda binaria es ms


eficiente que la bsqueda Iineal. un anlisis
detallado de la complejidad revela que
este algoritmo tiene comprejidad logartmica.

8.2 Algoritmos de ordenacin


La ordenacin se puede describir como
el problema de colocar los elementos de
oleccin siguiendo un determinado orden una
(ascendente o descendente). Es un probrema
262 Ar,conrrrros DE nseupnl v ononNlcrN

1 2 3 4 5 7 B c

Figura 8.4: Ordenacin por seleccin directa

ampliamente tratado y existen una gran cantidad de algoritmos dedicados a resoh -


Dependiendo de cmo llevan a cabo la ordenacin, podemos clasifrcar los algoritnt,--' -

ordenacin en:

Algoritmos de ordenacin por intercambio: se caracterizan por intercambiar par. '


elementos de la coleccin hasta conseguir su ordenacin. Son apropiados :
colecciones de datos pequeas. Pertenecen a esta categora los algoritmos d.
denacin por seleccin directa, insercin directa e intercambio directo.

Algoritmos de ordenacin por fusin: se basan en la operacin de fusin de 2 c .


ciones ordenadas y son apropiados para colecciones de datos grandes. E1 " -
ritmo mergesort pertenece a esta categora. (r,
rste
a
8.2.1 Ordenacin por seleccin directa -enad

Para ordenar una coleccin de modo ascendente/descendente, el algoritmo de


directa recorre la parte no ordenada de la coleccin seleccionando el elementt
funcr
norinravor en cada recomido y colocndolo en la primera posicin no ordenada c.
alg
coleccin. Tras n - 1 recorridos, la coleccin est ordenada (ver llgura 8.4). La
cia de pasos para ordenar una coleccin de forma ascendente es la siguiente: Se to
Ar,conrrmos DE onorNlcrN 263

I Se recorre toda la coleccin buscando el elemento menor y se coloca en la primera


posicin.
I Se busca el menor elemento del resto de la coleccin (elementos 2 al n) y se coloca
en la segunda posicin.

Se busca el menor elemento del resto de la coleccin (elementos j al n) y se coloca en


1a posicin j.

-r cdigo que se muestra a continuacin es una implementacin del algoritmo de selec-


-.,n directa:
.:ICEDURE SeleccionDirecta(VAR v: TVector) ;
-_l_-:,

i, j, posMenor: Tlntervalo;
valMenor: TElem;
: ] -,-II\T\T

0R i : = PRIMERO TO pred (ULTIMO) D0 BEGIN


valMenor := v[i];
PosMenor : = i;
FOR j := succ(i) TO ULTIMO D0
IF (vtjl < valMenor) THU\T
BEGIN
valMenor := v[j];
posMenor : = j
END; {Ir}
IF (posMenor<>i) THEN
BEGIN
v[posMenor] := v[i];
v[i] := valMenor;
END {rF}
IND {FOR i}
' l^
- ; tSeleCClonulrecta.f
- t l

8.2.2 Ordenacin por insercin directa


:\te algoritmo, como el anterior, divide la coleccin en parte ordenada \,parte no or-
::nada. La estrategia consiste en escoger el primer elemento de 1a parte no ordenada y
sJorrer la parte ordenada para insertar este elemento en su lugar correcto entre los ya
:denados. Tras n - I
recorridos, la coleccin est ordenada. En la frgura 8.5 se muestra
.. luncionamiento de esta algoritmo sobre un array de nmeros enteros. El esquema de
:>te algoritmo se puede expresar en la siguiente secuencia de pasos:

1 Se toma el primer elemento de la coleccin como el primero de los ordenados.

flt
264 Ar,conrrivros DE nsqurnl y ononNEcrN

9 3 1 2 7 B
t_J

I
tt
1 2 31415 7 B 9

Figura 8.5: Ordenacin por insercin directa

2 Se elige el segundo elemento de la coleccin (primer elemento de la parte flo orc:.


nada) y se coloca en el lugar que le corresponde respecto al elemento ordenad,-
3 Se elige el tercer elemento de la coleccin (primer elemento de la parte noorden;-
1, se coloca en el lugar que le coresponde respecto a los elementos orden
(primero y segundo).

j Se elige el elemento j
de la coleccin y se coloca en el lugal que le iorresponde den:
del conjunto de elementos 1 alj-1.

En el siguiente cdigo se presenta un procedimiento que recibe un affay desorder':


y lo devuelve ordenado por el mtodo de insercin directa:

PROCEDURE InsercionDirecta(VAR v: TVector) ;


VAR
i, j: Tlndice;
aux: TElem;
tsEGIN
0R i := succ(PRIMERO) T0 ULTIMO D0 BEGIN
rrY .= rlil
" L-) I

i := pred(i);
'/iliILE (j >= PRIMERO) AND (vtjl > aux) D0 BEGIN
Ar-conrrrros DE onBNlcrN 265

4 5 9 3 1 B 7 2

4 5 9 3 1 B 2 7 4 3 5 1 B 2 7
tl t+
4 5 3 9 1 B 2 7
tt
tl
4 3 1 5 2 B tl
tl
4 5 3 1 B 2 9 7
tl

Figura 8.6: Ordenacin por intercambio directo

v[succ(j)] := v[j];
i := pred(j)
END; iwHILr)
v[succ(j)] := aux
END {FoR}
:ND; {lnserciorDirecta}

8.2.3 Ordenacin por intercambio directo


El algoritmo por intercambio directo tambin se conoce con el nombre de mtodo de
1a burbuja. Consiste en recoffer el vector desde la primera posicin
hasta 1a actual'
intercambiando valores vecinos cuando no estn ordenados entre ellos' De este tlodo'
se traslada, mediante sucesivos intercambios. el valor mayor hasta la
posicin que ie
de
corresponde en una coleccin ordenada. En la figura 8.6 se ilustra el l-uncionatr-riento
esta algoritmo sobre un affay de nmeros enteros. El algoritmo consiste en la ejecucin
de los siguientes Pasos:

1 Colocar el elemento mayor en la ltima posicin' Para ello. se comparan el primer


y segundo elemento cle la coleccin y, si estn desordenados. se intercambian.
Posteriormente, se comparan el segundo y el tercero y se intercambian si estn
que
desorclenados. Se siguen comparando parejas de elementos contiguos hasta
se comparan el penltimo y el ltimo y se intercambian si estn desordenados.
266 Ar,conrrnros DE nsqurna y onoBNlcrN

2 Siguiendo el mismo procedimiento, se coloca el mayor de los elementos entre la po-


sicin 1 a n-1 en la penltima posicin.
j Se opera del mismo modo para colocar el mayor de los elementos entre la posicin 1

y la j en la posicin j.

El cdigo presentado a continuacin es una implementacin del mtodo de intercambio


directo:

PROCEDURE IntercambioDirecto (VAR v: TVector) ;


VAR
1
Lt f . 'l'ld^.
). arrfqruu,

aux: TEIem;
BEGIN
FOR i := ULTIMO DOWNTO succ(pRIMERO) DO
FOR j := PRIMERO TO pred(i) DO
IF (vtjl > v[succ(j)]) THEN BEGIN
aux := vljl ;
vtjl := v[succ(j)];
v[succ(j)] := aux
END {rF}
END; {IntercambioDirectoi

8.2.4 Mergesort
Los algoritmos de ordenacin considerados hasta ahora, ordenan la coleccin entera
de elementos. En algunas ocasiones, el tamao de la coleccin es demasiado grande
y estos mtodos dejan de ser adecuados. La estrategia ms conveniente en estos casos
consiste en ordenar la coleccin a trozos, para luego fusionar adecuadamente estos trozos
obteniendo toda ia coleccin ordenada. Se hace necesaria, entonces, la implementacin
de un algoritmo que permita unir dos colecciones ordenadas de forma que la unin est
tambin ordenada.
supongamos un array v en el que dos subarrays contiguos vliz..cel y v[ce +
l-..del estn ordenados ascendentemente. El objetivo es fusionar estos dos subarrays
para conseguir una regin ordenada en el aray w ltz . . de I . para ello, comenzamos com-
parando los elementos v [iz] y v fce + 1], colocamos el menor en w [iz] y avanzamos
en el ndice del sub-array que contena ese valor menor. Volvemos a comparar dos ele-
mentos y colocamos el menor en w fiz + 1] , avanzando slo en el ndice apropiado. La
solucin en forma de procedimiento en Pascal se muestra a continuacin:

::.::ilURE Fusion(v: TVector; iz, ce, de: Tlntervalo;


w: TVector) ;
I::: "AR
i, , k: ored (PRIMERO) . . succ (ULTIMO) ;
Ar,conrrvros DE onorNacrN 267

rym@m
mro=esoq.
_merOeso\

rodsort I
,/\ f
,"r*",, l*ffi)
*8".
E'" / / I

/ /
ErE
''r'/ / \r/
''ffiH T
ffiH
ErE

"/
@m \r,,i0,y'
mE
\sin
Iolil,ElqElilsFl8l

Figura 8.7: Ordenacin con el algoritmo mergesort

crr
uqve /^o\ .
\uu/ ,

--_J E (i <= ce) AND (j <= de) DO BEGIN


rF (v[i] . v[j]) rHN BEG]N
w[k] := vlil ;
i .= erra1i\
vgve \ r /

ND
JLSE BEGIN
w[k] ,= v[j];
j := succ(j)
268 Ar,conrrnros DE nseupl v onorNlcrN

END;
k := succ (k)
END; {wurln}
trOD k := i T de D0
w[k] := v[k] ;
FOR k := i TO ce D0
wlk, de - ce] := v[k] ;

END; {nusion}

El algoritmo mergesort hace uso del algoritmo de fusin para ordenar un affay de forma
recursiva (ver ligura 8.7). La estrategia consiste en dividir recursivamente el array en
mitades, hasta que se llega a un determinado tamao umbral. En los ejemplos mostrado'
en este tema. se considera como tamao umbral el valor 1. Sin embargo, se pued.
utilizar otro tamao umbral, en cuyo caso es necesario ordenar cada subamay utilizanc
algn algoritmo de ordenacin. A partir de ah. se f'usionan las soluciones generando .
array inicial ordenado. El coste de este algoritmo es nlog(n), por 1o que es ms efrcier'- .
que los algoritmos de ordenacin por intercambio, que tienen una complejidad Oi:-
Esta diferencia es importante para un nmero grande de datos (r). El siguiente cd--.
muestra un procedimiento que ordena un array con el mtodo mergesort.

PROCEDURE Mergesort(VAR v: TVector; izQ, der: Tlntervalo);


VAR
centro: Tlntervalo;
BEGIN
centro := ,izq - der) div 2;
-E
MY
. -^ \- stl
^-ntro) THEN
Mergesort (v, rq, cent.ro) ;
IF (succ(centro) < der) THEN
Mergesort (v, succ (centro) , der) ;

Fusion(v, ,rq., centro, der, v)


END ; {fuergesort }

8.3 Cuestiones de tiPo test


Las siguientes cuestiones Pueden tener una o varias respuestas coffectas.

8.3.1 Enunciados
-
1. uCual de los siguientes algoritmos es ms indicado para ordenar colecc: "

datos de gran tamao?

(rl Seleccin.
CUnSTToNTS DE TIPo TEST 269

(b) Burbuja.
(c) Mergesort.
(d) Todas las anteriores son falsas.

2. El orden de complejidad del algoritmo de bsqueda binaria:

(a) Es menor que el de bsqueda lineal.


(b) Es o(n).
(c) Es o("t).
(d) Es o(tog(n)).

El algoritmo de la burbuja:

(a) Es un algoritmo de ordenacin por f'usin.


(b) Es o(n).
(c) Es O(.n2).
(d) Es un algoritmo de ordenacin por intercambio.
-:. ,Cules de las siguientes estructuras son adecuadas para realizar una bsqueda
Iineal en un affay ordenado?

(a) nueuar..uNTrL.
(b) FoR.
(c) WHILE.
(d) 2 estructuras de repeticin cualesquiera anidadas.

La estrategia de ordenacin ascendente por el mtodo de la burbuja cosiste en:

(a) Recorrer la parte no ordenada seleccionando el elemento menor en cada re-


corrido y colocarlc en la primera posicin no ordenada del array.
(b) Escoger el primer elemento de la parte no ordenada y recoffer la parte orde-
nada para insertar este elemento en su lugar.
(c) Recorrer el array desde la primera posicin hasta la actual. intercarnbiando
valores vecinos cuando no estn ordenados entre ellos.
(d) Dividir recursivamente el aray en mitades y fusionar 1as scluciones gene-
rando el aray inicial ordenaCo.

6. La estrategia de ordenacin por el mtodo de insercin directa colrslste en:

(a) Recorrer el vector desde la primera posicin hasta la actual. intercambiando


valores vecinos cuando no estn ordenados entre ellos.
(b) Escoger el primer elemento de la parte no ordenada )' recorrer Ia parte orde-
nada para inseftar este elemento en su lugar.
210 Ar,conrruos DE nsgunol y onnrNlcrN

(c) Recorrer la parte no ordenada seleccionando el elemento menor en cada re -

corrido y colocarlo en la primera posicin no ordenada de la coleccin.


(d) Dividir recursivamente el array en mitades y fusionar las soluciones gene-
rando el array inicial ordenado.

7. El orden de complejidad del algoritmo de ordenacin por el mtodo de seleccin


directa:

(a) Es O(nlog(n)).
(b) Es o(n).
(c) Es O(n').
(d) Es o(tog(n)).

8. Cuntos recomidos son necesarios para ordenar una coleccin de n elemento:


utilizando el mtodo de intercambio directo?

(a) o(ntog(n)).
(b) o(n* (n - 1)).
(c) o(n).
(d) o(n - t).

9. Cuntos recorridos son necesarios para buscar un elemento en una coleccin de


n elementos?

(a) 1.
(b) los(.n').
(.c) n.
(d) 2.

8.3.2 Soluciones 8.

l. La respuesta colTecta es la (c). El orden de complejidad de los algoritmos cle 8.,


ordenacin por intercambio es 22 mientras que el algoritmo mergesoft tiene un
orden de complejidad de nlog(n). cuando n es muy grande, la cantidad nlog(n1 In
es sustancialmente menor que n2, por lo que, en ese caso, ser ms conveniente de
utilizar el algoritmo mergesort. esl

l. Las respuestas cor:rectas son la (a) y la (d). El orden de complejidad del algoritmo
de bsqueda binaria es log(n), que es menor que la correspondiente a la bsqueda $.2
lineal (ri).
Im
-1. Las respuestas correctas son la (c) y Ia (cl). Es un algoritmo de ordenacin por
10
intercarnbio cuya complejidad es n2.
RE]

tii
PRosr.nnr,s 271

-
:!
respuestas correctas son la (a) y la (c). La condicin de parada en la bsqueda
--neal en un array ordenado es "o bien se ha llegado al f,nal de la coleccin o bien
:1 elemento buscado es menor que el elemento actual'. Una estructura FOR no es
:decuada, ya que no permite la interrupcin de la bsqueda cuando el elemento
buscado es menor que el elemento actual.

La respuesta correcta es la (c). En este esquema se recome el vector desde la


primera posicin hasta la actual, intercambiando valores vecinos cuando no estn
,rdenados entre ellos.

La respuesta coecta es la (b). En este esquema se escoge el primer elemento de


.e parte no ordenada y se recofre la parte ordenada para insertar este elemento en
.u lugar.

n-a respuesta correcta es la (c). El orden de complejidad de los algoritmos de


rrdenacin por intercambio es n2. El algoritmo mergesort tiene un orden de com-
:lejidad de nlog(n). Los algoritmos de bsqueda lineal y binaria tienen un orden
Je n y log (n) respectivamente.

La respuesta correcta es la (d). En el primer recomido se coloca el mayor ele-


rento en la ltima posicin de la coleccin. En un segundo recorrido se coloca
:L segundo mayor elemento en la penltima posicin de la coleccin. Se sigue
recorriendo la parte no ordenada de la coleccin hasta la iteracin n-1, en la cual
se coloca en la segunda posicin el mayor de ios dos elementos que quedan por
ordenar. De este modo los dos ltimos elementos quedan ordenados y, con ellos,
:oda la coleccin.

-: respuesta corecta es Ia (a). Para encontrar un element0 en una coleccin es


.uf,ciente con recorrerla 1 vez.

*{ Problema
n .,!,1 Bsqueda secuencial en un array ordenado
:.:mente un procedimiento que perrnita buscar un elemento en un affay ordenado
nmeros enteros, siguiendo una estrategia de bsqueda secuencial. Utilice una
--, rura REPEAT . . UNTIL. Incluya la definicin de constantes y tipos de datos.

. +,2 Bsqueda binaria


' . ::tente un procedimiento que permita buscar un elemento en un affay ordenado de
-
- :iros enteros, siguiendo una estrategia de bsquedabinana. Utilice una estructura
--NTIL.
" r. -.. lncluya la deflnicin de cosstantes y treos de datos.
212 Alconrruos DE nsqurol y onorxncrN

8.4.3 Representacin grfica de una bsqueda binaria

Implemente un programa que represente grficamente los pasos dados por una bsqueda
binaria, como en el siguiente ejemplo:

Numero buscado:12
23 5 810 1.22L2429334L s4557889
t .l
t ,]
t=l
EL 72 esta en la posicion numero: 6

8.4.4 Representacin grfica del atgoritmo de la burbuja

Implemente un programa que represente grflcamente los pasos dados por un algoritmo
de ordenacin por intercambio directo. Imprima el vector en cada paso intercalando los
smbolos:

"==" debajo de los elementos que se estn comparando cuando estn ordenado:
entre s
"><" debajo de los elementos que se estn comparando cuando estn desordenado.
entre s

8.4.5 Versin mejorada del algoritmo de la burtluja

Una versin mejorada del algoritmo de ordenacin por intercambio directo consiste e:
realizar pasadas ordenando pares hasta que en un recorrido no haga falta ordenar nir..
guno. Se pide modificar el algoritmo de ordenacin por intercambio directo para >:
detenga en esta situacin.

8.4.6 Representacin grfica del algoritmo de seleccin directa

Implemente un programa que represente grflcamente los pasos dados por un algoritn,
de ordenacin por seleccin directa. Imprima el vector en cada paso, indicando los d' .

elementos que se intercambian.

8.1.7 Representacin grflca del algoritmo de insercin directa

In-rplemente un programa que represente grflcamente los pasos dados por un algontr
de ordenacin por insercin directa. Imprima el vector en cada paso, indicando e1 e ."
mento elegido para insertar, y los dos eiementos entre lo que se insertar.
SqLsq\qs \\
B.{.8 Listinte\etnico
\-srs\r.uautr\>rsB\b\tr'd q\'rrr-getre etrutram'a\sst'stsres'tt\'tsrgrs,s\e\t\g\srrs\s,
',lna\rs\a e personas B\ progtama ebe pemrirr'rr'.
.

l. Insertar un nuevo contacto en el lugar correspondiente segn el orden alfabtico.


2. Visualizar la coleccin.

B.-1.9 Representacin grfica del algoritmo mergesort


- ,-rnstruya un programa que represente grficamente los lmites de los sub-arays durante
. .visin y la mezcla en cada recursin del algoritmo mergesort. Para ello, imprima el
:--ror en cada paso, indicando si se est en la fase de divisin o de fusin, y debajo de
. itrchetes que limiten los sub-arrays que se estn dividiendo o fusionando.

S.5 Soluciones
\,5.1 Bsqueda secuencial en un array ordenado
--,nicin de constantes y tipos de datos:

--tr -
.llMERO = 1;
,-TTMO = 10;
- _l

_.:.:ervalo = PRIMERO. .ULT]MO;


- -:-lrce = pred(PRIMERO) ..ULTIMO;
:-lfll = lnteger;
.'::tor = array lTlntervalo] 0F TElem;
:- procedimiento propuesto se lista a continuacin:
' ' ,--lN BusqsecOrd2(v: TVector; elemBuscado: TElem): Tlndice;
:

. -=-:ion: Trndice;
..: _ :_n .= pred(PRIMERO)
l:r:--:

::sicion := succ(posicion) ;
- - -- (posicion = ULTIMO) oR (v [posicion] >= elemBuscado) ;

:r -.-:posicionl = elemBuscado) THEN


..^sqSec0rd2 ;= posicion
--::
:--qSecOrd2 ;= pred(PRIMERO)
.^ l
: -: ISeCUIOZ ]
^
274 Ar,conrruos DE nseupl y onorurcrN

8.5.2 Bsqueda binaria


La deflnicin de constantes y tipos de datos tttilizada es la misma que la anterior. El
procedimiento propuesto es el siguiente:

FUITCTION BusqBin2 (v: TVector; elemBuscado: TEIem) : Tlndice;


VAR
extlnf , extSup, central-: pred(PRIMERO) . . succ (ULTIMO) ;
enconLrado: boolean;
BEGIN
extlnf := PRIMERO;
extSup := ULTIMO;
encontrado := FALSE;
REPEAT
central i= (extlnf + extsup) div 2;
IF (vlcentrall = elemBuscado) THEN
encontrado : = TRUE I
ELSE V

IF (v[central] < elemBuscado) THEN


extlnf := succ(central) B,

ELSE
extSup = pred(central)
IJIITIL (encontrado) OR (extSup < extlnf ) ;
IF encont.rado THEN EN
BusqBin2 : = cenLral-
ELSE PR(

BusqBin2 = pred(PRIMERO) c0
END; {BusqBin2 }

8.5.3 Representacin grfica de una bsqueda binaria VAR


:
PROGRAM A1903; BEG]
CONST I,!

= 1;
PRIMERO
ULTIMO = 15; END;
N = ULTIMO - PRIMERO +1;
TYPE FIINC!
TINTCrVAIO = PRIMERO. .ULTIMO; VAR
Tlndice = Pred (PRIMERO) . . succ (ULTIMO) ; ex
I::em = integer; en
lTector = array [T1ntervalo] OF TElem; cu;
-I -;
BEG]N
e-=r.:*scado: TElem; ext
Sor,ucroNBs 275

vector: Tvector;
res : Tlndice;
i: integer;
. :.ICEDURE PedirVector (VAR vector: TVector);
-li-
r: Tlntervalo;
I I -TtT
- - --rr!
iOR i := PRIMERO T0 ULTIMO DO BEGIN
writeln(,Deme la componente/ /
i, ' de un vector ordenado:');
readln (vector Ii] )
]ND
-.-:
.: -lDURE ImprimirVector (VAR vector: TVector) ;
-i.

i: Tlntervalo;
!=GIN
FOR i := PRIMERO T0 ULTIMO DO
write(vect.orIi] : 3);
rrriteln
am,-

: -.]JRE Dibuj arBusquBin ( inf, sup, c: Tlndice; CurSorc: Char);


-_:
_

_]F I lt.
_ Lt
t1t.
-: -:P )t

'.:

.i *r lLt CUTSOTC: (c-InI)x3+1,


CSUP: (sup - c) *3 + i,

-::N BusqBin(v: TVector; elemBuscado: TElem. : TInd_ce;


".:

=..:-:f, extSup, central, posinf, possup: TInd-ce;


.--- - :::trado : boolean;

- -:s::central: char;

- .-- -:i : = PRIMERO;


276 Ar-conrruos op nseunDA Y oRDENACToN

extSup := ULTIMO;
encontrado : = FALSE;
WHILE (NOT encontrado) AND (extsup >= extlnf) D0 BEGTN
central := (extlnf + extsup) div 2;
n-qr-':= eXtinf;
PoSSup := extsup;
IF v Icentral] = elemBuscado THEN BEGIN
enconcrado = : TRUE;
CurSolcentra] i= '='
END
ELSE
' IF v [central] < efemBuscado THEN
BEGIN
extlnf := succ(central) ;

cursorcentral t= '>'
END
ELSE
BEGIN
extSuP = Pred(central) ;

CursorcenLTdl := '<'
END;
DibujarBusquBin (Posinf , Possup, central/ cursorcentral) ;

END; {WUrlr}
IF encontrado THEN
BusqBin : = central
ELSE
BusqBin = Pred(PRIMERO)
END; {eusqein}

BEGIN {Programa princiPali


PedirVector (vector) ;

write ('Numero buscado: ' ) ;


readln (elembuscado) ;
wri te ln;
ImprimirVector (vector) ;
res := BusqBin(Vector,elemBuscado) ;
-I res = pred(PRIMERO)) THEN
rr,riteln ( ' elemento no encontrado' )

:-S l
',i::rteln('el ', elembuscado, ' esta en Ia posicion: ', res
:l; . .-:: ::ama PrinCiPal )
Sor,ucroNns 211

!.5..1 Representacin grfica del algoritmo de la burtruja

.::3RAM Alg04;
. ];ST
f)TMtrDA - T

ILTIMO = 10;
l'i = 10;
-': ?1
IINTCTVA1O = PRIMERO. .ULTTMO;
llndice = Pred (PRIMERO) . . succ (ULTIMO) ;

lElem = integer;
-vector = drrdv [Trntervalo] 0F TElem;
.-:-
-,-ector: TVect.or;

::::EDURE PedirVector (VAR vector: TVector);


t:
- : Tlnterval-o;
----l __t\

ICR i : = PRIMERO TO ULTIMO DO BEGIN


writeln('Deme 1a componente ',
i, ' de un vecLor desordenado:');
readln (vector Ii] )
:l{D

:LOCEDURE ImprimirVecLor (VAR vector: TVecLor) ;


T}R
i: Tlntervalo; \

-GIN
i : = PRIMERO TO ULTIMO D0
FOR
write (vector Ii] : 3) ;
writeln
3B;

;ROCEDURE DibujarOrdenacion(orden: boolean; ind: Tlndice) ;


TR
i: Tlndice;
car: st.ring;
ffiIN
IF orden THEN
^r .- |
--l
278 Alconrrnros DE nsqunoa y onnnglcrN

ELSE
CaT i= t><t ;
writeln(car: ind*3 + 2\
END;

PROCEDURE IntercambioDirect.o(VAR v: TVector) ;


VAR
l-, I : -L'lndlce;
aux: TElem;
orden: boolean;
BEG]N
FOR i := ULTIMO DOWNTO succ(pRIMERO) DO
FOR j:= PRTMERO TO pred(i) Do BEGrN
ImprimirVector (v) ; 8

orden := (v[succ(j)] > v[j]); D


IF NOT orden THEN BEGIN
uX := v[j];
vtjl := v[succ(j)];
vlsucc(j)] := aux
END; {rri
T]
Dibuj arO::denacion (orden, j ) ;
readln
END
END; {IntercambioDirecto}

V
BEGIN {Programa principa}}
PedirVector (vector) ;
IntercambioDirecto (vector) ;
PR
Imprimi rVect.or (vector )
VA
END. {Programa principal}

BEt
8.5.5 Versin mejorada del algoritmo de la burbuja
;:aCEDURE IntercambioDirecto(VAR v: TVector) ;
.t_:
_ r. .
) fl'ind1.
rgrvu,
: -'
'Ftrlam.

-=*:-cs: boolean;
::r-1,
PRC
- : = IITIMO; VAR
la:i-CS := TRUE;
i;__: : >= succ(PRIMERO)) aNO (cambios) DO BEGIN
SolucroNBs
279
cambios := FALSE;
FOR j := pRIMERO TO pred(i) oO
rr (vljl > vlsucc(j)]) THEN BEGIN
aux := v[j];
vljl := vlsucc(j)l;
v[succ(j)] := uXi
cambios := TRUE;
END; {rei
i ,= pred(i)
END
:liD; {IntercambioDirecto}

8'5.6 Representacin grfica del argoritmo


de sereccin directa
::3GRAM A1906;

PRIMERO = 1;
ULT]MO = 1 N.
= 10;
- :';E
TINtCTVAlO = PRIMERO. .ULTIMO;
Ilndice = pred (PRIMERO) . . succ (ULTIMO)
;
TElem = integer;
r vecror
T\7^^! ^--
= array ITInterval0] oF ?EIem;
-
vector: TVect.or;

pedirVector (VAR vect.or: TVector)


=OCEDURE ;
;R
1 : '1'lntervaf o;

=3GIN
FOR i := pRIMERO TO
ULTIMO DO BEGIN
writeln(,Deme la componente ,,
i,'deun vect.or desorde:rado:, );
readln (vector Ii] )
E}D
4D,-

:, I:DURE fmprimirVector (VAR vector: TVecco-.

_: TfnLervalo;
280 Ar,conrrvros DE rsquroa y onorNlcrN

i : = PRIMERO T0 ULTIMO D0
FOR
write(vectorIi]: 3);
wrlteln
END;

PROCEDURE DibujarSeleccion (lugar, menor:TIndice)


CONST
a^p] - /_-_/.
CAP, t--t .
=
^Dl t_--t.
-
BEGIN
IF (lugar<>menor) THEN
writeln (cAR1: lugar*3 1, CAR2: (menor - Iugar)*3
ELSE
writeln (Can:: lugar*3 1)
END; {OinuiarSeleccion}

PROCEDURE SeleccionDirecta (VAR v: TVect.or) ;


VAR
i, j, posMenor: Tlntervalo;
valMenor: TElem;
BEG]N
FOR i := PRIMERO TO pred(ULTIMO) DO BEGIN
ImprimirVector (v) ;
valMenor := v[i];
PosMenor : = i;
FOR j := succ(i) T0 ULTIMO D0
rF (vljl < vafMenor) THEN
BEGIN
valMenor := v[j] ;

PosMenor | = j
END; {Ir}
IF (posMenor <> i) THEN
BEGIN
vfposMenor] := v[i];
v[i] := va1Menor;
END; {tr}
Dibuj arSeleccion ( j- , posmenor) ;
:eadln
.1,:t iFOR i)
,1
i=_E --rwLl;_L-LtsULd)
Sor,ucroNns 281

..,-:l {Programa principal}


.=dirVector (vector) ;
SeleccionDirecta (vector) ;

-mprimi rVector (vector )


r-,-. lPrograma principal j

t.5.7 Representacin grfica del algoritmo de insercin directa

- .-digo del ejercicio anterior se puede utilizar para este ejercicio sustituyendo el pro-
--:rlla principal y los procedimientos OibujarSeleccion y SeleccionDirecta por
-: rj arlnsercion e InsercionDirecta, listados a continuacin.
: , ]fDURE Dibujarlnsercion(lugar, menor: Tlndice) ;
--:l
-- D1

^-:a _ ,<_,;
__ I ) ,_, ;

-a (Iugar = pred(PRIMERO) ) rHnt'l


writeln(caRz: lugar*3 + 3,
CAR3: (menor - lugar - 1)*3)
:_::
-F Iugar=flnor-1THEN
writeln(CAR1: Iugar*3 + 1,
CAR3: (menor - lugar) *3 - 1)

writeln(CeRt: lugar*3 + 1-, CAR2,


CAR3: (menor - lugar - 1)*3)
I -buj arlnsercion)

InsercionDirecta(VAR v: TVector) ;

Tlndice;
-Ftrl am.

-t:i. i := succ(PRIMERO) TO ULTIMO DO BEGIN


ImprimirVector (v) ;
illlx := vlil ;
i := pred(i);
ITHILE(j >= PRIMER3) AND (v[j] > aux) DO BEGIN
v[succ(j)] := v[j];
i := pred(j)
282 Alconrruos DE sseupon v onprNlcrN

END; {wutln}
v[succ(j)] := Xi E
Dibujarlnsercion (j, i)
readln P
END {FOR} B.
END ; { InsercionDirecta}
BEGIN {Programa principali
PedirVector (vector) ;
InsercionDirecta (vector) ;
ImprimirVector (vector )
t- l
ENIJ. t Programa prlnclpar J

PR(
8.5.8 Listn telefnico

En este programa se debe llevar a cabo una bsqueda cadavez que inseftamos un nue\ - VA
elemento, puesto que hay que insertarlo en el lugar correspondiente segn el orden a--
fabtico. Adems hay que "hacer hueco" al nuevo elemento. Esto implica que, par-
no perder informacin, es necesario desplazar los elementos de la lista posteriores a .- BEG
ltima incorporacin. Para la realizacin de estas operaciones se ha implementado
procedimiento NuevoCont act o.

PRLGH*AIV] IlST1N;

TI]T
ar\r _ f1 .
- /

trT\T = ?0.
TYPE
TRango = INI..FIN;
TContacto = array [1..2] 0F string;
TAgenda = array [TRango] OF TContacto;
TTope = pred(INI) . .succ(FIN) ;
\71D

tope: TTope;
agenda: Tagenda;
contacto: TContacto;
!y. 'iraaar.
frluuYu! ,

;:l:llURE Leercontacto(VAR contacLo: TContacto) ; BEGIN


i;:::eln('Nombre:');
:eaCl-n (contacto []-l ) ;
w:-:=-:-'TeIefono:') ;
Sor,ucroNns 283

read.ln (cont acLo [2 j);


:\ln.

IROCEDURE MostrarMenu(VAR op: integer) ;


3EG]N
REPEAT
writeln (,Elija una opcion, );
writeln(,1 - Anadir,);
writeln(,2 - Mostrar,) ;
writeln (,3 - salir, ) ;
readln(op);
-l;llL (op>=t) amo (op<=3
-"t

.:--,DURE NuevoConLaclo (VAR agenda: TAgenda; VAR t.ope:TTope;


contacto: TContacto);

I/ l:'I'Ranqo;
cerminar: boolean;
:]-TNT
--grlr
tope := tope + 1;
rF (rope = INr) THEN
agendaItopeJ := contacto
{primer contacLoJ
:-SE
::GIN
terminar := FALSE;
; := rNI; iprimera posicion de la
I ----
agenda)
REPEAT
rF (agenda [j,1] > contacto t1l ) THEN {es eI sitio}
BEGIN
FOR i:= tope DOI^INTO (j + 1) OO
{se desplazan 1os elementos para hacer hueco]
agendalij := agendati _ 1l;
t.erminar := TFUE;
END
:LSE
J := J + 1;
I,

_liTIL (terminar) OR (j t^*^\


-- LUPe/ /'
:_erroa[]J
--^-l- rtl
:= COnLaCtO; {Se inserta el element.oi
:-: ]LSE}
,- t,ievoAlumno)
284 Alconrrvros DE nsquroa y ononNtcrN

PROCEDURE Mostr:arlistin(Agenda: TAgenda; tope: TTope) ;


VAR
l lr a^

BEGIIi
_a -_:F= <> pred(INI)) THEN
_- _-- 1 := INI co tope D0
writeln(agendali, ll,,,, agenda li,Zl
:LSE
writeln(,El listin esta vacio,) ;
END;

BEGIN {Programa principal}


tope : = pred (fNf ,
REPEAT
MostrarMenu (op) ;
CASE (op) oF
1
I. . DETI]
DEUAI!

Leercontact.o ( contacto ) ;
NuevoContacto(agenda, tope, contacto)
END;
2 : Mostrarlistin(Agenda, Tope)
END
-.ll\TTIL op = 3
:1--

L_\_ . programa prrnclpai


i
ltl

-
8.5.9 Representacin grfica del algoritmo mergesort
--
En este ejercicio, tambin hemos aprovechado el cdigo ya implementado en los e.-- -_l

cicios de representacin grfica anteriores. A continuacin se listan los segmento:


-: W
cdigo nuevos.
T

?ROCEDURE Dibujarlimites (izq, centro, der: Tlndice) ;


D

CONST
r(
= ' [';
CAR1
II
CAR2 = 'l';
BEGIN
IF
writeln(CAR1: izq*3 - 1, CAR2: (centro - izq) *3 + 2,
CAR1, CAR2: (der - on+-rn\*?
vearerv/ J --l\ Ll
rmj
END,- {Oibuj arl,imites }
Dil
re
PROCEDURE Fusion(v: TVector; iz, ce, de: Tlntervalo;
Flrc
Sot ucrol.Bs 285

VAR w: TVector);
VAR
i, j, k: pred(PRIMERO) . .succ (ULTIMO) ;
BEGIN
i :=
). ruvv
l orr i\uu/
o\ .
,

v .- :-.
WHILE (i <= ce) AND (j .= de) DO BEGIN
TEl (v[i] < v[j]) THEN BEGIN
--rt-l Tt l
WLJII := VLI,] ;

r.l .- ^,,^^/.1\
.- Duuu\al
END
ELSE BEGIN
w[k] := v[j];
j := succ(j)
END;
k := succ(k)
END; {WHILE i
k .:= Ji ro de D0
.FOR
-.. ,.

wlkl := v[k] ;
FOR k := i TO ce DO
w[k + de - ce] := v[k] ;
:. -; tuSIOn-|

.: l:EDURE Mergesort (VAR TlnLervalo);


::
tentro : TInt.ervaIo;
-t--\T
_ _,-_-!

-entro := (izq + der) div 2;


:iteln ('Mergesort :, ) ;
- :orimirVector (v) ;
--cujarLimites(j-zq, centro, der) ;
-:: ll n.

-: (izq < centro) THEN


ilergesort (v, irq., cent.ro) ;
:: succ(centro) < der THEN
iiergesort. (v, succ (centro) , der) ;
- -:eln ('Fusion: ' ) ;
--::imirVector (v) ;
, -: *_ arLimites (izq, centro, der) ;
- -:- _
- . i: r: /v,
irq,, centro, der, v)
Ar,conrrnros DE nsqunnl y ononNlcrN

END; {llergesort i

BEGIN iPrograma principal)


PedirVector (vector) ;
Mergesort (vector, PRIMERO, ULTIMO) ;
ImprimirVector (vector )

END. {Programa principa}i

r reglst
Ja uno
Para c

tendr
o

r lVombr

no
nor

LS
'refdentit
fdent i fi
c
qror eI pro
I&porantr
idenfcac
rdenri.ficad
Captulo 9

Registros

'siones para poder representar


la informacin de forma adecuada es necesario
----r1r diferentes tipos de datos. Es el caso, por ejemplo,
de una
: que todo nmero de telfbno almacenado debe llei'ar asociadoagenda telefnica,
un nombre. para
r:rrar esta necesidad existen Jos
regtsfros.

Descripcin del tipo registro


':-':iro tipo de dato estructurad,o que permite almacenar
es un
datos hetetogneos.
- -;
no de estos datos se denomina campo del
registro.
Para detrnir un trpo de dato registro en Pascal se emplea la palabra
reservada RECORD
-::cedida por el nombre que tendr
el tipo de dato. A continuacin se indican los campos
- - tendr el tipo registro mediante los identificadores de campo y
los tipos de datos
'ciados a estos ltimos. La deflnicin termina con la palabra reservada ElD.

--=:
fNombreRegistro = RECORD
nombref dentif icadorl : Tipoldent i f i cadorl ;
nombre Ident i f i cado12 : Tipoldenti f icad.or2;

nombreldentificadorN: Tipofdentif icadorlV;

istro es el nombre del tipo de dato registro que se desea definir. Los
-::ntificador, corresponden a los identificadores cle carlpo del e_cistro. Los
:ficador, son los tipos de datos, predefinidos de pascar. definiJos previa-
: : el programador o annimos, asociados a ios
canlpos del re-eistro.
n mismo .-oir,.o nol;;;., utilizar el
: - --:-
::ntificador de campo, aunque dos campos de regists
clistintos pueden tener el
-- rriticador.

281
Rocrsrnos
288

CONST
N = 30;

D - 1.
Lv t

TYPE
TNombre = string [N] ;
TDNr = string [D] ;
TAsignatur5 = 1' '8;
OF real;
fNots = ar:ay lTAsignaturasl
TEmpleado = RECORD

Nombre,APellido: TNombre; {Nombre}


DNI: TDNI; {del emPleado}
END; {rnmPleado)
TA]UMNO = RECORD
Nombre: TNombre; {Nombre
de} alumno}
DNI: TDNI;
Notas: TNotas; {tlotas}
END; iratumno)

9.2 OPeraciones
englobar .
que se pueden realizar sobre los registros se pueden
Las operaciones
y operaciones de asignacin'
;;;, .,o"ruciones de acceso
g,Z.l Acceso a los campos de un
registro
se utiliza el oPeradot
Para acceder a un campo
de una varilbil de tipo registro
y el identiflcador de
"." entre el no*f'" de 1a variable' de tipo registro'
punto
que se desea tener accestl'

variableRegi stro' identi f icadorCampo

Lasoperacionesdelecturayescrituraestndardeunavariabledetiporesl.-
sobre un:i*p"
utr !.'rvv u"
realizan campo a campo' )oDttr Ll1-'ff:l':::iTl:"i;:H:,;-
'smo tipo. Ejen-:
que se utilizan con variables
de su mrt
aplicar todos los op"tuio'"'

PRoGRAlvl EjemPlo01;
!:!L
rri emoloReq= REi'uKU
entero : integer;
^^r-^-or.Chaf;
LdIqUUU!.

-1.

VAR
Oprn,lcroNns 289

:jemplo: TEjemploReg;
I . inlano-.
+rugY!!,

:: char;

(i < ejemplo.entero) THEN


writeln(,EI valor mayor es ,, ejemplo.entero);
t_-

.,1.2 Asignacin
: :uede da valor a un registro de dos fbrrr
: , inicializado, o
asignado varores
orro regisrro com-

Registro compreto: si ras dos


".;;;':I#'"-ffi':"jiJ::""o
variables de tipo registro son
de tipos idnticos.
VAR
regl, reg2: TEjemploReg;
BEGIN

regl := reg2;
END.

Campo a campo: se selecciona


el campo del registro y se realiza la asignacin
..'uual que en variables
del
tipo de dato O"l.u_po.

PROGRAM Ejemp1o02;
CONST
N = 1n.
INI = ,
FIN = q.
TVDtr

TDigitos = INI..FIN;
TCadena= string [N] ;
TDNI = array [succ(INI)..FIN]
OF TDigiLos;
TDatospersonales = RECORD
nombre: TCadena;
dni : TDNI;
END;
',/AR
290 REGrsrRos

persona: TDatosPersonales;
i, j: inceger;
DET\]
DLU T I\
readln (persona . nombre ) ;
FOR i := succ(INI) T0 FIN D0
BEGIN
read (j ) ;
persona.dniIi] j
END;
'=
END.

Para dar valor al campo dni del registro persona es necesario hacerlo componen..
a componente ya que se trata de un tipo de dato array.

9.3 Registros como parmetros


Para ufilizar los registros como parmetros de subprogramas es necesario que el tipo c.
los parmetros formales sea idntico al tipo de los parmetros reales. Las funciones r
pueden devolver una variable de tipo registro, porque solo devuelven valores simples.

PROGRAM EjemploO3;
CONST
N = 30;
M = 7'
TYPE
TCadena = string [N] ;
TMatricula = srring [M] ;
TCoche = RECORD
marca, modelo : TCadena;
END; {tCoche}
TAutomovil = RECORD
matricula : TMatricula;
nombre : TCoche; {Reg. Anidados}
^-^^.i ^ : ral_
END; {rautomovil}

...:
:oche1: TAutomovil;

??l:a-r-TRE AsignaNombre (VAR coche: TCoche)


DE^-\'
DLU--_.
LA TNSTRUCCIN WITII 29t

:'Tn.

:iGIN

AsignaNombre ( cochel . nombre) ;

t1-

9.4 La instruccin WITII


?.rra evitar 1a repeticin del nombre de la variable de tipo registro cuando se utilicen
.eguidamente varios campos de un mismo registro se puede emptear 1a instrtccinWITH.
.rendo su sintaxis:

', --T\1 warra\:r\eRegrsLro DO


: *_ Instruccin

-s identificadores que no sean selectores de campo se tratan como si no existiese la


lrtIlICClOfl W1'.t'H.

.:ICEDURE AsgnaNombrel (VAR coche: TCoche) ;


:]lTIT
_ Jrt!
-
WITH coche D0
BEGIN
readln (marca) ;
readln (modelo) ;
END;
r'--l ,

;:ICEDURE AsignaNombre2 (VAR coche: TCoche) ;


:: --11\
readln (coche.marca) ;
readln (coche. modelo) ;

- 's procedimientos AsignaNombrely AsignaNombre2 hacen exactamente lo mismo.


Es posible utllizar lainstruccin l,,irrH con varias variables de tipo registro,
siempre
'-- no posean identificadores de campo idnticos. En ese caso el compilador es incapaz
-. discernir a qu variable de tipo registro se refiere el ccligo.
292 Rpcrsrnos

9.5 Registros variantes


Los re-eistros con parte variante son registros que tienen una parte comn (parte lijat
y otra parte que puede contener campos diferentes (parte variante). Se declaran de un
modo similar a los registros fijos excepto porque poseen un nico campo especial, campo
discrirninante, con uno o ms valores que definen los campos variantes. La declaracin
de la parte variante se realiza a continuacin de la de los campos fijos' Para eilo, se
cleclara el campo discriminante que solo puede ser de tipo ordinal simple, seguido por
las partes variantes que deseemos que tenga el registro. Dependiendo del valor que tome
el campo discriminante el registro almacenar una informacin u otra. En cualquier
caso, la memoria reservada para una variable de este tipo de dato es la correspondiente
al mximo nmero de campos, es decir, el espacio de almacenamiento es fijo.

TYPE
TNombreRegistroVariante = RECORD
nombreldentif icadorl : Tipoldentif icadorl ;
nombreldentif icador2 : Tipoldentif icador2 ;
CASE nombreDiscriminante: TipoDiscriminante 0F
<val-or-simp1e1> : (Identl-variantel : Tipoldentl-variantel;
IdentM-variantel, tipofdentM-variantel ) ;

<valor-simpleN>:(Identl-varianteN:TipoIdentl-varianteN;);
EI'ID;

p-'-
Ha' que tener especial cuidado a la hora de acceder o asignar informacin a la
variante. Cuancio se -Quarda informacin no se debe olvidar asignar el valor adecuad
campo discriminante. Antes de acceder a la informacin siempre se debe consultar
d:"'
campo. De 1o contrario pueden producirse efectos no deseados durante la eject''
dei programa, es necesario tener en cuenta que se tratar de interpretar la informr-
aunque el tipo de dato no sea el adecuado.

CONST
N = 40;
TYPE
TNombre = strng [N] ;
TForma = (Libro, Articulo) ;

TDia = 1..31;
l}les = 7..L2;
lAnio = 1900..2240;
_FEChA = RECORD

-Ia: I'lJla;
l,les : TMes;
ARRays PARCIALMENTE LLENoS 293

lsr\o'. \Nrr\o;
E\tn -

.. \!u\\\catlorl = \Lq\\
, li- \i'' \rsr'. Nssre., ant-e. Lr\a\1
..ampO Titulo: TNombre;
iracin Paginas: integer;
ello, se CASE Tipo: TForma OF iParte variante)
uido por Libro: (Editorial : TNombre;
lLie tome Anio : TAnio);
:,raiquier Articulo: (Periodico: TNombre;
,rtndiente Dia: TFecha);
END; {fnubticacion}

9.6 Arrays parcialmente llenos


:n el captulo 7 se ha introducido el concepto de array parcialmente lleno. Gracias a los
:gistros es posible agrupar las dos componentes de este tipo de dato como una sola. Es
-1.
.=Lt
-:'.ir. se puede definir un nuevo tipo de dato registro con dos campos: uno para el aray
, )tro para el campo que seala la parte ocupada.

INI
trTT\T

.-ta
TRango = INI..FIN;
TArraY = array [TRango] OF rea];
lArrayParcial = RECORD
vector: TArray;
tope: pred(INI) ..FIN; {Debe existir un val-or que indique}
iND; {que eI array est. vaco}

q.7 Cuestiones de tipo test


- -.1 Enunciados
, >iguientes cuestiones pueden tener una o ms respuestas correctas.

La siguiente deflnicin:

:'JPE
rFD a
r r\uY -- RECORD
CASE tipo: TForma OF
REGISTROS
2g4
libro: (editorial: stringll5i ;

fecha: TFechal);
articulo: (Periodico: string[25i ;

fecha: TFecha2) ;
END;

vadante'
(a) Es incorrecta porque solo tiene pafte
(b)Esinconectaporquenopuedehabernombresigualesendospafiesvaflan:-' e ! -:
de las dos pafles variantes flo
(c) Es incorrecta porque e1 campo fecha
mismo tiPo'
tener parte fija'
(d) Es correcta porque no es obligatorio

2. ResPecto a los registros:


de tipo registro'
(a) Un campo de un registro no puede ser
tipo conjunto'
(b) un campo de un registro puede ser de
para especificar dos campos distir-'
(c) No pr". usarse el mismo identificador
de un registro' r -r ^-" r^ ---
(d)Aunavariabledetiporegistrosiempreselepuedeasignarelvalordec*_
variable de tiPo registro'

3.,CulesdelassiguientesafirmacionesreferentesaunregistroenPascalson.l:.
tas?
ser de distinto tipo de datos'
(a) Todos los campos de un registro deben
compatibles la instruccin r-
(b) Si 11, y 12 son variables registro de tipos
r2 es correcta'
una variable selectora'
(c) Todos los registros variantes han de incluir
de almacenamiento que '
(d) Los registros variantes requieren un espacio
'

entre un valor mnimo Y uno mximo'

de tipo y el cdigo adjunto:


4. Dada la siguiente declaracin

TYPE
rAro = RECORD
campol : integer;
CASE camPo2: boolean OF
TRUE: (camPo3: integer) ;

FALSE: (camPo4: char);


END;
-";i.
-" lHIY I
CunsrroNrs DE TIPo rEST 295

]i E
!g TlT
rr\

,."r*pof := 3;
u.camPo2 := TRUE;

:ND.

.,Es correcto hacer en el programa principal u. campo3 , = ' 9' ?


(a) No, y produce un error de ejecucin.
(b) Es correcto porque se reordenan los bits.
(c) No es cor:recto y nos da un er:ror en tiempo de compilacin.
(d) Es cor:recto por el valor que toma u. campo2.
j. Teniendo en cuenta que TMiRegiscro es un tipo registro con tres campos enteros,
el siguiente fragmento de cdigo es correcto?

jUNCTION SumaDato(regEntrada: TMiRegistro; dato: integer) :

TMiRegi stro;

(a) Es incorecto ya que una variable de tipo RECORD no se puede definir como
un argumento.
(b) Es incorrecto porque una funcin no puede devolver un valor de tipo RECORD.
(c) Es correcto siempre que el tipo de datos TMiRegistro est def,nido.
(d) Es correcto ya que una funcin puede tener parmetros de tipo de dato
RECORD e integer.

La instruccin WITH se puede utilizar:

(a) Con varias variables de tipo registro con los mismos identif,cadores de campo.
(b) Con variables de tipo array, permitiendo el acceso a sus componentes utili-
zando nicamente el tipo ndice.
(c) Con varias variables de tipo registro si no tienen parte variante.
(d) Con varias variables de tipo registro con identificadores de campo diferentes.

-'.2 Soluciones

- . La afirmacin (d) es la correcta.


En un registro con pefie r ariante no es necesario
que exista una parte flja. Los identificadores que se utilicen dentro de 1as partes
variantes no tienen por qu ser nicos ni coincidir en e1 tipo de dato.
l, Las opciones (b) y (c) son colrectas. Se pueden hacer declaraciones de registros
anidados. Para que a una variable de tipo registro se le pueda asignar el valor de
otra variable de tipo registro, los tipos deben ser idnticos.
296 RBcISrnos

1
--) - La respuesta correcta es la (c). La nica restriccin que existe sobre los campo:
de un tipo registro, es que no pueden declararse de tipo fichero (captulo 10). I-r,
memoria que se reserva para una variable de tipo registro es constante. para que
la asignacin de la opcin (b) fuese correcta, las variables deberan ser de tipo:
idnticos.
4. La respuesta correcta es la opcin (c). El campo del registro campo3 es de tipi
entero, cualquier asignacin de otro tipo no esta permitida, adems la asignacir
y comprobacin de tipos se realiza en tiempo de compilacin.
5. La opcin correcta es la (b). Los registros, al igual que otros tipos de datos, puecle r

ser argumentos en funciones y procedimientos siempre que estn definidos. e.


decir, no sean tipos annimos. Las funciones no pueden devolver ninguna cla:.
de tipos compuestos.

6. La respuesta correcta es la opcin (d). Si los identificadores de campo son idnr:-


cos, el compilador no distingue la variable a la que se desea hacer referencia. \
se puede utilizar sobre variables de tipo affay en la lbrma descrita. La instruccii,.
WITH se puede utllizar con registros variantes.

9.8 Problemas
9.8.1 Declaracin de un tipo registro simple
Escriba una declaracin de tipo registro que almacene la siguiente informacin sobre u.
disco de audio: ttulo, autor, ao de publicacin y duracin en segundos.

9.8.2 Declaracin de un tipo registro con parte variante


Declare un tipo TEstudiante que contenga la siguiente informacin:

1. Nombre (hasta 30 caracteres).


2. Direccin (Calle, nmero. ciudad y cdigo postal).

3. Nmero de Telfono.

4. D|T.

-5. Califlcaciones de las asignaturas (una lista de hasta2l elementos conteniendo .


nombre de la asignatura y un carcter para la puntuacin).
6 Si el alumno es repetidor de alguna asignatura debe almacenarse el nmero :,
convocatorias consumidas (una lista de hasta2'7 elementos conteniendo el nomb:.
de Ia asignatura y un entero para el nmero de convocatoria).

\rta: Cada re-uistro delinido por el usuario debe tener una defrnicin separada.
Pnosr,nN{,{s 297

9.8.3 Visualizacin del contenido de un registro


Escriba un programa que lea informacin sobre un registro,
del tipo definido en el pro-
blema 9.8.2, y luego la visualice.

9.8.4 Correccin de errores


Identifique y corrija los errores del siguiente programa:

PROGRAM Informe;
TYPE
TCadenal5 = string tfS1,
'.t"1ar1ta = RECORD
nombre: TCadena*15;
fecha : TCadena*15;
horas : real
END;
VAR
operador: TTarifa;
BEGrN i1:,_:..
\
lrtITH TTarifa DO
BEGIN
nombre:=,Hotef Villarosa, ;
f echa : = ,,Junio 5, 19g9,,T ;
horas := 30.5
END;
writeln (operador) x
END" {Informe}

9.8.5 Clases de aerobic

En un gimnasio hay un grupo de aerobic con las plazaslimitadas


a 30. aunque Llurante el
'-urso el nmero de alumnos matricurados vara mucho. E1 gimnasio
:n la que se almacena informacin sobre los alurnnos. Los
por.. ,r, agencra
atos que se alnracenan por
;ada alumno son el nmero de telfbno, er nombre y
el dni. Este irrmo carnpo es er que
e utiliza para mantener ordenada la agenda en
memoria principal. Sepide:

o Defina los tipos de datos adecuados.


o Implemente un subprograma que aada un nuevo
arumno a ra a-eenda de la forma
ms eficiente pos;ble (recurdese que la agenda
debe continuar ordenada). Indique
el orden de complejidad del algoritmo.
298 Rncrsrnos

Implemente el algoritmo de bsqueda ms ehciente que pueda trabajar sobre esre


tipo de datos. Para que la bsqueda sea eficiente, debe realizarse en funcin del
campo en el que se ha ordenado la agenda. Indique el orden de complejidad.

9.8.6 Mensajes en un telfono mvil


Se desea realizar un programa que simule un gestor de mensajes de un telfono mvil.
Para ello se crearn dos memorias de mensajes, una para mensajes entrantes y otra para
mensajes enviados. Cada uno de las cuales tendr capacidad para guardar cinco men-
sajes. Tambin se tendr una agenda. con capacidad para 20 nmeros de telfono. el
1a que se almacenar el nombre y el nmero de telfbno de los contactos (esta agencl;
estar ordenada alfabticamente). La informacin de cada mensaje se almacenar en ur:
registro que contendr los siguientes campos:

o Texto: contendr el texto del mensaje (como mximo 255 caracteres).


o Fecha y hora de envo: La fecha y la hora a la que se envo el mensaje.
o Identificacin: esta ser un nombre de usuario que se localizar en la agenda de
telfono. En caso de no conocer al usuario (no tenerio almacenado en Ia agend-
de telfonos) ser el nmero de telfono del que procede el mensaje o el nmer
de telfono al que enviamos el mensaje.

Funcionalidades del telfono:

o Agenda:

- Aadir un nuevo contacto: para poder aadir un nuevo contacto primero ..


debe comprobar que hay sitio libre en la agenda. Si no lo hay se debe ofrec
al usuario la posibilidad de eliminar un antiguo contacto o abandonar. L
datos que se le solicitarn sern el nmero de telfono y el nombre del nue.
contacto.
- Eliminar un contacto: esta operacin sepodr realizar de dos formas. Una *.
ellas ser introduciendo el nombre del contacto a eliminar. La otra ser nr,..
trando por pantalla los nombres de los contactos almacenados y preguntan;
al usuario si desea eliminar ese contacto.

o Mensajes:

- Enviar un mensaje: Si se desea enviar un mensaje de texto desde el telfor


debe aparecer la opcin de enviarlo a un nmero de la agenda o a un te .
fono que no est guardado en la agenda. El mensaje enviado se almacen-
en mensajes enviados de forma automtica, por 1o tanto antes de enviar -'
n-iensaje si la memoria de mensajes enviados ya est llena deber limpia:..
Esto aparecer como opcin ante el usuario que escoger entre eliminar .
dos los mensajes o eliminar un mensaje ccncreto de todos los almacenad,
Pnosr,N{as 299

It l! l)
,,
r..
I
rrr .J
aa
aa
aa
*a
*aa
aaa

1...
Jo l: : aa
*a
aa
aa
a*a
**a

Figura 9.1: Evitando la Recursividad

- Recibir un mensaje: Para poder recibir mensajes, tambin se tendr que tener
hueco en la memoria destinada a tal fin. Pero en este caso cuando la memoria
est llena se avisar al usuario cada vez que este realice cualquier operacin
en el telfono.

\'uda: Para introducir el tiempo en la informacin que se guarda de los mensajes, se


-ttlizar la librera Dos de Turbo Pascal. Para ello despus de escribir la cabecera del
-rograma aparecer la siguiente lnea de cdigo: USES Dos; De este modo el compila-
-'lr permitir utilizar los procedimientos GetDay y Get.Time, que proporcionan la fecha
La hora del ordenador (la cual se tomar como fecha y hora a la que se ha enviado o
:cibido el mensaje). Los parmetros que devuelven estos procedimientos son de tipo
,. ord, enteros positivos, siendo sus cabeceras:

'=:Day(VAR anio, mes, dia, dia_semana: word);


.=:Time (VAR hora,
--ruto, segundo, cent_segundo: word) ;
:.ndo los rangos de valores, para el procedimiento GetDay: El ao: 1980..2099 El mes:
12 El da: 1..31 El da de la semana: 0..6 (siendo 0 el domingo)

),8.7 Evitando la recursividad


-. algunos alumnos de Ingeniera Informtica no les gusta utilizar la recursividad. Por
. lo han desarrollado un sistema para evitarla. Cada vez que necesitan emplear llama-
-:\ recursivas en algn subprograma, construyen un tipo de dato que se "encarga" de
-..tituirlas. Este tipo de dato no es ms que un array parcialmente lleno que almacena
"::istros con informacin sobre la "llamada" recursiva. Solucionar ei si_suiente problema
:lizando este tipo de estructura: Supongamos un barrio con sus calles. Queremos ir de
- punto inicial (A) a un punto final (B). Escribir un subprograma que cuente el nmero
-: :aminos posibles que hay entre los dos puntos suponiendo que solo podemos ayanzar
direccin norte y en direccin este. Hacer un programa que pida el punto inicial y el
' ,lto final y use el subprograma para decimos cuantos caminos posibles
hay. Fjese en
:lemplo de la figura 9.1.
RBcrstnos

9.9 Soluciones

9.9.1 Declaracin de un tipo registro simple

CONST
N = 30;
A.

TYPE
TTitulo = string [N] ;
TAutor = TTitulo;
TAnio = string [C] ;
TTiemPo = real;
TDiSCO = RECORD
titulo: TTitulo;
autor: TAutor;
anio: TAnio;
duracion: TTiemPo;

g.g.2 Declaracin de un tipo registro con parte variante

CONST
N = 30; {Para }a longitud del nombre}

v --
q.
't
INI = 1;
FIN = 27;
FIN-N = 2000; {mximo numero de casa)
FIN-C = 9999; imximo numero de cdigo
postali
ul,t = o; {mximo nmero de convocatorias}
TYPE
TNumeTO = INI. 'FIN-N;
TCodigo = INl..FIN-C;
TNombre = string [Nl ;
TTeIefono = string [Cl ;
TDni = TTelefono; {Para que el dni incluYa }a
letra)
TRango = INI. .FIN;
TRango2 = INI. .ULT;
LInfO = KI.\-UK!
tombre: 'I'NomDre;
Sor,ucroNrs 301

nota: char;
END;
TRepe = RECORD
nombre: TNombre;
Conv: TRango2;
END;
TAsignaturas = array [TRango] OF Tlnfo;
Tconvocatoria = array lTRangoJ OF TRepe;
TDireccion = RECoRD
calle, ciudad: TNombre;
numero: TNumero;
codigo: TCodigo;
END;
TEstudiante = RECORD
nombre: TNombre;
direccion : TDireccion;
telefono: TTelefono;
dni : TDni;
asignaturas : TAsignaturas;
CASE repecidor: boolean OF
TRUE: (convocatoria: TConvocatoria) ;
END;

9.9.3 Visualizacin del contenido de un registro


PROGRAM Ejemplo3;

{Dectaracin de tipos deI ejercicio 9.8.2}


isubprogramas para
introducir inf ormacin)
PROCEDURE IntroduceNombre (VAR nom: TNombre) ;
VAR
c . 1r r .

3EGIN
REPEAT
wrrte (,Inrroduzca e1 nombre: ,);
readln (nom) ;
writ.e ( ,El nombre es : si es correcto pulse s') ;
readln (c) ; "/nom''
LTIT]L c IN [,S,,,S,]
302 RBGISTRoS

END; ilntroduceNombre)

Flll\CTION IntroduceNumero : TNumero;


VAR
.l .iranar.
rlruuYUr,
s: string[4] ;
code: integer;
BEG]N
REPEAT
write (' Introduzca el numero: ' ) ;
readln (s) ;
va} (s,i,code);
IF code <> 0 THEN {Se na producido error)
i .= pred(INI);
r,lJTrL (i > pred (rNr ) ) AND (i < succ (FIN_N) )

InLroduceNumero : = i
END; {IntroduceNumero}

Fll-NCTI0N IntroduceCodigo : TCodigo ;


VAR
i i raav.
tlluuYL!,
a. ctri
UU!TIY na ll
L J
l
,

code: integer;
BEGIN
REPEAT
write ('Introduzca eI codigo postal:
readln (s) ;
val (s,i,code);
IF code <> 0 THEN {Se na producido error}
i ;= pred(INI);
UNTIL (i > pred(INI)) AND (i < succ (FIN C));
IntroduceCodigo : = i
END; {IntroduceCodigo}

PROCEDURE IntroduceDireccion(VAR dir: TDireccion) ;


BEGIN
writeln ('Nombre de Ia ciudad: ' ) ;
IntroduceNombre (dir. ciudad) ;
writeln ('Nombre de Ia calle: ' ) ;
IrtrcduceNombre (dir. cal1e) ;
Cir.numero := IntroduceNumero;
J-r.codigo := IntroduceCodigo

h,
Sor,ucroNns 303

IND; {IntroduceDireccion}

?ROCEDURE IntroduceTlf (VAR tlf: TTelefono) ;


.,.4R

^.
U. ^t^--. ,
UIIAI

:EGIN
REPEAT
write ('lntroduzca eI numero de telefono: ');
readln (t1f) ;
write ('E1 telefono es : ' ,LLf,' si es correcto pulse s');
readln (c) ;
IN [,S,,,S,]
UNTIL C
:){D; {Introducerlf}

IROCEDURE IntroduceDNl(VAR dni: TDni) ;


..AR

. ]n=v.

:JGIN
REPEAT
write ('rntroduzca el numero del D.N.I. : ') ;
readln (dni) ;
write('El D.N.r. es: ',dni,' si es correcto pulse s');
readln (c) ;
UNTIL c IN ['s','S']
:)JD; {IntroduceDNI }

-J'IJCTI0N
r Nota : char;
_'tD

^ D-. .
U, ^t--.
UIIAI ,
]fTTT
- -gII\

REPEAT
write ('Introduzca la nota: ') ;
readln (c) ;
write ('La nota es: ' , c,' si es correcto pulse s' ) ;
readln (s) ;
UNTIL s IN l's' ,'S') ;
IT^l
IIULA - . - L

:)'TD; {Xota}

;?OCEDURE Introducelnfo(VAR info: TInfo) ;


:iGIN
IntroduceNombre (info.nombre) ;
304 REGTSTROS

info.nota := Nota
END; {tntroducetnfo}

PROCEDURE IntroduceAsignaturas (VAR asig: TAsignaturas) ;

VAR
i: TRango;
BEGIN
FOR i- : = INI T0 FIN D0
Introducelnfo (asig lil )

END; {IntroduceAsignaturas}

FUNCTION NumeroConvo: TRango2 ;

VAR
i : integer;
s: string[4J ;
code: integer;
BEGIN
REPEAT
write('Introduzcaelnumerodeconvocatoria:');
readln (s) ;

VaI ( s, i, code) ;
IF COdC <> O THEN {se tra producido error}
i = pred(INI) ;
LINTIL (i > pred (INI ) AND (i < succ (ULT) ) ;
)

NumeroConvo : = i
END; {Numeroconvo}

PROCEDURE IntroduceRepe(VAR repe: TRepe) ;


BEGIN
IntroduceNombre (rePe. nombre) ;

repe.conv := NumeroConvo
END; {IntroduceRePe}

PROCEDURE IntroduceConvocatorias (vAR convo: TConvocatoria) ;

VAR
i: TRango;
BEGIN
FOR i : = INI T0 FIN D0
rntroduceRePe (convo Ii1 )

ElD ; { In[roduceConvocatorias ]

pRocEDURE lntroduceEstudiante (vAR esEudiante: TEstudiante) ;


SolucroNrs 305

--- D

l'r:r.

: IGIN
writeln ('Introduzca los datos del estudiante') ;
InLroduceNombre ( estudiante. nombre) ;
Int roduceDi recc ion ( estudiante . direcc ion ) ;
IntroduceTlf (estudiante. telefono) ;
IntroduceDni (estudiante . dni ) ;
writeln('Introduzca los datos de las asignaturas');
IntroduceAsignaLuras (estudiante. asignaLuras) ;
REPEAT
write (' Es repetidor (sln) 7 ' '
readln (c) ;
IINTIL c IN l's' ,'S' ,'r,' , 'N'] ;
estudiante. repetidor : = (c IN l' s' , 'S' I ) ;
IF estudiante.repetidor THEN
BEGIN
writeln ('Introduzca datos sobre l-as convocatorias:' )

IntroduceConvocaLorias ( estudiante . convocatoria ) ;


END

- : t-Lntroduce!;studlanteI
l_ )

!*oprogramas para mosLrar informacin)

:: -:EDURE MuestraNombre (nombre: TNombre) ;


- -17
,:: ,__L\

writeln (nombre)
:-l; {MuestraNombre}

.: -:EDURE MuestraNumero (num: integer) ;


I_ _: __-_r!
-tT

writeln (num)
:- -; {MuestraNumeroi

.:,:EDURE MuestraDireccion(dir: TDireccion) ;


:t--\1
, ,__L!

de la ciudad: ')
u^/rite ( 'Nombre ;
l,1ue (dir.ciudad);
straNombre
write ( 'Nombre de la cal-le: ' ) ;
lluestraNombre (dir. calle) ;
rvrite ( 'Nmero: ,);
l'luestraNumero (dir.numero);
306 Rpcrsrnos

write ('Cdigo postal: ,) ;


MuestraNumero (dir. codigo)
END ; {MuestraDireccion}
PROCEDURE MuestraTelefono (tIf: TTelefono) ;
BEGIN
writeln ( tlf )

END; {MuestraTelefonoi

PROCEDURE MuestraAsig (info: TInfo) ;


BEGIN
write('Nombre: ,);
MuestraNombre ( inf o. nombre) ;
write('Nota: ,);
writeln ( info. nota)
END; {MuestraAsig}

PROCEDURE MuestraAsignaturas (asig: TAsignaLuras) ;


VAR
i: TRango;
DD T\T
U!UAI\
writeln (,Listado de asignaturs: ,
) ;
FOR i : = INI T0 FIN DO
MuestraAsiS (asig Ii] )

END; iMuestraAsignaturas )

PROCEDURE MuestraConvo (r: TRepe) ;


BEG]N
write('Nombre: ,);
MuestraNombre ( r. nombre) ;
write('Convocatoria:, ) ;
writeln(r.conv);
END; iMuestraConvo)

PROCEDURE MuestraConvocatorias (asig: TConvocatoria) ;


VAR
i: TRango;
:]-TTT
-- .--aL\
writeln (,Listado de convocatoras consumidas: ,) ;
FOR i : = INI T0 FIN DO
MuestraConvo (asig Ii1

END; {MuestraConvocatorias}
Sor,ucroNrs 307

?R.OCEDURE MostrarEstudiante (estudiante: TEstudiante) ;


3EGIN
writeln ('Datos del estudiante: ' ) ;
write('Nombre:');
MuestraNombre est.udiante . nombre ) ;
(

MuesLraDireccion ( estudiant.e . direccion) ;


write('Telfono:');
MuestraTelef ono ( estudianLe . telef ono) ;
write('Nmero del D.N.i.: ');
MuestraTelefono ( estudiante . dni );
Muest raAs i gnaturas ( estudi ante . as ignaturas ) ;
IF estudiante. repetidor THEN
Mue straConvocatorias ( estudiante . convocatoria )

IND; {MostrarEsrudiante}
...4R

e1 : TEstudiante;
:EGIN {Programa Principal}
IntroduceEstudiante (e1) ;
MostrarEsrudiante (e1 ) ;
:-\l_). t Programa Prlnclpa_L )

9.9.4 Correccin de errores


o El primer error aparece en la primera lnea:
PROGRAM Informe.
Falta el ";", la forma correcta es:
PROGMM Inf orme; .

o El siguiente er:ror se encuentra en la declaracin del tipo TTarif a:

TTarifa = RECORD
nombre: TCadena 15;
fecha : TCadena 15;
horas : real
END;

TCadenal5 debe ir todo junto. Forma correcta:

TTarifa = RECORD
308 Rncrs:rnos

nombre: TCadenal5;
fecha : TCadenal5;
horas : rel
END;

o A continuacin, se confunde la variable con el tipo de dato:

WITH TTarifa D0

TTarif a es un tipo de dato, el nombre de la variable de ese tipo es operador. De


modo que la forma cor:recta es:

WITH operador DO

Seguidamente encontramos un cierre de parntesis en la asignacin de valor de


una cadena de texto.

fecha := 'Junio 5, 7989');

Este parntesis hay que eliminarlo.

fecha := 'Junio 5, L989' ;

En el primer END del programa no aparece el ";", y sin embargo hay una instrue -
cin a continuacin. Para que el cdigo compile debemos introducirlo.
La itima instruccin del cdigo writeln (operador) es una operacin errnea
El tipo de dato de operador, es un tipo registro sobre el que no se pueden aplicar
directamente las operaciones de entrada-salida. Para que el cdigo funcione ade-
cuadamente y muestre la informacin almacenada en esta variable, se tendr quc
hacer 1o siguiente:

writeln ( operador . nombre ) ;


writeln (operador. fecha) ;
writeln (operador. horas) ;

END. {Informe}{rafta el punto que da


por terminado el programai
De este modo se muestra por pantalla la informacin del dato operador.
Ei 1timo error que aparece en el cdigo es la falta dei carcter "." despus de.
1timo END.
Sor,ucroNns 309

9.9.5 Clases de aerobic


o Primer apartado:

CONST
N = 9;
INI = 1;
FIN = 30;

TYPE
TRango = INI..FIN;
TTeI = string INJ ;
TNombre = string IFIN] ;
TA}UMNO = RECORD
nombre: TNombre;
t1f, dni : TTel;
END;
TPlazas = array [TRango] OF TAIumno;
TAgenda = RECORD
plazas: TPlazas;
num: pred(INI)..FIN; ifuf -:- no hay alumnos
matricul-ados, FIN eI cupo esta completo)
END;

o Segundo aparlado:

PROCEDURE NuevoAl-umno (VAR agenda : TAgenda; alumno : TAlumno )

{lre = alumno contiene los dat.os del nuevo afumno


y hay plazas }ibres en el grupo)
ilost = agenda contiene los datos del nuevo atumno)
VAR
i, j : TRango;
terminar: boolean;
BEGIN
agenda.num := agenda.num + 1; {eorque sabernos
que a1 menos hay una plaza r lore J

IF (agenda.num = INI) THEN


agenda . plazas Iagenda. num] := alumno {norque
CS el primer atumno)
ELSE
BEGlN
terminar := FALSE;
310 RBCrSrnos

j := INI; {Primera Posicion de la agendai


REPEAT
IF (agenda.Plazas tjl .dni. > alumno.dni) THEN

BEGIN
FOR i := agenda.num DOWNTO (j + 1) Do

agenda.plazas IiJ :=agenda.plazas Ii-t]


terminar := TRUE;
END
ELSE
j := j + 1;
uNTrL terminar oR (j = agenda'num);
agenda.Plazas IjJ := alumno;
END i ELSE )
END; {tluevoa}umno}

El orden de complejidad es lineal, es decir, O(n)'


Tercer apartado:
..

FUI{CTION BuscarAlumno (agenda: TAgenda; alumno: TA}umno)


. .l
. -raaar.
aITLUYU!,

{rnu = agenda y alumno son estructuras correctas}


{losr = devuelve pred(INI) si no encuentra e1 alumno'
o Ia posicin en la que se encuentra)
r:^D
r,j,med: TRango;
BEGIN
WITH agenda D0
BEGIN
IF pred(INI) THEN
num =
BuscarAlumno := pred(IITI) ino hay alumnos)
ELSE {matriculados}
BEGIN
i := INI;
j := num;
REPEAT
med := (i + j) DIV 2;
IF (plazas[medl.dni > alumno.dni) THEN
-.1 .- ^ - T

ELSE
i := med +1
UNT]L (i , j) 0R (plazas [med] .dni = alumno.dni) ;
Sor,ucroNos 311

IF (plazas Imed] .dni = alumno.dni) THEN


BuscarAlumno := med
BLSE
BuscarAfumno := pred ( INI )

END{num <> Ped(INI) }


END i !\IrrH )
END; {BuscarAlumno}

Se trata de una bsqueda binaria, que se estudi en el captulo anterior, el orden de


complejidad es O (lo gn).

9.9.6 Mensajes en un telfono mvil


:ROGRAM Mensaj es;
--ltrQ nc.

I3NST {Primero se realiza 1a declaracin de constantes


Lipos de datos que son necesarios]
T\IT - 1.
= ?.
F'T\T
N = 5;
M = q.
- IPE
TCadena = string [N] ;
TTlf = string IMJ ;
TRango = INI..FIN;
TRango2 = INI..N;
TFecha = RECORD
dia: word;
mes: WOrd;
anio: word;
END;
THOrA = RECORD
hora: word;
minutos: word,.
END;
TMensaje = RECORD
texto: string;
fecha: TFecha;
hora: THora;
CASE conocido:boolean OF
TRUE : (identif icacion : TCadena)
3t2 Rncrsrnos

FALSE: (numero:TTlf);
END;
TAlmacen = array[TRango] OF TMensaje;
TMemoria = RECORD
todos: TAlmacen;
tope: pred (INI) . . FIN. {Necesitamos un valor que indique}
END; {que no hay datos}
Tlnfo = RECORD
nombre: TCadena;
LII: TIII;
i
I
END;
I
TContactos = array [TRango21 0F Tlnfo;
TAgenda
= RECORD
cont.actos: TContactos;
max: pred(INI) ..N; {Necesitamos un va}or que indique que}
END; {no hay datos}

PROCEDURE IntroducirNombre (VAR nom: TCadena) ;


I o-- .Prrr, 1
-
{eost = Devuelve un nombre int.roducido por e1 usuario}
VAR
^ .
u. ^L--.
uttql ,

BEGTN
REPEAT
write ('Int.roducir nombre: ,
) ;
readln (nom) ;
writeln ('EI nombre introducido es: , nom,
,
es correcto pulse s');
readln,",,tt
UNTIL c IN ['s','S']
END; { IntroducirNombrei

PROCEDURE IntroducirTlf (VAR t: TTlf) ;


f o-^ -- .orrr.
ir!u rl\u!J 1

{lost = Devuelve un telfono int.roducido por e1 usuario}


VAR
c: Char;
fr.-rT
-!J_r!
.R.EFEAT
write ('Introducir telefono: ,) ;
va,'ll-/r\
!!qurrr\L/ /

writeln('El numero introducido est ,,t,


Sor,ucroNrs 313

es correcto pulse s');


readrn,", r"t
LII]TIL c IN [' s' , 'S, ]
:l,trD; {IntroducirTf f }

:-NCTI0N MuestraOpcionesBorrar: char;


rrA ='l'l?llLl !
^.'--l
?ost = Devuelve la opcin escogida por e1 usuario)
---R

dev: char;
: ] 1T\T
_ _ J11\

REPEAT
writeln ( 'Escoj a una de las siguientes opciones : , ) ;
writeln('1. Int.roducir eI nombre de1 contacto,,
' que se desea eliminar') ;
writ.eln (,2. MosLrar la lista de cont.actos, ) ;
readln(dev);
IJ}'TTIL dev IN l'7', ,2,f; {Se podra aadir una opcin ms para
permit.ir salir sin act.uar)
Muest.raOpcionesBorrar : = dev
:.,1 ; {MuestraOpcionesBorrar}
: : - :EDURE AvisoMemoriallena;
::-r1T
__,-11\
r,riteln('La memoria de mensajes entrantes esta llena,)
. - ; {Avisol,lemoriaLlena}

.: , IEDURE AvisoMensaj eEnviado;


:: l-N
riteln('El mensaje se ha enviado correctamente,)
:.-) ; {AvisoMensaj eEnviado}

.-.: lTlON ModoEnvio : char,.


:_:.

: . 1rr.
91f q! ,

- - -rrnro,
writeln('1. Enviar mensaje a un numero de la agenda,);
wriLeln('2. Enviar mensaje a un numero introducido,,
' por el usuario') ;
readln(a);
-']NTIL a IN l'l.' ,'2,f ;
3t4 RncrsrRos

ModoEnvio : = a
END; {l',1odoEnvio}

FLINC:I-N MenuPpal: char;


f - --
1,t,-L: = --,,-l
IKUrll
{Post = Devue}ve Ia opcin escogida por e1 usuario}
VAR
: . hrr.

BEGIN
writeln ('1. Opciones Agenda' ) ;
writeln('2. Opciones mensajes' ) ;
writeln ('3. salir' ) ;
readln (a) ;
MenuPPal : = a
END; {tutenulpat }

FUNCTION MenuAgenda: char;


o-^ - 'Prru'l
{eost = Devuelve la opcin escogida por el usuarioi
VAR
q ; L110!
^t--. ,

BEGIN
REPEAT
writeln (' 1 Aniadir un nuevo conLacto')
. ;
writeln ('2 Eliminar un contacto ') ;
.

writeln ('3 Salir') ; .

readln (a) ;
UNTIL a IN [' ]-' , tat
L t
t)t1.
J Jt

MenuAgenda : = a
END; ilufenuagenda)

FUNCTION MenuMensajes: char; E]


f -^ - 'Prru \
o

,?cst = Devuelve ta opcin escogida por eI usuario) FI


-.-;-R
{r
G. ^1" - -
LltAr /
.
{r
:::-1. BE
: lltrl.f

rriteln(' 1. Enviar mensaje' ) ; EN


writeln('2. Recibir mensaje' ) ;
i;::iteln ('3. Salir') ; PR(
-- ^ ^ I - / ^ \
- -4sf
- \q/
'
ip,
Sor-ucroNns 315

IINTIL a IN l'1' ,'2' ,'3'f i


MenuMensajes := a
:l,D; {l,,tenulutensaj es }

.]OCEDURE CrearContacto(VAR c: TInfo) ;

?ost = devuel-ve cont completamente inicializado)


:: 1 TlT
__Jrf\

IntroducirNombre ( c . nombre) ;
IntroducirTlf (c. tlf)
:).); {CrearContacto}

':,ICEDURE MostrarContacto
(contac: TInfo) ;
--a -.prrnl
.:st = *r"a.u por pantalla el nombre det contacto]
::. T\T
___-rr\
writeln('Nombre:', contac.nombre)
:l-; {MostrarContactoi

.: ICEDURE CrearAgenda (VAR agenda: TAgenda);


lKUr,JI
_-:e = --rtr
.:st = Se Crea una agenda --^ ^r ^I
vdu_Ld l
-t^Tnf
_ _ if r\

agenda.max := pred(INI)
:--; {Crearagenda}

i -l;CTI0N Esvacia (agenda: TAgenda) : BOOLEAN;


: -'e = TRTTF'. J
.:st = si max = pred(INI), agenda vacia)
:]-TTT
_ _ --rr\

Esvacia := (agenda.max = pred(INI))


''', i tjsvaclaJ
l_ , )

" -I;CTION HaySitio (agenda : TAgenda) : BOOLEAN;


l
--:e = -^,,-
Tl(UEJ
.:st = Si max = N no hay si-tio, en cualquier otro caso si)
: ]_,-at!
_
^ TlT

HaySitio := (agenda.max<>N)
ll; {ttaysitio}
-:,CEDURE InsertarContacto (VAR agenda:TAgenda;contacto :TInfo)
.:e = la agenda no esta }lena)
316 RBcrsrnos

{eost = Se ha aadido un nuevo contacto, de forma ordenada a la


qYUruq J

VAR
i, j : TRango2;
final: boolean;
BEGIN
IF Esvacia (agenda) THEN
BEG]N
agenda.max := succ (agenda.max) ;
agenda. contactos Iagenda. max] : = contacto
END
ELSE
BEGIN
final := FALSE;
i := INI;
WITH agenda DO
BEGIN
max : = succ (max) ;
I^IHILE NOT f inal AND (i < max) D0
IF contacLos Ii] .nombre > contacto.nombre THEN
BEGIN
final := TRUE;
FOR 'i := nldX DOWNTO i + 1 DO
contactos Ij ] : = contactos Ij -1]
END
ELSE
i := i + 1;
conLactos Ii] : = contacto
END
END
END; {InsertarContacto}

PROCEDURE EliminarContacto (VAR agenda: TAgenda;indice:TRango2) ;

{pre = ndice se corresponde con un elemento de la agenda}


,?cst = la agenda contiene un el-emento menos)
...:
:: DIed (INI) . .N;
::l-li
;,_l_-_ agenda D0
__ ---__t
-,: -tT

:CR i := indice TO max-1 DO


contactos Ii] : = contactos Ii+1] ;
Sor,ucroNrs 3t7

- .:^
=y
.
;= nran /-^--
- prt:urtttdx/ t
;
:--]
: - rminarContacto )

. _ ,1,
Escogercontacto (agenda: TAgenda) : TRango2 ;
_

- = = -a agenda tiene al menos un registro)


: ': = devuelve el eremento que debe ser eliminado de la agenda)

-: pred(INI)..N;
. laar;
-, --
- ,= pred(INI);
i = agenda.max;
I ,l-l: _-_- r1
--

-r j_= j THEN
i := INI
:-SE
i := succ(i);
,,;::-tefn ('Si desea elimi-nar eI sgte. contacto, pulse s: , ) ;
:,:cstrarcontacto (agenda . contactos Ii ] ) ;
:eadln (c) ;
'-],:lL c IN ['s' , 'S'] ;
:.:cgerCont.acto : = i
:scogercontacco )

-:-3N Encontrarcontacto (agenda: TAgenda; nombre: TCadena) :

= = TPITtr l
:..- = Busca el nombre introducido por eI usuario en la agenda,
, -, encuentra devuelve la posicin en la que esta. Si no
--=-ve pred(INI) )
-j

- -,med: pred(INI) ..N;


- -:aI : boolean;
r :,':1,
-: NOT Esvacia(agenda) THEN
]]lTIT
--JLI\
final := FALSE;
WITH agenda DO
BEGIN
i Tarr
-t := -tI\I,'
j := max;
318 Rncrsrnos

REPEAT
med := (i+j) DIV 2;
final = (contactos [med] . nombre = nombre) ;
IF contactos [med] .nombre < nombre THEN
i := med + 1
ELSE
j := med - 1
UNTIL final 0R (i , j)-
IF final THEN
EncontrarConLacto : = med
ELSE
EncontrarConLacto := pred(INI)
END
END
ELSE
EncontrarContacto := pred(INI)
END; {EncontrarContacto}

PROCEDURE AniadirContacto(VAR a: TAgenda) ;

{ere = TRUE}
{post = Si hay sitio se aade el nuevo contacto. Si no 1o hay se
el:-ge un contacto para ser borrado o se abandona e1 proceso. Si se
e-rge borrar un antiguo contacto se aade el nuevo. La agenda debe
Dernanecer ordenada)
1r: D

c : TInfo;
abandonar: BOOLEAN;
'i .nD:nn, .
r l\qlIYV ,

eleccion: char;
BEGIN
abandonar := FALSE;
IF NOT HaySitio (a) {o se borra un contactoi
THEN
BEG]N {o se abandona el proceso}
writeln('No queda sitio en fa agenda, para aadir un nuevo,
' contacto tendr que eliminar un contacto antiguo.,);
REPEAT
writ.e ( 'Si desea elimi_nar un registro pulse s, si desea'
' abandonar pulse n
readln (eleccion) ;
--ITIL efeccion IN ['s' ,'S' ,'trr, ,N'];
,
abandonar := (eleccion IN [,n,, 'N',] ) ;
Sor,ucroNns 3t9

IF NOT abandonar THEN


BEGTN
CrearConcacto (c) ;
IF NOT HaySitio (a) THEN {vamos a hacer hueco}
BEGTN
i : = EscogerContact.o (a) ;
EliminarContacto (a, i) ;
END;
Insertarcontacto (a, c) ;

END
:i.D; {aniadirContacto}

.:.CCEDURE Borrarcont.acto(VAR a: TAgenda) ;


?:e = La agenda no esta vaca)
lcst = Se elimina eI contacto por nombre o mostrando los
-:rtactos )
-- D

-. 1r.

-: TRango2;
I: pred (INI) . .N;
lomb: TCadena;
:: -T\T
_ _ if r!

IF NOT Esvacia(a) THEN


BEG]N
c := MuestraOpcionesBorrar;
CASE c OF
' 1' I BEGTN
IntroducirNombre (nomb) ;
(a' nomb) ;
i,' J ::";:Hffil'ffito
EliminarContacto (a, j )

ELSE
writeln ('Ese nombre no se encuentra' ,

' en la agenda') ;
END;
,2, : BEGIN
i : = EscogerContact.o (a) ;
EliminarContacto (a, i )

END
END
END
ELSE
320 Rncrsrnos

writeln('No se puede el-iminar ningun contacto.',


, LA AGENDA ESTA VACIA')
END; {BorrarContacto}

PROCEDURE OpcionesAgenda(VAR agen: TAgenda) ;


Pro = rPttE]
ft--"

{eost = Se actualiza la agenda en funcin de los deseos


de los usuarios i
VAR
^ .,
u ^1"r. ,
ulrq!

BEGIN
REPEAT
c := MenuAgenda;
CASE C OF
,1, :AniadirContacto (agen) ;

'2' :BorrarContacto (agen) ;


END
LINTIL NOT (c IN l' l' , ' 2' ) )

END; {Opcionesagenda}

PROCEDURE CrearMensaj e (VAR mensa : TMensaj e ) ;

{ere = TRUE}

{eost = Se crea el texLo del mensaj e que introduce el


usuario desde e1 teclado)
VAR
f . -L - -
LLIG! .
,

BEGIN
REPEAT
writeln('Introduzca eI texLo de1 mensaje:');
readln (mensa. texco) ;
writeln('Si desea modificar eI mensaje pulse s');
readln (c) ;
UNTIL NOT (c IN ['s' , 'S'] )

END; {Crearl,tensaje}

PROCEDURE MostrarMensaje (mensaje: TMensaje) ;

ll(UrlJI
_"re = --,f
.?:st pantalla el
= Muestra por mensaje)
::: -li
l;-lF- mensae DO
-,--r ! ^ a' ,- ^,
/,r--ar-\Lcxto)
EN); ilosirarMensaje)
Sor,ucroNns 32t

?ROCEDURE CrearMemoria (VAR memoria : TMemoria);


Pre = TRUE)
Post = crea estructura de memoria vac a )
:EGIN
memoria.tope := pred(INI)
:ND; {CrearMemoria}

:UNCTION Memoriallena (memoria:TMemoria) : boolean;


= --,,-
l
iIE IKUT,J
Post = si tope = FIN l-a memoria esta ltena)
:EG]N
MemoriaLlena := (memoria.tope = FIN)
IND; {MemoriaLtena}

IROCEDURE VaciarMemoria (VAR mem : TMemoria) ;


Pre = memoria 1lena)
?ost = memoria vaca)
:GIN
mem. tope : = pred (INI)
:),lD; {VaciarMemoria}

IROCEDURE EliminarMensaj e (VAR mem: TMemoria);


?re = memoria ltena)
?ost = memoria con un hueco l;x-^\
- -r D

i,j: pred(rNr)..rrN;
. n1^,=r .

tlaTrr
_fgfr\
i = pred(INI);
REPEAT
IFi=FINTHEN
i := INI
ELSE
i := succ(i);
writeln('Si desea eliminar e1 sgte. mensaje, p'rlse s:');
MostrarMensaje (mem. todos Ii] ) ;
readln (c) ;
LIJTIL c IN ['s','S'];
WITH mem DO
FOR j := i TO pred(FIN) Do .,{"
rS
todos Ij ] : = todos j +11 ; ,qL

&;-.
-

d.
'\r
r,.",u:."ri,.:,.

of
322 REGISTRoS

mem.trope .= predtmem.cope)
; ,)
- _.f t Ll rmlnarlvlensal e ]

;RCCEDURE LimpiarMemoria(VAR memoria: TMemoria) ;


,Pre = La memoria esta ltena)
Post = memoria vaca o con un huecoi
.,IAR

op : char;
tsEGIN
REPEAT
writeln ('Escoj a una de la opciones : ' ) ;
writeln ('1. Borrar Ia memoria' ) ;
writeln ('2 . Seleccionar un mensaje para borrarlo' ) ;
readln (op) ;
TINTIL op IN l'1' ,'2') ;
CASE op 0F
' 1' :VaciarMemoria (memoria) ;
' 2' : EliminarMensaj e (memoria) ;
::'l
END
-
END ; i l,impiarltemoria )
l

PROCEDURE GuardarMensaje (VAR memoria: TMemoria;


mensa: TMensaje); I

{ere = En Ia memoria al menos habr un hueco libre} I

{eost = se ha guardado eI mensaje en Ia memoriai


BEGIN
WITH memoria DO
BEGIN
t-^a
uu}JU .. lrnna\.
\Lvyu/,

todosItopeJ := Illeilsi
END E

ilJD; {GuardarMensajei END;

;:::EDURE TerminarMensaj e (VAR mensa : TMensaj e ; agenda : TAgenda; PROC

i: inceger; tIf: TTlf; f: boolean); {lre


.'-=- = si final i es un ndice de Ia agenda sobre una posicin {eost
:--:;:ino en tlf esta el telfono al que debemos enviar eI afma<
-=-_-=..-:l VAR
-^ F^--.1 - m(
otr

::' ::-: :=g/ mseg:WOfd; NC

::r-l: TL
Sor,ucroNBs 323

.-
-ll mensa DO
: I _ -tT
_ _ ,--L!
-_*^^r^^
_ ___Jsrqv -. +-
- I i

:: ^ TNT
- _ -_rr\
identificacion : = agenda. contactos Ii] .nombre;
writeln ( ' Ef usuario de nombre , , agenda. cont.actos
Ii] . nombre,
' tiene e} numero ,, agenda.cont.actosIi] .t1f);
:l.l
:.SE
numero := tlf'
,,ITH f echa DO
GetDate (anio,mes, dia, semana) ;
}IITH hora DO
GetTime (hora, minutos, seg, mseg) ;
:ND;
: -: {TerminarMensaje}

: : : IEDURE TerminarMensaj eEntrante (VAR mensa : TMensaj


e; t1f : TTlf )
:,:
=3mana/ Seg, mseg:WOrd;

,-TH mensa D0
:: 1
__JAI\T\T

conocido .- E^TCEr.
numerO : = r'l t -

WITH fecha DO
GetDate (anio,mes/dia, semana) ;
WITH hora D0
GetTime (hora,minutos, seg,mseg) ;

,.
TerminarMensa j eEnt rante ]

EnvlarMensae(VAR mem: TMemoria; a: TAgenda ;

= rRUEi
= Se enva un mensaje, creado por eI usuario y s:
en la memoria de mensajes enviados)

rensaje: Tlvlensaje;
EP: char;
:om: TCadena;
Eif: TTlf;
REGISTROS

_: pred(INI)..N;
:rnal terror: boolean;
::-:-N
I
lrearMensaj e (mensaj e) ;
(
cp := ModoEnvio;
irnal := FALSE;
error := FALSE;
(
CASE op 0F
,1, :REPEAT
IntroducirNombre (nom) ;
a: - aT
j : = Encontrarcontacto ( a, nom) ;
IF j ., pred(INI) THEN
final : = TRUE t1e
_^^+
_-_>t
ELSE
BEGIN
---:,
writeln ('El nombre introducido no se"
' encuentra en la agenda') ; - I r rt
(

error : = Esvacia (a) ; __--1r

wriLeln('Vuelva a inLentarlo' ) ; I

END;
final 0R error;
UNTIL
'2':IntroducirTlf (tIf)
END;
IF NOT error THEN
BEGIN I
r'--l .
IF Memoriallena (mem) THEN
LimpiarMemoria (mem) ;
-l
TerminarMensaje (mensaj e, , ),tlf , final) ;

GuardarMensaje (mem, mensaje) ;

AvisoMensaj eEnviado;

(
END
,]e :_ :_ -JII T\
- -\lJ; t EnvlarMensal J
(
(
;-ICCEDURE RecibirMensaje (VAR mem: TMemoria) ;
\ (
--'-s - 'Prrr
:-rst = Ilega un mensaje desde otro telfono y se almacena en la I
-=-.:::ia de mensajes recibidos)
*::saje: TMensaje;
AAII,

::l-l:
-: MemoriaLlena(mem) THEN
Sor,ucroNns 325

BEGIN
Avi soMemoriaLlena ;
LimpiarMemoria (mem)

CrearMensaje (mensaje) ; {Simulamos que 11ega un mensaje)


IntroducirTlf (tlf);
TerminarMensa j eEntrante (mensaj e, t1 f )

GuardarMensaje (mem, mensaje)


:,-- : {RecibirMensaje}
.: - IEDURE OpcionesMensajes (VAR agen: TAgenda;
VAR entrantes,salientes: TMemoria) ;
.:: = TRUE]
.-st = Se habrn producido las actualizaciones
,-=rradas en fa memoria correspondiente)

:: char;
ti
].EPEAT
t .- MenuMensaj es;
CASE c0F
'1' :EnviarMensaje (salientes, agen) ;
'2' : RecibirMensaj e (entrantes) ;
END
-ITTIL NOT (c IN l'L' ,'2'))
, OpcionesMensaj es
)

=:enda: TAgenda;
::tra, sale : TMemoria;
lp : char;
T*
Programa Pr:_ncipal i
-:earAgenda (agenda) ;
l:earMemoria (entra) ;
--:earMemoria (sale ) ;
::ftrA.f

:p := MenuPpal;
lF Memoriallena(entra) THEN
Avi soMemori aLl ena;
IASE op OF
' 1' : OpcionesAgenda (agenda) ;
'2' : OpcionesMensajes (agenda, entra, sale)
326 Rncrsrnos

END
UNTIL NOT (op
fm l'L' ,'2'))
END. {Programa Principal}

9.9.7 Evitando la recursividad


PROGRAM NoRecursivo;
CONST
N = 30;
FIN = 100; EN

INI = 1;
-l tvt . pR(
-
ia tt. tsE(
- 1t
TYPE
TCadena = string [N] ;

TRango = INI..FIN;
TDATOS = RECORD
x,y: TRango; E}JD

END;
TAlmacen = array [TRango] 0F TDatos; FUtv(

Tl}amadas = RECORD BEG]

todas: TAlmacen;
t-pe: pred(INI) ..EIN;{Tiene que existir una posicin
que i-ndique que no haY datos)
lt,.t ;
PROC
BEG]]
F-LINCTICIi ii::rccuceCoordenada : TRango;

VAR EIVD;

c: chari
code tz: integer; Ft]-NCT

correcto: boolean; BEG]N


BEGIN A
COTTECTO := FALSE; END;

REPEAT
write ('lntroduzca Ia coordenada: ' ) ; FL']VCT]

readln (c) ; BEG]N


VAL (c, z, code) ; A1
correcto := (code = 0); EITJD:
,t {
--l:lIL correcto AND l(z > pred (INI) ) AND (z < succ (rIN) ) ) ;

-:::loduceCoordenada = : z PROCEDI
r^
:-.- -:-:lloduceeoor0enaOal
-al

t Post =
Sor,ucrorvps

.:.1:EDURE IntroduceDatos (VAR r: TDatos) ;


I I - -rr
- - i_1\
;,ITH r DO
3EGIN
writeln (,Coordenada x,) ;
x := IntroduceCoordenada;
writ.eln (,Coordenada y, ) ;
y := fntroduceCoordenada
:ND
_
-.-
: { IntroduceDatos }
.:.::EDURE MostrarDatos(d: TDatos) ;
--l--xr
_ _
--_L\

iIITH d DO
3EGIN
write (, (, ,x,, , ,
,y,,) ,) ;
:ND
:l: {MostrarDatos}

: l;:TI0N Iguales (o,d: TDatos) : boolean;


l: ^ -u
-- ---r!
lguales := ((o.x = d.x) AND (o.y = d.y));
- l:-]
L_: tlguales-| t_

.:::fDURE InicializaAlmacen(VAR a: Tllamadas)


;
: I - -\r
----_t!
a. tope = pred (INI) ;
- -: {InicializaAlmacen}
l-

f:;:IION AfmacenVacio (a: Tllamadas) : boolean;


::--1-

ilmacenvacio := (a.tope = pred(INI) )


I - ' lAJ_maCenVaClO]
f-:

--llION Almacenlleno(a: Tllamadas) : boolean;


_:-.macenll_efro := (a.tope = FIN)
:- .Almacenlleno)
:-ti) ) ) ;
::-::IURE GuardaAlmacen(VAR a: Tllamadas,.
o: TDatos);
l:= = a.tope <> FIN)
.:=-- = a.todas[a.topel = o]
318 Rrcrsrnos

::GIN
WITH a DO
BEG]N
tope := succ(tope)
todaslcope] := o
END
:l'Jf ; {GuardaAlmacen}

IROCEDURE ExtraeAlmacen (VAR a: Tllamadas; VAR o: TDaTos);


Pre = a.tope <> pred(iNI) )
Post = a.tope se ha decrementado y devuelve datos en o]
!E'TTT
J !g II\

WITH a DO
BEGIN
o := todas [t.ope] ;
rope ; = pred (t.ope )

END
END; {ExcraeAlmacen}

PROCEDURE Incrementax(VAR o: TDatos)


D TlT
U!UTI\
o.x := succ(o.x)
END; { IncrementaX}

PROCEDURE IncrementaY(VAR o: TDatos)


:ET\T
i !g rr!
o.)r := succ(o.y)
:ND; { IncrementaV}

?F,OCEDURE Decrementax(VAR o: TDatos)


] l TNT
:__J1L\

o.x := pred(o.xl
:_._: T
-
tlleCrementaX.l
-- l

.: - I:IURE Decrementay (VAR o : TDatos )

:: a-1,
._ nrorl /n .r\
I,lUu\v.}/
-ramo-r.v)
- = --c,,.crr-or I

: - -,- _:ualCoordenada (o,d: TDatos; char) : boolean;


. i: - l:
Sor,ucroNrs 329

C1: IgualCoordenada := (o.x = d.x);


C2: IgualCoorderda := (o.y = d.y)
:lJD
: -: {IgualCoordenada}

_:_0N NumeroCaminos(orig, dest: TDatos) : integer;

l'rarda: TLlamadas;
a;x: TDatos;
- -1- . 'i nlaaar.
tlrusyu!,

::ror: boolean;
: : r-]'t
lont : = 0;
:ilror : = FALSE;
-nicial izaAlmacen ( guarda ) ;
luardaAlmacen(guarda,orig) ; {No comprobamos que eI almacn
est lleno porque fo acabamos de crear)
;';:{ILE (NOT AlmacenVaco (guarda) ) ANO (NOT error) DO
:EG]N
ExtraeAlmacen (guarda, orig) ;
IF Iguales(orig,dest) THEN
cont := Cont + 1
ELSE
BEGIN
IF NOT lgualCoordenada(orig,dest,Cl) THEN
BEGIN
IncrementaX (orig) ;
error : = Almacenlleno (guarda) ;
IF NOT error THEN
GuardaAlmacen (guarda, orig ) ;
DecrementaX (orig)
END;
IF NOT IgualCoordenada (orig, dest, C2 ) fHE:,1
BEGIN
IncrementaY (orig) ;
error : = Almacenlleno (guarda) ;
IF NOT error THEN
GuardaAlmacen ( guarda, orig) ;
DecrementaY (oriq)
END
:., D
330
RBcrsrnos

IF error THEN
writeln ('Se ha Producido un error de
d'esbordamiento' )

ELSE
NumeroCaminos ; = cont
END; {NumeroCaminos}

TodoCorrecto(o, d: TDatos) :
boolean;
FT]NCTION
BEGIN
AND (o.y <= d.Y))
TodoCorrecto := ((o'x <= d'x)
END; {lodoCorrecto}

VAR
origen, destino: TDatos;
caminos: integer;
P,r'cTlJ {Proqrama PrinciPal i
,,ri re'l n ( 'Introduzca coordenadas de origen:') ;
IntroduceDatos ( origen) ;
.,ri rol n ('Introduzca coordenadas d,e destino:') ;

IntroduceDatos (destino) ;
lF TodoCorrecto(origen' destino)
THEN

BEGIN
destino) ;
caminos := NumeroCaminos(origen'
write ('El numero de caminos desde
') ;
McstrarDatos (origen) ;
'rite (' hasta ') ;

lics:rarDatos (dest ino) ;


v;::lle1n (' es ' , caminos)
E'\ln

EI,SE
uirilelnr'E- crigen es menor que eI destino,',
' no haY caminos');
1
END. {Programa PrrncrParl
rl- aptulo l0
Ficheros

:.:i;1]i:[i::x: se han visro hasta


ahlra se dennen y
armacenan en ra
me-

. _ principal
,1oria es una memoria
rvrrrurra vol
.:io volatll por lo qu(
':io de ajmacenamie
aimacenamienro
'nto pemanenre
permanente de ilf:]: :'e
.rF inf,ormacijn.
no se puede urilizar como
.: tene que proces
un gran volumen
-
_ -'pacio suficiente a,tt
-.pacio de
principat ,rlit"::]:|.ofifle cue no se disponga
enr memoria p.lr";porlrf::L::ffi:,T:

&ka superar estas Iimir


l;;rili;J;::u''on..
':'undario (discos
se necesiran disposirivos
rr*r.,i.o-ri;r,""ll;-"srrrvos
ls magnticos, de almacenamienro
armacer
extemo,
J"
u: rorma
forma 0".-ur"ni"';;
pticos. dr
iqarro+^-
ssueres, . qque
...) 'u-lento exrerno.
: permanenre y. en ;::::s' "') il;;;;;
ue permiten atmacenar
-.:
-:rrento.
-:tlento.
arsunos uaos, presentan
r 2 --- *rurrwD
""ljlTlll una gran capacidad
de
. : ..1lctur& de datos
q urrr coteccln
. ,mbre
,mbreo",0"i'lZ'::^::,Y::i,:::,::j:rarosenarmacenamienroexrerno
defichero;----"
archivo
de datos en alma
y a elia se dedjca
"r," "*ir'u'rJ.

Fichero o archivo?

e r
il Hffi T:il,"j fl:,|jl,LH:,:::,,,"
mi smo p-po,*o
'. '1ff'*l#:'::,;T,^l;;;,:;;r""1"ii ;,if *:
uesrgnar a una coreccin
ur, archivo "zip,, o..,ur,,. Si coleccin de ,.files,,,
,.rires,,
._- irrlJr'r. ir^,u,*
."1TS,:ffi
' un ejemplarl-;T:ffi * Ia paiabra
aotr. f ,i 'rtlltzar
que contien" "fichero"
-*;'hy,"xi,^[!:;T,,1i;#1#i:::l"',"#T
vo,, cuando lo haga
.._ coleccin de
ficheros. o "rrrdo
";"rnplm
qr"

331
FICHEROS

10.2 Definiciones
es una secuencia de componentes almacenados
en un soporte externo' S'
un fichero
sino que se asigna de fornl''
tamao no est fijado de antemano ni hay que concretarlo,
propio soporte de almacenamientt
dinmica; la limitacin de tamao viene dada por el
que permiten un almacenamient
una de ias principales caractersticas rle los licheros es
programas'
permanente que facilita el uso de los datos por diversos
Se denomin a registrut lgico a una componente
individual del fichero' se denomir'"'
(infbrmacin que se transf,ere) ent:'
bloque rt reg,istro.fsico alauniilad de transferencia
principal' Se denomina bttli'
el dispositivo de almacenamiento externo y la memoria
doncle se almacena el bloque ledc
de entrada/salida al rea de la memoria principal
bien clonde se construye un bloque antes de escribirlo'
con el tipo de dato punte:
Asociado a cada fichero hay un puntero (no confundir
que contiene la direccirl
que se ver en el captulo l1') o ctrrsor que es una variable
posicin del registro lgico que va a ser ledo o escrito'
lgicos:
Los ficheros pueden contener varios tipos de registros
frchero tienen la misma longitud'
Registros de longitud fija: todos los registros clel
Registros de longitud variable: la longitud de
los registros del mismo fichero pue-'
variar, pero oscila entre un mnimo y un mximo'
es totalmente variable' Normaim:.
Registros delimitados: la longitud de 1os registros
un registro de otro'
se utilizan caracteres delimitaclores para separar

Har clos modos de acceso a los registros lgicos: :l


en el que los registros lgicos estn alm"- '
-\cceso secuencial: se realiza en el orden
informacin del flc:..
nados en el frchero' As, para acceder a una determinada
precedente'
hav que rcceder previamente a la informacin
registro lgico que ocupa unii :
Acceso directo: permite acceder directamente a un
fichero sea direcciona: '
cin concreta de1 fichero. Requiere que el soporte del

10.3 Nombre lgico y nombre fsico de un flchero


en memoria extem"r -
El nombre fsico de un f,chero es el nombre que tiene asignado
fichero desde el sisten-i
identificador es el que se utiliza cuando se manipula el
fichero a travs -' -rl
rativo. Sin embargo, un programa no tiene porqu procesar un
las normas de los iden"
nombre fsico. De hecho, dicho nombre puede no cumplir
doresvlidosenellenguajedeprogramacinenelqueestescritoelprogranl"
tnnombre lgi''
instrucciones det program flente utilizan lo que se denomina
r ariable de tipo fichero, que ser un identificador vlido
del lenguaje de program:-
Cadalenguajedeprog,amacintienesupropiomecanismopararelacionareln.-.
programa fuente' En F -
fsico de un fichero .on no-bre lgico que se le dar en el
"i con el procedimiento assign cuya sintaxis es:
estr relae in se establece
Trpos DE FICHERoS EN PIscnr,
333

..ssign (varFichero, nombreFisico)


;

- ' -'arFichero una variable de tipo llchero y nombreFisico una


cadena
: _,ue se corresponde con el nombre fsico del fichero. por ejemplo:
cle carac-

::s1gn (ficheroAgenda,,c: \Datos\Agenda.dat,


);
na la variabre de tipo fichero f icheroAgenda
con er
:: 'c:\oatos\agenda.dat'. cuando una instruccinfichero cuyo nombre com_
del programa se refiera
- , r.ariable fichero, realmente estar operando sobre el fichero I/^v6rurrra ru rurt9ld

identificado por
,:::)it"":-1. dal., . Si en et no1lre fsico no se especifica la unidad y el
. camino
' -':iorios, se sobreentender que el fichero est ubicado en la unidatl y
directorio de
I.
'rn programa esta operacin se realizar una sola vez con cada
fichero y es previa
- '.ier otra. A continuacin se muestra un ejempro de su
uso dentro de un programa:
!j emploAssign;

::-_qn(fichero,'c:\Datos\agenda.txt, ) ;
:- . :=sarFichero (fichero)
;

trr-:scal estndar los nombres lgicos de


los ficheros utilizados en un progtama
-. 3n en la lista de parmetros de Ia declaracin del programa.
Sin embargo, en
.,ul no es necesario.
: :nlplo anterior escrito en Pascal estndar debera sustituir
la declaracin PROGF]{
_::iente:

:-emploAssign (INPUT, OUT,PUT, fichero) ;

que se va a utilizar la entrada estndar, la


sarida estndar 1. el fichero : _::erc.

Tipos de ficheros en pascal


:..s
-senerales que se han visto en el apartado 10.2 son r 1idas para los ficheros
-:'na de los lenguajes de programacin. sin embar-ro.
cada lenguaje presenta
:udes en la forma en que concibe y manipura
ros ficheros que-pueden hacer
:rnpliar las definiciones.
r
-';al se distinguen dos tipos de ficheros con respecto al tipo de infbrmacin que
: - -. cmo est estructurada:
334 Frcnrnos

Ficheros binarios: sus componentes o registros lgicos se almacenan en la represente-


cin interna de la mquina; es decir, con los mismos patrones de bits con los qu;
se almacenan en memoria principal.

Ficheros de texto: contienen registros delimitados compuestos por secuencias de c:-


racteres. Su carcter separador es el carcter de fin de lnea. La informacin ..
almacena utilizando un cdigo de representacin externa (ASC[, EBCDIC, . . .

Por ejemplo, el entero 27195 podra almacenarse como tal entero en un f,chero bin'-
rio de la misma manera que se representa en memoria principal (representacin intem",
en 16 bits, quedando: 0110101000111011. Sin embargo, si ese mismo valor entero ..
quisiera almacenar en un fichero de texto, se almacenara con sus correspondientes -'
racteresASCII: "2"'7" "1""9""5",esdecir:00110010001101110011000100111(r
001 10101.
Las ventajas de los f,cheros binarios respecto a los de texto son las siguientes:

o Las operaciones de lectura y escritura son ms rpidas ya que no requieren -- -

conversin de la representacin externa a la interna o viceversa.

o Un f,chero binario, en general, ocupa menos espacio de almacenamiento qu;


correspondiente flchero de texto.

Pero no todo son ventajas para los flcheros binarios. Tambin presentan un tn'
veniente: su falta de portabilidad. La representacin interna puede variar de uros r'r- -
nadores a otros y de unos lenguajes de programacin a otros, por 1o que no puede: '
utilizados por cualquier programa en cualquier ordenador.
-
A continuacin se describe en detalle cada uno de estos tipos de fichero. En ade -.
cuando se hable de una componente de un fichero se referir a un registro lgico.

l0.4.L Ficheros de texto

Un fichero de texto es una secuencia de caracteres organizados en lneas. Los car-',


se almacenan segn un alfabeto, en este caso el alfabeto ASCII.
El tipo fichero de texto es un tipo predeflnido en Pascal, el tipo text. As, un r.-'
de texto se declara como una variable de dicho tipo predefinido:

-'- D

ficheroTexto: text;
La entrada y salida estndar en Pascal, Input y Output, son ficheros de tir
que \ a estn definidos. En un fichero de texto:

Cada lnea termina con una marca de fin de lnea, eoIn.

o El fichero termina con una marca de fin de fichero, eof .

I
Trpos DE FICHERoS EN PnscIr. 335

Grflcamente podemos describir un fichero de texto como muestra la siguiente se-


cuencia:

eoln eoln eof


En la que cada celda representa un carcter ASCII, un final de lnea se representa
con eoln y el flnal del fichero con eof.

Operaciones de apertura y cierre

-,',do fichero antes de ser procesado tiene que ser "abierto" y una vez procesado debe
'jr ''cerrado". La forma en que un f,chero se abre depende de1 tipo de operaciones
.ictura, escritura) que se realizarn con el fichero. Sin embargo, la forma de cerrarlo es
.Jependiente de las operaciones que se hayan realizado.
Apertura de un fichero de texto. Hay tres formas de abrir un fichero de texto. La
:r--era de ellas slo es vlida en Turbo Pascal.
El procedimiento reset. abre un flchero de texto para leerlo, por 1o que presupone
- -: ei fichero existe. En caso de que no exista se producir un effor de ejecucin. Este
- --edimiento coloca el puntero del fichero especificado al principio del mismo. Su
-.ris es la siguiente:

:eset. ( f icheroTexto) ;

Este procedimiento utilizado con un fichero de texto no permite la modificacin de


-,-rntenido; es decir, no se pueden llevar a cabo operaciones de escritura. El flchero de
- :-.irada estndar Input no hay que abrirlo para utilizarlo.
EL procedimiento rewrit.e abre un fichero de texto para escribir en 1, destruyendo
, 'ntenido en el caso de que se realice con un fichero que existe. Este procedimiento
:r el puntero al principio del flchero especif,cado. Su sintaxis es la siguiente:
:ewrite ( f icheroTexto) ;

:ste procedimiento no permite ilevar a cabo operaciones de lectura. El fichero de 1a


-' estndar Output no hay que abrirlo para utilizarlo.
-- procedimiento append abre un fichero de texto para extenderio: es decir. para
--,r o escribir contenido (texto) al final. Coloca el puntero del fichero al final del
-l. Este procedimiento no existe en Pascal estndar, pero s en Turbo Pascal. Su
-',.is es la siguiente:

r: : end ( f icheroTexto) ;

: .rDo de apertura no permitellevar a cabo operaciones de lectura.


L ierre de un fichero de texto. El procedimiento close cierra un {ichero asegurando
. 'dos los datos del buffer de entrada o salida quedan ledos o escritos correctamente.
rnato es e1 siguiente:
:-ose (ficheroTexto) ;
336 FtcnBnos

Operaciones de lectura y escritura

La lectura de ficheros de texto es similar a la lectura desde la entrada estndar Input. r


la escritura de ficheros de texto Io es as mismo con respecto a la escritura hacia la salid.
estndar Output. A diferencia de la lectura y escritura con la entrada y salida estndar.
cuando se lee y escribe un flchero hay que indicar su nombre lgico en la correspondient
in:truccin de lectura o escritura.
Lectura de un fichero de texto. La lectura se lleva a cabo con los procedimiento.
read. y readln utilizando el formato explcito. La sintaxis de los procedimientos d.
lectura es la siguiente:

read ( f icheroTexto, listaParametros) ;


readln (ficheroTexto, IistaParametros) ;

Cuando se ejecuta una instruccin de entrada se leen secuencias de caracteres d


fi.chero especificado y, en caso necesario, se convierten al tipo de las variables expresade'
en lisLaParameLros.
El procedimiento readln se puede utilizar con flcheros de texto pero no con ficher, '
binarios. Este procedimiento lee el contenido del fichero hasta una marca de fin de In -
EoLN, sta incluida. Supngase que se tiene la siguiente informacin en un flchero :.
texto:
L 33453 .89\n
donde \n representa el fin de lnea. El primer elemento de la lnea es un valor de tip
char y el segundo es de tipo reaI. Para leer esta lnea y almacenar los valores en send.'
variables se podra recurrir a la siguiente instruccin de lectura:

readln(ficheroTexto, car, num)

Donde car es una variable de tipo char y num una de tipo real.
Hay dos funciones booleanas asociadas a la deteccin de la marca de fin de lnea
de fin de fichero: eoln y eof respectivilteflte: Srr sintaxis es:

eoln (ficheroTexto) : boolean


eof (ficheroTexto) : boolean
eoln devuelve valor TRUE si el puntero de ficheroTexto est apuntando a la ma; -
tle fin de lnea y FALSE en caso contrario. Por su parte, eof devuelve valor TRUE si ;
puntero de f icheroTexto est apuntando a la marca de lin de fichero y FALSE en ca:
i,ntrario.
En el siguiente fragmento de cdigo se lee todo el contenido de un fichero de ter
lire e lnea. Obsrvese que cada lnea contiene un valor de tipo char y un nmero ,
.i:, :::.-

.-.:
.'. -'-r: - -:?:--a: LeXt;
.-
Trpos DE FrcHERos EN Prsclr, J-1 /

=r. h=r.

num: real;
: ] 1T\T
--JII\

tu="t (ficheroTextol ;
WHILE NOT eof (ficheroTexto) D0 BEGIN
readln(ficheroTexto, car, num) ;
Procesarlinea (car, num) ;
END;
close ( ficheroTexto) ;

: Irl&rler&
ms adecuada de implementar una lectura secuencial (de principio a fin) de
--. fichero es mediante el esquema de recorido; en este caso, un bucle WHILE cuya
. rdicin de terminacin se refrere a la terminacin del flchero. As, cuando el puntero
-.. hchero detecte la marca de fin significar que se ha procesado todo su contenido. Si
: -ntenta realizar una lectura una vez que la marca de fin ha sido detectada se producir
.ror de ejecucin.
Escritura de un fichero de texto. La escritura se realiza con los procedimientos
- -:e y writeln utilizando el siguiente formato explcito:
write (ficheroTexto, listaParametros) ;
writeln (f icheroTexto, listaparametros) ;

Cuando se eiecuta una instruccin de salida se escriben las secuencias de caracteres


:spondientes a list.aParametros en el fichero especificado.
Ei procedimiento writeln se puede utilizar con ficheros de texto pero no con fl-
': \s binarios. Este procedimiento aade una marca de fin de lnea, EOLN, despus de
' - :: escrito el contenido de listaparametros.
'n el siguiente fragmento de cdigo se almacena en un lichero de texto ai rnenos una
"
.. iormada por un valor de tipo char y un valor de tipo reaI. a partlr de informacin
-. Je1 teclado:
:

: -:heroText.o : cext;
'=--
--y . 1r'
.racn. -,,4r;
:- rr : real ;

- :r,irite (f icheroTexto ) ;
::1tr^rll

write('Escribe un carcter y un valor real: ,);


FICHEROS

readln(car, num);
wriLeln(ficheroTexto' car:2'
num:10:2) ;

(s/n) :') ;
write('Qureres continuar
readln (resp) ;
UNTIL (resp = 's') oR
(resp = 's');
close (ficheroTexto) ;

END;

L0.4.2 Ficheros binarios


int-
en binario siguiendo la representacin
-

Estos ficheros almacenan informacin '


delordenador,deahquelainformacinpuedasertransferidaa,odesdelamen..
principalsinnecesitarui"g'i"tipodetransformacin'Todaslascomponentesson.
tiPo'
Logn"ut, es decir, del mismo F]LE oF' La sint*'
con 1as palabras reservadas
Los flcheros binarios se declaran
de la declaracin es la siguiente:

TYPE
OF TComponente;
TFicheroBinario = FILE
y t'
tipo excepto un tipo frchero "*:titly::11'i:
lComponente puede ser cualquier se presentan algunos eJ emF.
re d.l fr;;;r; qr. .. ".loru. A conlinuacin
sisrro 1gico

TYPE
= (Lun, Mar, Mie' Jue, Vie,
Sab, Dom);
TDiasSenana
r'r-:1^,r: = ARFAY [i..100] OF integer;
TRegistroEmPleado = RECORD
nombre: string[401 ;
numefo: feal
END;
TFicheroNumeros FILE OF integer;
TFicheroDias FILE OF TDiasSemana;
TFicheroTablas FILE OF TTabla;
0F TRegi stroEmPleado;
TFicheroEmPleados = FILE

EltipoTFicheroNumeroscomespondeaunficherobinariocuyascomponentes)
del tipo enumer'-
del tipo TFicheroDias son
de tipo integer; fu' tornpo'entls
I'

I
TDiasSemana;cadaComponentedeltipoTFicheroTablasesunaffaydetipoTTa:..
un flchero binario culos coffipol';-
tli;r"roe*pleados describe
y, por ltimo. el tipo
I
I

,", ,on de tiPo TRegistroEmPleado'


Trpos DE FrcrrgRos EN P.scu-

Operaciones de apertura y cierre

l,-rmo se ha visto con los ficheros de texto (apartado 10.4.1), un flchero binario antes
-:r procesado tiene que ser "abiefto" y una vez procesado debe ser "cerrado". La for
:r Que un flchero binario se abre depende del tipo de operaciones (lectura, escritura) r
.r \ ayan arealizar. Sin embargo, y al igual que con los de texto, slo hay una manera
-:rrarlo.
Apertura de un fichero binario. Hay dos formas de abrir un fichero binario.
rcedimiento reset abre un fichero binario para realizar tanto operaciones de lect
- lno de escritura. Presupone que el fi.chero existe. En caso de que no exista se produ,
- . enor de ejecucin. Este procedimiento coloca el puntero del fichero especificad
ncipio del mismo. Su sintaxis es la siguiente:
:,rin inr;.
reset. ( f icheroBinario) ;
1: la menl,
-
r:ntes soll El procedimiento rewrite tiene un comportamiento similar al visto con fichero
:'tto. Abre un fichero binario para escribir en 1, destruyendo su contenido en el

-I. La sint', ,: que se realice con un fichero que existe. Este procedimiento coloca el puntero
-hero al principio. Su sintaxis es la siguiente:

rewrite ( f icheroBinario) ;

Este tipo de apertura no permite llevar a cabo operaciones de lectura.


Cierre de un fichero binario. Para cerrar un fichero binario se utiliza el mi
rtu,ve el tiPt' -, : --,cedimiento que para ceffar un flchero de texto y tiene el mismo comporlamiento
:unos ejemp-
close ( f icheroBinario) ;

lperaciones de lectura y escritura

- - unidad lgica de transferencia entre la memoria externa y la memoria principal t


':trstro lgico. Es decir, en cada operacin de lectura o escritura de un fichero bin
que se lee o escribe es una de las componentes del lichero.
Lectura de un fichero binario. La lectura se lleva a cabo con e1 procedini
-=- i utilizando el formato explcito:

read (fcheroBinario, varTComponente) ;

::rdo varTComponente una variable del mismo tipo que las componentes del ficl
, -::eroBinario. Este procedimiento lee una componente de f icle:cBinario ,
:-ero contenido en varTComponente.
SU

.omponentes : La funcin eof ya descrita en el apartado 10.4.1 tambrn se utiliza para detectr
r tipo enumer.-
- - de un fichero binario. Sin embargo, la funcin eoln no se puede utilizar con fich
r de tipo TTa: - , - .arios.

Juyas COmPor:' El siguiente fragmento de cdigo muestra cmo se escribe en pantalla todo el cc
- ,de un fichero binario:
340 Frcnnnos

TRegistroEmpleado = RECORD
nombre: string [401 ;
numero: real
END;
TFj-cheroEmpleados = FILE OF TRegistroEmpleado;
VAR
f ichero : TFicheroEmpleados ;
registro : TRegistroEmpleado;
BEGIN

reset (trchero) ;
WHILE NOT eof (fichero) DO BEGIN
read (f ichero, registro) ;
writeln ( 'E1 nombre es : ' registro. nombre) ;
writeln ( 'EI nmero es : ' registro. numero) ;
END; {wurlr}
close (fichero) ;

END;

Vase que el esquema de la lectura secuencial de un fichero binario es similar al que .:


vio con ficheros de texto: un bucle WHILE cuya condicin de terminacin se refiere -
deteccin de 1a marca de fin del flchero, es decir, un esquema de recorrido.
Escritura de un fichero binario. La escritura de una componente de un fich;.
btnario se realiza e1 procedimiento write utilizando el formato explcito:

wr:-te (f icheroBrrario, varTComponente) ;

donde varTComponente es una r.ariable del mismo tipo qrre las componentes del flche :
ficheroBinario. Este procedimrento escribe el contenido de la variable varTCon: -
nente en f icheroBinario.
El siguiente fragmento de cdigo muestra cmo se crea un fichero binario a prtir -:
informacin leda del teclado:

TRegistroEmpleado = RECORD
nombre: string [40J ;
numero: redl

TFicheroEmpleados = FrLE OF TRegi stroEmpleado ;

f ichero : TFicheroEmpleados ;
Tlpos DE FICHERoS EN PASCAL 34

registro : TRegist.roEmpleado ;
:]-T\T
_ _ _-_r!

re\irLLe (f ichero) ;

t.!,}tt
vrrile('Escribe un nombre y un nmero: ,) ;
-rea,\n\-reg\sUco .nombre reg\s\-ro .rru\ero
, ) ,i

wrl-Le(tichero, regisLro) ;

writ.e('Quieres cont.inuar (s/n) :, ) ;


readln (resp) ;
UNTIL (resp = 's' OR resp = 'S');
close (fichero) ;

Ficheros de acceso directo

-'rs flcheros de acceso directo son aquellos en los que se puede acceder a una
: rnente cualquiera indicando la posicin que ocupa en el flchero. Pascal estnc
rport& los flcheros de acceso directo, pero otras versiones, como Turbo Pascal,
-,poftan.

imilar al que se En Turbo Pascal un fichero binario puede ser procesado indistintamente cor
n se refiere a la - -hero de acceso secuencial o de acceso directo. La nica condicin necesaria par
do. ,:. hchero pueda ser tratado con acceso directo es que est almacenado en un sr
te de un flcheo , :e ccionabie (disco magntico, disquete, ... ).
D: El acceso directo a una componente se realiza situando el puntero del fichero
'icin en la que se quiere hacer la operacin de lectura o escritura. El posicionan
, r. puntero se realiza con el procedimiento seek. Su sintaxis es:

nentes de1fich.- seek ( f icheroBinario, posicion)


rble varTCoi::
: lo ficheroBinario una variable de tipo f,chero binario y posicion una varial
b,inarioaparti: -' -cngint (entero largo) que indica la posicin en la que se desea colocar el pu
La posicin de la primera componente de un fichero binario es la posicin 0. Cr
. -r.e un fichero el puntero apunta a dicha componente 0.
Ei fragmento de cdigo siguiente muestra un ejemplo en el que se ubica el pt
- , posicin 23 para, seguidamente, leer la vigsimo cuafia componente que es
,:u dicha posicin.
_-
-?.egistroEmpleado = RECORD
nombre: stringl40J ;
numero: real
342 FICHEROS

END;
TFicheroEmpleados = FILE OF TRegistroEmpleado;
VAR
f ichero : TFicheroEmPleados ;
registro : TRegisLroEmPleado ;

BEGIN

reset (fichero);

=""0 t
fichero,
); 23
read (f ichero, registro) ;

END;

Tngase en cuenta que cada operacin de lectura y escritura hace avanzar el puntero u: *
posicin. En el ejemplo anterior, el puntero estara apuntando a la posicin 74 tras -
ejecucin de la instruccin read (fichero, registro).
Adems del procedimiento seek hay dos funciones predefrnidas que facilitan prtrc;'
sar flcheros con acceso directo: filepos y filesize. Su sintaxis es:

f ilepos (f icheroBinario) : Iongint


f ilesize (ficheroBinario) : longint
devuelve la posicin a la que apunta el puntero
filepos y filesize devuelre '
nmero de componentes que tiene el fichero.
A continuacin se muestra.-o es decir, aadir una coilr:
"I!9n!9I@, fic
nente a pafiir de la ltima.

TYPE
1(
, TRegistroEmPleado = RECORD
lA nombre: string [4ol ; _u
numero: real :,tl
END;
TFicheroEmpleados = FILE OF TRegistroEmpleado; . :.:
--j
VAR
f ichero : TFicheroEmPleados ;
registro : TRegistroEmPleado ;

3EGIN

PedirDatos (registro) ;

seek (fichero, filesize (fichero) );


v,':ite (f ichero, registro) ;
:,--l

END;
FrcnBnos coMo pnnnrnrnos -1+-1

:r el siguiente ejemplo se muestra cmo hacer una lectura secuencial a partir de una
.: :-rinada posicin del flchero.
_ .:
---.egistroEmpleado = RECORD
nombre: stri-ng[40i ;
numero: real

lFicheroEmpleados = FILE 0F TRegi stroEmpleado;

:rchero : TFrcheroEmpleados ;
:egistro : TRegistroEmpleado;
:csicion: longint;

:csicion : = PosicionPunt.ero (fichero)


seek (fichero, posicion) ;
i,:iILE NOT eof (f ichero) D0 BEGIN
read(fichero, registro) ;
ProcesarComponente ( registro) ;

Para poder utilizar el procedimiento seek y las funciones filesize y filepos el


- ::o al que se ref,eren debe estar abierto.

: ),5 Ficheros como parmetros /


#,lF..^
-*:do los ficheros se usan como parmetros deben ser parmetros variables. pasadcrs
.:t-erencia. Vase un ejemplo:

E j emploFicheroParametro ;

: - cheroText.o : text ;
ProcesarFichero (VAR fichTexto: text) ;

l-
t ProcesarF'lchero)

ProcesarFichero )
344 FTCHEROS
I

BEGIN
assign(ficheroTexto,'c: \Datos\agenda.txt' ) ;
reset (ficheroTexto) ;
ProcesarFichero (f icheroTexLo) ;

close (ficheroTexto)
END,

10.6 Control de errores d; entrada/salida


Turbo Pascal dispone de un sistema de deteccin de errores de operaciones de entrada 1
salida (E/S) que por defecto est activado ({$I+11. Tnganse en cuenta que la apertura.
cierre, lectura, escritura y posicionamiento del puntero se consideran operaciones de
E/S.
Cuando se produce un effor de E/S el programa detiene su ejecucin y muestra ur-
mensaje de error. Algunos de los errores ms comunes son: abrir mediante el procedi-
miento reset un fichero que no existe, intentar hacer una operacin de leOtura cuand
se ha detectado el final del flchero y ubicar el puntero del flchero en una posicin inexi.-
tente. Para evitar que el programa detenga su ejecucin cuando se produce un eror d.
este tipo se puede desactivar el sistema de deteccin de er:rores de Turbo Pascal, ( { $I- }
y realizar ese control desde el propio programa fuente. Para ello Turbo Pascal dispon.
de la funcin IOResult.
IOResult es una funcin sin parmetros que devuelve valor 0 si la ltima oper.
cin de E/S realizada ha finalizado con xito; en caso contrario devuelve otro valor q,.
identiflca el tipo de error que se ha producido. Por ejemplo, si en el programa fuente .-
quisiera comprobar la existencia de un fichero se podra utilizar la siguiente funcin:

FUNCTION Existe (VAR fichero: TFicheroBinario) :boolean;


BEGIN
{sr-i
reset (fichero) ;
{$r+}
Existe := (IOResuIt = 0);
:'-n ,

La funcin Exi ste devolver el valor TRUE si la operacin reset ( f i chero ) se i-.
;:bo con xito (el fichero asociado a la variable fichero existe) y devolver el r, '-
lr-:: encasocontrario. Ntesequeenelcasodequelafuncindevuelvaelvalor -.
c. i;he ro quedar abierlo. IJna vez hecha la comprobacin de la existencia del fic: -
er .&!rr cle que no se haya realizado la operacin de E/S correctamente, se podr d: ' -
si se muestra un mensaje al usuario, Se crea el fichero o 1o que pueda convenir .- -
correcta elecucin de1 programa.
Cursrroxps DE TrPo rEST 3115

\t).7 Cuestiones de tipo test


I tt.7.1 Enunciados
-,. siguientes cuestiones pueden tener una o ms respuestas correctas.

I Seale cul de las afirmaciones siguientes sobre los ficheros binarios es cierta:

(a) L funcin eoln (varFichero) utilizada con flcheros binarios devuelve va-
lor TRUE si el apuntador o puntero de varFichero est sobre la marca de fin
de lnea y FALSE en caso contrario.
(b) Su paso como parmetro sigue las mismas normas que con otros tipos de
datos: se pasa por valor cuando es un parmetro de entrada y por referencia
cuando es un parmetro de entrada-salida o slo de salida.
(c) Permiten realizar tanto un acceso secuencial como directo independiente-
mente del tipo de soporte.

-.-={d) Cando se abren con el procedimiento reset permiten tanto operaciones de


Iectura como de escritura.

I Seale cul de las afirmaciones siguientes sobre los ficheros de texto es cierta:

(a) Cuando se abren con append permiten operaciones de escritura una vez se
ha colocado el puntero con el procedimiento predefinido seek.
{b) Se utilizan mediante variables de un tipo predefinido.

-{c) Estn organizados igual que los archivos estndar Input y Output.
(d) Cuando se abren con reset permiten tanto operaciones de lectura como de
escritura.
. Seale cul de las aflrmaciones sobre eI siguiente cdigo es cierta:

-,rAR

fichero: FILE 0F char;


dato: char;
-]EGIN

,"rtr" (fichero,' misdatos. jpg' ) ;


WHILE NOT (eof (fichero) ) D0
readln (fichero, dato) ;

(a) l{o es correcto porque un f,chero con extensin . j pg no se puede asociar a


un fichero de texto.
{b) Es incorrecto porque el procedimiento readln no se puede tfllizar con fi-
cheros binarios.
346 Frcurnos
\
(c) Es cor:recto porque f ichero es un fichero de texto.
-*{d) Sera corecto si el tipo de fichero fuese Lext.

4. Seale cul cle las afirmaciones siguientes sobre los flcheros binarios es cierta:

-.+{a) Los procedimientos y funciones predefinidas assign, rewrite, read, wriLe


y eof tienen similar compor?miento con flcheros binarios que con ficheros
de texto.
(b) Siempre tienen componentes de tipo registro'
(c) Un fichero binario puede tener componentes de tipos distintos'
() Latuncin tilepos (i) puede devotver un valor comprendido entre 0 y A-

siendo 1{ el nmero de componentes del


fichero t'
5. Seale cttl de lts afirnaciones siguientes sobre los hchetos de terto es ciefa:

(a) S1o se puede tratar su conteido a travs de variables de tipo char.


(b) Se pueden pasar a un subprograma como parmetros por valor si slo se van
a realizar con ellos operaciones de lectura.
=-(c) E1 nico mtodo posible de acceso a los datos es el secuencial.
(d) La funcin f ilesize se puede uflhzar tanto con flcheros de texto como cor.
ficheros binarios.

6. Seale cul de las aflrmaciones siguientes sobre los ficheros binarios es cierta:

(a) La informacin se almacena utilizando un cdigo de representacin extern"


(b) Los ficheros binarios se abren mediante la instruccin assign.
(c) Para escribir un registro en un flchero binario hay que hacerlo campo -
campo.
-.,.(d) Ninguna de las anteriores es cor:recta.

7. Seale cul de las siguientes afirmaciones sobre ficheros es falsa:

(a) El modo de acceso utilizado en los ficheros de texto y en los binarios pue-.
ser distinto.
(b) Para sobreescribir cualquier tipo de flcherc se emplea el procedimiento :=
write.
-="(c) El procedimiento append funciona de la misma forma en ficheros de tert'
binarios.
td) En Pascal hay dos tipos de ficheros: binarios y de texto.

8. Seriale cul cle las aflrmaciones siguientes sobre los ficheros binarios con acc;.
secuencial es cierta:

l
CussrroNns DE TIPo rEST

'.*.(a)AlescribirComponentesenelficherosiempreseaadenalhnaldeltlrt.n,:
(b) No se puede acceder a la primera componente del fichero'
(c)ParaleerunaComponentedelficheroesnecesarioConocerlaposrcinque
ocupa.
haber ledo todas las pre-
**.(d) Para leer una componente del fichero es necesario
cedentes'

10.7.2 Soluciones
l.Laafirmacincomectaesla(d).Lafuncineo}nnosepuedeutilizarconficheros
pasarlos como parmetros por re-
binarios; los ficheros binarios siempre hay que
se puede realizat si el soporte
ferencia; y eI acceso directo a un fichero binario slo
es direccionable.

2. Las afirmaciones correctas son la (b) y la (c). La apertura


append ciertamente
procedimiento seek'
permite reaTizar operaciones de escritura, pero sin utilizar
el
parte' la apertura reset
qu" no puede ser usado con ficheros de texto' Por otra
conficherosdetextoslopermiterea|izaroperacionesdelectura.
3. Las afirmaciones correctas son la (b) y la (d) A un
fichero se le puede asociar
cualquier extensin independientemente de su tipo.
La extensin tiene fundamen-
contenido de un fichero' aunque
talmente un carcter informativo sobre el tipo del
por convenio (por ejemplo jpg
se recomienda utilizar las extensiones aceptadas
corresponde a un formato de imgenes)'
un fichero binario son todas
J. La afirmacin correcta es la (a). Las componentes de
clel mismo tipo, pero no necesariamente de tipo
registro. La funcin f ilepos (f )
siendo N el nmero de compo-
devuelve un valor comprendido entle 0 y N - 1,
nentes de f.
se pueden almecenar
5. La afirmacin correcta es la (c). En los ficheros de texto
siempre hay que pasarios como
datos de tipo distinto a char; los ficheros de texto
parmetosporreferencia;ylafuncinfi]esizeslosepuedeutilrzarconhche-
ros binarios.
infomracin se almacena
6. La afirmacin correcta es la (d). En un fichero binario la
en cada operacin de
utilizando el cdigo de representacin interna del ordenador:
una componente completa'
lectura o escritura-de un fichero binario se lee o escribe
--Laaflrmacinfalsaesla(c).Elprocedimientoappendslosepuedeutilizarcon
flcheros de texto.
acceso secuencial es precisa-
: Las aflrmaciones correctas son la (a) y la (d). En e1

mentelaprimeraComponentealaqueseaccedeenprimerlugarlnoesnecesario
leerla'
conocer la posicin que ocupa una componente para
348 Frcnnnos

10.8 Problemas
10.8.1 Copia de flcheros de texto
Escriba un programa que permita copiar un fichero de texto. Para ello, el programa
preguntar al usuario el nombre que tendr la rplica.

10.8.2 Sustitucin y recuento de vocales


Se desea disponer de un programa en Pascal que:

1. Lea un texto introducido por teclado y 1o almacene en un fichero de texto. La


introduccin del texto finalizar con la pulsacin de la tecla retorno de caro.
2. Muestre por pantalla el texto almacenado en el fichero, de manera que todas Iar
vocales, tanto mayrsculas como minsculas. estn sustituidas por el smbolo "_"

3. Proporcione infbrmacin sobre el nmero de veces que ha aparecido en el text T


cada una de las vocales..
-
10.8.3 Encontrar los ms jvenes
.
Sea un fichero que almacena los datos de una agenda de amigos y conocidos. Los d'' -
tos de cada entrada de la agenda son los siguientes: apellidos, nombre, DNI, ao c.
nacimiento, direccin, cdigo postal y ciudad. Se desea disponer de un prograrrla QL:
Iocalice )' muestre los N amigos ms jvenes, en orden ascendente, siendo N un va1'.
ctnocldo por el programa. Para la realizacin del mismo se podr suponer que es posrt,. .
disponer de una estructura de datos interna de tamao ly'.

10.8.4 \'isualizar fichero con imagen


Las imgenes . ra son aqueilas a las que no se especifica un determinado forma.

no poseen cabeceras. ni nin-sn tipo de informacin adicional a los propios valo:.


de intensidad de sus pxeles. Construya un programa que nos pida el nombre de L- -
imagen . raw en escala de grises. pregunte el tamao que tiene (anchura y altura
muestre los valores de los pxeles en pantalla respetando las dimensiones que se :
ha especificado. A la hora de mostrar en pantalla la imagen, haga que los va1c,..
aparezcan ocupando 3 caracteres (p. ej intensidad 0->' A ' , 32->' 32' ,...'). -'
':,-,,r,,.
e sce t . urj c . es/ mtp/material/ problemas/im25x25 . raw se puede desca::-

ia iinagen llamada im25x25.raw de tamao 25 pxeles de altura y de anchur&, ] \.e i :


.(rrte nido"
\ota: Las escalas de grises se suelen representar por valores enteros comprendidos e: '
0-15,i por 1o que puede ser conveniente el uso del tipo byte para los valores conten.:
en e1 frchero grflco. Recurdese que el tipo byte no est def,nido en Pascal Estr --
pero s en Turbo Pascal.
PR0BLEMAS 349

1(1.8.5 Particin de un flchero binario

-: particin de un fichero consiste en repartir sus componentes en dos o ms ftcheros de


--'uerdo a un determinado criterio. A continuacin se plantean problemas para partir un
- he ro binario en otros dos utilizando algunos de los criterios ms comunes.

Prticin de un fichero binario por contenido

!: trata de partir un fichero binario segn el contenido de sus componentes. Sea un


-hero con los datos personales de los alumnos matriculados en el primer curso de una
,-terminada carrera: apellidos, nombre, DI,II, direccin, cdigo postal, ciudad, turno
licitado (M o T). Se pretende generar dos flcheros: uno con la informacin de 1os
- imnos que han solicitado el turno de maana y otro con la informacin de los alumnos
- r: prefleren el turno de tarde.

Particin de un fichero binario en secuencias de longitud N

:: este tipo de particin el valor de los campos de los registros no se tiene en cuenta.
,nsiste en almacerrar Iy' registros contiguos del fichero origen alternativamente en los
, . o ms ficheros destino. Este tipo de particin se utiliza en el mtodo de ordenacin
-. ncheros de mezcla directa (ver apartado 10.8.7).
Sea el fichero de alumnos descrito anteriormente. Se quiere partirlo en dos ficheros,
-; lnanera que N registros contiguos del fichero origen se almacenen altemativamente
: -. .tro y otro. El valor de N se pedir por teclado. Ntese que en este caso el contenido

-- ios registros es irrelevante para la particin.

J'rticin de un fichero binario en secuencias ordenadas


:: trat& de partir un fichero binario teniendo en cuenta el contenido de alguno de los
, -r.npos de sus registros. En concreto, se almacenan en un mismo fichero secuenci.as de
":listros contiguos que estn ordenados con respecto al campo que dirige Ia particin,
- uanto se detecte un registro no ordenado con respecto al anterior. se cambia el
-
-:rero destino. Este tipo de parlicin se utiliza en el mtodo de ordenacrn de cheros
,' rrezcla natural (ver apartado 10.8.8).
Sea un fichero binario que se desea partir en secuencias ordenrdas de uno de sus
-:.ipos y sean los siguientes valores su contenido: 15.20,2.3.7.10.+.1. La particin en
: - lencias ordenadas dara como resultado:

!1 -l ( )i t_

!2: 2, 3, 7, 10, 1

r-: determinar en qu fichero se escribir una componente se compara su valor con el


: ..rcolllporlente anterior. Si est ordenado con respecto a dicha componente se escribe
' :1 mismo fichero que ella; en caso contrario, se escribe en e1 otro f,chero.
350 FrcnBnos

Sea el flcherb de alumnos utilizado anteriormente. Se pretende partirlo en dos fiche-


ros en secuencias ordenadas de registros contiguos ordenados por el campo apellidos.
Escriba un programa que lleve a-cabo dicha particin.

10.8.6 Fusin de flcheros binarios

La fusin de dos f,cheros consiste en agrupar en un nico nuevo fichero los registros de
ambos. Los f,cheros que se quieren fusionar estn ordenados por uno de sus campos y el
f,chero resultante de la fusin se espera que tambin est ordenado por el mismo campo-
Obviamente, los ficheros que se quieren fusionar deben tener el mismo tipo de registro
lgico. Por ejemplo, se tienen dos flcheros F1 y F2 y los valores del campo por el que
estn ordenados son:

F7 2, 3, 6, 8, 9, 72, 15
F2.. L,3, 5,'7,10t

El flchero resultado de la fusin de rr y F2, FF, debera contener:

FF: 1,2,3, 3,5, 6,'7,8, 9, 10, 72, 15


Escriba un programa que fusione dos flcheros binarios. Para ello, supngase que .
re-qistro lgico del flchero est compuesto de los campos: nombre, apellidos y clar.
siendo este ltimo el campo por el que estn ordenados ambos flcheros.

10.8.7 Ordenacin de un fichero por mezcla directa

Este mrotlo de ordenacin consiste en sucesivas operaciones de particin y fusin .-


secuencias ordenadas cle longitud I/. El valor de N comienza siendo 1 y se va duplican -
tras cada realizacin de las tareas de particin y fusin, hasta que iguala o superr :
nmero de registros de1 fichero que se desea ordenar. No ttiliza ninguna estructure -,
'
tipo array para almacenar parcial o totalmente el flchero. A los mtodos de ordenac-
de flcheros que no utilizan estructuras de datos en memoria principal se les denonl,- -
mtodos de ordenacin externa.
Sea un fichero binario que se desea ordenar en orden ascendente y sean los siguier...
valores el contenido de sus registros: 15,20,2,3,J,10,12,1. El mtodo comienza con r '
l/: 1.
Particin en secuencias de tamao N : 1:

FL: ]-5, 2, 7, 12
12: 2a, 3, 10, 1
Fusin en secuencias de tamao N : 1:

15, 20, 2,3, '1


,10, 7, L2
PnosLnr,{A,s 351

llbsrvese que tras la particin y fusin en secuencias de tamao 1, el fichero resul-


. :.'ontiene secuencias de 2 elementos ordenados. A continuacin, se duplica el valor
', \ se procede de la misma manera.
- - :ln en secuencias de tamao N : 2:

F1: 15, 20, 7,10


F2: 2, 3, 7, 12
Fsin en secuencias de tamao N :2:
:: 2, 3, 15, 2A, L, 7, 10, 12
\hora el fichero resultante contiene secuencias de 4 elementos ordenados. Se du-

: ' e1 valor de 1/ y se contina de la misma manera.


-
--,-in en secuencias de tamao N :4:

::: 2, 3, 15, 20
:2:1,'7,10, L2
' . ..,rn en secuencias de tamao Iy' : 1:

i: 7, 2, 3, J, 10, L2, 15, 2A


' -hero resultante contiene secuencias de 8 elementos
ordenados. A1 duplicar el valor
: ste iguala el nmero de registros del fichero, por lo que finaiiza la ordenacin.
"'Escriba
un programa que realice la ordenacin de un flchero binario por el mtodo
: lezcla directa. El registro lgico del fichero contendr dos campos: cdigo y deno-
cin, cuyo contenido son cadenas de caracteres. Se desea ordenar dicho flchero por
-:mpo correspondiente al cdigo.

,8.8 Ordenacin de un fichero por mezcla natural


: Intodo se aprovecha de la posible existencia en el fichero de secuencias tle crurpo-
ordenadas. Consiste en sucesivas operaciones de particin y fusiiin en :e;ueneias
. Al igual que el mtodo de ordenacin por mezcla directa. no uriliza nin-
estructura de tipo array para almacenar parcial o totalmente el fichertr. por 1o que
in es un mtodo de ordenacin externa.
Sea un fichero binario que se desea ordenar en orden ascendente ] sean los siguientes
- res el contenido de sus registros: 15,20,2,3,7.10.12.i.
:
-..rcin en secuencias ordenadas:

F1: 15, 20, 1

F2:2,3,7,10, 12

Flsin en secuencias ordenadas:


352 FrcnBnos

2, 3, 1, 10, L2, 15, 20, 1

Obsn'ese que la fusin se realiza con una secuencia ordenada de cada fichero.
Particin en secuencias ordenadas:

F1 : 2, 3, 7, 10, 72, 15, 20


F2: 1

Fusin en secuencias ordenadas:

F: L,2,3, '7,10, L2, 15, 20


Cuando que<la una sola secuencia ordenada qr cada fichero, la fusin obtiene ya e
fichero ordenado.
Escriba un programa que realice la ordenacin de un fichero binario por el mtodi
de mezcla natural. El registro lgico del fichero contendr dos campos: cdigo y denl-
minacin, cuyo contenido son cadenas de caracteres. Se desea ordenar dicho flchero p -
el campo corespondiente al cdigo.

10.8.9 Asistente para crear pginas web


Una pgina web tpica es un fichero de texto con extensin . html (HyperText Mar,
Language pero es vlido .htm para conservar el nmero de caracteres de una e.r.--
sin para el antiguo MS-DOS) con ciertas etiquetas que hacen posible que un prosrr
adecuado, el navegador, identiflque un formato que se da a un contenido. Escriba -
programas con las siguientes caractersticas:

i. Un asistente de creacin de pginas web personales simples (tipo currcur


donde el usuario pueda desarrollar su pgina, de tal manera que sea transpir :-
la codificacin HTML que lleva en su interior. Para ello, se pedir el ttulo -.
pgina (nico para la pgina) que servir tambin como encabezamiento. ) s- -.
sucesivamente preguntando los campos que se desean introducir (nombre. - ,

llidos, fecha de nacimiento, direccin, telfono, direccin e-mail, fbto, est,..-


previos, idiomas, puestos de trabajo, conocimientos informticos, preferenc.-
puesto,...). Tambin se podr introducir una imagen y un enlace y si se q-
centrado o alineado a la izquierda (por defecto).
). Un asistente de creacin de pginas web simples con ttulo, uno o varios pr- -.
r' la posibilidad de introducir una imagen y un enlace, como en el punto ante

-\ rnodo ilustrativo, se presenta un ejemplo del funcionamiento del cdigo Hl


r-:i; rI fOrmatO a un texto:

< --:::: :s un comentario en HTML, e1 navegador no lo mostrara--


PnosrnN,rA,s 353

=ri> <l--En la cabecera se incluye el tiLulo de la pagina-->


< : :-t1e >TITULO< /t itle>

:,:ad> < I - -Fin de la cabecera- - >


j','> <I--Tras Ia cabecera viene e1 cuerpo BODY-->
--sf encabezado de mayor prioridad es hl-->
r--.- aI ign= " center " ><h1 >TITULO< /hl >< /div>

--as etiquetas <p> y <lp> delimitan un parrafo-->


:>:ste parrafo es texto plano. Las etiquetas para dar formato
.-:exto comienzan con el signo "menor que" -nombre de la
=--queta- lmayor que" y terminan con 10 mismo pero anteponien-
r_ ..rna barra diagonal u l' aL identif icador de 1a etiqueta. EI
- -::*tenido interior a esas etiquetas tendra un formato bien
:=:lnido.</p>

<img src= " imagenes/logoU. gif ',,

:"-a etiqueLa para mostrar una imagen estrimgtr, no tiene fin


-ng>) y la direccion de la imagen respecto al- documento que
::--rros escribiendo se la pasamos al atributo src (source). En
-.-: ejemplo la imagen de logoU.gif se encontrara en l-a carpe-
: -:genes que esta dentro de Ia que contiene a este archivo
'-:- que estamos generando. Las imagenes sofo pueden ser .jpg
::f para una correcta visualizacan en todos los navegado-
.-../p,
: '::demos mostrar la imagen centrada en el navegador si mete-
, = su etiqueta en el interior de una "div con aLributo
--anlartr . - /n.
;</_u>
---=LtrttLUr

<I --fmagen centrada-->


,,'- aIign=IIcenterrt r.img stc=rrimagenes/1ogoU. gif ,, ></di'>

; ,,-:s enlaces vienen dados por 1a etigueta "a", de1 ingles


.--.:::or" (ancIa) . El texto que metamos entre "ail y ,t/a,' sera
. - I*e podamos pinchar con el raton para ir a Ia direccion

' -:=:.ficada en el atributo "href" del ancla:</p>

' "-.::f =rthttp : I lwww .urj c . es " >Universidad Rey Juan Carlos</a>

,,:bien podemos complicarlo un poco metiendo una imagen


;.ncharla como enlace y centrando todo.</p> <div
- ::-=rrcenterrt> <a href=trhttp : I /www.urjc.es,'><img
Frcuonos
354
>< l a> </div>
src=rt imgenes/IogoU'gf"

</body> <l--Fin de1 cuerpo de Ia pagna-->


./titmtr. I --Fin del documento HTML-->

Notas:UnenlaceaunadireccindecorTeosepuedeetiquetarmediante:<p>E-ma-- sobre una r -


> webmaster' a' <lP'' Unatilde
<a href ="mailto:urjcourjc'es'r eso asegurar que en cu-'
t;;;;; ;'on" # es la vocal a acentuar'
cal se debe escribir como un carcter extrar.
se ,;;;;;" una tilde sobre una vocal y no
quier ordenador
a efectos prcticos lo
ignoraremos'
n
"*borgo
dicotmica en un fichero
hinario
10.8.10 Bsqueda binaria o
Labsquedabinariasepuedeaplicar.enestructurasdedatosquepermitenaccesodire.
porloquesepu"o"u,u,"nltsficherosbinariosqueestnalmacenadoSeflsoptlf:
direccionables'
;.J:*Htero b in ar
"''1"'T-":l :::: 1,:
io que alm ac en

#;"1''*-*'":T:""',."fi
]':":t:;"n,T:X[i": :,.'
o,o,i"",lJlff Hil:"X,:::.:ff
i::il:::#;:H1: [',::?i:ilffi;,r ;"i
:::i:::ff::ti;li;lliil],'
e:
J"J:J:,:::J:::"""0:'"

#ffiil:*:l*::11;;"1'";1[:'
i::lli:,"$:1,"J;ii1xl;til?"il1;':il:*trl,:^T:::tH"J::':X?i#:Tl;
','J:'J,1?.:r;:X1""$?#"'ilX"'*f utilizando bs' 1a -'
o"nas consultas
T i?:il:ll:?:H#::T[::,T:Ttl'*"
binario'
i.trtc,*i.u sobre el propio f,chero

10.8.11 RuPturas de control


consta de ms de un reg
'

algunos problemas e1 fichero que se quiere procesar


En
lgicoconelmismot"t"nunoouu'io'd"'o'campos'Adems'elflcheroeste':
nadoporunodeu.n",.*,o"sY'eventualmente'ensegundootercerlugarpor... de todas 3Q.-:
tipo de informacin o resumen
El objetivo.'"i" '"'"oU"*t "ffl
componente. oo" tornpu't"n "t
*i1t"1v|1r en alguno de sus campos'
toil'io'*ucin
Sea un fichero conlnlormaclutr LrL rorventas d:
de las "'":T::::ifffi#['
stb ,
contrene informacin
por zonas' Cada componente de1 flchero que ha rea" -'
geogrficamente cdigo de la zona. en la
de1 producto,
producto vendido
y las unidad.; ;ilff-
!f ; t:T:: ::::"":::"T::3","[1
"*, "i"orgo
1a venra
de zona' va que todos
::l|-*
los produi
:iffi[J:::i#ffi:"Tffiffi"i;u,";;;d"
r.enden en todas las zonas'
prr'-:-
de zona' escriba un
que el fichero est ordenado por cdigo
1. Suponiendo
que obten ga .., *:
iJ:, ::[::J':i"?ffi #;il;
"' i:;il :lt::l*,,,'JT,'::il
;il^'" v'otuid" unidades
Tl.#::;
vendidas e n -

zona.
Sor,ucroNrs 355

2. Suponiendo que el fichero est ordenado por cdigo de zona y, dentro de cada
zona, por cdigo de producto, escriba un programa que obtenga un informe por
pantalla de las unidades vendidas. El informe deber tener una lnea por cada
zonay producto dentro de esa zona. Cuando se acabe una zona se indicar, en
otra lnea, el total de unidades vendidas enla zona.

10.9 Soluciones
10.9.1 Copia de ficheros de texto
,
Se van a plantear dos soluciones pafa tealttzr la copia de un flchero de texto.

1. La primera solucin copia el flchero origen en el destino leyendo y escribiendo


catcter acarcter, sin tener en cuenta las lneas.

PROCEDURE CopiaCaracterAcaracter(VAR FOrg, FDes: text) ;

VAR
r. hzr.

BEGIN { CopiaCaracterACaracter }
reset (FOrg) ;
rewrite (FDes) ;
WHILE NOT eof (FOrg) D0 BEGIN
read (hOrg, car) ;
wrrte (f'ljes, car ) ;
,y
close (FOrg) ;
cfose (FDes) ;
END; {CopiaCaracterACaracter}

l. Esta segunda solucin copia el fichero origen en el destino considerando tanto


caracteres como lneas.

PROCEDURE CopiaCaracterYlinea(VAR FOrg, FDes: t-ex: ;

VAR
car: char;
BEGIN i CopiaCaracterYLinea)
reset (FOrg) ;
rewrlte (t'Des) ;
WHILE NOT eof (FOrg) DO BEGIN
IIIHILE not eoln(FOrg) D0 BEGIN -
read(FOrg, car);
write (FDes, car)
356 Frcnnnos

END;
writeln (FDes) ;

readTn(rorg);
END;
l['r)rl
\l v!f / ,
.

- l^a lL'llaq
\L Dee l
I .
I

END ; lCopiaCaracterYLrnea)

El programa completo:

PROGRAM CopiarF icheroTdxto ;

VAR
FOrigen, FDestno: text;
correcto: boolean;
nombre: string;

FUNCTION Existe(VAR fichero: text): boolean;


BEGIN iexiste)
{sr-}
reset (fichero) ;
ler-l
IY- ' ]

Existe := (IOResult = 0);


END; {existe}

PF.CCEDURE PedirFicheroOrigen(VAR FOrg: text; VAR


correcto: boolean);
VAR
caT i Cha::;
nombre : st::i:rg;
BEGIN
REPEAT
CorIeCto := TRUE;
write ('Escribe el nombre del fichero ' ,
'que quieres copiar: ' ) ;
readln (nombre) ;
assign (FOrg, nombre) ;
IF NOT EXiSTC (FOTg) THEN BEGIN
writeln('El fichero no se encuentra',
' (pulse cualquier tecla Para
seguir o S para salir)') ;
read (car) ;
COTTECTO := FALSE;
Sor,ucroNns 357

END;
UNTIL correcto OR (upcase(car) = 'S,);
END;

PROCEDURE PedirFicheroDestino (VAR FDes: t.ext; VAR


L\\qqL'. \ss\qa\\',
\\R
=r:--- *S--\
nomlre: sLring;
DETIT
D!UAI\

REPEAt'
correcto := TRUE;
write('Escribe el nombre del fichero copia: ,);
readln (nombre) ;
:oo.i (FDes, nOmbre) ;
IF Existe(FDes) THEN BEGIN
writeln ('El fichero copia existe (pu1se R , ,
'para reescribirlo, S para salir)');
read (car) ;
lF Upcase(car) <> 'R' THEIV
correcto := FALSE;
END;
UNTIL correcto OR (Upcase(car) = 'S');
ItrIn .

IROCEDURE CopiaCaracterACaracter(VAR FOrg, FDes: text) ;


- -1D

car: char;
SfGIN {CopiaCaracter}
reset (FOrg) ;
rewrlte (lDes) ;
WHILE NOT eof (FOrg D0 BEGIN
read(FOrg, car);
wrl_te (hljes, car) ;
END;
close (FOrg);
:lose (FDes) ;
r.-- , iCopiaCaracter)

:: -::DURE CopiaCaracterylinea (VAR FOrg, FDes: text) ;


:_:
':-. . h=r .
358 Flcnonos

BEGIN { CoPiaCaracterYLinea }
(t"Org)
reset ;

rewrite(bDes);
hIHILE NOT eof (Forg) D0 BEGIN
P
v,
WHILE not eofn(FOrg) D0 BEGIN
read(FOrg, car);
write (FDes, car)
!L
END;
writeln 1fes) ;
readln (FOrg) ;
END;
close tFOrg) /
c,Lose ('Des ) ;

END; iCoPiaCaracterYLinea)

BEGIN {Programa PrinciPal}


PedirFicheroOrigen(FOrigen' correcto) ;

IF correcto THEN BEGIN


PedirFicheroDestino (FDestino' correcto) ;

IF correcto THEN
CopiaCaracterACaracter ( F0rigen' FDestino);
(FOrigen' FDestino) )
{o CopiaCaracterYLinea
END;
END. {lrograma PrinciPalJ

10.9.2 Sustitucin y recuento de vocales


PROGRAM SustituirYContarVocales ;

VAR
l^vi-^. iovl :

PROCEDURE Almacenar (VAR fTexto: text);


i/AR
car : char;
i:3IN {elmacenar}
:ewrite (fTexto) ;

,.;:tte1n 'Escribe el- texto: ' ) ;


(

:.: ?IAT
read (car) ;
E
-: car <> chr(13) THEN END;
tfTexto, car) ;
"',:-:e
:a: chr(13); wri t:
,1,--- --
SorucloNns 359

close (fTexto);
:i.); {almacenar}

-:iOCEDURE Most.rar (VAR fTexto: t.ext) ;


--R
r. h-.
contA, contE, contI, conto, contU: inLeger;
::GIN {Uostrar}
cont.A : = 0;
contE : = 0;
^^lT .-
.- u;
^
contO : = 0;
contu ,= A;'
reset (fTexto);
WHILE NOT eof (fTexto) DO BEG]N
read (fTexto, car);
CASE car 0F
,4, ,,A, : BEGIN
contA := contA + 1,.
writ.e (, ,)
END;
tFt //. DETIT
e . Dlgal!

contE := contE + 1;
write (, ,) ;
END;
,I, ,,i, : BEGIN
contl := ConLf +
write (, _,) ;
END;
'a' ,'o' : BEGIN
contO := conto +
writ.e (, _,) ;
END;
,U,
,,U,: BEGIN
contU := conLU + 1;
write (, ,) ;
END;
ELSE
write (car) ;
trI\Tn.
!a!u/ f^-^^i
luqDEJ
IND; {whilei
,,;riteln;
360 Frcnnnos

writeln ('La a aparece 'rccntA, ' veces');


writeln ('La e aparece ' , contE, , rraac,\.
vU99, /,
writeln ('La i aparece ' nnl T ' veces');
writeln ('La o aparece ' , conLo, , raac/\.
vueru / /
writeln ('La u aparece 'rcontU, ' veces');
close (fTexto) ;
END; {fUostrar}

BEGIN {Programa principal}


assign (texto,'texto.txt' ) ;
Almacenar (texto) ;
writ.eln('El texto sin vocales y las est.adisticas'
' de aparicion de cada UIld Sofl: /);
Mostrar (texto) .

END. {Programa principal}

10.9.3 Encontrar los ms jvenes


PROGRAIvI LosNMas,Toveses ;
CONST
N = 10;
TYPE
TRegistro = RECORD
apellidos: strng[35J ;
nombre: string[20] ;
dni: strinS [9] ;
anioNacimiento: integer;
direccion: string[35J ;
codigoPostal: string[5] ;
ciudad: string [20] ;
END;

TFichero = FILE OF TRegistro;


TArray = ARRAY [1..N] OF TRegistro;
TEstructuraArray = RECORD
]-^^,
U..!\/\T,
datos: Tarray;
:. -_.

I
C

=:-:: ; jl : l;.=---stro;

f,
SolucroNns

nj ovenes : TEstruct.uraArray;
EIJI\TCTION Existe (VAR f ichero: TFichero) :

BEGIN {existe}
{$r-}
reset (fichero) ;

{$r+}
Exrste := (IOResuIr = 0);
close (fichero) ;
END; iexiste)

PROCEDURE CalcularNMasJovenes (VAR agenda: TFichero;


VAR nMenores: TEstructuraArray) ;
VAR
i i. . .in1-aaa-.
) tlruuYUr /

esMenor: boolean;
encrada: TRegistro;
BEGIN { CalcularNMasJovenes }
reset (agenda) ;
nMenores.tope := 0;
WHILE NOT eof (agenda) DO BEGI}J
read (agenda, entrada) ;
IF nMenores.tope < N THEN BEGIN
nMenores. t.ope : = nMenores. tope + 1;
nMenores. datos lnMenores . tope] . anioNacimienLo : = MAXINT
END;
.-
)'
r ll .

esMenor := FALSE;
REPEAT
j := j + 1;
IF entrada. anioNacimient.o <

nMenores . datos I j I . anioNac_:_.:_-_ l


THEN BEGIN
esMenor := TRUE;
i i= nMenores.tope DOWNTO j*1 :
FOR
nMenores.datos Ii] := nMenores.oa:_= ._--_ ;

nMenores.datos Ij] := entrada;


END;
LINTIL (j = nMenores.tope) OR (esMenor = [rue.;
END; iwuri,e)
close (agenda) ;
:l:l ; { CalcularNMasJovenes i
rl FrcuBnos

,: - ::-]URE MostrarNMasJovenes (nJovenes : TEstructuraArray) ;

.:_:
PI
A I\I .
U ' ' !r ,
::l:N {MostrarNMasJovenes }
FOR nJovenes'tope DO BEGIN
i:= 1 TO
VA
write (nJovenes'datos Iil 'apel]idos:35) ;

wrj-te (nJovenes 'd'atos lil 'nombre:20) ;


write (nJovenes 'datos Ii] 'dni:10) ; JE
write (nJovenes 'datos Ii] 'anioNacimienLo:5) ;

writeln;
END;
END; {MostrarNMasJovenes}

BEGIN {Programa PlinciPati


assign(agenda,' agenda'dat' ) ;
IF Existe (agenda) THEN BEGIN
calculartqasJovenes (agenda' nJovenes)
;

MostrarNMaSJovene s (nJovenes ) ;

E}\D
ELSE
,,,riielnt'EI fichero agenda.dat no existe')
;

\Tn I Proorama PrinciPal]


!!\!. t_--J

10.9.4 Yisualizar fichero con imagen


PROGRAM LecturalmagenRaw ;

CONST
vm-lr=rtl,
[Af |
-
TYPE
TFicherolma$en = FILE ob DYte;
TNombreFichero = string [501 ;
'.-iR
ancho, alto: integer;
correcto: boolean;
:,cherolmagen : TFicherolmagen ;

-'- -"r^ts/IIAR fichero: TFicherolmagen) : boolean;


a - . - --r )tI5Ls\r
--., -to\
----*.--l

:--j
1:s.: fichero) ;

:--l
Sor,ucroNns 363

Existe := (IOResuIt = 0);


{ exi ste }

?ROCEDURE PedirDatoslmagen(VAR fichero: TFicherolmagen;


VAR ancho, alto: integer;
VAR correcto: boolean) ;
-,:AR

n:v. hr.

nombre : TNombreFichero ;

:EGIN { nediroatostmagen}
REPEAT
COTTECTO : = TRUE;
write('Ruta y nombre de Ia imagen sin extension',
(.raw):');
readln (nombre) ;
nombre := nombre + EXT;
assign (fichero, nombre) ;
IF Existe (fichero) THEN BEGIN
write('Anchura: ') ;

readln(ancho);
write('Altura:');
readln (alto) ;

END
ELSE BEGIN
writeln('El fichero no se encuentra (Pulse ',
'una tecla para seguir o S:Salir)');
read (car) ;
correcto : = FALSE;
END;
l,'}JTIL correcto 0R (Upcase (car) ='g' '

:. 1; {ledirnatoslmagen}
.:ICEDURE PintarPixel (pix: byte) ;
: r,IN i eintarlixel )
write(pix:3);
-
-; ilintareixel)
::ICEDURE ErrorlecLura(comp_x, comp_y: integer) ;

.. IIN { ErrorLectura }
'.'-.i ral.
writeln('Error de lectura en efemento: ', comp x, ',',
364
FrcnBnos

comp_y) ;

writeln ('aborfada la ej ecucion del programa ' ' )


END; {Errorlectura}

FLICTION LecturaCorrecta (ancho, alto: integer; VAR


fRaw: TFicherolmagen) :boolean;
VAR
--t t. i nl aaov
--'--t--i
r. val lntt tv a .
pf
PL^v!. t

fallo: boolean;
BEGIN {lectura}
reset (fRaw) ;
fallo := FALSE;
., .-
.- 1.
r,
^
,, ._ 1.
| '- -t
WHILE (x <= alto) AND NOT fallo DO BEGIN
writeln;
WHILE (y <= ancho) AND (not eof (fRaw) ) D0 BEGIN
read (fRaw, Pixel) ;
pintarPixel (Pixel) ;
y := y+1;
END;
rF eof (fRaw) AND (y <= ancho) THEN BEGrN
errorlectura (x, y) ;
fallo := TRUE;
END;
y:= 1_;

x+1;
END;
LecturaCorrecta := NOT falIo;
close (fRaw) ;
end; {rrN }ectura}

PROCEDURE FinalExito;
BEG]N {rinalExito}
','-.iraln.
writeln ('Fin de programa con exito' ) ;
writeln('Alejate para ver el resultado') ;

Il.iD ; irinalrxito )

PRCCEDURE FinalFalIo;
BEGIN { rinalrallo}
Sor,ucroNBs 365

writeln ('Fin de programa con errores, ) ;


iND; {rina}ral1o}

:EGIN {Programa principal}


PedirDat.oslmagen(ficherolmagen, ancho, alto, correcto) ;
IF correcto THEN
IF LecturaCorrecta(ancho, a1to, ficherolmagen) THEN
finalExito
ELSE
f inalFallo;
ral l - .

r-
:.,U. t Programa prrncrpal J

10.9.5 Particin de un flchero binario


\ continuacin de detallan las soluciones de la particin de un fichero de acuerdo a los
-itintos criterios.

Particin de un fichero binario por contenido

. : IGRAM Part icionFicheroBinarioContenido ;


'_:5
TRegistro = RECORD
apellidos: string [351 ;
nombre: string[20J ;
dni: string [9] ;
direccion: string[35] ;
codigoPostal: string [5J ;
ciudad: stringl20J ;
turno: char;
:\Tn .

-tichero = F]LE OF TRegistro;


:

-i:igen, fMagnana, fTarde: TFichero;


-=:Logico: TRegistro;

ParticionContenido (VAR fOrg, fMan, flal: -: _::=ro, ;

r=j: TRegistro;
,' Part i c ionContenido )
:eset (f0rg) ;
:ewrite (fMan) ;
366 Frcnnnos

rewrite (fTar) ;
WHILE NOT eof (forg) DO BEGIN
read (fOrg, reg) ;
IF reg.turno = 'M' THEN
write (fMan, reg)
ELSE
write (fTar, reg) ;

END; {wttrlri
close ( fOrg) ;
close (fMan) ;
close (t'Iar) ;
END ; {ParticionContenido}
BEGIN IPrograma principa])
assign (fMagnana,' turnoMagnana.bin' ) ;
assign (fTarde, 'turnoTarde.bin' ) ;
assign (fOrigen, 'TodosTurnos.bin' ) ;
ParticionContenido (fOrigen, fMagnana, fTarde) ;
-1
EjNlJ. t Programa prlncrpal.f

Particin de un fichero binario en secuencias de longitufN

PROGMM Part i c ionFicheroBinarioSecuenc iasN ;


TYPE
TRegistro = RECORD
apellidos: string[35] ;
nombre: string [201 ;
dni: string [9] ;
direccion: string[35] ;
codigoPostal: string [5] ;
ciudad: string[20J ;
turno: char;
END;
TFichero = FILE 0F TRegistro;
':-:.
:irigen, fPartl, fParL2: TFichero;
:=r-ogico: TRegistro;
-_- _=JcL t

.:.,,:--:.1 ?a::rcionSecuenciasN(VAR f0rg, fPar1, fPar2: TFicherc,


n: integer);
-.-_::_
SolucroNrs 367

reg: TRegistro;
conr: inCeger;
cambio: boolean;
BEGIN { Particl-onSecuenciasN}
reseL (fOrg) ;
rewrite (fPar1) ;
rewrite (fPar2) ;
Camb1o := TRUE;
nnl .-
. n.
vt

WHILE NOT eof (forg) D0 BEGIN


read(fOrg,reg);
IF cambio THEN
write ( fPar1, reg)
ELSE
write (fPar2, reg) ;
Cont := cont + 1;
IF cont = n THEN BEGIN
cambio := NOT cambio;
cont := 0i
I
END;
END; {wurle}
close (fOrg) ;
cfose (fPar1) ;
cl-ose (f Par2 ) ;
:l l; { ParticionSecuenciasNi

:: :IN t Programa prInClpa-L )


assign (fPart1,' fPartl.bin' ) ;
assign (fPart2 ,'fParL2.bin' ) ;
assign (fOrigen, 'afumnos.bin, ) ;
writ.e('Teclea eI valor de N: ,\;
readln (n) ;
Part.icionSecuenciasN (fOrigen, f Part1, fparL2, n) ;
:-:. iPrograma principal]

: rticin de un fichero binario en secuencias ordenadas


- I - lzu\M ParLicionFicheroBinarioSecuenciasOrdenaCas
;
'-l
_:_
TRegistro = RECORD
apellidos: string [351 ;
nombre: string [20J ;
368 Frcnnnos

dni: string[9J ;
direccion: string[35J ;
codigoPostal : string [51
ciudad: string[20J;
turno: char;
END;
TFichero = FILE OF TRegistro;
VAR
fOrigen, fPar[l, fParL2: TFichero;

PROCEDURE ParticionSecordenadas (VAR fOrg, fParl ,fPar2: TFichero) ;

VAR
regAnt, regAct: TRegistro;
cambio: boolean;

BEGIN { rarticionSecOrdenadas }
reseL (forg) ; t
rewrite (fPar1) ;

rewriLe (fPar2) ;

:ambio := TRUE;
::c.lrt. aPellidos i= ' ' i
,';:---: NCT eof (fOrg) DO BEGIN
-..-^i j--- zoaAcj-).
-=:- ---y/!tYreu/ /

-: l.: - :egAnt. aPellidos <= regAct . apellidos) THEN

:1::--- := NOT cambio;


-= ^a--_ ^ _-_-:_,
'i:-:::Pa:-, regAct)
ELSE
wrire :?er'-, :egAct);
rreaAnl
sY]r u .= -cfA-'

END; {wttri,r}
close (fOrg) ;
cfose (fPar1) ;
close 1fPar2) ;
E\D; {ParticionSecOrdenadas}

BEGII\ {Programa PrinciPal}


asslgn fParcl, 'fPartl.bin' ) ;
assLgn fParL2, 'F.ParL2.bin') ;
assign (fOrigen, 'alumnos.bin' )
Sor,ucroNns 369

Partici-onSecOrdenadas (f0rigen, tPartl, fPart2) ;

END. {Programa principal)

10.9.6 Fusin de flcheros binarios

El punto crtico de la fusin de dos ficheros es garantizar que se procesan todas la


componentes de ambos. Con un control convencional de la salida de los bucles qu
realizan la lectura secuencial de los ficheros, a travs de eof ( ), se puede quedar e
ltimo registro de cada uno sin procesar. Por el1o, la solucin que se propone utiliza u:
procedimiento especfico para realizar la lectura de los ficheros, y el control de detecci
del fin de cada uno se realiza a travs de sendas variables booleanas.

PROGRAM FusionDosFicherosBinarios ;
TYPE
TDATOS = RECORD
nombre: string[20J ;
apellidos: string[35J ;
END;
I
TReqistro = RECORD
clave: rnteger;
datos: TDatos;
END;
TFi-chero = FILE 0F TRegistro;
-,.AR

fFusion, f1, f2: TFichero;


reglogico : TRegistro;

;ROCEDURE LeerFichero (VAR fichero: TFichero;


VAR registro: TRegistro;
VAR fin: boolean);
:iGIN {leerfichero}
IF NOT eof (fichero) THEN
read ( f ichero, regisLro)
ELSE
fin := TRUE;
:i.lJ; tLeerF'].cnero]

:ICEDURE FusionFicheros(VAR f1, f2, fFus: TFrchelc ;


'.r1,

tL, 12: TRegistro;


fin1, fin2: boolean;
:::IN
310 Frcurnos

rewrite (fFus) ;

reset (f1) ;
reset (f2) ;
]
!r11r -1
,-
. -
f:lao.
Lqre,

f:.n2 := false;
LeerFichero(f1, 17, finl) ;

LeerFichero (f2, 12, fin2) ;

IdHILE NOT finl- AND NOT fin2 D0 BEGIN


IF 11.clave <= 12.clave THEN BEGIN
write(fFus, r1) ;
LeerFichero(f1, T7, finl) ;

END
ELSE BEGIN
wrice (fFus, 12) ;
LeerFichero(f2, 12, ftn2) ;

END;
}
END; {wHrf,r}
WHILE NOT finl DO BEGIN
write (fFus, r1) ;
LeerFichero ( f1, T7, finl ) ;
E\TN.

WHILE NOT fin2 DO BEGIN


i;:ite (f Fus, 12) ;
=r:Fichero (f2, 12, fin2)
-
;
:l.l:
--_:= -- *:
l aca f I

END; {Fusron;-c:r=::s

BEGIN {Programa prrncrpali


assign(f1, 'f1.bin";
assign(f2, 'f2.bin');
assign(fFusion,' fusi-on.bin' ) ;
FusionFicheros (f1, f2, fFusion)
- _\J. Programa prlnclpaI.l
l- - \
t

10.9.7 Ordenacin de un fichero por mezcla directa

?LCGLAM 0rdenacionMezclaDirecta ;
TYPE
TRegisrrc = RECORD
Sor,ucroNns 311

codigo: string[10] ;
denominacion: strinq [3 0] ;
END;
TFichero = FILE OF TRegistro;

fOrigen, fPartl, fparL2: TFichero;


regLoglco :'I'Reglstro;

PROCEDURE ParticionSecuenciasN (VAR fOrg, fpar1, fPar2: TFichero;


n. rruuYUr
ra. i nl-aa-\ ,
/ /
'iaR
reg: TRegistro;
cont : int.eger;
cambio: boolean;
: IIIN { narticionSecuenciasN}
reset (fOrq)
\- --, "
.

rewrite (fpar1) ;
rewrit.e (fpar2\ ;
cambio := TRUE;
anl . = n.
WHILE NOT eof (fOrg) D0 BEGIN
read (fOrg, reg) ;
IF cambio THEN
write (fpar1, reg)
ELSE
write (fpar2, reg) ;
cont := cont + 1;
IF cont = n THEN BEGIN
cambio := NOT cambio;
Cont : = 0;
END;
END; {wHrlo}
close (f0rg) ;
close (fparf) ;
close (fPar2) ;
:, -, {ParticionSecuenciasN}

:--I:)URE Leer(VAR f: TFichero; VAR r: TRegistro;


VAR fin:boolean);

-: NOT eof (f) THEN


read (f , r)
)tz f,'rcnnnos

ELSE
fin := TRUE;
END;

PROCEDURE FusionSecuenciasN(VAR fOrg, fParl, fPar2: TFichero;


n: Iongint) ;
IIi:

regF1, regF2: TRegistro;


finl, fin2: boolean;
contFl, contF2 : lonqint.;
:E1T\T
J !g II\

rewrite (fOrg) ;
reset (fPar1) ;
reset lfPar2)
finl : = false;
fin2:= false;
Leer(fParr1, regF1, lint) ;
Leer ( fParL2, regF2, fin2\ ;
conlF'T .- n.
.^nlF', .=
. n.
vl

WHILE NOT finl OR NOT fin2 DO BEG]N


WHILE NOT finl fin2 AND (contFl < n)
AND NOT
AND (contF2 < n) D0 BEGIN
IF regF1. codigo <= L:e9F2. codigo THEN BEGIN
write (fOrg, regFl) ;
Leer (fPart1, regF1, finl) ;
contFl := cont.Fl + 1;
END
ELSE BEGIN
write (forg, regF2) ;
Leer (fPart2, regE2, fin2) ;
contF2 := contF2 + 1;
END;
END; {wurlr}
1
WHILE NOT finl AND (contFl < n) D0 BEGIN
write (fOrg, regFl) ; P]
Leer(fPart1, regF1, finl) ; T'
contFl := conLFl + 1;
Errn.
LNJ; TI4HILE]
IIHILE NOT fn2 AND (contF2 < n)DO BEGIN
write (fOrg, regE2) ;
Leer(fPart2, regF2, fin2) ;
. SoLUCToNES 313

contF2 := contF2 + 1;
END; {wurlr}
ContFl := 0;
ContF2 : = 0;
END; iwiirln i
close (f0rg) ;
close (fPartf) ;
close(fParL2);
:. --t .

.:SCEDURE MezclaDirecta(VAR fOrg, fPar1, fPar2: TFichero) ;


.-:
reg: TRegistro;
n, numRegistros: longint;
::lIN {MezclaDirecta}
lr
h
.-
.-
r,
f . i
I
reseL (fOrg) ;
numRegistros := filesize(fOrg) ;
close (fOrg) ;
WHILE n < numRegistros DO BEGIN
ParticionSecuenciasN (fOrg, fParl , fPar2, n) ;
FusionSecuenciasN (fOrg, fParl , fPar2, n) ;
n:=n*2;
END; {wurle}
:,,); iMezclaDirectai

:: -:IN t Programa prrnclpal


l_ - \
J

assign(fPart1,' fPartSl.bin' ) ;
assign(fPart2,' fPartS2.bin' ) ;
assign (fOrigen, 'afumnos,bin') ;
MezclaDirecta (fOrigen, fParLl , fParL2) ;
l_ -
:. tPrograma prlnclpar
1

-. ]

1U.9.8 Ordenacin de un fichero por mezcla natural


. : IGRAM OrdenacionMezclaNatural ;
. _'?E
TRegistro = RECORD
codigo: string[10] ;
denominacion: string [30J ;
END;
TFichero = FILE OF TRegistro;
314 FICHERoS

VAR VAR
fOrigen, fPartl, fParL2: TFichero;
reglogico: TRegistro;
DE
PROCEDURE ParticionSecOrdenadas (VAR fOrg, fParl ,fPar2: TFichero) ; DEU

VAR
regAnt, regAct: TRegistro;
cambio: boolean;

BEGIN { ParticionSecOrdenadas }
reset (fOrg ;
rewrite (fPar1) ;
rewrite (fPar2) ;
cambio := TRUE;
regAnt.codigo i= ";
WHILE NOT eof(fOrg D0 BEGIN
read (fOrg, regAct) ;
IF NOT (regAnt.codigo <= regAcL.codigo) THEN
cambio := NOT cambio;
IF cambio THEN
write (fPart, regAct)
ELSE
write (fPar2, regAct) ;
regAnt := regAct;
END; {wurlu}
close (f0rg) ;
close (fPar1) ;
close (fPar2) ;
END; {ParticionSecOrdenadas}

PROCEDURE Leer(VAR f: TFichero; VAR r: TRegistro;


VAR fin: boolean);
BEGIN
IF NOT eof (f) THEN
read (f, r)
ELSE
fin := true;
END;

PROCEDIIRE FusionSec0rdenadas (VAR fOrg, fParl , fPar2: TFichero) ;


Sor,ucroNBs 375

regF1, regF2: TRegistro;


fin1, fin2: boolean;
codAntFl, codAntF2: strj-ng[10J ;
: jGIN { FusionSecOrdenadas }
rewrite (fOrg) ;
reset (fPar1) ;
reset (f"Par2) ;
finl := FALSE;
ftn2 := FALSE;
Leer(fPart1, regF1, finl) ;
Leer(fPart2, regF2, fin2) ;

WHILE NOT finl OR NOT fin2 DO BEGIN


codAntFl := regFl.codigo;
codAntF2 := regF2.codigo;
WHILE NOT finl AND NOT fin2
AND (codAntFl- <= regFl.codigo)
AND (codAntF2 <= regF2.codi-go) DO BEGIN
IF regF1. codigo <= regF2. codigo THEN BEGIN
write (f0rg, regFl-) ;
write (regF1. codigo : 3) ;
codAntFl := regFl.codigo;
Leer(fPart1, regF1, finl) ;

END
ELSE BEGIN
write (fOrg, regE2) ;
write (regF2. codigo:3 ) ;
codAnLF2 := regF2.codigo;
Leer(fPart2, regF2, fin2\ ;
END;
END; {wHrlu}
WHILE NOT finl AND (codAntFl <= regFl.codigc :- ::l-l:
write (fOrg, regFl) ;
write (regF1 . codigo:3 ) ;
codAntFl := regFl.codigo;
Leer(fPart1, regF1, finl) ;
END; t wHrLE l
WHILE NOT fin2AND (codAntF2 <= re9F2.cci:gc1 D0 BEGIN
write (forg, regE2) ;
wriLe (regF2. codigo:3 ) ;
codAntF2 := regF2.codigo;
Leer ( fParL2, regE2, ftn2\ ;
316 FICHEROS

END; {wurrn}
END; {Wtttt u}
close (fOrg) ;
JIose (IPartr) ;
close (fPart2) ;
I),); {FusionSecOrdenadas}

;::SCEDURE MezclaNatural (VAR fOrg, fParl , fPar2: TFichero) ;


"- D

reg: TRegistro;
ordenado: boolean;
::GIN {MezclaNatural}
ordenado := FALSE;
REPEAT
ParticionSecOrdenadas (fOrg, fParl , fPar2) ;
reset (fPar2) ;
ordenado := (filesize(fPar2 = 0);
cl-ose (fPar2) ;
IF NOT ordenado THEN
FusionSecOrdenadas (fOrg, fParl , fPar2) ;
LTJTIL ordenado;
:1,-r; {MezclaNaturali
::l:N {Programa princiPali
assign(fPart1,' fPartSl.bin' ) ;

assign (fParL2, 'fParLS2.bin') ;


assign (f Origen, 'al-umnos . bin' ) ;
MezclaNatural (fOrigen, fParLl , fParL2) ;
-1.-. t- .l
tPrograma prlnclpa.Li

10,9.9 Asistente para crear pginas web


VA
', Programa que asiste en la creacin de pginas web personales simples.

PROGRAM As i sLenteWebPersonal ;
CONST PR(

NIIMIDIOMAS = 1; Vzu
NIIMEROESTUDIOS = 1;
;f-PE BEC

TFicheroTexto = text;
THes = string [10J ;
TDia = 1..31;
Sor,ucroNns 371

TAnio = 1900..2100;
TNombre = string[15];
TApellidos = string[30] ;
TFecha = RECORD
dia: TDia;
mes: TMes,.
anio: TAnio;
END;
TDi reccion=RECORD
calle: string[20] ;
numero: integer;
codigo: string[5] ;
localidad: string[15] ;
provincia: string[15J ;
END;
TEstudio = string [15] ;
TEstudios = array Il..NumeroEstudios] OF TEstudio;
Tldioma = string[15];
Tldiomas = arrayIl..NumIdiomas] OF Tldioma;
TCurriculum = RECORD
nombre: TNombre;
apellidos : TApellidos ;
fechaNacimient.o : TFecha;
direccion : TDireccion;
Lelefono: string[9] ;
mail: string[40];
estudiosprevios : TEstudios ;
roromas : Idlomas;
'.1

foto: string[50] ;
END;

pagWeb : TFicheroTexto;
curriculum: TCurriculum;

PROCEDURE InicializacionCurriculum(VAR curir: l:l::.culum) ;


VAR
i . llluUYUr,
irra^^-.
BEGIN { fniciatizacionCurriculum}
wiLh Curr DO BEGIN
writeln ( ,Nombre : ,
);
readln(Nombre);
318 Frcunnos

writeln ('ApelIidos' ) ;
readln(Apellidos);
writeln ('Fecha de Nacimiento' ) ;

write (' Dia: ' ) ;


readln ( FechaNacimiento. Dia) ;

write (' Mes: ' ) ;


readln (FechaNacimienTO. Mes ) ;

write l' Anio: ') ;

readln ( FechaNacimiento . Anio) ;

writeln ('Direccion' ) ;

write (' calle: ' ) ;


readln (Direccion. CaIle) ;
write (' Numero: ') ;
readln (Direccion. Numero ) ;
write (' Codigo Postal: ') ;

readln (Direccion. Codigo) ;


write (' Localidad: ') ;

readln (Direccion. Localidad) ;

write (' Provincia: ' ) ;


readln (Direccion. Provincia) ;

write('Telefono:');
readln (Telefono) ;

write ('Correo El-ectronico: ' )

readln (Mait) ;
FOR i := 1 TO NumeroEstudios DO

BEGIN
write ('Estudios Previos ' ,

readln (EstudiosPrevios Ii] ) ;

END;
FOR i := 1 TO Numldiomas DO

BEGIN
write ('rdioma ' , i,
readln(rdiomas Ii] );
END;
write ('Ruta nombre de la foto: ');
readln (F',oto )

r'-- f -i ei:l i zacionCurriculum)

.: -l:l-:.1 MostrarEstudios (curr: TCurriculum; VAR


n=n.
vuY . TE.r cheroTexto) ;
SolucloNe s 319

i . i nt-aaa-,
reuYur,
BEGIN {MostrarEstudios}
FOR i := 1 TO NumeroEst.udios-1 DO
write(pag,,,, curr.Estudiosprevios [i],,,, ) ;
f n-,.i r ^
tEvrra mostrar 1a ",', al final del ultimo)
write (pag, " , curr.Estudiosprevios [NumeroEstudios] ) ;
END; iMost.rarEstudios)

PROCEDURE Mostrarldiomas (curr: TCurriculum;


VAR pag: TFicheroTexto) ;
VAR
i . int-aa-.
rrluuYUr,
BEGIN {Mostrarldiomas}
FOR i := 1 TO Numldiomas-1 DO
write(pag, , ,, curr.Idiomas[i], ,,,)i
I n.'i . mostrar Ia ,,,
IEVTLd " al final deI ultimo)
write (pag, ' ' , curr. Idiomas lNumrdiomasl ) ;
END; {Mostrarldiomas}

PROCEDURE CreacionCabecera (curr : TCurriculurn;


VAR pag: TFicheroTexro r;
BEGIN {CreacionCabecera}
writeln (.pag, ,<head><t.it1e>,
, curr . Nombre,
, ,
,
curr.Ape11idos,, </title></head>, ) ;
END; {CreacionCabecera}

PROCEDURE CreacionCuerpopagina (curr : TCurriculum;


VAR pag: TFicheroTexLo) ;
BEGIN {CreacionCuerpopagina}
writeln (pag,' <body><div align=,rcent.erilr.h1r,,
curr.Nombre,,,,curr.Apeltrdos,, .,LLr. il-.-r, ;
writeln(pag,' <div align=ilsgnlgrrr.ing SuC=r,, a.:!: .aa--a,
"'><f dl>' ) ;
writeln(pag,,<p><b>Nombre:<fb> , ,ct)rr.Nombre ,,<
i>, ) ;
writeln(pag, ,<p><b>Apellidos :</b> , ,
curr.Apellidos, , ./pr,) ;
write (pag, '<p><b>Fecha de Nacimiento : <lb> , ,
curr.FechaNacimiento .Da,, f ,,
curr.FechaNacimiento .Mes,, f , ) ;
writeln (pag, curr. FechaNacimiento.Anio,,, lpr, ) ;
write (pag, ,<p><b>Direccion :<fb> Cf , ,
curr. Direccion. Ca11e,
380
FlcHsnos

',',ct)TT.Direccion'Numero"
curr.Direccion'Codigo"' ) ; "'
writeln (pag, curr.Direccion' Localidad"
curr. Direc cion. Provinca, "'
,<fp>,);
writeln(pag,' <p><b>Telefono: </b>', curr'Tefefono'
, .lpr,) ;

writeln (pag,' <p><b>Correo Electronico : </b>


<a href ="mail-T0:' ,

curr.Mail ,'")' ,curr'Mail ,'<f a><fP>');


write(pag,'<p><b>Estudios Previos:</b>' ) ;
MostrarEstudios (curr, Pag) ;
writeln (Prg, ' .lPr' ) ;
write (Pag, '<P><b>Idiomas: </b> ' ) ;
Mostrarldiomas ( curr, Pa9) ;
writeln(pag,'.lPr')

END ; { CreacionCuerPoPagina}

PROCEDURECreacionPagina(curr: TCurriculum; VAR


Pag: TFicheroTexto);
BEGIN {CreacionPagina}
writeln(pag,'<htmf>' ) ;
CreacionCabecera (curr, Pag) ;
CreacionCuerPoPagina (curr, Pag) ;

writeln (pag, ' </ht.ml>' ) ;


END; {CreacionPagina}

BEGIN {Programa PrinciPali


assign (PagWeb,' Pagina.html' ) ;
Inic ial i zacionCurriculum ( Curriculum) ;

rewrite (Paglleb) ;

CreacionPagina (Curriculum, PagWeb) ;

close (PagWeb) ;
END. {Programa PrinciPal}

2. Programa que asiste en la creacin de pginas web simples'

PROGRAM ASiStCNTCWCb;
TYPE
TTrtulo = string [25] ;
T?arrafo = string;
TFi:neroTexto = text;
Sor,ucroNns 381

pagWeb : TFicherotexto;
fin: boolean;
buf f er: word,.

PROCEDURE Inicializacion(VAR pagina: TFicheroTexto) ;


VAR
titulo : TTitulo;
BEGIN {rnicializacion}
writeln (pagina, ,<hLm1>, ) ;
writeln (pagina, ,<head>, ) ;
writeln ('Nombre del t i tulo de Ia web: ,
) ;
readln (titulo) ;
writeln (pagina, ,<tit1e>, , titulo, ,</t.itle>,) ;
writeln (pagina, , </head>, ) ;
writeln (pagina, ,<body>, ) ;
writeln(pagina,,<div align=rrcenter,><h1>,, titulo,
, </h1,><ldiv>,) ;
rND; { rnicializacion}

?ROCEDURE Parrafo(VaR pag: TFicheroTexto) ;


-,IAR

parrafo, parrafo2: Tparrafo;


centrar: char;
3cIN {earrafo}
writeln ('Introduzca el texto de1 parrafo: ,) ;
readln (parrafo) ;
parrafo2 i= " ;
IF length(parrafo) > 110 THEN BEGIN
l_^-
{DOS no dea tomar cadenas mayores de 127 caracteres}
writeln(,Siga escribiendo:, ) ;
readln (parrafo2) ;
END;
writeln('Lo quiere centrar en Ia pantalla? (S/N) ,);
readln (centrar) ;
IF upcase ( centrar) =' S' THEN
writeln (pag, ' <div align= " center" )(p), ,

parrafo+parrafo2,' < f p>< f div>, )

ELSE
writeln (pag, ' .p>' , parrafo+parrafo2, , </p>,) ;
:).1; {narrafo}
lil Frcnnnos

PROCEDURE lmagen (VAR pag: TFicheroTexto);


VAR
image: string;
centrar: char;
BEGIN {rmageni
write ('lntroduzca la ruta Y nombre de Ia imagen: ') ;

readln(image); (S/N) ')


writeln ('La quiere centrar en la pantalla?
readln (centrar) ;
IF uPcase (centrar) ='S' THEN
(pag , ' <div al ign=tr cent'errt img src=rr ' '
writeln "
image, ' "</div>')
ELSE
writeln (Pag, '<img src="' ' image' ' " '' ) ;

END; irmagen)

PROCEDURE Enlace (VAR pag: TFicheroTexto) ;

VAR
texto, link: string;
cenLrar: char;
BEGIN {untace}
write ('Introd'uzca el destino del enlace: ' ) ;
readln (link) ;

write ('Introduzca el texto que hara de enface:


');

readln (texto) ;
(S/N) ');
writeln('La quiere centrar en Ia pantalla?
readln ( centrar ) ;
IF uPcase(centrar) = 'S' THEN
*ria"tr, (p,g, '<div align="center" ><a href="' '
Iink, "'>', texto , '<fa><fdiv>')
ELSE
I rrI <f a>')
writeln(pag,'<a href="',link' 't'eXLo
i 10.9
"
END; {enl-ace}
?R0(

pagina: TFicheroTexto; VAR f inal i zar : IYPI


PROCEDURE Menu(VAR
boolean) ;

-.-:
rnal,oPcion: char;
:::-); {fuienui (I)magen"
i;rrteln('EIrge insertar entre (P)arrafo'
'o (E)n1ace');
:eaCln(opcion);
Sor,ucroNBs 383

TF upcase(opcion) = 'P' THEN


parrafo (pagina)
ELSE IF upcase (opcion) = 'l'
imagen (pagina)
ELSE IF upcase (opcion)
enlace (pagina)
ELSE
writeln('Error en Ia eleccion') ;

writeln (' Quiere terminar? (S/N) ') ;


readln(final);
IF upcase(final) = 'S' THEN
trnalrzar := TRUE;
{tutenu }

PROCEDURE Finalizacion(VAR pagina: TFicheroTexto) ;


BEGIN { Fina} i zacion }
writeln(pagina,' <fbody><fhtml>' ) ;
END; {finatizacion}

BEGIN {Programa principali


buffer := 1000;
assign(PagWeb,'pagina.html' ) ;
rewrite (pagl^leb) ;
Inicializacion ( PagWeb) ;
fin := FALSE;
WHILE NOT fin DO
Menu (PagWeb, fin) ;
Finalizacion (PagWeb) ;
close (Paglleb) ;
ENIJ. t Programa prlncIpal ,|

.10 Bsqueda binaria o dicotmica en un flchero binario


BusquedaB inariaFi chero ;

lFechaReduc = RECORD
mes: 7..L2;
anio: ir.teger;
:ITN.
_LtD I

-Registro = RECORD
referencia: string[15] ;
titulo: string[30J ;
FICHEROS

END;
autor: string[501;
fechaEdicion : TFechaReduc ;
IIrtJCl
paisEdicion: string [25] ;
3EGI}
numPaginas: integer;
numPrestamos: integer;
estado: char;
END;
TFichero = FILE OF TRegistro; l1-- .

'--t_:,
:--.JLE
:iblioteca: TFichero; :l^Ttf
_
- -bro : 'I'Reglstro;
--41!

::fe: string [15] ;


: :sicion: Ionglnt ;
..-on. her.
- u-y . vrs I

i ---;CTION BusquedaBinariaF (VAR biblio: TFichero;


ref: string) : longlnt;

extlnf, extsup, central: longlnt;


encontrado: boolean;
reglog: TRegistro; t'-_..
l:'-N iBusquedaBinariaF)
^,-LT-t .- WI
:,{LII]I ._ ^. I I -TtT
ovrsrn '= filesize(biblio)
er! uv sy
- 7; _,-lt!

encontrado := FALSE;
|^IHILE (NOT encontrado) AND (extsup>=extlnf ) D0 BEGIN II
cenLral := (extSuP + extlnf) div 2;
seek (bib1io, central) ;
read (biblio, reglog) ;
IF reglog.referencia = ref THEN

encontrado : = TRUE

ELSE
IF reglog.referencia < ref THEN

extlnf := centraf + 1
ELSE
extSuP := central - 1;
.'- illlILEJ
-, -..-::-:radO THEN
.-=;-:iaBinariaF := central
:,::
: .-'l*=:==inariaF z= -L;
,l
Sor,ucroNns 385

:ND; {BusquedaBina:iaF}
j-lrlJCTION Existe (VAR f ichero: TFichero) : boolean;
IIGIN {existe}
{sr-}
reseL (fichero) ;

{$r*}
Existe := (IOResult = 0);
- l. /^vr.lt

.: ICEDURE Mostrarlibro ( Iibro: TRegistro) ;


::lIN {Mostrarlibro}
write (Iibro.referencia: 16) ;
wriLe (Iibro.tituIo:31) ;
write (libro.autorr51) ;
write (1ibro. fechaEdicion.mes : 3) ;
write (1ibro. fechaEdicion.anio: 5) ;
write (libro.paisEdicion 26) ;
write (libro.numPaginas : 5) ;
write ( Iibro. numPrestamos :4 ) ;
write (libro.esLado:2) ;
writeln;
- {Mostrarlibro}
r.-1, {Programa principat}
,ssign(biblioteca,'biblio.dat' ) ;
-: Existe (bibtioteca) THEN BEGIN
REPEAT
write('Teclee Ia referencia que desea consultar: ');
readln (refe) ;
posicion := BusquedaBinariaF(biblioteca, refe) ;
IF posicion >= 0 THEN BEGIN
seek(biblioteca, posicion) ;
read (biblioteca, libro) ;
Mostrarlibro (libro) ;
END
ELSE
wriLeln ( 'esa referencia no existe' ) ;
write (' "Quiere realizar otra consulta? (s/n) ')
readln (resp) ;
-NTIL Upcase (resp) = 'N' ;
:iose (biblioteca) ;
386 FrcuBnos

END
ELSE
writeln ('EI fichero bibio.dat no existe');
T-
ENIJ. t Programa prlnclpai lJ

10.9.11 Rupturas de control


IJnavez que los ficheros estin ordenados por el campo o campos de los que se quiere
obtener informacin, el tratamiento de rupturas de control consiste en procesr todas las
componentes con el mismo valor de dichos campos, que estarn en posiciones consecu-
tivas en el fichero.

1. Para obtener un nuevo f,chero en el que haya un registro lgico por cada zona, se
deben procesar todas las componentes con el mismo cdigo de zona y realizat el
sumatorio por cada una.
En este caso slo debemos controlar el cambio de zona, por lo que tenemos una
alto nivel para realizar un programa con
--lruptwa de control. Una descripcin de
una ruptura de control sera el siguiente:

LeerRegistro ( ) ;
I4HILE NOT f inFichero 0 D0 BEGIN
IniciacionCodigo ( ) ;
\,^IHILE coincideVatorCodigo 0 AND NOT f inFichero 0 D0 BEGIN
TratamientoCoincidevalorCodigo ( ) ;
LeerRegistro ( ) ;
E-'iD ; {wHIlr }
. -:-a. -zacionCodigo ( ) ;
ErT.
DI\U, ,'l-:r-:"

Ntese que no se han detallado los parmetros de los subprogramas, ya que van--
rn segn el probiema particular.
Una particularizacin de la descnpcin anterior al problema que nos ocupa se..-
1a siguiente:

PROGRAM RupturasControl 1;
TYPE
TRegistroVentas = RECORD
codigoProducto: string [151 ;

codgoZona: string [10J ;


unidadesVendidas: integer;
E\TN.

TRegistroVentasZona = RECORD
Sor,ucroNns 387

codigoZona: string [10J ;


unidadesZona: real;
END;
TFicheroVentas = FILE OF TRegistroventas;
TFicheroVentasZona = FILE OF TRegistroVent.asZona;

VAR
fVentas: TFicherovent.as;
fVentasZona : TFicheroVentasZona ;

PROCEDURE Leer(VAR fich: TF'icheroVentas;


VAR reg: TRegistroventas; VAR fin: boolean);
BEGIN {Leer }
IF NOT eof (fich) THEN
read (fich, reg)
ELSE
fin := TRUE;
trt\Tn. /r ^^-i

PROCEDURE calculoTotal-esPorZona (vAR fventas : TFicheroventas ;


VAR fVentasZona : TFicheroVentasZona) ;
VAR
reg: TRegistroVentas;
regNuevo : TRegistroVent asZona ;
fin: boolean;
codigoZonaAnt I string [10] ;
sumaZona: reI;
:iGIN {CalcutoTota}esporZona}
rewrite ( fVentasZona ) ;
reset (fVentas) ;
fin := FALSE;
Leer(fVentas, reg, fin) ;
I^IHILE NOT fin DO BEGIN
codigoZonaAnt := reg.codigoZona;
sumaZona : = 0.0;
WHILE (codigoZonaAnt = reg.codigoZona)
AND NOT fin DO BEGIN
:=
sumazona + reg.unidadesVendidas;
sumaZona
Leer(fVentas, reg, fin) ;
END; {wurle}
regNuevo.codigoZona := codigoZonaAnt;
regNuevo.unidadesZona := sumaZona;
388 FrcnERos

write (fVentasZona, regNuevo)


rrTn.
L!\U, ir,rurral
yVlf !!
I J
-1 - - - 1.-/onrc\
LJ-USe .
\.L!sll-qD/ ,

cfose (fVentasZona) ;
END ; { CalculototalesporZona}

FUNCTION Exist.e(VAR fichero: TFicheroventas) : boolean;


BEGIN{existe}
{sr- }
reset (fichero) ;
{$r* i
Exisre := (IOResult = 0);
close (fichero) ;
END; {existe}

BEGIN {Programa principa}}


assign(fVentas,' fVentas.bin, ) ;
assign (fVentasZona, 'fVenZona.bin, ) ;
IF existe(fVentas) THEN
CalculoTotalesPorZona (fVent.as, fVentasZona) ;
ELSE
writeln('El fichero de ventas no existe,);
END. {Programa principal}

2. Para obtener un informe con una lnea por cada producto dentro de cada _
y una lnea con los totales por zona, se deben procesar todas las compol.:-
con el mismo cdigo de zona y con el mismo cdigo de producto dentro dt ,, .

zona. llevando dos sumatorios: producto por zona y zona. En este caso deb;'
controlar el cambio de zona y el cambio de producto, por 1o que tenem, . _

rupturas de control. Una descripcin de alto nivel pararealizar un prograr-_


dos ruptura de control sera el siguiente:

LeerRegistro ( ) ;
WHILE NOT finFichero 0 D0 BEGIN
IniciacionCodigol ( ) ;
WHILE coincideValorCodigol 0 ANO
NOT finFichero O D0 BEGIN
IniciacionCodigo2 0 ;
I^IHILE coincideValorCodigol ( )

AND coincideValorCodigo2 ( )
AND NOT finFichero 0 D0 BEGIN
TratamientoCoincideValorCodigo ( ) ;

E
Sor,uctoNss 389

LeerRegistro ( ) ;
END; {wHrlu}
FinalizacionCodigo2 ( );
END; {wntLn}
FinalizacionCodigol ( ) ;
END; {wurln}

Ntese, que al igual que en el caso anterior, no se han detallado los parmetros
de
los subprogramas, ya que variarn segn el problema pafticular.
lJna particularizacin de la descripcin anterior al problema sera la siguiente:

PROGRAM Rupturascontrol 2;
TYPE
TRegistroVentas = RECORD
codigoproducto: string [15] ;
codigoZona: string [10] ;
unidadesVendidaS ; j nroaor.
END;
TFicheroVentas = FILE OF TRegistroVentas;
,7AR

r ventas :'.]-'I,'rcheroventas ;

;ROCEDURE Leer (VAR fich: TFicheroVentas;


VAR reg: TRegistroVentas;
VAR fin: boolean);
::crt\T fr ^^-1
IF NOT eof (fich) THEN
read (fich, reg)
ELSE
fin := TRUE;
l_
I I
^^r

,. - IaDURE CalculoTotalesporZonayporproducto (VAF.

.-1
reg: TRegiscroVentas;
fin: boolean;
codigoZonaAnt : string [10] ;
codigoProductoAnt: string [15J ;
sumaZona, sumaProducto: real;
: ::IN { Ca}culoTotalesPorZonayporproducto }
390 Frcunnos

reset (fVenLas);
r:
lIl-t-- := IrA.lrtr;
Leer(fVenuas, reg, fin) ;
WHILE NOT fin DO BEGIN
codigoZonaAnt := reg.codigoZona;
sumazona := 0.0;
writeln(codigoZonaAnt : 11) ;
WHILE (codigoZonaAnt = reg.codigoZona) AND NOT fin
DO BEG]N
codigoProductoAnt : = re9 . codigoProducLo ;
sumaProducto : = 0.0;
WHILE (codigoZonaAnt = reg.codigoZona) AND
(codigoProductoAnt = reg.codigoProducto)
AND NOT fin DO BEG]N
sumaProducto := sumaProducto +

reg. unidadesVendidas ;
Leer ( fVencas , reg, fin) ;
END; {wHrlr}
,
sumaZona := Sumazona + sumaProducto;
writeln (' ' :l!, codigoProductoAnt:16,
sumaProducto:6:0) ;
END; {wurln}
writeln(" i12, 'Tota1 zona ttt sumaZona:6:0);
END; {wHrlu}
cfose (fVentas) ;
END; { Cal culotota} e s PorZonaYPorProducto }

FUNCTION Existe(VAR fichero: TFicheroVenLas) : boolean;


BEGIN{ existe }
l- I

1P-L-l
reset (fichero) ;

{$r*}
Existe := (IOResulc = 0l;
close (fichero) ;
END; {existe}

:- jIN t Programa prlnclpal .l

assign(fVentas,' fVentas.bin' ) ;
-: Existe(fVentas) THEN BEGIN
writeln('Informe Ventas por Zona y Producto':40);
',.- l r o l - .

i.:iteln ('Zona' :77, 'Producto':16, 'UnidaCes' :10);


Sor,ucroNrs
391
uri
ry! r to l
uuaf -
.
,

CalculoTotalesporZonayporproducto ( fVentas ) ;
END
ELSE
writeln(,El fichero de ventas no existe,);
END. {Programa principa}}
W

Captulo 11

Punteros y estructuras de datos


dinmicas

: ' el captulo 7 se introdujo er array como estructura de


datos esttica que permite
rergar datos homogneos. Su mayor
inconveniente es que la cantidad de
': memoria
'-rvada se declaraba en tiempo de compilacin haciendo necesa.ia
una estimacin del
-:rao mximo de Ios datos para er problema a resorver.
posible saber de antemano las necesidades
sin embargo, no siempre
'' cle memoria de una ejecucin a otra.
El
;nejo de memoria dinmica permite controlar
de manera ms adecuada los recursos
- -'omputadora segn los requisitos de cada de
ejecucin.
En este captulo se introducirn los
conceptos bsicos necesarios para manejar
:ltemente los recursos del sistema as efi-
como el diseo de diferentes esucturas
jmicas' capaces de cle datos
- modificar su tamao en funcin de las necesidades
del programa.
'3se que el uso de punteros es una tarea
-' .lemas a programadores compleja y que incruso los clescuidos
crean
expeftos.

- 1.1 Punteros
un valor entero en un prograrna se declara
H:::::111
r:*" : ""cesita
co.nle-ner_un dato de esre ripo, f".-n"r, ;il;";;;
una varia-
:::
deciaraunavariabre-0"i,r"""ir.";;"t.*;'j;,:'B:',;",-',fj:'f,J*:fflT:
' !rv vraq! J 4)r )uLs51\arllenle. ue ra m1(mir manera algu_

-:i".J::T"'T"":::: "j]:1":::9" "*l,fres de tipos especial5 capaces


Jpa.e\ de contener
conter
9"*g-gT-..{r3. Esre tipo de variabtes ,on jlr_u^ ---- ,rrr;.ffi:
-
)s otle cc refio.o- ^lI^^ ^^-^-
,'::n:?::"':::::j:'
lar el valor contenido en: "11:'' "*:,'
,
t L"t ct d o r e
una posicin cle memoria determrnadal
x- ,
s,'r r. i,ffi r-
0,,; 1";;;;;
-
:T
i
:raxis :: J:::l' ::':l:'T i1''i;"p,;il'J :';'::ffi
en Pascal paraladeclaracin de un puntero
a entero
oles un,ipo bas er
es:

393
PUNTEROS Y ESTRUCTURAS DE DATOS
DINMICAS
)g4
pEntero, ^integer;
pEntero que es de tlpo-p*[[!!fo 9r'
En la lnea anterior se declara una variable llamada
s1o ser capaz de referenciar' o corn:--
cias al smbolo circunflejo "A" l Este puntero
tipo base at que se refiere .
ffi; ;;;;;ra;;ores de tipo enrero, puesro que el necesita un tipo base al que "
;;;;Jf ;;;.;" general la declaracin de un puntero el puntero o el tipo punl':
para definir
pueda referir y utiliza un smbolo de circunflejo
i"no. En el ejemplo anterior el tipo base es integer y para apunt;:
propiamente
valoresdeestetiposernecesarioreservarmemoriaparaguardarunvalorentero.E...
a travs de la declaracin de una 3Il*-
\
reserva ha podido ser realizada estticamente
de tipo entero:

Puntero; ()'
- 'l
PROGRAM
g,-{
VAR
pEntero: ^ integer ;
.l-laar.
entero : IltuLYe! / ., " .i:
t '.
BEGIN - (. - -" q-$- .' ".t

entero := 2i *uI'o' .-"


pEntero := @entero; ci'
'
\' '' "*."
.),-
{ ''
END.

Eloperaclot.,@,,,tambjnllamadooperadordedireccin,aplicadoauna
r/er.c-Ir.e tit poscit, cle ntentot'it en la que se en.:uentra. La a.signacin de )a
cie mernoria del entero al puntero le da control total al puntero sobre el valor dcl enter'
.\s. el puntero estar en disposicin de actuar sobre el valor del entero una yez que e,\l;
enlazado. En Pascal. la forma de ret-erenciar al valor al que est apuntando es a trar-.
dei operador posthjo circunflejo "A" aplicado a la variable puntero, tambin llamadi'
operador de cle s re.feretlL'iLt o indireccin.

L'lr^ L
IJ!]lLurv .- J t

Mediante el puntero se puede actuar sobre la variable de tipo entero que est decla-
rada, de hecho, en este ejemplo se ha conseguido alterar su valor, de manera que en:
s
a
VAR
pEnterc' ^inLeger; pi
entero : integer; 11r

BEGIN pr
.- 4.
^lv^ se
a
pEntero : = @entero; ut
Lhf^v^ l.
.- r t
Plluurv ac
write (entero) ;
END; V
'l
PuNrpnos 395

entero

pEntero

'-gura 11.1: Puntero que contiene la direccin de memoria flcticia 215 correspondiente
- ,ina variable entera con valor 2 r'
- ravs del puntero se ha modificado el valor de la variable ent.ero y en pantalla se
-.u.stra 3 en lugar de 2.
t
= Para indicar que un puntero no apunta a una direccin especfica de memoria se le
-':qna un valor especial, tlrllEs especialmente til, como se ver ms adelante, y puede
:- asignado
|j!1eluiT.t]po 9-e puntero. Ntese que esto no conlleva que el valor del
-ntero sea indefinido, pues est my bien deflnido con el valor de NrL.
Hasta ahora se ha introducido el concepto de puntero haciendo uso de variables de
- s annimos pero, al igual que con cualquier otro tipo de datos, se puede
- pio. Nuevamente se utiliza un tipo base para la creacin del tipo puntero: definir uno

,: , IRAM TipoPuntero;
-,
-:-
-l

T-! ^.^^
_lIlLErU i rro_o-.
= f,I-LEyCr;
lPuntEntero = ^in1-eoer.
-:
DEntero: TpuntEnLero;
entero : TEntero;

,1,1.1 Manejo de memoria dinmica


: ra mencionado que el uso de un puntero necesita la reserva previa de esp.r;ro para
' -:cenar un valor del tipo base. Sin embargo no es necesario cleclarar Lrne \aiable
' : :ipo base para rcalizat esta accin. A partir del puntero es posible reser\.ar
memoria
---r guardar un valor del tipo base del mismo. En Pascal. esto se realiza trar.s de la
-
- da al procedimiento new pasndole el puntero. Tras llamar a este procedimiento,
el
' -
3ro que se pasa queda apuntando al bloque de memona reserrado.''De esta
manera
I ':nnite el acceso a ese bloque a travs de su identillcador.tsin embargo, new provoca
'- :.serva explcita de memoria que tras haber sido utilizada
debe ser liberada.'Esta
- rn liberadora se realiza en Pascal tpicamente a travs del procedimiento dispose.

.:
396 PUNTERoS Y ESTRUCTURAS DE DAToS DINMICAS

pEntero: ^integer; 'tt


BEGIN t'
lSElL(PEntero) ; '4
p!.;ntero := 3;
A. .).-{ 3 t?
Eg"(pEn!ero^) ; r> . 1,- g16.;r-=l

dispose(pEntero) ' o \L..Lcr-\ )(\"


END;

En este ejemplo se reserva memoria a travs del puntero para albergar un r a- - ,

tipo entero. Una vez reservado dicho espacio se le asigna el valor 3 y se escn'n- .'
pantalla. Tras utilizarlo debemos liberar la memoria previamente reservada, utiliz*- -
el procedimiento dispose.

11.1.2' Simulacin de paso por referencia


Las asignaciones de variables puntero son totalmente anlogas a las de otro tipo de J-'
simples. Puesto que un puntero contiene por valor una posicin de memoria. er -
asignacin la posicin a Ia que apunta un puntero queda anotada como valor en j:
variable puntero. En ese caso se dice que ambos punteros apuntan a la misma inlc':-'-
cin. Esto, obviamente no quiere decir que la informacin se duplique.
Puesto que a travs de un puntero se puede controlar el valor de una posici,-,.' - ,

memoria que no ocupa el propio puntero, cabe la posibilidad de simular una transf'er: ,
de infbrmacin de una porcin de cdigo a otra mediante la asignacin de puntero:
Por otra parte, el paso por referencia de parmetros a un subprograma no im: . -
una copia del contenido de la variable pasada, sino que el parmetro real y el ft
identifican fsicamente al mismo bloque de memoria.
=-
Por tanto, si un bloque de memoria est apuntado porun puntero y ste es pa.-_
por valor a un subprograma, el parmetro formal toma como valor una copia del - _

contena el real. Es decir, el puntero destino se queda apuntando al bloque de mem - _

que apuntaba el parmetro real. En esencia, este paso de puntero por valor es url :.
f
por referencia del dato que era apuntado por el puntero. En otros lenguajes, como er .
el paso por referencia no existe de manera explcita mediante alguna palabra reser\:-,
como VAR en Pascal. En estos lenguajes el paso por ref'erencia se hace especficamc .
mediante punteros.

.: - l:-LU Referencia; 11
_:--:
:. -:.:Sntero = ^integer;
: :.==^-- : -:unCEnterO;
' ----'''-
---A1AY.
|
------a

Es:rnucruRAs DE DATos orNurc,ls

PROCEDURE PasoReferencia (pFormal : TpuntEnt.ero) ;


BEGIN
pFormal^ .= pFormal^ + 2;

?ROCEDURE PasoValor (pFormal : integer) ;


:!GIN
pFormal := pFormal + 2;
;\in -

:
_ larrf
Jlt\
-
a+-v^
srlLurv .-
._ 1-
i

pReal : = @entero;
writeln (pReat) , {se imprime 2}
PasoValor (entero) ;
writeln (entero) ; {se imprime 2}
PasoValor (pReal^) ;
writeln (pReal^) ; { se imprime z }
?asoRef erencia (pRea1 ) ;
'riteln (pReal^ ) ;
{se imprime 4}

evidente que el f'uncionamiento del procedimiento pasoRef erencia anterior es


al del siguiente:

E PasoReferencia2(VAR entero: int.eger) ;

entero + 2;

en PasoReferencia el puntero al entero se pasa por valor. mientras que


ierencia2 el paso del entero es por referencia.

Estructuras de datos dinmicas ,-

r-'-r hasta este punto, adems de no parecer muy tiles. e1 uso los punteros
va
-; todos los principios de abstraccin tan deseables en un lenguaje de progra-
-: :ito nivel. sin embargo, gracias a la facultad de reservar y liberar memoria
los punteros son esenciales para la creacin de estructuras dinmicas
que
en funcin de las necesidaries de la ejecLrcin.
398 PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

entero

pEntero
ptrntero_

r --
Figura 11.2: Laasignacin de un puntero a otro no duplica la informacin, ambos
teros quedan apuntados al mismo dato

" ll.2.l Listas enlazadas


Una1istaeSunaeStructuIadedatosenlaque'"o'd"',*@}
manera que a cada uno l-e,-corye-sponde
y Un SUa.'
"" P1-9"+?":"i91:XP;pJ
que una
ffiffi"dearrays.Sinembargo,yaSehamencionadoqueelusodearra1r -
para ciertas estructuras en las que el tamao no est bien definido en tiempo de
c'-- :
iacin puede ser ineflciente y provocar un desaprovechamiento de los recursos'
Una lista dinmica permite insertar y borrar elementos, llamados nodos, utili-
-
adecuadamente la memoria en cada instante. En Pascal, los nodos se implement"-
diante un registro de dos o ms campos. Uno de estos campos debe enlazar con
-
siguiente v la forma de hacerlo es mediante el uso de un puntero que 1o ref'erencie '-
gura 1 1.3 l. Se entiencle que el tipo base del puntero que hace de enlace debe ser e1 :'

L:s--:

Figura 11.3: Lista de nodos, implementada como registro con campo infornt.-
enlace al nodo siguiente

trpo de registro que lo contiene, por lo que se tiene una delinicin recursiva exceF -
en Pascal.

-_'-a
- -a)
lEiemento = ...;
l- rsra = ^TNodo;
TNodo = RECORD
:-nf o : TEIemento;
EsrnucruRAs DE DATos orNvrrcas 399

s19: TL]-sta;
END;

se observa que la definicin de lista anterior tiene


un nico campo de enlace, por este
motivo se la denomina lista enlazada simple. Existen
tanto estticas como dinmicas. En
multitud ie variantes de listas,
concreto una implementacin dinimica muy habitual
es la que hace uso de dos enlaces para unir
los nodos, las listas doblemente enlazadas.
A continuacin se analizan las operaciones fundamentales que pueden
se llevar a
cabo para sacar provecho a las listas.
Para crear una lista enrazada simple vaca se deja
apuntando a NrL un puntero, que
es pasado por referenciapara actuar sobre
er propio parmetro real.

.: - IEDURE CrearlistaVacia (VAR lista: TLista) ;


:: _-_l\
I I ^L
-
: = NIL;

-'.mprobar si una lista est vaca, se compara su cabecera con el puntero


vaco:
_ON EsVacia(lista: Tlista) : boolean.

:svacia := (lista = NIL);

- r:r lnsertar un nodo al inicio de una lista se reserva


memoria para el nodo a travs
f Llntero auxiriar, se asigna informacin a su
campo de datos respectivo y se enlaza
enlace sig a la lista original (que puede estar vaca
o no).

InsertarElemento (VAR lista : TLista; info: TElemento) ;


I(_
-.-7

1.lJ_L S Ld,'

ey(aux);
a:r^.info := info;
a;x^.sig := Iista;
lista := uxi

el uso de listas tambin se puede inserlar elementos


clesde el interior de la lista.
r respecto a la insercin en arrays es que la reorganizacin de los erementos
o sucesores) tiene un coste constante, mientras
que en el caso de arrays implica
:os los elementos hasta el finar para dejar un
hueco para el nuevo.
400 Puxrrnos y EsTRUCTURAS DE DATos orNurc,ls

Para borrar el elemento cabecera de una lista y liberar la memoria que lo contiene
previamente se debe comprobar que la lista es no nula. Seguidamente y utilizando
un
puntero auxiliar para tomar la cabecera de la li.sta, se hace avanzar el puntero original
que apuntaba a la propia cabecera y se libera memoria con el puntero auxiliar.

PROCEDURE EliminarElemento (VAR listar TI.ista) ;

VAR
aux : Tlista;
D D TTT
D!U f L\
IF NOT EsVacia(Iist.a) THEN
BEGIN
aux := lisra^.sig;
dispose (1isca) ;
lista := uxi l
(
END;
e
END;

Como puede observarse en el procedimiento anterior, para ayanzar en una Iista enlazad. SI

con un puntero desde un nodo al siguiente, se le va asigna eI campo enlace (sig) de d,


nodo al que apunta. Anlogamente, para ayanzaf el puntero cabecera de una lista:

lista := list.a^.sig;
o bien mediante una funcin, y teniendo cuidado de no salirse del espacio reservado ;.
la estructura:

FUNCTION Siguiente(lista: Tlrsta) : Tlista;


BEGIN
IF NOT(EsVacia (lisra) ) rHrN
Siguienre := Iista^.sig
ELSE
Siguiente := NIL;
END;

Por extensin, para recorrer una lista desde su cabecera y procesar cada uno de :-
rlementos de informacin se utilizara un bucle a modo de esquema de recorrido:

.:,1:IJRE Recorrer(lista: TLista) ;


::r-1,
,:---: ilista <> NIL) DO
__: 17.2
ProcesarElemento (lista^. info) ; trs c
lista := lista^.sig -r
:C ln
r col
-E
Concr
EsrnucruRAs DE DATos rNnrrcRs 40t

frritese que la lista se pasa por valor al procedimiento y se ayanza directamente con el
:-rrmetro fbrmal, que es una copia del real. Avanzar con el real, sin ayuda de punteros
-:riliares, implicara la prdida de los elementos que se dejan atrs, sin posibilidad cle
::uperarlos y desperdiciando la memoria.

\1.2.2 Pitas

r ejemplo de pila de elementos surge habitualmente cuando se tiene una columna de


- ,:toS. Se dice que estos estn apilados unos encima de otros formando una pila. La
.:rer& ms intuitiva de proceder a su manipulacin es metiendo o sacando platos desde
:ima.
Las pilas, como estructuras de datos, son particularizaciones de listas enlazadas cu-
-. inserciones y extracciones se realizan por la cabecera o cima de Ia pila. Se entiende
",: el primer elemento en entrar a la pila queda tapado por siguientes elementos. De
' : Irl&Ilea, se tiene una estructura en la que el primer elemento en entrar es el ltimo
.alir, lo que se conoce como estructura FILO (First-ln Last-Out). La accin de in-
:lf,r elementos se denomina comnmenfe apilar, y anlogamente la de extraccin se
-r-,rntina desapilar.

pila

illra i 1.4: Ejemplo de pila, el nico elemento accesible es el que hace de cima

, definicin de tipos y los procedimientos necesarios para apilar v desapilar son


a la definicin de tipos y procedimientos de las listas enlazadas r istos anterior-

Colasr!'
- .s son enlazadas con Ia particularidad de que los elementos
k
As. e1 primer elemento en entrar a
.s el prlme que equivale a una estructura FIFO (First-In First-Out).
es fcil ver ejemplos de colas en Ia vida cotidiana, desde
-- las personas
402 PuNrnnos y ESTRUCTURAS DE DATos orNrrrcls

que esperan en fila en la taquilla de un cine hasta la cola de impresin de documentos


de una impresora. En ambos casos un n se inserta por el extremo fi
mientrasque la eliminacin es a travs rto Ia cahecera EIEble una im!ffidlffi
esttica de una cola considerndose el uso de arrays, in embargo, es habitual lLizar
memoria dinmica con el fin de mejorar el rendimiento de las operaciones ms habituales
de la estructura.

Extraccin

Cola

Figura 11.5: Cola como particularizacin de una lista enlazada simple donde la insercir
es por el final de la estructura y la extraccin por cabecera

En la implementacin dinmica de una cola con un nico puntero cabecera, a moc


de iista enlazada simple, Ia insercin de elementos implica un recorrido por toda,-
estructura hasta llegar al extremo final.

;:: l:-.:: -:-serrarFinal (VAR cola:TLisra; info: TElemento) ;


,":-:i-

r:^- -l.^-. -:T.

BEGIN
Pruru .- r\r!/
pAct := col&;
I^IHILE (pAct <> NiLl D0
BEG]N
pAnt ; = pAct;
nr
yuu .-
.- -Ar^ oi-.
.Drg;
IJ6UL
END;
IF (pAnt = NIL) THEN
InsertarElemenLo (coIa, info)
ELSE
InsertarElement.o (pAnt, inf o) ;
tr\Tn .

El procedimiento InsertarFinal anterior no slo es engoffoso sino que bastante -:.


flciente. pues el recorido a la estructura conlleva una complejidad O(N). Es cor---
\srxrtr.xxs.xrusrN\Nt..s \\\

Co 1a

Fi_sura 11.6: Cola como registro con punteros cabecera y final para facilitar la insercin
. la extraccin de elementos

-tilrzar 2 punteros para realizar el acceso a los elementos cabecera y linal de manera
-.re actuando sobre el elemento flnal se pueda insertar un nuevo nodo como indica la
:ura 11.6. Completando la definicin de tipos, las tareas de insercin y eliminacin
- ,nsiguen terier una complejidad constante O(1).
" ';E
TEIemento
TEnlace = ^TNodo;
TNOdO = RECORD
info: TElemento;
s j-g: TEnlace;

TCola = RECORD
cabecera, final: TEnlace;
:.1\ l,_/ ,'

- :4. 1a cola es un registro con 2 punteros que apuntarn a la cabecera y al frnal res-
te de manera que la creacin de cola vaca se ve modificada.

CrearColaVacia (VAR Cola: TCola) ;

,:ia . cabecera \TTT


I!I!,
.

-:-a . final NIL;

,' iuncin EsColaVacia queda:


l)l' EsColaVacia (cola: TCola) boolean; :

..lclaVacia = (cola.cabecera = NIL) AND (cola.final = NIL)


404 PuNTBnos Y ESTRUCTURAS DE DAToS DINMICAS

Extraccin

Cofa
I
Figura 11.7: Cola doblemente enlazada como registro con punteros cabecera y final par.
facilitar la insercin y la extraccin de elementos

La insercin es mucho ms sencilla para el caso de tener elerrentos ya insertados (r'e-


rama ELSE):

PROCEDURE InsertarNodo(VAR cola: TCoIa; info: TElemento) ;


BEGIN
IF EsColaVacia (cola) THEN
BEGIN
InsertarElemento ( cola . cabecera , info ) ;
cola. final : = cofa. cabecera;
END
ELSE
BEGIN
InsertarElemento (cota. final^ . sig, info) ;
cola.final := cola.fina1".sig;
END;
END;

Se observa claramente que el orden de complejidad de este procedimiento es consi. ,

O(1), pues las operaciones individuales necesarias son simples y todas ellas tienei -"
orden de complejidad constante.
Un caso especial es la cola doblemente enlazada con punteros cabecera y finai d,. - - ,

;ada uno de los nodos contiene campos de enlace con el nodo anterior y siguiente :
n sura 1 1.7). Esta implementacin ofrece sutiles mejoras y la posibilidad de retro, : - :
er los recorridos sin el uso de punteros adicionales.
--,_ - l

lI -::ent o
l::-_.ce = -lNooo;
TN-cdc = RECORD
CunsrtoNBS DE TIpo rEST 405
I
lnlo : I'Ejlemento;
ant, sig: TEnlace;
END;
TCola = RECORD
caDecera/ Irna-L:'ltjnlace;
END;

11.3 Cuestiones de tipo test


I-es siguientes preguntas pueden tener ninguna, una o ms respuestas correctas.

11.3.1 Enunciados
1. cul de las siguientes afirmaciones sobre 1as estructuras FIFo es falsa?
* ila) Es una lista particularizada al caso en el
cual slo se insertan y eliminan
elementos por uno de los extremos.
(b) Se puede implementar como una estructura dinmica.
(c) Es una cola.
(d) Es una lista particularizada ai caso en el cual se insertan los elementos por
un extremo y se eliminan por el otro.

- En la implementacin de una estructura de tipo lista doblemente enlazada:

( a) cada nodo tiene un sucesor pero puede tener varios predecesores.


tb) cada nodo tiene un predecesor pero puede tener varios sucesores.
tc) Cada nodo guarda nicamente la posicin de su sucesor en un puntero.
* I d) Cada nodo guarda la posicin de su predecesor y
sucesor en sendos punteros.

Dado el siguiente programa:

PROGRAM TesT3;
'AR .,\ b
lt
b: integer; L-l t-; r
r
c, d: ^ inLeger ; --: {-t
"*L
I - - Ttf
_,-rL\

'l .- .
6t" J (
I

^ .= ):.
t- A t

3s39
1
406 PuNrBnos y ESTRUCTURAS DE DATOS DTNMTCAS

d= t , , ./ \
Nl ^ ,1-,-/ t n^-t t d^-t d^
wtILctttt
',,r'iJ-ol-lr^ dt 9- t Ut U - , u/u-ru,itt .
^
e .= d.
a^ ,- ).:
.1,
nr1
writeln l'a=" at ,k-,
D- t
1^
D I
I
^A -
U
I
r c^ , 'd^=' , d^) ;
dispose (d) ; 2- 'z
END.

(a) Mostrar en pantalla:


.A
a=5 b=5 c"=5 d"=3; a=5 b=5
-
c"=2
^
d"=2
(b) Habr un eror de ejecucin al ejecutar la instruccin dispose (d) .

(c) Mostrar en pantalla:

a=3 b=5 c"=5 d"=3; a=5 b=5 c"=2 d'=3


Mostrar en pantalla:
-- t{d)
a=J b=5 c =5 d =J; a=3 b=5 c =2 d =2

4. Cul de las siguientes afirmaciones respecto a listas dinmicas es cierta:

, (a) Idealmente pueden tener ilimitados nodos.


(b) Tienen prefijadas las dimensiones.
(c ) Existen diferentes implementaciones.

{ d ) Una lista vaca contiene un nodo que apunta a NIL.

5. Una pila doblemente enlazada con elemento cabecera y linal:

,. ,:(a) Es una estructura LIFO.


(b) Es una estructura FIFO.
(c) Es una estructura LILO.
; (d) Es una estructura FILO.

6. El procedimiento NEW:
(a) Debe ser llamado cuando queramos utilizar una variable de tipo pur' :-
registro.
9.(b) Reserva de manera dinmica tanta memoria como necesite el tipo b.,.-
puntero pasado como argumento.
(c) Se utiliza en los subprogramas para dar sentido a los punteros locale:
(d) S1o se llama cuando el puntero que se le pasa como parmetro debe
a memoria comparlida.

7. Dado el siguiente programa:


CunsrroNns DE Trpo rBST 407

PROGRAM Test7;
TYPE
'I'Plnteger = .lnteger ;
VAR
i ,i
plnt: TPlnteger; '- \. L: L
t*r
._,r
t \
_1-
d, D, c, d: integer; \-i t-.t
-.\ -r

PROCEDURE TPlnteger; VAR ent: integer);


BEG]N 'i,4 ': : r:

pAux :=
pAux :=
END;

PROCEDURE MisLerio2 (pAux: TPlnteger; ent.: integer) ;


BEGIN
pAux : = @enL;
.
/\11v ..-
-
').
-t
END;

BEGIN c

b := a;
MisLeriol (plnt, a) ;
a .- nlnl-

Misterio2 (plnt, b);


A = ptnt j .;,

:ND.

Tras la ejecucin del programa, las variables a, b, c, d contendrn valores:

(a) a=5, b-5, c-5, d*5.


b) a=2, b-5, c-5, d=2 .

.) a=2,b=2, c es indeterminado, d es indeterminado.


. I r a=5, b=2, c-5, d-5.
Dado el siguiente programa seale la af,rmacin corect:

?ROGRAM TesTS;
5PE
TPEnt.ero = ^integer;
ER
i: integer;
408 PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

P, g: TPEntero;

PROCEDURE Misterio(a: nteger; TPBntero)


BEGIN
llnt:
..ir
- 1 * . ":-t*:'
-A
PlllL ;= _ualtL ,

END;
BEGIN
.^',,
Iluw /\
\Y/ ,

I .- r/
A^
1 '- zt
n .-
.- i
t, "-,
Misterio (p", q) ;
write("i - ", i);
writeln ( ", q^ = ", q );
dispose (q) ;

END.

(a) En pantalla se imprime: i = 3 , Q^ = 4.


(b) Enpantallaseimprime: i = 1, o,^ = 2.
,*,(c) En pantalla se imprime: i = 1 , Q.^ -- 4'
(d) Se produce efror de tipos en la llamada al procedimiento Misterio

9. Lo. nodos de una lista dinmica:

ia r Idealmente tienen tamao ilimitado.


Son todos del mismo tipo de dato.
-+b)
(c) Se reservan en tiempo de compilacin.
(d) Se liberan en tiempo de compilacin'

q 10. Dada la declaracin:

VAR
p : A_-'lijato;

(a) Tras la declaracin tenemos una lista preparada para ser utilizada'
(b) Para poder utilizar p necesitamos hacer la llamada new (p) '
(c ) p permite apuntar a cualquier tipo de dato definido por el usuario.
---c,(d) Podemos utilizar p sin necesidad de hacer new (p) .

S 11. Dado el siguiente programa seale la afirmacin coffecta:


CunsrroNns DE Ttpo rEsr 409

PROGRAM TesT11;
TYPE
'IPEntero = rntegeri
VAR
p,e : TPEntero;

PROCEDURE Misterio (VAR a : nteger; b: TPEntero);


BEGIN
: .- f*.

IA^'
h .- t*h .

END;
BEGIN
-^,., \y/
]]uw /-\ .
|

new (q) ;
_
P '- r t
d .-
.- l.
Y J,

Misterio (p^, q) ;
writeln (p^ ) ;
writeTn(q^);
dispose (p) ;
dispose (q) ;
END.

(a) En pantalla se imprimen los valores: 5 y 9.


--1Jb) En pantalla se imprimen los valores: l0 y 9.
(c) Se produce error de tipos en la llamada al procedimiento Misterio.
(d) En pantalla-s imprimen los valores: 5 y 3.

L l. Una cola es una estructura LILO cuya insercin es ms eflciente:

(a) Si disponemos de un puntero cabecera pues es por donde se insertan 1os


nodos.
(b) Una cola no es una estructura LILO sino FIFO (First In. Fir:t Our L
(c) La insercin de nodos en una cola tiene complejidad Or\ r en to.ios los casos
porque tenemos que recorrer la estructura.
-(l Si tenemos disponible un puntero que ref-erencra ai nnal de 1a estructura.

i -:. Dado el siguiente cdigo:

PROGRAM TesT13;
VAR
d, b, c: ^integer;
4lO PuNrnnos Y ESTRUCTURAS DE DATos orNlrrcls

BEGIN
-^,.,
1luw I/. \
\q/ /
p l' at

new(c); &
dispose (c) ;
.- h.
dispose (c) ;
dispose (a) ;
END.

(a) se produce un etror de compilacin por las asignaciones de punteros


inicializados.
(b) Se produce un error de ejecucin por la doble instruccindispose (c) '
*g@) Se produce un effor de ejecucin por la instruccin dispose (a) .
(d) Se produce un ertor de compilacin por utilizar b sin haher reservado m-
moria mediante new (b) .

11.:
t 14. Seale las af,rmaciones correctas:
1
(a) Es muy conveniente liberar el espacio de memoria mediante di spose cuan -
no se vaya a utilizar ms un puntero'
(b) No conviene liberar el espacio de memoria mediante dispose cuando n! ':
r,a a volver a utilizar ms el puntero ya que corremos el peligro de desaju.,-"
la memoria de la mquina.
-
(c ) Siempre ocurre que por cada declaracin de variable puntero que escrib;, .
una seccin VAR debo escribir en la seccin de instrucciones una llamec- -
new. J.
-Hd) Despus de llamar a new, el valor al que apunta el puntero es indefinido

g15. Teniendo en cuenta que pTres y pUno son punteros a inLeger, eS correc--
siguiente secuencia de instrucciones para triplicar el valor numrico apuntadc
pUno?

(I) PTres '= PUno;


(II) PTres^ : = 3*PTres^ i

( a) No, porque es imprescindible llamar al procedimiento new (pTres ) an,.


utilizar el puntero pTres.
-alb ) (II) triplica el valor numrico'
S. porque la instruccin C

(c) )io. porque la instruccin (II) slo triplica el valor numrico ilpulltu- a

p - :e s. no el de pUno. a
CuB,srroNBS DE TIPo TEST 411

(d) S, porque la instruccin (II) triplica la direccin de memoria donde est


ubicado pTres, triplicando as el valor al que apunta.

e 16. Despus de la defrnicin

vPun: ^integer

y ejecutar 1a instruccin

-^ : = 3,
vPun
la operacin @vpun:

(a) Devuelve la direccin de memoria donde est ubicado el valor numrico 3.


-*{b) Devuelve Ia direccin de memoria donde est ubicada la variable vpun.
(c) Devuelve el valor numrico 3.
(d) Reserva memoria paa alrnacenar
el nmerl 3.

-X.3.2 Soluciones
l' La afirmacin farsa es ra (a). En una
esactua donde er priner eremento en
entrar es el primero en sarir (First-In First-out
o FiFo) no ," r", pueden insertar y
eliminarpor el mismo extremo.
I La afirmacin correcta es la (d). un nodo
de una rista dobremente enrazada
tiene dos punteros que apuntan con_
a los nodos predecesor y sucesor
respectivamente.
caso de nodos cabecera o final
uno de los punreros quedar
i::#:r;11'J-',eI
-: ' La afirmacin correcta es la (cl). Haciend
o wa trazase observa que se
dos variables de tipo entero (a inicializan
y b) a los valores 3 y 5 respectivamente.
puntero c se reserva memoria A trar s cier
pata almacenar un entero y
para que apunte a ra misma se iniciariza er puntero d
regin de memoria reservada
vuelca el contenido de la anteriormente. Luego se
varire a (3) u i"rru regin
contiene el puntero c para que
apunte a la variable a. En
, ,. .r,nilr';ilJaTil:
c^ y d^ contienen el mismo este punto _ie rlene que a,
varr: 3- ,.uuu, de c se modica
asignando er varor de b (5). por er conenido de a,
tanto tu prir"r, instruccin
tre'cre nrura mostrar:
a=5 b=5 c^= d^=3,

Tras ello se actuariza la direccin


que contiene el puntero c para
donde lo haca d y se asigna que apunte a
el valor 2. por.rru.u)n. ,unio'"
apuntados a una regin que como d quedan
contiene dicho valor 2. La
a que siguiente instrucci nfuerza
se imprima:
4t2 PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

a-)
^-tr 1^-tr
D-J n^-'
V A^-a
V -L
--

Puesto que tanto c como d quedan apuntados a una regin de memoria que fue
reservada en tiempo de ejecucin, la instruccin dispose (d) es legtima para li-
berar clicha memoria antes de finalizar el programa, y por tanto no produce ningn
error de ejecucin.
,1. Las respuestas correctas son la (a) y la (c). Idealmente, el tamao de una lista
dinmica no viene limitada por el tipo de dato con el que se implementa, sin em-
bargo, en la prctica, la cantidad de memoria disponible en una computadora no
es ilimitaclo. Lo que es seguro es que por el hecho de ser una estructura dinmica
el tamao no viene prefijado en tiempo de compilacin como en el caso de las
estticas, descartndose la respuesta (b). En cuanto a las implementaciones bastil
decir que se pueden encontrar implementaciones simplemente enlazadas, doble-
mente enlazadas, con puntero cabecera y final,... Por otra pafte, una lista vaca nt
contiene ningn nodo, incoherente es el hecho de que adems dicho nodo apuntc
a NIL, pues un nodo en s no es un puntero.
5. Las afirmaciones correctas son la (a) y la (d). Cuando se trata de forma abstract-
el concepto cle una estructura se debe ignorar la implementacin que se utiliz,
En este caso, y por hablarse de una pila, 1o nico que se debe tener en cuenta a l*
hora de categorizar la estructura es que el ltimo elemento que entra en ella es
primero que sale (Lasfln First-Out, LIFO) y que por tanto el primer elemento qLi.
entra es elltimo que sale (First-In Last-Out, FILO).
6 La rnica respuesta coffecta es la (b). Tal y como fue descrito el procedimien:
:-r.'en 1a seccin 11.1.1, se necesita pasar un puntero como parmetro al ptoir-
dirniento. Este puntero queda apuntando a la regin que se reserva en tiempo c.-
ejecucin. El resto de respuestas son totalmente incoherentes.
7. La afirmacin correcta es la (d). Se deben observar los pasos por valor y p
referencia que se hacen en los procedimientos Misteriol y Misterio2. En l*'
primeras lneas de cdigo se inicializan las variables a y b a 2. Seguidamente ,.
llama a Misteriol pasando por referencia un puntero y la variable a. Por tanto. :
parmetro formal ent referencia a la misma regin de memoria que el parne .:
real a. A travs del puntero se le asigna a esa regin de memoria el valor de 5. -
la salida se tiene que el valor de a es 5, y puesto que plnt se pas por referen-. -
contina apuntando a la variable a. A la variable c se le asigna el valor .-5. --
llamada a Misterio2 se hace con el puntero y la variable b, ambos pasados :
vaior. Dentro de1 procedimiento se modifica el valor de la copia de b, pero nl .
parmetro real, por tanto no afecta a dicha variable b. A la saiida, y puesto qu; .
parmetro real plnt fue pasado por valor, se asigna el valor de 5 a la variable ''

8. La respuesta correcta es la (c). En las primeras lneas del programa prinir--


se reserva memoria a travs del puntero q para almacenar un entero al que. - -
CunstroNrs DE TrPo rEsr 413

inicializar la variable i, se le da el valor de 2. El puntero p se pone apuntando a la


variable i y se llama al procedimiento Misterio pasando por valor tanto el clato
apuntado por p como el puntero q. En el procedimiento el entero pasado como
primer argumento se triplica, pero esto no se refleja en la variable i a la salida
por tratarse de una copia de su valor. El parmetro formal del puntero enviado
a Misterio apunta a la misma regin que apuntaba el parmetro real q, incluso
habindolo pasado por valor. De esta manera duplicando el valor al que apunta
se ver reflejado a la salida, conteniendo q^ el valor de 4. obsrvese que puesto
que el primer parmetro que se pasa al procedimiento Misterj-o es un entero y
el segundo un puntero del tipo definido en la seccin TYPE no se produce ningn
error de compilacin.
9. La respuesta correcta es la (b). Para hacer recursiva la definicin de la lista se
crea un tipo puntero capaz de apuntar a un tipo nodo. El tipo de datos de1 nodo es
nico para todos los elementos de la lista. La respuesta (a) es incorrecta porque
es la lista la que idealmente tiene tamao ilimitado, no los nodos. Las respuestas
(c) y (d) son falsas de acuerdo a que la gestin de memoria dinmica se efecta en
tiempo de ejecucin.
10. La respuesta correcta es la (d). Con la declaracin de p se consigue un puntero
capaz de apuntar a un dato de tipo TDato. No es necesario reservar memoria
en tiempo de ejecucin a menos que tengamos necesidad de ello, es importante
descartar 1a idea de que se debe llamar a new 0 con el puntero para utilizarlo,
pues es falso.
',. La respuesta correcta
es la (b). Ambos valores pasados al procedimiento se ven
alterados tras la llamada. El primer argumento se pasa por ref'erencia y cualquier
modif,cacin en el parmetro formal se ver reflejado en el real. El segundo es un
puntero pasado por valor y aunque se hace una copia de su contenido, el dato al
que apunta el parmetro real contina siendo apuntado por la copia.

- La respuesta correcta es la (d). Suponiendo, como se ha tratado en la teora. que se


hacen inserciones por el extremo final de la cola, se debe recorrer toda 1a estructura
para aadir elementos si no se dispone de un puntero que apunte a dicho e\tremo.
De esta manera se obtiene una complejidad O (n) , cuando se podra simplifrcar a
- i1) mediante un puntero que apuntara a dicho extremo.
La respuesta correcta es la (c). Tras la primera liberacin de mentoria mediante
l.spose (c) se asigna aI puntero c la direccin de memoria que apunta b, que a
>u vez estaba apuntando a donde lo haca a. Por tanto. medianre c se libera la
rlemoria previamente asignada con new (a) . La siguiente liberacin de memoria
-rrn dispose(a) produce un error en tiempo de ejecucin. por tratar de liberar
..na regin que no est reservada.

- ' : afirmacin correcta es la (d). A primera vista puede parecer correcta la (a), sin
-::bargo no se especilica si el puntero apunta a una regin reservada o no. Si la
4t4 PuNrpnos y ESTRUCTURAS DE DATos nrNurcas

regin a Ia que apunta un puntero no est reservada dinmicamente, el intento de


Iiberacin de memoria dar un consecuente error en tiempo de ejecucin. Lo quc
s es cierto es que si se reserva memoria con new 0 , el puntero utilizado quedari
apuntado a la direccin de memoria de dicha regin. cuyo valor es, en general.
indefinido.
(b). Tras la asignacin de punteros pTres qued.,
15. La nica afirmacin cor:recta es la l
(
apuntado a la direccin de memoria donde apuntaba puno y por tanto referenci'
al mismo dato. Actuando sobre pTres se puede modificar el dato apuntado pt':
puno. l
t6. La respuesta correcta es la (b). El operador "@" devuelve la direccin de memorL'
:
de la variable a la que se aplica, ya sea un puntero o de cualquier otro tipo c.
datos.

II.4 Problemas r
.:

ll.4.l Simulacin de tipo string :


Simule el tipo de dato string con una gestin dinmica de memoria mediante una li. -
enlazada de valores de tipo char. Implemente operaciones comunes de los strings cor:
la funcin length, insertar subcadena,...

11.4.2 Funcin contadora iterativa


Escriba una funcin iterativa que cuente el nmero de elementos que contiene una 1.' -
que se le pasa como argumento. Compruebe dicha funcin con una lista de ptueba cre : --
1
para el propsito.

11.4.3 Funcin contadora recursiva


Repita el ejercicio anterior escribiendo una funcin recursiva.

L1.4.4 Ordenacin ascendente


Fscnba una funcin a la que se le pasa como parmetro una lista de nmeros y deter:- "
:. Jir ordenada de forma ascendente. Puede probar el algoritmo creando previal.--
-::: rsta de valores numricos.

11..1.5 Interseccin de listas


ReiL.-e un programa que devuelva la interseccin de dos listas de artculos. Un ar , -
est iorn-rado por el cdigo del artculo (un nmero) y la descripcin del artcu,
PRonr,rus

El resultado derainterseccin son los jr.:", :


' "
arcuro.s que estn en an.iL,as
-.,-,: son iguales si tiene el mismo cdigo de artculo).

ll.{.6 Unin de \istas


'r'ealice un subprograma que d'evuelva
la unin de las dos listas ante.ores (los
que hay en una \ista, en \a ar1cu\o.
otra o en ambas).

11.4.7 Sucursales de venta


se tienen dos sucursares cle una
empresa (en Madrid y en ciudad
Ia venta de artculos variados. Real) que se dedican
cuando llega un ,u.uo artculo al
rucursal se anota en una almacn de cacla
lista la crescripcin del artcuro
-uracteres), el precio en euros y un i* i.r," de no ms de 3L)
cdigo de artcuro que es unvoco.
: " .a cantidad de
arrcuros que podemos d-isponer
No hay lmite
p ,ru ,i ,ritr.- ungnun
-:ilione dos listas dertculos (una programa que
-' para los artc,ros " tu rr.r.rar
1os de la sucursal de de Madrid y otra
-
ciud,ad n ar Er programu o"t"ra
-en que permita de forma independiente *ostrar por pantalla un
para cada sucursal:

1. Insertar un nuevo artculo.


L Borrar uno ya existente.
t todos los arrcuros descle
er principio de ra risra hasta
,y';tliy"r er final o de manera

11.4.8 Visualizacin inyersa


t programa que visuarice
una lisra en orden inverso.
:::1":l Realice el programa para

I . Una lista simple.


l. Una lista r]oblemente enlazada.

1.1.9 Suma de polinomios


.rba un algoritmo que lea
dos polinomios de una misma
.:mentacin se realizar rariable,r. los sume. La
mediante tiriur'"nluroor.
:i:
-r)=2x2 +3x-7:
-r)=5x3+x2_2x;
rit+g(x)=5x3+3x2+x_7
416 PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

11.4.10 Sala de espera


Se desea modelar, mediante una cola, la sala de espera de un centro de salud. A ell;
llegan pacientes, se les pide su nmero de historia clnica. se les asigna una hora d
llegada y se sientan en la sala de espera hasta que el mdico les llama para que pi1-
-'
sen a su despacho. Dada la siguiente def,nicin para el dato paciente (siendo THora
TNumHistClinica tipos predef,nidos):

TPaciente = RECORD
numHistCli : TNumHistClinica ;

hora: THora;
END;
TCola = ^TNodo;
TNOdO = RECORD
rnlO: 1'Pacl-ence;
sig: TCola;
END;

Se pide:

1. Subprograma de aviso del siguiente paciente en entrar al despacho del mdicc


por tanto de salida de la sala de espera.
2. Subprograma de llegada de un paciente nuevo a la sala de espera. Supongan
qlre tenemos accesible un procedimiento de inicializacin de variables de t::
l?acrente llamado IniPaciente, aI cual se le pasa la variable y la devue-
inicializada.
3. Subprograma de abandono de la sala de espera sin llegar a visitar al mdico de ,'
paciente. dado su ntmero de htstoria clnica.
4. Subprograna que il.ttercale en una cola dada, otra nueva cola de perSofloS i.,:
1l
esperaban, en otra sala de espera. a un mdico que Se tiene que marchar (la c
resultante debe quedar ordenada por la hora de llegada). Supongamos que tener
..
una funcin cu) o prototipo e\:
.l
Mayorlgual (hora1 , hora2: THora) : boolean;
que devuelve TRUE si horal >= hora2 y FALSE en caso contrario.

11.-1.11 Cambio de sentido del tren


Consiclere 1a simulacin del cambio de sentido de un tren de metro dentro de ut.t t-- -

mediante una pila. El tren entra en el tnel por las vas de un andn y sale por las
del otro. cambiando as el sentido de su marcha. Suponga que cada vagn es un res-'
que contiene ia siguiente infbrmacin:
lI
Pnonr,Buls 411

l. Peso del vagn (Entero).

2. Mquina propulsora o vagn de pasajeros (Booleano):

Si es mquina propulsora:

(a) Potencia de la mquina (Entero).


(b) Cabecera (Booleano).

Si es vagn de pasajeros:

(a) Mximo nmero de ocupantes (Entero).

Para simular el cambio de sentido del tren considere la siguiente situacin: El tren
. -.tiene un nmero indeterminado de vagones. Los vagones van entrando en el tnel uno

-ro. y una vez que el tren entra completamente, ste estar listo para salir, habiendo
-:rbiado el sentido de su marcha. El primer y ltimo vagn del tren son mquinas
:ulsoras (la cabecera del tren ser el primer vagn).
Se pide:

Definir los tipos de datos necesarios para simular un tren de vagones como los
cspeci fi cados anteriormente.

- Dado el subprograma:

-nicializarvagon(VAR vagon: TVagon; maquina: boolean) ;

Implemente la operacin de creacin de un tren con tantos vagones de pasajeros


.omo un usuario nos haya introducido por teclado.
: Implemente un subprograma llamado Tunel que haga uso de una pila y que dado
Lrn tren realice Ia operacin de cambio de sentido de su marcha.

-{,12 Almacn de artculos


-..ere gestionar la informacin de los ar1culos de un almacn. Esta infbmairin
-lrdada en un fichero binario cuyo nombre y ruta de acceso es :: -.::--;
,-
=:: . dat. Por cada artculo se quiere llevar la siguiente infbrmacin:

r ildigo, que es un nmero entero.


. fescripcin, de hasta 30 caracteres.
r 'lantidad, que es un nmero entero.
-'.rrmacin se actualizar con la informacin sobre 1as inciclencias habidas. Cada
: -.:ia llevar adems de la informacin que ller.a un artculo. un tipo de incidencia
Jr ser:

. .. si es una entrada.
418 PUNTNNOS Y ESTRUCTURAS DE DATOS NTNUTCAS

o 2, si es una salida.
o 3. si es un alta.
o 1, si es una baja.

Se pide:

l. Defrna los tipos de datos adecuados para representar:

(a) Un artculo del almacn en una lista.


(b) Un archivo binario para almacenar los artculos.
(c) Una incidencia en una lista.

Los nombres de los tipos debern ser acordes a la informacin que se tiene en :
siguiente apartado.
2. Disee un subprograma, cuyo nombre ser ActualizaAlmacen que actualic;
lista de los artculos del almacn con una lista de las incidencias. en funcin -.
tipo de incidencia:

oI , 2 y 4, si hay correspondencia del cdigo de la incidencia en 1a lis:* -

artculos:

- 1. sumar a la cantidad de la lista de artculos la cantidad de la de r -

dencias.
- 2. restar a la cantidad de la lista de artculos la cantidad de la de r -

dencias.
- -1. eliminar la informacin del artculo de la lista de artculos.
o 1.2 J. si no hay correspondencia:

- mostrar un mensaje de error con los datos de la incidencia.


o 3, haya o no correspondencia:

- insertar la inibrmacin de la incidencia en la lista de artculos.

Ambas listas estn ordenadas por el cdigo de artculo. Laacttalizacin se c.-.


hacer sobre la lista de artculos, sin poder lullizar una lista auxiliar (aunqi.
punteros auxiliares).

11.4.13 Balance de parntesis

Escriba la definicin de tipos de una pila de caracteres y las operaciones C:'=. -


PilaVacia, EsPilaVacia, Apilar, Desapilar y Cima. Utilice esta pi1; :-
comprobar e1 balance de parntesis en una expresin aritmtica.
Solucrolvns
119
11.5 Soluciones

11.5.1 Simulacin de tipo


string
.:, :RAM SimulaStrings
;
..
.::
,lefinicn de la
lisLa]
-Lista = ^T\T^^.
-lJodo = RECORD
caracter: char;
sig: TLista;

lista: TLista.
c: char,.
f,:iTION EsVacia Gista: Tlista) : boolean;
&G]N
EsVacia := (lista
=NIL);

-:--Tn
__ J CrearlistaVacia (VAR lista :
.-1. TList.a)
-:l^
:= NIL;

,_
(cadena: rlisra)
= *^r,r::::ii:i0"",
rrvr .ESVCla (cadena) THEN ; BEGrN

WHILE (cadena <> NIL) DO


BEGIN
writeIcad--_^
cadena,==::0";:l'::i;:',
END
l- --

write ( ,La cadena esta var_ a,


__uealf,

E fnsertarFinal (VAR lisca: TIisca; c: :r_ar


420 PUNTERoS Y ESTRUCTURAS DE DATOS DINMICAS

act , ant , aux: Tlista;


BEGIN
--I NTTT .
a1lU ;- 1\a!,
al .- licl.

{se inicializa eI nodo final}


new(aux);
aux^.caracter:= c;
^
aux'-.slg := NIL;
IF NOT EsVacia (1ist.a) THEN
BEGIN
WHILE (act <> NIL) D0
BEGIN
ant : = act;
act := act^.si9;
END;

{Se engancha el ltimo nodo a Ia lista}


.-l^ ai
.u-:J : = dUXi
END
ELSE
lista := aux;
END
PROCEDURE Eliminarlista(VAR lista: Tlista) ;
PROCEDURE EliminarNodo (veR primer: Tlista)
VAR
pAux: TLista;
BEGIN
pAux := primer;
primer ;= primer^.sig;
dispose (pAux) ;
END;
BEGIN
WHILE (lista
<> NIL) DO
EliminarNodo (lista) ;
END;

BEGIN {Programa principal}


CrearlistaVacia ( I ista) ;
writeln ('Introduzca cadena:') ;
WH]LE NOT EOLN DO
BEG]N
{se lee carcter a carcter}
Sor,ucroNBs QT

read (c) ;
InsertarFinal (lista, c) ;
END;
readln;
MosrrarCadena ( lista)
;
{se tibera la memoria reservadai
Eliminarlista ( lisca) ;
readln;
-. {programa principal}

1 1.5.2 Funcin contadora iterativa


I ::u este programa se utiliza una constante para definir el nmero
de elementos que
. rtendr la lista de prueba.
. :r(\]vl eOntaltef /.

]:T
l{ = 10;

-.:
IInfo = string[10];
_L1sta = "TNodo;
, A___

INOdO = RECORD
rnIO : I'-LntO;
cr^. lrl l
)f,9: rLrSL,.

-lSta: '.t'LlSta;
_, numElementos: integer;
,:IURE CrearlistaVacia(VAR I: TListar ;
- := NIL;

Insertar(VAR primer: TLista; info: r-n:: ;

_--.rx: t!1sta/.

-= (pAux) ;
Aaa PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

pAux^.rnfo := info;
pAux^.sig := Primer;
primer '= PAux;
END;
1

FUNCTION ContarElemlter(primer: TLista) : integer;


VAR -
pAux: TLista;
conLador: integer;
BEG]N
contador : = 0;
pAux := Primer;
WHILE (PAux<>NIL) DO

BEG]N
contador := contador+1;
pAux := pAux^'sig;
END;
ContarElemlter := contador;
END;

PROCEDURE Etiminarlista(VAR lsta: TLista) ;


FROCEDURE EliminarNodo (VAR prj-mer: TLista) ;
-.--r.?.

P-r'ux: TLista;
:: l -1,
:-_.--,: ; = primer;
-'l o'i a.
- - -...= - --
! rtlLur
-o-^ ' J!: /
_-_t-.*X
ll_:!::= ;

END;
BEGIN
IdHILE (lista <> l,-Lr )O
EliminarNodo ilisa) ;
END;

:aGIN {Programa PrinciPal}


CrearlistaVacia ( Iista) ; l
I
FOR i := 1 TO N DO
Insertar (1ista, 'nuevo' ) ;

::;:Fiementos := ContarElemlter (lista) ; ':


wrrteln ( 'Hay ' , numElementos, 'elementos en Ia lista' ) ;

fIrLqo 'lrrp!rs
'i her: l.a
r memoria reservada)
Sor,ucroNrs +13
-T
Eliminarlista ( lisca) ;
r-
:ND. iPrograma principal)

11.5.3 Funcin contadora recursiva


En esta versin slo se escribe el subprograma recursivo y la llamada del programa
:rincipal. La definicin de tipos y dems subprogramas auxiliares son los mismos que
-,s del ejercicio anterior.

|RAM ContaRecur;

tlSta: '1'Lrsta;
i, numElement.os: integer;
:-]:CTION ContarElemRecur(primer:
TLista) : integer;
:::II\
IF (primer = NIL) THEN {caso base}
ContarElemRecur : = 0
ELSE
contarElemRecur := 1 + ContarEremRecur(primer^.sig) ;
::

..-l; {Programa principali


l:earlistaVacia ( lisua ) ;
ICR i := l- TO N DO
Insertar (1ista, ,nuevo, ); {deI ejercicio anteriori
:umEl_ementos : = ContarElemRecur (lista)
;
-..riol-/ru-,,
\ rtdy , ,numElementos, , efementos en la lista,
r.___r_1r ,

) ;
.Se libera la memoria reservada]
._iminarlista (1isca) ;
.|
, Programa principal

i.4 Ordenacin ascendente


' ' solucin se utiliza el procedimiento de insercin por cabecera para
rellenar una
-lmrica' Puesto que Ia evaluacin de la orclenacin se hace tambin por
la cabe-
' la hora de rellenar la estructura se insertan elementos en orden descendente. En
-j utilizar una insercin por el linal de la lista se podrn insertar los elementos en
-:iCendente-
424 PuNrrnos y ESTRUCTURAS DE DATos oruvrrcls

PROGRAM Ordenacion;

CONST
N = 6;

TYPE
TInfo = integer;
Tlist.a = ^TNodo;
TNodo = RECORD
info: integer;
sig: TLista;
END;

VAR
lista: TList.a;
i, entero: integer;
PROCEDURE CrearlistaVacia(VAR Iista: TLista) ;
BEGIN
II
_Lr5Ld.
-L -
:= 1\1L,.
END;

PROCEDURE fnsertar(VAR primer: TLlsta; rnfo: TInfo);


VAR
pAux: Tlista;
BEGIN
new(pAr.x) ;
pAux^.info := info;
pAux^.sig := primer,.
primer : - pAux;
end;

FLINCTION EsOrdenada (lista: TLista) : boolean;


VAR
anterrOr: ILrSta;
orden: boolean;
:: J_r!
-TT
-_
- rlar ..- - rDTTE .
lf\ulf

;:-terlOr := lrSLa;
_; ,Iista <> NIL) THEN
tsGJN
--sta := lista^.sig;
SolucroNns 1l<
a-J

WHILE (lista <> NIL) AND orden DO


BEGIN
IF (lista^. info < anterior^. info) THEN
orden : = FALSE
ELSE
BEGIN
anterior := lisLa;
lista := lista^.sig
END;
END;
END
ELSE
orden := FALSE;

EsOrdenada := orden;

.: -ICEDURE Mostrarlj sta (lista: TLista);


I l-TtT
-_JII\

WHIl,E (lista<>NIL) DO
BEGIN
writeln ( lsta^ . info) ;
lista := lista '"'3tAi^.
lND;
;riteln

Eliminarlista(VAR Iista: TLisLa) ;


..13CEDURE EliminarNodo (VAR primer: TLista)
-:.
pAux: TLista;
::-:IN
pAux ;= primer;
primer ;= primer^.sig;
dispose (pAux) ;

__ (lista <> NIL) D0


lliminarNodo ( Ii-sta) ;

.:cgrama principal]
--: PuNrnnos Y ESTRUCTURAS DE DATos DINAMIcAS

l:=al- tstaVacia (Iista) ; BEGIl


:-:. : := 1 TO N D0
I - -'T
:_,,-_-! END;
'riteln ( 'Dame un entero: ') ;

:eadln lentero) ; FUNCl

Insertar(Iista, entero) ; BEGI]


:l,l ;
l
END;

l,:a ver cmo es ta lista)


:,::strarLista ( Iista) ; PROC]

-l Esordenada (lista) THEN VAR

writeln ('Lista ordenada' ) I


:LSE BEG]}
writeln ('Lista desordenada' ) ; T

:eadln; I
{se libera la memoria reservada} t
Eliminarlista ( lista) ; l
:::1. {Programa princiPat} END;

PROCE
11.5.5 Interseccin de listas
innol
;l -GRAM Interlistas; rAR
tr

pide al usuario 1os elementos


;1OPSITO: Programa que que p

:::man dos listas para posteriormente calcular los elementos BEGIN

rlxunes a ambas) R

. IPE
{Se detine e1 campo de informacin de las lista}
TDATO = RECORD
cod: integer;
A^^^- - >uI1fJ$i
ucsur: l

]ID;
--sta = ^TNodo; : _-.
U

-],:Co = RECORD
producto: TDato;
- -g : TLista; .: _ lE.
t---
_:

- :-,:--- -lsta2, listalnterseccion: TLista; .:.lP(


-: -d.

.- :,'.: l:=a:ListaVacia(VAR lista: TLista) ;


Sor,ucroBs 427

:GIN
llof. .- Nl ll.

]-JNCTION EsVacia(lista: Tlista) : boolean;


:!GIN
EsVacia := (lista = ttlIl) ;

.i.OCEDURE Insertar(VAR lista: Tlista; elem: TDato);


"D

pAux: TLista;
: ] TIT
- _UII\
new (pAux) ;
pAux^.producto := elem;
pAux^.sig := lista;
Iista .= pAux;
r.-n.

.IICEDURE Rellenar(VAR lista: TLista) ;


.ROPSITO: Aadir elementos en }a listai
-- l

elem: TDato;
parar: char;
l
,I I_ itr\TtT

REPEAT
write ('Dame cdigo de1 producto: , )

readln (elem. cod) ;


write ('Breve descripcion: ' ) ;
readln (elem. descr) ;
Insertar (lisra, elem) ;
writeln ('Parar? (s/n) , ;
readln (parar)
-LI-NTIL (UpCase (parar)
=' S' ) ;

E Interseccion (lista1, lista2: TLista;


VAR IistaOut: TLista) ;

:.-?SITO: Aadir a listaout los elementos comunes a


=:a1 y lista2.
428 PuNrnnos y ESTRUCTURAS DE DATos orNnrrcas

PRECONDICII: Setrata el caso ms general en el que se


supone que lisLa1 y 1ista2 estn desordenadas y que un
elemento no aparece ms de una vez en Ia misma lista)

VAR
auxl2: Tlista;
BEG]N
auxl2 : = lista2;
{Se recorre la listal una sola vez}
WHILE (listat <> NIL) DO
BEGIN
{Se recorre lista2 tantas veces como elementos
tenga 1ista1 )
WHILE (auxl2 <> NIL) D0
BEGIN
{Buscamos coincidencias en cdigo}
IF (Iist.a1^.producto.cod = auxl2^.product.o.cod)
THEN
Insertar ( listaOut, listal^ . producto) ;
auxl2 : = auxl2^.=ig,
END;
la
tAI salrr
-^r r -- de este bucle se tiene auxl2 aI final
de lista2. Se debe volver a apuntar al primer
nodo de la lista)
auxl2 : = lista2;
{Sin embargo se avanza e1 puntero cabecera de
listal porque se t.rabaja sobre una copia (la
Iista fue pasada por valor) )
listal := listal".sig;
END;
END;

;P.OCEDURE Mostrarlista (lista: TLista) ;


I - -\Tf!
:_-,-

-F EsVacia (lista) THEN


writeln (,La Iista vaca, )

:--::
WHILE (lista <> NIL) D0
BEG]N
writ.eln ( 'Cdigo: , , list.a^ . producto. cod) ;
writeln('Detal_l_e:,, lista^.producto.descr)
lista:=li-sta^.sig;
Sor,ucroNrs 129

END;
IND;

PROCEDURE Eliminarlista(VAR lista: TLista) ;


PROCEDURE EliminarNodo(VAR primer: Tlista)
VAR
pAux: TL:_sta;
BEGIN
nArrv . _ prlmer;
n-i -o-
y_4,LLur prlmer
..-- .srg;
dispose (pAux) ;
END;
lfTtl
_JU1L!

WHILE (lista <> NIL) D0


EliminarNodo (lista) ;
:' tTt .

:llIN {Programa principal}


CrearlistaVacia ( lista1 )

CrearlistaVacia ( lista2 )

{ al usuario por los elementos de cada J-ista)


Se pregunta
writeln(' Introduzca los producto de la lisca 1: ' ) ;
Rellenar(1istal);
writeln('Introduzca los producro de ]a lista 2:' ) ;
Rellenar (lista2) ;

{Mostramos las listas actuales:}


writeln ('La lista 1 es: , ) ;
Most.rarlista ( lista1) ;
r.,r'ital-.

writ.eln('La lista 2 es:,);


Mostrarlista ( lista2 ) ;
'.,-.ir^t-.

l_
t lntersecclon de ambas.f
Interseccion (1ista1, lista2, list.alntelrsE.:_t:-
:rriteln('Los elementos comunes a ambas s3::' I

I'iostrarlista ( Iistalnterseccion) ;

.Se
libera Ia memoria reservadar
430 PunrBnos Y ESTRUCTURAS DE DATos orNn,rrcIs

Eliminarlrsta r lisral ) ;
Eliminarlrsra, lista2 ) ;
E1 iminarlista ( Iistalnterseccion) ;
END. {P:ograma principat}

11.5.6 Unin de listas

El cdigo y la forma de proceder son anlogos a los del ejercicio anterior. E1 subpro-
-qrama lnterseccin modilica para realizar la operacin de unin, que incluye todos
se
los elementos de ambas listas en la lista resultante, aunque sin repeticiones en caso cle
haberlas.

PROCEDURE union(1ista1, lista2: TLista; VAR Iistaout: TLista);


a--^-<-__-
tPRoPosrrO: Aadrr a listaOut todos los efementos de ristal y
lista2, quedando una aparicin de Ios que se repitan.

PRECONDTCTN, se t.rata el caso en el que se supone que 1ista1 y


lista2 son listas no vacas, desordenadas y que un elemento no
aparece ms de una vez en la misma lista)

VAR
aux, auxOuc: TLista;
ENCONTRADO: Boolean;

BEGIN
{se recorre la listal una sor-a vez y se copia cada nodo en
I ^r-a- l
r-L!jLdUUL- I
WHILE (listal <> NIL) DO
BEGTN
Insertar ( IistaOut, 1ista1^ . producto) ;
liscal := lisral^.sig;
EI\TN.

,Por cada elemento de lista2 se recorre listaOut con un


:r:Lero auxiliar para determinar si existe el mismo produc*-:
.:--: (Iista2 <> NIL) DO
:ll-l;
.a:a evitar repeticiones se utiliza un vafor lgico)
:.- l:llADO := FALSE;
. -.:,-l r: : = listaOut;
.:.__: a;xOut <> NIL) AND (NOT ENCONTRADO) DO
SorucroNns _+-: I

BEGIN

{Se buscan coincidencias}


ENCONTRADO : = (auxOut^.producto.
cod =
Iista2^ .producto. cod) ;
u .-
aUXOU -"-'n---A .SIg;
._ au.2(uuL '

END;
iSi no hubo coincidencias t.ras recorrer
listaOut
i nsorl-. se
"o o.l_ producto de 1ista2)
IF (NOT ENCONTRADO)
TUM
fnsertar (listaOut, 1ista2^.producto)
;
{Se continua con el siguiente nodo}
'I i eJ-o
ruua ,= 1ista2^.sig;
END;
]\T .

17.5.7 Sucursales de venta

':.CGRAM AlmMadCiud;
. IPE
TArticulo = RECORD
precio: integer;
descripcion: string;
codigo: integer;
END;

Tlist.a = "TNodoArt.iculo;
TNodoArIicu]o = RECORD
info: TArticulo;
sig: TLista;
END;

-:
lMadrid, lCiudadReal, list.a: TI,i sr: .

;: int.eger ;
opcion: char;
salir: boolean;
rr L : tArtl_cuIo;
:odigo: integer;
eleccion: string;
r:: _ IfDURE
VisualizacionRecursiva (l
l=:a visualizar la lista del fin : TLrsta) ;
a1 principio)
lil PuNrnnos y ESTRUCTURAS DE DATos rNvrrcls

:: i_-i

: l^.sig <> NIL) THEN


Visual izacionRecursiva ( I^ . sig) ;
wriceln(l^.info.codigo, I^.info.descripcion, l^.info.precio)
]'T .

?ROCEDURE Visualizarlista (lista: TLista) ;


l:l D
E

inversa: char;
P
BEGIN
v
writeln ('Quiere visualizar de forma inversa? (S/N) ') ;
readln (inversa) ;
B
IF (upcase(inversa)='S') AND (Iista <> NIL) THEN
Visual i zacionRecurs iva ( I i sta)
ELSE
BEGIN
WHILE (lista <> NIL) D0
E]
BEGIN
wriLe ( IisLa^ . info. codigo) ;
PI
write (Iista^ . info. descripcion) ;
B]
wri-te ( lista^ . info. precio) ;
wri te In;
Iista := Iisca^.sig;
END;
END;
END;

PROCEDURE EliminarArticulo(VAR Iista:TLista; cod: integer) ;


VAR
anL, act. : TLista;
BEGIN
ant := NIL;
ct := lista;
IF (act <> NIL) THEN
BEGIN
WHILE (act <> NIL) AND (act^.info.codigo <> cod) DO
BEGIN
ant :=
act := at-^ oi^.
'PY I

END;
IF (act <> NIL) THEN
BEGIN
SolucroxBs 433

IF (ant = NIL) THEN


lista := lista^.sig
ELSE
ant^. sig : = act^. si9;
dispose (act) ;
-

;?.OCEDURE Insertar(VAR I: TLista; art: TArticulo);


'-:-R

aux: TLista;
::3IN
new (aux) ;
aux^ . info ..-
- .7+-
q!U, .

aux^ . sig ._ t.
1 := uxi

.: -:EDURE PedirlnfoArticulo (VAR articulo: TArtrculo) ;


- -T
: :_,-_L!

writeln ('fnserte codigo de articulo, ) ;


readln (articulo. codigo) ;
writeln ('Escriba 1a descripcion, ) ;
readln (articulo. descripcion) ;
,riteln ('Insert.e precio de articulo, ) ;
:eadln (articulo. precio) ;

:: - IIDURE CrearlistaVacia (VAR lista: TLista)


;

-1sta := NIL;

Eliminarlista (VAR lista: Tlista) ;


Ii.OCEDURE EliminarNodo (VAR primer: TL-sta, ;
- -- D

pAux: TList.a;
: _
_ ] JII!
-TIf

pAux = primer;
primer ;= primer".sig;
dispose (pAux) ;
-,-- PuNrsnos Y ESTRUCTURAS DE DATos DINAMICAS

':,:IDURE Insertar(VAR
primer: TLista; info: Tlnfo);
-.--t-:l

pAux: TLista;
::^T\T
__irr\
new (pAux) ;
-^
nArrY rnfa .- info.
nArlv^
r_.,*-. .__9
ci := prlmer;
primer '= PAux;
:]\tn .

?RCCEDURE Mostrarlnversa (primer: TLista) ;


,Muestra los valores en orden inverso pero no invierte la
-:-sta (RECURSIVO) )
3EGIN
IF (primer <> NIL) THEN
BEGIN EI\
Mostrarlnversa (primer". sig) ;
writeln (primer^. info) ; PF
END; BI
END;

PROCEDURE Mostrarlista (primer: TLista) ; llr


BEGIN
WHILE (primer <> NIL) D0 vl
BEG]N
writeln (primer^. info) ;
r
y!rLLlu!
^-i ..-
- prlmer .sIg;
END; B
END;

PROCEDURE EliminarNodo (VAR primer: TLisLa) ;


-,tAR

pAux: TLista;
t:-f\T
__JTI\

cAux .-:-
^^.,.. IJrrmer;
^-ir
Drimer ;= primer^.sig;
i-spose (pAux) ;
:.-
--: - -::-T.E Invertir (VAR primer: T],ista) ;
r,-."-::--e fsicamente la lista)
SolucroNrs 431

pAuxprimer: TLista;
BEGIN
IF (primer <> NIL) THEN
BEGIN
{Sl tray elementos se necesita una lista auxiliar.|
)
Crearli s t aV ac i a ( pAuxpr imer ) ;
IHILE (primer <> NIL) DA
BEGIN
Insertar (pAuxprimer, primer^. info) ;
{Se eliminan elementos de Ia original
segn se copian)
EIi_minarNodo (primer) ;
END;
primer ;= pAuxprimer;
END;
END;

PROCEDURE Eliminarlista(VAR tista: TLista) ;


BEGIN
WHILE (1sta <> NIL) DO
EliminarNodo (tista) ;
END;

VAR
lista: tlista;
j . i nlaaa-.

BEGIN iPrograma principal)


CrearlistaVacia ( lista) ;
FOR i := 1 TO N DO
fnsertar(1ista, i);
writeln(,Lista:,);
Mostrarlisca (lista) ;
readln;

writeln ('Lista invertida: , ;


Mostrarlnversa ( lista ) ;
readln;

{Se comprueba que no est fsicamence tnvertida}


writeln('Lista:,)
438 PUNTnnOS Y ESTRUCTURAS DE DATOS DINAMICAS

Mostrarlista (lista)

writeln ('Invertimos: ') ;


Invertir (lista) ;
writeln('Lista:');
Mostrarlista (lista) ;
readln;

{se libera Ia memoria reservada}


Eliminarlista (lista) ;
END. {Programa principal}

2. Lista doblemente enlazada


El cdigo anterior consigue perfectamente invertir una lista doblemente enlazad.
pues los nodos de sta tambin contienen un campo de enlace al nodo siguient;
Sin embargo, se podran utilizar los enlaces a los nodos anteriores para mostrar -
lista invertida o para invertirla fsicamente.

PROGRAM Visli staDoble ;


CONST
N = 10;

TYPE
'I'lnto = ].nteger;
TLISTa = ^TNodo;
TNOdO = RECORD
info: Trnfo;
ant: TLista;
.
>.9; 'l'l
r!It)Ld,'
END;

PROCEDURE CrearlistaVacia (VAR 1: TLista) ;


BEGIN
fI ._
,- rTTf
r\f!, .

PROCEDURE Insertar (VAR primer : TLista; info: Tlnfo);


VAR
pAux: Tl,ista,-
BEGIN
nes(pAr:x) ;
SoructoNRs

pAux^.info := info;
pAux^.ant := NIL;
nArrv^ .!_Y
ai ._ prlmer;
I,s,! ^
primer ;= pAux;
END;

PROCEDURE Mostrarlista(primer: TLista) ;


BEGIN
I^IHILE (primer <> NIL) DO
BEGIN
writeln (primer^. info) ;
nri-o-
yr rrrLtrl .: -= pf lmef . S lg ;
END;
END;

PROCEDURE Mostrarlnversa ( lista: TLista) ;


{Muestra los vafores en orden inverso pero no inviert.e la
lista (ITERATTVO)
)
BEGIN
IF (lista <> NIL) THEN
BEG]N
{Recorrido hasta el final de la lista)
WHILE (lista^.sig ., NIL) DO
I I ---
rrsLd. := .LlSta A .S19;
iRecorrido hacia fa cabecera de 1a lista)
WHILE (lista^.ant <> NIL) DO
BEGIN
I J
_L_LULd
-L -
:= tlSta .ant;
writeln (1ista". info) ;
END;
END;
END;

PROCEDURE EliminarNodo (VaR primer: Tlistal ;


VAR
pAux: TLista;
BEGIN
pAux = primer;
primer ;= primer^.sig;
primer^.ant := NIL;
dispose (paux ,
END;
440 Purnnos y ESTRUCTURAS DE DATos orNurcls

PROCEDURE Invertir(VAR primer: TLista) ;

{Invierte fsicamente la lista}


VAR
pAuxPrimer: TLisra;
BEGIN
IF (primer <> NIL) THEN
BEGIN
{Si nay elementos se necesita una Iista auxiliar}
CrearLi staVacia (pAuxPrimer) ;
WHILE (primer <> NIL) D0
BEGIN
Insertar (pAuxPrimer, primer^. info) ;
iSe eliminan elementos de 1a original
segn se copian)
EliminarNodo (primer)
END;
primer := pAuxPrimer;
END;
END;

PROCEDURE Eliminarlista(VAR lista: TLista) ;


BEGIN
I,{HILE (Iista <> NIL) D0
EliminarNodo ( 1i-sta) ;
:)iD;

VAR
I I ^L^ !r I
^-^
J-.L5Ld.: LLlSLd.;
i . rlauLYU!,
. i ntaaa-.

BEGIN {Programa principat}


CrearlistaVacia ( lista) ;
FOR i := 1 TO N D0
Insertar(1ista, i);

writeln('Lista:,);
Most.rarlista ( lista) ;
--^^lf-
r rid uIl.t,.

writ.eln ( 'Lista invertida: ' )


Mostrarfnversa ( lista) ;
Sor,ucroNns 4.+1

!rarrll
uqurr-. /

r,rri rol /\ /T.'i


lrJLq, cta.
/ l,
/ /

{Se comprueba que no est invertida}


Mostrarlista (Iista) ;
readln;

writeln(' Invertimos :, ) ;
Invertir (lista) ;
writeln(,Lista:,);
Mostrarlista (lista) ;
ra,.1 1-.

{se tibera }a memoria reservada}


Eliminarlista ( lista) ;
END. {Programa principal}

11.5.9 Suma de polinomios


;lOcRAM SumaPolin.
-:PE
TINfO = RECORD
exp : integer;
coef: real;
END;
Tlista = ^TNodo;
TNOdO = RECORD
rnfo : TInfo;
sig: TLista;
END;

--:
11, lZ, f: 'I'LISta; --
:-L-

,:,:EDURE CrearlistaVacia (VAR 1: TLista);


:: l-N
I := NIL;
-:
-. lIION EsVacia (1: TLista) : boolean;
:: .-li
:5Vd.Lj_Ld. := (t _ ITTT \ .
PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

l,_: PRO(

{ nnr
.: - I:IURE InsertarElemenLoPorElFinat (VAR I : Tlista; b : Tlnfo) ; VAR
"-::.
-:'*x/ nuevo: TLisCa;
::i--\ tsEGI
IF EsVacia(l) THEN
3EGIN
new (aux) ;
aux^.info := b;
^
aux^.sig := l;
'I .- lrrv.

END
ELSE
BEG]N
aUX := I;
I{HILE (aux^.sig .> NIL) D0
aux:= aux^.sig;
new(nuevo);
nuevo^.info := b;
nuevo^. sig : = aux^. sigi
aux^.Sig := riUeVoi
END
:\Tn .

?ROCEDURE CrearPolinomio (VAR I : TLista) ;


-.:AR

mono: Tlnfo;
orden, coef,i: integer;
::GIN
writeln ('Indica eI orden del polinomio' ) ;

:eadln (orden) ;
liR i := orden DOi^INTO 0 D0
- TIT
: ] ,.II\

writeln ( 'coef iciente de x^' , i, ' '.' ) ;


:eadln (coef) ;
-:1O.exp := i;
- --: . coef : = cof ;
-.-=:::arElementoPorElFinal (1, mono) ;

ENI
SolucroNBs 413

PROCEDURE Suma (I1, l2: TLista; VAR r: TLista);


1pR; : La lrsta result.ant.e r est vaca)
VAR
aux1, aux2: TLista;
mono: Tlnfo; imonomio auxiliar)
tsEGIN
.l1.
auxl :=
:rrv, .-
. _
1a.t
LZ

{si ambas list.as no son vacas se comparan y suman


los coeficientes)
IF (NOT EsVacia(aux1)) Nn (NOT EsVacia(aux2)) THEN
BEGIN
WHILE (NOT EsVacia(aux1)) aO (NOT
EsVacia(aux2))
BEGIN
{si- fos exponentes son iguales se suman
los coeficientes )
IF (aux1^.info.exp = aux2n.nfo.exp) THEN
BEGIN
mono := auxl^.info;
mono.coef := mono.coef + anjx2^.info.coef;
auxl := auxl^.si9;
aux2 := aux2^.si9;
END
ELSE
BEGIN
{Si un exponenLe es mayor que otro,
su monomio se aade a la resultante)
IF (aux1^.info.exp > aux2^.into.expj THEN
BEGIN
mono:= uX1^.info;
auxl := auxl^.si9;
END
ELSE
BEG]N
mOnO := aux2^.rr.f:;
aux2 := ux2".S_f;
END
END;
IF (mono.coef <> O) THEIi
InsertarElementoporEiFrna -
END; iwHrLE)
END:
, {r'l
l-- ]
PUNTEROS Y ESTRUCTURAS DE DATOS DINMICAS

j- -:a -isLa es vaca la otra se aade taI cual) 3I


. a :_=-.-,:_a tauxl) THEN
;.;:ILE NOT EsVacia(Aux2) DO

3]G1N
InsertarElementoPorEIFinaI (R, aux2^. info) ;

aux2 := aux2^.si9i
END
:.SE
WHILE NOT EsVacia(aux1) D0
BEG]N
InsertarElementoPorElFinal (r, auxl^. info) ;

auxl := auxl^.si9;
END;
END;

PROCEDURE Mostrarlista(1 : TLista) ; BEGIN


IF NOT EsVacia(I) THEN
BEGIN
WHILE (I^. sig <> NIL) D0
BEGIN
wrice(I^.info.coef ,' x^',
I := 1^.sig;
END;
write(]^.info.coef,'x^', I^.info.exp) ;

writeln;
END;
1l
END;

PROCEDURE Eliminarlista(VAR lis[a: Tlista) ;

PROCEDURE EliminarNodo (VAR primer: Tlista) ;

VAR
pAux: Tlista;
BEGIN
r--*._
nArrv pr].mer;
primer := Primer^.sig;
dispose (pAux) ;
:1.- I

:l r--
': <> NTL)
-: -lsta D0

' - -- -::arNodo ( lista) ;


:- -
SolucroNrs 445

:IGIN {Programa principal}


CrearlistaVacia (11) ;
CrearlistaVacia (12) ;
CrearlistaVacia (r) ;

{Se crean y se muestran los polinomios}


CrearPolinomio (11) ;
Mostrarlist.a (11) ;

CrearPolinomio(I2);
Mostrarlista(I2);
writeln;

{Se suman ambos polinomios y se muestra e} resultante}


Suma( I1, 12 , r) ;

Mostrarlista (r) ;
ral l n .

{se linera fa memoria reservada}


Elj-minarlista (I1) ;
Eliminarlista(I2);
Eliminarlista (r) ;
t_
:-.). tPrograma pr1nclpal.l

11.5.10 Sala de espera


l. Salida de lct sala de espera: En este procedimiento slo es necesctrio extror tLtt
elemento de la sala (de la cola)

FLTJCTION EsVacia(cola: TCoIa) : boolean;


BEGIN
EI7-^i- /^^f
.E_svduJ-d := \uurd^ = I\1L/ ;

END;

PROCEDURE EliminarNodo(VAR coLa: tl:-: ;

VAR
pAux: TCola;
DEN
D!U IT\T
I!
pAux := cola;
IF NOT EsVacia(cola) THEN
BEGIN
446 PuNtBnos y EsTRUCTURAS DE DATos nrNnrrcls

cola := col-a^.si9;
dispose (pAux) ;
tr\T .

END;

). Lo llegada de un paciente nuevo es Lrna insercin en la cola

PROCEDURE Insert.arFinal(VAR cola: TCola; p: Tpaciente) ;


VAR
pAux, pAux2: TCola;
BEGIN
pAux := cola;
new(pAux2);
- ^
pAux2.Into := p;
pAux2^.sig := NIL;
IF NOT EsVacia (pAux) THEN
BEGIN
WHILE (pAux^.sig <> NIL) DO
pAux:= pAux^.sig;
pAux^.sig := pAux2;
END
ELSE
cola : = pAux2;
END;

3. El abandono de la sala de espera sin entrar ct la consulta es una eliminacit,


un nodo interno de la cola

PROCEDURE Abandono(VAR cola: TCola; num: TNumHistClinica) ;


VAR
pAct, pAnt: TCola;
BEGIN
IF NOT EsVacia(cola) THEN
BEGIN
pAct := cola;
pAnt := NTL;
{Se busca por nmero de historial el nodo
Itre se elimina)
;,-1--E (pAct <> NIL) AND
:-r-t:^. info.numHistCli <> num) DO
:: l-l:
Sor,ucroNns 447

pAnt ;= pAct;
PAUL ;=
n71l- pACt
^^*^ .Stg; '

END;
IF (pAct^ . info. numHistCli = num) THEN
BEGIN
IF (pAnt <> NIL) THEN {si no es el primero)
BEGIN
pAnt". sig : = pAct^. sig;
dispose (pAct) ;
END
ELSE
BEGIN
cola := pAct^.sig; icabecera al 2oelem.
dispose(pAct); {se libera Ia cabecera}
END;
END;
END;
END;

4. Intercalamiento de colas segn rnra de llegacla cle rrs .tacierrtes

PROCEDURE EliminarCola(VaR cola: TCoIa) ;


VAR
pAux: TCola;
BEG]N
WHILE (cola <> NIL) DO
BEGIN
pAux := cola;
cola := cola^.sig;
di qnnco lnArrv\
\y^u^/ /
END;
END;

PROCEDURE Intercalar(VAR cola1, cola2: lCc_, :

{Se crea una nueva a partir de las dcs...s= j=-.-,-.=_:


en co1a1 )
VAR
colaAux, pAux1, pAux2: TCo1a,-
BEG]N
CrearColaVacia ( colaAux )

IF (NOT EsVacia (cota1) ) AND (lOt EsVacia(co1a2)) tHeN


BEG]N
+-*,\ PuNTnnos Y ESTRUCTURAS DE DAToS DINMICAS

pAuxl := colal;
pAux2 := cola2;
{tvlientras haya elementos en ambas col-as se
comparan y se aaden pacientes a la auxiliar)
11
WHILE (pAuxl <> NIL) AND (pAuxZ <> NIL) D0
BEGIN
IF NOT Mayorlgual (pAuxl^. info.hora,
pAux2^. info.hora) THEN
DETI]
DUTI\

InsertarFinal (colaAux, pAuxl^ . info) ;


nnr rv'1 := pAuxl .Srg;
END
ELSE
BEGIN
InsertarFinal (colaAux, pAux2^ . info) ;
pAux2 ;= pAux2^.sig;
END;
END;

{Cuando se termine de insertar una col-a se vue}ca


ta otra)
WHILE (pAuxt <> NIL) D0
BEG]N
InsertarFinal (colaAux, pAuxl^. info) ;
nArlv"l . - rrlAuxl .slg;
.-

END;
I{HILE (paux2 <> NIL) DO
BEGIN
InsertarFinal (colaAux, pAux2^. info) ;
nnrrw? . - nArrv)^ '"-Y
ci a.
END;

{Se eliminan ambas colas porgue se tiene


1a resultante en colaAux)
EliminarCola (cola2 ) ;
EliminarCola (cola1) ;
colal := colaAux;
END {rF}
{Si cota2 es no vaca es porque co}a1 s to era}
ItSE IF (NOT EsVacia(co1a2)) THEN
]: ^ TIT

;Se devuelve la cola restante en coIal)


::-al := Cola2;
___1- := N-LL;
Sor-ucrows 449

END;
END;

11.5.11 Cambio de sentido del tren


1. Dejrnicin de tipos
El vagn es un registro con parte variante donde la mquina es el campo discrimi-
nante.

TVagon = RECORD
peso: integer;
CASE maquina: boolean OF
TRUE: (potencia: integer;
maquinista: string [10] ) ;
FALSE: (pasaj eros : integer) ;
END;

TTren = ^TNodo;
TNodo = RECORD
vagon: TVagon;
dr_t rtrtrr^.
olY. f I!uff,

END;

). Creacin de un tren con fantos vagones como se den pctr teclado


El tren tendr una mquina propulsora en cada extremo.

PROCEDURE CrearTrenvacio(VAR t.ren: TTren) ;


BEGIN
tren : = NIL.
END;

PROCEDURE Insertarvagon(VAR tren: TTren; vagon: l-.-;:_:.


VAR
aux: TTren;
BEGIN
new (aux) ;
aux .vagon := v9oni
aux .SIg :='-ren;

r.ft#"
H1 ,.-
a

END;
#s'"
:.'
PROCEDURE CrearTren(VAR tren: TTren, ;
*'
r+l

-
450 PUNTERoS Y ESTRUCTURAS DE DATOS DINMICAS

{Se dispone de1 procedimiento InicializarVagon}


VAR
numVagones, i: integer;
.. r\I.-^.
vqYvl1 l vuYvl,

BEGIN
CrearTrenvacio (tren) ;
{Se inserta una mquina en un extremoi
Inicializarvagon (vagon, IRUE) ;
Insert.arVagon(tren, vagon) ;
{Se insertan los vagones de pasajeros}
writeln('Numero de vagones de pasajeros?');
readln (numVagones) ;
FOR i := 1 T0 numVagones D0
BEGIN
InicializarVagon (vagon, FALSE) ;
InsertarVagon (Lren, vagon) ;
END;

{Se inserta una mquina en el otro extremo}


Inicializarvagon (vagon, TRUE) ;
Insertarvagon (tren, vagon) ;
END;

3. Prot'etlintienfo Tunel para el carubio de sentido de la marcha de un tren


Se rtraen todos los vagones del tren desde el final y se vuelcan a una pila r--.
h.;e ls iun.irrnes de tnel. Una vez que se han metido todos los vagones .-
la prl.r sa e\triien \ se crea de nuer.o el tren con el orden de vagones inven.:
respecto.Ll rriSin1. Lo: identihcadores de los subprogramas se han particul. -

zado para e1 crrnte\to del tren pero son operaciones comunes altipo PiIa (C--.
Ll^d. i

FUNCTI0N EsVacio --:::i: lTl::n) : boolean;


BEGIN
EsVacio := (tren = NIL,;
END;

PROCEDURE ExtraerUltimoVagon(VAR tren: TTren;


VAR vagon: TVagon);
-I: D

pActual, pAnterior: TTren;


:=^TI]
J- --_r\
IF NOT EsVacio (tren) THEN
EF^TIT
!!g r l\
Sor,ucroNrs 451

pActual : = tren,. -F
pAnt.erior := NIL;
WHILE (pActual^.sig <> NIL) DO
BEGIN
pAnterior = pAct.ual;
pActual ;= pActual^."ig,
END;
IF (pAnterior = NIL) THEN
tren := pAct.ual^.sig
ELSE
pAnterior^. sig : = pActual^. sig;
vagon = pActual^.vagon;
dispose (pActual) ;
END;
END;

PROCEDURE SalirTunel (VAR pila : TTren; VAR vagon: TVagon);


VAR
aux: TTrtrn.
BEGIN
IF (NOT EsVacio (pi1a) ) rHl
BEGIN
qu^
f]]v ._
;= p-LId/.
^.,,]-

Vagon : = uX^ . vagon;


ni'l
yrJ-d. : A
ci^.
= pI_La '"-Y,
dispose (aux) ;
END;
END;

PROCEDURE Tunel (VAR tren: TTren) ;


VAR
pila: TTren;
vagon: TVagon;
BEGIN
IF (NOT EsVacio (tren) ) :.-.:,
{Ul tren no est. vacoJ
BEGIN
CrearTrenVacio (piIa) ; iC::ea:;__._.-.:-;
{volcado de los vagones a l; c-_= :_ _:::s
hay 2 vagones: cabeceras de tren r

REPEAT
ExtraerUltimoVagon (tren, vagon/ ;

J
PUNTEROS Y ESTRUCTURAS DE DATOS
DINMICAS

InsertarVagon (PiIa, vagon) ;


a

LINTIL EsVacio (tren) ; f.

{Se vuelcan todos Ios vagones


det tnel aI tren}
WHILE NOT EsVacie (Pila) D0
I
BEGIN E

SalirTunel (pita, vagon) ; {cima + Desapi}arJ


rnsertarvagtn(tren, vagon) ; {construir}
END;
END;
DTTN.
r\! ,

11.5.12 Almacn de artculos


| . Tiyts de dutos ttec't'suritts

TYPE
Tlncidencia = 7..4;
TArticulo = RECORD
codigo: integer;
descriPcion: string [30J ;

cantidad: integer
END;

TListaAlmaceri = ^TNodoAlmacen;
TNOdCAIMACEN = RECORD
articulo: TArticulo;
sig: TListaAl-macen
tr\Tn '

TFicheroAlmacen = FILE OF TArticulo;

TListalncidencias = ^TNodolncidencia;
TNodolncidencia = RECoRD

articufo: TArticulo;
incidencia : Tlncidencia ;

sig : TListalncidencias
l. --t .

)" Procedimiento AcLtaI i zaAlmacen V,


de artculo basta con
Puesto que ambas listas estn ordenadas por cdigo
ambas hasta encontrar coincidencias. Si el cdigo
del artculo de la lista
'
Sor,ucroNBs
453

cn es menor que el de ra de incidencia


se avanza con el puntero de ra rista
almacn hasta encontrar coincidencia. der
si dicho cdigo der artculo der armacn es
mayor entonces er artcuro de la rista
de incidencia lsiemp.e que el identiricador
de incidencia sea 3, cle lo contrario
existira eror).
PR,CEDURE AvanzarNodo(VAR
actual, anterior: TlistaAlmacen) ;
BEGIN
-^r ^--l - , :=
cijlLerlOf aCtUaf ;
actual := actual^.sig
END;

PROCEDURE EliminarNodo(VAR ant, act, lAlmacen:


TListaAlmacen) ;
VAR
:ttv. TLi staAlmacen;
BEG]N
IF (anterior = NIL) ?HEN
lAlmacen := act^ .sig
EtSE
ant^.sig := act^ .sig;
aUX : = aCL;
dcL := act .S1g; ,

dispose (aux)
END;

HKUUrjuuR-E _LnsertarNodo (VAR


ant, act, lAlmacen : TListaAlmacen,.
listalnc : TList.alncidencias )
VAR
aux: TList.aAlmacen;
BEGIN
new (aux) ;
aux^.art.iculo := listalnc^.art.icu1o;
aux^.sig:= act;
IF (ant = 1; THEN
lAlmacen := auxi
anLerior := uXi
END;

PROCEDURE ActualizaAlmacen (VAR


lisraA-:a::: TList.aAlmacen;
listalnc: TListalncidenctas ;, :

VAR
act.ual , anterior, aux: TlistaAlmacen,.
DINMICAS
PUNTBROS Y ESTRUCTURAS DE DATOS

:: llN
^rl := listaAlmacen;
anterior := NIL;
haya nodos
{ut siguiente bucle se realizar mientras
en ambas listas)
wHrLE (actual <> NrL) AND (listarnc <>
NlL) D0
BEGIN
IF (actual^ . articulo ' codigo = listalnc^ '
articulo ' codigo) THEN
fu:r r'oincidencia de cdigo de artculo de
i 11qJ
uvtrvt

ambas listas)
BEGIN
(listaInc^'incidencia) 0F
CASE
1: actual-^ ' articulo ' cantitiad : = actual^ '
articulo. cantidad + listalnc^ ' articulo ' cantidad;
2: actuaf^ ' articulo ' cantidad : = actual^ '
articulo. cantidad - listalnc^ ' articulo ' cantidad;
4 : EliminarNodo(anterior' actual'
listaAlmacen) ;

3 : writeln ('Artculo ya est en


el almacn ' ' '
'No corresponde una incidencia de alta'');
END; {casr}
IF (listaInc"'incid'encia <> 4) THEN
Avanzarlrlodo (actual , anterior) ;
listalnc := listalnc^'sig
END
ELSE
IF (actual" . articulo ' codigo < listalnc^ '
articulo. codigo) THEN
de almacn es menor
{et cAigo del- nodo de Ia lista
que el de Ia de incidencias ' Se avanza al siguiente
nodo de lista de almacn)
AvanzarNodo (actual, anterior)
ELSE
BEGIN
incidencias es
{et caiqo del nodo de Ia }ista de
menor que el de la de almacn)
casE (listalnc^.i-ncidencia) 0F
1 . rn cArl rNoclo anLerior, actual , I staAlmacen '
J.
(

listarnc) ;
ELSE
writeln('Artculo no existe en el almacn"
SorucroNns 455

'No corresponde una incidencia de baja. ,);


^* ^-
r
trNU; ILAtr1I

listalnc := listalnc^.sig
END;
END; {WHILE}
{rin aet bucle para nodos en ambas listas}
ir1 siguient.e bucle procesa incidencias restantes, si
l
Ias nllb1era i
WHILE (listrnc <> NIL) Do
BEGIN
CASE (listalnc^. incidencia) OE
3: InsertarNodo(anterior, actual, IistaAlmacen,
listalnc);
ELSE
writeln('Artculo no existe en eI almacn.',
'No corresponde una incidencia de baja.');
END;
listalnc := Iistalnc^.sig
uuo; {wurlu}

END;

11.5.13 Balance de parntesis

TYPE
TElemento = char;
TPila = ^TNodo;
TNodo = RECORD
e: TElemento;
c i n. TDi
-,a. I
-. --a;
END;

PROCEDURE CrearPilaVacia(VAR pila: TPila) ;

BEGIN
prla = NtL;
END;

FU1CTION EsPilaVacia(pila: TPiIa) : bcc-=;:-;


BEG]N
EsPilaVacia := (piIa = NIL);
456 PuNrrnos y ESTRUCTURAS DE DATos orNtrrcas

END;

PROCEDURE Apilar (VAR pila : TPila; e: TElemento)


VAR
l I
dux: "L-Y-Ltd/'
-

BEGIN
new (aux)
qq^
"ra*^ t o.
u. -o
-u,
.

aux^.si-g;= pila;
pila: =aux;
END;

PROCEDURE Desapilar(VAR pila: Tpila) ;


VAR
l l
dux: 1-H_LId,'
BEGIN
IF NOT EsPiIaVacia (pita) THEN
DDT\T
DLU f I\
aux := pila;
pila := pila^.sig;
dispose (aux) ;
END;
END;

;: _ _-:_l:E C:_ma (piIa: Tpila; VAR e: TElemento) ;


--:-=:::::aCo como procedimiento por generalidad. Una funcin
:::r-a :-t s.r capaz de devolver TElemento.
Se j:-.-*=---= -a :-ma sin eliminar el elemento de la pifa. )
BEGIIi
{lara ;: :-rl s-nple la asignacin simple es vlida}
o .- nr = ='
END;

FLINCTION Balanceada (expr: string) : boolean;


VAR
. nl-- ,

nilr.'FD'iI:.
t L L Ls t

posicion: integer;
: _] - TIT
- --11\
ISe recorre Ia expresin, se apilan 1os ,(, y
s: desapilan cuando se encuentran los cierres ,) , .
S- la pila termina vaca, Ios parntesis estn
SolucroNBs 457

balanceados en la expresin)
CrearPilaVacia (pila) ;
posicion := 1;
WHILE (posicion <= length(expr)) DO
BEGIN
IF [posicion] = ' (') THEN
(expr
Apilar (pila, expr [posicion] )

ELSE IF (expr fposicion] = ') ' ) THEN


Desapilar (pita) ;
posicion := succ(posicion) ;
END;
Balanceada := EsPilaVacia(piIa)
END;
Captulo 12

Unidades en Turbo Pascal

Como el lector sabr, a travs de las funciones y de los procedimientos se puede descom-
poner un problema complicado en varios ms sencillos de resolver. Adems se simplifica
:1 cdigo ya que se evita duplicarlo, es decir, se reutiliza un mismo cdigo. or-eanizado
:n subprogramas, en varias partes del programa. El nico incon\.eniente es que este
.'digo debe estar definido en el programa que 1o utiliza. Esta limitacin desaparece
1 hacer uso de las unidades de Turbo Pascal. Las unidades. pueden contener subpro-
lramas, constantes, tipos de datos, y variables. Para que un pro-srama pueda utilizar el
-ontenido de una unidad, nicamente debe incluir el nombre de Ia unidad, precedido de
-r palabra reservada Uses, a continuacin de 1a ,:abecera del programa.
Las unidades pueden compilarse de forma separada al programa que las utiliza. Esto
:ioporciona grandes ventajas, especialmente para el mantenimiento del cdigo, porque
-: pueden modiflcar y probar independientemente de los programas que las utilicen.

12.1 Estructura
-l estructura de las unidades permite separar qu hace un procedimiento o una funcitin
,: cmo lo hace. A esta separacin de conceptos se le llama abstraccitr .fiutt r,,i. L:
-:rdades encapsulan Ia implementacin de los procedimientos y las fun.i\rn->. permi-
:rdo al usuario emplearlos sin que se tenga acceso al cdigo de 10: nrirr-t,>.
Las unidades estn formadas por cuatro paftes: la cabecera de 1a un:i:l1. una pafie
-[ca, una parte privada, y una zona de inicializacin de variables.
.l <idencificador> {cabecera}
INTERFACE
IUSES<]ista de unidades> {opcionaL}-
{Declaraciones pblicas de consra:-r:-: , -: : : ' -rariables }
{Cabeceras pblicas de procedrmie:-cc- '.' : ^:-::-ones}
IMPLEMENTAT]ON
IUSES <]ista de unidades> {opcional-i,

459
460 UNrolons EN TURBo Plsclr

{Declaraciones privadas }
Implementacin de procedimientos y funciones)
IBEGIN
-i;-- i .-icializacin) {opcional}J
- '-o
En cabecera de la unidad se 1e da el nombre que la identifica. Este nombre es
1a e.

que se emplea para utilizar la unidad desde un programa.


o La parte pblica de la unidad, que es a la que tienen acceso los programas que
utilicen la unidad, viene precedida por la palabra reservada INTERFACE. En estl
parte. deben aparecer los prototipos de los procedimientos y de las funciones p-
blicas que forman parte de la unidad. Adems se pueden declarar constantes. e.
uso de otras unidades, tipos de datos y variables. Tambin es recomendable. per,
no obligatorio, declarar las especiflcaciones de la; funciones y procedimient...
que aparecen en esta seccin, con el fin de infbrmar sobre cmo emplear dichi.,
subprogramas.
o La parte privada, oculta para los programas que utilicen la unidad, Se ercuerrr.:
despus de la palabra reservada IMPLEMENTATION. Aqu es donde estn definidi.,.
los procedimientos y funciones cuya cabecera aparece en el INTERFACE. Dich.
cabeceras deben ser idnticas en ambas partes de la unidad. Tambin se puede:'
definir otros tipos de datos, constantes, el uso de otras unidades, y subprogrant.'
auxiliares a los que los programas que utilicen la unidad no tendrn acceso.
o La zona de inicializacin de variables, se encuentra al hnal de la unidad r .
opcional. En esta zona se pueden inicializar variables o invocar procedimien: .
y/o funciones. si es necesario, para eI conecto funcionamiento de la unidad. E::-,.
inicializaciones se realizan entre las palabras reservadas BEGIN y END. Cuando -,'
programa hace uso de una unidad, esta seccin de inicializacin se ejecuta an::
que el cuerpo del programa que la invoca. Aunque este apartado es optativo. p-,,
que una unidad se cree correctamente siempre debe aparecer el END final.

De las cuatro partes que componen una unidad la nica opcional es la de inicializacr
Sin embargo, no tiene sentido crear una unidad con el INTERFACE vaco, porque rf .:
:clra utilizar ningn procedimiento o funcin deflnido en la zona de IMPLEMENTA:- -.'
-:' .r
se crea con las definiciones de los subprogramas en el INTERFACE no se estara li., -

. .', la abstraccin funcional, que es uno de los objetivos de la programacin modL. --


- : ,- tanto de las unidades.

11.: Creacin de una unidad


:- - , .--,.,1 har operaciones aritmticas no predefinidas, tales como la poten. -
j ..-r " ::' , -:,:1.1uier base. Se puede crear una unidad ejemplo que contenga d,, "

l. -- ':'
Cnn.lcrN DE uNA uNTDAD 161

El primer paso es darle un nombre a la unidad. En


este caso. parece apropiado
llamarla Mates.

En la parte pblica (TNTERFACE) deben aparecer las


cabeceras de las funciones
y procedimientos que sern visibles. En este ejemplo
solo habr dos funciones:
Potencia y Logaritmo. Tambin se incluirn comentarios
que indiquen qu es
lo que hacen estas funciones y cur es ra forma de usarlas
corectamente.
Despus, en la parte privada (TMPLEMENTATTON)
se declarar el cdigo de estas
funciones. si fuera necesario tambin se podran declarar
funciones y/o procedi_
mientos auxiliares.

En la parte final de la uniclad, la inicializacin, no


se realizar ninguna llamada a
subprogramas ni ninguna iniciarizacin porque esta
unidacl ejemplo no lo necesita.

-NIT Mates;
TNTERFACE {parce pbIica}
FUNCTION potencia(base: real; exponente:
integer) : real;
{nre = rnuui
lrwDL -= ocl resultado es base^exponente)
fDncr
FLI-NCTI0N Logaritmo (numero, base: real ) . re:t
nrrmr^ >
{ Pro = rlumero 0 .,y base
- n *-^^--- > O)
{eost = eI resultado es e1 logaritmo de nmero en base)
IMPLEMENTATION {parte privada}
FIINCTION potencia(base: real; exponente:
integer) :
VAR
acum: real;
i . trLuYUr
i rra^o-.
/

BEGIN
aCUm = 1;
:
f'UR 1 := 1 T0 abs (exponenLe) DO
acum := acum * baSe.
IFexponente>0THEN
Potencia : = ct_t.
ELSE
potenci-a := _,,a:.^:
END;

FIINCTI0N Logaritmo (numerc, ilas: i :=.._ : __:__ i

BEGIN
Logaritmo : = Ln (numero) ,,'T i,.bas:
END;
462 UNrrrnrs nN Tunso Plsclr,

Para concluir el proceso de creacin de la unidad se deben realizar los siguiente.


pasos:

Guarda La unidad como un fichero con extensin . PAS. El nombre que se le da .


e-ste hchero debe coincidir (al menos los primeros ocho caracteres) con el identi-
ncador de Ia unidad. En el ejemplo: Mates . PAS.

,\continuacin se compila con destino a disco. Para ello se activa la opcin de


con-rpilacin Destination Disk, que generar un fichero con extensin .TF-.
Turbo Pascal Unit. que no es un flchero ejecutable.

La unidad compilada debe almacenarse en el mismo archivo que el programa que va *


hacer uso de ella o en el archivo UNITS de Turbo Pascal.

12.3 Uso de una unidad


Para poder ufllizar una unidad en Lln programa se debe incluir, en la cabecera del mism .

la siguiente lnea de cdigo:


USES <nombreunidad>
A continuacin se incluye un ejemplo que utiliza la unidad creada en el apartac
anterior.

PROGRAM Ejemplo0l;
USES Mates;
VAR
u,v: Iedl,'
'i tlltUYu!,
'i nraaav.

BEGIN
write ('Introduzca un numero real: ')
readln (u) ;
write (' Introduzca un numero entero:
--::1- 1i \
/,
--rurrr\f
':-.--eln(u:2:2, ' elevado a', i, t
C.

---: i'Introduzca otro numero real:


:eadln (v) ;
r:::eln('E1 logaritmo de ', v:2:2, , en base ,, t):2:2, , es: ,

, Logaritmo(v,u) t2t2) ;
--_

Este ejemplo se limita a comprobar el correcto funcionamiento de la unidad Mates.


Cursrroqns DE Trpo rEsr 463

12.4 Cuestiones de tipo test


12.4.1 Enunciados
Las siguentes cuestiones pueden tener una o ms respuestas correctas.

1. Las unidades sirvenpara:

(a) Complicar el proceso de programacin.


(b) Aadir funcionalidad al cdigo.
separar la implementacin de los subprogramas de su deflnicin.
-f) (d) Almacenar nicamente datos.

2. Cules de las siguientes afirmaciones son correctas?

(a) La estructura de una unidad se compone de dos partes, una parte pblica y
una parte privada.

-{b) La estructura de una unidad se compone de cuatro partes, siendo una de ellas
opcional.
(c) Todas las partes que forman parte de la estructura de una unidad son opcio-
nales.
(d) La estructura de una unidad no contiene partes opcionales.

3. Fjese en el siguiente fragmento de cdigo y seale aquellas respuestas que sean


comecta$

UNIT EjemploOl;
]NTERFACE
PROCEDURE Inr,ercambio (VAR a, integer) ;

IMPLEMEN?ATION
PROCEDURE Inr:::a:i_: -.';i :, integer) ;
VAR
aux: intege:;
BEGIN
,rv
qu^ .
.- l-'.
- !/

b := a;
:= Uxi
END;

END.
461 UNrlns nN Tunso PASCAL

(a) Una vez compilada la unidad, el procedimiento Intercambio, intercambia


los valores de las variables a y b.
(b) Esta unidad est incompleta porque le falta el cdigo de inicializacin.
(c) La unidad no podr ser compilada porque la variable aux tena que haber
sido declarada en el TNTERFACE.
-Pf) La unidad no podr ser compilada porque las cabeceras de los procedimien-
tos en el INTERFACE y en la zona de IMPLEMENTATION no son idnticas.

4. Seale las respuestas incorrectas:

*.fla) Las unidades facilitan la reutilizacin de cdigo.


(b) Si tienen cdigo de inicializacin, las unidades se pueden comportar comr
un programa.
'i{c) Las unidades deben compilarsc para poder utilizarse.
(d) Las unidades no satisfacen el concepto de abstraccin funcional.

12.4.2 Soluciones
1

l. La opcin correcta es la (c). Las unidades no complican el proceso de progr,,'


macin, al favorecer la reutilizacin de cdigo 1o simplifican. No aaden func, - I
nalidad al cdigo. Pueden almacenar tipos de datos, constantes, subprogramai t
variables.
2. La respuesta correcta es la opcin (b). La estructura de una unidad est fbmt.,:- 1

por cuatro partes y solo la ltima, la inicializacin de variables, es opcional.


t
3. La opcin cor-recta es la (d). La unidad no est incompleta, porque el cdigo :, t)
inicializacin es opcional. La variable aux est declarada en el lugar correcto. u
4. Las respuestas comectas son la (a) y la (c). Las unidades no son cdigo ejecutab .
Y s satisfacen la abstraccin funcional. I
R
12.5 Problemas
11,5.1 Ejemplo de una unidad
': -.
. ha hablado de la utilidad de las unidades como almacenes de cdigo, de tip,- . ,,
,-' ' j- constantes y de variables globales. Implemente la unidad que almacen.
: -: iloS v subprogramas del problema 9.8.6.
l:.5": \lgoritmos de ordenacin
: : : ,.r',: ,,r:-dad en la que estn presentes todos los algoritmos de orde: -,
:.- - -- ' ;-. r.,-.::'-r1o 8.
PnosLrM,{s ,165

12.5.3 Suma de polinomios


Implemente una unidad que almacene los tipos de datos y subprogramas del problema
11.4.9. Y desamolle un programa que la utilice.

12.5.4 Operaciones sobre un registro


Implemente una unidad que contenga la declaracin de tipo del problema 9.8.2 y tas
,.rperaciones sobre este tipo de dato del problema 9.8.3.

12.5.5 Calculadora para nmeros complejos


Implemente une unidad en la que se almacene el tipo de dato adecuado para representar
nmeros complejos y todas las operaciones aritmticas simples sobre los mismos. Un
nmero complejo es un nmero con pafte real y con parte imaginaria. La parte imagina-
rra se representa con un argumento, nmero real, seguido de la letra ,,i,,. Donde ,,i,, es la
:az cuadrada de -1. Disee un programa que compruebe la funcionalidad de la unidad.

12.5.6 Lista con registros


Implemente una unidad que contenga las operaciones sobre una lista, cuyos nodos con-
tendrn la informacin descrita en el problema 12.5.4.

12.5.7 Pila de datos


Una pila es una estructura que almacena datos, de tal modo que la forma de introducir y
obtener estos datos se produce por ei mismo extremo de la estructura. Implemente una
unidad Pi1a, que puede almacenar datos de tipo TElemento.

12.5.8 Guardar los datos de una cola en un fichero


Realice cada uno de los siguientes apartados:

o Implemente una unidad que conten-qa el tipo cie dart r-,r.::r : :. :.;ma 9.g.1
y las operaciones necesarias que perrnitan: rnicielizer:1 ::,..:,: :,--,n datos intro-
ducidos por el usuario: del'olr'er cacla uno de est Lj.i,..: :r.,-)::r;lor pantalla la
informacin acumulada en el registro.

e Implemente una unidad que contenga un tipo de ditr. c.. ur o tipo elemento sea
el tipo de dato definido en el apartado anenor.

c Implemente una unidad para un tipo de dato fichero binario, siendo el elemento
base del fichero el definido en el primer aparrado.
466 UNroIrs rN Tun.no PASCAL

o Disee un programa que cree una cola vaca, le inserte varios nodos, y antes de
terminar la ejecucin del programa cree un flchero con la informacin contenida
en la cola.

12.6 Soluciones

12.6.1 Ejemplo de una unidad


IntIIT E j emplo;
TNTERFACE
CONST {Primero se realiza la declaracin de constantes y
i nne ,de datos que son necesarios)
l-Lr^,uD

INI = 1;
= q.
E'T\T
N = 20;
M -- tO.I
LL

TYPE
TCadena = string [N] ;
TTlf = st.ring[Ml ;
TRango = IN] .FIN;
TRango2 = INI..N;
IFecha = RECORD
Cia: word;
:.: S : V,'Ord;
::- I : i:c::C:
l.t:
-:---;':-::1:'.,:
= --.:----.-
:::'
m-f-*--:-:: ,..-Ii;
END;
TMensaje = RECCRD
texto: strlng;
I eCna : '.t'l'Cha ;
hora: THora;
CASE conocido: boolean OF
TRUE: (identificacion: TCadena) ;
FALSE: (numero:TTlf); IM
IND; usl
--r,lmacen = array[TRango] OF TMensaje; PR(
].:::.oria = RECORD VAJ
:cdos: TAlmacen;
-3ce: pred(INI)..Flll; {Necesitamos un valor que :E(
Sor,ucrouns 467

indique que no hay datos)


END;
TINfO = RECORD
nomDre : '1 Cadena;
tlf : TTlf;
END;
TContactos = arrayITRango2] OF TInfo;
TAqenda = REeopn
contactos: TConcactos;
max: pred(fUf . ., {Necesitamos un valor que
indique que no hay datos)
END;

PROCEDURE CrearMemoria (VaR memoria: TMemoria)


;
{rre = rRUE}
{lost = crea estructura de memoria vaca}
PROCEDURE CrearAgenda (VAR agenda: TAgenda)
;
{prc
t--- = Tprrni
{nost = se crea una agenda vaca}
FIIITCTION Memoriallena (memoria : TMemoria)
: boolean;
{lre = TRUE}
fPnet - oi
-- fav
__pe = FIN la memoria esta llena)
PROCEDURE 0pcionesAgenda (VAR agen: TAgenda);
{pre Tpnnl
t--- =
{nost = se actualiza la agenda en funcin de ros deseos de
1os usuarios)
PROCEDURE OpcionesMensajes (VAR agen: TAgenda;
VAR entrantes, salientes: TMemoria) ;
r^
{Pre = TRUE}
f^--
tpost = Se habrn producido las accualizacic:r=s ,:=---::=.
en la memoria correspondiente)
FUCTION Menuppal: char;
{pre = TRUEi
{eost = Devuelve ta opcin esccg_ja ::: =_ --:'.rr__
PROCEDURE Avi soMemoriaLlena ;

_:.iPLEMENTATION
-SES Dos;
;iOCEDURE IntroducirNombre (VAR ncn: tlaj:::_ ;
".iR
. lnn.
:farrf
!g aI!
-
468 UNronops nl Tunno Plsclr,

REPEAT
wrrLe ('Introducir nombre: ') ;
readln (nom) ;
'riLeIn ('El nombre introducido es: ' , nom, '
si es correcto pulse s');
readln (c) ;
-NTIL C IN [,S,,,S,]
:-,- ; t IntroduclrNombreJ

PROCEDURE IntroducirTlf (VAR t: TTlf) ;


VAR
. 1^,=r.
BEG]N
REPEAT
write (' Introducir telefono: ' ) ;
readln (t) ;
writeln('Ef numero introducido esi ',L, E;
si es correcto pulse s');
readln (c) ; F1
UNTIL c IN ['s','S'] VJ
END; {IncroducirTlf}
BI
FUNCTION MuestraOpcionesBorrar: char;
VAR
dev: char;
BEGIN
REPEAT
writeln ('Escoja una de las siguientes opciones: ' ) ; EN
writeln('1. Introducir el nombre del contacto que',
' se desea eliminar') ; FU
writeln('2. Mostrar 1a lista de contactos'); vzu
readln(dev);
LINTIL dev IN l'L', '2'); {Se podra aadir una opcin ms BE(
para permit.ir salir sin actuar)
i r:straOpcionesBorrar := dev
:.-- il.lest.raOpcionesBorrar)

.: r--,1 : ---isoMemoriaLlena;
:1. ,

- ---=-.. -a r.emoria de mensajes entrantes esta llena')


r.-- i. =-:_-;-ienai
Sor,ucroNBs 469

PROCEDURE AvisoMensaj eEnviado ;


BEGIN
writeln('EI mensaje se ha enviado correctamente,)
END ; IAviso]4ensaj eEnviadoi

FUI\CTION NlodoEnvio: char ;

VAR
a: char;
BEGIN
REPEAT
writeln(,1. Enviar mensaje a un numero de Ia agenda,);
writeln(,2. Enviar mensaje a un numero introducido,,
' por eI usuario,) ;
readln (a) ;
IINTIL a IN l, l, ,,2,) ;
ModoEnvio : = a
END; {uoaonnvio}

FUNCTION Menuppal: char;


VAR
a: char;
BEG]N
writeln(,1. Opciones Agenda,) ;
writeln(,2. Opciones mensajes,)
writeln(,3. Salir') ;
readln (a) ;
MenuPpal : = a
END; {Uenuepal}

FIrT'TCTION MenuAgenda : char;


VAR
a: char;
BEGIN
REPEAT
writeln(,1. Aniadir un nuevo cont.acto, )
writeln ,2 Eliminar
( . un contacto ') ;
writeln(,3. Salir') ;
readln (a) ;
IINTIL a fN [, 1, , ,),4 I
tar1.
J J,
MenuAgenda : =a
lND; {Uenuagenda}
470 UNrolons BN Tunno Ptsclr,

FUNCTION MenuMensajes : char;


VAR
a: char,'
BEG]N
REPEAT
i.':rreIn ('1. Enviar mensaje') ;
.,--: _a- r (t)
4!ruur}l \ Recj-bir mensaje')
;
rireln ('3. el i -r \It .
rarrllr
!!qsr1]
/\
\q/ ,

-NTIL a IN l'l' , t zat t


,1/
) I .
Jt
MenuMensaj es : = a
iD; {Uenul',tensa j es i
PROCEDURE CrearContacto(VAR c: TInfo) ;
BEGIN
IntroducirNombre (c. nombre) ;
IntroducirTlf (c. tlf)
END; {CrearContactoi

PROCEDURE MostrarContacto (contac: TInfo) ;


BEGIN
writeln('Nombre:', contac.nombre)
END; {MoscrarContacto}

PROCEDURE CrearAgenda(VAR agenda: TAgenda) ;


BEGIN
agenda.max := pred(INI) EI\
END; {Crearagenda}
PR
FUNCTI0N Esvacia (agenda: TAgenda) : boolean; VA
BEGIN
Esvacia := (agenda.ftx = pred(INI)) 3E
:-,1; tESvaCta-|

r -. ll-0N HaySitio (agenda:TAgenda) :boolean;


:: -'-l
:, j-::c := (agenda.max<>N)
I - ::-l-rinI
--* ---rvi

ENI
.: -:- ',:: -:.=:..arContacto (VAR agenda: TAgenda; ConLacto: TInf o)
'-i ;

Fti
-'"--:" VAT
Sor,ucroNrs
4lt
final: boolean;
BEGIN
IF Esvacia (agenda) THEN
BEGIN
agenda.max := succ (agenda.max)
;
agenda.conLact,os lagenda.max] :=
contacto
END
ELSE
BEGIN
final := FALSE;
i := INI;
WITH agenda DO
BEGIN
max : = succ (max) ;
WHILE NOT final AND (i < max) DO
IF contactos Ii] .nombre > contacto.nombre THEN
BEGIN
final := TRUE;
E'aD ._ i+1DO
-.i
.,rq^ DOWNTO
contacrosIj] := contactos Ij -1]
END
ELSE
r .- a + _L;
contactosIi] := contacto
END
END
END; {InsertarContacto}

PROCEDURE EliminarContacto (VAR agenda: TAgenda;


-/AR indice: TRango2);
i: pred(rNr ..1q.
BEGIN
WITH agenda DO
BEGIN
FOR i := indice TO max_i D3
contactos Ii] : = contactos i.___ ;
max := pred(max)
END
END; {eliminarContacto}

FUNCTI0N EscogerContacto (agenda


: TAgenda) : TRango2,.
VAR
412 UNroInrs nN Tunso PASCAL

i,j: pred INI ..N;


s, ^t - -
!1-f,I
.
l

BEG]N
I r--i frrr \
_ ;= _I\-Lj /'
--_=J
- := ao3nda.max;
:.: : a-:.f
_ii=jTHEN
i := INI
ELSE
i := succ(i);
writ.eln('Si desea eliminar el sgte. contacto, pulse s:,);
MostrarContacto (agenda. cont.actos Ii] ) ;
readln (c) ;
UNTIL c IN ['s','S'];
EscogerContacto : = i
END; {EscogerContacroi

FUNCTION EncontrarContacto (agenda: TAgenda; nombre: TCadena) :


'iraaar.
rllLUyu!,
VAR
i, j,med: pred(INI) . .N;
final: boolean;
BEG]N
IF NOT Esvacia(agenda) THEN
BEGIN
final := FALSE;
WITH agenda DO
BEGIN
i := INI;
j := max;
REPEAT
med := (i+j) DIV 2;
final := (cont.actos[med].nombre = nombre);
IF contactos [med] .nombre < nombre THEN
i := med + 1
ELSE
j:=med-1;
'JITTIL final OR (i > j);
-I final THEN
Encont.rarConLacto : = med
I _::
::ccntrarConLacto := pred(INI)
Sor,ucroNBs +tJ

END
END
ELSE
EncontrarContacto := pred(INI)
END; {EncontrarContacto}

PROCEDURE AniadirContacto(VAR a: TAgenda) ;


VAR
L: : .LII1IO;
abandonar: BOOLEAN;
i: TRango2;
eleccion: char;
BEGIN
abandonar := FALSE;
IF NOT HaySitio(a) THEN {o se borra un contacto o se
abandona et proceso)
BEGIN
writern' -:,'x;:i"'::;:,::"'l"l3il'l;"'3i.,illl'1,
: ;,
contacto antiguo.' ) ;
REPEAT
write('Si desea eliminar un registro pulse s,',
si desea abandonar pulse n ') ;
readln (eleccion) ;
UNTIL eleccion IN ['s ' , ' S' ,'n' , 'N' ] ;
abandonar : = (eleccion IN ['n' , 'N' ] )
END;
IF NOT abandonar THEN
BEGTN
CrearContacto (c) ;
IF NOT ttaySitio (a) THEN {vamos a hacer hue::
BEGIN
i := EscogerContacto(a) ;
EliminarContacto (a, i )
END;
InsertarConracto (a, c
END
END; {aniaAirContacco}

PROCEDURE BorrarContacto(VAR a: lAce:ia :

VAR
u^ : uIl.d.r
-L^-^
,'
Urnons nN Tunro PASCAL

. ----raa). VAR
--.)!lYv- t
- --:,4
!--u\a!\r/
T\lT\ !.r!, NT.
- --, , tr'.U^-- . lJ-(r -L 1

:: r-1, RI

-: NOT Esvacia(a) THEN


:]iTTT
__ JII\

c := MuesLraOpcionesBorrar;
CASE C OF
, 1, : BEGIN U}
IntroducirNombre (nomb) ; END;
(a'nomb) ;
i,', ::";:HffilHto PROCE

EliminarConcacco (a, j ) BEGIN


ELSE WI
writeln ('Ese nombre no se ' ,
'encuenLra en la agenda') END;
END;
, 2, BEGIN PROCE
:

i = EscogerContacto (a)
: ; BEGIN
EliminarContacto (a, i ) mr

END END;
END
END FUNCT.
ELSE BEG]N
writeln('No se puede eliminar ningun contacto. Mer
, LA AGENDA ESTA VACIA') END; 1

:\D; {BorrarContacto}
PROCEI
:F.OCEDURE OpcionesAgenda (VAR agen: TAgenda) ; BEGIN
----t
meI
! . ^L--.
!1rq! , B.ID; {
::l-l'l
:.:PEAT PROCED
c := MenuAgenda; orlR

CASE c OF li
r, J
'1' :AniadirContacto (agen) ;
,2, :BoTTaTContacto (agen) ; 3EG]N
rl.- t.
- .-- -- - ,c IN l'7','2'l); REP.
: - . ...=-.-:-genda)

': - -:-'-- : ,- = -: Il:rsaj e (VAn mensa: TMensaj e) ;


Sor,ucroNrs 415

VAR
^. ^].--.
U. Ullql ,

BEGIN
REPEAT
writeln('Introduzca eI texto del mensaje:');
readln(mensa.texto);
writeln('Si desea modificar eI mensaje pulse s');
readln (c) ;
tllVTIL NOT (c f N [' s' , ' S' ] )
END; {Crearlzlensaj e}

PROCEDURE MostrarMensaje (mensaje: TMensaje) ;


BEGIN
WITH mensaje DO
writeln (texto)
END; {MostrarMensaje}

PROCEDURE CrearMemoria(VAR memoria: TMemoria) ;


BEGIN
memoria.tope := pred(INI)
END; {CrearMemoria}

FUNCTION Memoriallena (memoria : TMemoria ) : bool-ean;


BEGTN
MemoriaLlena := (memoria.tope = FIN)
END; {lulemorial,}ena}

PROCEDURE VaciarMemoria (VAR mem: TMemoria) ;


tsEGIN
mem. tope = pred ( INI )

END; {VaciarMemoria}

PROCEDURE EliminarMensaj e (VAR mem: TMerno::- a :

VAR
i,j: pred(INI) ..FIN;
^.
U. ^t--.
UIIAI ,

BEGIN
i = pred (rNr) ;
REPEAT
]Fi=FINTHEN
i := INI
ELSE
476 UNrlors nN Tunso Plscll-

I /t \
.L := SUCU\Il;
-----

writeln('Si desea eliminar e1 sgte. mensaje, pulse s:,);


MostrarMensaj e (mem. todos Ii] ) ;
readln (c) ;
LT'ITIL c IN ['s','S'];
WITH mem D0
FOR j := i TO pred(FlNt DO
todos [j ] : = tocios Ij +11 ;
mem.tope .= pred(mem.tope)
END; {Uliminartrlensaj e}

PROCEDURE LimpiarMemoria (VAR memoria: TMemoria) ;


VAR
op : char;
BEGIN
REPEAT
writeln ('Escoja una de Ia opciones: ' ) ;
writeln ('1. Borrar l-a memoria') ;
l
writeln ('2. Seleccionar un mensaje para borrarlo' ) ;
\
readln (op) ;
LINTIL op IN l'7' ,'2') ;
E
AQEr nn AEr

' 1' :VaciarMemoria (memoria) ;


' 2' : EliminarMensaje (memoria) ;
:l:l
EID; {i,impiarMemoria}

PROCEDIIRE GuardarMensaje (VAR memoria: TMemoria; mensa: TMensaje) ;

BEG]N
WITH memoria D0
BEG]N
tope : = succ (tope) ;
todosItopeJ := mensa
END
END; {GuardarMensaje}

PROCEDURE TerminarMensaje (VAR mensa: TMensaje; agenda: TAgenda;


i: integer; tlf: TTlf; f: boolean);
VAR
semana, seg, mseg: word;
BEGIN
WITH mensa DO
Sor,ucloNns
171

BEGIN
conocido := f;
T E' f! TUE^I
ffEt!

BEGIN
identificacion : = agenda. contacLos .nombre;
Ir]
writeln(;r:-, de nombre,, agenda.conracros
:::r:io Ii] .nombre,
' tiene eI numero ,, agenda.contactos ti] .t]f);
END
ELSE
nUmero :- llf.
WITH fecha DO
GetDate (anio, mes, dia, semana)
;
WITH hora DO
GetTime (hora, minut.os, seg, mseg)
;
END
:\D; {TerminarMensajei

:R0CEDURE TerminarMensa j eEntrante (VAR mensa: TMensaje;


--: p t1f: TTtf);
semana/ seg, mseg:word;
::GIN
WITH mensa DO
BEGIN
conocido := FALSE;
numero := tlf;
WITH fecha DO
uerLjate ( an1o, mes, dia, semana)
^^--L
;
WITH hora DO
GetTime (hora, minutos, seg, mseg)
,.
END
:i;D; {TerminarMensa j eEnt. rani e}

::CCEDURE EnviarMensaje (VAR


:e: : TMemoria,. a:
-rjl
mensaje: TMensaje;
op: char;
nom: Tcadena;
tlf : TTlf;
j: pred(INI) ..Ni
final, error: boolean;
: ]1TIT
,---r1\
lrearMensaj e (mensaj e) ;
418 UNrolons eN Tunno P,tsclr,

op : = ModoEnvio;
frn- .-;LTetr.
'- "'-"Lt

------: - L Jl

'-' , nPEaf
IntroducirNombre (nom) ;
j : = Encontrarcontacto (a, nom) ;
IF j ., pred(INI) THEN
final : = TRUE
ELSE
BEGIN
writeln (,El nombre introducido no se ,

'encuentra en la agenda,);
error : = Esvacia (a) ;
writeln(,Vuelva a intentarlo, ) ;
END;
final OR error;
UNTIL
'2' i Introducj_rTlf (tlf )

END;
IF NOT error THEN
BEGTN
IF Memoriallena (mem) THEN
LimpiarMemoria (mem) ;
TerminarMensaj e (mensaj e, , j , tlf, final ) ;
GuardarMensaje (mem, mensaje) ;
Avi soMensaj eEnviado ;
END
END; {EnviarMensaje}

PROCEDURE RecibirMensaje (VAR mem: TMemoria) ;


VAR
mensaje: TMensaje;
ix
_rL :
-l! I l.j-L,'
::.-)i
-: l,lemoriaLiena (mem) THEN
:: l_1.:
oMemori aLl ena ;
-:-'.-- s
__::_arMemoria (mem)
:-
l- =. ' =-.:-.-:'mensaje) ; {Simulamos que 11ega un mensaje}
- --f r.
-=_--- .- =-=r =a;;;rnte (mensaje,rlf) ;
GuardarMensaje (mem, mensaje)
END; {Recibirltensaj e}

PROCEDURE
salientes:
VAR
SorucroNBs

OpcionesMensajes (VAR agen: TAgenda; VAR entrantes,


TMemoria) ;
179

l
u. ^L--
ullar -
i
f FN TIT
JUat!
REPEAT
c := MenuMensajes;
CASE c 0F
'1' :EnviarMensaje (salientes, agen) ;

' 2' :RecibirMensaje (entrantes) ;


END
LTITIL NOT (c IN l'L' ,,2,))
:ND; {OpcionesMensajes}

:ND.

En 1a zona de INTERFACE, se ha incluido la declaracin de tipos y los procedimientos y


Iunciones que se utilizaban en el programa principal del ejercicio.
En la zona de IMPLEMENTATIoN, estn las definiciones (el cdigo) de todos los sub-
programas necesarios para el correcto funcionamiento del ejercicio, incluyendo tambin,
claro est, los que aparecen en el INTERFACE. El cdigo de los subprogramas es el mismo
que aparece en la solucin del problema 9.8.6. Con ayuda de esta unidad el programa
principal de ese problema qr,reda de la siguiente fbrma:

IROGRAM Mensajes;
-ses Ej emplo;
.,'AR

agenda: TAgenda;
trl]LId bd_Le : -'.iomnr i :
, -- -E...! _ ta /

op: char;
:IGIN {Programa Principaii
CrearAgenda (agenda ;

CrearMemoria (entra) ;

CrearMemoria (sale ;
REPEAT
op := MenuPpal;
IF MemoriaLlena (entra) THEN
Avi soMemori aLlena ;
CASE op 0F
180 Uxrnlons rN Tunso Plsclt-

' 1' : OpcionesAgenda (agenda) ;

'2' : OpcionesMensajes (agenda, entra, sale) ;

END
-LINTIL NOT (oP fU l'L' ,'2'))
:),Tl . {Programa PrinciPal }

Todos los subprogramas que utiliza este programa estn en el INTRFACE de la unidad
por lo tanto, una vez compilada (y almacenada en el directorio correspondiente) el pro-
grama Mensaj es podr ejecutarse coffectamente.

12.6.2 Algoritmos de ordenacin


Adems de los algoritmos, necesitamos el tipo de dato sobre el que acta el algoritm'
en este caso urays cle enteros. La unidad quedara de este modo:

UNIT Orden;
INTERFACE
CONST
pRIMERO = 1; {Constantes necesarias para la descripcin
ULTIMO = 30; de los tiPos de datos)
TYPE
Tlntervalo = pR1MERO..ULTIMO; {fipos de datos pblicos}
TEIem = lntegeri
TVector = array [Tlnterva]ol OF TElem;

{subprogramas pblicos }
PROCEDURE SeleccionDirecta(VAR v: TVector) ;
PROCEDURE InsercionDirecta(VAR v: TVector) ;
PROCEDURE IntercambioDirecto(VAR v: TVector) ;
PROCEDURE Mergesort(VAR v: TVector; izq, der: Tlntervalo);

IMPLEMENTATION
IYPE {Tipo de dat.o Privado}
Tlndice = pred (PRIMERO) . . succ (ULTIMO) ;

_-:_:rnentacin de los subprogramas pbticos y privados de la


:-=:l
.:, I:DURE SeleccionDirecta (VAR v: TVector) ;
-:
- - ::sMenor: Tlntervalo;
" -',
=:-- - t lElem;
::t-,

: -: - r= ?RIMERO TO pred(ULTIMO) DO BEGIN


SorucroNns 48r

valMenor := v[i];
posMenor : = i;
FOR j := succ(i) rO ULTIMO DO
IF vIj]<valMenor THEN BEGIN
valMenor := v[j];
posMenor : = j
END; {rr}
IF posMenor<>i THEN BEGIN
v[posMenor] := v[i] ;
v[1] := vafMenor;
Et\u tr_-r
1')
END {FoR i}
END; {SeleccionDirecta}

PROCEDURE InsercionDirecta(VAR v: TVect.or) ;


VAR
i, j . 'l^i^^.

aux: TElem;
BEGIN
FOR i := succ(pRIMERO) TO ULTIMO DO BEGTN
arlv .-.rf il
j := pred(i);
WHILE (j>=pRTMERO) AND (vIj]>aux) DO BEGIN
vlsucc(j)] := v[j];
j := pred(j)
END; iwt+ilu)
v[succ(j)] := aux
END {FOR}
END; { InsercionDirecta}

PROCEDURE IntercambioDirecto (VAR v: TVector);


VAR
r-/ J:'I'_LndrCe;
aux: TElem;
BEGIN
FOR i : = ULTIMO DOW}IO succ (pRIMERO) DO
FOR j := pRIMERO TO pred(i) DO
IF v[j] >vlsucc (j ) I runr BEGIN
aux := vljl;
vljl := v[succ(j)];
vlsucc(j)] := aux
END {rF}
UNrlss BN Tunro PascAL
definido
I)-; {IntercambioDirecLo} o de entt
es un til
:?.1:EDURE Fusion(v: TVector; iz' ce' de: Tlntervalo; internas
VAR w: TVector);
...,D
L2.6.3
'I 'i)t 1''
-L/ L' nrarl.(PRIMERO)
Ylev
..succ(ULTIMO) ;

f E.T]T\T
.IJN]T
SI
.l .- iry.
L ,_ L4I INTERF
-.1 :=
.- errf ne)'
Duuv\vv/ I TYPE
J
Y ;= iz; TI
I{HILE (i<=ce) AND 1i<=de) D0 BEGIN

IF VIiI<V[J] THEN BEGIN


wtkl '= viil; EN
i := succ(i) TI
END T}
ELSE BEGIN
wikl := v[j];
i := succ(i) E]
END;
k := succ(k)
. -----
fc,
-l
END; iv"lHILu 1

FORk:=j TOdeDO P:
wtkl := vlkl ; P
FOR k := i TO ce DO P
w[k+de-ce] := v[k] ; P

END; {fusion} P

PROCEDURE Mergesort(VAR v: TVecLor zq' der: Tlntervalo); _}iPLE


VAR
centro: TInterval0; !
BEG]N E

centro := (izq+der) div 2;


IF izq<centro THEN I
mergesort (v, centro) i
rtr q'rr'' (cencro) "q,
<der THEN
I
mergesorL (v, SUCC (centrs ' der) ;
E

iusion(v, izq, centro' der'v)


r- - ':ergeSOrt) I
]'-
I
:-::-_:rrloelprocedimientoEusion,necesarioparaelcorrectofuncionam-'- \
-::-:::-r--.lertenecealapafieprivadadelaunidad'EltipodedatoTlndic:':-*
Sor,ucroNrs 483

definido en la parte privada de la unidad porque no aparece


como parmetro de entratla
o de entrada./salida en ninguno de los subprogramas pblicos
de la unidad. No obstante
es un tipo de dato empleado por dichos subprogramas,
en la declaracin de variables
internas a los mismos.

12.6.3 Suma de polinomios


-TN]T SUT{.APOL;
INTERFACE
IYPE
TINfO = RECORD
exp: integer;
Coef: reaf;
END;
Tlista = ^TNodo;
TNOdO = RECORD
lnlo: '1 Into;
Srg:'.LL1Sta;
END;

iSubprogramas publicos )

PROCEDURE CrearlistaVacia iVAR r: TLista) ;


PROCEDURE Crearpolinomio (yAi. l: TLista) ;
PROCEDURE Mostrarlista (I : t- _s:al ;
PROCEDURE Suma (11, 12: fL_-:,; -.AR r: TLista)
PROCEDURE Eliminarlista ir.._i. __s:r: TLista) ;
IMPLEMENTATION

PROCEDURE Crearlist.avacla,:.r-_:. _ : - _-.-_


BEGIN
lisLa := NIL
END; {CrearlistaVacia}

FLll\lCTION EsVacia (I: TListal : bc:_=.::


BEGIN
EsVacia := (lista = NIL)
END; {nsVacia}

PROCEDURE Insert.arElement.oporElFinal r Vi-r _ : :--sta; b: Tlnfo)


VAR

I
UNrpaps EN TURBo Plsclr,

aux, nuevo: Tlista;


:r:-1,
rF Esvacia (L) THEN
tsEGIN
new(aux);
aux^.info := b;
aux^.sig := 1;
1 := Aux
END
ELSE
BEGIN
-.,.,
du^ __ I
;_ r/
WHILE (aux^.sig <> NIL) D0
&uX:= aux^.sig;
new(nuevo);
nuevo^.info := b;
nuevo^. sig : = aux^. sig;
aux^.sig := ouevoi
END
END ; { InsertarElementoPorE}Fina1 }

PROCEDURE CrearPolinomio (VAR 1:TLista) ;

VAR
mono: TInfo;
l. irfanor.
UILlc]I,
^rlan LvE!
^aaf / l. tlruuYu!,
BEG]N
writeln ('Indica el orden del polinomio' ) ;

readln (orden) ;

FOR i := orden DOI^INTO 0 D0


BEGIN
writeln ('Coeficiente de x^' , i, ' :' ) ;

readln (coef) ;
mOnO.exP:= i;
mono.COef := cOef;
InsertarElementoPorElFinal (1, mono) ;

END

-. lrearPolinomio)

.:. -:-,1,1 Suma(11, 12: Tlista; VAR r: Tlista);


:
.- -,.- a:x2: TLsta;
--'.:: --:ic; {monomio auxiliar}
Sor,ucroNns 4g-5

BEGIN
ar:'l .= .]1.
aux2 := L2; {Si ambas list.as no son vacas se comparan
y suman los coeficientes)
IF (NOT EsVacia(aux1)) ANO (NOT EsVacia(aux2)) THEN
BEG]N
WHILE (NOT EsVacia(auxl)) AlO (NOT EsVacia(aux2)) DO
BEGIN {Sr 1os exponentes son iguales se suman fos
coeficentes )
IF (auxl^.info.exp = aux2^.info.exp) THEN
BEG]N
mono:= ux1^.info;
mono.coef := 1o[o.coef + aux2^.info.coef;
auxl := auxl^.si9;
aux2 := aux2^.si9;
END
ELSE
BEGIN {Si un exponente es mayor que otror su
monomio se aade a la resultante.|
IF (aux1^.info.exp > aux2^.info.exp) THEN
BEGIN
mono:= ux1^.info;
auxl := auxl^.si9;
END
ELSE
BEGIN
mono := uX2^.info;
aux2 := aux2^.Si9;
END
END;
IF (mono.coef <> 0) THEN
InsertarElementoporElFina- :, l::_-
END; {WHILE }
END; {tri {Si una lisra es vaca
la otra se aade :a_ :-=_
IF EsVacia (auxt ) TI:EN
WHILE NOT EsVacra i;rl t:
BEGIN
Insert.arElementoporElFinal (R, ar:x2^. info)
aux2 := aux2^.sig;
END
ELSE

/
:- UNIDADES EN TURBO P'SCAI

l,iILE NOT EsVacia(aux1) DO


BE
3EGIN
InsertarElementoPorElFinal(r'aux1^'info)
auxl := auxl^'si9;
END
:l,l; {Suma}

=i.CCEDURE
Mostrarlista(I: Tlista) ;

3]GIN
IF NOT AsVacia(1) THEN
BEGIN
WHILE(1^.sig <> NIL) DO

BEGIN
write (1" ' info. coef, 'x ^,, I^.info.exp, '+');
I := l^'sig;
END;
write (l^. info. coef, 'xn' , l^ ' info ' exp) ;

writeln
END
EN
END; {Mostrarlista}

PROCEDURE EliminarNodo(VAR primer: Tlista) ; t2


VAR '\T

PAux: Tlista; iN
BEGIN
:0
PAux := Primer;
primer = Primer^'sig;
disPose (PAux)
END; inliminarllodo)

PROCEDURE Eliminarlista(VAR lista: TLista) ;

BEGIN
WHILE (lista<> NIL) D0
TY
EliminarNodo ( lista)
:lll ; {U1imi-narl,ista}
l

-.Jelossubprogramas,deestauni<lad,hasidoextradodelcaptuloL1
'- - ' .: ::rn.ipal del problema 11'4'9 quedara:

. . -
-.
.--:!l

i -':--
.-t
Sor,ucroNBs 481

11, L2, r: TLista;


3EGIN {Programa principal}
CrearlistaVacia (11) ;
CrearlistaVacia (12) ;
CrearlistaVacia (r) ;
{Se crean y se muestran los polinomios}
CrearPolinomio (I1) ;
MostrarlisLa (I1) ;
CrearPolinomio(12);
Mostrarlista (12 ) ;
r.,ri ral n.

{Se suman ambos polinomios y se muestra el result.ante}


Suma ( 11, L2 , r) ;
Mostrarlista (r) ;
ranl -.

{se tinera la memoria reservada}


Eliminarlista (11) ;
Eliminarlista (I2) ;
Eliminarlista (r) ;
:ND. {Programa principat}

12.6.4 Operaciones sobre un registro


.TJIT Registro;
INTERFACE
:ONST
N = 30; {para Ia longitud del nombre}
a _ o.
INI = 1;
= ?7.
F'T\T
FIN_N = 2000; {mximo numero de casa}
FIN_C = 9999; {mxrmo numero de cdigo p:s-.=-
ULT = 6; {mximo nmero de convocatclta:,
TYPE
TNumero = INI..FIN-N;
TCodigo = INI..FiN_C;
TNombre = string [N] ;
TTelefono = scring . ll ;

tnni = TTelef ono ; {para ;'*= =- ::-- -:-:- .". - - =:':,


TRango = INI..FIN;
TRango2 = INI..ULT;
TINfO = RECORD
:"::bre: TNombre; VAR

:-:la: char; i
D
:1,-;
a-=-=
nEaADD
r\!Lv\
C
-
:lombre : TNombre; BEGI

conv: TRango2;
:'-:.
--isignaturas = arraY [TRango] 0F Tlnfo;
-:onvocatoria = array [TRango] OF TRepe;
-f,ireccion = RECORD
calle, ciudad: TNombre;
numero: TNumero;
codigo: TCodigo;
END;
END;
TEstudiante = RECORD
FUNC
nombre: TNombre;
VAR
direccion: TDireccion;
telefono: TTelefono; i
dni: TDni; S

asignaturas : TAsignaturas; C

^atr
!J! raeLidOf:
lu|\/ bOOIean OF BEG]

TRUE: (convocatoria: Tconvocatoria) ;

END;

{ subprogramas Pblicos }
(VAR estudiante : TEst'udiante)
PROCEDURE IntroduceEstudiante
PROCEDUREMostrarEstudiante(estudiante:TEstudiante);

IMPLEMENTATION

?ROCEDURE IntroduceNombre (VAR nom: TNombre) ; END;


-,--r.R

:: char; PROC

:
----'l -__\ tsEGI

: ].DEAT
rite ('Introduzca eI nombre: ' ) ;
::adln (nom) ;
pulse s' ) ;
'::
-ie ('El nombre es : ' , nom, ' si es correcto
..:lr l\ I
-:.r-ra\e/
' - ,- , -l'tr ['s','S']
: - - ,:-:eNombre) B,ID;

- - :. ^ :)'iumero : TNumero ; ?ROC


Sor,ucroNns
489

VAR
-l .i-r^^^-^
rllLCgeI ,.

s: string[4];
code: integer;
BEGIN
REPEAT
write ('Introduzca el ]-]ufie ro: /) ,.

readln (s) ;
val (s, i, code) ;
IF code <> O THEN iSe tra producido error)
i := pred(INI);
UNTIL (i > pred (rmr ) ) arm (i < succ (FIN_N)
IntroduceNumero : = i
);
END; {IntroduceNumero}

FLI1VCTI0N Int roduceCodigo : TCodigo;


VAR
i . 4rrueYur,
in1-a^o-.
s : st.ring [4 ] ;
code : int.eger;
BEG]N
REPEAT
write (,fntroduzca
readln (s) ;
vat (s/1,code);
IF code <> 0 THEN {Se na producido
error J
i : = Pred (INr) ;
LINTIL (i > pred (rUr ; 4 (i
< succ (FIN_C) ) ;
IntroduceCodiqo : = i
trNU; t ntroduceCodigo)
_t

rnrroduceDireccion (vAR dir:


::::^Trr.r rDireccion),.
writeln (,
Nombre de Ia ciudad: ,
);
IntroduceNombre (dir. ciudad)
;
writ,eln ( , Nombre de Ia ca11e: ,
);
Int,roduceNombre (dir . cal1e)
;
dir.numero := IntroduceNumero;
/- dir.codigo := IntroduceCodigo
END; { IntroduceDireccion}

PROCEDURE rntroduceTlf (ven trf : TTelefono) ;


UNro.gs nN Tunno P'sclr-
END;

-':
PRO(
- ---i-- I

:-r-1, VAR
- 1:1''-f
- ---_ :

-^^a"-^' ol
',';'rite (' Introduzca nrrP.,^o de celef ono: ' ) ;
el numero BEG:

readln (t]f) ;
write 'tt
' 't:""t"1'1"?i""t;tfl"=" =' '
'
]ND
read'Ln (c) ;

-'ldTIL c IN ['"','S') FUN(


:1.-: {IntroduceTlf} VAR

;:ICEDURE Introd'uceDNl (VAR dni:


TDni) ;

"')
c: Char; BEG
:
"rlT\T
REPEAT
,.,riror'Tntroduzca
w!ttu \ rr e} numero del D'N'I': ');
readln (dni) ;
,.,rirol'tr1.
w!ruu \ !f D.N.I. es: ',dni,
' si es correcto Pulse s');
readln (c) ;
UNTIL C IN [,S,,,S']
END; {IntroduceDut} ENI

FIr'NCTION Nota: chari PR(


VAR BE(
c, s : char;
tsEGlN
REPEAT EN:
le ('lntroduzca la noLa: ') ;
urri
readln(c); s'); PR
write ('La nota es: rUr^
I t -.i
Dr ac
uP correcto Pulse
VA
readln (s) ;
-,l.lIL s IN ['s' , 'S'] ;
BE
.- a
., l
r ---a l
EN
.- .-- -: -::roducelnf o (VAR inf o: TInf o) ;

:a" PR
. '- - -----=l'::'ire (info'nombre) ;
VA
'- -- ': ---. : = NOta
Sor,uctovrs
491

END; {Introducelnfo}

PROCEDURE IntroduceAs i gnaturas


VAR
(VAR asig: TAsignaturas);
1 : ',l',Rango;
BEGIN
FOR i
= INI TO FIN DO
:
Introducelnfo (asig Ii] )
END; { Introduceasignaturas
}

FIINCTION NumeroConvo: TRango2;


VAR
i : int.eger;
s: string[4] ;
code: integer;
BEGIN
REPEAT
write (,Introduzca
e1 numero de convocatoria: ,
readln (s) ; );
vd-L 1s,t,code),.
IF code <> 0 THEN {Se ha producido
error)
i : = pred (fNr ,
LTITIL (i > pred (rNr ) ) AND (i
< succ (ulr;,
NumeroConvo : = i
END; {Numeroconvo}

rnrroduceRepe(vAR repe:
::::^:rr*r
D!gAI\
rRepe) ;

fntroduceNombre (repe.nombre)
;
repe.conv := NumeroConvo
END; ilntroduceRepeJ

PROCEDURE fntroduceConvocat.orias (VAR


vAR ccnr,,3: - l::,_.,-: _ -. . :
_:.,_--,.
l- : l,Rango;
BEGIN
F'nP 'i .:=
!w^ -L - rnrr
1I\1 l0 F_N __ E

IncroduceRepe co:-..- _
END; {IntroduceConvocator_as

PROCEDURE IntroduceEstudiante ri?.:. :s::it::::


: -:s:udrante) ;
UNIDADES EN TURBO PISCIT,

I: a':-aT ;
END;
::a-1,
.:-eln ('Introduzca los datos deI estudiante') ;
Dpn/r
- :: roduceNombre estudiante . nombre ) ;
(
BEGI
- ion ( estudiante . di recc ion ) ;
:-: roduceDi recc
- :-, roduceTlf estudiante . telef ono ) ;
l
(

-rtroduceDni (estudiant.e . dni ) ;


',,,':iLeln('Introduzca los datos de Ias asignaturas') ;
PROC]
- it roduceAs i gnaturas es tudiante . as ignaturas ) ;
(
DU
u!ga1T1
?.EPEAT
write ('Es repetidor (s/n) ? '\ ;
I

readln (c) ;
-rTlTILc IN ['s' ,'S' ,'rr','N'] ; !

estudiante.repetidor := (c IN ['s','S'] ); tr,NTN.


1F estudiante. rePetidor THEN
BEGIN
PROCI
writeln ('Introduzca datos sobre fas convocatorias: ' )
VAR
IntroduceConvocatorias (estudiante . convocatoria) ;

END
i:
3EGIN
:lJ); {IntroduceEstudiante}
W

F
Subprogramas para mostrar informacin)

(nombre: TNombre) ; :ND;


.:.CCEDURE MuestraNombre
I lTrl
JII\
- -
: ?or.E,t
writeln (nombre )
3EGIN
:ilD; {MuestraNombre}
M
l:CCEDURE MuestraNumero (num: integer) ;
:]-_IT W
_,,--r\
'*'riteln (num) W,

iND;
:.'- I MuestraNumero)

-I :,1;.9 MuestraDireccion(dir: TDireccion) ; :-ROCEI


-,AR
j

i:
- --,= 'lTombre de la ciudad: ');
sEGIN
,1,:mbre (dir.ciudad) ;
w1
l -rbre de la calle: ');
- .-::e (dir.calle); FC

. - :-]: '\;
:: ..'--=t: (dir.numero) IND; i
;
: , :-:: POStal: ') ;
SotuctoNns
193

MuestraNumero (dir. codigo)


END ; {MuestraDireccion}
PROCEDURE MuestraTelefono (tlf: TTelefono) ;
BEGIN
writeln (tlf)
END; {MuestraTelefono}

PROCEDURE MuestraAsig (info: TInfo) ;


BEGIN
write (,Nombre: ,) ;
MuestraNombre ( info . nombre ) ;
write(,Nota: ,;
writeln ( info
. nota )
END; {UuestraAsigJ

PROCEDURE MuestraAsignaturas (asig: TAsignaturas)


;

r: IRango;
BEGIN
writeln (,Listado de asignaturas: ,)
;
FOR i : = INI TO FIN DO
MuestraAsig (asig ti; ;
END; {MuestraAsignaturas
}

PROCEDURE Muestraconvo (r: TRepe) ;


BEGIN
write(,Nombre: ,);
MuestraNombre (r. nombre
);
write(,Convocat.oria:, ) ;
writeln(r.conv)
END; {MuestraConvo}

PROCEDURE MuestraConvoca:c:_as as _r :
VAR
i: TRango;
BEGIN
writeln (, List.ado de convocatorias
consumidas: , ) ;
FOR i := fNf TO FIN DO
MuestraConvo (asig tjl
END; {Muest.raConvocatorias}
Urrrtuns BN Tunso Pasc'r'

.. -1- -:: l::strarEstudiante (estudiante: TEstudiante) ;

'': -:=-n ('Datos del estudiante: ' ) ;


'': -:3 ,'Nombre: ') ;
l
l l *:s:raNombre (estudiante' nombre) ;
I
'.;=straDireccion (estudiante " direccion) ;
E
',,;:tte (' Telfono:' ) ;
I'luestraTelef ono (estudiante ' telef ono) ;
''r'::ite('Nmero del D.N.I.: ');
l,{uestraTelef ono (estudiante 'dni) ;
MuestraAs ignaturas ( e studiante' as ignaturas ) ;
IF estudiante. rePetidor THEN
MuestraConvocatorias ( estudiante' convocatori
a)

=\D ; {MostrarEstudiance}
;\ln

los subprogramas es e1 mismo que el de 1a solucin del problema 9.8.3. El


E,l ccligo de
programa principal quedara como sigue:

PROGRAM EjemPlo3;
USES Registro;

VAR
e1 : TEstudiante;
BEGIN iPrograma PrinciPal)
IntroduceEstudiante (e1) ; p
MostrarEsrudiante t e1) ;
B
END. {Programa PrinciPal}

12.6.5 Calculadora para nmeros compleios


-1,IT ComPle j o;
--:Dft7\atr

a:

,,-:plelo = RECORD
rreal, Pimag: real;

.: -,r-,:.: IntroduceNumero(VAR c: TComplejo) ;


=: - :----: ::;estraNumero
(c: TComplejo) ;
.: -:---:: l::ol-ementado(VAR c: TComplejo) ;
.: --.-:.: ir:a'a, b: TComplejo; VAR c: TComplejo) ;
SorucroNns _195

PROCEDURE Resta(a, b: TComplejo;


VAR c: TComplejo);
PROCEDURE Multiplica(a, b: TCompIejo; VAR c: TCompIejo);
PROCEDURE Divide(a, b: TComplejo; VAR c: TComplejo);

IMPLEMENTATION
PROCEDURE IntroduceNumero(VAR c: TComplejo) ;
BEGIN
write('Introduzca la parte real del numero complejo: ,);
readln (c.prea]) ;
write('rntroduzca Ia parte imaginaria del numero complejo: ,);
readln(c.pimag)
END; ilntroduceNumero)

PROCEDURE MuestraNumero (c : TCompIejo) ;


BEGIN
write(c.prea1:2: 2);
IF c.pimag <> 0 THEN
BEGIN
IFc.pimag>0THEN
write(, * ,, c.pimag 2: 2, ,i,)
ELSE
write(, ,, c.pimag:2:2, ,,)
END
END; {MuestraNumero}

PROCEDURE Complementado(VAR c: TComptejo) ;


BEGIN
c.pimag : = -1*c.pimag
END; {Complementadoi

PROCEDURE Suma(a, b: TComplejo; VAR c: TComplejo,;


BEGIN
c.preal := a.preaf + b.preal;
c.pimag := a.pimag + b.pimag;
END; {Suma}

PROCEDURE Resta(a, b: TComplejo; VAR c: TComplejo);


BEGTN
c.preal := a.preal - b.preal;
c.pimag:= a.pimag - b.pimag
END; {nesta}
t
UNIDADES EN TURBO PISC,tI-

)l;,trpIica(a, b: TCompIejo; VAR c: TComplejo) ;

-1) * (a.pimag*b.Pimag) ;
c.Preal := a.Preal*b'Preal + (

a . preal *b . Pimag
c.Pimag := a.Pimag*b'Preal +

anD; {r"rurtipri-ca}

Divide(a, b: TComPlejo; VAR c: TComplejo);


':-::DURE
TComPlejo;
'lxl , avx2:
auxl := b;
ComPlementado (aux1) ;

MuttiPlica (b, aux1, aux2 ) ;


MultiPlica(a, auxl' c) ; L,,

^ nro:l := c.Preal laux2'Prea1;


u.y!uqt

c.pimag := c.Pimag I aux2'Prea1 Pr

END; {Divide} 1I:

END. Rr

UnprogramaquepruebesilaunidadComplejofuncionaCorrectamente,podraserel U]
que se detalla a continuacin' I]
PROGRAMCalculadora;
T
USES Complejo;
VAR
n7, n2, n3: TComPIejo;
BEGIN {Programa PrinciPal}
IntroduceNumero (n1) ;
IntroduceNumero (n2) ;
write ('Resultados de 1as operaciones sobre: ') ;

MuestraNumero (n1) ;

write('y');
MuesLraNumero (n2) ;
' ::-teln;
' : -:e ('Suma: ') ;
.---: 11 , n2, n3)
--.::aNumero(n3) ;

-^---. ,\.
- - '--- !

'==-q. 1t

.=a ..,- :-2, n3);


. .,. . n 2\
:- LlJt I
=--

- =- -

- -'-= -----:--:aCiOn: ') ;


Sor,ucroNns
191

Multiplica (nt, n2, n3);


MuestraNumero (n3 ) ;
wri t eln;
write(,Division: ,);
Divide (nl, n2, n3 ) ;
MuestraNumero (n3 ) ;
wri te ln;
write(,Complement.o de:, ) ;
MuestraNumero (n1) ;
r,rri 1-ol -.
rYr{uuIlf,
Complementado (n1) ;
MuestraNumero (n1) ;
END. iprograma principal)

12.6.6 Lista con registros


Para evitar volver a escribir el cdigo
que necesitamos, utilizaremos Ia unidad
mentada en el problema 12'5.4. Para imple-
elio basta con introcrucir la lnea de cdigo
Registro en 1a seccin adecuada de la unidad. usES
En este caso, en el TNTERFACE.
',TJIT Lista;
iNTERFACE
USES Registro;
TYPE
TElemento = TEstudiante;
Tlist.a = ^TNodo;
TNOdO = RECORD
inf o : TElemento,.
Srg: '.t,Lrsta i
END;

pROCEDURE CrearlistaVacia(VAR Irsta: TLrsca :


PROCEDURE InsertarElement.o (VAR lista: T- _s:a,
_nfo: l._=1.::_. _

PROCEDURE EliminarElemenLo (VAR


l-:s:,: t_ __=:,
FLINCTION SiguienteGista: Tlis::
: _-_s_:
PROCEDURE Recorrer lrsra: -:-:
:I'lPLEMENTATION

PROCEDURE CrearlistaVacia (VAR _ls:a: -- - c_:


BEGIN
498 UNrolnns nN TuRso Pascrr,

__-:ta : = 1,,_-

:1.-: l:=a:LrscaVacia)
I-1.-l- -f EsVacia (lista: TLista) : boolean;
:::_:; I
_JVAUIA .- \aIDLa - t\aL/
:'-- fE'ol/".i".| I

PROCEDURE InsertarElemento (VAR lista: TLista; info: TElemento) ; a

VAR s

aux: TLista; l
BEGIN lr

new(aux); c
aux^.info := info; d
A.
aux^.sig := Iista; d
Iista : = aux d
END; {InsertarElemento} e
c
PROCEDURE EliminarElemento(VAR Iista: TLista) ;
VAR
aux: TLista;
I
BEGIN u
IF NOT EsVacia(lista) rHnU I]
BEGIN T'
aux := lista^.sig;
dispose(liscal ;
lista := aux;
END
END; {eliminarflementoi

FIIJCTION Siguiente (lisLa: Tlista) : TLista;


BEGIN
IF NOT (EsVacia (1ista) ) rUl
Siguiente := Iista^.sig
ELSE
Siguiente := NIL
: -- ':rn,r'i^-r^\

n4
-:- :: j--:LUIler vllif
\rf a.
Duq. lrl 1di-\
r!aDuq/ PR
::.--' BE
:--: --S:a <> NIL) D0
:: r--_ EN
Sor,ucrouBs
199

MostrarEst.udiante( lista^ . info)


;
Iista := Iista^.sig
END
END; {Recorrer}
END.

Se ha modificado el cdigo del procedimiento


Recorrer, porque en este caso concreto
el procesamiento que se realiza sobre los nodos
de la lisia *orr.u,
almacenada en cada uno de ellos. Esta es ", que sela infbrmacin
la nica modifrcacin debe realizar
sobre las operaciones estudiadas sobre una lista.
De este moilo se ha creado un Tipo
Abstracto de Dato (TAD). un TAD es un tipo
de dato crefinido por el programador, ms
las operaciones que pueden realizarse sobre
ese tipo de dato. En este problema se ha
creado el rAD lista que a su vez utiliza el
rAD .egistro. Agrupando la definicin de tip'
de dato y las operaciones sobre r se consigu.
,n .digo ,iro ms claro y sencillo de
depurar' como se ha estudiado previamente.
el cdigo de las unidades se puede mejorar
de forma separada sin que ello tenga por
qu af'ectar a ros programas que hacen uso
ellas' El resto de los procedimientos y funciones, de
de esta uniia, han sido extrados del
captulo I 1.

12.6.7 Pila de datos


LTITTIT Pila;
INTERFACE
TYPE
TElemento = . .;
Tpila = ^TNodo;
TNodo = RECORD
lnto: TElemento;
sig: Tpila;
END;

PROCEDURECrearpilaVaciaiirii. :__a: -:_ :


FUNCTION EspilaVacia(pi1a, :;-_ , a_._=r.
PROCEDURE Apilar(VAR pila:
=
T.__., _:.::: t:-=_=..:.
PROCEDURE Desapilar(VAR pila:
IF__a; --_:-i _:.:-: -:,=_=__^
PROCEDURE Destruirpila(VaR
piia: I!__. ;

IMPLEMENTATION
PROCEDURE CrearpiLaVacia(VAR pila: TFria ;
BEGIN
pila : _- NIL
END; {Crearpilavacia}
500 UNToInps EN TURBo PASCAL

FUNCTION EsPilaVacia (pi1a : fPiIa) : boolean;


BEG]N
EsPilaVacia := (pila = N]L)
END; {nseilavacia}

PROCEDURE Apilar (VAR pila : TPila; inf o: TElement.o) ;


VAR
aux: TPila;
BEG]N
new (aux) ;
aux^.info := info;
aux^.sig := pila;
pila := aux
END; {api-l-ar}

PROCEDURE Desapilar(VAR pila: TPila; VAR info: TElemento);


VAR
aux : TPila;
BEGIN
IF NOT EsPilaVaci (pila) THEN
BEG]N
aux := pila^.sig;
info := pila^.info;
dispose 1piIa) ;
pila := aux;
END
END; {Oesapilar}

PROCEDURE DestruirPila(VAR pila: tPila) ;


VAR
info: TElemento;
BEGIN
(pi1a)
WHILE NOT EsPilaVacia D0
Desapilar(pi1a, info)
3E: {DestruirPila} IIv
ffi-
PT
VA
-TaX l'curx) se ha creado esta unidad es posible apilar diferentes tipos de datos. Es decir
si se h E:emento = integer, se obtendra una unidad Pila que trabaja sobre enF BE
rm. Si - hre fElemento = TEstudiante, incluyendo antes USES Registro (unidad
defuida en el problema 12.5.4),la unidad Pila trabajara sobre un tipo de datos com-
Sor,ucroNns 501

puesto. Lo que se quiere resaltar en este problema, es Ia posibilidad de disear unidades


generales que puedan trabajar sobre diferentes tipos de datos incluyendo en su defini-
cin el uso de otras unidades y cambiando el tipo base. Esta unidad implementa un TAD
PiIa genrico. Se invita al estudiante ha probar la veracidad de estas palabras probando
los ejemplos a los que se hace ref'erencia en el texto.

12.6.8 Guardar los datos de una cola en un fichero


Solucin dei primer apartado:

IINIT Disco;
INTERFACE

L,tlt\ 5 I

N = 30;

TYPE
TTitulo = stri_ng [N] ;
TAutor = TTitulo;
TAnio = string [C] ;
TTiempo = reaf;
TDisco = RECORD
titulo: TTitulo;
autor: TAutor;
anro: 'I'Anro;
ouracl0n: '1"I'rempo;
END;

PROCEDURE Int.roducelnfo '"'-:-J. l:r: lDlsco i


PROCEDURE Muest.ralnfo(reg: -l_s:: ;

PROCEDURE DevuelveAutort':::: -l_sll : -'-t_:. ::-::: :,1_:__:


PROCEDURE DevuelveTitulc:=:: l_-*=,. -.'__: r-_: .: __ -.-_.
PROCEDURE DevuelveAnio (reg: ll_s:' . -,-_r_: i:-_: : l,:_-.__
FUNCTION DevuelveDuracionlreo: --, .-^

IMPLEMENTAT]ON
PROCEDURE IntroduceTitulo (VAR nom: TT::*_:
VAR
c: char;
BEGIN
REPEAT
writ.e (, Introduzca el nombre: , ) ;
UNrn.oBS BN Tunno PASCAL

:eadln (nom) ; l
i;rite ('E} nombre inLroducido es : ' , nom, v
' si es correcto pulse s'); L

-^.t-/-\
!uqutI] \u/ / IND;
-liTIL c IN ['s','S']
?ROC
]DAT
J!Ut

.: l:EDURE IntroduceAnio (VAR anio: TAnio) ;


-l_:. IND;
-. 1r.
:: IIN ?ROC
REPEAT 3EGI
write (' rntroduzca eI anio: ' ) ;
readln (anio) ; IND;
write ('E} anio introducido es: ' , anio,
' si es correcto pulse s'); JROC
readln (c) ; ,-ET
JLUA

UNTIL c IN ['s','S']
IND; {IntroduceAnio} :ITN.

FUNCTION IntroduceTiempo : TTiempo ; !IA]C


fUT
VAR JLga
tn=r.

tiempo: real-; rilTn .

3EGIN
REPEAT PROC:
wriLe ('Introduzca la duracion: ' ) ; 3EGI]
readln (tiempo) ; II

write('E1 tiempo de duracion es: ', t.iempo, B]


' si es correcLo pulse s');
readln(c);
'"TJTIL c IN [' s' , 'S' ] ;
-::troduceTiempo : = tiempo
-rt roduceTiempo ) EI
IND;,
: : :,---:.: Introducelnf o (VAR reg: TDisco) ; ]ND.
-l
Soluc
-, 'Introduzca el nombre del titulo: ') ;
- - r-::l:rulo(reg.titulo) ; -.]NIT
. - .. - -::::oduzca el nombre def autor: ' ) ; INTEI
--,=- :*io (reg.autor) ; USES
-- --::it:zca el anio de grabacion: ') ; TYPE
Sor,ucroNns 503

InrroduceAnio (reg. anio r ;


writeln('Int.roduzca eI tiempo de duracion: ,);
reg.duracion := IntroduceTiempo
END; {Introducelnfo}

PROCEDURE DevuefveAutor(reg: TDisco; VAR nombre: TTiLulo)


BEG]N
nombre := reg.autor
END; {DevuelveAutor}

PROCEDURE DevuelveTiLulo(reg: TDisco; VAR disco: TTitulo) ;


BEGIN
disco := r9.titulo
END; {DevuelveTitulo}

PROCEDURE DevuelveAnio(reg: TDisco; VAR anio: TAnio);


BEGIN
anio := reg.anio
END; {DevuelveAnio}

FUNCTION DevuelveDuracion (reg: TDisco) : TTiempo;


BEGIN
DevuelveDuracion : = reg.duracion
END; {OevuelveDuracion}

PROCEDURE Muestralnfo(reg: TDrsco) ;


BEGIN
WITH reg DO
BEGIN
writeln(,El autor del o_::: :s
writeln(,El titulo del i:s:: :s
writeln(,El anio de graoa:_:::-=
writeln(,La duracion toa_ :: :=
END
END; {Muestralnfo}
END.

Solucin del segundo apartado:

L]NIT Cola;
INTERFACE
USES Disco;
TYPE
504 UNT.nBs BN TuRso PASCAL

lE,enenro = lDlsco;
lE:-_ece = "INodo;
Iiicco = RECORD
Lnlo : TElemento,.
sig: TEnIace;
EINT .

TCO]A = RECORD
cabecera, final: TEnlace;
END;

PROCEDURE CrearColaVacia(VAR Cola: TCoIa) ;


EsColaVacia(cola: TCola) : boolean;
FII1VCTION
PROCEDURE InsertarNodo(VAR cola: TCoIa; info: TElemento) ;
PROCEDURE ExtraerNodo (VAR cola:TCola; VAR info: TElemento)
PROCEDURE Dest.ruirCola (VAR cola: TCola) ;

IMPLEMENTATION
PROCEDURE CrearColaVacia(VAR Cola: TCola) ;
BEGIN
cola.cabecera := NIL;
cola.final := NIL
END; {CrearColaVacia}

FUNCTION EsColaVacia(cola: TCola) : boolean;


BEGIN
EsColaVacia := (cola.cabecera = NIL) AND (cola.final = NIL)
END; {usColavacia}

PROCEDURE InsertarElemento(VAR lista: TEnface; info: TE1emento) ;


VAR
aux: TEnlace; a.
__: - TIT
__Jfl\

new (aux) ; P]
1*x .l-nlo := info;
^..--a l --r^
VJ

=-::^.sig := lista;
- =:- := aUX B]
::'-- rFl
^-^-f ^l

.:,::,-,-: _._.::*,arNodo(VAR cola: TCola; info: TElemento) ;


::r-.

-: :.-:---.'=:- :OIa) THEN


:: i -'
Sor,ucroNns
505

InsertarElemento ( cola . cabecera,


info);
cola. final : = cofa. cabecera;
END
ELSE
BEGIN
InsertarElemento (co1a. final^.
sio. infnl
cola. final : = cola. final^ . sig;
END
END; {tnsertarlodo}

PR..EDURE ExtraerNodo(vAR
cora: TCola; vAR info: TElemento);
aux: TEnIace;
BEGIN
IF NOT EsColaVacia(cola) THEN
i
t
BEGIN
I
info := cola.cabecera^.infc;
IF cola.cabecera = cola.firal THEN {Es el ltimo nodo}
BEGIN
dispose (cola. cabecera r;
cola.cabecera := NIL;
cola.final := NIL;
END
ELSE
BEGIN
dux : = CO_La. Ca.beCe:i .

cola.cabecera := cc-a. :,::t::a^.sio;


dispose (aux) ;
END
END
END; iExtraerNodo)

PROCEDURE DestruirCola(VAR coia: ll:_a


VAR
aux: TEnlace;
DFTNI
J!ga1!

cola.final := NIL;
WHILE NOT EsColaVacia(cola) DO
BEGIN
aux:= cola.cabecera;
cola . cabecera : = cola . cabecera^ .s iq ;
dispose (aux) ;
506 UNroIoBs EN TURBo PIscIr,

END;
END; {DestrurrCola}
END.

Solucin del tercer apartado. En este caso hemos supuesto que cuando se abre un ficher
para escritura se sobreescribe todo su contenido anterior. Esta ltima unidad se pue .r
ver como un recubrimiento de las funciones y procedimientos de Turbo Pascal.

;1i-IT Binario;

INTERFACE
USES Disco;
TYPE
TElem = TDisco;
TFichero = FILE OF TEIem;

PROCEDURE AbrirFicherolectura(nombre: string; VAR f : TFicherc:


VAR error: boolean);
PROCEDURE AbrirFicheroEscritura (nombre : string ;
f: TFichero) ;
VAR
PROCEDURE CerrarFichero(VAR f : TFichero) ;
PROCEDURE LeerFichero(VAR f: TFichero; VAR elem: TElem);
PROCEDURE EscribirFichero(VAR f : TFichero; elem: TElem) ;

IMPLEMENTATION
FUNCTI0N ExisteFichero (VAR f: TFichero) : boolean;
{ere = el nombre fisico del fichero ha sido asignado a fi
{lost = TRUE si el fichero ya existe, FALSE en caso contrario}
VAR
aux: boolean;
D E TIT
J!glr!

{$r-}
:e:jeL \Il ;

-. _+ )

-a iOResult = 0) THEN P
:: a-l; {
-- --^ !\
{
: -. -=: -chero : = TRUE B
:
:-:: E]

EI
:.-- t - . .-.-
--
Sor,ucroNns -507

PROCEDURE AbrirFicherolectura(nombre: string; VAR f ; TFichero;


VAR error: boolean);
BEG]N
assign(f, nombre);
IF ExisteFichero(f) THEN
BEGIN
re5eL\I/;
error := FALSE;
END
ELSE
error : = TRUE
END; {anrirficherolectura}

PROCEDURE AbrirFicheroEscritura(nombre: string; VAR f : TFichero) ;


BEGIN
assign(f, nombre);
rewrite f ) (

END; {abrirficheroEscritura}

PROCEDURE LeerFichero(VAR f: TFichero; VAR elem: TElem);


{ere = el fichero ha sido abierto para lect.ura y no es vacio}
{fost = devuel-ve el elemento que ha leido del fichero en e}em}
BEGIN
read(f, elem)
END; {LeerFichero}

PROCEDURE EscribirFichero(VAR f: TFichero; elem: TEIem) ;

{lre = el fichero ha sido ablerto para escritura}


{lost = ha grabado un nuevo regl-stro en eI fiche::
se
BEGIN
write (f, elem)
END; {EscribirFichero}

PROCEDURE CerrarFichero (VAR f: TF-c:=::


iere = el fichero debe estar a.-.r::-
{eost = el fichero esra::rr=j:
BEGIN
close ( f )
END; {CerrarFichero}
END.
UNrnroBs nN Tunno Pasclr,

*i luin del cuarto apartado:

.: , l:_rfi Programa;
-::: -rsco, CoIa, Binafio;
,,t,s:
llOM = 'fichero.dat';
_-_1

: : TCola;
E
=-:m: TDisco;
E
^L---

^h^t^.
END.
:::IN {Programa Principati
CrearColaVacia (c) ;
REPEAT
writeln ('InLroduzca l-a informacion por favor: ' ) ;
Introducelnfo (elem) ;
InsertarNodo (c, elem) ;
writeln (' Para parar pulse s' ) ;
readln (p) ;
LINTIL p IN ['s' ,'S'f ;
AbrirFicheroEscritura (NOM, fich) ;
I{HILE NOT EsColaVacia(c) D0
BEGIN
ExtraerNodo (c, elem) ;
EscribirFichero (fich, elem) ;

END;
CerrarFichero ( fich)
END. {Programa Principal}

Si se desea comprobar que los datos se ha guardado conectamente, se puede utilizar -


sisuiente cdigo.

.:llFAM Comprobar;
.--::j Disco, Binario;
.,-: -
= ' fichero. dat' ;
- --: l)isco;
- ' -: ichero;
., :::iean;
::.- . -r:a:a PrinCipal)
,r ., =__,t IHEN
Sor,ucroNBs 509

BEGIN
I{HILE NOT eof (f ich) D0
BEGIN
LeerFichero (fich, elem) ;
Muescralnfo (e1em) ;
END;
CerrarFichero ( fich)
END
ELSE
writeln('Se ha produci-do un error,)
END. {Programa Principal}
Anexo I
Normas de estilo

un programa adems de ser correcto cle acuercro a las especificaciones,


debe ser
legible y fcilmente comprensible. para conseguir
estos objetivos, se deben tener en
cuentalos siguientes aspectos relevantes:

o comentarios: el programa ha de estar tiocumentado con comentarios


encerados
entre "{rr y "}r' (han sido utilizaci.s ma'oritariamente
en este libro) o entre ,,(x,,y
"* )". Los comentarios sirven prrr:

- Dar descripciones de funcirn.lmlenril: de subprogramas,


bloques, decisio-
nes, etc.
Describir las precondicione::,-rtntlr,-iones de entrada.
Describir las postcondicione.: .-L ld1.-iones de salida.

Estructuracin del cdigo fuente: i> -\-:r.ial clotar


cie clariclad a la escritura del
cdigo fuente. Para ello se seguirr, .i.: ,r,,,irl.r 7e e.si1r:

Uso de retornos de lnea; ssls rma instnccin por lnea.


Longitud de una fnea; no debe exceder el area visible de
edicin.
uso de tabuladores de manera que se refleje la estncuracin dr progmma
Eleccin de identificadores: ros identificadores deben describi -objetivo,,
el del
elemento Que representan. Siempre que haya dudas de
la utilidad o necesidad de
un elemento, se aadir un comentario descriptiro al final
de la lnea donde se
introduzca o declare. Debe existir un equilibrio en la longitud
del identificador,
sin que sea excesivamente largo ni excesivamente corto. para
los subprogramas se
escogern identif,cadores que en el caso de las funciones
describan lo que devuel_
ven y en el caso de los procedimientos la accin que rearizan. por
ejemplo una
funcin podra llamarse sarario y un procedimiento carcurasarario.
uso de los tabuladores: para elprogramn principat se seguir
el siguiente for-
mato con identacin:

597
-
598 ANnxo I

PROGRAM NombrePrograma ;
Propsito:
Entrada:
Salida:

USES {neclaracin de unidades}


Unidades;

CONST {nefiniciOn de constantes}


C9NSTANTE1 = #VALORI;

VAR iDeclaracin de variablesJ


l

variablel : tipol;

PROCEDURE NombreProcedimiento ( IistaParametros) ;


BEGIN {Nombrelrocedimiento }

END ; {Nombrelrocedimiento}
FI.IITCTION NombreFuncion ( tistaParametros) : tipoFuncion;
BEGIN iuombreFuncion)

END; {NombreFuncion}

BEGIN {Programa principali


Instruccin1;
Instruccin2 ;

InstruccinN
END. {Programa principa}}

Para las instrucciones estructuradas se seguir el siguiente fbrmato:

Instruccin IF. Se elegir entre este formato, que escribe BEGIN en la siguiente
:.: -11 -F y a su misma altura,

]F Condicon THEN

"=GIN
fnstruccin1;
...i
I-=:mccinN
Axrxo I s99

END
ELSE
BEGIN
InstruccinA;

InstruccinZ
END; {elsu}

o este formato, que pone BEGIN en la misma lnea que IF:

IF Condicion THEN BEGIN


' Instruccin1;

InstruccinN
END
ELSE IF Condicin2 THEN BEGIN
fnstruccinA;
...;
InstruccinZ
END
ELSE BEG]N
Instruccina;
:'
lnscrucclonz,.
END; {rlsr}

Instruccin CASE. Se seguir el siguiente esquema:

CASE expresin OF
valor1: BEGIN
Instruccin1;
...;
TnstruccinN
END; {Valort_ }
valor2: InsLruccioni;

valorN: BEGIN
InstruccinA;
..,;
InstruccinZ
END; {Valorn}
600 Annxo I

ELSE
InstruccionElse;
END; {casn}

Instruccin wHrLE. Es similar al tp. Se elegir una de las dos formas de escri-
birlo, poniendo BEGIN en la lnea siguiente,

WHILE Condicion DO

BEGIN
Instruccin1;
..,;
InstruccinN
END; {wutrr}

o en la misma lnea:

VHILE CONdiCiON DO BEGIN


Instruccin1;
t..

InstruccinN
END; {wHrlu}

Istmccin REPEAT.

REPEAT
Instruccin1 ,'

...;
Inst.ruccinN
UNTIL Condicin;

Instruccin FoR. Si el bucle posee un bloque de instrucciones se puede elegir


poner BEGIN en la lnea siguiente al FOR,

FOR indice : = explnic TO expFinal DO

BEGIN
InsLruccin1;

-rstruccinN
.-^- I
=. - -'Jf .l

['=,.-.
ANrxo I 6ul

o en la misma lnea:

FOR indice : = explnic DOI,^]NTO expFinal D0 BEGIN


Instruccin1;
.,.;
InstruccinN
END; {ron}

Normas tipogrficas: se trata de seguir unas normas para que todos los progra-
madores las sigan y se facilite la lectura )' comprensin del cdigo. Algunas reglas
son:

- Los identificadores de constontes l1evan todas las letras en mayscula. Por


ejemplo: MMINT. PI. VALOR-I:ri--:- -. }'IINIMO, . . . .
- Los identificadores de y,ctrictbles estn escritos en minsculas (i, opcion,
suma, alumno, ...). si el identihcador es compuesto, la segunda palabra
cOmienza con mayscula { sa_j:. t:a-. sumaParcial, primeraApuesta,
punterolnicial, ... ).
- Las palabras clave o resenttLTcts en mar,sculas (eUGIt't, END, IF, WHILE.
DE'DE'AT
rrlr
larr, ... \
/.

- Los identificadores predefir-ridr: .e escriben en minscula (writeIn, read,


char, ... ).

- Los identificadores de los tito: ilctuitlo.\ por el programador comienzan con


T seguido de la primera ietra en nla\ :cLrla (TLetra, TDia, TColor, ' ' ' )'
- Los subprogromas comienzn !t)n ltta\'lscula y el resto de la palabra va
en minscula. Si el identicador e! compuesto, Ia primera letra de la se-
gunda palabra tambin colnienza crrn nla)'scula. Algunos ejemplos sonl
Calcular, Sumar, SumaC.rl -=- =. - l::a. ....
- Los identificadores de latuticlttl sigLren 1a misma regla que los iCntri::-
dores de subprogramas.

- Losidentiflcadores(losnombresI.ll-..ficlreros.fuente.segr.. l.,:-,i;'r-.,'tll3s
normas que los identificadores en P.ca1 l debern te n.: . :-- il-.:\illltr ocho
Caracteres, SegUidOS de Un pUntt \ rJne e\tenlirln i.- :l.i-> .:,r,1> P.\S)para
sercompatibles con el sistema operri-\''- '\1S-DOS -' :l-'':'-' -----:i'pas' o
como ejemplo.Pas.

Вам также может понравиться