Sei sulla pagina 1di 55

Introducción a la Ingeniería del

Computador
EE-150

Arturo Vilca Román Ciclo 2019-1


avilca@uni.edu.pe Clase 12
9
Lenguajes de
programación
9.2
Foundations of Computer Science Cengage Learning
Objetivos
Después de estudiar este capítulo, el estudiante debe ser capaz de:
 Describir la evolución de los lenguajes de programación desde el lenguaje de
máquina hasta el lenguaje de alto nivel.

 Comprender cómo un programa en un lenguaje de alto nivel se traduce al


lenguaje de máquina.

 Distinguir entre cuatro paradigmas del lenguaje informático.

 Comprender el paradigma de procedimiento y la interacción entre una


unidad de programa y los elementos de datos en el paradigma.

 Comprender el paradigma orientado a objetos y la interacción entre una


unidad de programa y objetos en este paradigma.

 Definir paradigma funcional y comprender sus aplicaciones.

 Definir un paradigma de declaración y entender sus aplicaciones.

 Definir conceptos comunes en lenguajes de procedimiento y orientados a


objetos.
9.3
9-1 EVOLUCIÓN

Para escribir un programa para una computadora,


debemos usar un lenguaje de computadora. Un lenguaje
de computadora es un conjunto de palabras predefinidas
que se combinan en un programa de acuerdo con reglas
predefinidas (sintaxis). Con los años, los lenguajes
informáticos han evolucionado desde los lenguajes de
máquina hasta los lenguajes de alto nivel.

9.4
Lenguajes de maquina
En los primeros días de las computadoras, los únicos
lenguajes de programación disponibles eran los lenguajes de
máquina. Cada computadora tenía su propio lenguaje de
máquina, que estaba hecho de flujos de 0 y 1. En el Capítulo
5 mostramos que en una computadora hipotética primitiva,
necesitamos usar once líneas de código para leer dos enteros,
sumarlos e imprimir el resultado. Estas líneas de código,
cuando se escriben en lenguaje de máquina, forman once
líneas de código binario, cada una de 16 bits, como se
muestra en la Tabla 9.1.
i
El único lenguaje entendido por una computadora es
el lenguaje de máquina.
9.5
9.6
Lenguajes ensambladores
La siguiente evolución en la programación vino con la idea
de reemplazar el código binario para instrucciones y
direcciones con símbolos o mnemónicos. Debido a que
usaban símbolos, estos lenguajes se conocían primero como
lenguajes simbólicos. El conjunto de estos lenguajes
mnemónicos fue referido más tarde como lenguajes
ensambladores. El lenguaje ensamblador de nuestra
computadora hipotética para reemplazar el lenguaje de
máquina en la Tabla 9.2 se muestra en el Programa 9.1.

i
El único lenguaje entendido por una computadora es
el lenguaje de máquina.
9.7
9.8
Lenguajes de alto nivel
Aunque los lenguajes de ensamblaje mejoraron en gran
medida la eficiencia de la programación, aún requerían que
los programadores se concentraran en el hardware que
estaban usando. Trabajar con lenguajes simbólicos también
fue muy tedioso, porque cada instrucción de máquina tenía
que ser codificada individualmente. El deseo de mejorar la
eficiencia del programador y cambiar el enfoque de la
computadora al problema que se está resolviendo llevó al
desarrollo de lenguajes de alto nivel.
A lo largo de los años, se desarrollaron varios
lenguajes, sobre todo BASIC, COBOL, Pascal, Ada, C, C++
y Java. El programa 9.1 muestra el código para agregar dos
enteros como aparecería en el lenguaje C ++.
9.9
9.10
9-2 TRADUCCIÓN

Los programas de hoy normalmente se escriben en uno


de los lenguajes de alto nivel. Para ejecutar el programa
en una computadora, el programa debe traducirse al
lenguaje de máquina de la computadora en la que se
ejecutará. El programa en un lenguaje de alto nivel se
llama el programa fuente. El programa traducido en
lenguaje de máquina se llama el programa objeto. Se
utilizan dos métodos para la traducción: la compilación
y la interpretación.

9.11
Compilación
Un compilador normalmente traduce todo el programa
fuente en un programa objeto.

