Escolar Documentos
Profissional Documentos
Cultura Documentos
'SBODJTDP+BWJFS/PHVFSB0UFSP
%BOJFM3JFSB5FSSÏO
Diseño de la colección: Editorial UOC
Primera edición digital en lengua castellana: noviembre 2013
Este capítulo procede de la obra: Escaneando la informática (Joan Arnedo Moreno, Jordi Cabot Sagrera,
Isabel Guitart Hormigo, Francisco Javier Noguera Otero, Rafael Macau Nadal, Maria Jesús Marco Galindo,
Josep Maria Marco Simó, Joan Antoni Pastor Collado, Josep Prieto Blázquez, Daniel Riera Terrén, Jordi
Tubella Murgadas, José Ramón Rodríguez Bermúdez, M. Elena Rodríguez González, Ramon Segret Sala)
publicada en 2010, con ISBN: 978-84-9788-110-4
Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada, reproducida,
almacenada o transmitida de ninguna forma, ni por ningún medio, sea éste eléctrico, químico, mecánico, óptico,
grabación, fotocopia, o cualquier otro, sin la previa autorización escrita de los titulares del copyright.
Autores
Índice
Capítulo IV
Programación
Francisco Javier Noguera Otero y Daniel Riera Terrén
1. Introducción
Aunque quizás no tengamos una idea clara de a qué nos referimos cuando
hablamos de programar, sin ser conscientes de ello, a lo largo de nuestras vidas
lo hacemos bastante a menudo y de maneras diversas. Así, programamos el
vídeo para que se active a una hora determinada y grabe, programamos la hora
a la que tiene que sonar el despertador, e incluso, hacemos viajes programados.
¿Pero, realmente, tiene todo eso alguna relación con los programas de ordena-
dor?
Al contratar un viaje programado nos ofrecen la lista de los lugares adonde
iremos, qué día iremos, qué visitaremos y qué actividades realizaremos. Así, el
programa, en este caso, es una especificación detallada previa del acontecimien-
to. Aunque eso ya nos va dando ciertas pistas de lo que se considera un progra-
ma en el mundo de la informática, más cercanos aún son los otros dos ejem-
plos. Cuando programamos el despertador o el vídeo, le damos una orden –o un
conjunto de órdenes– que en un cierto momento del futuro ejecutará automá-
ticamente.
Reuniendo estas ideas, podemos acercarnos a la idea de programa, ahora ya
desde el punto de vista informático. Diremos, hoy por hoy, que un programa es
un conjunto de órdenes ordenadas que la máquina ejecutará para llevar a cabo
una tarea determinada.
Si buscamos la definición en el diccionario, vemos que es bastante parecida
a lo que acabamos de decir: “Conjunto unitario de instrucciones que permite a
un ordenador realizar diversas funciones, como el tratamiento de textos, el dise-
ño de gráficos, la resolución de problemas matemáticos, el tratamiento de ban-
cos de datos, etc.”. Así, las órdenes que damos al ordenador se llaman instruc-
ciones y la ejecución de éstas hace que el ordenador cumpla ciertos objetivos.
© Editorial UOC 103 Programación
3. Historia
A finales de 1976, los tripulantes de un flamante caza F16 de las fuerzas aére-
as de los Estados Unidos vieron sorprendidos que, en determinados momentos,
el avión giraba 180 grados y quedaba cabeza abajo. Después de analizar cuál
podía ser el problema, detectaron que provenía de un signo menos mal coloca-
do dentro del programa de navegación del aparato. Este error hacía que el apa-
rato girara cada vez que cruzaba el ecuador. Menos mal que estas primeras prue-
bas las hicieron sobre simulador, ya que si no el susto, sin duda, hubiera sido
mucho mayor.
Es curioso que un programa de algunos miles de líneas (y por lo tanto, de
varios millones de caracteres) pueda depender de un solo signo, pero la progra-
mación no es un ejercicio simple y cualquier programa, por sencillo que sea, es
susceptible de tener errores. Precisamente para evitar los errores y facilitar la
programación, los lenguajes y los paradigmas de programación han ido evolu-
cionando continuamente. Veamos, pues, cómo ha sido esta evolución.
Las diferencias entre los primeros programas y lenguajes, llamados de prime-
ra generación, y los que se utilizan actualmente es muy grande, no sólo por el
cambio de tipos de problemas que hay que resolver sino por las estrategias
seguidas para la simplificación, el diseño, la división en subproblemas, etc.
© Editorial UOC 104 Escaneando la Informática
Hasta aquel momento, para ejecutar un programa entero, lo que se hacía era
ir cargando una tarjeta por instrucción. Así, hasta que no se había acabado la
ejecución de la actual, no se retiraba y se introducía la siguiente.
Las siglas ENIAC significan Electronic Numerical Integrator And Computer. Los
primero programas que se utilizaron en el ENIAC estaban relacionados con el
diseño de la bomba de hidrógeno. Los aclamados como primeros ordenadores,
como por ejemplo el ENIAC, no tenían algunas de las características que hoy
día se consideran indispensables en un ordenador. Eran máquinas bastante rígi-
das. En cambio, en la Universidad de Manchester, se crearon una serie de
máquinas que incluían tanto la posibilidad de almacenar programas en la
memoria como de introducir el programa mediante un teclado en vez de recon-
figurar circuitos (tarea que podía durar días).
© Editorial UOC 107 Programación
1. Un acumulador es un sitio de la memoria del ordenador que se utiliza de manera auxiliar para
hacer operaciones intermedias aparte de la memoria principal (un tubo Williams de 32x32).
© Editorial UOC 108 Escaneando la Informática
El primer programa fue escrito por el propio Tom Kilburn y fue ejecutado el
día 21 de junio de 1948. Este programa calculaba el factor máximo de un núme-
ro. En la imagen siguiente podemos ver el “diseño” a mano del primer progra-
ma.
3.4. Generaciones
10110000 01100001 Esta línea contiene una instrucción que mueve un valor (61 en hexadecimal)
en el registro2 del procesador al. Como se puede ver, no es muy comprensi-
ble desde el punto de vista humano (de hecho, es realmente misteriosa).
Para evitar tener que utilizar el alfabeto de la máquina (ceros “0” y unos “1”),
que está muy lejos de lo que entendemos nosotros, se crearon los llamados len-
© Editorial UOC 111 Programación
mov al, 061h Esta línea contiene la instrucción mov, que mueve un byte (61 en hexadecimal) en el
registro al. Esta manera de escribir código es más comprensible que la que hemos
visto anteriormente.
MOV DS, AX
MOV DX, OFFSET MSG
MOV AH, 09H ; DOS: output ASCII$ string
INT 21H
MOV AX, 4C00H
INT 21H
END Start
if (x>0) factorial(x) Esta línea comprueba si x es mayor que cero (0). En caso de que así sea
llama a una parte del programa que calcula el factorial de x.
Así, a partir del código escrito en un lenguaje de este grupo, se utiliza una
herramienta (de hecho hay diferentes maneras de hacerlo) que “traduce” el
código a código máquina. Normalmente se hace mediante un compilador, aun-
que puede utilizarse un intérprete o incluso una máquina virtual (conceptos
que veremos más adelante).
La mayor parte de los lenguajes que se utilizan hoy día para la programación
de aplicaciones son de tercera generación (por ej. C, C++ y Java).
© Editorial UOC 113 Programación
Esta línea busca en una base de datos todos los registros que tienen
SELECT * FROM USUARIS
como campo de nombre BOB. Se puede ver que es casi como el len-
WHERE NAME=”BOB”
guaje natural (en este caso, el inglés).
hermano(X,Y):- madreOpadre(X,Z), Esta línea dice que X e Y son hermanos si comparten padre o
madreOpadre(Y,Z). madre.
4. Algorítmica
Hasta ahora hemos revisado un poco la evolución de los lenguajes hasta lle-
gar a los que utilizamos hoy día. Pero exactamente, ¿cómo son estos lenguajes?
¿Qué tipo de problemas nos permiten resolver y de qué manera? Pronto vere-
mos algunas de las características comunes a todos ellos.
© Editorial UOC 115 Programación
Acabamos de definir los pasos que hay que seguir para, a partir de unos
ingredientes y unas herramientas que tenemos en casa, llegar a hacer una torti-
lla de patatas para dos personas. Estos pasos definirán el algoritmo. Cuando
queremos resolver un problema con el ordenador, la mecánica es parecida: tene-
mos un estado inicial y queremos hacer alguna tarea. Tenemos que preparar un
algoritmo, traducirlo a un lenguaje de programación (programar) y ejecutarlo
sobre el ordenador. Así, si es correcto, el ordenador cumplirá la tarea definida
inicialmente.
Para escribir un algoritmo, sin darnos cuenta, utilizamos tres estructuras con
las que se puede resolver cualquier problema. Así, un buen programador, ante
un problema, tiene que ser capaz, inmediatamente, de ver cuáles de estas estruc-
turas combinará para resolverlo. Veamos cuáles son.
© Editorial UOC 117 Programación
4.1.1. Estructuras
En este caso, la orden “corregir examen” se repetirá tantas veces como exá-
menes tenga el profesor. Si tiene treinta estudiantes, estas dos líneas equivalen
a escribir treinta veces la orden “corregir examen”.
En el algoritmo de la tortilla de patatas, vemos una estructura iterativa en el
paso 2, ya que se van repitiendo dos acciones, mientras quedan patatas.
© Editorial UOC 118 Escaneando la Informática
4.1.2. Datos
Hasta ahora hemos visto que para resolver un problema se tiene que pensar
un algoritmo y –en el caso de que se tenga que ejecutar en un ordenador–, pos-
teriormente, traducirlo a un lenguaje de programación. Ahora bien, recordando
lo que nos decía Wirth, los programas no son simplemente algoritmos, sino una
combinación de éstos con estructuras de datos. Pero ¿qué son los datos?
Consideramos que el estado está definido por la situación de los elementos
con los que trabaja el algoritmo en un instante concreto. Ya hemos dicho que
un algoritmo (o un programa) nos lleva de un estado inicial a un estado final.
Así, antes de aplicar el algoritmo de la tortilla de patatas, el estado es: estamos
en la cocina de casa, tenemos huevos, aceite, patatas, etc. En cambio, una vez
hemos aplicado el algoritmo, tenemos una tortilla, y algunas cosas que tirar a la
basura. Es fácil ver que cada paso del algoritmo que vamos ejecutando produce
un cambio de estado.
Cuando programamos, estos estados se tienen que guardar de alguna mane-
ra, ya que cada paso del algoritmo tiene sentido si se aplica sobre un/os cierto/s
elemento/s, y en un cierto estado. Un ejemplo claro es, por ejemplo, el segun-
do paso del algoritmo de la tortilla de patatas: pelar las patatas. Esto sólo tiene
sentido si las patatas todavía no están peladas. En este caso, consideramos que
tenemos un dato (patata) que está en un estado (pelada). Otros posibles estados
para el dato “patata” serían “sin pelar”, “cortada”, etc.
Estos datos, cuando hablamos de programas, quedan guardados en la memo-
ria del ordenador y determinan el estado de ejecución del programa en cada ins-
tante.
Recordemos así lo que decía Wirth: “Algoritmos + Estructuras de datos =
Programas”. Efectivamente, cualquier programa contendrá un conjunto de ins-
trucciones ordenadas (un algoritmo) y un conjunto de datos sobre los cuales se
aplican las instrucciones.
© Editorial UOC 119 Programación
cambia_neumático:
quita neumático_gastado
pon neumático_nuevo
comprueba neumático
fin cambia_neumático
ahora puedo utilizar el bloque a lo largo del algoritmo sin volver a escribir
cada orden:
De esta manera, vemos que será más legible el código, ya que queda claro
qué hace sin tener que leer todas las líneas. Si ya sé que uno de estos bloques
funciona correctamente, no hace falta que lo revise si después mi programa
tiene errores. Eso facilita también la fase de búsqueda de errores, dado que es
más fácil ir aislando los errores que se produzcan.
© Editorial UOC 120 Escaneando la Informática
Cada línea de la tabla anterior presenta los resultados para un algoritmo dife-
rente. Si nos fijamos, por ejemplo, en la última línea, vemos que dado este algo-
ritmo, si se tienen que ordenar 10 tarjetas (n=10), hay que hacer 1.000 movi-
mientos para conseguirlo.
De esta manera, los tres primeros (con complejidades lg n, n y 50·n) se con-
sideran algoritmos aceptables para solucionar el problema. Los otros no son lo
bastante eficientes.
El Clay Mathematics Institute ofrece un millón de dólares a las personas que
resuelvan una serie de problemas matemáticos altamente complejos. Uno de
ellos es ¿P=NP?. El último que se solucionó fue la demostración del último
Teorema de Fermat.
Yendo un poco más allá, también se clasifican los problemas según la exis-
tencia o no (hasta ahora) de algoritmos que los resuelvan en tiempo polinomial
(problemas P) o no (problemas NP). Así, un problema P es el que tiene un algo-
ritmo conocido con complejidad polinómica que lo resuelve. Una de las gran-
des incógnitas a que actualmente se enfrenta la comunidad científica es, como
hemos comentado, si todos los problemas son P. Eso se resume normalmente
con la pregunta ¿P=NP?.
4.2.2. Recursividad
la recursividad, pero se tiene que tener en cuenta que ésta tiene que acabar (si
no el algoritmo no sería finito). Para hacerlo se añade una condición final (en
este caso, cuando N es 0).
5.1. La compilación
5.2. La interpretación
6. Paradigmas de programación
gramación, utilizada con los primeros lenguajes, hace que el programa sea difí-
cil de entender, corregir o modificar para añadir una nueva funcionalidad. Otro
problema es la dificultad que tiene el programador en reaprovechar el código.
Algunos ejemplos de este tipo de lenguajes son: BASIC, FORTRAN y algunos
lenguajes de scripting.
Los paradigmas que veremos a partir de ahora se consideran estructurados, ya
que la programación desestructurada plantea algunos problemas.
7. Lenguajes de programación
7.1.1. BASIC
En los primeros años en que se utilizó, las líneas del programa tenían que
estar numeradas. Esta numeración normalmente se hacía de diez en diez (10,
© Editorial UOC 129 Programación
20, 30, etc.) dejando así un espacio entre instrucción e instrucción por si se tení-
an que añadir líneas posteriormente. El lenguaje de programación BASIC
(Beginner’s All-purpose Symbolic Instruction Code) fue diseñado e implementado
en el Dartmouth College (EE.UU.) para facilitar a los estudiantes de letras el
acceso al ordenador. Por extensión, cualquier persona sin conocimientos cien-
tíficos podía utilizar un sencillo juego de instrucciones para escribir un progra-
ma.
El BASIC se hizo popular a partir de la aparición de los ordenadores domés-
ticos que, a diferencia de los grandes computadores que había en las universi-
dades y en las industrias, disponían de muy poca memoria y espacio de disco.
Requería menos recursos para ejecutarse que el resto de los lenguajes de la
época, lo que lo hacía ideal para este tipo de ordenadores. Esta necesidad míni-
ma de recursos y el hecho de que fuera sencillo de aprender hizo que la mayo-
ría de los ordenadores domésticos llevaran incorporado un intérprete de BASIC.
Precisamente fue en esta época y gracias a BASIC, cuando se fundó la com-
pañía Microsoft. Bill Gates y sus socios desarrollaron un intérprete de BASIC
para el primer ordenador doméstico, el Altaif 8800. En 1975 pusieron en venta
Altair BASIC y posteriormente desarrollaron nuevas versiones de Microsoft
Basic para otras plataformas (Apple, IBM, etc.). Treinta años después es la mayor
compañía de software del mundo.
El código del “Hello World” en BASIC es el siguiente:
7.1.2. C
El nuevo lenguaje era bastante flexible para permitir combinar las programacio-
nes en bajo y alto nivel. Mediante un compilador específico para cada arquitec-
tura (que traducía de C al ensamblador de la máquina) podían obtener progra-
mas ejecutables para diferentes ordenadores sin tener que cambiar el código
fuente. En el año 1973 el código de UNIX se rescribió utilizando C. De esta
manera, fue el primer sistema operativo no escrito en ensamblador. Eso aceleró
y simplificó la programación para este sistema, lo cual se tradujo en un impor-
tante avance en el desarrollo.
El hecho de que, a pesar de ser propiamente un lenguaje de alto nivel, ofrez-
ca la posibilidad de codificar también en bajo nivel para poder acceder a todos
los recursos del ordenador, hace que C sea un lenguaje peligroso para princi-
piantes. Aun así, su potencia lo ha convertido en uno de los más utilizados.
La sintaxis de C se muy permisiva. Tanto es así que incluso hay concursos de
“programación ofuscada”, es decir, concursos en que se valora que el código
fuente no pueda leerse o incluso que forme bonitos dibujos de caracteres (véase
un ejemplo en el anexo 2 de este capítulo).
El código del “Hello World” en C es el siguiente:
#include <stdio.h>
int main (void)
{
printf ("Hello world!\n");
return 0;
}
7.1.3. C++
#include <iostream>
using namespace std;
class HelloWorld
{
public: HelloWorld () {}
~HelloWorld () {}
void sayHello { cout << "Hello World!" << endl;}
};
int main (void)
{
HelloWorld hw;
hw.sayHello();
return 0;
}
7.1.4. Java
JAVA fue desarrollado por Sun Microsystems en los años noventa. En argot
norteamericano JAVA quiere decir “café” y la historia cuenta que el equipo que
desarrollaba este lenguaje escogió este nombre en torno a una taza de café. Por
eso, su logotipo es una taza de café y los objetos que utiliza para encapsular
información (agrupar en bloques) se llaman “Java Beans” (granos de café). Aún
podemos encontrar otra referencia al café en su código, ya que si abrimos cual-
quier clase compilada de JAVA con un editor hexadecimal, veremos que todas
las clases empiezan con los cuatro primeros bytes hexadecimales CA FE BA BE.
© Editorial UOC 132 Escaneando la Informática
JAVA es un lenguaje orientado a objetos que ofrece, en la misma base del len-
guaje, apoyo para la utilización de redes y la ejecución remota de código (fue
creado durante el boom de Internet). Sintácticamente, JAVA es muy parecido a
C y C++, pero mucho más simple, ya que tiene reglas menos permisivas. Eso
implica limitar las diferentes maneras de hacer lo mismo (cosa que da lugar a
ambigüedades), no permitir ciertas estructuras que puedan generar errores, etc.
Un programa escrito con JAVA puede ejecutarse en cualquier ordenador y sis-
tema operativo sin tener que modificar ninguna línea de código y sin volver a
compilar. La idea “codifica una vez, ejecuta en cualquier lugar” junto con el
hecho de proporcionar un entorno seguro a la hora de ejecutar código han
hecho que sea uno de los lenguajes más utilizados actualmente.
La Máquina Virtual Java (Java Virtual Machine, JVM) es una capa que se
podrá poner por encima de cualquier máquina para que así pueda ejecutarse el
mismo código, independientemente de ésta. Por eso, al compilar, se genera
código intermedio, interpretable por la JVM. Las mayores críticas a JAVA provie-
nen de su velocidad de ejecución y la cantidad de memoria que utiliza para la
ejecución. Es un lenguaje que se compila y genera un código intermedio que
después tiene que ser interpretado por la Máquina Virtual Java. Por eso, la eje-
cución de los programas de las primeras versiones de JAVA era mucho más lenta
que la de otros similares hechos en C o C++. Actualmente la diferencia ya no es
tan grande.
El código del “Hello World” en JAVA es el siguiente:
7.1.5. PHP
8. Software libre
La idea del software libre surgió a partir de un problema que tuvo Richard
Stallman con una impresora. El software que la controlaba no se podía modifi-
car y él quería mejorarlo para evitar unos problemas que se le planteaban. Así
el concepto “software libre” nace en 1984 cuando Stallman inicia el proyecto
GNU y crea la Free software Foundation (FSF). Este proyecto tiene por objetivo
crear un sistema operativo totalmente libre. Antes de esta fecha también había
muchas aplicaciones que se distribuían con el código fuente o de forma gratui-
ta, pero no es hasta ese momento cuando se crean unas normas y emerge la
conciencia identitaria y de pertenencia. GNU es una palabra que se define recur-
sivamente. Quiere decir: “GNU’s Not UNIX”.
Un software se considera libre si garantiza las cuatro libertades siguientes:
• La libertad de ejecutar el programa para cualquier propósito.
• La libertad de estudiar cómo trabaja el programa y de adaptarlo a las nece-
sidades propias. El acceso al código fuente es una condición previa.
© Editorial UOC 134 Escaneando la Informática
Así pues, el software libre se puede redistribuir y modificar, bien de forma gra-
tuita o cobrando por esta distribución.
Uno de los proyectos de software libre más conocidos es, sin duda, el núcleo
(kernel) Linux, programado por Linus Torvals en el año 1991. GNU/Linux es la
implementación abierta del sistema operativo Unix para computadores perso-
nales, con Linux de núcleo. El proyecto GNU/Linux lo inició Richard M.
Stallman en el año 1984 con el objetivo de crear un clon del sistema operativo
Unix, pero garantizando las cuatro libertades mencionadas más arriba.
Los proyectos de código abierto y la creación de software libre se caracterizan
por que en su elaboración participan decenas a miles de personas de todo el
mundo. Un grupo reducido de personas toma las decisiones de diseño y de pro-
gramación mientras que un gran número de programadores detectan y corrigen
errores y añaden nueva funcionalidad.
9. El mundo laboral
10. Apéndice
Bibliografía
Aho, A.; Hopcroft, John E.; Ullmann, Jeffrey D. (1988) Data Structures
and Algorithms, Addison-Wesley (Edició espanyola: Estructuras de Datos y
Algoritmos, 1988)
6LOHKDJXVWDGRHVWHFDStWXORSXHGHDGTXLULUHOUHVWRGHODREUD
HQODVSODWDIRUPDVKDELWXDOHVJRRJOH3OD\&DVDGHO/LEUR&DVDOLQL
/LEHUGUDFH/LEUR'DZVRQHUDHQXQIXWXURSUy[LPR$PD]RQHWF