Control Flujo Condicional

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 18

Control de flujo condicional

5
5.1 Introducción

Los programas vistos hasta el momento se ejecutan de forma secuencial, una sentencia a continua-
ción de otra sin omitir ninguna.
Estas sentencias, asociadas a la función principal main(), constituyen un ejemplo de sentencia
compuesta: conjunto de sentencias situadas dentro de un bloque de código entre llaves { }.
La programación limitada a la ejecución secuencial de instrucciones es demasiado simple. Las
capacidades que vemos día a día en nuestra interacción con los ordenadores y las aplicaciones
informáticas, serían imposibles si solamente contáramos con las opciones vistas hasta el momento.
Es suficiente la introducción de dos nuevas estructuras básicas para que se abra la puerta a la
posibilidad de realizar todas las tareas de cómputo que son teóricamente concebibles.
Estas dos estructuras, constituidas por sentencias compuestas, son:
las estructuras condicionales
las estructuras iterativas o bucles
Sirven para alterar la estructura secuencial que se tiene por defecto.
Una sentencia condicional realiza un conjunto u otro de sentencias dependiendo del cumplimiento
o no de una determinada condición.
En C++ podemos distinguir diferentes tipos:
Simple: if
Ampliada: if - else
Anidada: if – else if - . . . - else
Multisalida: switch
Además de las sentencias de control de flujo condicional, introduciremos algunos de los opera-
dores típicamente asociados a éstas.

1
Fundamentos de Programación en C++, Curso 2020/21

5.2 Operadores relacionales de comparación

Sirven para comparar dos variables o expresiones. La expresión boolena resultante en la que
intervienen puede resultar cierta (true) o falsa (false).

Tabla 1: Operadores relacionales de comparación


Operador Descripción
> mayor que
>= mayor o igual que
< menor que
<= menor o igual que
== igual que
!= distinto que

C++ utiliza el tipo de dato nativo bool para almacenar los valores true o false de una expresión
boolena. En la práctica, C++ lo que hace es lo siguiente:
si la expresión en la que interviene el operador es falsa, internamente se almacenará un 0.
si la expresión se evalúa como cierta, se almacenará un 1.
Las palabras reservadas true y false son literales predefinidos por el lenguaje con el objetivo de
aportan legibilidad y contexto a las expresiones booleanas.

Atención: En C++ todos los valores representan verdad, excepto el 0.

#include <iostream>
using namespace std;
int main()
{
int x = 3;
int y = 4;
bool z = x > y; // z tomará el valor false
cout << z << endl;
z = x != y; // z tomará el valor true
cout << z << endl;
}

Edita, compila y ejecuta el código

2 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

5.3 Control de flujo condicional if

Es una sentencia en la que se evalúa una condición y, solo si es verdad, se ejecuta un conjunto de
sentencias asociadas.
if (condicion)
{
bloque de sentencias;
}

Las llaves { . . . } delimitan el conjunto de sentencias afectadas por la condición if.

Figura 1: Diagrama de flujo de la sentencia if

Ejemplo
/*----------------------------------------------------*/
/* Este programa transforma temperaturas de */
/* grados celsius a grados kelvin */
/* Comprueba si la temperatura tiene existencia real */
/*----------------------------------------------------*/
#include <iostream>
using namespace std;

int main()
{
double centig;
cout << "Introduzca grados celsius: ";
cin >> centig;
if (centig >= -273.)
{
double kelvin = centig + 273.; // Inicializacion
cout << centig << " grados celsius son " << kelvin
<< " grados kelvin\n";
}
}

Edita, compila y ejecuta el código

5.3. Control de flujo condicional if 3


Fundamentos de Programación en C++, Curso 2020/21

Nótese en el ejemplo anterior que las dos sentencias asociadas a la sentencia if se ejecutan en
función de si la expresión entre paréntesis centig >= -273. es evaluada como cierta o falsa.
Consideraciones respecto a la sintaxis
Cuando el bloque está formado por una única sentencia, pueden omitirse las llaves.
Así,

if (a != 0)
{
a = 1/a;
}

es equivalente a:

if (a != 0)
a = 1/a;

Siguiendo con el ejemplo anterior, es habitual escribirlo como:

if (a) // a != 0 <-> a
a = 1/a;

dado que cualquier valor no nulo será siempre evaluado como cierto.

Advertencia: El siguiente fragmento ilustra un error habitual.


a = 5;
if (a = 1) //¡¡ERROR!!
cout << "La variable vale 1\n";