Interpretación
Algunos lenguajes de computadora utilizan un intérprete
para traducir el programa fuente al programa objeto. La
interpretación se refiere al proceso de traducir cada línea del
programa fuente a la línea correspondiente del programa
objeto y ejecutar la línea. Sin embargo, debemos ser
conscientes de dos tendencias en la interpretación: la que
usan algunos lenguajes antes de Java y la interpretación que
usa Java.

9.12
Proceso de traducción
La compilación y la interpretación difieren en que la primera
traduce todo el código fuente antes de ejecutarlo, mientras
que la segunda traduce y ejecuta el código fuente una línea a
la vez. Sin embargo, ambos métodos siguen el mismo
proceso de traducción que se muestra en la Figura 9.1.

Figura 9.1 Proceso de traducción del código fuente

9.13
9-3 PARADIGMAS DE PROGRAMACIÓN

Hoy en día, los lenguajes de computadora se clasifican


según el enfoque que utilizan para resolver un
problema. Un paradigma, por lo tanto, es una forma en
que un lenguaje informático mira el problema a
resolver. Dividimos los lenguajes de computadora en
cuatro paradigmas: procedimental, orientado a objetos,
funcional y declarativo. La figura 9.2 resume estos.

9.14
Figura 9.2 Categorías de los lenguajes de programación

9.15
El paradigma procedimental
En el paradigma de procedimiento (o paradigma imperativo)
podemos pensar en un programa como un agente activo que
manipula objetos pasivos. Encontramos muchos objetos
pasivos en nuestra vida diaria: una piedra, un libro, una
lámpara, etc. Un objeto pasivo no puede iniciar una acción por
sí mismo, pero puede recibir acciones de agentes activos.
Un programa en un paradigma de procedimiento es un
agente activo que utiliza objetos pasivos a los que nos
referimos como datos o elementos de datos. Para manipular
una parte de los datos, el agente activo (programa) emite una
acción, conocida como un procedimiento. Por ejemplo, piense
en un programa que imprime el contenido de un archivo. El
archivo es un objeto pasivo. Para imprimir el archivo, el
programa utiliza un procedimiento, que llamamos imprimir.
9.16
Figura 9.3 El concepto de paradigma procedimental

9.17
Un programa en este paradigma consta de tres partes: una parte
para la creación de objetos, un conjunto de llamadas a
procedimientos y un conjunto de códigos para cada
procedimiento. Algunos procedimientos ya han sido definidos
en el propio lenguaje. Al combinar este código, el programador
puede crear nuevos procedimientos.

9.18
Figura 9.4 Los componentes de un programa procedimental
Algunos lenguajes de procedimiento

 FORTRAN (FORmula TRANslation)

 COBOL (COmmon Business-Oriented Language)

 Pascal

C

 Ada

9.19
El paradigma orientado a objetos.
El paradigma orientado a objetos trata con objetos activos en
lugar de objetos pasivos. Encontramos muchos objetos
activos en nuestra vida diaria: un vehículo, una puerta
automática, un lavaplatos, etc. La acción a realizar en estos
objetos se incluye en el objeto: los objetos solo necesitan
recibir el estímulo apropiado desde el exterior para realizar
una de las acciones.
Un archivo en un paradigma orientado a objetos se
puede empaquetar con todos los procedimientos, llamados
métodos en el paradigma orientado a objetos, que debe
realizar el archivo: imprimir, copiar, eliminar, etc. El
programa en este paradigma simplemente envía la solicitud
correspondiente al objeto.

9.20
Figura 9.5 El concepto de paradigma orientado a objetos.

9.21
Clases
Como muestra la Figura 9.5, los objetos del mismo tipo (los
archivos, por ejemplo) necesitan un conjunto de métodos que
muestren cómo reacciona un objeto de este tipo a los
estímulos desde fuera de los "territorios" del objeto. Para
crear estos métodos, se usa una unidad llamada clase (ver
Apéndice F).

Figura 9.6 El concepto de paradigma orientado a objetos.


9.22
Métodos
En general, el formato de los métodos es muy similar a las
funciones utilizadas en algunos lenguajes de procedimiento.
Cada método tiene su encabezado, sus variables locales y su
declaración. Esto significa que la mayoría de las
características que analizamos para los lenguajes de
procedimiento también se aplican a los métodos escritos para
un programa orientado a objetos. En otras palabras, podemos
afirmar que los lenguajes orientados a objetos son en
realidad una extensión de los lenguajes de procedimiento con
algunas ideas nuevas y algunas características nuevas. El
lenguaje C++, por ejemplo, es una extensión orientada a
objetos del lenguaje C.

