📝 tema1
← Volver

Lenguajes de Programación — Guía Completa para Oposiciones


ÍNDICE

  1. Lenguajes de Programación
  2. Representación de Tipos de Datos
  3. Operadores
  4. Instrucciones Condicionales
  5. Bucles y Recursividad
  6. Procedimientos, Funciones y Parámetros
  7. Vectores y Registros
  8. Estructura de un Programa

1. Lenguajes de Programación

1.1 Concepto

Un lenguaje de programación es un conjunto de reglas sintácticas y semánticas que permiten expresar instrucciones que una máquina puede interpretar o ejecutar. Actúan como puente entre el pensamiento humano y la operación de la máquina.

1.2 Niveles de Abstracción

Nivel Tipo Ejemplo
Bajo nivel Lenguaje máquina (binario) 10110000 01100001
Bajo nivel Ensamblador (Assembly) MOV AL, 61h
Alto nivel Lenguajes estructurados/OOP C, Java, Python, Pascal

1.3 Clasificación

Por paradigma:

Por generación:

Generación Descripción Ejemplo
1ª GL Lenguaje máquina Binario
2ª GL Ensamblador Assembly
3ª GL Lenguajes procedurales de alto nivel C, Pascal, COBOL
4ª GL Orientados a aplicaciones/bases de datos SQL, ABAP
5ª GL Inteligencia artificial y lógica Prolog, Mercury

1.4 Traductores de Lenguaje

Diferencia clave (oposición): El compilador produce un ejecutable independiente; el intérprete necesita estar presente en tiempo de ejecución.

1.5 Fases de Compilación

Código fuente
     ↓
[Análisis Léxico]     → Tokens
     ↓
[Análisis Sintáctico] → Árbol de Análisis (AST)
     ↓
[Análisis Semántico]  → Tabla de símbolos
     ↓
[Generación de Código Intermedio]
     ↓
[Optimización]
     ↓
[Generación de Código Máquina]
     ↓
Ejecutable (.exe / binario)

2. Representación de Tipos de Datos

2.1 Concepto de Tipo de Dato

Un tipo de dato define el conjunto de valores que puede tomar una variable y las operaciones que pueden realizarse sobre ella.

2.2 Tipos Simples o Primitivos

2.2.1 Entero (Integer)

Representa números sin parte decimal.

Tipo Bits Rango (sin signo) Ejemplo
byte 8 0 a 255 byte b = 200;
short 16 -32.768 a 32.767 short s = 1000;
int 32 -2.147M a 2.147M int i = 42;
long 64 -9.2×10¹⁸ a 9.2×10¹⁸ long l = 9999999999L;

Representación interna: complemento a dos (permite representar negativos).

Ejemplo: -5 en 8 bits (complemento a 2)
  5 en binario = 00000101
  Invertir bits = 11111010
  Sumar 1       = 11111011  → Esto es -5

2.2.2 Real o Flotante (Float/Double)

Representa números con parte decimal. Se usa el estándar IEEE 754.

Tipo Bits Precisión
float 32 ~7 dígitos decimales
double 64 ~15 dígitos decimales
Estructura IEEE 754 (float, 32 bits):
[1 bit signo | 8 bits exponente | 23 bits mantisa]

2.2.3 Carácter (Char)

Representa un único carácter. Usa codificación ASCII (7/8 bits, 128/256 caracteres) o Unicode/UTF-8 (hasta 4 bytes, millones de caracteres).

ASCII: 'A' = 65, 'a' = 97, '0' = 48
Char en C: char c = 'A';   // almacena el valor 65

2.2.4 Booleano (Boolean)

Solo dos valores: true (verdadero) o false (falso). Internamente se representa con 1 bit (o 1 byte por eficiencia).

boolean activo = true;
boolean terminado = false;

2.3 Tipos Compuestos o Estructurados

// Enum en C
enum DiaSemana { LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO };
enum DiaSemana hoy = MIERCOLES;  // hoy vale 2 (empieza en 0)

2.4 Tipos Especiales

// Puntero en C
int x = 10;
int *ptr = &x;   // ptr apunta a la dirección de x
printf("%d", *ptr);  // imprime 10 (desreferencia)

