Sei sulla pagina 1di 13

Codificación de Algoritmos en Java

Sitio: Instituto de Tecnología ORT


Curso: Taller de Programación 1 - Plan 2 años
Libro: Codificación de Algoritmos en Java
Imprimido por: ESCALANTE ECHAGÜE ENRIQUE JOSÉ
Día: miércoles, 28 de agosto de 2019, 17:48

Tabla de contenidos
1. Introducción
2. Bloques de instrucciones
3. Instrucciones básicas con variables
4. Bloques de Entrada/Salida
4.1. Operaciones de Salida
4.2. Operaciones de Entrada
5. Instrucciones de control de flujo
5.1. Condicional Simple (If)
5.2. Condicional múltiple (Switch)
6. Subprocesos (invocación y retorno)
7. Ciclos
7.1. While (ciclo 0-n)
7.2. Do-while (ciclo 1-n)
7.3. For (ciclo fijo)
7.4. For-each

1. Introducción
Los diagramas forman parte de las herramientas de la programación.Aunque muchos programadores han
aprendido directamente escribiendo código su uso es importante, en especial cuando damos los primeros pasos
dentro del mundo de la programación. Posteriormente son una excelente forma de documentar secuencias
detalladas de instrucciones, permitiendo programar con exactitud más allá de la elección final del lenguaje de
implementación utilizado.
A diferencia del pseudocódigo (donde las palabras a utilizar no están totalmente pautadas entre dos
programadores que no se conocen) cualquier tipo de diagrama que se use es en sí mismo un
lenguaje unívocoque no da lugar a ninguna confusión o mala interpretación. Incluso hay lenguajes donde el
programador construye el programa a partir del diagrama y luego éste se ejecuta, sin haber pasado jamás por la
escritura completa del código en forma textual.

La diagramación Nassi-Shneiderman fue desarrollada a comienzo de los años 70 para cumplir con el
paradigma de la Programación Estructurada.
Según la diagramación Nassi-Shneiderman, cada instrucción es un pequeño bloque. Su forma permite
combinar estos bloques entre sí para cumplir con lo deseado, incrustando uno dentro de otro si fuese necesario.
Cada instrucción tiene su correlación en el diagrama. Esa relación es unívoca (es decir, hay una única manera
de diagramar una instrucción) y no hay lugar a confusiones. Por eso, el diagrama intenta ser universal, y no está
atado a una única forma de codificado.

No obstante, dado que nosotros usaremos Java como lenguaje de implementación de nuestros algoritmos,
veremos también cómo se escribe en Java cada uno de los bloques definidos según los diagramas Nassi-
Shneiderman.

2. Bloques de instrucciones
Hay varios grupos de bloques de instrucciones:

Instrucciones básicas con variables;


Instrucciones de entrada o salida: Salida o Mostrar, Entrada o Ingresar:
Instrucciones de control de flujo: Condicional simple, Condicional múltiple, Llamado a subprocesos e
Instrucciones repetitivas o ciclos (while, do-while y for).
Veamos, entonces, para qué sirven los componentes de cada uno de estos grupos.

3. Instrucciones básicas con variables


Si bien no tienen su correlato como bloque en la diagramación Nassi-Shneiderman, la declaración de variables
es indispensable, pues es en ellas donde guardamos los datos que serán usados durante el tiempo de ejecución
de un programa, y siempre las variables que son utilizadas en el diagrama son declaradas junto a él.

Una asignación es la instrucción que permite poner un determinado valor como contenido de una variable. Por
lo tanto, primero necesitamos crear el "frasco" donde vamos a dejar el valor: eso es crear o declarar la variable.

Una vez que la hayamos creado ya podemos asignarle un valor, con este formato:

Por ejemplo, así declaramos la variable cantidad y la inicializamos con el valor 0:

El código en Java que implementa esta instrucción es

int cantidad;
cantidad = 0;

En el caso de las cadenas de caracteres (Strings) el valor se escribe entre comillas dobles. Por ejemplo, si
creamos la variable saludo...

El código en Java que implementa esta instrucción es

String saludo;
saludo = "¡Hola Mundo!";

También podemos asignar expresiones que generen un valor. Por ejemplo, así obtenemos un promedio:

El código en Java que implementa esta instrucción es

double promedio;
promedio = acumulado / cantidad;

