Saltar al contenido
Topos Uranos

Resumen

Esta clase abre la primera unidad del curso, dedicada a los primeros pasos en la programación con C++. Explica para qué sirve la unidad: llevar a quien nunca ha programado desde un problema enunciado en lenguaje corriente hasta un programa que compila, se ejecuta, lee datos y escribe resultados, sabiendo qué hizo cada herramienta en el camino; presenta sus seis clases y el hilo que las une, desde el algoritmo escrito en español hasta la clasificación de los errores; precisa lo poco que se da por sabido, que es la aritmética escolar, la costumbre de seguir instrucciones escritas y el manejo de archivos y carpetas; formula el problema que la unidad resuelve, el de convertir un cálculo que se sabe hacer a mano en un procedimiento que una máquina ejecuta sin equivocarse y sin cansarse; y muestra adónde conduce, en las unidades siguientes y en el curso Programación en C++ II.

Objetivos de aprendizaje

  1. Describir la secuencia de contenidos de la unidad y explicar qué aporta cada clase a la siguiente.
  2. Reconocer los conocimientos previos que el curso supone (operar con enteros y decimales, calcular un cociente y un resto, seguir instrucciones escritas, guardar un archivo en una carpeta determinada) y repasarlos si hace falta.
  3. Explicar, con un ejemplo, el camino que la unidad enseña a recorrer: del enunciado a la especificación, de la especificación al algoritmo y del algoritmo al programa que se compila y se ejecuta.
  4. Reconocer qué se espera saber hacer al terminar la unidad, y distinguirlo de lo que se aprenderá en las unidades siguientes.

Evaluación de entrada

Antes de recorrer la unidad conviene medir el punto de partida. Esta evaluación es una autoevaluación: no se califica, y su único propósito es orientar el estudio. Como esta es la primera unidad del curso, no hay preguntas sobre unidades anteriores; en su lugar, las tres primeras comprueban lo que el curso da por sabido: el cociente y el resto de una división entera, el orden de los pasos de un procedimiento y el nombre, la extensión y la carpeta de un archivo. Las siete siguientes tocan, en orden, las ideas centrales de las seis clases de la unidad. Quien nunca haya programado no debe esperar acertarlas, y no importa: cada respuesta, acertada o no, explica el punto y nombra la clase que lo trata. Las mismas destrezas se vuelven a medir al final, en la clase de síntesis.

Evaluación de entrada

Antes de comenzar la unidad, mide tu punto de partida. Es una autoevaluación breve: no se califica y su resultado se guarda solo en tu navegador.

  1. Pregunta 1De unidades anterioresSe reparten 47 hojas entre 6 personas, en partes enteras iguales, y las que no alcanzan para una vuelta completa se guardan. ¿Cuántas recibe cada persona y cuántas se guardan?

  2. Pregunta 2De unidades anterioresPara enviar un archivo adjunto por correo electrónico hay cuatro pasos: A, escribir la dirección del destinatario; B, pulsar «Enviar»; C, abrir un mensaje nuevo; D, adjuntar el archivo. ¿Qué orden es el adecuado?

  3. Pregunta 3De unidades anterioresUn archivo está guardado en C:\Users\ana\programas\suma.cpp. ¿Cuál es su nombre, cuál su extensión y en qué carpeta está?

  4. Pregunta 4Una receta dice: «Si la masa está seca, añadir una cucharada de agua y amasar; repetir hasta que no lo esté». La masa necesita exactamente tres cucharadas para dejar de estar seca. ¿Cuántas veces se pregunta si la masa está seca?

  5. Pregunta 5¿Cuál de estas instrucciones puede seguirla cualquier persona, o una máquina, exactamente de la misma manera?

  6. Pregunta 6Un programa se compila sin errores ni avisos, se ejecuta bien con muchos datos, y con uno en particular se detiene con el mensaje «division by zero». ¿En qué momento se produjo el error?

  7. Pregunta 7Se instaló Visual Studio Code con su extensión de C++, y al pedir g++ --version en la terminal, esta responde que no reconoce g++. ¿Qué es lo más probable?

  8. Pregunta 8El compilador escribe un mensaje que comienza con warning: y, a pesar de él, produce el ejecutable. ¿Qué significa?

  9. Pregunta 9¿Dónde comienza la ejecución de un programa de C++?

  10. Pregunta 10Un programa declara int age{};, ejecuta std::cin >> age; para leer una edad, y el usuario escribe abc. ¿Qué ocurre?