9.23
Herencia
En el paradigma orientado a objetos, como en la naturaleza,
un objeto puede heredar de otro objeto. Este concepto se
llama herencia. Cuando se define una clase general, podemos
definir una clase más específica que hereda algunas de las
características de la clase general, pero también tiene algunas
características nuevas. Por ejemplo, cuando se define un
objeto del tipo FormasGeometricas, podemos definir una
clase llamada Rectangulos. Los rectángulos son formas
geométricas con características adicionales..

9.24
Polimorfismo
Polimorfismo significa "muchas formas". El polimorfismo
en el paradigma orientado a objetos significa que podemos
definir varias operaciones con el mismo nombre que pueden
hacer cosas diferentes en clases relacionadas. Por ejemplo,
supongamos que definimos dos clases, Rectángulos y
Círculos, ambos heredados de la clase FormasGeométricas.
Definimos dos operaciones denominadas área, una en
Rectángulos y otra en Círculos, que calculan el área de un
rectángulo o un círculo. Las dos operaciones tienen el mismo
nombre.

9.25
Algunos lenguajes orientados a objetos
 C++

 Java

9.26
El paradigma funcional
En el paradigma funcional un programa es considerado una
función matemática. En este contexto, una función es una
caja negra que mapea una lista de entradas a una lista de
salidas.

Figura 9.7 Una función en un lenguaje funcional.


9.27
Por ejemplo, podemos definir una función primitiva llamada
primero que extrae el primer elemento de una lista. También
puede tener una función llamada resto que extrae todos los
elementos excepto el primero. Un programa puede definir
una función que extrae el tercer elemento de una lista
combinando estas dos funciones como se muestra en la
Figura 9.8.

Figura 9.8 Extraer el tercer elemento de una lista


9.28
Algunos lenguajes funcionales
 LISP (LISt Programming)

 Scheme

9.29
El paradigma declarativo
Un paradigma declarativo utiliza el principio de
razonamiento lógico para responder consultas. Se basa en la
lógica formal definida por los matemáticos griegos y más
tarde desarrollada en el Cálculo de Predicados de primer
orden.
El razonamiento lógico se basa en la deducción. Se
dan algunas afirmaciones (hechos) que se suponen
verdaderas, y la máquina de inferencia usa reglas sólidas de
razonamiento lógico para deducir nuevas afirmaciones
(hechos). Por ejemplo, la famosa regla de deducción en
lógica es:

9.30
Usando esta regla y los dos hechos siguientes,

podemos deducir un nuevo hecho:

9.31
Prolog
Uno de los lenguajes declarativos famosos es Prolog
(PROgramming in LOGic), desarrollado por A. Colmerauer
en Francia en 1972. Un programa en Prolog se compone de
hechos y reglas. Por ejemplo, los hechos anteriores sobre los
seres humanos se pueden afirmar como:

El usuario puede entonces preguntar:

y el programa responderá con un sí.


9.32
9-4 CONCEPTOS COMUNES

En esta sección, realizamos una navegación rápida a


través de algunos lenguajes de procedimiento para
encontrar conceptos comunes. Algunos de estos
conceptos también están disponibles en la mayoría de
los lenguajes orientados a objetos porque, como
explicamos, un paradigma orientado a objetos utiliza el
paradigma de procedimiento al crear métodos.

9.33
Identificadores
Una característica presente en todos los idiomas de
procedimiento, así como en otros idiomas, es el
identificador—es decir, el nombre de los objetos. Los
identificadores nos permiten nombrar objetos en el
programa. Por ejemplo, cada pieza de datos en una
computadora se almacena en una dirección única. Si no
hubiera identificadores para representar simbólicamente las
ubicaciones de los datos, tendríamos que conocer y utilizar
las direcciones de datos para manipularlos. En su lugar,
simplemente damos nombres de datos y dejamos que el
compilador haga un seguimiento de dónde se encuentran
físicamente.

9.34
Tipos de datos
Un tipo de datos define un conjunto de valores y un
conjunto de operaciones que se pueden aplicar a esos
valores. El conjunto de valores para cada tipo se conoce
como el dominio para el tipo. La mayoría de los idiomas
definen dos categorías de tipos de datos: tipos simples y
tipos compuestos.

Un tipo simple es un tipo de datos que no se puede


dividir en tipos de datos más pequeños.