2.5 Conversión de Tipos


3. Operadores

3.1 Operadores Aritméticos

Operador Operación Ejemplo Resultado
+ Suma 5 + 3 8
- Resta 5 - 3 2
* Multiplicación 5 * 3 15
/ División 7 / 2 3 (enteros) / 3.5 (reales)
% Módulo (resto) 7 % 3 1
** o ^ Potencia 2 ** 3 8

Importante (oposición): En división entera, 7 / 2 = 3 (se trunca). Para obtener 3.5 hay que usar 7.0 / 2 o hacer casting.

3.2 Operadores Relacionales (Comparación)

Devuelven un valor booleano (true/false).

Operador Significado Ejemplo Resultado
== Igual a 5 == 5 true
!= Distinto de 5 != 3 true
> Mayor que 5 > 3 true
< Menor que 3 < 5 true
>= Mayor o igual 5 >= 5 true
<= Menor o igual 3 <= 4 true

3.3 Operadores Lógicos

Operador Operación Descripción
&& / AND Conjunción true solo si ambos son true
\|\| / OR Disyunción true si al menos uno es true
! / NOT Negación Invierte el valor booleano
XOR Disyunción exclusiva true si exactamente uno es true

Tablas de verdad:

AND:           OR:            NOT:
A  B  A&&B    A  B  A||B    A   !A
T  T   T      T  T   T      T    F
T  F   F      T  F   T      F    T
F  T   F      F  T   T
F  F   F      F  F   F

3.4 Operadores de Asignación

Operador Equivale a Ejemplo
= Asignación simple x = 5
+= x = x + n x += 3
-= x = x - n x -= 3
*= x = x * n x *= 2
/= x = x / n x /= 2
%= x = x % n x %= 3

3.5 Operadores de Incremento/Decremento

int x = 5;
x++;    // Post-incremento: usa x (=5) luego suma 1 → x=6
++x;    // Pre-incremento: suma 1 primero → x=7, usa x (=7)
x--;    // Post-decremento
--x;    // Pre-decremento

3.6 Operadores de Bits (Bitwise)

Operador Operación Ejemplo (4 bits)
& AND bit a bit 1010 & 1100 = 1000
\| OR bit a bit 1010 \| 1100 = 1110
^ XOR bit a bit 1010 ^ 1100 = 0110
~ NOT bit a bit ~1010 = 0101
<< Desplazamiento izquierda 0001 << 2 = 0100 (×4)
>> Desplazamiento derecha 1000 >> 2 = 0010 (÷4)

3.7 Precedencia de Operadores (de mayor a menor)

1. () → Paréntesis
2. ! ~ ++ -- → Unarios
3. * / %      → Multiplicativos
4. + -        → Aditivos
5. << >>      → Desplazamiento
6. < <= > >=  → Relacionales
7. == !=      → Igualdad
8. &          → AND bit a bit
9. ^          → XOR bit a bit
10. |         → OR bit a bit
11. &&        → AND lógico
12. ||        → OR lógico
13. ?:        → Ternario
14. = += -=   → Asignación

4. Instrucciones Condicionales

4.1 Concepto

Las instrucciones condicionales permiten alterar el flujo de ejecución del programa en función de si una condición es verdadera o falsa.

4.2 IF / IF-ELSE / IF-ELSE IF

Sintaxis general (pseudocódigo):

SI condición ENTONCES
    instrucciones
SINO SI condición2 ENTONCES
    instrucciones
SINO
    instrucciones
FIN SI

En Java/C:

int nota = 7;

if (nota >= 9) {
    System.out.println("Sobresaliente");
} else if (nota >= 7) {
    System.out.println("Notable");
} else if (nota >= 5) {
    System.out.println("Aprobado");
} else {
    System.out.println("Suspenso");
}
// Salida: Notable

En Python:

nota = 7
if nota >= 9:
    print("Sobresaliente")
elif nota >= 7:
    print("Notable")
elif nota >= 5:
    print("Aprobado")
else:
    print("Suspenso")

4.3 SWITCH / CASE

