Documento de David Arlekin (2)

Iniciación a la Programación Orientada a las Telecomunicaciones · Sistemas de Telecomunicaciones e Informáticos · Estudios España. Documento de David…

Iniciación a la Programación Orientada a las Telecomunicaciones · Estudios España · Sistemas de Telecomunicaciones e Informáticos

33 páginas

Texto del documento

UT3. Estructuras de control en C: condicionales y bucles Iniciación a la programación orientada a las telecomunicaciones Curso 2025 - 2026 Contenidos Introducción Estructuras de selección Estructuras de repetición Sentencias de salto Programación defensiva Ejemplo integrador Errores frecuentes y buenas prácticas 2 / 33 ¿Qué son las estructuras de control? Concepto Permiten modificar el flujo secuen- cial del programa para: Tomar decisiones Repetir operaciones Optimizar la ejecución Instrucción 1 ¿Condición?

Opción A Opción B Continuar 3 / 33 Repertorio de estructuras en C Selección Ñ if if-else switch-case Iteración L while do-while for Salto $ break continue return Importante C no tiene excepciones nativas (try/catch). Usaremos programación de- fensiva y códigos de retorno. 4 / 33 La sentencia if Sintaxis 1 if (condicion) { 2 // Bloque ejecutado 3 // si condicion es 4 // verdadera (!=0) 5 } 6 Recuerda Falso: 0 Verdadero: cualquier valor ̸= 0 Inicio ¿Condición?

Ejecutar bloque Saltar Continuar Sí No 5 / 33 Ejemplo práctico: if 1 #include <stdio.h> 2 3 int main(void) { 4 int numero = 10; 5 6 if (numero > 0) { 7 printf("El numero es positivo\n"); 8 } 9 10 printf("Fin del programa .\n"); 11 return 0; 12 } Salida El numero es positivo Fin del programa. 6 / 33 . Errores comunes con if Asignación vs Comparación 1 // MAL 2 if (x = 0) { ... } 3 4 // BIEN 5 if (x == 0) { ...

} 6 Comparar flotantes 1 // MAL 2 if (precio == 10.5) {...} 3 4 // BIEN 5 if (fabs(precio -10.5) < 0.001) {...} 6 Buenas prácticas Usa paréntesis en expresiones complejas: if ((a > 0) && (b < 10)) Siempre usa llaves {}, incluso para una línea 7 / 33 La sentencia if-else 1 #include <stdio.h> 2 3 int main(void) { 4 int n = -5; 5 6 if (n >= 0) { 7 printf("No negativo\n" ); 8 } else { 9 printf("Negativo\n"); 10 } 11 12 return 0; 13 } 14 Inicio ¿n 0? Bloque if Bloque else Fin Sí No Ventaja Garantiza que siempre se ejecuta una de las dos ramas.

8 / 33 Cadena if-else if-else 1 int nota = 75; 2 3 if (nota >= 90) { 4 printf(" Sobresaliente \n "); 5 } else if (nota >= 70) { 6 printf("Notable\n"); 7 } else if (nota >= 50) { 8 printf("Aprobado\n"); 9 } else { 10 printf("Suspenso\n"); 11 } 12 Inicio 90? Sobresaliente 70? Notable 50? Aprobado Suspenso Fin Sí No Sí No Sí No 9 / 33 La sentencia switch-case 1 int opcion = 2; 2 3 switch (opcion) { 4 case 1: 5 printf("Opcion 1\n"); 6 break; 7 case 2: 8 printf("Opcion 2\n"); 9 break; 10 case 3: 11 printf("Opcion 3\n"); 12 break; 13 default: 14 printf("Invalida\n"); 15 } 16 ¿Cuándo usar?