Los contenidos de la unidad

La unidad tiene seis clases, que recorren en orden el camino de un problema a un programa en funcionamiento. Cada una supone la anterior, y la primera no supone nada del lenguaje.

  • Del problema al algoritmo. El curso comienza sin código, porque el algoritmo precede al programa. La clase enseña a especificar un problema por su entrada, su salida y la relación entre ambas (la precondición y la poscondición); a describir un algoritmo en pasos numerados, sin ambigüedad; a seguirlo a mano con una tabla de traza; a reconocer en él la secuencia, la decisión y la repetición; y a justificar que una repetición termina, con una cantidad que decrece en cada vuelta.
  • Programas, compiladores y C++. Un algoritmo escrito para una máquina es un programa, y un programa de C++ no se ejecuta tal como se escribe: el preprocesador, el compilador y el enlazador lo convierten en un ejecutable. La clase recorre esas tres etapas, distingue lo que se descubre al compilar de lo que solo se manifiesta al ejecutar, compara el modelo compilado con el interpretado y sitúa en el tiempo las normas del lenguaje, hasta C++23, la que el curso usa.
  • Instalar el entorno en Windows, macOS y Linux. Tres guías completas, una por sistema, para instalar un compilador capaz de C++23 y el editor Visual Studio Code con su extensión de C++, comprobar que todo funciona con un programa de prueba y resolver las fallas frecuentes: el compilador que la terminal no encuentra, la versión antigua y la norma que no se pidió.
  • Compilar, ejecutar y configurar. El ciclo de editar, guardar, compilar, ejecutar y leer, desde la terminal y desde el editor, con la orden de compilación del curso. La clase distingue los errores, que impiden el ejecutable, de los avisos, que señalan código sospechoso; activa los detectores, que vigilan el programa mientras corre; y explica por qué una salida muestra símbolos extraños en lugar de tildes y eñes.
  • Anatomía de un programa. El programa mínimo, pieza por pieza: la directiva de inclusión y las cabeceras, la función main y el código de salida, el espacio de nombres std, las sentencias, los bloques y los comentarios. La clase enseña a corregir los errores de estructura leyendo los mensajes del compilador desde el primero, y fija la guía de estilo del curso.
  • Entrada, salida y errores. El programa se comunica con el exterior: escribe con std::print y std::println, con campos de formato para el ancho y los decimales, y lee con std::cin. La clase muestra qué ocurre cuando la entrada no tiene la forma esperada y cómo se comprueba la lectura, y cierra la unidad con la clasificación de los errores por su momento: de compilación, de enlace, de ejecución y de lógica.

El hilo que las une es el del propio programa. La primera clase lo concibe, la segunda explica en qué se convierte, la tercera instala las herramientas que lo convierten, la cuarta enseña a usarlas y a escuchar lo que dicen, la quinta lo disecciona y la sexta lo pone a conversar con quien lo usa. Si esto es así, al final de la unidad el estudiante sabe todavía muy poco de C++, pero sabe cómo se trabaja con él, y eso es lo que el resto del curso supone.

Lo que se da por sabido

El curso no supone ninguna experiencia previa en programación. Supone, en cambio, tres destrezas que conviene repasar ahora, si la evaluación de entrada mostró alguna duda.

