Prerrequisitos y Entorno Requerido¶
Para compilar y verificar las soluciones de este módulo, se requiere:
Entorno de Compilación: Compilador GCC 9+ o Clang bajo estándar estricto ISO C11 (
-std=c11 -Wall -Wextra -Werror -pedantic).Direccionamiento e Indirección: Dominio del operador de dirección (
&), operador de desreferencia (*), punteros como parámetros de función (pasaje por referencia simulado) y cualificadores de inmutabilidad (const int *).Manejo Defensivo: Validación mandatoria mediante
assert(p != NULL)de la cabecera<assert.h>para prevenir accesos a memoria inválida.
Acerca de¶
Estos ejercicios prácticos y aplicados complementan la teoría de punteros, pasaje por referencia y aritmética básica de indirección de memoria en C.
Capítulos de Apunte Correspondientes¶
Ejercicio 2.02b.01 - Intercambio de Valores por Referencia ⭐⭐☆☆☆¶
Solution to Exercise punteros-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#include <assert.h> #include <limits.h> #include <stddef.h> void intercambiar(int *a, int *b) { assert(a != NULL); assert(b != NULL); int temporal = *a; *a = *b; *b = temporal; } int main(void) { // Caso normal int x = 10; int y = 20; intercambiar(&x, &y); assert(x == 20 && y == 10); // Caso con negativos int n1 = -5; int n2 = 15; intercambiar(&n1, &n2); assert(n1 == 15 && n2 == -5); // Caso borde ceros int c1 = 0; int c2 = 0; intercambiar(&c1, &c2); assert(c1 == 0 && c2 == 0); // Caso borde aliasing (mismo puntero) int mismo = 42; intercambiar(&mismo, &mismo); assert(mismo == 42); // Caso extremal límites INT int min_val = INT_MIN; int max_val = INT_MAX; intercambiar(&min_val, &max_val); assert(min_val == INT_MAX && max_val == INT_MIN); return 0; }
Ejercicio 2.02b.02 - Búsqueda del Valor Máximo en Arreglo ⭐⭐☆☆☆¶
Solution to Exercise funciones-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#include <assert.h> #include <limits.h> #include <stddef.h> int encontrar_maximo(const int *arreglo, size_t n) { assert(arreglo != NULL); assert(n > 0); int maximo = *arreglo; const int *fin = arreglo + n; for (const int *p = arreglo + 1; p < fin; p++) { if (*p > maximo) { maximo = *p; } } return maximo; } int main(void) { // Caso normal const int arr1[] = {1, 5, 3, 9, 2}; assert(encontrar_maximo(arr1, 5) == 9); // Caso máximo al inicio const int arr2[] = {99, 10, 5}; assert(encontrar_maximo(arr2, 3) == 99); // Caso máximo al final const int arr3[] = {2, 4, 88}; assert(encontrar_maximo(arr3, 3) == 88); // Caso unitario negativo const int arr4[] = {-7}; assert(encontrar_maximo(arr4, 1) == -7); // Caso duplicados const int arr5[] = {4, 4, 4, 4}; assert(encontrar_maximo(arr5, 4) == 4); // Caso negativos extremos const int arr6[] = {INT_MIN, -100, -1}; assert(encontrar_maximo(arr6, 3) == -1); return 0; }
Ejercicio 2.02b.03 - Copia de Cadenas mediante Punteros ⭐⭐⭐☆☆¶
Solution to Exercise funciones-2
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#include <assert.h> #include <stddef.h> #include <string.h> void copiar_cadena(char *destino, const char *origen) { assert(destino != NULL); assert(origen != NULL); while (*origen != '\0') { *destino = *origen; destino++; origen++; } *destino = '\0'; } int main(void) { char buffer[64]; // Caso normal copiar_cadena(buffer, "Hola C11"); assert(strcmp(buffer, "Hola C11") == 0); // Caso cadena vacía copiar_cadena(buffer, ""); assert(buffer[0] == '\0'); assert(strcmp(buffer, "") == 0); // Caso un caracter copiar_cadena(buffer, "Z"); assert(strcmp(buffer, "Z") == 0); // Caso puntuación copiar_cadena(buffer, "puntero -> dato;"); assert(strcmp(buffer, "puntero -> dato;") == 0); return 0; }
Ejercicio 2.02b.04 - Suma de Arreglo con Rango Semiapierto de Punteros ⭐⭐⭐☆☆¶
Solution to Exercise funciones-3
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#include <assert.h> #include <stddef.h> int sumar_arreglo(const int *inicio, const int *fin) { assert(inicio != NULL); assert(fin != NULL); assert(inicio <= fin); int suma = 0; for (const int *p = inicio; p < fin; p++) { suma += *p; } return suma; } int main(void) { int arr[] = {1, 2, 3, 4, 5}; // Caso normal assert(sumar_arreglo(arr, arr + 5) == 15); // Caso rango vacío (longitud 0) assert(sumar_arreglo(arr, arr) == 0); // Caso un elemento assert(sumar_arreglo(arr + 2, arr + 3) == 3); // Caso opuestos int opuestos[] = {10, -10, 25, -25}; assert(sumar_arreglo(opuestos, opuestos + 4) == 0); // Caso subrango interno int sub[] = {10, 20, 30, 40}; assert(sumar_arreglo(sub + 1, sub + 3) == 50); return 0; }
Ejercicio 2.02b.05 - Inversión In-Place con Dos Punteros Convergentes ⭐⭐⭐☆☆¶
Solution to Exercise punteros-2
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#include <assert.h> #include <stddef.h> void invertir_arreglo(int *arreglo, size_t n) { assert(arreglo != NULL); if (n < 2) { return; } int *inicio = arreglo; int *fin = arreglo + n - 1; while (inicio < fin) { int temp = *inicio; *inicio = *fin; *fin = temp; inicio++; fin--; } } int main(void) { // Caso tamaño impar int imp[] = {1, 2, 3, 4, 5}; invertir_arreglo(imp, 5); assert(imp[0] == 5 && imp[1] == 4 && imp[2] == 3 && imp[3] == 2 && imp[4] == 1); // Caso tamaño par int par[] = {10, 20, 30, 40}; invertir_arreglo(par, 4); assert(par[0] == 40 && par[1] == 30 && par[2] == 20 && par[3] == 10); // Caso unitario int unit[] = {99}; invertir_arreglo(unit, 1); assert(unit[0] == 99); // Caso vacío (n = 0) int vacio[] = {1}; invertir_arreglo(vacio, 0); assert(vacio[0] == 1); // Caso negativos int neg[] = {-1, 0, 1}; invertir_arreglo(neg, 3); assert(neg[0] == 1 && neg[1] == 0 && neg[2] == -1); return 0; }