Alternativa al if-else encadenado cuando se compara una variable contra múltiples valores constantes.

// Java
int dia = 3;
switch (dia) {
    case 1:
        System.out.println("Lunes");
        break;
    case 2:
        System.out.println("Martes");
        break;
    case 3:
        System.out.println("Miércoles");
        break;
    default:
        System.out.println("Otro día");
}
// Salida: Miércoles

Importante: Sin break, el flujo "cae" al siguiente caso (fall-through). En las oposiciones es un error frecuente.

// Pseudocódigo
SEGUN variable HACER
    CASO valor1: instrucciones
    CASO valor2: instrucciones
    POR DEFECTO: instrucciones
FIN SEGUN

4.4 Operador Ternario

Forma compacta de un if-else simple:

// condicion ? valor_si_true : valor_si_false
int max = (a > b) ? a : b;
String estado = (activo) ? "Activo" : "Inactivo";

4.5 Evaluación en Cortocircuito

// Si (a > 0) es false, NO se evalúa (b / a)
// Esto evita división por cero
if (a > 0 && b / a > 2) { ... }

// Si (x != null) es false, NO se evalúa x.length()
// Esto evita NullPointerException
if (x != null && x.length() > 0) { ... }

5. Bucles y Recursividad

5.1 Concepto de Bucle

Un bucle (o ciclo) permite ejecutar un bloque de instrucciones repetidamente mientras se cumpla una condición.

Elementos de un bucle:
- Inicialización: valor de partida del contador/variable de control.
- Condición: expresión booleana que determina si el bucle continúa.
- Actualización: modificación de la variable de control en cada iteración.
- Cuerpo: instrucciones que se repiten.

5.2 Bucle WHILE (mientras)

Se comprueba la condición antes de ejecutar el cuerpo. Puede que no se ejecute ninguna vez.

// Java
int i = 0;
while (i < 5) {
    System.out.println("Iteración: " + i);
    i++;
}
// Imprime 0, 1, 2, 3, 4
MIENTRAS condicion HACER
    instrucciones
FIN MIENTRAS

5.3 Bucle DO-WHILE (hacer-mientras)

Se ejecuta el cuerpo al menos una vez, y luego se comprueba la condición.

int i = 0;
do {
    System.out.println("Iteración: " + i);
    i++;
} while (i < 5);
HACER
    instrucciones
MIENTRAS condicion

Diferencia clave (oposición): while puede ejecutarse 0 veces; do-while se ejecuta al menos 1 vez.

5.4 Bucle FOR (para)

Ideal cuando se conoce el número de iteraciones de antemano.

// Java
for (int i = 0; i < 5; i++) {
    System.out.println("i = " + i);
}

// For mejorado (for-each) para colecciones
int[] numeros = {10, 20, 30, 40};
for (int n : numeros) {
    System.out.println(n);
}
# Python
for i in range(5):        # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 10, 2): # 2, 4, 6, 8
    print(i)
PARA i DESDE 1 HASTA 10 PASO 1 HACER
    instrucciones
FIN PARA

5.5 Control de Bucles

Instrucción Acción
break Sale inmediatamente del bucle
continue Salta a la siguiente iteración
return Sale del método/función completo
for (int i = 0; i < 10; i++) {
    if (i == 3) continue;  // Salta el 3
    if (i == 7) break;     // Sale del bucle al llegar a 7
    System.out.print(i + " "); // Imprime: 0 1 2 4 5 6
}

5.6 Recursividad

La recursividad es una técnica en la que una función se llama a sí misma para resolver un problema, dividiéndolo en subproblemas más pequeños del mismo tipo.

Requisitos para que sea correcta:
1. Caso base: condición que detiene la recursión (sin él → bucle infinito / desbordamiento de pila).
2. Caso recursivo: la función se llama a sí misma con un argumento que se acerca al caso base.

Factorial (n!)

n! = n × (n-1) × (n-2) × ... × 1
0! = 1  (caso base)
// Java - Recursivo
int factorial(int n) {
    if (n == 0) return 1;           // Caso base
    return n * factorial(n - 1);    // Caso recursivo
}
// factorial(5) = 5 × 4 × 3 × 2 × 1 = 120
// Java - Iterativo (equivalente)
int factorialIterativo(int n) {
    int resultado = 1;
    for (int i = 1; i <= n; i++) {
        resultado *= i;
    }
    return resultado;
}

