Saltar al contenido
Portada » C/C++ » 3. Estructuras de Control

3. Estructuras de Control

Estructuras de Control. Arrancamos este capítulo donde vamos a abordar uno de los elementos clave en cualquier lenguaje de programación. Las estructuras de control nos permiten dirigir el flujo de ejecución de un programa en C, tomando decisiones y repitiendo bloques de código según condiciones específicas. Aprenderemos a utilizar instrucciones condicionales como if, else y switch para ejecutar distintas acciones dependiendo del valor de ciertas variables, así como bucles como while, for y do...while para repetir instrucciones de forma controlada. También veremos sentencias especiales como break y continue que alteran el flujo dentro de los bucles. Empezamos!!!

3.1 Sentencias condicionales (if, else, switch)

En programación, los condicionales son estructuras que permiten tomar decisiones durante la ejecución de un programa. En el lenguaje C, las decisiones se toman evaluando expresiones booleanas (que resultan en verdadero o falso) y ejecutando distintos bloques de código según el resultado.

Sintaxis básica del if

if (condición) {
// Código que se ejecuta si la condición es verdadera
}

La condición se evalúa como verdadera si su resultado es distinto de cero (en C, 0 es falso, y cualquier otro valor es verdadero). Si la condición se cumple, el bloque de código dentro del if se ejecuta.

Ejemplo:

#include <stdio.h>

int main() {
int edad = 20;

if (edad >= 18) {
printf("Eres mayor de edad.\n");
}

return 0;
}

Explicación: El programa declara una variable edad con valor 20. Como 20 >= 18 es verdadero, se imprime «Eres mayor de edad».

if + else

Cuando queremos ejecutar un bloque de código en caso contrario, usamos else.

if (condición) {
// Se ejecuta si la condición es verdadera
} else {
// Se ejecuta si la condición es falsa
}

Ejemplo:

#include <stdio.h>

int main() {
int numero = -5;

if (numero > 0) {
printf("El número es positivo.\n");
} else {
printf("El número es negativo o cero.\n");
}

return 0;
}

Explicación: En este caso, como numero es -5, la condición numero > 0 es falsa, por lo tanto se ejecuta el bloque del else.

if, else if, else

Cuando hay múltiples condiciones que queremos evaluar en orden, usamos else if.

if (condición1) {
// Se ejecuta si condición1 es verdadera
} else if (condición2) {
// Se ejecuta si condición2 es verdadera
} else {
// Se ejecuta si ninguna de las anteriores es verdadera
}

Ejemplo completo:

#include <stdio.h>

int main() {
int nota = 85;

if (nota >= 90) {
printf("Sobresaliente\n");
} else if (nota >= 70) {
printf("Aprobado\n");
} else {
printf("Reprobado\n");
}

return 0;
}

Explicación:

  • Si la nota es mayor o igual a 90, se imprime «Sobresaliente».
  • Si no, pero es mayor o igual a 70, se imprime «Aprobado».
  • En cualquier otro caso (nota < 70), se imprime «Reprobado».

Consideraciones a tener en cuenta:

  • Paréntesis obligatorios: Siempre debes poner la condición entre paréntesis ().
  • Bloques opcionales: Si el cuerpo del if o else es de una sola línea, las llaves {} son opcionales, pero es buena práctica usarlas siempre para evitar errores.
  • Encadenamiento de if...else: Puedes usar tantos else if como necesites.

Ejemplo práctico adicional

#include <stdio.h>

int main() {
int temperatura;

printf("Introduce la temperatura: ");
scanf("%d", &temperatura);

if (temperatura > 30) {
printf("Hace calor.\n");
} else if (temperatura >= 15) {
printf("Clima templado.\n");
} else if (temperatura >= 0) {
printf("Hace frío.\n");
} else {
printf("¡Temperatura bajo cero!\n");
}

return 0;
}

Explicación: El programa pide al usuario que introduzca una temperatura y luego clasifica el clima dependiendo del valor ingresado, usando múltiples else if

3.2 Bucles en C: for y while

Los bucles permiten repetir un bloque de instrucciones mientras se cumpla una condición. C cuenta con varios tipos de bucles, siendo los más usados:

  • for: Se usa cuando conocemos de antemano cuántas veces queremos repetir algo.
  • while: Se usa cuando no se sabe con certeza cuántas iteraciones serán necesarias, y depende de una condición que puede cambiar en el tiempo.