La primera es la aritmética escolar: operar con enteros y con decimales, respetar el orden de las operaciones (la multiplicación y la división antes que la suma y la resta, salvo paréntesis) y, sobre todo, calcular el cociente y el resto de una división entera. Esta última es más importante de lo que parece. Dividir 47 hojas entre 6 personas da 7 a cada una y sobran 5, lo que se escribe 47=6⋅7+547 = 6 \cdot 7 + 5, con el resto 55 menor que el divisor 66. C++ tiene un operador para el cociente y otro para el resto, y una gran parte de los cálculos con enteros (convertir segundos en horas, separar las cifras de un número, decidir si un número es par) se reduce a ellos. Quien quiera estudiarla con detenimiento la encuentra, con su demostración, en el curso Álgebra y Geometría I: Números, Funciones y Geometría del Plano; aquí basta saber calcularla.

La segunda es la costumbre de seguir instrucciones escritas al pie de la letra y de reconocer cuándo una instrucción no basta para saber qué hacer. No se trata de un conocimiento, sino de una actitud: leer «añadir sal a gusto» y advertir que esa instrucción depende de quien la ejecuta. La primera clase de la unidad convierte esa actitud en método.

La tercera es el manejo básico de un computador: crear una carpeta, guardar en ella un archivo con un nombre elegido, reconocer la extensión del nombre (.cpp, .txt, .exe) y saber en qué carpeta está cada archivo. Conviene configurar desde ahora el sistema para que muestre las extensiones, que algunos sistemas, como Windows, ocultan por omisión: el código fuente suma.cpp y el ejecutable suma.exe son archivos muy distintos, y confundirlos es una fuente de errores absurdos. La unidad enseña también a usar la terminal, de modo que no hace falta saberlo de antemano; basta con estar dispuesto a escribir órdenes en lugar de pulsar botones. Instalar programas exige, por último, poder hacerlo en el propio computador; la clase de instalación indica una alternativa en línea para quien no pueda.

No se supone el inglés. Los mensajes del compilador están en inglés, y el curso enseña a leerlos campo por campo, de modo que lo que importa de ellos (el archivo, la línea, la clase de defecto) se entiende sin dominar la lengua. Tampoco se supone ninguna matemática más allá de la escolar: los ejemplos usan la división, los promedios, las tablas de multiplicar, las fechas y las horas.

El problema que la unidad resuelve

Un cálculo que se sabe hacer a mano no es todavía un programa. La distancia entre ambos es lo que la unidad enseña a recorrer, y un problema sencillo permite medirla.

EjemploUna duración en horas, minutos y segundos

Un cronómetro registra la duración de cada actividad como un número de segundos, por ejemplo 7384, y se quiere escribirla en la forma habitual de horas, minutos y segundos, con los minutos y los segundos siempre en dos cifras: 2:03:04. A mano, el cálculo es una cadena de divisiones: 7384=3600⋅2+1847384 = 3600 \cdot 2 + 184, de donde resultan 2 horas y 184 segundos; 184=60⋅3+4184 = 60 \cdot 3 + 4, de donde resultan 3 minutos y 4 segundos. Para una duración se hace en un minuto. Para las mil duraciones de un registro, en cambio, el cálculo a mano es largo y propenso a errores, y la tarea se presta a que una máquina la ejecute.

Ahora bien, una máquina no puede recibir la explicación anterior. Recibe un texto en un lenguaje de programación, y para escribir ese texto hay que haber resuelto antes tres cuestiones que el cálculo a mano dejaba implícitas. La primera es la especificación: qué entra (un número entero de segundos, no negativo), qué sale (tres enteros, las horas, los minutos y los segundos) y qué relación los une: si tt es el total, t=3600h+60m+st = 3600 h + 60 m + s, con 0≤m<600 \leq m < 60 y 0≤s<600 \leq s < 60. La segunda es el algoritmo: los pasos precisos que, para cualquier entrada admisible, producen esa salida.

  1. hh toma el valor del cociente de tt por 36003600.
  2. mm toma el valor del cociente por 6060 del resto de tt por 36003600.
  3. ss toma el valor del resto de tt por 6060.
  4. Escribir hh, dos puntos, mm con dos cifras, dos puntos y ss con dos cifras.