Fibonacci

F(0) = 0, F(1) = 1
F(n) = F(n-1) + F(n-2)
int fibonacci(int n) {
    if (n <= 1) return n;                       // Casos base
    return fibonacci(n - 1) + fibonacci(n - 2); // Caso recursivo
}
// fibonacci(6) = 0,1,1,2,3,5,8 → 8

Traza de recursión — Factorial(4)

factorial(4)
  → 4 * factorial(3)
        → 3 * factorial(2)
              → 2 * factorial(1)
                    → 1 * factorial(0)
                          → 1  (caso base)
                    → 1 * 1 = 1
              → 2 * 1 = 2
        → 3 * 2 = 6
  → 4 * 6 = 24

Recursión vs Iteración

Aspecto Recursión Iteración
Legibilidad Alta (problemas divisibles) Alta (secuencial)
Memoria Mayor (pila de llamadas) Menor
Riesgo Stack Overflow Bucle infinito
Rendimiento Menor (overhead de llamadas) Mayor
Uso ideal Árboles, grafos, divide y vencerás Cálculos simples

Tipos de Recursión


6. Procedimientos, Funciones y Parámetros

6.1 Concepto

Un subprograma (procedimiento o función) es un bloque de código con nombre que realiza una tarea específica y puede ser invocado desde cualquier parte del programa.

Ventajas:
- Reutilización: escribir una vez, usar muchas.
- Modularidad: dividir el problema en partes manejables.
- Abstracción: ocultar detalles de implementación.
- Mantenimiento: cambios localizados.

6.2 Procedimientos vs Funciones

Característica Procedimiento Función
Devuelve valor No
Palabra clave void / procedure function / tipo de retorno
Propósito Realizar una acción Calcular y devolver un resultado
// Procedimiento (no devuelve nada)
void mostrarBienvenida(String nombre) {
    System.out.println("Bienvenido, " + nombre + "!");
}

// Función (devuelve un valor)
int sumar(int a, int b) {
    return a + b;
}

// Uso
mostrarBienvenida("Ana");     // Llama al procedimiento
int resultado = sumar(3, 5);  // Llama a la función → resultado = 8

6.3 Parámetros y Argumentos

6.4 Formas de Paso de Parámetros

Por Valor (Pass by Value)

Se copia el valor. Cambios en la función NO afectan a la variable original.

void duplicar(int x) {
    x = x * 2;     // Solo modifica la copia local
    System.out.println("Dentro: " + x); // 10
}

int num = 5;
duplicar(num);
System.out.println("Fuera: " + num); // Sigue siendo 5

Por Referencia (Pass by Reference)

Se pasa la dirección de memoria. Cambios en la función SÍ afectan a la variable original.

// En C, se simula con punteros
void duplicar(int *x) {
    *x = *x * 2;   // Modifica el valor en la dirección apuntada
}

int num = 5;
duplicar(&num);
printf("%d", num);  // num ahora es 10
// En Java: los objetos se pasan por referencia de valor
// (se pasa la referencia, no el objeto completo)
void modificar(int[] arr) {
    arr[0] = 99;  // Sí modifica el array original
}

Resumen para oposición: En Java, los tipos primitivos se pasan por valor; los objetos y arrays se pasan por referencia (técnicamente, la referencia por valor).

Por Nombre (Pass by Name)

La expresión del argumento se evalúa cada vez que se usa el parámetro dentro de la función. Usado en ALGOL. Poco común hoy.

6.5 Ámbito (Scope) de Variables

int global = 100;  // Variable global

void ejemplo() {
    int local = 50;         // Variable local
    System.out.println(global); // OK: accede a la global
    System.out.println(local);  // OK: accede a la local
}
// Aquí NO se puede acceder a 'local'

6.6 Recursividad en Funciones

Cada llamada recursiva crea un nuevo marco de pila (stack frame) con sus propias variables locales.

Pila de llamadas para factorial(3):
┌─────────────────┐
│ factorial(0)=1  │  ← cima (último en entrar)
├─────────────────┤
│ factorial(1)=1  │
├─────────────────┤
│ factorial(2)=2  │
├─────────────────┤
│ factorial(3)=6  │  ← base
└─────────────────┘

6.7 Sobrecarga de Funciones (Overloading)

Mismo nombre de función, diferente número o tipo de parámetros.

int sumar(int a, int b) { return a + b; }
double sumar(double a, double b) { return a + b; }
int sumar(int a, int b, int c) { return a + b + c; }

sumar(1, 2);        // llama a la primera
sumar(1.5, 2.5);    // llama a la segunda
sumar(1, 2, 3);     // llama a la tercera

7. Vectores y Registros

7.1 Vectores (Arrays)

Concepto

Un vector (o array / tabla) es una estructura de datos que almacena un conjunto de elementos del mismo tipo en posiciones de memoria contiguas, accesibles mediante un índice.

Características

Declaración e Inicialización

// Java
int[] notas = new int[5];          // Vector de 5 enteros (sin inicializar → todos 0)
int[] pares = {2, 4, 6, 8, 10};   // Con inicialización directa

pares[0] = 2;   // Primer elemento
pares[4] = 10;  // Último elemento
// pares[5] → ArrayIndexOutOfBoundsException (fuera de rango)
// C
int notas[5];                    // Declara 5 enteros
int pares[] = {2, 4, 6, 8, 10}; // Con inicialización
notas[0] = 7;                    // Acceso
# Python (listas dinámicas)
notas = [0] * 5            # Lista de 5 ceros
pares = [2, 4, 6, 8, 10]
print(pares[2])            # 6

Recorrido de un Vector

int[] v = {5, 3, 8, 1, 9};

// Recorrido con for clásico
for (int i = 0; i < v.length; i++) {
    System.out.print(v[i] + " "); // 5 3 8 1 9
}

// Recorrido con for-each
for (int elem : v) {
    System.out.print(elem + " ");
}

Búsqueda en un Vector

// Búsqueda lineal: O(n)
int buscarLineal(int[] v, int objetivo) {
    for (int i = 0; i < v.length; i++) {
        if (v[i] == objetivo) return i;  // Devuelve el índice
    }
    return -1;  // No encontrado
}

// Búsqueda binaria (el vector debe estar ORDENADO): O(log n)
int buscarBinaria(int[] v, int objetivo) {
    int izq = 0, der = v.length - 1;
    while (izq <= der) {
        int medio = (izq + der) / 2;
        if (v[medio] == objetivo) return medio;
        else if (v[medio] < objetivo) izq = medio + 1;
        else der = medio - 1;
    }
    return -1;
}

Ordenación de un Vector (Burbuja)

// Bubble Sort: O(n²)
void burbuja(int[] v) {
    int n = v.length;
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (v[j] > v[j + 1]) {
                // Intercambio
                int temp = v[j];
                v[j] = v[j + 1];
                v[j + 1] = temp;
            }
        }
    }
}

Arrays Multidimensionales (Matrices)

// Matriz 3×3 en Java
int[][] matriz = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// Acceso: matriz[fila][columna]
System.out.println(matriz[1][2]);  // 6 (fila 1, columna 2)

// Recorrido
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        System.out.print(matriz[i][j] + " ");
    }
    System.out.println();
}

7.2 Registros (Structs / Records)

Concepto

Un registro (struct en C, record en Pascal) es una estructura de datos que agrupa variables de distintos tipos bajo un mismo nombre. Equivale a un objeto simple (sin métodos).

Declaración y Uso en C

// Definición del tipo registro
struct Alumno {
    char nombre[50];
    int edad;
    float nota;
};

// Uso
struct Alumno a1;
strcpy(a1.nombre, "María García");
a1.edad = 22;
a1.nota = 8.5;

// Acceso a campos con el operador punto (.)
printf("Nombre: %s\n", a1.nombre);
printf("Nota: %.1f\n", a1.nota);

Registros en Pascal