Un tipo compuesto es un conjunto de elementos en el


que cada elemento es un tipo simple o un tipo compuesto.

9.35
Variables
Variables son nombres para ubicaciones de memoria. Como
se discutió en el Capítulo 5, cada ubicación de memoria en
una computadora tiene una dirección. Aunque la
computadora utiliza internamente las direcciones, es muy
incómodo para el programador usar direcciones. Un
programador puede usar una variable, tal como nota, para
almacenar el valor entero de una calificación recibida en una
prueba. Desde que una variable contiene un elemento de
datos, también tiene un tipo.

9.36
Literales
Un literal es un valor predeterminado usado en un programa.
Por ejemplo, si necesitamos calcular el área del círculo cuando
el valor del radio se almacena en la variable r, podemos usar la
expresión 3.14 × r2, en la cual el valor aproximado de π (pi) se
usa como un literal. En la mayoría de los lenguajes de
programación podemos tener literales enteros, reales, de
caracteres y booleanos. En la mayoría de los idiomas, también
podemos tener literales de cadena. Para distinguir los literales
de caracteres y cadenas de los nombres de variables y otros
objetos, la mayoría de los idiomas requieren que los literales de
caracteres se incluyan entre comillas simples, como 'A', y que
las cadenas se incluyan entre comillas dobles, como "Ana".

9.37
Constantes
El uso de literales no se considera una buena práctica de
programación a menos que estemos seguros de que el valor
del literal no cambiará con el tiempo (como el valor de π en
geometría). Sin embargo, la mayoría de los literales pueden
cambiar de valor con el tiempo.
Por esta razón, la mayoría de los lenguajes de
programación definen constantes. Una constante, al igual
que una variable, es una ubicación con nombre que puede
almacenar un valor, pero el valor no se puede cambiar
después de que se haya definido al comienzo del programa.
Sin embargo, si queremos usar el programa más adelante,
podemos cambiar solo una línea al comienzo del programa,
el valor de la constante
9.38
Entradas y salidas
Casi todos los programas necesitan leer y/o escribir datos.
Estas operaciones pueden ser bastante complejas,
especialmente cuando leemos y escribimos archivos grandes.
La mayoría de los lenguajes de programación utilizan una
función predefinida para entrada y salida.

Los datos se ingresan mediante una declaración o una


función predefinida como scanf en el lenguaje C.

Los datos se generan mediante una instrucción o una


función predefinida, como printf en el lenguaje C.

9.39
Expresiones
Una expresión es una secuencia de operandos y operadores
que se reduce a un solo valor. Por ejemplo, la siguiente es
una expresión con un valor de 13:

Un operador es un símbolo (token) específico del


idioma que requiere que se realice una acción. Los
operadores más familiares se extraen de las matemáticas.

9.40
La Tabla 9.3 muestra algunos operadores aritméticos
utilizados en C, C ++ y Java.

9.41
Los operadores relacionales comparan datos para ver si un
valor es mayor, menor o igual que otro valor. El resultado de
aplicar operadores relacionales es un valor booleano
(verdadero o falso). C, C++ y Java utilizan seis operadores
relacionales, como se muestra en la Tabla 9.4:

9.42
Los operadores lógicos combinan valores booleanos
(verdadero o falso) para obtener un nuevo valor. El lenguaje
C utiliza tres operadores lógicos, como se muestra en la
Tabla 9.5:

9.43
Sentencias
Una sentencia hace que una acción sea realizada por el
programa. Se traduce directamente en una o más
instrucciones de computadora ejecutables. Por ejemplo, C,
C++ y Java definen muchos tipos de sentencias.

Una sentencia de asignación asigna un valor a una variable.


En otras palabras, almacena el valor en la variable, que ya se
ha creado en la sección de declaración.

Una sentencia compuesta es una unidad de código que


consta de cero o más instrucciones. También es conocido
como un bloque. Una sentencia compuesta permite que un
grupo de instrucciones se trate como una sola entidad.
9.44
La programación estructurada recomienda encarecidamente
el uso de los tres tipos de instrucciones de control:
secuencia, selección and repetición, como discutimos en el
capitulo 8.

Figura 9.9 Decisiones bidireccionales y multidireccionales.


