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:
Compilador C11: GCC 9+ o Clang 11+ configurado con flags
-Wall -Wextra -Werror -pedantic -std=c11.Entorno POSIX: Linux o WSL con utilidades estándar y verificación estática.
Herramientas de Verificación: Valgrind (memcheck) y AddressSanitizer (
-fsanitize=address,undefined) para garantizar la ausencia de lecturas fuera de rango en tablas de enumeración.Conocimientos Previos: Creación de alias mediante
typedef, enumeraciones (enum), convención institucional del sufijo_ty sentenciasswitchexhaustivas condefault.
Objetivos Pedagógicos y Competencias (Taxonomía de Bloom)¶
Nivel 2 (Comprensión): Diferenciar tipos primitivos de alias semánticos de dominio y mapeo entero de enums.
Nivel 3 (Aplicación): Implementar tipos de datos legibles, traductores enum a cadena inmutable y clasificadores de estado en C11.
Nivel 4 (Análisis): Evaluar el tratamiento defensivo de valores fuera de rango y la seguridad de tipos.
Andamiaje Progresivo: Ejercicios andamiados con contratos formales (precondiciones/postcondiciones), tablas de vectores de prueba y suites ejecutables con
assert().
Capítulos de Apunte Correspondientes¶
Cuestiones de Estilo Aplicables¶
Nombres de tipos: Por convención de cátedra (0x2001h: Las funciones deben usar cláusulas de guarda y retornos anticipados para reducir la anidación profunda), todo tipo definido con
typedefdebe llevar el sufijo_t(ej.dia_semana_t).Validación defensiva: Validar rangos en
switchincluyendo siempre la cláusuladefaultpara manejar valores inesperados.Aserciones: Utilizar
<assert.h>para aserciones invariantes en suites de verificación.
Definición de Alias de Tipos¶
Ejercicio 2.10.01 - Clasificación de Días de la Semana con Enums ⭐⭐☆☆☆¶
Solution to Exercise enums-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86#include <assert.h> #include <stdbool.h> #include <string.h> typedef enum { LUNES = 0, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO, DIA_INVALIDO } dia_semana_t; typedef enum { DIA_LABORAL, FIN_DE_SEMANA, ERROR_DIA_INVALIDO } tipo_dia_t; tipo_dia_t clasificar_dia(dia_semana_t dia) { switch (dia) { case LUNES: case MARTES: case MIERCOLES: case JUEVES: case VIERNES: return DIA_LABORAL; case SABADO: case DOMINGO: return FIN_DE_SEMANA; default: return ERROR_DIA_INVALIDO; } } const char *dia_a_string(dia_semana_t dia) { static const char *const nombres[] = { "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo" }; if (dia < LUNES || dia >= DIA_INVALIDO) { return "Día inválido"; } return nombres[dia]; } int main(void) { // Casos normales días laborales assert(clasificar_dia(LUNES) == DIA_LABORAL); assert(strcmp(dia_a_string(LUNES), "Lunes") == 0); assert(clasificar_dia(MIERCOLES) == DIA_LABORAL); assert(strcmp(dia_a_string(MIERCOLES), "Miércoles") == 0); assert(clasificar_dia(VIERNES) == DIA_LABORAL); assert(strcmp(dia_a_string(VIERNES), "Viernes") == 0); // Casos normales fin de semana assert(clasificar_dia(SABADO) == FIN_DE_SEMANA); assert(strcmp(dia_a_string(SABADO), "Sábado") == 0); assert(clasificar_dia(DOMINGO) == FIN_DE_SEMANA); assert(strcmp(dia_a_string(DOMINGO), "Domingo") == 0); // Casos de error y fuera de rango assert(clasificar_dia(DIA_INVALIDO) == ERROR_DIA_INVALIDO); assert(strcmp(dia_a_string(DIA_INVALIDO), "Día inválido") == 0); assert(clasificar_dia((dia_semana_t)-1) == ERROR_DIA_INVALIDO); assert(strcmp(dia_a_string((dia_semana_t)-1), "Día inválido") == 0); assert(clasificar_dia((dia_semana_t)99) == ERROR_DIA_INVALIDO); assert(strcmp(dia_a_string((dia_semana_t)99), "Día inválido") == 0); return 0; }
Ejercicio 2.10.02 - Distancia Manhattan con Alias de Estructura ⭐⭐☆☆☆¶
---
(ej_b2_c10_03)=
### Ejercicio 2.10.03 - Aritmética de Números Complejos con Alias de Tipos ⭐⭐⭐☆☆
:::{exercise}
:label: alias_numeros_complejos
Definí un tipo con alias `complejo_t` para representar números complejos con componentes flotantes de doble precisión (`real` e `imag`).
Implementá funciones puras para sumar y multiplicar dos números complejos:
- $(a + bi) + (c + di) = (a + c) + (b + d)i$
- $(a + bi) \times (c + di) = (ac - bd) + (ad + bc)i$
```c
typedef struct {
double real;
double imag;
} complejo_t;
complejo_t complejo_sumar(complejo_t c1, complejo_t c2);
complejo_t complejo_multiplicar(complejo_t c1, complejo_t c2);
```
#### Contrato de las Funciones
- **Precondiciones:** Componentes numéricas finitas.
- **Postcondiciones:** Retornan por valor una nueva estructura `complejo_t` con el resultado exacto.
#### Tabla de Vectores de Prueba
| Tipo de Caso | $C_1$ | $C_2$ | Suma Esperada | Producto Esperado | Justificación Técnica |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Normal** | $3 + 2i$ | $1 + 4i$ | $4 + 6i$ | $(3 - 8) + (12 + 2)i = -5 + 14i$ | Aritmética compleja estándar |
| **Elemento Neutro**| $5 - 7i$ | $1 + 0i$ | $6 - 7i$ | $5 - 7i$ | Neutro del producto |
| **Complejo Puro**| $0 + 1i$ | $0 + 1i$ | $0 + 2i$ | $-1 + 0i$ | Propiedad $i^2 = -1$ |
Solution to alias_numeros_complejos
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55#include <assert.h> #include <math.h> #include <stdbool.h> #define EPSILON 1e-9 typedef struct { double real; double imag; } complejo_t; complejo_t complejo_sumar(complejo_t c1, complejo_t c2) { complejo_t res; res.real = c1.real + c2.real; res.imag = c1.imag + c2.imag; return res; } complejo_t complejo_multiplicar(complejo_t c1, complejo_t c2) { complejo_t res; res.real = (c1.real * c2.real) - (c1.imag * c2.imag); res.imag = (c1.real * c2.imag) + (c1.imag * c2.real); return res; } static bool son_iguales(complejo_t a, complejo_t b) { return fabs(a.real - b.real) < EPSILON && fabs(a.imag - b.imag) < EPSILON; } int main(void) { complejo_t c1 = {3.0, 2.0}; complejo_t c2 = {1.0, 4.0}; complejo_t suma = complejo_sumar(c1, c2); assert(son_iguales(suma, (complejo_t){4.0, 6.0})); complejo_t prod = complejo_multiplicar(c1, c2); assert(son_iguales(prod, (complejo_t){-5.0, 14.0})); // Neutro complejo_t neutro = {1.0, 0.0}; complejo_t c3 = {5.0, -7.0}; assert(son_iguales(complejo_multiplicar(c3, neutro), c3)); // i * i = -1 complejo_t i_puro = {0.0, 1.0}; assert(son_iguales(complejo_multiplicar(i_puro, i_puro), (complejo_t){-1.0, 0.0})); return 0; }
Ejercicio 2.10.04 - Álgebra Vectorial 3D con Alias de Tipos ⭐⭐⭐☆☆¶
Solution to Exercise alias-4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60#include <stdio.h> #include <math.h> #include <stdbool.h> #include <assert.h> #define EPSILON 1e-7 typedef struct { double x; double y; double z; } vector3d_t; double vector3d_producto_punto(vector3d_t a, vector3d_t b) { return (a.x * b.x) + (a.y * b.y) + (a.z * b.z); } vector3d_t vector3d_producto_cruz(vector3d_t a, vector3d_t b) { vector3d_t res; res.x = (a.y * b.z) - (a.z * b.y); res.y = (a.z * b.x) - (a.x * b.z); res.z = (a.x * b.y) - (a.y * b.x); return res; } double vector3d_norma(vector3d_t v) { return sqrt(vector3d_producto_punto(v, v)); } static bool vec_iguales(vector3d_t a, vector3d_t b) { return fabs(a.x - b.x) < EPSILON && fabs(a.y - b.y) < EPSILON && fabs(a.z - b.z) < EPSILON; } int main(void) { vector3d_t v1 = {1.0, 2.0, 3.0}; vector3d_t v2 = {4.0, -5.0, 6.0}; // 1. Producto punto double dot = vector3d_producto_punto(v1, v2); assert(fabs(dot - 12.0) < EPSILON); // 2. Producto cruz i x j = k vector3d_t i_hat = {1.0, 0.0, 0.0}; vector3d_t j_hat = {0.0, 1.0, 0.0}; vector3d_t k_esperado = {0.0, 0.0, 1.0}; assert(vec_iguales(vector3d_producto_cruz(i_hat, j_hat), k_esperado)); // 3. Vectores paralelos tienen producto cruz cero vector3d_t colineal = {2.0, 4.0, 6.0}; vector3d_t cero = {0.0, 0.0, 0.0}; assert(vec_iguales(vector3d_producto_cruz(v1, colineal), cero)); // 4. Norma vector3d_t v_norma = {0.0, 3.0, 4.0}; assert(fabs(vector3d_norma(v_norma) - 5.0) < EPSILON); return 0; }