TYPE
  TAlumno = RECORD
    nombre : STRING[50];
    edad   : INTEGER;
    nota   : REAL;
  END;

VAR
  alumno1 : TAlumno;

BEGIN
  alumno1.nombre := 'María';
  alumno1.edad   := 22;
  alumno1.nota   := 8.5;
END.

Equivalente en Java (Clase sin métodos)

class Alumno {
    String nombre;
    int edad;
    double nota;
}

Alumno a = new Alumno();
a.nombre = "María García";
a.edad = 22;
a.nota = 8.5;

7.3 Arrays de Registros

Combinación potente: lista de registros.

struct Alumno clase[30];  // Array de 30 alumnos

// Inicializar el primero
strcpy(clase[0].nombre, "Ana López");
clase[0].edad = 20;
clase[0].nota = 7.5;

// Recorrer y mostrar todos
for (int i = 0; i < 30; i++) {
    printf("%s - %d años - %.1f\n",
        clase[i].nombre, clase[i].edad, clase[i].nota);
}

7.4 Diferencias Clave: Vector vs Registro

Característica Vector (Array) Registro (Struct)
Tipos de datos Homogéneo (mismo tipo) Heterogéneo (distintos tipos)
Acceso Por índice numérico Por nombre de campo
Tamaño Fijo en declaración Definido en la estructura
Uso típico Colecciones del mismo tipo Representar una entidad

8. Estructura de un Programa

8.1 Estructura General

Todo programa tiene al menos tres partes conceptuales:

┌─────────────────────────────┐
│       CABECERA              │  Nombre, metadatos, imports
├─────────────────────────────┤
│    DECLARACIONES GLOBALES   │  Constantes, tipos, variables globales
├─────────────────────────────┤
│    SUBPROGRAMAS             │  Funciones y procedimientos
├─────────────────────────────┤
│    PROGRAMA PRINCIPAL       │  Punto de entrada (main)
└─────────────────────────────┘

8.2 Estructura en Pseudocódigo

PROGRAMA nombre_del_programa

CONSTANTES
    PI = 3.14159
    MAX = 100

TIPOS
    TAlumno = REGISTRO
        nombre: CADENA
        nota: REAL
    FIN REGISTRO

VARIABLES
    edad: ENTERO
    nombre: CADENA

FUNCIÓN calcularArea(radio: REAL): REAL
INICIO
    DEVOLVER PI * radio * radio
FIN FUNCIÓN

PROCEDIMIENTO mostrar(texto: CADENA)
INICIO
    ESCRIBIR(texto)
FIN PROCEDIMIENTO

INICIO   // Programa principal
    nombre ← "Ana"
    edad ← 25
    mostrar("Hola, " + nombre)
    ESCRIBIR(calcularArea(5.0))
FIN

8.3 Estructura en C

/* ====== Cabecera ====== */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* ====== Constantes ====== */
#define MAX 100
#define PI 3.14159

/* ====== Tipos definidos por el usuario ====== */
typedef struct {
    char nombre[50];
    int edad;
    float nota;
} Alumno;

/* ====== Variables globales ====== */
int contador = 0;

/* ====== Declaración de funciones ====== */
float calcularMedia(float notas[], int n);
void mostrarAlumno(Alumno a);

/* ====== Función principal ====== */
int main() {
    // Declaraciones locales
    float notas[] = {7.5, 8.0, 6.5, 9.0};
    Alumno a1;

    // Instrucciones
    strcpy(a1.nombre, "Carlos Ruiz");
    a1.edad = 21;
    a1.nota = calcularMedia(notas, 4);

    mostrarAlumno(a1);

    return 0;  // 0 indica ejecución exitosa
}

/* ====== Implementación de funciones ====== */
float calcularMedia(float notas[], int n) {
    float suma = 0;
    for (int i = 0; i < n; i++) suma += notas[i];
    return suma / n;
}

void mostrarAlumno(Alumno a) {
    printf("Nombre: %s\nEdad: %d\nNota: %.2f\n",
           a.nombre, a.edad, a.nota);
}

8.4 Estructura en Java

/* ====== Paquete e imports ====== */
package com.ejemplo;