La tercera es la escritura del algoritmo en C++, con la forma exacta que el lenguaje exige, y su traducción a un ejecutable con las herramientas adecuadas. El programa siguiente lo hace. Contiene muchas cosas que todavía no se han explicado: las variables (clase 2.1), los operadores / y %, que dan el cociente y el resto de la división entera (clase 3.1), la lectura con std::cin y los campos de formato como {:02}, que escribe un número con dos cifras completando con ceros (clase 1.6). Por ahora basta reconocer en él los cuatro pasos del algoritmo.

Programa en C++
#include <iostream>#include <print>​int main(){    int total{};  // las variables se explicarán en la clase 2.1    std::print("Duración en segundos: ");    std::cin >> total;    const int hours{total / 3600};    const int minutes{total % 3600 / 60};    const int seconds{total % 60};    std::println("{} s = {}:{:02}:{:02}", total, hours, minutes, seconds);}
Entrada del programa
7384
Salida
Duración en segundos: 7384 s = 2:03:04

Las líneas 9 a 11 son los pasos 1 a 3, y la línea 12 es el paso 4. Que el resultado coincida con el calculado a mano no es una casualidad, sino la comprobación que todo programa merece: probarlo primero con un dato cuya respuesta se conoce.

El programa resuelve el problema, pero la unidad enseña también a desconfiar de él. Si el usuario escribe abc en lugar de un número, la lectura fracasa, total queda en cero y el programa escribe, sin ninguna señal de alarma, que la duración es 0:00:00: una conclusión falsa con apariencia de verdadera. Si escribe una duración negativa, la especificación no dice qué debe ocurrir, y el resultado carece de sentido. Si se escribe total / 360 en lugar de total / 3600, el programa compila, se ejecuta y da un resultado equivocado, y ninguna herramienta lo advierte. Cada uno de esos defectos pertenece a una clase distinta de error, que se descubre en un momento distinto y se busca de un modo distinto; la última clase de la unidad los clasifica. De ello se sigue que el problema que la unidad resuelve no es solo el de escribir este programa, sino el de saber por qué funciona, con qué datos deja de funcionar y qué herramienta avisará, o no, de cada defecto.

Por tanto, al terminar la unidad el estudiante podrá escribir, compilar y ejecutar programas de esta clase: unos pocos datos de entrada, unas cuentas en secuencia y unos resultados escritos con formato. No podrá todavía tomar decisiones ni repetir instrucciones en C++ (aunque sí en un algoritmo escrito en español), ni elegir con criterio el tipo de cada dato; eso es lo que traen las unidades siguientes.

Adónde conduce

La unidad es el umbral del curso. Lo que en ella se usa sin explicar se explica después, en este orden. La unidad 2, «Datos y tipos», explica las variables y cómo se guardan en la memoria, los límites de los enteros (y por qué un cálculo correcto puede desbordarse), el redondeo de los números con decimales y las conversiones entre tipos. La unidad 3, «Expresiones y operadores», explica la aritmética de C++, con el cociente y el resto de los negativos, la lógica de las condiciones y lo que la norma deja sin definir en una expresión. La unidad 4, «Control de flujo», lleva a C++ las decisiones y las repeticiones que la primera clase escribe en español, y enseña a justificar que un bucle es correcto y termina. La unidad 5 descompone los programas en funciones; la 6 introduce los datos compuestos (arreglos, vectores, tablas y registros), con los algoritmos de búsqueda y ordenación y su costo; la 7 trata el texto, la entrada robusta y los archivos; y la 8, los programas de varios archivos, las pruebas sistemáticas y el depurador.

Después del curso, Programación en C++ II continúa con lo que este deja fuera a propósito: los punteros y la memoria dinámica, las clases con métodos, las plantillas propias, las funciones anónimas y las excepciones. Ninguno de esos temas es necesario para resolver los problemas de este curso, y aplazarlos permite concentrarse en lo que vale en cualquier lenguaje: especificar, diseñar el algoritmo, escribirlo con claridad y comprobar que es correcto. La clase de síntesis de esta unidad recogerá precisamente esa distinción, entre lo que es propio de C++ y lo que se llevará a cualquier otro lenguaje.