Lección 20 · 20 de 20
Proyecto: gestor de inventario · C
Un pequeño gestor de inventario en C que reúne structs, memoria dinámica, una lista enlazada y archivos, y libera toda la memoria al terminar.

Este proyecto junta lo visto en el curso. Cada artículo es un Item con nombre, cantidad, precio y un puntero next: el inventario es una lista enlazada en el montón. add reserva un nodo con malloc, copia el nombre de forma segura con snprintf y lo pone delante de la lista; las tres llamadas anidadas de main crean el inventario de golpe.
Para guardar, main abre inventory.csv y escribe una línea por artículo con fprintf, separando los campos con ;. Si el archivo no se puede abrir, libera la lista antes de salir con código 1. Después de fclose, free_all libera todos los nodos: a partir de ahí, los datos solo existen en el archivo.
load hace el camino contrario. fscanf lee cada línea con el formato " %19[^;];%d;%lf": el espacio inicial salta el salto de línea anterior, %19[^;] lee hasta el punto y coma sin pasar de 19 caracteres (los que caben en name) y el bucle sigue mientras se lean los tres campos. Cada línea crea un nodo nuevo con add.
Como add inserta al principio, la lista cargada queda en orden inverso al del archivo: por eso Screws x100 sale primero. El informe recorre la lista, marca con REORDER lo que tiene menos de 5 unidades y acumula el valor del almacén en el propio for.
Al final se liberan todos los nodos con free_all y se borra el archivo de prueba con remove. Escriba este programa en el destino Consola de DMarlon Studio y ejecútelo con F9: es una buena base para añadirle un menú, búsquedas o la ordenación con qsort.
Código · main.c
#include <stdio.h>#include <stdlib.h>typedef struct Item { char name[20]; int qty; double price; struct Item *next; } Item;Item *add(Item *head, const char *name, int qty, double price) { // a new node in front Item *it = malloc(sizeof *it); if (!it) exit(EXIT_FAILURE); snprintf(it->name, sizeof it->name, "%s", name); it->qty = qty; it->price = price; it->next = head; return it;}void free_all(Item *it) { while (it) { Item *next = it->next; free(it); it = next; } }Item *load(const char *path) { // reads the file into a new list; NULL if it cannot FILE *f = fopen(path, "r"); if (!f) return NULL; Item *head = NULL; char name[20]; int qty; double price; while (fscanf(f, " %19[^;];%d;%lf", name, &qty, &price) == 3) head = add(head, name, qty, price); fclose(f); return head;}int main(void) { Item *stock = add(add(add(NULL, "Screws x100", 40, 4.25), "Drill", 3, 59.00), "Hammer", 12, 9.90); FILE *f = fopen("inventory.csv", "w"); if (!f) { free_all(stock); return 1; } for (const Item *it = stock; it; it = it->next) fprintf(f, "%s;%d;%.2f\n", it->name, it->qty, it->price); fclose(f); free_all(stock); // now the data lives only in the file stock = load("inventory.csv"); double total = 0; for (const Item *it = stock; it; total += it->qty * it->price, it = it->next) printf("%-12s %3d x %6.2f%s\n", it->name, it->qty, it->price, it->qty < 5 ? " REORDER" : ""); printf("Stock value: %.2f\n", total); free_all(stock); remove("inventory.csv"); return 0;}Salida · cc main.c -o main && ./main
Screws x100 40 x 4.25 Drill 3 x 59.00 REORDER Hammer 12 x 9.90 Stock value: 465.80
Para recordar
- Los datos viven en una lista enlazada en el montón.
- Guardar en texto y volver a cargar separa la memoria del archivo.
%19[^;]lee hasta un separador sin desbordar el búfer.- Cada
malloctiene sufree:free_allantes de salir, también si hay error.
Ejercicio
Añada int sell(Item *stock, const char *name, int units), que busque el artículo y reste las unidades (y devuelva -1 si no existe o no hay bastantes), y úsela antes de guardar para vender 2 martillos.