9.45
Figura 9.10 Tres tipos de repetición
9.46
Subprogramas
La idea de subprogramas es crucial en los lenguajes de
procedimiento y, en menor medida, en los lenguajes
orientados a objetos. Esto es útil porque el subprograma hace
que la programación sea más estructural: un subprograma
para llevar a cabo una tarea específica puede escribirse una
vez, pero puede llamarse muchas veces, al igual que los
procedimientos predefinidos en el lenguaje de programación.

Figura 9.11 El concepto de un subprograma.


9.47
En un lenguaje de procedimiento, un subprograma, como el
programa principal, puede llamar a procedimientos
predefinidos para operar en objetos locales. Estos objetos
locales o variables locales se crean cada vez que se llama al
subprograma y se destruyen cuando el control regresa del
subprograma. Los objetos locales pertenecen a los
subprogramas.
Es raro que un subprograma actúe solo sobre objetos locales.
La mayoría de las veces, el programa principal requiere un
subprograma para actuar sobre un objeto o conjunto de
objetos creados por el programa principal. En este caso, el
programa y el subprograma usan parámetros. Estos se
conocen como parámetros reales en el programa principal y
parámetros formales en el subprograma.
9.48
Pasar por valor
En el paso de parámetros por valor, el programa principal y
el subprograma crean dos objetos (variables) diferentes. El
objeto creado en el programa pertenece al programa y el
objeto creado en el subprograma pertenece al subprograma.
Como el territorio es diferente, los objetos correspondientes
pueden tener nombres iguales o diferentes. La comunicación
entre el programa principal y el subprograma es
unidireccional, desde el programa principal hasta el
subprograma.

9.49
Ejemplo 9.1
Suponga que un subprograma es responsable de llevar a cabo la
tarea de impresión del programa principal. Cada vez que el
programa principal desea imprimir un valor, lo envía al
subprograma a imprimir. El programa principal tiene su propia
variable X, el subprograma tiene su propia variable A. Lo que se
envía desde el programa principal al subprograma es el valor de
la variable X.

Figura 9.12 Un ejemplo de paso por valor.


9.50
Ejemplo 9.2
En el ejemplo 9.1, dado que el programa principal solo envía un
valor al subprograma, no necesita tener una variable para este
propósito: el programa principal solo puede enviar un valor literal
al subprograma. En otras palabras, el programa principal puede
llamar al subprograma como imprimir (X) o imprimir (5).

Ejemplo 9.3
Una analogía de pasar por valor en la vida real es cuando un
amigo quiere pedir prestado y leer un libro valioso que usted
escribió. Dado que el libro es precioso, posiblemente agotado,
usted hace una copia del libro y se lo pasa a su amigo. Cualquier
daño a la copia por lo tanto no afecta al original.

9.51
Ejemplo 9.4
Supongamos que el programa principal tiene dos variables X e Y
que necesitan intercambiar sus valores. El programa principal
pasa el valor de X e Y al subprograma, que se almacena en dos
variables A y B. El subprograma de intercambio utiliza una
variable local T (temporal) e intercambia los dos valores en A y
B, pero los valores originales en X e Y siguen siendo los mismos:
no se intercambian.

Figura 9.13 Un ejemplo en el que el paso por valor no funciona.


9.52
Pasar por referencia
Se diseñó el paso por referencia para permitir que un
subprograma cambie el valor de una variable en el programa
principal. Pasando por referencia, la variable, que en realidad
es una ubicación en la memoria, es compartida por el
programa principal y el subprograma. La misma variable
puede tener diferentes nombres en el programa principal y en
el subprograma, pero ambos nombres se refieren a la misma
variable. Metafóricamente, podemos pensar en el paso por
referencia como una caja con dos puertas: una se abre en el
programa principal y la otra se abre en el subprograma. El
programa principal puede dejar un valor en este cuadro para
el subprograma, el subprograma puede cambiar el valor
original y dejar un nuevo valor para el programa en él.

9.53
Ejemplo 9.5
Si utilizamos el mismo subprograma de intercambio pero
permitimos que las variables se pasen por referencia, los dos
valores en X e Y se intercambian realmente.

Figura 9.14 Un ejemplo de paso por referencia


9.54
Valores de retorno
Un subprograma puede diseñarse para devolver un valor o
valores. Esta es la forma en que se diseñan los
procedimientos predefinidos.
Cuando usamos la expresión C←A+B, en realidad
llamamos a un procedimiento sumar(A,B) que devuelve un
valor para ser almacenado en la variable C.

9.55

Potrebbero piacerti anche