¡Se esta asignando en lugar de comparando!

5.4 Control de flujo condicional if - else

La forma ampliada permite ejecutar dos bloques de sentencias distintas dependiendo de que se
cumpla la condición o no.

if (condicion)
{
bloque de sentencias 1;
}
else
{
bloque de sentencias 2;
}

4 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Figura 2: Diagrama de flujo de la sentencia if - else

Ejemplo 1

/*----------------------------------------------------*/
/* Grados celsius -> grados kelvin */
/* Comprueba si la temperatura tiene existencia real */
/* En caso negativo visualiza un mensaje de error */
/*----------------------------------------------------*/

#include <iostream>
using namespace std;

int main()
{
double centig;
cout << "Introduzca grados celsius: ";
cin >> centig;

if (centig >= -273.)


{
double kelvin = centig + 273.;
cout << centig << " grados celsius son " << kelvin
<< " grados kelvin\n";
}
else
{
cout << "Esa temperatura no existe.\n";
}
}

Edita, compila y ejecuta el código

5.4. Control de flujo condicional if - else 5


Fundamentos de Programación en C++, Curso 2020/21

Ejemplo 2

// Ejemplo que ilustra el hecho de que hay que evitar


// realizar comparaciones entre valores en coma flotante

#include <iostream>
using namespace std;

int main()
{
double x = 0.3;
double y = 0.1;
double z = 0.2;

if (x == y+z) // Matemáticamente son iguales, pero ...


cout << "x es igual a y+z.\n";
else
cout << "x no es igual a y+z.\n";
}

Edita, compila y ejecuta el código


Ejemplo 3

// Ejemplo similar al anterior: no existe asociatividad en


// operaciones en coma flotante
#include <iostream>
using namespace std;

int main()
{
double x = 0.1 + (0.2 + 0.3);
double y = (0.1 + 0.2) + 0.3;
// Fija 20 posiciones a visualizar despues de la coma
cout.precision(20);
cout << "x=" << x << "\ny=" << y << endl;

if (x == y) // Matemáticamente son iguales, pero ...


cout << "x es igual a y\n";
else
cout << "x no es igual a y\n";
}

Edita, compila y ejecuta el código

6 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Consideraciones respecto a la sintaxis


El siguiente fragmento ilustra un error de sintaxis habitual.

if (a != 0)
{
b = a;
a = 1/a;
};
else
cout << "No se puede invertir el 0\n";

El ; tras la llave de cierre } es la causa del error. Podemos reescribir el código como:

if (a != 0)
{
b = a;
a = 1/a;
}
;
else
cout << "No se puede invertir el 0\n";

Así se aprecia mejor que la sentencia vacía ; hace que el else quede desvinculado del if.
Otro error sintáctico típico es olvidar las llaves {...}.

if (a != 0)
b = a;
a = 1/a;
else
cout << "No se puede invertir el 0\n";

Podemos reescribir el código como:

if (a != 0)
b = a;
a = 1/a;
else
cout << "No se puede invertir el 0\n";

Así se aprecia mejor que la sentencia a = 1/a; no pertenece al bloque if y, de nuevo, el else queda
desvinculado.

Advertencia: Un error semántico muy habitual es situar un ; tras el cierre de paréntesis ) de


la condición if.
if (a != 0);
{
b = a;
a = 1/a;
}

5.4. Control de flujo condicional if - else 7


Fundamentos de Programación en C++, Curso 2020/21

Para apreciar el error semántico, podemos reescribir el código como:

if (a != 0)
;

{
b = a;
a = 1/a;
}

Ahora resulta que la única sentencia asociada al if es la sentencia vacía ;. El bloque de sentencias
entre llaves {...} se ejecutará siempre.
Los errores semánticos son en muchas ocasiones los más complejos de depurar, pues pasan des-
apercibidos para el compilador y sólo son detectables a través de la salida espuria del programa.

5.5 Control de flujo condicional if - else if - ... - else

En muchas ocasiones interesa evaluar de forma anidada varias expresiones condicionales de arriba
a abajo. Cuando aparece una condición verdadera, ejecuta las acciones asociadas y salta el resto de
las expresiones condicionales sin necesidad de evaluarlas.
Normalmente existe un bloque final else{. . . } que actúa como condición por defecto.

if (condicion_1)
{
bloque 1 de sentencias;
}
else if (condicion_2)
{
bloque 2 de sentencias;
}
else if (condicion_3)
{
bloque 3 de sentencias;
}
// Tantos bloques else if como sean necesarios
else // si no se cumple ninguna de las anteriores
{
bloque n de sentencias;
}

Nótese que no se está introduciendo ninguna novedad sintáctica en el lenguaje. Para comprobarlo,
basta reorganizar visualmente esta sentencia compuesta en forma anidada a la forma ampliada.

8 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Por ejemplo, para 4 bloques de sentencias, los bloques anidados en forma ampliada quedarían
visualmente así:

if (condicion_1)
{
bloque 1 de sentencias;
}
else
{
if (condicion_2)
{
bloque 2 de sentencias;
}
else
{
if (condicion_3)
{
bloque 3 de sentencias;
}
else // si no se cumple ninguna de las anteriores
{
bloque 4 de sentencias;
}
}
}

El último bloque else puede aparecer opcionalmente.

Figura 3: Diagrama de flujo de la sentencia if - else if - ... - else

5.5. Control de flujo condicional if - else if - ... - else 9


Fundamentos de Programación en C++, Curso 2020/21

Ejemplo

// Solicita tres enteros y determina su orden


#include <iostream>
using namespace std;
int main()
{
int x, y, z;
cout << "Introduce tres enteros separados por espacios: ";
cin >> x >> y >> z;

cout << "El orden de menor a mayor es: ";


if (x < y)
{
if (z < x)
cout << z << ", " << x << ", " << y << endl;
else if (z < y)
cout << x << ", " << z << ", " << y << endl;
else
cout << x << ", " << y << ", " << z << endl;
}
else
{
if (z < y)
cout << z << ", " << y << ", " << x << endl;
else if (z < x)
cout << y << ", " << z << ", " << x << endl;
else
cout << y << ", " << x << ", " << z << endl;
}
}

Edita, compila y ejecuta el código


Consideraciones respecto a la sintaxis
De cara a la legibilidad del código y evitar errores es fundamental sangrar las líneas de un bloque
anidado de sentencias.
A pesar de sus pocas líneas, el siguiente fragmento de código es ilegible:

if (n > 0)
if (a > b)
z = a;
else
z = b;

Su versión sangrada permite visualizar de forma más clara las intenciones del programador:

if (n > 0)
if (a > b)
z = a;
else
z = b;

10 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Nótese que el bloque else siempre está asociado al if inmediatamente anterior. Por ello, si en el
ejemplo anterior, lo que realmente se desea es asociar el else al primer if, la solución sería:

if (n > 0)
{
if (a > b)
z = a;
}
else
z = b;

5.5.1 Condiciones de evaluación mutuamente excluyentes

La siguiente tabla muestra dos escenarios en los cuales la salida del programa será idéntica si el
conjunto de condiciones es mutuamente excluyente.

Opción 1 Opción 2

if (condicion_1) if (condicion_1)
{ {
bloque 1 de sentencias; bloque 1 de sentencias;
} }
else if (condicion_2) if (condicion_2)
{ {
bloque 2 de sentencias; bloque 2 de sentencias;
} }
// Resto de bloques else if // Resto de bloques if
else if (condicion_n) if (condicion_n)
{ {
bloque n de sentencias; bloque n de sentencias;
} }

En estos casos, además de la mejora en la legibilidad del código, es computacionalmente superior


la Opción 1.
Con la opción 1, en el momento en que una condición se evalúe como true, el resto de
condiciones serán ignoradas.
Con la opción 2, aunque una de las condiciones se evalúe como true, el programa seguirá
evaluando el resto de condiciones, lo que, al ser excluyentes, es una pérdida de tiempo.

5.5. Control de flujo condicional if - else if - ... - else 11


Fundamentos de Programación en C++, Curso 2020/21

5.6 Operadores relacionales lógicos

Sirven para evaluar expresiones compuestas de tipo lógico, cuya resultado, por tanto, resultará
cierto o falso, true o false.
La evaluación de las operaciones lógicas se realiza de izquierda a derecha y se interrumpe cuando
se ha asegurado el resultado. Esto se conoce como propiedad de cortocircuito: si se puede con-
cluir el valor lógico del resultado a partir de una evaluación parcial de la expresión, no se sigue
evaluando la misma.

Tabla 2: Operadores relacionales lógicos


Operador Descripción
&& Y, devuelve true cuando todas las expresiones que relaciona son ciertas
|| O, devuelve true cuando al menos una expresión es cierta
! NO, devuelve true cuando la expresión a la que afecta es false

Las tablas de verdad asociadas a estos operadores son:

Tabla 3: Operador Y lógico


a b a && b
false false false
false true false
true false false
true true true

Tabla 4: Operador O lógico


a b a || b
false false false
false true true
true false true
true true true

Tabla 5: Operador NO lógico


a !a
false true
true false

Los operadores de comparación y lógicos aparecen habitualmente de forma simultánea en las ex-
presiones. Por ello, es conveniente conocer su orden de precedencia relativo:

12 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Tabla 6: Tabla de precedencia de los operadores de comparación y lógicos


Precedencia Operador Descripción Asociatividad
3 ! Negación lógica Izquierda a derecha
9 < <= > >= Operadores de comparación Izquierda a derecha
10 == != Operadores de igualdad Izquierda a derecha
14 && Conjunción lógica Izquierda a derecha
15 || Disyunción lógica Izquierda a derecha

Insistimos en usar los paréntesis (...) en caso de duda y/o para mejorar la legibilidad.
Ejemplo 1

// Ejemplo que controla el rango permitido de valores de dos enteros


#include <iostream>
using namespace std;

int main()
{
int x, y;
cout << "Introduce dos numeros enteros positivos o 0. "
<< "Ambos no pueden valer simultáneamente 0.\n";
cout << "Introduce el primer numero: ";
cin >> x;
cout << "Introduce el segundo numero: ";
cin >> y;

if (x < 0 || y < 0)
cout << "Error. Los numeros introducidos no son ambos positivos.\n";
else if (x == 0 && y == 0)
cout << "Error. Los dos numeros son 0.\n";
else
cout << "Los numeros introducidos son validos.\n";
}

Edita, compila y ejecuta el código


Nótese la superior precedencia de los operadores de comparación respecto a los lógicos && y || en
expresiones como x < 0 || y < 0 o x == 0 && y == 0.
Por la propiedad de cortocircuito, en el ejempo anterior, si el usuario introduce cualquier valor de
x negativo, no se evaluará la expresión y < 0.

5.6. Operadores relacionales lógicos 13


Fundamentos de Programación en C++, Curso 2020/21

Ejemplo 2

// Ejemplo que controla que un denominador no sea 0


#include <iostream>
using namespace std;

int main()
{
int x, y;
cout << "Introduce el numerador: ";
cin >> x;
cout << "Introduce el denominador: ";
cin >> y;

if (!y) // Equivalente a if (y != 0)
cout << "Error. No podemos dividir por 0.\n";
else
cout << "x/y= " << x/y << endl;
}

Edita, compila y ejecuta el código


Este ejemplo nos permite recordar que el operador división / entre enteros genera un entero.

14 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

5.7 Control de flujo condicional switch

Aunque el escalonamiento if - else if - else puede evaluar de forma anidada múltiples condi-
ciones, si estas son muy numerosas, empieza a haber pérdida de legibilidad.
C/C++ posee una estructura condicional múltiple, switch, que ejecuta un bloque de sentencias si
una variable o expresión entera coincide con alguno de los valores proporcionados en una lista
de constantes enteras (literales int o char, por ejemplo).

switch (expresion)
{
case valor_1:
sentencias_1
case valor_2:
sentencias_2
//Resto de bloques case
case valor_n:
sentencias_n
default:
sentencias_default;
}

La ejecución del programa consiste en comparar expresion de arriba a abajo con cada constante
literal que aparece tras la palabra reservada case. Si se localiza una coincidencia, se ejecutan todas
las sentencias por debajo de esa constante hasta:
finalizar el bloque switch
encontrar una sentencia break;
Opcionalmente se puede insertar una condición por defecto mediante default, cuyas sentencias
asociadas se ejecutarían si no se ha encontrada previamente una coincidencia.
Para ilustrar el funcionamiento de la sentencia switch vamos a ver diferentes versiones de un
programa con idéntica salida por pantalla, que muestra el númer de días de un mes.
Versión 1 con if anidados

#include <iostream>
using namespace std;

int main()
{
cout << "Dame el mes: (1, 2, ..., 12): ";
int mes;
cin >> mes;

if (mes > 0 && mes < 13)


if (mes == 1)
cout << "El mes tiene 31 dias.\n";
else if (mes == 2)
cout << "El mes tiene 28 o 29 dias.\n";
else if (mes == 3)
(continué en la próxima página)

5.7. Control de flujo condicional switch 15


Fundamentos de Programación en C++, Curso 2020/21

(proviene de la página anterior)


cout << "El mes tiene 31 dias.\n";
else if (mes == 4)
cout << "El mes tiene 30 dias.\n";
else if (mes == 5)
cout << "El mes tiene 31 dias.\n";
else if (mes == 6)
cout << "El mes tiene 30 dias.\n";
else if (mes == 7)
cout << "El mes tiene 31 dias.\n";
else if (mes == 8)
cout << "El mes tiene 31 dias.\n";
else if (mes == 9)
cout << "El mes tiene 30 dias.\n";
else if (mes == 10)
cout << "El mes tiene 31 dias.\n";
else if (mes == 11)
cout << "El mes tiene 30 dias.\n";
else if (mes == 12)
cout << "El mes tiene 31 dias.\n";
else
cout << "¡Imposible!\n";
else
cout << "El valor introducido no es válido\n";
}

Edita, compila y ejecuta el código


Versión 2 mejorada con if anidados

#include <iostream>
using namespace std;

int main()
{
cout << "Dame el mes: (1, 2, ..., 12): ";
int mes;
cin >> mes;

if (mes > 0 && mes < 13)


if (mes == 1 || mes == 3 || mes == 5 || mes == 7 ||
mes == 8 || mes == 10 || mes == 12)
cout << "El mes tiene 31 dias.\n";
else if (mes == 2)
cout << "El mes tiene 28 o 29 dias.\n";
else if (mes == 4 || mes == 6 || mes == 9 || mes == 11)
cout << "El mes tiene 30 dias.\n";
else
cout << "¡Imposible!\n";
else
cout << "El valor introducido no es válido.\n";
}

16 Capítulo 5. Control de flujo condicional


Fundamentos de Programación en C++, Curso 2020/21

Edita, compila y ejecuta el código


Versión 3 con switch

#include <iostream>
using namespace std;

int main()
{
cout << "Dame el mes: (1, 2, ..., 12): ";
int mes;
cin >> mes;

if (mes > 0 && mes < 13)


switch(mes)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
cout << "El mes tiene 31 dias.\n";
break;
case 4:
case 6:
case 9:
case 11:
cout << "El mes tiene 30 dias.\n";
break;
case 2:
cout << "El mes tiene 28 o 29 dias.\n";
break;
default:
cout << "¡Imposible!\n";
}
else
cout << "El valor introducido no es válido.\n";
}

Edita, compila y ejecuta el código


La sentencia break, de la que hablaremos más adelante, es un tipo de sentencia de control de flujo
incondicional. Su objetivo es forzar la salida inmediata del bloque en el que está declarada, en
este caso, el bloque switch.

5.7. Control de flujo condicional switch 17


Fundamentos de Programación en C++, Curso 2020/21

5.7.1 Realización de menús

La sentencia condicional switch se utiliza con frecuencia para gestionar la selección en menús.
En caso de que la opción elegida no sea válida, se realiza el código asociado al bloque default,
visualizándose un mensaje de error.
Ejemplo de menú

// Transforma temperaturas de celsius <-> kelvin


#include <iostream>
using namespace std;
int main()
{
int opcion;
double celsius, kelvin;
cout << "Este programa transforma temperaturas.\n";
cout << "Elija una opcion:\n";
cout << "1. De grados celsius a grados kelvin.\n";
cout << "2. De grados kelvin a grados celsius.\n\n";
cout << "Por favor, introduzca su opcion (1 o 2): ";
cin >> opcion;
switch(opcion)
{
case 1: // paso de Celsius a Kelvin
cout << "Introduzca la temperatura en grados Celsius: ";
cin >> celsius;
if (celsius >= -273)
{
kelvin = celsius + 273;
cout << celsius << " grados C son " << kelvin << " grados K.\n";
}
else
cout << "Temperatura por debajo del cero absoluto.\n";
break;
case 2: // paso de Kelvin a Celsius
cout<<"Introduzca la temperatura en grados kelvin:\n";
cin >> kelvin;
if (kelvin >= 0)
{
celsius = kelvin - 273;
cout << kelvin << " grados K son " << celsius << " grados C.\n";
}
else
cout << "Temperatura por debajo del cero absoluto.\n";
break;
default:
cout << "La opcion escogida no es válida.\n";
}
}

Edita, compila y ejecuta el código

18 Capítulo 5. Control de flujo condicional

También podría gustarte

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy