Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Ejercicios: Control de Flujo

Problemas y soluciones sobre lazos y condicionales en C

Universidad Nacional de Río Negro

Prerrequisitos y Entorno de Ejecución Requerido

Para compilar y verificar las soluciones de este módulo bajo el estándar C11 estricto de cátedra, se requiere:

Objetivos Pedagógicos y Competencias (Taxonomía de Bloom)

Capítulos de Apunte Correspondientes

Cuestiones de Estilo Aplicables


Estructuras Condicionales

Ejercicio 1.03b.01 - Condición de Aprobación ⭐⭐☆☆☆

```c #include <stdio.h> #include <string.h> #include <assert.h> const char *evaluar_condicion_aprobacion(int nota) { if (nota >= 6) { return "Promociona"; } else if (nota >= 4) { return "Aprueba"; } else { return "Desaprueba"; } } int main(void) { assert(strcmp(evaluar_condicion_aprobacion(10), "Promociona") == 0); assert(strcmp(evaluar_condicion_aprobacion(6), "Promociona") == 0); assert(strcmp(evaluar_condicion_aprobacion(5), "Aprueba") == 0); assert(strcmp(evaluar_condicion_aprobacion(4), "Aprueba") == 0); assert(strcmp(evaluar_condicion_aprobacion(3), "Desaprueba") == 0); assert(strcmp(evaluar_condicion_aprobacion(0), "Desaprueba") == 0); return 0; } ```

---

## Estructuras de Repetición (Lazos)

(ej_b1_c03b_02)=
### Ejercicio 1.03b.02 - Cuenta descendente ⭐⭐☆☆☆

:::{exercise}
:label: lazo_while 
:enumerator: while-1

Implementá una función `void cuenta_descendente(int inicio, int fin, int *salida, size_t cap)` que genere la secuencia decreciente desde `inicio` hasta `fin` paso unitario en el arreglo `salida`.

**Nivel de Bloom:** Nivel 3 (Aplicación).  
**Conceptos requeridos:** Lazo `while`, condición de corte (`i >= fin`), decremento ordenado y límites de arreglo.  
**Techo conceptual:** Prohibido el uso de lazos infinitos con `break`.

#### Contrato de la Función
- **Firma:** `size_t cuenta_descendente(int inicio, int fin, int *salida, size_t cap);`
- **Precondiciones:** `salida != NULL`, `cap >= (size_t)(inicio - fin + 1)` cuando `inicio >= fin`.
#### Tabla de Vectores de Prueba Obligatorios

| Caso de Prueba | Entrada (`inicio`, `fin`) | Capacidad | Elementos Generados | Secuencia Resultante | Justificación Técnica |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Cuenta Estándar** | `10, 1` | `10` | `10` | `[10, 9, ..., 1]` | 10 iteraciones decrecientes |
| **Paso Unitario** | `5, 5` | `1` | `1` | `[5]` | Caso base inicio igual a fin |
| **Rango Invertido** | `1, 5` | `5` | `0` | `[]` | Condición falsa inmediata |
```{code-block} c :linenos: #include <stdio.h> #include <stddef.h> #include <assert.h> size_t cuenta_descendente(int inicio, int fin, int *salida, size_t cap) { if (salida == NULL || inicio < fin) { return 0; } size_t count = 0; int i = inicio; while (i >= fin && count < cap) { salida[count] = i; count++; i--; } return count; } int main(void) { int buf[10] = {0}; size_t n = cuenta_descendente(10, 1, buf, 10); assert(n == 10); assert(buf[0] == 10); assert(buf[9] == 1); int uno[1] = {0}; assert(cuenta_descendente(5, 5, uno, 1) == 1); assert(uno[0] == 5); assert(cuenta_descendente(1, 5, buf, 10) == 0); return 0; } ```

(ej_b1_c03b_03)=
### Ejercicio 1.03b.03 - Múltiplos de 3 ⭐⭐☆☆☆

:::{exercise}
:label: lazo_for
:enumerator: for-1

Usá un lazo `for` para mostrar o recolectar los números múltiplos de 3 comprendidos en el rango de 0 a `limite` inclusive dentro de un arreglo.

**Nivel de Bloom:** Nivel 3 (Aplicación).  
**Conceptos requeridos:** Lazo `for`, operador módulo (`%`), incremento de contador y comprobación de divisibilidad.  
**Techo conceptual:** Prohibido el uso de lazos `while` o saltos incondicionales.

#### Contrato de la Función
- **Firma:** `size_t recolectar_multiplos_tres(int limite, int *salida, size_t cap);`
- **Precondiciones:** `salida != NULL`, `limite >= 0`.
- **Postcondiciones:** Almacena los múltiplos de 3 en `[0, limite]` dentro de `salida` sin desbordar `cap` y retorna la cantidad de elementos almacenados.

#### Tabla de Vectores de Prueba Obligatorios

| Caso de Prueba | Límite Máximo | Capacidad Buffer | Cantidad Retornada | Secuencia Almacenada | Justificación Técnica |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Rango Regular 30** | `30` | `15` | `11` | `[0, 3, 6, ..., 30]` | 11 múltiplos en $[0, 30]$ |
| **Límite Cero** | `0` | `5` | `1` | `[0]` | $0$ es divisible por 3 |
| **Límite No Múltiplo**| `8` | `5` | `3` | `[0, 3, 6]` | Múltiplos menores a 8 |
| **Capacidad Insuficiente** | `30` | `3` | `3` | `[0, 3, 6]` | Truncamiento seguro por cota `cap` |
```{code-block} c :linenos: #include <stdio.h> #include <stddef.h> #include <assert.h> size_t recolectar_multiplos_tres(int limite, int *salida, size_t cap) { if (salida == NULL || cap == 0 || limite < 0) { return 0; } size_t count = 0; for (int i = 0; i <= limite && count < cap; i++) { if (i % 3 == 0) { salida[count] = i; count++; } } return count; } int main(void) { int buf[15] = {0}; size_t n = recolectar_multiplos_tres(30, buf, 15); assert(n == 11); assert(buf[0] == 0); assert(buf[1] == 3); assert(buf[10] == 30); size_t n0 = recolectar_multiplos_tres(0, buf, 5); assert(n0 == 1); assert(buf[0] == 0); size_t n8 = recolectar_multiplos_tres(8, buf, 5); assert(n8 == 3); assert(buf[0] == 0 && buf[1] == 3 && buf[2] == 6); size_t n_trunc = recolectar_multiplos_tres(30, buf, 3); assert(n_trunc == 3); assert(recolectar_multiplos_tres(30, NULL, 10) == 0); return 0; } ```

Ejercicio 1.03b.04 - Verificación de Clave con Límite de Intentos ⭐⭐☆☆☆

```c #include <stdio.h> #include <stdbool.h> #include <assert.h> bool verificar_clave_intentos(const int *intentos, size_t n, int clave_secreta) { if (intentos == NULL || n == 0) { return false; } size_t i = 0; bool concedido = false; do { if (intentos[i] == clave_secreta) { concedido = true; } i++; } while (i < n && !concedido); return concedido; } int main(void) { int intentos_ok[] = {1111, 2222, 1234}; assert(verificar_clave_intentos(intentos_ok, 3, 1234)); int inmediato[] = {1234}; assert(verificar_clave_intentos(inmediato, 1, 1234)); int fallidos[] = {9999, 8888, 7777}; assert(!verificar_clave_intentos(fallidos, 3, 1234)); assert(!verificar_clave_intentos(NULL, 0, 1234)); return 0; } ```

---

## Control de Flujo Seguro

(ej_b1_c03b_05)=
### Ejercicio 1.03b.05 - Refactorización de break ⭐⭐☆☆☆

:::{exercise}
:label: lazo_break
:enumerator: break-1

Modificá el siguiente programa para eliminar la instrucción `break` prohibida por las normas de estilo institucionales ({ref}`0x2001h`), estructurando correctamente la iteración mediante una bandera booleana:

```{code-block} c
:linenos:
#include <stdio.h>
int main()
{
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("valor actual: %d\n", i);
        if (i == 4)
        {
            break;
        }
    }
    return 0;
}
```
<!-- {code-block} c -->

**Nivel de Bloom:** Nivel 3 (Aplicación) y Nivel 4 (Análisis).  
**Conceptos requeridos:** Control de flujo estructurado, variables booleanas (`<stdbool.h>`), condición compuesta de lazo.  
**Techo conceptual:** Prohibido el uso de `break`, `continue` o `goto`.

Ejercicio 1.03b.06 - Refactorización de continue ⭐⭐☆☆☆

Ejercicio 1.03b.07 - Lazo de Clave con Bandera y Timeout ⭐⭐☆☆☆


---
(ejercicio_4_8)=
## Ejercicios de Práctica de Control

(ej_b1_c03b_08)=
### Ejercicio 1.03b.08 - Mayor de dos números reales ⭐⭐☆☆☆

Escribí un programa que solicite dos números reales al usuario y muestre cuál es
el mayor.

:::{hint} Lógica y Consideraciones

Ejercicio 1.03b.09 - Números del 1 al 100 ⭐⭐☆☆☆

Diseñá un programa que imprima en pantalla los números enteros del 1 al 100 utilizando un lazo for.

Ejercicio 1.03b.10 - Suma de pares del 1 al 100 ⭐⭐☆☆☆

Desarrollá un algoritmo que sume los números pares comprendidos en el rango del 1 al 100 inclusive.

Ejercicio 1.03b.11 - Verificación de número primo ⭐⭐☆☆☆

Escribí un programa que solicite un número entero positivo e indique si es un número primo (divisible únicamente por 1 y por sí mismo).

Ejercicio 1.03b.12 - Estado de aprobación de calificación ⭐⭐⭐☆☆

Escribí un programa que pida una calificación (0 a 10) e indique si el estudiante aprobó (calificación mayor o igual a 4).

Ejercicio 1.03b.13 - Contraseña de caracteres iterativa ⭐⭐☆☆☆

Escribí un programa que solicite repetidamente una contraseña de caracteres al usuario hasta que coincida con un valor establecido de acceso seguro.

Ejercicio 1.03b.14 - Contar del 1 al 10 ⭐☆☆☆☆

Mostrá los números del 1 al 10 usando un lazo for.

Orientación:


Ejercicio 1.03b.15 - Suma de N Números ⭐☆☆☆☆

Leé un número N y calculá la suma de los primeros N números naturales.

Orientación:


Ejercicio 1.03b.16 - Tabla de Multiplicar ⭐⭐☆☆☆

Mostrá la tabla de multiplicar de un número ingresado por el usuario (1 a 10).

Orientación:


Ejercicio 1.03b.17 - Factorial con While ⭐⭐☆☆☆

Calculá el factorial de N usando un lazo while.

Orientación:


Ejercicio 1.03b.18 - Números Pares en Rango ⭐⭐☆☆☆

Mostrá todos los números pares entre dos valores ingresados.

Orientación:


Ejercicio 1.03b.19 - Suma hasta Cero ⭐⭐☆☆☆

Leé números enteros hasta que el usuario ingrese 0, luego mostrá la suma total.

Orientación:


Ejercicio 1.03b.20 - Validación de Entrada ⭐⭐⭐☆☆

Leé un número entre 1 y 100. Si está fuera de rango, pedí nuevamente hasta que sea válido.

Orientación:


Ejercicio 1.03b.21 - Contar Dígitos ⭐⭐⭐☆☆

Contá cuántos dígitos tiene un número entero.

Orientación:


Ejercicio 1.03b.22 - Número Primo ⭐⭐⭐☆☆

Determiná si un número es primo probando divisibilidad.

Orientación:


Ejercicio 1.03b.23 - Secuencia de Fibonacci ⭐⭐⭐☆☆

Generá los primeros N números de Fibonacci.

Orientación:


Ejercicio 1.03b.24 - Búsqueda en Array ⭐⭐⭐☆☆

Buscá un valor en un array. Si lo encontrás, mostrá su posición y break.

Orientación:


Ejercicio 1.03b.25 - Validador de Fechas Gregorianas y Regla de Bisiestos ⭐⭐⭐☆☆


Ejercicio 1.03b.26 - Mayor y Menor de N Números ⭐⭐⭐☆☆

Leé N números y encontrá el mayor y menor.

Orientación:


Ejercicio 1.03b.27 - Invertir un Número ⭐⭐⭐⭐☆

Invertí los dígitos de un número (ej: 1234 → 4321).

Orientación:


Ejercicio 1.03b.28 - Números Perfectos ⭐⭐⭐⭐☆

Encontrá todos los números perfectos hasta N. Un número es perfecto si la suma de sus divisores (excluyéndolo) es igual al número.

Ejemplo: 6 = 1 + 2 + 3

Orientación:


Ejercicio 1.03b.29 - Patrón de Asteriscos - Triángulo ⭐⭐⭐⭐☆

Dibujá un triángulo de asteriscos de altura N.

Ejemplo (N=5):

*
**
***
****
*****

Orientación:


Ejercicio 1.03b.30 - Máximo Común Divisor (Euclides) ⭐⭐⭐⭐☆

Implementá el algoritmo de Euclides iterativo para calcular MCD.

Algoritmo:

mientras b != 0:
    temp = b
    b = a % b
    a = temp
retornar a

Orientación:


Ejercicio 1.03b.31 - Número de Armstrong ⭐⭐⭐⭐☆

Determiná si un número es Armstrong (suma de sus dígitos elevados a la cantidad de dígitos igual al número).

Ejemplo: 153 = 1³ + 5³ + 3³ = 153

Orientación:


Ejercicio 1.03b.32 - Simulación de Cajero Automático ⭐⭐⭐⭐⭐

Simulá un cajero con saldo inicial. Menú: depositar, retirar, consultar, salir.

Requisitos:

Orientación:


Ejercicio 1.03b.33 - Criba de Eratóstenes ⭐⭐⭐⭐⭐

Encontrá todos los números primos hasta N usando la Criba de Eratóstenes.

Algoritmo:

  1. Creá array booleano de tamaño N+1, todos en true

  2. Marcá 0 y 1 como no primos

  3. Para cada número i de 2 a √N:

    • Si i es primo (marcado true):

      • Marcá todos sus múltiplos como no primos

  4. Los que quedaron en true son primos

Orientación:


Ejercicios Adicionales de Patrones

Ejercicio 1.03b.34 - Pirámide Centrada ⭐⭐⭐⭐⭐

Dibujá una pirámide centrada de asteriscos.

Ejemplo (N=5):

    *
   ***
  *****
 *******
*********

Orientación:


Ejercicio 1.03b.35 - Rombo ⭐⭐⭐⭐⭐

Dibujá un rombo de asteriscos.

Orientación:


Problemas de Lazos Anidados

Ejercicio 1.03b.36 - Tabla de Multiplicar Completa ⭐⭐⭐⭐☆

Mostrá tabla de multiplicar del 1 al 10 (todas las tablas).

Orientación:


Ejercicio 1.03b.37 - Números Primos en Rango ⭐⭐⭐⭐☆

Mostrá todos los números primos entre A y B.

Orientación:


Problemas de Validación y Control

Ejercicio 1.03b.38 - Juego de Adivinanza Mejorado ⭐⭐⭐⭐⭐

El programa elige un número aleatorio. El usuario tiene máximo 7 intentos.

Orientación:


Notas Finales

Estas consignas cubren todos los aspectos de lazos: for, while, do-while, lazos anidados, control de flujo y validación con repetición.

Ejercicio 1.03b.39 - Mostrar Argumentos ⭐☆☆☆☆

Mostrá todos los argumentos recibidos.

Orientación:

1
2
3
4
5
6
7
8
int main(int argc, char *argv[])
{
    printf("Cantidad de argumentos: %d\n", argc);
    for (int i = 0; i < argc; i++)
    {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
}

Ejercicio 1.03b.40 - Saludo Personalizado ⭐☆☆☆☆

Lee un nombre desde argv y saludá.

Uso: ./saludo Juan

Orientación:


Ejercicio 1.03b.41 - Suma de Dos Números ⭐⭐☆☆☆

Sumá dos números pasados como argumentos.

Uso: ./suma 5 3

Orientación:


Ejercicio 1.03b.42 - Calculadora Simple ⭐⭐⭐☆☆

Implementá calculadora: ./calc <num1> <operador> <num2>

Uso: ./calc 10 + 5

Orientación:


Ejercicio 1.03b.43 - Flags Booleanos ⭐⭐⭐☆☆

Procesá flags opcionales -v (verbose) y -h (help).

Uso: ./programa -v archivo.txt

Orientación:


Ejercicio 1.03b.44 - Concatenar Argumentos ⭐⭐☆☆☆

Concatená todos los argumentos (excepto argv[0]) en un string.

Uso: ./concat Hola mundo desde C Salida: Hola mundo desde C

Orientación:


Ejercicio 1.03b.45 - Conversor de Temperatura ⭐⭐⭐☆☆

Convertí temperatura según flags.

Uso: ./temp -c 100 (Celsius a Fahrenheit) Uso: ./temp -f 212 (Fahrenheit a Celsius)

Orientación:


Ejercicio 1.03b.46 - Procesamiento de Texto desde Consola ⭐⭐⭐☆☆

Leé texto carácter por carácter desde la entrada estándar (stdin) hasta encontrar EOF y mostralo en mayúsculas.

Orientación:


Ejercicio 1.03b.47 - Flag con Valor ⭐⭐⭐⭐☆

Procesá flag que requiere un valor: -n <cantidad>

Uso: ./programa -n 10 archivo.txt

Orientación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for (int i = 1; i < argc; i++)
{
    if (strcmp(argv[i], "-n") == 0)
    {
        if (i + 1 < argc)
        {
            cantidad = atoi(argv[++i]); // Incrementa i
        }
        else
        {
            fprintf(stderr, "Flag -n requiere valor\n");
        }
    }
}

Ejercicio 1.03b.48 - Múltiples Flags ⭐⭐⭐⭐☆

Implementá programa con varios flags: -v (verbose), -o <salida>, -n <num>

Uso: ./programa -v -o salida.txt -n 100 entrada.txt

Orientación:


Ejercicio 1.03b.49 - Validación de Argumentos ⭐⭐⭐☆☆

Validá que números sean realmente números.

Orientación:

1
2
3
4
5
6
7
char *endptr;
long num = strtol(argv[1], &endptr, 10);
if (*endptr != '\0')
{
    fprintf(stderr, "Error: '%s' no es un número válido\n", argv[1]);
    return 1;
}

Ejercicio 1.03b.50 - Ayuda Automática ⭐⭐⭐☆☆

Mostrá ayuda si se pasa -h o --help, o si argumentos son incorrectos.

Orientación:

1
2
3
4
5
6
7
8
9
10
11
12
13
void mostrar_ayuda(const char *programa)
{
    printf("Uso: %s [opciones] archivo\n", programa);
    printf("Opciones:\n");
    printf("  -h, --help    Mostrar esta ayuda\n");
    printf("  -v            Modo verbose\n");
    printf("  -o <archivo>  Archivo de salida\n");
}
if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
{
    mostrar_ayuda(argv[0]);
    return 0;
}

Ejercicio 1.03b.51 - Grep Simplificado ⭐⭐⭐⭐☆

Buscá patrón en archivo(s).

Uso: ./grep "patron" archivo1.txt archivo2.txt

Orientación:


Ejercicio 1.03b.52 - Wc (Word Count) Simplificado ⭐⭐⭐⭐☆

Contá líneas, palabras y caracteres de archivos.

Uso: ./wc [-l] [-w] [-c] archivo(s)

Flags:

Orientación:


Ejercicio 1.03b.53 - Sort con Opciones ⭐⭐⭐⭐⭐

Ordená líneas de archivo con opciones.

Uso: ./sort [-r] [-n] archivo.txt

Flags:

Orientación:


Ejercicio 1.03b.54 - Procesamiento de Lote ⭐⭐⭐⭐⭐

Aplicá operación a múltiples archivos.

Uso: ./batch -op <operacion> archivo1 archivo2 ...

Operaciones: upper, lower, reverse, count

Orientación:


Ejercicio 1.03b.55 - Configuración desde Archivo y Args ⭐⭐⭐⭐⭐

Leé configuración de archivo, permitiendo override por línea de comandos.

Uso: ./programa -c config.txt -n 50

Orientación:


Ejercicio 1.03b.56 - Pipeline Simulado ⭐⭐⭐⭐⭐

Implementá programa que puede leer de stdin o archivo.

Uso:

Orientación:

1
2
3
4
5
6
7
8
9
FILE *entrada;
if (argc > 1)
{
    entrada = fopen(argv[1], "r");
}
else
{
    entrada = stdin; // Lee de stdin
}

Ejercicio 1.03b.57 - Getopt Simplificado ⭐⭐⭐⭐⭐

Implementá tu propia versión simplificada de getopt para parsear flags.

Orientación:

int getopt_simple(int argc, char *argv[], const char *optstring);

Ejercicio 1.03b.58 - Sistema de Comandos ⭐⭐⭐⭐⭐

Implementá programa con subcomandos estilo Git.

Uso:

Orientación:


Notas Finales

Estas consignas cubren procesamiento de argumentos desde básico hasta sistemas complejos estilo herramientas Unix, esenciales para programas de línea de comandos profesionales.