Bucle for

Sintaxis:

for (inicialización; condición; incremento/decremento) {
// Código que se ejecuta mientras la condición sea verdadera
}
  • Inicialización: se ejecuta una vez al comienzo del bucle.
  • Condición: se evalúa en cada iteración; si es falsa, el bucle termina.
  • Incremento/Decremento: se ejecuta al final de cada iteración.

Veamoslos con un Ejemplo, vamos aimprimir los números del 1 al 5

#include <stdio.h>

int main() {
for (int i = 1; i <= 5; i++) {
printf("Número: %d\n", i);
}
return 0;
}

Explicación:

  • int i = 1: inicializa la variable de control.
  • i <= 5: mientras la condición sea verdadera, el bucle continúa.
  • i++: incrementa i en cada ciclo.

Veamos og

Veamos otro ejemplo: Vamos a hacer un programa pra sumar los primeros 100 números naturales

#include <stdio.h>

int main() {
int suma = 0;

for (int i = 1; i <= 100; i++) {
suma += i;
}

printf("La suma de los primeros 100 números naturales es: %d\n", suma);
return 0;
}

Explicación: Se recorre del 1 al 100 y en cada paso se suma i a la variable suma.

Bucle while

El bucle while evalúa la condición antes de cada iteración. Si la condición es falsa desde el principio, el bloque no se ejecuta ni una sola vez.

Sintaxis:

while (condición) {
// Código que se ejecuta mientras la condición sea verdadera
}

Veamos como contar hasta 5 utilizando un bucle while.

#include <stdio.h>

int main() {
int contador = 1;

while (contador <= 5) {
printf("Contador: %d\n", contador);
contador++;
}

return 0;
}

Explicación:

  • El bucle se ejecuta mientras contador sea menor o igual a 5.
  • contador++ incrementa el valor para evitar un bucle infinito.

Hagamos otro ejemplo para leer números hasta que el usuario introduzca 0

#include <stdio.h>

int main() {
int numero;

printf("Introduce números (0 para salir): ");
scanf("%d", &numero);

while (numero != 0) {
printf("Ingresaste: %d\n", numero);
printf("Introduce otro número (0 para salir): ");
scanf("%d", &numero);
}

printf("Programa terminado.\n");

return 0;
}

Explicación:
El programa sigue pidiendo números al usuario hasta que se introduce un 0. Es un caso típico de uso para while, donde no sabemos cuántas veces se repetirá.

Diferencias clave entre for y while

Característicaforwhile
Uso típicoRepeticiones con un número definidoCondición depende del contexto
Declaración de controlIncluida en una sola líneaDeclaración suele estar separada
LegibilidadMás conciso para ciclos contadosMás flexible pero menos compacto
Puede omitirse todoSí (aunque poco recomendable)No

Precaución: Bucles infinitos

Un bucle infinito ocurre cuando la condición nunca se vuelve falsa. Esto puede causar que el programa no termine o consuma muchos recursos.

Ejemplo de bucle infinito:

while (1) {
// Esto se ejecuta para siempre
}

Este tipo de bucles pueden usarse en sistemas embebidos o juegos, pero deben controlarse cuidadosamente con una condición de salida interna (break), esto lo veremos más adelante.

Bucle do...while en C

El bucle do...while es una variante del bucle while, con una diferencia muy importante: evalúa la condición al final del ciclo, no al principio. Esto garantiza que el código dentro del bucle se ejecute al menos una vez, incluso si la condición es falsa desde el principio.

Sintaxis

do {
// Código a ejecutar
} while (condición);
  • El bloque dentro de do { ... } se ejecuta una primera vez sin verificar la condición.
  • Después de esa ejecución, se evalúa la condición en while (condición).
  • Si la condición es verdadera, se repite el ciclo.
  • Si es falsa, el bucle termina.

Vamos a verlo con un ejemplo

#include <stdio.h>

int main() {
int numero = 0;

do {
printf("Este mensaje se muestra al menos una vez.\n");
} while (numero != 0);

return 0;
}

Explicación:

  • Aunque la condición numero != 0 es falsa desde el inicio, el mensaje se imprime una vez porque el cuerpo del bucle se ejecuta antes de verificar la condición.

Otro ejemplo de como leer hasta que el usuario introduzca una contraseña correcta:

