DMarlon Studio

Lección 20 · 20 de 20

Proyecto: cuaderno de notas · C

Combine todo lo aprendido en C en un cuaderno de notas: structs, arrays, enum, funciones, punteros y un informe guardado en un archivo.

C · Proyecto: cuaderno de notas en DMarlon Studio: el código del ejemplo y su salida en la terminal

Este proyecto reúne el curso. `#define SUBJECTS 3` da nombre a un valor fijo: antes de compilar, cada SUBJECTS se sustituye por 3. Si mañana hubiera cuatro asignaturas, bastaría con cambiar una línea. Con typedef se definen el enum Result (suspenso, aprobado y mención) y la struct Student, que guarda un nombre y un array de notas.

average recibe un puntero a const Student: no copia el alumno entero y promete no cambiarlo. Con s->marks[i] suma sus notas en un for. result_of usa el operador ternario dos veces para elegir MERIT desde 8.5, PASS desde 5 y, si no, FAIL.

En main, group es un array de estructuras iniciado entre llaves, y sizeof calcula cuántos alumnos hay. counts[3] = {0} empieza los contadores a cero y, como los valores del enum son 0, 1 y 2, counts[r]++ suma uno al resultado de cada alumno. labels[r] da su nombre en texto.

El mismo bucle escribe cada fila en pantalla con printf y en report.txt con fprintf, separada por ; para que se pueda abrir en una hoja de cálculo. Al final, fclose guarda el informe y se escribe el resumen. En DMarlon Studio, cree un proyecto de destino Consola, pegue el código y pulse F9: verá la tabla y el archivo report.txt en la carpeta del proyecto.

Código · main.c

#include <stdio.h>#define SUBJECTS 3  // a name for a fixed value, replaced before compilingtypedef enum { FAIL, PASS, MERIT } Result;typedef struct { char name[16]; double marks[SUBJECTS]; } Student;double average(const Student *s) {    double sum = 0;    for (int i = 0; i < SUBJECTS; i++) sum += s->marks[i];    return sum / SUBJECTS;}Result result_of(double avg) {    return avg >= 8.5 ? MERIT : (avg >= 5 ? PASS : FAIL);}int main(void) {    Student group[] = {{"Ana", {7.5, 8.0, 9.0}}, {"Bruno", {4.0, 5.5, 3.5}},                       {"Carla", {9.5, 8.5, 9.0}}, {"Diego", {6.0, 5.0, 7.5}}};    int n = sizeof(group) / sizeof(group[0]), counts[3] = {0};    const char *labels[] = {"fail", "pass", "merit"};    FILE *report = fopen("report.txt", "w");    if (report == NULL) return 1;    printf("%-8s %5s  %s\n", "Student", "Avg", "Result");    for (int i = 0; i < n; i++) {        double avg = average(&group[i]);        Result r = result_of(avg);        counts[r]++;  // the enum value works as an index        printf("%-8s %5.2f  %s\n", group[i].name, avg, labels[r]);        fprintf(report, "%s;%.2f;%s\n", group[i].name, avg, labels[r]);    }    fclose(report);    printf("Merit: %d, pass: %d, fail: %d\n", counts[MERIT], counts[PASS], counts[FAIL]);    return 0;}

Salida · cc main.c -o main && ./main

Student    Avg  Result
Ana       8.17  pass
Bruno     4.33  fail
Carla     9.00  merit
Diego     6.17  pass
Merit: 1, pass: 2, fail: 1

Para recordar

  • #define da nombre a un valor que se repite.
  • Un array de struct guarda una lista de registros.
  • Pase un puntero const para leer una estructura sin copiarla.
  • Los valores de un enum sirven de índice en arrays.
  • Escriba en pantalla y en archivo desde el mismo bucle.

Ejercicio

Añada un quinto alumno y una cuarta asignatura (cambie SUBJECTS a 4), y escriba al final el nombre del alumno con la media más alta.