4. Bloques de Entrada/Salida
Las operaciones de Entrada (por ejemplo, carga de datos por teclado) y Salida (mostrar algo por pantalla o
imprimir) son muy similares. Ambas tienen en su esquina superior derecha o izquierda una letra que identifica el
tipo de operación (si lo vemos en nuestro idioma será una “E” para entrada y “S” para las salidas).
La gran diferencia entre uno y otro es que las operaciones de entrada solo pueden tener como elemento una
variable, pues es el único elemento que puede contener un dato.
4.1. Operaciones de Salida
Al igual que en la asignación, las operaciones de Salida pueden mostrar
tanto valores (sean literales, constantes o variables) u operaciones que devuelvan un valor.

El bloque de diagrama que representa la operación de Salida es:

Pero algo que se ve completamente simple en el diagrama es un poco más largo en su codificación en Java, y
hay un porqué.

Debido a la concepción modular de Java, las operaciones de Entrada y Salida no forman parte del corazón del
lenguaje. Esto es porque Java considera que son operaciones periféricas, con distintas variaciones según el
dispositivo donde se ejecute la aplicación o el tipo de interfaz utlizada. Inclusive, las librerías de entrada y salida
podrían no estar presentes en un programa si éste no necesita la interacción con una persona, o porque esta
interacción va por otro lado. Imaginemos por ejemplo una aplicación de control de un brazo robot que no tiene
una pantalla para mostrar texto, sino sólo un conjunto de luces de estado. Otra posibilidad (mucho más cercana
y común) es que Java delegue las operaciones de entrada y salida a un tercero (como por ejemplo a una página
web).

Volviendo a nuestro caso (donde trabajaremos con la consola de sistema de Java) usaremos el componente de
consola del sistema.

El programa HolaMundo suele ser el primer ejemplo en cada libro y/o presentación de un lenguaje de
programación. Así es su diagrama, y a continuación su equivalente en Java utilizando la consola del sistema:

System.out.println(“¡Hola Mundo!”);

También podemos cargar el mensaje en un variable para luego mostrarla (y entonces veremos su contenido):

En Java, esto sería:

String saludo;
saludo = "¡Hola Mundo!";
System.out.println(saludo);
Java permite que la definición de una variable se complete con la asignación de su valor inicial. De esta forma
podríamos tener.

String saludo = "¡Hola Mundo!";


System.out.println(saludo);

Veamos otro ejemplo: si quisiéramos mostrar el resultado de una suma podríamos hacer:

Esto, en Java, es:

int a = 8;
int b = 3;
System.out.println(“La suma de a + b es ” + (a + b));

4.2. Operaciones de Entrada


A nivel de Nassi-Shneiderman una operación de entrada es muy, muy simple, y se ve así:

Tal como se ve en esta caja, en las operaciones de entrada siempre el contenido es una variable.

Por ejemplo, si pedimos por teclado la carga del nombre del usuario que está usando el programa hacemos…

Pero, al igual que en el caso anterior (donde recurrimos a System.out.println() para mostrar algo por consola)
Java necesita utilizar un elemento del lenguaje que no está incluido en su núcleo para que nos ayude a capturar
lo que un usuario va a ingresar por teclado.

Ese elemento es el Scanner. Este objeto deberá crearse y referenciarse a System.in. Como su
contraparte System.out para las operaciones de salida, System.in abre un canal hacia la entrada de datos del
sistema, que en este caso es el teclado. Para hablar de manera simple, el Scanner se conecta y lee lo que el
usuario va escribiendo en el teclado y captura esa información para dejarla en una variable cada vez que el
usuario pulsa ENTER.

Veamos cómo es, entonces, una operación de carga de datos por teclado en Java:
Por suerte, el Scanner debe ser creado una sola vez (no hay que crearlo por cada operación de carga de datos
desde teclado) pero sí será usado cada una de estas veces.

Para crear un Scanner (al que en el ejemplo llamaremos input) escribiremos lo siguiente:

Scanner input = new Scanner(System.in);

La primera palabra resaltada indica, aunque ahora no lo parezca, un tipo muy especial de dato, y la variable
asociada a ese tipo de dato es input. Tal como adelantamos hace unos pocos párrafos, la parte de la asignación
resaltada a la derecha del igual indica que lo que estamos haciendo es crear un Scanner que leerá
el canal de System.in. Este objeto que estamos creando quedará, entonces, referenciado por la variable input.

Listo, ya tenemos el lector de teclado; ahora hagamos que lea.

Para cargar el dato de una cadena de caracteres (que es el tipo de dato del nombre):

nombre = input.nextLine();

