Introducción¶
Antes de escribir tu primera línea de código en C, es fundamental repasar (y comprender) algunos conceptos básicos sobre cómo funcionan las computadoras y cómo comunicarnos con ellas de manera efectiva. En este apunte, sentaremos las bases algorítmicas de forma independiente de cualquier lenguaje, utilizando un pseudocódigo estructurado similar a C en español. Esto te permitirá concentrarte en el pensamiento lógico antes de abordar la sintaxis formal de C.
Desarrollo¶
¿Qué es una computadora?¶
Una computadora es una máquina electrónica diseñada para procesar información de manera automática, siguiendo instrucciones precisas y explícitas. A diferencia de los seres humanos, una computadora:
No entiende ambigüedades: necesita instrucciones exactas y sin interpretación posible.
No tiene intuición: hace exactamente lo que le decimos, ni más ni menos, sin asumir nada.
Es extremadamente rápida: puede ejecutar millones (o incluso miles de millones) de instrucciones por segundo.
Es determinista y sigue instrucciones de forma estricta: ejecuta exactamente las instrucciones que le proporcionamos, pero su aritmética física está limitada por el almacenamiento finito de datos. No comete “descuidos” humanos, pero la representación matemática en hardware (por ejemplo, de números reales mediante el estándar IEEE 754) tiene imprecisiones de redondeo y límites de rango (desbordamiento o subdesbordamiento).
No se cansa: puede repetir la misma operación millones de veces sin degradación en su rendimiento.
Componentes básicos¶
Para entender cómo programar, es útil conocer los componentes físicos de una computadora y cómo interactúan entre sí.
Hardware¶
El hardware son los componentes físicos de la computadora:
Procesador (CPU): El “cerebro” que ejecuta las instrucciones. Realiza operaciones aritméticas, lógicas y de control. Su velocidad se mide en GHz (gigahertz).
Memoria RAM: Memoria de acceso rápido donde se guardan temporalmente los datos y programas mientras se ejecutan. Es volátil: se borra por completo cuando se apaga o reinicia el equipo.
Almacenamiento permanente: Disco duro (HDD) o unidad de estado sólido (SSD) donde se guardan archivos, programas y el sistema operativo de forma persistente.
Dispositivos de entrada: Permiten introducir información (teclado, mouse, sensores, etc.).
Dispositivos de salida: Permiten obtener información (pantalla, parlantes, impresoras, etc.).
Arquitectura básica de una computadora: el CPU coordina el flujo de datos entre la memoria RAM (rápida y volátil), el almacenamiento permanente (lento pero persistente), y los dispositivos de entrada/salida.
Software¶
El software son los programas e instrucciones de control:
Sistema operativo: El programa fundamental que controla directamente el hardware y proporciona servicios básicos a las aplicaciones. Actúa como intermediario directo.
Programas o aplicaciones: Software diseñado para realizar tareas específicas para el usuario (editores de texto, navegadores, compiladores).
Código fuente: Las instrucciones estructuradas que los programadores escriben en lenguajes de programación. Este código debe ser traducido a código de máquina (código binario de instrucciones de CPU) para que el procesador pueda ejecutarlo.
Las aplicaciones utilizan los servicios del sistema operativo, que a su vez controla y gestiona el hardware.
¿Qué es programar?¶
Programar es el proceso de estructurar instrucciones detalladas para que una computadora realice una tarea específica.
Cuando programamos, debemos considerar:
¿Qué problema queremos resolver? - Entender el objetivo.
¿Qué datos necesitamos? - Identificar las entradas de información y las salidas resultantes.
¿Qué pasos seguir? - Diseñar el algoritmo.
¿Cómo traducirlo a código? - Escribir en un lenguaje de programación.
¿Funciona correctamente? - Probar y depurar.
Especificación Formal: Máquina de Transición de Estados¶
En lugar de analogías informales, en ciencias de la computación modelamos los algoritmos como un sistema formal que transforma un conjunto de entradas () en un conjunto de salidas () a través de una secuencia finita de transiciones de estado ().
Consideremos el algoritmo de control de un sistema de autenticación de sensor
industrial. El algoritmo debe procesar una señal física (una secuencia de
caracteres ASCII que ingresa de a un byte por vez) y determinar si se ha
recibido la clave de activación exacta ON.
Entradas (): Caracteres individuales recibidos secuencialmente desde el puerto serial: .
Salidas (): Señal de estado de activación: .
Estados del Algoritmo (): El estado interno cambia según el avance de la coincidencia detectada:
: Estado de reposo (esperando primer carácter
O).: Primer carácter correcto recibido (esperando
N).: Secuencia completada (emitiendo señal
ACTIVO).
A continuación se detalla la tabla de transición que define formalmente el comportamiento unívoco de este algoritmo:
Table 1:Tabla de Transición de Estados del Algoritmo
| Estado Actual () | Evento / Entrada () | Siguiente Estado () | Salida Emitida () |
|---|---|---|---|
| (Reposo) | 'O' | (Coincidencia parcial) | BLOQUEADO |
| (Reposo) | Cualquier otro carácter | (Reposo) | BLOQUEADO |
| (Parcial) | 'N' | (Activado) | ACTIVO |
| (Parcial) | 'O' | (Coincidencia parcial) | BLOQUEADO |
| (Parcial) | Cualquier otro carácter | (Reposo) | BLOQUEADO |
| (Activado) | Cualquier carácter | (Reposo) | BLOQUEADO |
Este modelo formal demuestra que un algoritmo no es una receta subjetiva, sino una definición determinista de comportamiento donde cada combinación de estado interno y datos de entrada produce una transición y una salida perfectamente predecibles.
La computadora necesita instrucciones de este segundo tipo: específicas, ordenadas, sin ambigüedades y detalladas al extremo.
¿Qué es un algoritmo?¶
Un algoritmo es una secuencia finita, ordenada y no ambigua de pasos bien definidos que resuelve un problema o realiza una tarea específica. Los algoritmos son la base fundamental de la programación y el diseño de sistemas.
El algoritmo es el puente conceptual que transforma un problema de entrada en su solución.
Características de un buen algoritmo¶
Un algoritmo efectivo debe cumplir con los siguientes vectores de diseño:
Finito: Debe finalizar en algún momento, después de un número determinado de pasos ejecutados.
Bien definido: Cada paso debe ser unívoco, claro y libre de toda ambigüedad en su interpretación.
Con entrada (opcional): Puede recibir cero o más datos iniciales del entorno para procesar.
Con salida: Debe retornar o producir al menos un resultado o cambio de estado visible.
Efectivo: Cada paso debe ser realizable y computable en un tiempo finito utilizando recursos de memoria finitos.
Determinista: Dado el mismo conjunto de datos de entrada, debe producir siempre exactamente el mismo resultado de salida.
Representación de Algoritmos y Diagramas de Flujo¶
Los diagramas de flujo son representaciones gráficas estandarizadas de algoritmos. Permiten visualizar la lógica de control, bifurcaciones e iteraciones antes de escribir código.
Símbolos estándar de diagramas de flujo¶
Símbolos universales utilizados en diagramas de flujo para representar diferentes procesos de un algoritmo.
Óvalo / Elipse: Representa el inicio o el fin del algoritmo.
Rectángulo: Representa un proceso o instrucción de cómputo (cálculos, asignación de variables).
Rombo: Representa un decisión o bifurcación condicional. Posee una pregunta adentro y al menos dos caminos de salida (generalmente Sí y No).
Paralelogramo: Representa operaciones de entrada y salida de datos (leer entrada del usuario o mostrar un mensaje por pantalla).
Flechas de flujo: Indican la dirección lógica de ejecución del algoritmo.
Ejemplos de Algoritmos en Pseudocódigo y Diagramas de Flujo¶
Ejemplo 1: Algoritmo para hacer café¶
Homogeneizando la estructura cotidiana mediante ramificaciones secuenciales condicionales:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24================================================= Algoritmo: Hacer café ================================================= Entrada: ninguna Salida: taza de café servida ------------------------------------------------- Pasos: 1. Inicio 2. Verificar depósito de agua 3. Si (depósito de agua está vacío) entonces: a. Llenar depósito con agua Sino: b. No hacer nada 4. Verificar portafiltro 5. Si (filtro está sucio o ausente) entonces: a. Limpiar portafiltro y colocar filtro nuevo Sino: b. No hacer nada 6. Agregar 2 cucharadas de café molido al filtro 7. Encender cafetera 8. Esperar a que finalice el filtrado de agua 9. Servir café en una taza limpia 10. Fin =================================================
Ejemplo 2: Verificar si N es par¶
Este algoritmo calcula si un número entero es par utilizando el operador módulo
% (resto de la división entera):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16================================================= Algoritmo: Verificar si N es par ================================================= Entrada: número entero N Salida: mensaje por pantalla "par" o "impar" ------------------------------------------------- Pasos: 1. Inicio 2. Leer N 3. entero resto = N % 2 4. Si (resto == 0) entonces: a. Escribir "El número es par" Sino: b. Escribir "El número es impar" 5. Fin =================================================
Representación de datos y memoria¶
Las computadoras operan sobre datos almacenados en memoria física. Para procesar esta información, es necesario asignarle un tipo de dato que defina su rango y operaciones válidas.
Tipos de información fundamentales¶
Los cuatro tipos de datos fundamentales: enteros, reales, cadenas de caracteres y valores lógicos.
Enteros (
entero/int): Números sin parte fraccionaria (ej.5,-20,0). Se utilizan para conteos, índices de lazos y posiciones.Decimales / Punto Flotante (
float/double): Representan aproximaciones numéricas finitas de números racionales bajo el estándar internacional IEEE 754.Carácter (
char): Representa un único símbolo físico (letra, dígito, signo de puntuación) que ocupa exactamente 1 byte de memoria RAM.Lógicos / Booleanos (
logico/bool): Solo admiten dos estados lógicos:verdadero(true) ofalso(false).
Variables: Direcciones físicas de memoria¶
Una variable es un espacio reservado en la memoria física RAM de la computadora para almacenar un dato que puede cambiar durante la ejecución del programa.
Visualmente, una variable vincula una etiqueta lógica con una dirección física en el hardware:
1 2 3 4 5 6 7+------------------------------------------+ | Dirección Física (ej. 0x7ffd8) | <- Celda en la memoria RAM +------------------------------------------+ | nombre: edad | <- Identificador de la variable | tipo: entero | <- Tipo de dato asignado | valor: 25 | <- Dato de almacenamiento actual +------------------------------------------+
Cada variable posee:
Dirección física de memoria: La dirección hexadecimal real en el hardware RAM donde se ubica el dato.
Nombre (identificador): La etiqueta lógica que usa el programador en el código (ej.
edad,temperatura).Tipo de dato: Define el tamaño en bytes reservado y cómo el hardware interpretará los bits guardados.
Valor: El contenido binario actual de la celda de memoria.
El ciclo de vida de una variable en memoria¶
Una variable se declara e inicializa en memoria, es leída o modificada durante la ejecución, y finalmente se libera de la memoria física.
Estructuras lógicas y operaciones básicas¶
Operaciones aritméticas¶
A nivel de hardware, se ejecutan operaciones aritméticas sobre celdas numéricas:
Operaciones aritméticas básicas y especiales, con precedencia de evaluación.
Módulo
%: Retorna el resto de la división entera. Es útil para evaluar paridad (N % 2 == 0) o extraer dígitos.Precedencia estándar: 1. Paréntesis
(), 2. Potencias, 3. Multiplicación/División/Módulo, 4. Suma/Resta.
Operaciones lógicas y tablas de verdad¶
Las operaciones lógicas combinan valores booleanos para evaluar condiciones complejas:
Las tres operaciones lógicas fundamentales (Y, O, NO) con sus tablas de verdad.
AND (
y): Da verdadero únicamente si ambos operandos son verdaderos.OR (
o): Da verdadero si al menos uno de los operandos es verdadero.NOT (
no): Invierte el estado lógico.
Las Tres Estructuras Fundamentales del Pensamiento Lógico¶
Todo algoritmo de control estructurado puede resolverse utilizando únicamente tres estructuras lógicas:
Las tres estructuras fundamentales del pensamiento algorítmico: secuencia, decisión y repetición.
1. Secuencia¶
Ejecución lineal de instrucciones en orden cronológico estricto de arriba hacia abajo. El cambio del orden de los factores altera el resultado lógico o provoca fallas en tiempo de ejecución.
2. Decisiones (Condicionales)¶
Bifurcación del flujo lógico en base al resultado de una condición booleana
(Si... Sino).
3. Repetición (Lazos)¶
Estructuras de iteración de código. Se clasifican didácticamente en:
Lazo controlado por contador (
Para/for): Utilizado cuando el límite de iteraciones es conocido de antemano.Lazo controlado por condición (
Mientras/while): Utilizado cuando la parada del lazo depende de una expresión lógica evaluada dinámicamente.
Ejemplos de Programas Traducidos a Pseudocódigo Estricto (Estilo C)¶
A continuación se presentan los ejemplos lógicos resueltos en pseudocódigo estricto con sintaxis cercana a C en español, eliminando dependencias de lenguajes interpretados dinámicos.
Ejemplo 1: Calculadora simple¶
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// Algoritmo: Calculadora Simple // Entrada: dos números reales y un carácter de operación // Salida: el resultado de la operación matemática por pantalla real numero1; real numero2; real resultado; caracter operacion; Escribir("=== CALCULADORA SIMPLE ==="); Escribir("Ingrese el primer número: "); Leer(numero1); Escribir("Ingrese el segundo número: "); Leer(numero2); Escribir("Ingrese la operación (+, -, *, /): "); Leer(operacion); Si (operacion == '+') { resultado = numero1 + numero2; Escribir("Resultado: ", resultado); } Sino Si (operacion == '-') { resultado = numero1 - numero2; Escribir("Resultado: ", resultado); } Sino Si (operacion == '*') { resultado = numero1 * numero2; Escribir("Resultado: ", resultado); } Sino Si (operacion == '/') { Si (numero2 != 0.0) { resultado = numero1 / numero2; Escribir("Resultado: ", resultado); } Sino { Escribir("Error: No se puede dividir por cero."); } } Sino { Escribir("Error: Operación no válida."); }
Ejemplo 2: Tabla de multiplicar¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21// Algoritmo: Tabla de Multiplicar // Entrada: un número entero // Salida: la tabla de multiplicar de N del 1 al 10 entero numero; entero contador; entero resultado; Escribir("=== TABLA DE MULTIPLICAR ==="); Escribir("Ingrese un número: "); Leer(numero); Escribir("Tabla del ", numero, ":"); Escribir("-----------------"); // Lazo controlado por contador (Para) de 1 a 10 Para (contador = 1; contador <= 10; contador = contador + 1) { resultado = numero * contador; Escribir(numero, " x ", contador, " = ", resultado); }
Ejemplo 3: Adivinar número¶
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// Algoritmo: Adivinar Número // Entrada: intento numérico del usuario // Salida: mensajes guía (mayor/menor) e indicación de éxito o derrota entero numero_secreto = 42; // Simulado para propósitos de prueba entero intentos_maximos = 5; entero intentos_realizados = 0; entero intento; logico adivinado = false; Escribir("=== ADIVINA EL NÚMERO ==="); Escribir("Tenés 5 intentos para adivinar un número entre 1 y 100"); Mientras (intentos_realizados < intentos_maximos y adivinado == false) { intentos_realizados = intentos_realizados + 1; Escribir("Intento ", intentos_realizados, " de ", intentos_maximos, ":"); Leer(intento); Si (intento == numero_secreto) { adivinado = true; Escribir("¡Adivinaste el número!"); } Sino Si (intento < numero_secreto) { Escribir("El número secreto es MAYOR"); } Sino { Escribir("El número secreto es MENOR"); } } Si (adivinado == false) { Escribir("Game Over. El número secreto era: ", numero_secreto); }
Ejercicios de Autoevaluación¶
Ejercicio 1: Instrucciones precisas¶
Solution to Exercise 1
Hacer un sándwich de jamón y queso:
Retirar 2 rebanadas de pan del paquete.
Colocar ambas rebanadas horizontalmente sobre un plato limpio.
Retirar una rebanada de jamón del paquete correspondiente.
Colocar la rebanada de jamón cubriendo la primera rebanada de pan.
Retirar una rebanada de queso del paquete.
Colocar la rebanada de queso sobre el jamón.
Tomar la segunda rebanada de pan.
Colocarla sobre el queso, tapando el sándwich.
Presionar suavemente hacia abajo para asentar el sándwich.
Calcular el promedio de tres números:
Obtener el primer número (llamémoslo A).
Obtener el segundo número (llamémoslo B).
Obtener el tercer número (llamémoslo C).
Sumar los tres valores: suma = A + B + C.
Dividir el resultado de la suma por 3: promedio = suma / 3.
Mostrar el valor del promedio obtenido.
Ejercicio 2: Tipos de variables¶
Solution to Exercise 2
entero: Se cuentan individuos discretos.real: Requiere representar centavos fraccionarios.cadena: Secuencia de caracteres alfabéticos.logico: Estado binario (verdadero/falso).real: Contiene parte fraccionaria (ej: 8.5).
Ejercicio 3: Aplicación Algorítmica¶
Solution to Exercise 3
A. Conversión de temperatura:
1 2 3 4 5 6 7 8real celsius; real fahrenheit; Escribir("Ingrese temperatura en Celsius: "); Leer(celsius); fahrenheit = celsius * 9.0 / 5.0 + 32.0; Escribir("Equivalente en Fahrenheit: ", fahrenheit);
B. Verificar triángulo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19real lado1; real lado2; real lado3; Escribir("Ingrese lado 1: "); Leer(lado1); Escribir("Ingrese lado 2: "); Leer(lado2); Escribir("Ingrese lado 3: "); Leer(lado3); Si (lado1 + lado2 > lado3 y lado1 + lado3 > lado2 y lado2 + lado3 > lado1) { Escribir("Los lados pueden formar un triángulo."); } Sino { Escribir("Los lados NO pueden formar un triángulo."); }
C. MCD (Algoritmo de Euclides):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17entero a; entero b; entero temporal; Escribir("Ingrese el primer número: "); Leer(a); Escribir("Ingrese el segundo número: "); Leer(b); Mientras (b != 0) { temporal = b; b = a % b; a = temporal; } Escribir("El MCD es: ", a);
D. Palíndromo (lazo de comparación de extremos):
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 31cadena palabra; entero longitud; entero inicio = 0; entero fin; logico coincide = true; Escribir("Ingrese la palabra: "); Leer(palabra); Escribir("Ingrese la longitud de la palabra: "); Leer(longitud); fin = longitud - 1; Mientras (inicio < fin y coincide == true) { Si (palabra[inicio] != palabra[fin]) { coincide = false; } inicio = inicio + 1; fin = fin - 1; } Si (coincide == true) { Escribir("La palabra es un palíndromo."); } Sino { Escribir("La palabra NO es un palíndromo."); }
Ejercicio 4: Integradores¶
- Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.
- Sedgewick, R., & Wayne, K. (2011). Algorithms (4th ed.). Addison-Wesley. https://algs4.cs.princeton.edu/
- Wing, J. M. (2006). Computational Thinking. Communications of the ACM, 49(3), 33–35. 10.1145/1118178.1118215
- Aho, A. V., & Ullman, J. D. (1995). Foundations of Computer Science. W. H. Freeman. http://infolab.stanford.edu/~ullman/focs.html
- Polya, G. (2014). How to Solve It: A New Aspect of Mathematical Method. Princeton University Press.
- Bentley, J. (1999). Programming Pearls (2nd ed.). Addison-Wesley.