#include <stdio.h>
#include <string.h>

int main() {
char password[20];

do {
printf("Introduce la contraseña: ");
scanf("%19s", password); // Limitamos a 19 caracteres para evitar desbordamiento
} while (strcmp(password, "clave123") != 0);

printf("¡Contraseña correcta!\n");

return 0;
}

Explicación:

  • El programa siempre pide una contraseña al menos una vez.
  • Luego compara con "clave123" mediante la función strcmp().
  • El bucle continúa mientras la contraseña sea incorrecta.

Hagamos otro programa para validar entrada de número entre 1 y 10, sería así:

#include <stdio.h>

int main() {
int numero;

do {
printf("Introduce un número entre 1 y 10: ");
scanf("%d", &numero);
} while (numero < 1 || numero > 10);

printf("Número válido: %d\n", numero);

return 0;
}

Explicación:

  • El bucle asegura que el número ingresado esté en el rango entre 1 y 10.
  • Si el usuario ingresa un número fuera del rango, se repite la petición.

Cuándo usar do...while

Caso típicoJustificación
Mostrar un menú que debe aparecer al menos una vezEl menú necesita mostrarse antes de evaluar
Validar datos de entrada del usuarioSe deben pedir datos al menos una vez
Bucle que depende de eventos que suceden después de una acciónLa condición solo puede saberse tras ejecutarse

Importante

  • Si olvidas actualizar una variable dentro del bucle o la condición nunca se vuelve falsa, puedes generar un bucle infinito.
  • Es imprescindible tener claro qué condición terminará el bucle y asegurar que el usuario o el programa puedan influir en ella.

Comparativa entre bucles

Tipo de bucle¿Evalúa antes?¿Se ejecuta al menos una vez?Ideal para…
for✅ Sí❌ No (si condición es falsa)Iteraciones conocidas
while✅ Sí❌ No (si condición es falsa)Condición controlada externamente
do...while❌ No✅ SíMenús, validaciones, ejecución inicial

Sentencia switch en C

La instrucción switch es una estructura de control de flujo condicional múltiple que permite ejecutar diferentes bloques de código en función del valor de una única expresión. Es especialmente útil cuando necesitas comparar una variable contra varios valores posibles.

Se considera una alternativa más legible al uso de múltiples sentencias if...else if...else cuando todas las condiciones se basan en comparar una misma variable con distintos valores constantes.

Sintaxis general

switch (expresión) {
case valor1:
// Código si expresión == valor1
break;
case valor2:
// Código si expresión == valor2
break;
...
default:
// Código si no se cumple ningún caso anterior
}

Elementos de la sentencia switch:

  • expresión: debe ser de tipo entero (int, char, enum, etc.). No se permiten expresiones float ni double.
  • case valor:: compara el valor de la expresión con valor. Si coinciden, se ejecuta ese bloque.
  • break;: interrumpe la ejecución del switch tras ejecutar un caso. Es fundamental para evitar que se ejecuten los siguientes casos (comportamiento llamado fall-through).
  • default:: es opcional. Se ejecuta si ningún caso anterior coincide con la expresión.

Veamos un ejemplo básico para implementar un menú de opciones.

#include <stdio.h>

int main() {
int opcion;

printf("Menú:\n");
printf("1. Nuevo archivo\n");
printf("2. Abrir archivo\n");
printf("3. Guardar archivo\n");
printf("Selecciona una opción: ");
scanf("%d", &opcion);

switch (opcion) {
case 1:
printf("Has seleccionado: Nuevo archivo\n");
break;
case 2:
printf("Has seleccionado: Abrir archivo\n");
break;
case 3:
printf("Has seleccionado: Guardar archivo\n");
break;
default:
printf("Opción no válida.\n");
}

return 0;
}

Explicación:

  • Según el número introducido por el usuario, se ejecuta un bloque diferente.
  • Si introduce un número fuera del 1 al 3, se activa el default.

Vamos a ver cómo utilizar witch con valores tipo char mediante un sistema que identifique el día de la semana.

#include <stdio.h>

int main() {
char dia;

printf("Introduce una letra (L, M, X, J, V): ");
scanf(" %c", &dia); // Ojo: el espacio antes de %c consume saltos de línea anteriores

switch (dia) {
case 'L':
printf("Lunes\n");
break;
case 'M':
printf("Martes\n");
break;
case 'X':
printf("Miércoles\n");
break;
case 'J':
printf("Jueves\n");
break;
case 'V':
printf("Viernes\n");
break;
default:
printf("Letra inválida\n");
}

return 0;
}

