Fundamentos de Programación
Fundamentos de Programación
Conceptos básicos de
programación
Introducción
Video de inmersión
La programación es una de las etapas más importantes del ciclo de vida de un proyecto y
requiere un método de trabajo. La programación es el resultado de dicho trabajo. Es el
instrumento que permite la ingesta de datos o la ejecución de las tareas automatizadas de un
sistema informático. Las herramientas utilizadas para programar son los lenguajes de
programación, a través de los cuales se codifican los programas o aplicaciones.
☰ Metodología de la programación
☰ Lenguaje de programación
Existen aplicaciones informáticas que facilitan a los programadores el desarrollo de software, son
denominadas “entornos de desarrollo integrado” (IDE, por sus siglas en inglés). Consisten en un
editor de código fuente, herramientas de construcción automáticas y un depurador de código.
El lenguaje ensamblador surgió como evolución natural, donde a cada secuencia de ceros y
unos se le asocia un nombre nemotécnico. Estos nombres necesitan traducción, que se
realiza mediante un programa que se llama como el lenguaje: ensamblador. Aunque fue un
gran avance, todavía es necesario conocer cómo está constituida y qué recursos tiene la
computadora.
Más tarde, se fueron asociando nombres a conjuntos de instrucciones que realizaban una tarea
compleja determinada y programaban de manera independiente la computadora donde se iba a
ejecutar el código. Nacen los lenguajes de alto nivel y se encuentran más cercanos a la forma de
pensar de los humanos que al lenguaje que entiende la máquina.
es el proceso mental por el que el ser humano extrae las características esenciales de algo e
ignora los detalles superfluos. En programación, el término se refiere a que el énfasis está
puesto en “¿qué se hace?”, más que en “¿cómo se hace?”. Esto es esencial para modelar el
mundo real. Al principio, las personas hacían programas pensando como una computadora
sobre la cual corrían. En la actualidad, se solucionan los problemas sin conocer la máquina
donde va a ser ejecutado el programa.
☰ Encapsulación
☰ Modularidad
☰ Jerarquía
Es importante tener en cuenta algunas consideraciones para que la programación sea de buena
calidad y los resultados sean o se acerquen lo más posible a los esperados en tiempo y forma.
Para esto, se pueden enunciar las siguientes características que se deben tener en cuenta
durante la programación de aplicaciones:
Eficacia: el programa ejecuta correctamente las tareas definidas por su especificación y
satisface los objetivos de los usuarios. Un programa eficaz regresa el resultado correcto del
cálculo que hace o lleva a cabo la tarea requerida de la forma esperada.
Eficiencia: el programa hace un uso adecuado y no malgasta los recursos de la
computadora, como la memoria y el tiempo de procesamiento. Un programa eficiente,
además de eficaz, completará la tarea con mayor rapidez con respecto a otro programa que
no lo es.
Integridad o completitud: un programa es completo solo si ejecuta todas las operaciones
que se codifican en los algoritmos al procesar un conjunto de datos. Es decir, la capacidad
del sistema para realizar todas las operaciones que el usuario podría requerir.
Claridad: es muy importante que el programa sea lo más claro y legible posible, para
facilitar tanto su desarrollo como su posterior mantenimiento. Al elaborar un programa, se
debe intentar que su estructura sea sencilla y coherente, así como cuidar el estilo de
programación. De esta forma, se ve facilitado el trabajo del programador, tanto en la fase de
creación como en las fases posteriores de corrección de errores, ampliaciones,
modificaciones, etc.
Portabilidad: un programa es portable cuando tiene la capacidad de poder ejecutarse en
una plataforma —ya sea hardware o software— diferente a aquella en la que se desarrolló.
La portabilidad es una característica muy deseable para un programa, ya que permite, por
ejemplo, que un programa que se ha elaborado para el sistema GNU/Linux pueda
ejecutarse también en la familia de sistemas operativos Windows. Esto permite que el
programa pueda llegar a más usuarios más fácilmente.
Es importante conocer cada una de estas fases, ya que están íntegramente relacionadas. El
resultado que producen sirve de entrada para el comienzo de la siguiente fase. Dependiendo de
la metodología de desarrollo que se use, son las fases que utilizará el programador. Cada
persona involucrada en este proceso debe conocer e interactuar con cada una de las etapas.
Definición de las necesidades o identificación del problema
Es la comprensión completa del problema con sus detalles. En este punto empezamos a definir el
alcance de la solución, es decir, qué se va a desarrollar y qué no. Nos involucramos con el
problema y buscamos todas las fuentes de información necesarias para solucionarlo. Como
resultado de este análisis exhaustivo, debemos realizar la determinación de las entradas y salidas
del proceso de software. Además, debemos delimitar cómo funcionará el programa, qué datos se
necesitan y qué salida se deberá generar. En definitiva, los requisitos para lograr una solución
eficaz y eficiente.
Diseño de la solución
Existen muchas formas de plasmar la solución analizada. Dos formas comunes de diagramar la
solución a un problema son dibujar un diagrama de flujo y escribir un pseudocódigo. En algunos
casos, para entendimiento de la persona que solicita la resolución del problema, es necesario
emplear ambas metodologías.
Codificación
Este paso consiste en empezar a escribir el código del programa, es decir, expresar la solución
en un lenguaje de programación; traducir la lógica del resultado de la fase anterior a un lenguaje
de programación. Como ya hemos señalado, un lenguaje de programación es un conjunto de
reglas que proporciona una forma de instruir a la computadora qué operaciones realizar.
Prueba y depuración
Algunos expertos insisten en que un programa bien diseñado se puede escribir correctamente la
primera vez. De hecho, afirman que hay formas matemáticas de demostrar que un programa es
correcto. Sin embargo, las imperfecciones del mundo existen, por lo que la mayoría de los
programadores se acostumbran a la idea de que sus programas recién escritos probablemente
tengan algunos errores. Esto es un poco desalentador al principio, ya que los programadores
tienden a ser personas precisas, cuidadosas y orientadas a los detalles; personas que se
enorgullecen de su trabajo. Aun así, hay muchas oportunidades para introducir errores en los
programas. Por esta razón, los programas deben probarse en un ambiente controlado, dedicado
a tal fin.
En realidad, esta actividad no puede ser catalogada como una etapa del proceso de desarrollo de
software; sino que, por lo general, se puede presentar en la etapa de codificación o en la etapa de
verificación. Documentar es un proceso continuo y necesario. Sin embargo, como les pasa a
muchos programadores, podés sentirte ansioso por realizar actividades más emocionantes
centradas en la programación. La documentación es una descripción detallada por escrito del
ciclo de programación y hechos específicos sobre el programa. Los materiales típicos de
documentación del programa incluyen el origen y la naturaleza del problema, una breve
descripción narrativa del programa, herramientas lógicas —como diagramas de flujo y
pseudocódigos—, descripciones de registros de datos, listas de programas y resultados de
pruebas.
Mantenimiento
Es la fase de mayor duración, permite adaptar el desarrollo a cambio de necesidades del negocio
o tecnológicas. Cuando se detectan estas alteraciones en los requerimientos estipulados con
anterioridad, se debe realizar el mantenimiento del software. Siempre es preferible realizar un
mantenimiento preventivo, por lo cual se debe estar atento a los cambios de necesidades.
Figura 1: Fases de un proyecto de software
Algunas características importantes que deben cumplir los programas con respecto a la manera
en que están programados son las siguientes:
Usabilidad: el programa es fácil de usar si las personas a las que está destinado pueden
comprender su manejo de manera intuitiva, realizar sus tareas de forma cómoda y sin
esfuerzos innecesarios.
Mantenibilidad: el código fuente del programa permite localizar y corregir defectos
rápidamente, así como también permite hacer cambios que resultan más fáciles para
adaptarlo a las necesidades cambiantes de los usuarios.
Fiabilidad: un programa es fiable si realiza sus tareas cuando es necesario, con la precisión
requerida y nos brinda la salida esperada.
Otra forma de comunicar los procesos o algoritmos es mediante un pseudocódigo, que puede
definirse como un conjunto de sentencias que no corresponden a ningún lenguaje de
programación específico, pero que denotan la lógica que dicho algoritmo debe seguir.
A continuación, se verán los dos casos: la representación por diagrama de flujo y por
pseudocódigo.
Diagrama de flujo (o flujograma)
Un diagrama de flujo expresa, de manera gráfica, los pasos que seguir y las decisiones que tomar
de un algoritmo o proceso específico.
Por ejemplo, en el caso de un proceso que indica que, si un número es mayor que 5, se lo debe
imprimir en la pantalla y que, de lo contrario, se debe descartar el número.
Figura 2: Ejemplo de diagrama de flujo
Los diagramas de flujo utilizan símbolos con significados definidos que modelan los pasos
del algoritmo y representan el flujo de ejecución mediante flechas que conectan los puntos de
inicio y de fin del proceso.
Elementos de un diagrama de flujo
1. Flechas o líneas de curso: las flechas indican la dirección por la cual avanza el flujo. Van a
conectar al resto de los símbolos del diagrama.
2. Círculos u óvalos: los círculos especifican el inicio o el final del diagrama de flujo. Pueden
simplemente indicar cuándo comienza o termina, pero también pueden ser usados para
representar el evento que inicia el algoritmo y todas las posibles acciones finales. Siempre
se tendrá un solo elemento de inicio, pero se puede tener uno o más elementos finales.
Los círculos se suelen utilizar también como conectores entre diferentes diagramas de flujo.
Cuando estos se vuelven complejos, es conveniente que se dividan en diagramas más pequeños
y, por lo tanto, más legibles.
Figura 3: Ejemplo de círculos u óvalos
3. Rombos: los rombos indican una pregunta, la cual puede tener como respuesta «Sí» o
«No», o «Verdadero» o «Falso». Un rombo siempre tiene un camino para cada respuesta. Se
utiliza cuando se debe tomar una decisión.
Figura 4: Ejemplo de rombo
Los diagramas de flujo pueden ser muy simples, como los vistos ahora, o muy complejos y largos.
Todo depende del problema que se esté intentando resolver.
Figura 6: Diagrama de flujo de pasos que seguir cuando una lámpara no funciona
Fuente: [imagen sin título sobre diagrama de flujo de pasos a seguir cuando una lámpara no funciona], 2017, https://bit.ly/2ZImGKE
En la figura anterior se puede ver que el flujo tiene un inicio, dos posibles finales y diferentes
flujos que pueden darse según las respuestas a las preguntas de los rombos.
Existen otras figuras que se pueden incluir en un diagrama de flujo, las cuales se muestran a
continuación:
Pseudocódigo
Otra forma muy útil de representar los procesos o algoritmos es mediante un pseudocódigo. Este
se define como una representación en lenguaje natural con el objetivo de ser más explicativo y
fácil de leer que el código de los lenguajes de programación.
El código se diferencia del pseudocódigo en que, para leer el primero, se necesita tener cierto
grado de experiencia y conocimiento del lenguaje, mientras que, para leer el pseudocódigo, no.
Los pseudocódigos pueden tener diferentes estilos y parecerse a ciertos lenguajes. Si bien
mantienen su característica principal de estar expresados en lenguaje natural, pueden acercarse
un poco a lenguajes en los cuales, seguramente, sean codificados. Veremos unos ejemplos
comparativos de pseudocódigos con el estilo de tres lenguajes tradicionales: Fortran, Pascal y C
(predecesor de C++). En el siguiente caso, para el juego matemático bizz buzz, las reglas son las
siguientes:
Fuente: [imagen sin título sobre pseudocódigo estilo fortran], 2017, https://bit.ly/2NzEOnp
Fuente: [imagen sin título sobre pseudocódigo estilo Pascal], 2017, https://bit.ly/2NzEOnp
El pseudocódigo es una herramienta muy útil no solo para enseñar, sino también para compartir
un algoritmo y hacerlo más fácil de entender. En conjunto con los diagramas de flujo, ayuda
mucho a la comunicación de cómo debe ejecutarse la lógica de determinados procesos.
Como resumen, algunas de las ventajas de los diagramas de flujo y pseudocódigos son las que
nombramos a continuación:
Las variables siempre tienen un tipo de dato asociado, que establece cómo el lenguaje tiene que
tratar el dato contenido dentro de esa variable; por ejemplo, no es lo mismo manipular un número
que una palabra.
Tipos de datos
Integers: este tipo de datos se utiliza cuando queremos almacenar un número sin
decimales (un número entero). Por ejemplo, es lo que usamos si queremos calcular la suma
de 100 + 300.
Float: el tipo float permite la manipulación de números con decimales. El número 12,25
sería de tipo float.
Double: las variables de este tipo, al igual que las del tipo float, permiten manipular
números con decimales. La principal diferencia es la precisión. Como el nombre lo indica, el
tipo de dato double tiene una precisión doble que el tipo de dato float (2x). En general, un
double tiene 15 dígitos decimales de precisión, mientras que el tipo de dato float tiene
solamente 7.
Character: representa un único carácter, que puede ser un número, una letra o un símbolo.
String: representa cadenas de caracteres. Es utilizado cada vez que necesitamos
manipular o almacenar cadenas con letras, números y símbolos. Un texto, por ejemplo, se
debe almacenar con este tipo de dato.
Boolean: puede tomar solamente los valores «true» (verdadero) o «false» (falso).
Según el tipo de dato, las variables serán manejadas y procesadas dentro del programa de
diferentes modos. Con variables numéricas, se podrán realizar, por ejemplo, conteos y
operaciones matemáticas; sobre strings o cadenas de caracteres, se podrán realizar
concatenaciones o divisiones en cadenas más pequeñas, etcétera.
El tipo de datos string, en C++, no es un tipo de dato nativo. Por lo tanto, para poder utilizarlo,
necesitamos incluir en nuestro programa la librería «String». A continuación, se presenta un
ejemplo de cómo utilizarlo:
Figura 16: Ejemplo de datos string
Constantes
Algunos datos necesarios tendrán información almacenada que no cambiará a lo largo del
programa. En estos casos, es conveniente declarar ese dato como una constante en lugar de una
variable.
Una constante es un valor que no puede ser alterado o modificado durante la ejecución de un
programa, únicamente puede ser leído.
Ejercicios de repaso
1. Se está construyendo un sistema de atención de clientes por orden de llegada. Cuando se
saca un turno, el sistema debe seleccionar cuál de las dos mesas debe atender al solicitante.
Para esto, debe derivar al cliente a la mesa que tenga menos solicitantes en cola de espera.
Conociendo el tamaño de dichas colas de espera, se debe programar un algoritmo que compare
dos números y que retorne el menor. Se debe tener en cuenta que, si son iguales, debe
informarlo para que quien ejecute el algoritmo decida a qué mesa deriva al cliente.
Leer n1
Leer n2
Si n1 es menor que n2
Si n2 es menor que n1
FIN
Opción 2
Leer n1
Leer n2
Si n1 es menor que n2
Si n2 es menor que n1
FIN
Opción 3
Leer n1
Leer n2
Si n1 es mayor que n2
Si n2 es mayor que n1
FIN
RESPUESTA
Para poder crear un programa, necesitamos tener un conjunto de instrucciones o estructuras que
nos permitan controlar el flujo de ejecución; en otras palabras, necesitamos ser capaces de
controlar las acciones del programa que estamos creando y codificar esas instrucciones o
evaluaciones en nuestro programa.
Supongamos que tenemos un programa que cambia el color de una pantalla cuando hacemos
clic en un botón: el evento de entrada sería el clic en el botón, el proceso sería el cambio de color
y el resultado sería el nuevo color mostrado en pantalla.
Ahora bien, ¿cómo sabe el programa que tiene que cambiar el color cuando se hace clic en un
botón y no en otro lado?, ¿cómo sabe que tiene que cambiar el color de la pantalla y no de otra
cosa? Este tipo de decisiones tienen que estar plasmadas en el código y no dejar nada librado al
azar. Todo esto se logra mediante las estructuras de control que veremos a continuación.
Los ejemplos en este módulo son codificados en C++, pero las estructuras de control
son comunes en todos los lenguajes.
Tema 1. Condicionales
Los condicionales son instrucciones que evalúan la veracidad de una sentencia. Evalúan una
expresión booleana (una proposición lógica) y, según el valor booleano (verdadero o falso)
resultante, deciden si ejecutan o no una determinada sección de código. A estas secciones se las
llama bloques de código.
La sentencia if
cin >> Este comando se utiliza para ingresar datos por la entrada estándar (el teclado).
cout << Este comando se utiliza como método de salida de datos por pantalla (realiza una
impresión en la consola de salida). Lo que se imprime es el texto entre comillas, un string en este
caso.
En la imagen anterior, podemos ver cómo se define un condicional en el lenguaje C++. En primer
lugar, solicitamos al usuario que ingrese dos números —num1 y num2—, luego se evalúa si esos
dos números son iguales o no, utilizando una estructura condicional. Para poder comparar el
valor de num1 y num2, se utilizan operadores lógicos de comparación. A continuación, se detallan
algunos de ellos:
Tabla 1: Operadores lógicos de comparación
La sentencia else
Else puede considerarse una extensión de la sentencia if y significa “de lo contrario”. Permite la
ejecución de un conjunto de sentencias en caso de que la expresión booleana del if sea falsa,
esta sección se llama bloque else.
Para el ejemplo del if anterior, la parte del código donde evalúa la no igualdad de los números es
el bloque else.
Es importante destacar que la sentencia else solo puede utilizarse si una sentencia if ha sido
declarada anteriormente.
La combinación else-if
Hasta ahora, la sentencia if y la sentencia else pueden ser de gran utilidad, pero ¿qué sucede si
necesitamos evaluar más de dos condiciones? Por ejemplo, si debemos realizar un programa que
muestre en pantalla si dos valores ingresados son iguales, el primero mayor que el segundo o el
segundo mayor que el primero; el código sería como el siguiente:
De este modo, dentro de un bloque if o else, podemos anidar otros bloques if o else. Es
importante notar que else-if es posible gracias a esta característica.
Figura 23: Anidamiento de bloques (en C++)
Observá que el primer bloque if, además de la sentencia de salida por consola (cout), tiene otro
bloque if anidado. Lo mismo podríamos hacer en el bloque else, en caso de ser necesario.
La sentencia switch
Con switch, podemos evaluar el valor de una variable o el resultado de una expresión de
cualquier tipo y, de acuerdo con este, ejecutar cierta sección del código. Es similar a else-if, ya
que es útil cuando queremos comparar el valor de una variable o resultado con más de una
opción.
Switch y else-if cumplen la misma función. Siempre es recomendado utilizar switch cuando
tenemos opciones múltiples en vez de else-if, debido a su simplicidad.
Su principal característica es que permite establecer en forma clara muchas opciones para el flujo
de ejecución a diferencia de la sentencia if, en donde solo hay dos opciones.
Por ejemplo, tenemos que codificar un algoritmo que, dada la variable «intNumber», pueda
mostrar su equivalente en números romanos. El algoritmo debe funcionar para los números entre
el 1 y el 5.
Switch permite agregar una opción por defecto (por default), es decir, una opción que se ejecute
cuando ninguna de las demás es verdadera (también puede ser nombrada opción por defecto).
Esto permite responder en caso de que el valor de la variable no corresponda con ninguna de las
opciones esperadas. Para el ejemplo, podríamos imprimir un mensaje que indique que el valor
evaluado por el switch no está dentro de los esperados:
Figura 26: Switch con default (C++)
Fuente: elaboración propia
Por ejemplo, queremos mostrar los números del 0 al 10. ¿Cómo podría codificarse? Esta sería
una de las formas:
El bucle do-while
Este bucle es similar al bucle while y permite la repetición de la ejecución de un bloque de código
determinado mientras se cumpla una condición determinada. La única diferencia es que la
expresión booleana se evalúa al final de cada repetición (iteración).
Podés observar que, a diferencia del while, en el bucle do-while el bloque de código se ejecuta al
menos una vez (invariablemente), ya que es al final de cada iteración cuando se evalúa la
condición que determina el final del ciclo.
La siguiente sería una forma de imprimir los números del 0 al 10 con un do- while:
Es muy similar a while, pero con la palabra clave «do» y luego el código que se repite. La
condición de repetición se indica al final.
El bucle for
Este bucle también permite la repetición de una sección de código de acuerdo con el valor de una
variable o expresión booleana, pero teniendo control y conocimiento sobre la cantidad de
iteraciones. En el caso de que la expresión sea verdadera, el código se repite. En el caso de que
sea falsa, el código no se repite y pasa a la línea siguiente.
Con un for, es necesario tener un valor inicial, un valor final de referencia y una expresión que
indique cómo será el paso de una iteración a la siguiente.
Por ello, una sentencia for está compuesta por tres partes:
Volvamos a tomar el ejemplo de los números del 0 al 10: ¿cómo podría codificarse con un for?
Esta sería una de las formas:
Figura 33: Bucle for (en C++)
Como se puede ver en la figura anterior, en el bucle for podemos definir una variable, utilizarla
como punto de partida y como condición para decidir si el código repite la ejecución (conocida
como condición de repetición o condición de corte) y, también, aumentar el valor de dicha variable
al final de cada repetición.
La función endl imprime un carácter de final de línea con retorno de carro “\n”. La salida del
código anterior sería la siguiente
El bucle for-each
Por ejemplo, ¿cómo podríamos imprimir en pantalla una lista de palabras? Veamos el
siguiente código:
Figura 35: Bucle for-each (en C++)
For-each es mucho más simple que un for regular, debido a que no necesitamos establecer la
condición de repetición. Se evaluará la variable «arr», y, a medida que se va recorriendo la lista,
la variable «x» va tomando el valor de cada uno de los ítems de dicha lista.
Uno de esos lineamientos es crear funciones. Las funciones son secciones de código que
podemos reutilizar de forma tal que no tengamos que codificar varias veces el mismo código y lo
podamos reutilizar.
Comentario
En el código de la figura 37, tuvimos que escribir el código de la fórmula dos veces. Ahora bien,
¿qué sucede si tuviésemos que calcular el área para 4 triángulos? Para este ejemplo, solo
tenemos que repetir dos líneas de código (cada una con los valores respectivos) por cada uno de
los triángulos. Sin embargo, en desarrollos más grandes, para resolver una funcionalidad común
para ciertos casos, podemos tener muchas más líneas.
Una mejor forma de hacer esto es escribiendo el código repetido en una función que resuelva el
problema y que podamos invocar cada vez que sea necesario. En nuestro ejemplo, en lugar de
escribir el código de la fórmula, invocamos la función y le proporcionamos los datos del triángulo
como parámetros de entrada para que realice el cálculo.
Figura 37: Función para imprimir el área de un triángulo (en C++)
La palabra «void» indica que la función no va a generar ningún resultado para quien la llama,
solamente calculará el área e imprimirá el resultado. En caso de que, por ejemplo, la función
devuelva algún dato, se debe reemplazar «void» por el tipo de dato correspondiente al que
retorna la función. Seguido, se debe incluir el nombre de la función, y entre paréntesis, se deben
indicar los parámetros de entrada con sus nombres y el tipo de dato correspondiente (en el
ejemplo, son base y altura del triángulo). Estos últimos son los valores sobre los cuales se
ejecutará el algoritmo de la función.
Figura 38: Uso de función para imprimir el área de un triángulo (en C++)
De esta manera, cada vez que necesitemos mostrar por pantalla el área de un triángulo,
simplemente invocamos la función con los parámetros de entrada correspondientes a la altura y
la base.
Si, en lugar de imprimir el área, necesitamos que la función retorne ese valor para que sea
procesado en otra parte del código, la función debería especificarse de la siguiente manera:
En este caso, «int» especifica que la función devolverá el área como un valor entero en donde el
parámetro es de salida de la función. La sentencia para realizar este retorno es, en C++, «return»,
seguida de la variable que contiene el resultado (en este caso, la variable «área»).
Figura 40: Uso de función para devolver el área de un triángulo (en C++)
La variable «área» tendrá asignado los valores que retorne la función calcularArea en cada una
de las invocaciones.
Funciones anónimas
Las funciones de tipo anónimas se caracterizan por no poseer un nombre. En nuestro ejemplo
anterior, creamos una función nombrada, cuya función es calcularArea, que usamos para
ejecutarla.
Ahora bien, si una función no tiene nombre, ¿cómo la utilizamos? En realidad, estas funciones no
se utilizan más que en el lugar donde son definidas, ya que no pueden ser llamadas. El propósito
de estas funciones es darle flexibilidad al programador. Sin embargo, como regla general, no
deberíamos usarlas, salvo que sea estrictamente necesario, porque agrega más complejidad al
código. En su lugar, deberíamos utilizar funciones nombradas o no anónimas, como vimos en el
ejemplo anterior.
Las funciones anónimas son también conocidas como funciones lambda.
Las funciones lambda, a menudo, son enviadas como parámetros de entrada a funciones
nombradas para que estas las apliquen a otros datos que procesan. Si la función solo se usa una
vez o un número limitado de veces, una expresión lambda puede ser sintácticamente más simple
que usar una función con nombre.
Figura 41: Ejemplo de función lambda (en C++)
En C++, entre corchetes, podemos definir las variables que podrán ser utilizadas en el cuerpo de
la función; entre paréntesis, los parámetros de entrada de la función. Luego, el operador lambda
(->) separa la declaración de parámetros de entrada de la declaración del cuerpo de la función.
Opcionalmente, se puede especificar el tipo de data que retornará la función.
Figura 42: Función lambda como argumento de otra función
Este código calcula el doble del valor de cada elemento en el array o lista. La función for_each
definida por C++ permite procesar listas de valores. Es importante que sepas que for_each tiene
tres parámetros de entrada: el primero es el inicio de la lista de valores; el segundo es el final de
la lista, y el tercero es la función lambda que se debe aplicar a cada uno de los valores de la lista.
La función for_each pertenece a la librería «Vector». Las librerías son paquetes de funciones
predefinidas que se instalan cuando lo hace la herramienta. Dichas librerías extienden la
funcionalidad básica de la herramienta. Más adelante veremos las librerías con mayor detalle.
Figura 43: Resultado del código de la función 25
Podemos definir un algoritmo recursivo como aquel que se utiliza dentro de sí mismo. Una
función recursiva es la codificación de dicho algoritmo, y se caracteriza por llamarse a sí misma
dentro de la propia función.
La recursividad es útil para resolver problemas definibles en sus propios términos. La recursividad
es, en cierta medida, análoga al principio de inducción.
La recursividad se debe usar cuando sea absolutamente necesaria, es decir, cuando no exista
una solución iterativa simple. Utilizando mal la característica de recursividad, podemos caer en
bucles infinitos o utilización de los recursos computacionales de manera inadecuada.
Llamar una función
El cálculo del factorial de un número, además de como lo vimos anteriormente, podría ser
representado de la siguiente forma:
n! = n * (n -1)!
4! = 4 * 3!
Por lo tanto, si tenemos una función para calcular el factorial, podremos utilizarla dentro del
mismo cálculo y estaríamos generando recursividad.
A simple vista, se puede notar lo relativamente más simple que queda la función utilizando
recursividad.
Es importante que una función de este tipo tenga una condición que finalice la recursión. Dicha
condición se llama condición de corte y, de no estar presente la función, podría generar un ciclo
infinito; por lo que el programa fallaría, ya que nunca se llegaría a la solución esperada. Además,
recordá siempre que, dentro de la función, no se debe invocar con los mismos parámetros de
entrada, dado que, de este modo, también se ingresaría en un ciclo recursivo infinito. En el
ejemplo del factorial, la función calcularFactorial se vuelve a invocar siempre con el parámetro
número - 1.
Revisá cómo impactan estos conceptos en Java:
Ejercicios
1. Para el siguiente algoritmo, indicá la salida por consola que se genera:
Ejercicio 1
Muchas veces, necesitamos contar las repeticiones de un suceso en un programa. Esta acción
que la hemos visto mediante ejemplos dentro de este módulo, se denomina contador. Los
contadores son muy útiles y usados en programación.
Sabiendo esto, tenés que confeccionar un programa donde se calcule tantos múltiplos de 2 como
una cantidad x ingresada. El programador debe solicitar el ingreso de dicha variable al usuario.
Ejercicio 2
Ahora que ya sabés qué es un acumulador, codificá un programa donde el usuario ingrese el
monto de las ventas del día. Se tendrán que acumular estas ventas hasta que el usuario ingrese
0 (cero). Cuando el usuario ingrese dicho valor, el programa deberá mostrar el total de ventas.
Descargá el PDF a continuación para conocer los resultados:
Preguntas de habilidades
¿Qué indica las secciones entre estos símbolos “/** */” en Java?
Comentarios
Objetos
Métodos
Clases
Atributos
Justificación
¿Qué palabra clave identifica una sección de código como una clase en
Java?
object
class
new
string
interface
Justificación
Imprimir en pantalla
Es un método estático
Declarando atributos
Justificación
Con espacios
Con guiones
Todo en minúscula
Inicia con una mayúscula y luego separando cada palabra con mayúsculas, sin
guiones ni espacios
Justificación
Cuadernillo de actividades
Actividad
Resolución
Glosario
Referencias
[Imagen sin título sobre diagrama de flujo de pasos a seguir cuando una lámpara no
funciona], (2017). https://commons.wikimedia.org/w/index.php?curid=2161669