Decisiones por valor discreto Enteros, chars, enums Múltiples opciones ( 3) Importante Cada case necesita break pa- ra evitar fall-through 10 / 33 Flujo de switch-case Inicio switch(opcion) case 1 case 2 case 3 default Continuar Fin 1 2 3 otro break break break sin break . Fall-through Si olvidas break, se ejecutan los casos siguientes (línea roja discontinua). 11 / 33 Bucle while (pre-test) Sintaxis 1 while (condicion) { 2 // Cuerpo del bucle 3 // actualizacion 4 } 5 Ejemplo 1 int i = 1; 2 while (i <= 5) { 3 printf("i= %d\n", i); 4 i++; 5 } 6 Inicio Inicializar ¿Condición? Cuerpo Actualizar Fin Sí No Característica Puede no ejecutarse nunca si la condición inicial es falsa.

12 / 33 Bucle do-while (post-test) Sintaxis 1 do { 2 // Cuerpo del bucle 3 // actualizacion 4 } while (condicion); 5 Ejemplo 1 int n = 0; 2 do { 3 printf("n= %d\n", n); 4 n++; 5 } while (n < 3); 6 Inicio Inicializar Cuerpo Actualizar ¿Condición? Fin Sí No Importante Se ejecuta al menos una vez, sin importar la condición. 13 / 33 Bucle for Sintaxis canónica 1 for (init; cond; update){ 2 // Cuerpo 3 } 4 Ejemplo típico 1 for (int i=0;i <5;i++){ 2 printf("i = %d\n",i); 3 } 4 // i no existe aqui 5 Ámbito Inicio Inicialización ¿Condición?

Cuerpo Actualización Fin Sí No 14 / 33 Comparativa: while vs for Con while 1 int i = 0; // init 2 while (i < 5) { // cond 3 printf(" %d ", i); 4 i++; // update 5 } 6 Con for 1 for (int i=0; i<5; i++) { 2 printf(" %d ", i); 3 } 4 5 6 ¿Cuándo usar cada uno? for: cuando sabes de antemano el número de iteraciones while: cuando la condición de parada es más compleja do-while: cuando necesitas ejecutar al menos una vez 15 / 33 Sentencias break y continue break Sale inmediatamente del bucle o switch actual. 1 for (int i=0; i <10; i++) { 2 if (i == 5) { 3 break; // sale aqui 4 } 5 printf(" %d ", i); 6 } 7 // Salida: 0 1 2 3 4 8 continue Salta a la siguiente iteración, omi- tiendo el resto del cuerpo.

1 for (int i=0; i<5; i++) { 2 if (i == 2) { 3 continue; // salta 2 4 } 5 printf(" %d ", i); 6 } 7 // Salida: 0 1 3 4 8 Uso responsable Úsalos con moderación para mantener el código legible. Demasiados saltos dificultan la comprensión. 16 / 33 Flujo visual: break vs continue Con break ¿i < 10? ¿i == 5? Imprimir i++ Salir Sí No Sí No Con continue ¿i < 5? ¿i == 2? Imprimir i++ Salir Sí No Sí No $ break sale del bucle completamente L continue salta a la actualización 17 / 33 Programación defensiva en C ¿Qué es?

Técnica para escribir código robusto que: Valida entradas antes de operar Previene errores comunes Devuelve códigos de error claros Documenta restricciones (contrato) Importante C no tiene excepciones (try/catch). De- bemos manejar errores manualmente.

Entrada del usuario Validar Procesar 18 / 33 Ejemplo: función segura de división 1/2 1 #include <stdio.h> 2 #include <stdbool.h> 3 4 bool dividir(int a, int b, int* resultado) { 5 // Validar puntero (contrato) 6 if (resultado == NULL) { 7 return false; 8 } 9 10 // Validar division por cero 11 if (b == 0) { 12 return false; 13 } 14 15 *resultado = a / b; 16 return true; // Exito 17 } 18 19 / 33 Ejemplo: función segura de división 2/2 1 int main(void) { 2 int r; 3 4 if (dividir (10, 0, &r)) { 5 printf("Resultado = %d\n", r); 6 } else { 7 printf("Error en la division .\n"); 8 } 9 10 return 0; 11 } 12 Ventajas de este enfoque Validación de punteros: evita crashes por NULL Código de retorno claro: true/false Resultado por referencia: permite distinguir éxito de error 20 / 33 Validación de entradas con scanf 1 int numero; 2 3 printf("Introduce un numero: "); 4 5 if (scanf(" %d", &numero) != 1) { 6 // Limpiar buffer 7 int c; 8 while ((c = getchar ()) != '\n ' && c != EOF) { } 9 10 printf("Entrada invalida\n"); 11 numero = 0; // Valor por defecto 12 } 13 ¿Por qué validar?

scanf puede fallar si: El usuario escribe texto en vez de número Hay problemas de formato Se alcanza EOF Regla de oro Siempre comprueba el valor de retorno de scanf. 21 / 33 Estrategias de programación defensiva Validación de entrada Comprobar retornos de scanf Verificar rangos válidos Validar punteros antes de usarlos Códigos de error Usar bool para éxito/fallo Usar int para códigos específicos Documentar todos los casos Casos especiales División por cero Desbordamiento de arrays Punteros nulos Archivos no existentes Documentación Define el contrato de cada función: qué espera y qué devuelve.

22 / 33 Menú interactivo: estructura general Componentes 1 Bucle do-while para repetir 2 switch para opciones 3 Validación de entrada 4 Funciones auxiliares Funciones auxiliares 1 static void saludar(void) { 2 printf("Hola !\n"); 3 } 4 5 static void contar(void) { 6 for (int i=1; i <=5; i++) 7 printf(" %d ", i); 8 printf("\n"); 9 } 10 Inicio Mostrar menú Leer opción switch ¿opción ̸= 3?

Fin Sí No 23 / 33 Menú interactivo: código completo (1/2) 1 #include <stdio.h> 2 3 static void saludar(void) { 4 printf("Hola , usuario !\n"); 5 } 6 7 static void contar_hasta_5 (void) { 8 for (int i = 1; i <= 5; i++) { 9 printf(" %d ", i); 10 } 11 printf("\n"); 12 } 13 14 int main(void) { 15 int opcion; 16 17 do { 18 printf("\n=== Menu ===\n"); 19 printf("1) Saludar\n"); 20 printf("2) Contar hasta 5\n"); 21 printf("3) Salir\n"); 22 printf("Elige una opcion: "); 23 24 / 33 Menú interactivo: código completo (2/2) 1 // Validacion de entrada 2 if (scanf(" %d", &opcion) != 1) { 3 int c; 4 while ((c = getchar ()) != '\n' && c != EOF) { } 5 printf("Entrada no valida .\n"); 6 opcion = 0; 7 continue; 8 } 9 switch (opcion) { 10 case 1: 11 saludar (); 12 break; 13 case 2: 14 contar_hasta_5 (); 15 break; 16 case 3: 17 printf("Saliendo ...\n"); 18 break; 19 default: 20 printf("Opcion no valida .\n"); 21 } 22 } while (opcion != 3); 23 return 0; 24 } 25 / 33 Diagrama de flujo: menú completo Inicio Mostrar menú Leer opción ¿Válida?

Limpiar buffer switch case 1: saludar() case 2: contar() case 3: Salir default ¿opción ̸= 3? Fin Sí No Sí No 26 / 33 Análisis del ejemplo integrador Elementos clave do-while: garantiza al menos una ejecución switch: gestión clara de opciones Validación: previene crashes por entrada incorrecta Funciones: modularidad y reutilización Mejoras posibles Añadir más opciones Implementar submenús Guardar configuración Validar rangos específicos Concepto importante Este patrón (menú + validación + switch) es fundamental en programación y lo encontrarás en muchos contextos profesionales. 27 / 33 Errores frecuentes (1/2) 1. Asignación vs Compara- ción 1 // MAL 2 if (x = 0) { 3 // x ahora vale 0!

4 } 5 // BIEN 6 if (x == 0) { 7 // compara x con 0 8 } 2. Olvidar break 1 switch (x) { 2 case 1: 3 printf("Uno\n"); 4 // falta break! 5 case 2: 6 printf("Dos\n"); 7 } 3. Bucle infinito 1 int i = 0; 2 while (i < 10) { 3 printf(" %d\n", i); 4 // falta i++! 5 } 4. No validar scanf 1 int n; 2 // MAL: no validar 3 scanf(" %d", &n); 4 // BIEN 5 if (scanf(" %d", &n) != 1) { 6 // manejar error 7 } 28 / 33 Errores frecuentes (2/2) 5. Comparar flotantes 1 float precio = 10.5; 2 // MAL 3 if (precio == 10.5) {...} 4 // BIEN 5 #include <math.h> 6 if (fabs(precio - 10.5) < 0.001) {...} 6. Punto y coma extra 1 // MAL 2 if (x > 0); // <- punto y coma!

3 { 4 printf("Siempre se ejecuta"); 5 } 6 // BIEN 7 if (x > 0) { 8 printf("Solo si x > 0 "); 9 } . Consejo Estos errores son muy comunes incluso en programadores experimentados. La práctica y las pruebas constantes son clave.

29 / 33 Buenas prácticas (1/2) Legibilidad Indentación consistente (2 o 4 espacios) Nombres descriptivos: contador_intentos mejor que c Comentarios útiles: explica el "por qué", no el "qué" Estructuras Siempre usa llaves {} Evita anidación excesiva (máx 3-4 niveles) Usa paréntesis en condiciones complejas Validación Valida todas las entradas del usuario Comprueba retornos de funciones Prevé casos extremos: cero, negativo, vacío Mantenibilidad Funciones pequeñas y específicas DRY: Don't Repeat Yourself Constantes en lugar de números mágicos 30 / 33 Buenas prácticas (2/2): Ejemplos Usa constantes 1 // MAL 2 if (nota >= 90) {...} 3 4 // BIEN 5 #define SOBRESALIENTE 90 6 7 if (nota >= SOBRESALIENTE ) { 8 ...

9 } Evita números mágicos 1 // MAL 2 for (int i=0; i <100; i++) { 3 ... 4 } 5 6 // BIEN 7 #define MAX_USUARIOS 100 8 9 for (int i=0; i< MAX_USUARIOS ;i++) {...} Regla de oro Escribe código pensando en que lo leerás dentro de 6 meses (o en que lo leerá otra persona) 31 / 33 Checklist de revisión de código Antes de entregar § ¿He validado todas las entra- das? § ¿He usado == en vez de =? § ¿Todos los case tienen break? § ¿Mis bucles tienen condición de salida clara? § ¿He probado con entradas invá- lidas? Calidad de código § ¿El código está bien indentado? § ¿Los nombres son descriptivos? § ¿He eliminado código comenta- do? § ¿Las funciones son pequeñas? § ¿Compila sin warnings?

Tip profesional: Usa esta checklist antes de cada entrega 32 / 33 ¡Gracias! Cualquier pregunta será bienvenida IES Pacífico

Más apuntes de Iniciación a la Programación Orientada a las Telecomunicaciones

Exámenes, temas y apuntes de Iniciación a la Programación Orientada a las Telecomunicaciones