Fall-through: ejecutar varios casos seguidos

Si omites break, la ejecución continuará en los siguientes case, incluso si ya se ha encontrado uno válido. Esto se conoce como fall-through, y aunque generalmente se evita, puede ser útil en ciertos escenarios.

#include <stdio.h>

int main() {
int nota = 5;

switch (nota) {
case 10:
case 9:
printf("Sobresaliente\n");
break;
case 8:
case 7:
printf("Notable\n");
break;
case 6:
printf("Bien\n");
break;
case 5:
printf("Suficiente\n");
break;
default:
printf("Insuficiente\n");
}

return 0;
}

Explicación:

  • Las notas 10 y 9 entran en el primer bloque (Sobresaliente).
  • Las notas 8 y 7 entran en el segundo bloque (Notable).
  • Se reutilizan los mismos bloques para valores similares sin repetir código.

Limitaciones de switch en C

  • Como hemos indicado anteriormente, solo permite evaluar tipos enteros (int, char, enum). No sirve para float, double ni cadenas de texto.
  • No puedes usar rangos (case 1..5: no es válido).
  • La expresión debe evaluarse a un valor constante. No se admiten variables como condiciones de caso.

Resumen comparativo con if...else

Característicaswitchif...else
Tipo de expresiónEntero (int, char, enum)Cualquier expresión lógica
Comparación múltiple✅ Excelente para múltiples valores✅ También sirve, pero menos legible
Uso con rangos o condiciones❌ No es posible✅ Sí
Claridad y legibilidad✅ Alta (si se compara la misma var)Puede volverse complejo con muchos casos

3.3 Control de flujo: break, continue y goto

En C, estas sentencias especiales permiten alterar el flujo natural de ejecución de un programa dentro de bucles o estructuras de control. Aunque deben usarse con responsabilidad para mantener la legibilidad del código, son muy útiles en situaciones específicas.

break

La sentencia break interrumpe la ejecución de un bucle o un switch. Cuando el programa encuentra un break, sale inmediatamente del bucle o del bloque switch que lo contiene.

Usos típicos:

  • Para salir anticipadamente de un bucle for, while o do...while.
  • Para finalizar la ejecución de un caso en una estructura switch.

Veamoslo con un ejemplo dentro de un bucle, vamos a imprimir los número del 1 al 10 pero cuando llegue al 5 salimos sin imprimir el resto.

#include <stdio.h>

int main() {
int i;

for (i = 1; i <= 10; i++) {
if (i == 5) {
break; // Sal del bucle cuando i sea 5
}
printf("i = %d\n", i);
}

return 0;
}

Resultado:

i = 1
i = 2
i = 3
i = 4

Explicación:

  • El bucle termina prematuramente cuando i vale 5.

continue

La sentencia continue salta el resto del código dentro de la iteración actual y continúa con la siguiente iteración del bucle. No interrumpe el bucle, solo omite el código posterior al continue en esa vuelta.

Ejemplo:

#include <stdio.h>

int main() {
int i;

for (i = 1; i <= 5; i++) {
if (i == 3) {
continue; // Salta la iteración cuando i es 3
}
printf("i = %d\n", i);
}

return 0;
}

Resultado:

i = 1
i = 2
i = 4
i = 5

Explicación:

  • Cuando i == 3, se ejecuta continue y se omite el printf, pasando a la siguiente vuelta del bucle.

goto

La sentencia goto salta la ejecución a una etiqueta específica ubicada en otra parte del programa. Es una forma de control incondicional del flujo.

Aunque la tenemos disponible, su uso está desaconsejado porque puede dificultar la lectura y mantenimiento del código si se usa sin cuidado. En la programación actual, se prefiere evitarla y recurrir a funciones o estructuras más claras.

Sintaxis:

goto etiqueta;
// ...
etiqueta:
// Código al que se salta

Quedaría así en un programa:

#include <stdio.h>

int main() {
int i = 1;

while (i <= 10) {
if (i == 5)
goto fin;

printf("i = %d\n", i);
i++;
}

fin:
printf("Has saltado a la etiqueta 'fin'\n");

return 0;
}

