jueves, 29 de octubre de 2009

Aprende a programar: 4 - Estructuras de Control

Las estructuras de control nos permiten definir el flujo de nuestro programa, nos permiten indicar qué sentencias se ejecutarán en función de que se cumplan una serie de condiciones. También nos permitirán repetir la ejecución de una o varias sentencias un número determinado de veces. Para el primer caso usamos las estructuras de selección, y para el segundo las estructuras de repetición.

Cada sentencia que se usa en C++ está separada de la otra por ';'. En algunos casos nos interesa agrupar sentencias, pues bien, el bolque de sentencias se define mediante llaves '{' y '}'. Todas las sentencias que estén dentro del mismo bloque se ejecutarán el mismo número de veces.

ESTRUCTURAS DE SELECCIÓN

El formato es el siguiente:
if (expresion)
    bloque de sentencias 1;
else
    bloque de sentencias 2;

Esta sentencia evalúa la expresión booleana que hay entre paréntesis, y si el resultado es cierto se ejecutarán las sentencias del bloque 1 y en caso contraro se ejecutarán las del bloque 2.
Ejemplo:
#include <iostream>
using namespace std;

int main()
{
    int num;
    cout << "Introduce un numero" << endl;
    cin >> num;

    if(num%2==0)
        cout << "El numero es par" << endl;
    else
        cout << "El numero es impar" << endl;

    system("pause");
}

El bloque else es opcional. Si en caso de que no se cumpla la condición no quieres hacer nada, no tienes porque poner el bloque else. Recuerda que si quisieras ejecutar varias sentencias seguidas, tendrían que estar englobadas con llaves.
Ejemplo:
#include <iostream>
using namespace std;

int main()
{
    int num;
    cout << "Introduce un numero" << endl;
    cin >> num;

    if(num%2==0)
        cout << "El numero es par" << endl;
    else {
        cout << "El numero es impar" << endl;
        cout << "O sea, que no es par"<< endl;
    }

    system("pause");
}

Selección Múltiple

Se usa cuando se dispone de una expresión que al evaluarla puede dar varios resultados.
El formato es el siguiente:
switch (expresion)
{
    case valor1:
        sentencia 1;
        sentencia 2;
        break;
    case valor2:
        sentencia;
        break;
    default:
        sentencia;
}

Las etiquetas case no pueden estar repetidas y deben ser del mismo tipo que el selector.
Si ninguno de los valores de las etiquetas case coincide con el valor del selector, se pasará a la siguiente instrucción que haya después de switch, a menos que se haya usado la opción default, que será la que se ejecuta en caso de que el valor de la expresión no coincida con ningún valor de los case.
Ejemplo:
#include <iostream>
using namespace std;

int main()
{
    int num;
    cout << "Introduce un numero del 1 al 3" << endl;
    cin >> num;

    switch (num) {
        case 1:
            cout << "uno" << endl;
            cout << "que no pare ninguno" << endl;
            break;
        case 2:
            cout << "dos" << endl;
            cout << "nos movemos los dos" << endl;
            break;
        case 3:
            cout << "tres" << endl;
            cout << "voy del reves" << endl;
            break;
        default:
            cout << "Has introducido un numero menor que 1 o mayor que 3" << endl;
    }

    system("pause");
}

¡¡ACUÉRDATE DE PONER EL BREAK!! Es importante escribir el break después de cada case ya que si no se escribiera break, una vez encontrada la etiqueta case correspondiente, se ejecutaría la sentencia asociada a dicha etiqueta y todas las sentencias que hay a continuación hasta el final del switch o encontrar una sentencia break.

ESTRUCTURAS DE REPETICIÓN

Volvamos al ejemplo anterior, el cual nos indicaba si un número era para o impar. Vamos a hora a modificarlo para que nos obligue a introducir un número mayor que cero.
#include <iostream>
using namespace std;

int main()
{
    int num;
    cout << "Introduce un numero positivo" << endl;
    cin >> num;

    if (num<=0) {
        cout << "ERROR" << endl;
        cout << "Introduce un numero positivo" << endl;
        cin >> num;
    }

    if(num%2==0)
        cout << "Es par" << endl;
    else
        cout << "Es impar" << endl;

    system("pause");
}

Mediante esta solución sólo garantizamos que si el usuario se equivoca una vez se le permita de nuevo la entrada de datos, pero si el usuario se equivoca por segunda vez, no tendrá la oportunidad para rectificar y la comparación se hará con un número menor o igual a cero. Por tanto, necesitamos otro tipo de estructura para repetir una serie de sentencias un determinado número de veces.

Con condicion inicial: WHILE

Se emplea para genarar bucles (repeticiones) mientras la sentencia de la expresión sea cierta.
Forma general:
while (condicion)
    sentencia;

En caso de haber varias sentencias, se agruparán mediante llaves como ya sabemos.

Tiene que haber dentro del bucle alguna sentencia que altere el valor de la expresion, sino se entraría en un bucle infinito.

Ejemplo (solución al problema anterior):
#include <iostream>
using namespace std;

int main()
{
    int num;
    cout << "Introduce un numero positivo" << endl;
    cin >> num;

    while (num<=0) {
        cout << "ERROR" << endl;
        cout << "Introduce un numero positivo" << endl;
        cin >> num;
    }

    if(num%2==0)
        cout << "Es par" << endl;
    else
        cout << "Es impar" << endl;

    system("pause");
}

Podemos hacer cosas interesantes como mostrar la tabla de multiplicar de cualquier numero:
#include <iostream>
using namespace std;

int main()
{
    const int kveces=10;
    int contador;
    int n;

    cout << "Introduce un numero" << endl;
    cin >> n;

    contador=0;
    while(contador<=kveces)
    {
        cout << n << " x " << contador << " = " << n*contador << endl;
        contador++;
    }

    system("pause");
}

Con condicion al final: DO WHILE

Al igual que en la estructura anterior, el bucle se ejecutará meintras las expresión sea verdadera.
do
    sentencias;
while (expresion);

La diferencia entre while y do-while es que en el segundo se comprueba la condición de continuación del bucle al final, esto significa que siempre se ejecutará por lo menos una vez el cuerpo del bucle.
Un uso muy común de este tipo de bucles es el de realizar filtros para garantizar que el usuario introduzca información correctamente, según los valores permitidos.

Para usar todo lo que llevamos aprendido hasta ahora, vamos a hacer el pequeño juego de escribir un número entre 1 y 100, y luego que otra persona tenga que adivinarlo en menos de 5 intentos.
#include <iostream>
using namespace std;

int main()
{
    int intentos,secreto,numero,i;
    const int klineas=24; //Líneas de la pantalla
    const int kMaxIntentos=5;

    do {
        cout << "Escribe el numero a adivinar entre 1 y 100: ";
        cin >> secreto;
        cout << endl;
    }
    while (secreto<1 || secreto>100);

    system("pause");

    //Ahora borraremos la pantalla
    i=0;
    while (i<klineas) {
        cout << endl;
        i++;
    }

    intentos=0;
    numero=0;

    while(numero!=secreto && intentos<kMaxIntentos) {
        cout << "Adivina el numero: ";
        cin >> numero;

        if(secreto>numero)
            cout << "El numero que buscas es mayor" << endl;
        else
        if (secreto<numero)
            cout << "El numero que buscas es menor" << endl;

        intentos++;
    }

    if (numero==secreto)
        cout << "MUY BIEN, SOLO HAS NECESITADO "<<intentos<<" INTENTOS." << endl;
    else
        cout << "HAS HECHO "<<kMaxIntentos<< " INTENTOS Y NO LO HAS ADIVINADO. ERA EL " << secreto << endl;

    system("pause");
}

Con contador: FOR

Es equivalente a un bucle con condicion inicial, pero genera un código más compacto. Se suele uasr cuando la finalización del bucle depende del valor de una variable que se decremente o incrementa en una cantidad fija (no tiene porque ser una unidad). No obstante, se puede usar para muchas posibilidades.
El formato general es:
for (e1;e2;e3)
    sentencias;

* e1 es una o varias sentencias que se ejecutan una sola vez antes de comenzar el bucle.
* e2 es una expresión lógica que mientras se evalúe a cierto se ejecutará el bucle.
* e3 es una o varias sentencias que se ejecutan en cada iteración después de ejecutar las sentencias del cuerpo del bucle.

Una estructura FOR es equivalente a una do while de la siguiente forma:
e1;
while(e2)
{
    sentencias;
    e3;
}

Por ejemplo, en el ejemplo anterior, podríamos haber usado un bucle FOR para borrar la pantalla en vez del WHILE:
for (i=0;i<klineas;i++)
    cout << endl;

Como vemos, las instrucciones para borrar la pantallan pasan de ocupar 4 líneas, a sólo 2.

No hay comentarios:

Publicar un comentario