Al hacer esto, cuando el usuario pulse ENTER el scanner capturará el contenido del buffer de teclado y lo
asignará a la variable nombre.

Cada tipo de dato tiene su propia forma de ser leído con el scanner, y eso tiene que ver con el formato interno
del dato.

Así, para cargar un entero se hace:

int numeroEntero;
numeroEntero = input.nextInt();

Es recomendable no utilizar el scanner de esta manera para capturar números. La instrucción equivalente que
recomendamos es:

numeroEntero = Integer.parseInt(input.nextLine());

También para los números reales, aunque podríamos hacer

double numeroReal;
numeroReal = input.nextDouble();

haremos:

double numeroReal;
numeroReal = Double.parseDouble(input.nextLine());

5. Instrucciones de control de flujo


Hasta ahora, todas las instrucciones que vimos fueron secuenciales: cada una se escribe detrás de la otra y se
ejecuta de la misma manera. Pero un programa es mucho más que una secuencia de comandos: debemos
tomar decisiones que impliquen hacer una cosa, otra o ninguna, elegir un camino entre varios posibles, repetir
varias veces el mismo proceso, etc. También nos pasará que debamos invocar a una subtarea específica que
podemos pensar como un mini-programa dentro de nuestro programa, e incluso esperar de esta subtarea un
respuesta (como es en el caso de las funciones):

Condicional simple;
Condicional múltiple;
Llamado a subprocesos;
Instrucciones repetitivas o ciclos (while, do-while y for).

5.1. Condicional Simple (If)


Más conocido como if, el condicional simple permite elegir entre dos caminos posibles a partir del resultado
de una condición lógica (cuyo valor sólo puede ser verdadero o falso).

En Java, la estructura básica de una condición simple o if es

if (condición lógica) {
… lo que hago si es verdadero;
} else {
… lo que hago si es falso;
}

Por ejemplo, si queremos saber cuál si un valor de una variable es mayor al de otra, hacemos:

Que en Java se traduce como:

if (a>b) {
System.out.println(“el valor de a es mayor que el de b”);
} else {
System.out.println(“el valor de b es mayor o igual que el de a”);
}

En el diagrama genérico decíamos que podríamos “no hacer nada” por el camino falso (por el else). En ese
caso, dejamos ese lado del if vacío:
Siempre hacemos que el lado vacío sea el else. La razón es simple: el camino verdadero del if es obligatorio,
mientras que el camino falso es opcional y por lo tanto, cuando el lado falso queda vacío no es necesario escribir
el else. Así, el diagrama anterior pasado a Java quedará como:

if (edad > 18) {


System.out.println(“es mayor de edad”);
adultos = adultos + 1;
}

5.2. Condicional múltiple (Switch)


También conocido como switch, el condicional múltiple permite elegir entre varios caminos a partir de un
valor enumerable. La estructura del switch es:

En Java, el switch se escribe de la siguiente manera:

switch(variable o expresión enumerable) {


case A: ...lo que hago si vale A: break;
case B: ...lo que hago si vale B: break;
default: ...lo que hago si es cualquier otro valor;
}

Es importante remarcar que si bien el break no forma parte de la estructura del switch, es necesario al final de
cada case, excepto el último, para que no se sigan ejecutando las instrucciones por caída. Esto quiere decir que
si no ponemos el break en la primera opción y el valor de la expresión es A, se ejecurarán los bloques de A y de
B, consecutivamente.

Veamos un ejemplo:

cuyo código en Java es:


switch(resultado_del_partido) {
case LOCAL:
System.out.println(“Ganó el equipo local”); break;
case VISITANTE:
System.out.println(“Ganó el equipo visitante”); break;
default:
System.out.println(“Empataron”);
}

Los valores posibles para resultado_del_partido, entonces, son LOCAL, VISITANTE o EMPATE. Si no
pusiéramos el break luego del System.out del primer case, se mostrarían las dos salidas, consecutivamente:

Ganó el equipo Local


Ganó el equipo Visitante

Al poner el break, ese problema desaparece.

6. Subprocesos (invocación y retorno)


Los subprocesos son parte fundamental de la programación moderna, y nacen de la necesidad de reutilizar
porciones de código que bajo el paradigma de la programación lineal debían escribirse una y otra vez, con los
mismos o distintos valores.

Presentamos aquí cómo se invoca a un subproceso según Nassi-Shneiderman y cómo lo escribimos en Java.

El único componente de una llamada es el nombre del subproceso seguido de un par de paréntesis.

En Java, para llamar a un subproceso, escribiremos exactamente lo mismo que escribimos dentro del bloque del
diagrama, seguido del punto y coma habitual que termina la instrucción:

subproceso();

Ahora, si ese subproceso necesita recibir parámetros, éstos se incluirán dentro de los paréntesis, uno detrás del
otro y separados por comas, y siempre respetando el orden y el tipo de cada uno de ellos según la declaración
del subproceso, en su encabezado (deben respetar la firma del método).

Invocación a métodos de otros objetos o clases

Cuando el método que queremos invocar pertenece a otro objeto o clase, simplemente anteponemos a su
nombre el nombre de la clase u objeto correspondiente. De hecho, es lo que hacemos cuando queremos
mostrar algo por consola o cargar algo desde el teclado utilizando un Scanner:

System.out.println("Esto es lo que se muestra");


int numero = Integer.parseInt(input.nextLine());

En estos ejemplos invocamos...


al método println() del objeto System.out;
al método nextLine() del objeto input.
al método parseInt() de la clase Integer.

Dado que este último es un método de clase, podemos asegurar que es un método estático (static).

La cláusula return
Todo método que no sea del tipo void deberá devolver un valor a través de la cláusula return.

Por ejemplo, un getter() devuelva el valor del campo nombre sería así:

public String getNombre() {


return this.nombre;
}

No es necesario que el valor de retrorno sea una variable. Por ejemplo, el método doble(int valor) devuelve valor
recibido multiplicado por 2:

public int doble(int valor) {


return valor * 2;
}

7. Ciclos
Los ciclos permiten que una instrucción (o un grupo de dos o más instrucciones) se ejecute una y otra vez
mientras se den las condiciones deseadas.

Según la programación estructurada existen tres tipos de ciclo. Dos de ellos son controlados por una
condición lógica de permanencia: mientras ésta se cumpla (mientras su resultado sea verdadero) el flujo se
mantiene dentro del ciclo y sus instrucciones se repiten una y otra vez hasta que la condición deja de cumplirse
y se sale del ciclo. El tercero es controlado por una variable cuyo valor se incrementa o decrementa, lo cual
indica que podemos saber de antemano y con exactitud cuántas vueltas van a cumplirse antes de terminar o
seguir con las instrucciones posteriores.

Teniendo en cuenta la cantidad de ciclos o vueltas que darán, se los denomina:

Ciclo 0-n (Cero-n) o while;


Ciclo 1-n (Uno-n) o do-while;
Ciclo Fijo o for.

A éstos agregamos, para la POO el ciclo for-each, que utilizamos para recorrer colecciones de datos o cualquier
otro elemento que sea iterable.

7.1. While (ciclo 0-n)


Se lo llama así porque puede ser que no haya posibilidad de entrar al ciclo (porque ya antes de entrar la
condición del ciclo no se cumple) y porque, una vez que se entró al ciclo, lo único que permitirá que se salga es
que la condición deje de cumplirse. Este ciclo es conocido como while y se caracteriza porque la condición de
permanencia antecede al bloque de instrucciones que conforman el ciclo:

Su paralelo en Java es:


while (condicion_de_permanencia) {
instruccion o bloque de instruccciones;
}

Es muy probable que el ciclo esté controlado por una o más variables que, incluidas dentro de la condición de
permanencia, determinen a partir de su estado (si la condición relacionada con la variable de control se cumple o
no) y, por lo tanto, si se permanece dentro del ciclo o si sale y continúa con el resto del programa. Por eso,
podemos ver también este ciclo de esta manera:

Uno de los usos habituales de los ciclos es el ingreso validado de valores. Como muchas veces los programas
interactúan con usuarios y éstos casi inevitablemente cometerán errores, es muy importante que los datos que
vamos a usar en nuestros programas estén controlados, siendo sus valores acordes a lo que esperamos.

Veamos un ejemplo: queremos que alguien ingrese el número de día de la semana para que nosotros, a partir
de eso, hagamos algo (no importa qué). Por eso, controlaremos que el número esté dentro del rango esperado
(un número entre 1 y 7), caso contrario deberíamos informar del error y volver a pedir el número. El diagrama es
el siguiente:

Esto se traduce en java como:

int numeroDeDia;
System.out.print("Ingresa el numero de dia de la semana (1 a 7)");
numeroDeDia = Integer.parseInt(input.nextLine());
while (numeroDeDia < 1 || numeroDeDia > 7) {
System.out.print("Me parece que te equivocaste. " +
"Ingresa el numero de dia de la semana " +
"asegurandote de que sea un numero " +
"entre el 1 y el 7 (inclusive):");
numeroDeDia = Integer.parseInt(input.nextLine());
}
7.2. Do-while (ciclo 1-n)
Se lo llama ciclo 1-n porque, a diferencia del while, su condición de permanencia se escribe y chequea luego
de ejecutar el bloque de instrucciones que conforman el ciclo. Por lo tanto, siempre se entrará al ciclo
aunque, al igual que en el caso de while, una vez que se entró al ciclo sólo se permitirá salir de él cuando la
condición deje de cumplirse.

Su paralelo en Java es:

do {
instruccion o bloque de instruccciones;
} while (condicion_de_permanencia);

Haciendo un paralelo con lo que dijimos anteriormente para el while, podemos ver a este ciclo de esta manera:

Es importante aquí resaltar que no hay dos puntos de actualización de la variable de control, y que éste
es apenas se ingresa al ciclo, ni antes ni después.

Veamos el ejemplo de la carga del día de semana tal como se haría con este ciclo. Dado que el dato se carga
apenas antes de ser procesado, y dentro del ciclo, en caso de desear un tratamiento especial en caso de error
implicaría que usemos un if para mostrar el problema. Para hacer eso, aconsejamos usar el ciclo while.

El diagrama es el siguiente:

Esto se traduce en Java como:

int numeroDeDia;
do {
System.out.print("Ingresa el numero de dia de la semana (1 a 7)");
numeroDeDia = Integer.parseInt(input.nextLine());
} while (numeroDeDia < 1 || numeroDeDia > 7);

7.3. For (ciclo fijo)


Se conoce al for como ciclo fijo porque la cantidad de veces que se ciclará es conocida antes de entrar al ciclo,
siempre y cuando no se altere artificialmente el valor de la variable de control.

A nivel de diagramación Nassi-Shneiderman se diferencia claramente de los dos ciclos anteriores:

Por ejemplo, para mostrar en orden ascendente los primeros diez números naturales, hacemos:

Ahora bien, en Java y todos los lenguajes que se basan en C en cuanto a su estructura sintáctico-semántica, el
for es casi un while encubierto. Para entenderlo mejor, veamos el ejemplo anterior pasado a Java:

int numero;
for (numero=1; numero <= 10; numero++) {
System.out.println(“numero “ + numero);
}

También podemos hacer al revés y mostrar estos números en orden descendente:

Así es el código Java del diagrama:

int numero;
for (numero=10; numero >= 1; numero--) {
System.out.println(“numero “ + numero);
}

Cuando decimos que el ciclo es fijo porque se conoce de antemano la cantidad de vueltas, eso no significa que
ese valor sea fijo o constante. Veamos el siguiente ejemplo para que quede más claro:
En este caso, el ciclo dará tope vueltas, siempre y cuando el valor de numero no sea mayor a tope. Por lo tanto,
si el usuario ingresase un valor para tope menor o igual que cero, las instrucciones del ciclo no se
ejecutarán. ¡Cuidado con eso!

7.4. For-each
El for-each (literalmente "para cada uno [de los elementos de...]") es el miembro más nuevo de los ciclos, y
nació especialmente para recorrer colecciones de datos.

Su definición no está reglada por Nassi-Shneiderman, pero podemos definirla de forma similar al for:

Por ejemplo, para mostrar todos los elementos de una colección haríamos:

La primera parte, a la izquierda, declara la definición del ciclo. En forma similar a su primo estructurado, el for-
each sabe cuál es la cantidad de vueltas que ciclará: eso está determinado por la cantidad de elementos que
tiene la colección, valor que se obtiene de su método size().

Para bajar aún más a concreto el ejemplo, el siguiente diagrama recorre todos los elementos de la colección
alumnos inscriptos en esta materia en el Aula Virtual. La colección contiene elementos de la clase Alumno:

En Java escribiremos:

for (Alumno alu: aulaVirtual.alumnosRegistrados("TP1") {


System.out.println("¡Bienvenido al nuevo TP1 " + alu + "!");
}

Suponiendo que la clase Alumno tiene implementado su método toString(), y que éste devuelve nombre y
apellido del alumno, el ciclo le dará la bienvenida a cada uno de los alumnos registrados en la materia
mostrando sus nombres y apellidos.

Potrebbero piacerti anche