Resultado:

i = 1
i = 2
i = 3
i = 4
Has saltado a la etiqueta 'fin'

Explicación:

  • Cuando i == 5, el programa salta a la etiqueta fin, interrumpiendo el bucle.

Cuándo evitar goto

Aunque el lenguaje lo permite, usar goto puede llevarnos a lo que en programación se llama «código espagueti», donde es difícil seguir el flujo lógico. Solo en situaciones muy específicas (como salir de múltiples bucles anidados o manejar errores de forma estructurada en sistemas embebidos) puede estar justificado.

Comparativa

SentenciaSignificadoUso Principal
breakSale inmediatamente del bucle o switchInterrupción anticipada
continueSalta al siguiente ciclo del bucleOmitir una iteración
gotoSalta a una etiqueta específica del códigoControl de flujo incondicional

Conclusión

En este capítulo hemos aprendido uno de los pilares fundamentales de la programación: el control del flujo de ejecución. Mediante estructuras condicionales como if, else y switch, hemos aprendido a tomar decisiones en los programas. Por otro lado, hemos visto que con los bucles for, while y do...while podemos repetir bloques de código tantas veces como lo necesitemos. Además, las sentencias especiales break, continue y goto te permite modificar el flujo estándar de estas estructuras, aunque deben usarse con cautela para mantener un código limpio y fácil de entender. Pasemos a la parte práctica con unos ejercicios.

Ejercicio 1: Números pares del 1 al 20 (usando for y continue)
Enunciado:
Escribe un programa que imprima todos los números pares entre 1 y 20. Utiliza un bucle for y la sentencia continue para omitir los números impares.

Código:

#include <stdio.h>

int main() {
    int i;

    for (i = 1; i <= 20; i++) {
        if (i % 2 != 0) {
            continue;  // Si el número es impar, lo saltamos
        }
        printf("%d ", i);
    }

    return 0;
}

Explicación:

  • El bucle recorre del 1 al 20.
  • Si el número actual no es divisible entre 2 (i % 2 != 0), se ejecuta continue y no se imprime.
  • Solo se imprimen los números pares.
Ejercicio 2: Suma de positivos hasta número negativo (usando while y break)
Enunciado:
Escribe un programa que lea números enteros del usuario y los sume hasta que se introduzca un número negativo. Cuando esto ocurra, el programa debe finalizar mostrando la suma total.

Código:

#include <stdio.h>

int main() {
    int num, suma = 0;

    while (1) {  // Bucle infinito hasta encontrar número negativo
        printf("Introduce un número (negativo para salir): ");
        scanf("%d", &num);

        if (num < 0) {
            break;  // Salir si el número es negativo
        }

        suma += num;
    }

    printf("La suma total es: %d\n", suma);

    return 0;
}

Explicación:

  • Se utiliza un bucle while (1) para repetir indefinidamente.
  • Si el usuario introduce un número negativo, se ejecuta break y se finaliza el bucle.
  • Se acumulan los números positivos en la variable suma.
Ejercicio 3: Menú de operaciones con switch
Enunciado:

Escribe un programa que presente un menú al usuario con tres opciones: sumar dos números, restar dos números o salir. Según la opción elegida, el programa debe realizar la operación correspondiente usando switch.

Código:

#include <stdio.h>

int main() {
    int opcion, a, b;

    printf("Menú de operaciones:\n");
    printf("1. Sumar dos números\n");
    printf("2. Restar dos números\n");
    printf("3. Salir\n");
    printf("Elige una opción: ");
    scanf("%d", &opcion);

    switch (opcion) {
        case 1:
            printf("Introduce dos números: ");
            scanf("%d %d", &a, &b);
            printf("Resultado: %d\n", a + b);
            break;
        case 2:
            printf("Introduce dos números: ");
            scanf("%d %d", &a, &b);
            printf("Resultado: %d\n", a - b);
            break;
        case 3:
            printf("Saliendo del programa...\n");
            break;
        default:
            printf("Opción no válida\n");
    }

    return 0;
}

Explicación:

  • Se usa un switch para ejecutar una operación distinta según la opción ingresada.
  • Las opciones válidas son 1 (suma), 2 (resta) y 3 (salir).
  • Se manejan errores con default si el usuario introduce una opción no válida.
Logo C++

Bibliografía del tutorial de C/C++.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *