1. Ejercicio 1: Estructura Modular
Flashcards
- ¿Qué macros se definen en `senal.h`?
- `UMBRAL_BAJO` y `UMBRAL_ALTO`.
- ¿Qué hace la función `clasificar_rssi`?
- Clasifica la señal RSSI en categorías.
- ¿Qué rango de valores retorna `ajustar_a_decada`?
- De 0 a 9.
- ¿Por qué es importante incluir `senal.h` en `main.c`?
- Para conocer los prototipos de las funciones del módulo `senal`.
Preguntas tipo test
- ¿Cuál es el propósito del archivo `senal.h` en el código proporcionado?
- a) Contener la implementación de las funciones `clasificar_rssi` y `ajustar_a_decada`.
- b) Definir las macros `UMBRAL_BAJO` y `UMBRAL_ALTO`, y los prototipos de las funciones.
- c) Incluir la función principal `main` del programa.
- d) Realizar operaciones de entrada y salida de datos.
Respuesta: b) Definir las macros `UMBRAL_BAJO` y `UMBRAL_ALTO`, y los prototipos de las funciones.. El archivo `senal.h` define las macros `UMBRAL_BAJO` y `UMBRAL_ALTO`, y contiene los prototipos de las funciones `clasificar_rssi` y `ajustar_a_decada`, actuando como la interfaz del módulo.
- ¿Qué hace la función `clasificar_rssi`?
- a) Ajusta el valor RSSI a una escala de 0 a 9.
- b) Clasifica el valor RSSI en tres categorías: 0, 1 y 2, según los umbrales definidos.
- c) Convierte el valor RSSI a su valor absoluto.
- d) Calcula la media de una serie de valores RSSI.
Respuesta: b) Clasifica el valor RSSI en tres categorías: 0, 1 y 2, según los umbrales definidos.. La función `clasificar_rssi` clasifica el valor RSSI en tres categorías (0, 1, 2) basándose en los umbrales `UMBRAL_BAJO` y `UMBRAL_ALTO`.
- ¿Cuál es el propósito de la función `ajustar_a_decada`?
- a) Ajustar el valor RSSI a una escala de decibelios.
- b) Convertir el valor RSSI a una representación hexadecimal.
- c) Ajustar el valor RSSI a un nivel entre 0 y 9.
- d) Normalizar el valor RSSI a un rango entre -1 y 1.
Respuesta: c) Ajustar el valor RSSI a un nivel entre 0 y 9.. La función `ajustar_a_decada` ajusta el valor RSSI a un nivel entre 0 y 9 sumándole 100 y dividiendo el resultado por 10, asegurando que el resultado esté dentro de ese rango.
2. Ejercicio 2: Costo de Plan
Flashcards
- ¿Qué archivo define la interfaz de la función `costo_plan`?
- `tarifa.h`
- ¿Qué valor tiene la macro `BASE`?
- 100
- ¿Qué significa el término 'fall-through' en un `switch`?
- La ejecución continúa en el siguiente `case` si no hay un `break`.
- ¿Qué retorna la función `costo_plan` si el valor de `plan` no coincide con ningún `case`?
- 0
Preguntas tipo test
- ¿Qué plan en la función `costo_plan` resulta en la adición de 45 a la tarifa base?
- a) Plan Básico (0)
- b) Plan Pro (1)
- c) Plan Ultra (2)
- d) Plan con valor 7
Respuesta: c) Plan Ultra (2). El Plan Ultra (2) permite la acumulación de `extra += 30` y `extra += 15` debido al fall-through, resultando en un incremento total de 45.
- Si se añade `break;` después de `case 1: extra += 15;`, ¿cuál sería el costo del plan Pro (1)?
- a) 100
- b) 105
- c) 115
- d) 130
Respuesta: c) 115. Con el `break` después del `case 1`, solo se sumaría 15 a la base, resultando en 100 + 15 = 115.
- Si se cambia `BASE` a 150, ¿cuál sería el costo del plan Básico (0)?
- a) 100
- b) 150
- c) 155
- d) 165
Respuesta: c) 155. El plan Básico (0) suma 5 a la base. Si la base es 150, el costo sería 150 + 5 = 155.
3. Ejercicio 3: Flujo de Datos
Flashcards
- ¿Qué hace la función `es_valido(int x)`?
- Verifica si `x` está entre 0 y 100.
- ¿Cuál es el propósito de `actualizar_suma(int suma_actual, int x)`?
- Añade `x` a la `suma_actual` si `x` es válido.
- ¿Qué valor especial se resta a la suma en `actualizar_suma`?
- 1, si x es igual a 0
- ¿Qué función se utiliza para leer la entrada del usuario en `main`?
- `scanf`
Preguntas tipo test
- ¿Qué rango de valores acepta la función `es_valido(int x)`?
- a) De -100 a 100
- b) De 0 a 100
- c) De 0 a 99
- d) Cualquier entero
Respuesta: b) De 0 a 100. La función `es_valido(int x)` retorna verdadero (1) si `x` está entre 0 y 100 (inclusive), y falso (0) en caso contrario. Por lo tanto, acepta valores en el rango de 0 a 100.
- ¿Cuál es el propósito del ajuste especial en `actualizar_suma` cuando `x` es 0?
- a) Incrementar la suma en 1
- b) No modificar la suma
- c) Restar 1 a la suma
- d) Reiniciar la suma a 0
Respuesta: c) Restar 1 a la suma. Dentro de la función `actualizar_suma`, si `x` es igual a 0, se resta 1 a la suma. Este es un ajuste específico para el valor 0, según se indica en el comentario del código.
- ¿Qué valor de retorno de `scanf` causa la terminación del bucle `while` en `main`?
- a) 0
- b) 1
- c) -1
- d) EOF
Respuesta: d) EOF. El bucle `while` en `main` termina cuando `scanf` retorna un valor diferente de 1. En este caso, la condición `x == -999` también causa la terminación del bucle, pero la pregunta se centra en el valor de retorno de `scanf`. `scanf` retorna `EOF` (End Of File) cuando no puede leer más entradas, lo cual también terminaría el bucle.
4. Ejercicio 4: Primer Divisor Propio
Flashcards
- ¿Qué retorna la función `primer_divisor_propio(int n)` si `n <= 3`?
- -1
- ¿Cuál es el propósito de la condición `d * d <= n` en el bucle de `primer_divisor_propio`?
- Optimizar la búsqueda de divisores hasta la raíz cuadrada de `n`.
- Si `primer_divisor_propio(n)` retorna un valor diferente de -1, ¿qué representa ese valor?
- El primer divisor de `n` mayor que 1.
- ¿Qué indica un retorno de -1 de la función `primer_divisor_propio`?
- Que `n` es primo o menor/igual a 3.
Preguntas tipo test
- ¿Qué valor retorna la función `primer_divisor_propio` si el número `n` es menor o igual a 3?
- a) El propio número n.
- b) 0.
- c) -1.
- d) 1.
Respuesta: c) -1.. La función `primer_divisor_propio` retorna -1 si `n` es menor o igual a 3, según la línea 4 del código en `numero.c`: `if(n <=3) return -1;`.
- ¿Cuál es la condición del bucle `for` en la función `primer_divisor_propio`?
- a) d < n
- b) d <= n
- c) d * d < n
- d) d * d <= n
Respuesta: d) d * d <= n. La condición del bucle `for` es `d*d<=n`, lo que optimiza la búsqueda de divisores al no tener que iterar hasta `n`, sino hasta la raíz cuadrada de `n`.
- Si `primer_divisor_propio(n)` retorna `d`, ¿qué se puede afirmar con certeza?
- a) `d` es un número primo.
- b) `d` es el divisor más grande de `n`.
- c) `d` es un divisor de `n` y es mayor que 1.
- d) `d` es igual a la raíz cuadrada de `n`.
Respuesta: c) `d` es un divisor de `n` y es mayor que 1.. Si la función retorna `d`, significa que encontró un divisor de `n` que es mayor que 1, cumpliendo la condición `n % d == 0` dentro del bucle.
5. Ejercicio 5: Histéresis
Flashcards
- ¿Qué hace la función `siguiente_estado`?
- Determina el siguiente estado (encendido o apagado) basado en la medida `m`, los umbrales y el estado actual.
- ¿Qué dos umbrales se utilizan en el ejercicio de histéresis?
- `umbral_on` (umbral de encendido) y `umbral_off` (umbral de apagado).
- ¿Cuándo retorna 1 la función `siguiente_estado`?
- Cuando el sistema está apagado y `m` es mayor o igual que `umbral_on`.
- ¿Cuándo retorna 0 la función `siguiente_estado`?
- Cuando el sistema está encendido y `m` es menor o igual que `umbral_off`.
Preguntas tipo test
- ¿Qué condición debe cumplirse para que `siguiente_estado` retorne 1, asumiendo que `encendido` es inicialmente 0?
- a) `m` debe ser menor o igual que `umbral_off`
- b) `m` debe ser mayor o igual que `umbral_on`
- c) `m` debe estar entre `umbral_on` y `umbral_off`
- d) `m` debe ser igual a 0
Respuesta: b) `m` debe ser mayor o igual que `umbral_on`. La función `siguiente_estado` retorna 1 (encendido) solo si el sistema está apagado (`!encendido`) y la medida `m` es mayor o igual al umbral de encendido (`umbral_on`).
- Si `encendido` es 1 y `m` es 3.5, ¿qué retornará la función `siguiente_estado` con `umbral_on` de 6.0 y `umbral_off` de 4.0?
- a) 1
- b) 0
- c) Depende del valor anterior de `m`
- d) Error
Respuesta: b) 0. Dado que `encendido` es 1 y `m` (3.5) es menor o igual que `umbral_off` (4.0), la función retornará 0, apagando el sistema debido a la histéresis.
- ¿Cuál es el propósito principal de usar dos umbrales (`umbral_on` y `umbral_off`) en el código de histéresis?
- a) Reducir el consumo de energía
- b) Evitar fluctuaciones rápidas en el estado del sistema
- c) Aumentar la precisión de las mediciones
- d) Simplificar el código
Respuesta: b) Evitar fluctuaciones rápidas en el estado del sistema. La histéresis, al usar dos umbrales, evita que el sistema cambie de estado rápidamente debido a pequeñas fluctuaciones en la entrada, proporcionando una mayor estabilidad.
6. Ejercicio 6: Ámbito de Fichero
Flashcards
- ¿Qué significa que una variable tenga ámbito de fichero en C?
- Que la variable es visible y accesible solo dentro del archivo en el que se declara.
- ¿Qué palabra clave se utiliza para dar a una variable ámbito de fichero en C?
- static
- ¿Qué es el sombreado de variables (shadowing)?
- Ocurre cuando una variable local tiene el mismo nombre que una variable en un ámbito exterior, ocultando la variable exterior dentro del ámbito local.
- ¿Por qué es útil el ámbito de fichero?
- Ayuda a encapsular datos y a evitar conflictos de nombres entre variables en diferentes archivos.
Preguntas tipo test
- ¿Cuál es el ámbito de la variable 'contador' definida como 'static int contador = 0;' en el archivo metricas.c?
- a) Global, accesible desde cualquier archivo del programa.
- b) De fichero, accesible solo dentro del archivo metricas.c.
- c) De bloque, accesible solo dentro de la función en la que se define.
- d) Local, accesible solo dentro de la función main.
Respuesta: b) De fichero, accesible solo dentro del archivo metricas.c.. El especificador 'static' en la declaración de la variable 'contador' en metricas.c le da ámbito de fichero, lo que significa que solo es visible y accesible dentro de ese archivo. Esto impide que otros archivos, como main.c, accedan directamente a esta variable.
- Si se elimina la palabra clave 'static' de la declaración de 'contador' en metricas.c, ¿qué ocurriría?
- a) Se produciría un error de compilación.
- b) La variable 'contador' sería accesible desde main.c.
- c) El programa se ejecutaría de la misma manera.
- d) La variable 'contador' se reiniciaría en cada llamada a la función 'incrementar'.
Respuesta: b) La variable 'contador' sería accesible desde main.c.. Si se elimina 'static', la variable 'contador' tendría ámbito externo y podría ser accedida o modificada desde otros archivos, como 'main.c', siempre y cuando se declare externamente en esos archivos.
- Dentro del bloque con llaves en main.c, se declara una variable local llamada 'contador' inicializada a 1000. ¿Cómo afecta esta variable a la variable 'contador' definida en metricas.c?
- a) Modifica directamente el valor de la variable 'contador' en metricas.c.
- b) No tiene ningún efecto sobre la variable 'contador' en metricas.c.
- c) Causa un error de compilación debido a la redefinición de la variable.
- d) Crea una copia de la variable 'contador' de metricas.c dentro del bloque.
Respuesta: b) No tiene ningún efecto sobre la variable 'contador' en metricas.c.. La variable 'contador' declarada dentro del bloque en 'main.c' es una variable local que sombrea (shadowing) la variable 'contador' del ámbito exterior (en este caso, la variable global del mismo nombre si no fuera static). No modifica la variable 'contador' en 'metricas.c', ya que son variables distintas con ámbitos diferentes.
7. Ejercicio 7: Lectura de Entero en Rango
Flashcards
- ¿Qué valor retorna la función `leer_entero_en_rango` si se alcanza el fin de archivo (EOF)?
- `VALOR_ERROR`
- ¿Cuál es la función del bucle `while(1)` en `leer_entero_en_rango`?
- Reintentar la lectura hasta obtener un valor válido o EOF.
- ¿Qué hace `scanf` cuando retorna `EOF`?
- Indica que no hay más datos para leer.
- ¿Qué ocurre si el valor leído está fuera del rango en `leer_entero_en_rango`?
- Se muestra un mensaje y se solicita un nuevo valor.
Preguntas tipo test
- ¿Qué valor de retorno de la función `leer_entero_en_rango` indica que se ha alcanzado el fin del archivo (EOF)?
- a) 0
- b) 1
- c) VALOR_ERROR
- d) El valor máximo del rango
Respuesta: c) VALOR_ERROR. La macro `VALOR_ERROR` se define como -1 y se retorna cuando se detecta el fin de archivo (EOF) en la entrada.
- ¿Cuál es el propósito del bucle `while(1)` en la función `leer_entero_en_rango`?
- a) Leer un entero solo una vez
- b) Asegurar que la función siempre retorne un valor
- c) Reintentar la lectura hasta obtener un valor válido o detectar EOF
- d) Validar el rango del entero leído
Respuesta: c) Reintentar la lectura hasta obtener un valor válido o detectar EOF. El bucle `while(1)` permite reintentar la lectura de un entero hasta que se cumpla una de las condiciones de salida: leer un valor válido dentro del rango o detectar el fin de archivo (EOF).
- Si `scanf` retorna `EOF` en la función `leer_entero_en_rango`, ¿qué debe hacer la función?
- a) Retornar el valor leído hasta el momento
- b) Mostrar un mensaje de error y continuar
- c) Retornar `VALOR_ERROR` inmediatamente
- d) Solicitar un nuevo valor al usuario
Respuesta: c) Retornar `VALOR_ERROR` inmediatamente. Cuando `scanf` retorna `EOF`, indica que no hay más datos para leer, por lo tanto, la función debe retornar `VALOR_ERROR` inmediatamente para indicar esta condición.
8. Ejercicio 8: Máximo Común Divisor y Mínimo Común Múltiplo
Flashcards
- ¿Qué calcula el algoritmo de Euclides?
- El Máximo Común Divisor (MCD)
- Propiedad fundamental del algoritmo de Euclides
- MCD(a, b) = MCD(b, a % b)
- ¿Cuál es la condición de parada en el algoritmo de Euclides?
- Cuando b es igual a 0
- Fórmula para calcular el MCM usando el MCD
- MCM(a, b) = (a * b) / MCD(a, b)
Preguntas tipo test
- ¿Cuál es la propiedad fundamental del algoritmo de Euclides para calcular el MCD?
- a) MCD(a, b) = MCD(a, b % a)
- b) MCD(a, b) = MCD(b, a % b)
- c) MCD(a, b) = MCD(a % b, b)
- d) MCD(a, b) = MCD(a * b, a + b)
Respuesta: b) MCD(a, b) = MCD(b, a % b). La propiedad fundamental del algoritmo de Euclides establece que el MCD de dos números a y b es igual al MCD de b y el resto de la división de a entre b (a % b). Esta propiedad permite reducir el problema a números más pequeños hasta llegar al MCD.
- ¿Cuál es la condición de parada del algoritmo de Euclides?
- a) Cuando a es igual a 0.
- b) Cuando b es igual a 1.
- c) Cuando a es igual a 1.
- d) Cuando b es igual a 0.
Respuesta: d) Cuando b es igual a 0.. El algoritmo de Euclides se detiene cuando el valor de 'b' (el segundo número) es igual a 0. En ese momento, el MCD es el valor de 'a' (el primer número).
- ¿Cuál es la fórmula matemática que relaciona el MCD y el MCM de dos números?
- a) MCD(a, b) + MCM(a, b) = a * b
- b) MCD(a, b) - MCM(a, b) = a * b
- c) MCD(a, b) * MCM(a, b) = a * b
- d) MCD(a, b) / MCM(a, b) = a * b
Respuesta: c) MCD(a, b) * MCM(a, b) = a * b. La relación entre el MCD (Máximo Común Divisor) y el MCM (Mínimo Común Múltiplo) de dos números a y b se define como: MCD(a, b) * MCM(a, b) = a * b.
9. Ejercicio 9: Códigos de Turno
Flashcards
- ¿Qué rango de valores emite el módulo de códigos de turno?
- El módulo emite códigos de turno de 4 cifras, en el rango de 0 a 9999.
- ¿Qué hace la función `inicializar_turnos`?
- Inicializa el sistema de códigos con una semilla, asegurando que la secuencia sea reproducible.
- ¿Qué hace la función `siguiente_turno`?
- Devuelve el siguiente código de turno en la secuencia.
- ¿Por qué es importante fijar una semilla en el módulo de turnos?
- Para asegurar que la secuencia de códigos de turno sea reproducible.
Preguntas tipo test
- ¿Cuál es el rango de valores que puede devolver la función `siguiente_turno()`?
- a) De 1 a 10000
- b) De 0 a 9999
- c) De 0 a 10000
- d) De 1 a 9999
Respuesta: b) De 0 a 9999. La función `siguiente_turno()` devuelve un valor en el rango de 0 a `CODIGO_MOD - 1`, donde `CODIGO_MOD` está definido como 10000u. Por lo tanto, el rango es de 0 a 9999.
- ¿Qué propósito tiene la macro `CODIGO_MOD` en el contexto del módulo de códigos de turno?
- a) Define el valor inicial de la semilla.
- b) Establece el límite superior para los códigos de turno generados.
- c) Especifica el incremento para generar el siguiente código.
- d) Determina la cantidad de códigos de turno que se generarán.
Respuesta: b) Establece el límite superior para los códigos de turno generados.. `CODIGO_MOD` define el módulo utilizado para asegurar que los códigos de turno se mantengan dentro de un rango específico, actuando como el límite superior de los valores generados.
- ¿Cuál es el propósito de la función `inicializar_turnos(unsigned int s)`?
- a) Generar el primer código de turno.
- b) Establecer la semilla inicial para la secuencia de códigos de turno.
- c) Incrementar el contador de turnos.
- d) Mostrar el siguiente turno en la pantalla.
Respuesta: b) Establecer la semilla inicial para la secuencia de códigos de turno.. La función `inicializar_turnos` se utiliza para establecer la semilla inicial que determinará la secuencia de códigos de turno generados por la función `siguiente_turno`.
10. Ejercicio 10: Módulo de Calibración
Flashcards
- ¿Qué hace la función `calibrate_value`?
- Devuelve el valor calibrado y saturado en el rango [SAT_MIN, SAT_MAX].
- ¿Qué hace la función `was_clipped`?
- Indica si el valor lineal previo a la saturación estaría fuera de rango.
- ¿Cuál es el propósito de las macros `SAT_MIN` y `SAT_MAX`?
- Definen los límites mínimo y máximo para la saturación del valor calibrado.
- ¿Qué debe hacerse para evitar la división por cero en `calibrate_value`?
- Si `gd` es 0, se debe usar `gd = 1`.
Preguntas tipo test
- ¿Qué ocurre si `gd` es 0 en la función `calibrate_value`?
- a) Se produce una división por cero, causando un error.
- b) La función retorna un valor predeterminado.
- c) Se utiliza `gd = 1` para evitar la división por cero.
- d) El resultado de la calibración es siempre 0.
Respuesta: c) Se utiliza `gd = 1` para evitar la división por cero.. Para evitar una división por cero, la función `calibrate_value` debe protegerse asignando `gd = 1` si el valor original de `gd` es 0.
- ¿Cuál es el propósito de la función `was_clipped`?
- a) Ajustar el valor calibrado dentro del rango [SAT_MIN, SAT_MAX].
- b) Verificar si el valor lineal previo a la saturación está fuera de rango.
- c) Aplicar la transformación lineal entera.
- d) Calcular el valor calibrado final.
Respuesta: b) Verificar si el valor lineal previo a la saturación está fuera de rango.. La función `was_clipped` determina si el valor antes de la saturación excede los límites definidos por `SAT_MIN` y `SAT_MAX`, indicando si habría recorte.
- ¿Qué macros se utilizan para definir los límites de saturación en el módulo de calibración?
- a) `MIN_SAT` y `MAX_SAT`
- b) `SAT_MIN` y `SAT_MAX`
- c) `LOWER_BOUND` y `UPPER_BOUND`
- d) `MIN_LIMIT` y `MAX_LIMIT`
Respuesta: b) `SAT_MIN` y `SAT_MAX`. El módulo de calibración utiliza las macros `SAT_MIN` y `SAT_MAX` para definir los límites inferior y superior del rango de saturación, respectivamente.
Y 10 flashcards y 20 preguntas más en el documento.
Texto del documento
Iniciación a la Programación Orientada a las Telecomunicaciones Ejercicios UT4 Programación modular en C: funciones y bibliotecas Iniciación a la Programación Orientada a las Telecomunicaciones IES Pacífico Curso 2025/26 Ejercicio 1 Se analiza un proyecto con estructura modular: Código C: senal.h 1 // senal.h 2 #ifndef SENAL_H 3 #define SENAL_H 4 5 // Macros de umbral 6 #define UMBRAL_BAJO (-80) 7 #define UMBRAL_ALTO (-50) 8 9 // Prototipos 10 int clasificar_rssi (int rssi); // retorna 0,1,2 11 int ajustar_a_decada (int rssi); // retorna nivel 0..9 12 13 #endif // SENAL_H Código C: senal.c 1 // senal.c 2 #include "senal.h" 3 4 int clasificar_rssi (int rssi){ 5 if(rssi < UMBRAL_BAJO) return 0; 6 else if(rssi <= UMBRAL_ALTO) return 1; 7 else return 2; 8 } 9 10 int ajustar_a_decada (int rssi){ 11 int nivel = (rssi + 100) /10; Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 1 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 12 if(nivel <0) nivel =0; 13 if(nivel >9) nivel =9; 14 return nivel; 15 } Código C: main.c 1 // main.c 2 #include <stdio.h> 3 #include "senal.h" 4 5 int main(void){ 6 int rssi; 7 scanf(" %d" ,&rssi); 8 int q = clasificar_rssi (rssi); 9 int nv = ajustar_a_decada (rssi); 10 printf("q= %d nv= %d\n", q, nv); 11 return 0; 12 } Preguntas: 1.
¿Qué imprime el programa para los valores rssi=-82, -65 y -49? 2. Explica el papel de los prototipos en el archivo senal.h y por qué son ne- cesarios en este diseño modular. 3. ¿Qué ventaja aporta el uso de macros (UMBRAL_BAJO y UMBRAL_ALTO) frente a usar directamente los valores -80 y -50 en el código? 4. Analiza el funcionamiento de ajustar_a_decada(): ¿qué hace la expresión (rssi + 100)/10? ¿Por qué se suma 100? 5. ¿Qué valores de rssi producirían nivel=0 y nivel=9 tras los ajustes en ajustar_a_decada()? 6. Si se modifica UMBRAL_BAJO a -85, ¿qué resultado daría ahora el programa para rssi=-82? 7. ¿Qué ocurriría si se elimina la línea #include "senal.h" del archivo main.c?
¿Compilaría el programa? 8. Propón una modificación en clasificar_rssi() para que retorne 3 catego- rías diferentes: 0 (débil), 1 (moderada), 2 (buena), 3 (excelente), añadiendo un nuevo umbral en -30. 9. ¿Qué sucede si se introduce un valor rssi=0? Calcula paso a paso los valo- res de q y nv. 10. Explica qué cambios serían necesarios en el código si se quisiera que ajustar_a_decada() devuelva niveles del 1 al 10 en lugar de 0 al 9.
Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 2 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Ejercicio 2 Código C: tarifa.h 1 // tarifa.h 2 #ifndef TARIFA_H 3 #define TARIFA_H 4 #define BASE 100 5 int costo_plan(int plan); // 0=Basico ,1=Pro ,2= Ultra 6 #endif 7 Código C: tarifa.c 1 // tarifa.c 2 #include "tarifa.h" 3 int costo_plan(int plan){ 4 int extra =0; 5 switch(plan){ 6 case 2: extra += 30; // Ultra (fall -through) 7 case 1: extra += 15; // Pro 8 case 0: extra += 5; break;// Basico 9 default: return 0; 10 } 11 return BASE + extra; 12 } 13 Código C: main.c 1 #include <stdio.h> 2 #include "tarifa.h" 3 int main(void){ 4 int plan; 5 scanf(" %d" ,&plan); 6 printf(" %d\n", costo_plan(plan)); 7 return 0; 8 } 9 Preguntas: 1.
¿Qué imprime el programa para los valores plan=0, 1, 2 y 7? 2. Explica detalladamente cómo funciona el mecanismo de fall-through en el switch y por qué permite que extra se incremente acumulativamente para los planes Pro y Ultra. 3. Si se añade un break; después de case 2: extra += 30;, ¿qué valor retor- naría la función para plan=2? Justifica tu respuesta. 4. ¿Qué modificación habría que hacer en el código si se quisiera cambiar la tarifa base de 100 a 150 para todos los planes? ¿Cuántas líneas de código habría que modificar y por qué? Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 3 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 5.
Propón una modificación del switch para añadir un nuevo plan Premium (plan=3) que cueste BASE + 60, manteniendo la lógica de acumulación ac- tual.
Ejercicio 3 Código C: flujo.h 1 // flujo.h 2 #ifndef FLUJO_H 3 #define FLUJO_H 4 int es_valido(int x); // 0..100 5 int actualizar_suma (int suma_actual , int x); 6 int actualizar_contador (int contador_actual , int x); 7 #endif 8 Código C: flujo.c 1 // flujo.c 2 #include "flujo.h" 3 int es_valido(int x){ return x>=0 && x <=100; } 4 5 int actualizar_suma (int suma_actual , int x){ 6 if(es_valido(x)){ 7 int s = suma_actual + x; 8 if(x==0) s--; // ajuste especial para 0 9 return s; 10 } 11 return suma_actual; 12 } 13 14 int actualizar_contador (int contador_actual , int x){ 15 if(es_valido(x)) return contador_actual + 1; 16 return contador_actual ; 17 } 18 Código C: main.c 1 #include <stdio.h> 2 #include "flujo.h" 3 4 int main(void){ 5 int x, suma=0, contador =0; 6 // Entrada ejemplo: 12 5 -1 7 999 3 0 -999 8 7 while( scanf(" %d" ,&x)==1 ){ 8 if(x== -999) break; 9 suma = actualizar_suma (suma , x); 10 contador = actualizar_contador (contador , x); Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 4 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 11 } 12 printf(" %d %d\n", contador , suma); 13 return 0; 14 } 15 Preguntas: 1.
¿Qué imprime el programa con la secuencia de entrada indicada en el co- mentario (12 5 -1 7 999 3 0 -999 8)? Muestra el valor final de contador y suma. 2. Traza paso a paso el procesamiento de los tres primeros valores válidos (12, 5 y 7), indicando cómo evolucionan las variables suma y contador tras cada lectura. 3. Explica por qué el valor 0 recibe un ajuste especial en actualizar_suma() restándole 1 a la suma. ¿Qué resultado tendría la suma si se elimina la línea if(x==0) s–;? 4. ¿Qué papel cumple el valor centinela -999 en este programa? ¿Por qué no se procesa el último valor 8 de la secuencia? 5.
Modifica la función es_valido() para que acepte valores en el rango [10, 50] en lugar de [0, 100]. ¿Qué imprimiría el programa con la misma se- cuencia de entrada?
Ejercicio 4 Código C: numero.h 1 // numero.h 2 #ifndef NUMERO_H 3 #define NUMERO_H 4 int primer_divisor_propio (int n); // retorna primer divisor d>1 o -1 5 #endif 6 Código C: numero.c 1 // numero.c 2 #include "numero.h" 3 int primer_divisor_propio (int n){ 4 if(n <=3) return -1; 5 for(int d=2; d*d<=n; d++){ 6 if(n %d==0) return d; Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 5 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 7 } 8 return -1; 9 } 10 Código C: main.c 1 #include <stdio.h> 2 #include "numero.h" 3 int main(void){ 4 int n; scanf(" %d" ,&n); 5 printf(" %d\n", primer_divisor_propio (n)); 6 return 0; 7 } 8 Preguntas: 1.
¿Qué imprime el programa para n=77? ¿Y para n=97? Justifica ambos resul- tados. 2. Explica por qué la condición del bucle es d*d<=n en lugar de d<n. ¿Qué ventaja aporta esta optimización en términos de eficiencia? 3. Traza la ejecución del bucle para n=36, indicando los valores de d que se prueban y cuándo termina el bucle. 4. ¿Por qué la función retorna -1 directamente cuando n<=3? ¿Qué sucedería con los valores n=2 y n=3 si se elimina esta validación inicial? 5. Analiza la complejidad temporal de la función. ¿Cuántas iteraciones realiza como máximo para un número n?.
Ejercicio 5 Código C: histeresis.h 1 // histeresis.h 2 #ifndef HISTERESIS_H 3 #define HISTERESIS_H 4 int siguiente_estado (double m, double umbral_on , double umbral_off , int encendido); // retorna 0/1 5 #endif 6 Código C: histeresis.c 1 // histeresis.c 2 #include "histeresis.h" Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 6 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 3 int siguiente_estado (double m, double umbral_on , double umbral_off , int encendido){ 4 if(!
encendido && m>= umbral_on) return 1; 5 if(encendido && m<= umbral_off) return 0; 6 return encendido; 7 } 8 Código C: main.c 1 #include <stdio.h> 2 #include "histeresis.h" 3 int main(void){ 4 double umbral_on =6.0, umbral_off =4.0; 5 int encendido =0; double m; 6 // Entrada de medidas: 2 2.3 4.3 6.7 8.6 6.6 4.3 2 7 while(scanf(" %lf" ,&m)==1){ 8 encendido = siguiente_estado (m, umbral_on , umbral_off , encendido); 9 printf(" %d", encendido); 10 } 11 printf("\n"); 12 return 0; 13 } 14 Preguntas: 1. Indica la secuencia de salida (0s y 1s) que imprime el programa con los valores del comentario (2 2.3 4.3 6.7 8.6 6.6 4.3 2). 2.
Traza paso a paso el procesamiento de cada medida, indicando el valor de m, el estado previo encendido, qué condición se evalúa en siguiente_estado(), y el nuevo estado resultante. 3. Explica qué es la histéresis en este contexto y por qué es necesario tener dos umbrales diferentes (umbral_on=6.0 y umbral_off=4.0) en lugar de uno solo. 4. ¿Qué sucedería si se cambia el estado inicial a encendido=1? Indica la nueva secuencia de salida con los mismos valores de entrada. 5. Propón valores de umbral_on y umbral_off que hagan que el sistema per- manezca siempre apagado (estado 0) para la secuencia de entrada dada. Justifica tu respuesta.
Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 7 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Ejercicio 6 Código C: metricas.h 1 // metricas.h 2 #ifndef METRICAS_H 3 #define METRICAS_H 4 void incrementar(void); // sin retorno (efecto lateral) 5 int obtener_contador (void); 6 #endif 7 Código C: metricas.c 1 // metricas.c 2 #include "metricas.h" 3 static int contador = 0; // solo visible en este fichero 4 5 void incrementar(void){ contador ++; } 6 int obtener_contador (void){ return contador; } 7 Código C: main.c 1 #include <stdio.h> 2 #include "metricas.h" 3 int main(void){ 4 incrementar (); incrementar (); 5 printf(" %d ", obtener_contador ()); 6 { // nuevo bloque: variable local con el mismo nombre 7 int contador = 1000; 8 incrementar (); 9 printf(" %d ", contador); 10 } 11 printf(" %d\n", obtener_contador ()); 12 return 0; 13 } 14 Preguntas: 1.
¿Qué imprime el programa? Justifica el valor de cada número impreso. 2. Explica el concepto de ámbito de fichero que proporciona el modificador static en la variable contador de metricas.c. ¿Por qué esta variable no es accesible directamente desde main.c? 3. Dentro del bloque con llaves en main.c, existe una variable local contador = 1000. ¿Esta variable afecta al contador de metricas.c? Explica el concepto de sombreado (shadowing) y ámbito de bloque. 4. ¿Qué sucedería si se elimina la palabra clave static de la declaración static int contador = 0; en metricas.c? ¿Podría accederse a contador desde main.c?
Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 8 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 5. Traza paso a paso la ejecución del programa, indicando el valor de contador (en metricas.c) después de cada llamada a incrementar() y qué valores se imprimen en cada printf. Ejercicio 7 Objetivo. Escriba un módulo que lea un entero en el rango [minimo, maximo] desde la entrada estándar, reintentando hasta obtener un valor válido o detectar el fin de archivo (EOF).
Interfaz pública Código C: entrada.h 1 // entrada.h 2 #ifndef ENTRADA_H 3 #define ENTRADA_H 4 5 #define VALOR_ERROR (-1) // Marca de error si se alcanza EOF 6 7 /* Lee un entero en [minimo , maximo] desde stdin. 8 * Devuelve: 9 * - un entero válido dentro del rango , o 10 * - VALOR_ERROR si se alcanza EOF.
11 */ 12 int leer_entero_en_rango (int minimo , int maximo); 13 14 #endif Programa de prueba Código C: main.c 1 // main.c 2 #include <stdio.h> 3 #include "entrada.h" 4 5 int main(void){ 6 printf("Introduce una edad (0 -100): "); 7 int edad = leer_entero_en_rango (0, 100); 8 9 if(edad == VALOR_ERROR){ 10 printf("Error: no se pudo leer .\n"); 11 }else{ 12 printf("Edad válida: %d\n", edad); 13 } 14 return 0; 15 } Tarea: Implementa el archivo entrada.c que contenga la función leer_entero_en_rango() siguiendo las especificaciones de la guía de re- solución.
Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 9 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Guía de resolución (paso a paso). 1. Modularidad (UT4): El prototipo está declarado en entrada.h. Debes crear entrada.c e incluir el archivo de cabecera. Toda la comunicación se realiza mediante parámetros y valor de retorno (sin variables globales). 2. Estructura del bucle (UT3): Utiliza un bucle infinito while(1) que solo termina cuando: Se lee un valor válido dentro del rango (retorna el valor). Se detecta EOF (retorna VALOR_ERROR). El bucle garantiza que la función no retorna hasta cumplir una de estas condiciones. 3.
Lectura con scanf (UT3): Usa int resultado = scanf(" %d", &valor); para leer un entero. El valor de retorno de scanf indica: 1: se leyó correctamente un entero. EOF: se alcanzó el fin de archivo (no hay más datos). Si resultado == EOF, la función debe retornar inmediatamente VALOR_ERROR. 4. Validación del rango (UT2): Después de leer exitosamente, verifica: if(valor >= minimo && valor <= maximo). Si el valor está dentro del rango, retórnalo inmediatamente. Si está fuera del rango: Muestra un mensaje informativo: printf("Valor fuera de rango [ %d, %d]. Intenta de nuevo: ", minimo, maximo); Continúa el bucle para volver a pedir el valor. 5.
Esquema general de la implementación: Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 10 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones int leer_entero_en_rango(int minimo, int maximo){ int valor; while(1){ // 1. Leer un entero con scanf // 2. Si es EOF, retornar VALOR_ERROR // 3. Si está fuera de rango, mostrar mensaje y continuar // 4. Si está en rango, retornar el valor } } 6. Casos de prueba recomendados: a) Entrada: 50 con rango [0, 100] debe aceptar 50. b) Entrada: -5 10 con rango [0, 100] debe rechazar -5, luego aceptar 10. c) Entrada: 150 80 con rango [0, 100] debe rechazar 150, luego aceptar 80.
d) Entrada: EOF inmediato (Ctrl+D o Ctrl+Z) debe retornar VALOR_ERROR. Ejercicio 8 Objetivo. Implementar un módulo matemático que calcule el Máximo Común Di- visor (MCD) y el Mínimo Común Múltiplo (MCM) de dos números enteros positivos utilizando el algoritmo de Euclides.
Programa de prueba Código C: main.c 1 // main.c 2 #include <stdio.h> 3 #include "mates.h" 4 5 int main(void){ 6 int a, b; 7 if(scanf(" %d %d", &a, &b) != 2) return 0; 8 printf("MCD= %d MCM= %d\n", mcd(a,b), mcm(a,b)); 9 return 0; 10 } 11 Tarea: Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 11 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Implementa los archivos mates.h (interfaz) y mates.c (implementación) con las funciones mcd() y mcm() siguiendo las especificaciones de la guía de resolución. Guía de resolución (paso a paso). 1.
Archivo mates.h (UT4): Debe incluir guardas de inclusión para evitar inclusiones múltiples: Código C: Inicio mates.h 1 #ifndef MATES_H 2 #define MATES_H 3 // ... prototipos ... 4 #endif 5 Declara el prototipo: int mcd(int a, int b); Declara el prototipo: int mcm(int a, int b); Opcionalmente, añade comentarios descriptivos sobre qué hace cada función. 2. Función mcd - Algoritmo de Euclides (UT3): El algoritmo de Euclides calcula el MCD mediante restos sucesivos. Propiedad fundamental: MCD(a, b) = MCD(b, a % b) Condición de parada: cuando b == 0, el MCD es a.
Estructura del bucle: Código C: Estructura del bucle 1 while(b != 0){ 2 int resto = a % b; 3 a = b; 4 b = resto; 5 } 6 return a; El bucle termina porque el resto siempre es menor que el divisor, redu- ciendo progresivamente b hasta 0. 3. Función mcm - Fórmula matemática (UT2): Relación entre MCD y MCM: MCD(a,b) × MCM(a,b) = a × b Por tanto: MCM(a,b) = (a × b) / MCD(a,b) Caso especial: si a == 0 o b == 0, el MCM es 0 (usa if para validar). Pasos de implementación: a) Verificar si alguno de los números es 0.
Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 12 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones b) Calcular el MCD llamando a la función mcd(a, b). c) Aplicar la fórmula: (a * b) / mcd_calculado. d) Retornar el resultado. 4. Archivo mates.c: Debe incluir: #include "mates.h" Implementar primero mcd() porque mcm() la necesita. Implementar después mcm() utilizando la función mcd(). 5.
Casos de prueba recomendados: a=12, b=18: MCD = 6 (divisores comunes: 1,2,3,6; el mayor es 6) MCM = 36 (múltiplos de 12: 12,24,36,...; múltiplos de 18: 18,36,...; el menor común es 36) a=7, b=5: MCD = 1 (son coprimos, no tienen divisores comunes excepto 1) MCM = 35 a=0, b=8: MCD = 8 MCM = 0 a=15, b=15: MCD = 15 (un número es su propio MCD) MCM = 15 Ejercicio 9 Objetivo. Diseñar un pequeño módulo que emita códigos de turno de 4 cifras (0..9999). Los códigos deben formar una secuencia reproducible al fijar una semilla, de modo que: inicializar_turnos(unsigned int s) inicializa el sistema. siguiente_turno(void) devuelve el siguiente código (entero en 0..9999).
Requisitos: prototipos en .h, implementación en .c, macros de configura- ción, estado interno con static. Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 13 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Apoyos: validaciones simples con if y bucle for en el programa de prueba. Interfaz pública Código C: turnos.h 1 // turnos.h 2 #ifndef TURNOS_H 3 #define TURNOS_H 4 5 /* Macros de configuración: rango y parámetros internos del avance de estado. 6 Cambiarlas permite "sistemas de códigos" distintos (mismo diseño, otro comportamiento ).
*/ 7 #define CODIGO_MOD 10000u // Códigos en 0..9999 8 #define CODIGO_A 1103u // Parámetros elegidos para buena " mezcla" didáctica 9 #define CODIGO_C 9277u 10 11 /* Inicializa el sistema de códigos con una semilla s. 12 Si s == 0, se fuerza una semilla mínima distinta de 0 para evitar estados degenerados. */ 13 void inicializar_turnos (unsigned int s); 14 15 /* Devuelve el siguiente código de turno en el rango 0.. CODIGO_MOD -1.
*/ 16 unsigned int siguiente_turno (void); 17 18 #endif Código C: main.c 1 // main.c 2 #include <stdio.h> 3 #include "turnos.h" 4 5 int main(void){ 6 unsigned int semilla; 7 int n = 5; // UT3: generaremos 5 códigos para comprobar reproducibilidad 8 9 if(scanf(" %u", &semilla) != 1) return 0; // leer semilla 10 inicializar_turnos (semilla); 11 12 for(int i=0; i<n; i++){ 13 unsigned int codigo = siguiente_turno (); 14 printf(" %04u\n", codigo); // imprime con 4 cifras , rellenando con ceros 15 } 16 return 0; 17 } Tarea: Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 14 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Implementa el archivo turnos.c que contenga las funciones inicializar_turnos() y siguiente_turno() siguiendo las especificaciones de la guía de resolución.
Guía de resolución (paso a paso). 1. Modularidad: La interfaz ya está declarada en turnos.h: prototipos y macros (CODIGO_MOD, CODIGO_A, CODIGO_C). Debes implementar en turnos.c y encapsular el estado con static a nivel de fichero: ninguna otra unidad de compilación puede acceder directamente. 2. Semilla (inicializar_turnos): Usa if para manejar el caso s==0: forzar un estado inicial válido (p.ej., 1). estado = s % CODIGO_MOD normaliza la semilla al rango de códigos. 3. Siguiente código (siguiente_turno): Calcula un nuevo estado combinando el estado actual con las constan- tes del sistema; luego reduce el resultado al rango con % CODIGO_MOD.
Para evitar problemas de rango en la multiplicación/suma intermedia, promueve a unsigned long durante el cálculo y solo al final reduce y convierte. Devuelve el estado actualizado como nuevo código. 4. Bucle (UT3): en main.c, imprime una pequeña tanda de códigos (p.ej., 5) para comprobar que con la misma semilla siempre se obtiene la misma secuencia. 5. Pruebas rápidas: Entrada: 0 (semilla) se fuerza a 1. Ejecutar dos veces debe dar la misma secuencia. Entrada: 1234 produce otra secuencia, pero siempre idéntica si repites con 1234. Cambiar CODIGO_MOD a 1000u muestra códigos en 0..999 (más corto para depuración). 6.
Diseño y ámbito: Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 15 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones Se ilustran funciones sin retorno (inicializar_turnos) y con retorno (siguiente_turno). El estado interno no es global exportado: queda encapsulado gracias a static. El uso de macros permite "reconfigurar" el sistema (rango y mezcla) sin tocar la lógica. Ejercicio 10 Objetivo. Diseñar un módulo de calibración que: Aplique una transformación lineal entera: y = (raw + offset) · gn gd . Sature el resultado a [SAT_MIN, SAT_MAX]. Permita preguntar si habría habido recorte (clipping) antes de saturar.
Requisitos: prototipos en .h, implementación en .c, macros de configuración. Interfaz pública Código C: calib.h 1 // calib.h 2 #ifndef CALIB_H 3 #define CALIB_H 4 5 #define SAT_MIN 0 6 #define SAT_MAX 1023 7 8 /* Devuelve el valor calibrado y ya saturado en [SAT_MIN , SAT_MAX ]. 9 * Si gd==0, debe proteger contra división por cero (p.ej., usar gd =1). 10 */ 11 int calibrate_value (int raw , int offset , int gn , int gd); 12 13 /* Indica si el valor lineal previo a la saturación estaría fuera de rango.
*/ 14 int was_clipped(int raw , int offset , int gn , int gd); // 1 si recortaría, 0 si no 15 16 #endif Código C: main.c 1 // main.c 2 #include <stdio.h> 3 #include "calib.h" Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 16 de 17 Iniciación a la Programación Orientada a las Telecomunicaciones 4 5 int main(void){ 6 int raw , off , gn , gd; 7 if(scanf(" %d %d %d %d", &raw , &off , &gn , &gd) != 4) return 0; 8 int y = calibrate_value (raw , off , gn , gd); 9 int c = was_clipped(raw , off , gn , gd); 10 printf("y= %d clipped= %d\n", y, c); 11 return 0; 12 } Guía de resolución (paso a paso). 1. Modularidad (UT4): prototipos en calib.h, funciones en calib.c.
Usa ma- cros SAT_MIN/SAT_MAX. 2. Transformación lineal: define una función interna apply_linear (ámbito de fichero con static) que calcule y = (raw + offset) · gn gd . Evita división por cero: si gd==0, usa gd=1. Promociona a long antes de multiplicar para reducir desbordamientos. La división entera / trunca hacia 0 (esto es correcto para esta práctica). 3. Saturación (UT2): en calibrate_value, aplica dos if para acotar a [SAT_MIN, SAT_MAX]. 4. Detección de recorte: en was_clipped, compara el valor previo a saturar con los límites y devuelve 1/0. 5. Pruebas: raw=900, off=200, gn=1, gd=1 lineal = 1100 y=1023, clipped=1. raw=100, off=-50, gn=2, gd=3 lineal 33 dentro de rango.
gd=0 se usa gd = 1 (protección). Curso 2025/26 UT4 - Programación modular en C: funciones y bibliotecas Página 17 de 17