import java.util.Scanner;

/* ====== Clase principal ====== */
public class GestionAlumnos {

    /* ====== Constantes de clase ====== */
    static final int MAX_ALUMNOS = 30;

    /* ====== Atributos de clase ====== */
    static int totalAlumnos = 0;

    /* ====== Método principal ====== */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Introduce una nota: ");
        double nota = sc.nextDouble();

        String calificacion = obtenerCalificacion(nota);
        System.out.println("Calificación: " + calificacion);

        sc.close();
    }

    /* ====== Métodos auxiliares ====== */
    static String obtenerCalificacion(double nota) {
        if (nota >= 9) return "Sobresaliente";
        else if (nota >= 7) return "Notable";
        else if (nota >= 5) return "Aprobado";
        else return "Suspenso";
    }

    static double calcularMedia(double[] notas) {
        double suma = 0;
        for (double n : notas) suma += n;
        return suma / notas.length;
    }
}

8.5 Estructura en Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Módulo de gestión de alumnos
"""

# ====== Imports ======
import sys

# ====== Constantes ======
MAX_ALUMNOS = 30
PI = 3.14159

# ====== Funciones ======
def calcular_media(notas: list) -> float:
    """Calcula la media de una lista de notas."""
    if not notas:
        return 0.0
    return sum(notas) / len(notas)

def obtener_calificacion(nota: float) -> str:
    """Devuelve la calificación textual de una nota."""
    if nota >= 9:
        return "Sobresaliente"
    elif nota >= 7:
        return "Notable"
    elif nota >= 5:
        return "Aprobado"
    else:
        return "Suspenso"

# ====== Programa principal ======
def main():
    notas = [7.5, 8.0, 9.5, 6.0, 5.5]
    media = calcular_media(notas)
    calificacion = obtener_calificacion(media)

    print(f"Media: {media:.2f}")
    print(f"Calificación: {calificacion}")

if __name__ == "__main__":
    main()

8.6 Fases de Ejecución de un Programa

1. ESCRITURA      → El programador escribe el código fuente (.c, .java, .py)
2. COMPILACIÓN    → El compilador traduce a código objeto / bytecode
3. ENLAZADO       → El linker une código objeto con bibliotecas → ejecutable
4. CARGA          → El SO carga el ejecutable en memoria RAM
5. EJECUCIÓN      → La CPU ejecuta las instrucciones
6. FINALIZACIÓN   → El programa libera recursos y devuelve el control al SO

8.7 Áreas de Memoria en Ejecución

┌──────────────────────────────┐  Dirección alta
│          PILA (Stack)        │  Variables locales, marcos de función
│      (crece hacia abajo)     │
├──────────────────────────────┤
│                              │
│          MONTÓN (Heap)       │  Memoria dinámica (new, malloc)
│       (crece hacia arriba)   │
│                              │
├──────────────────────────────┤
│   SEGMENTO DE DATOS (.data)  │  Variables globales y estáticas
├──────────────────────────────┤
│   SEGMENTO DE CÓDIGO (.text) │  Instrucciones del programa
└──────────────────────────────┘  Dirección baja

RESUMEN PARA OPOSICIÓN — PUNTOS CLAVE

Tema Concepto Crítico
Lenguajes Compilador genera ejecutable; intérprete ejecuta línea a línea
Tipos IEEE 754 para flotantes; complemento a 2 para enteros negativos
Operadores Precedencia: ! > * / > + - > comparación > && > \|\|
Condicionales switch sin break produce fall-through
Bucles while puede ejecutarse 0 veces; do-while al menos 1 vez
Recursividad Siempre necesita caso base; usa la pila de llamadas
Paso de parámetros Por valor: no modifica original; por referencia: sí modifica
Arrays Homogéneos, índice desde 0, acceso O(1)
Registros Heterogéneos, acceso por nombre de campo
Estructura Todo programa: cabecera + declaraciones + subprogramas + main

Guía elaborada para preparación de oposiciones. Temas: Lenguajes de Programación, Tipos de Datos, Operadores, Condicionales, Bucles, Recursividad, Funciones, Vectores, Registros y Estructura de Programas.