Código de inventario en C

Iniciado por Boris Morales, 19 Noviembre 2020, 04:13 AM

0 Miembros y 1 Visitante están viendo este tema.

Boris Morales

Amigos necesito de su poderosa ayuda, este es mi código pero aún me faltan 3 acciones o menús, los cuales serían:
-Muestra el laboratorio de un producto buscándolo por su descripción, en este ya hice unos cambios que de hecho están en el menú "buscarDescripcion"; pero no me da el resultado que espero :(
-Ordenar alfabéticamente los productos por su descripción, utilizando método de selección
-Ordenar alfabéticamente los productos por laboratorio, utilizando método de inserción

POR FAVOR, CUALQUIER AYUDA O COMENTARIO ES BIENVENIDO  :(  :-(
ESPERO NO ME IGNOREN...
ESTE ES EL CÓDIGO:






#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>

#define MAX 80
#define VALOR_CENTINELA -1

/* Estructuras */
struct producto {
int codigo;
char nombre[MAX];
char descripcion[MAX];
char laboratorio[MAX];
float costo;
float precio;
int cantidad;
};

typedef struct producto Producto;

/* Opciones del Menú */
void menuPrincipal();
void menuInsertar();
void menuBuscarClave();
void menuBuscarDescripcion();
void menuUtilidad();
void menuMuestras();
void menuEliminar();
void menuMostrar();
void menuModificar();
void menuEliminarFisica();
void menuStockMinimo();

/* Funciones para manejar el archivo directamente */
Producto *obtenerProductos(int *n); /* Obtiene un vector dinámico de productos */
char existeProducto(int codigoProducto, Producto *producto); /* Busca si existe el producto en el archivo de productos */
char existeProducto2(char descripcionProducto, Producto *producto);
char insertarProducto(Producto producto); /* Inserta el producto al final del archivo */
char eliminarProducto(int codigoProducto); /* Eliminar el producto de código codigoProducto del archivo */
char eliminacionFisica(); /* Realiza la eliminación física de registros inválidos del archivo de productos */
char modificarProducto(Producto producto); /* Modifica el producto en el archivo */
char guardarReporte(); /* Genera un archivo TXT con el reporte de los productos */

/* Función de lectura de cadenas */
int leecad(char *cad, int n);

/* Titular del programa */
void tituloPrincipal();

char linea[MAX];

int main()
{
setlocale(LC_ALL, "spanish"); /* Permite imprimir caracteres con tilde */
menuPrincipal();

return 0;
}

void menuPrincipal()
{
char repite = 1;
int opcion = -1;
/* Cuando el usuario ingresa texto en lugar de ingresar una opción. El programa no modifica
el valor de opcion. En ese caso, no se debe de ingresar a ninguno de los case, por eso se está
inicializando la variable opcion con un valor que no permita ejecutar ningún case. Simplemente,
volver a interar y pedir nuevamente la opción. */

do {

system( "COLOR 2" );//con esto sólo cambiamos el color de nuestra fuente
system("cls");

tituloPrincipal();

printf("\n\t\t\t\t\t\tMENÚ PRINCIPAL\n");
printf("\n\t\t[1] Insertar nuevo producto\n");
printf("\t\t[2] Eliminar un producto\n");
printf("\t\t[3] Modificar un producto\n");
printf("\t\t[4] Lista ligada de productos con menor stock\n");
printf("\t\t[5] Muestra: \n");
printf("\t\t[6] Mostrar listado de productos (generar reporte)\n");
printf("\t\t[7] Salir\n");
printf("\n\t\tQué deseas hacer?: [ ]\b\b");

/* Lectura segura de un entero */
leecad(linea, MAX);
sscanf(linea, "%d", &opcion);

switch (opcion) {

case 1:
menuInsertar();
break;

case 2:
menuEliminar();
break;

case 3:
menuModificar();
break;

case 4:
menuStockMinimo();
break;

case 5:
menuMuestras();
break;

case 6:
menuMostrar();
break;

case 7:
repite = 0;
break;
}

} while (repite);
}

void menuMuestras()
{
char repite = 1;
int opcion = -1;

do {
system("cls");

tituloPrincipal();

printf("\n\t\t\t\t\t\tMENÚ QUE MUESTRA: \n");
printf("\n\t\t[1] Info de un producto (por clave)\n");
printf("\t\t[2] Laboratorio que elabora/distribuye un producto (con descripción)\n");
printf("\t\t[3] Utilidad total del inventario\n");
printf("\t\t[4] Volver al Menú Principal\n");
printf("\n\t\tQué deseas hacer?: [ ]\b\b");

/* Lectura segura de un entero */
leecad(linea, MAX);
sscanf(linea, "%d", &opcion);

switch (opcion) {

case 1:
menuBuscarClave();
break;

case 2:
menuBuscarDescripcion();
break;

case 3:
menuUtilidad();
break;

case 4:
repite = 0;
break;
}

} while (repite);
}

void menuInsertar()
{
Producto producto;
int codigoProducto = 0;
char repite = 1;
char respuesta[MAX];

do {
system("cls");
tituloPrincipal();
printf("\n\n\t\t\t    SISTEMA DE INGRESO DE PRODUCTOS \n");

/* Se pide el código del producto a insertar */
printf("\n\tCódigo de producto: ");
leecad(linea, MAX);
sscanf(linea, "%d", &codigoProducto);

/* Se verifica que el producto no haya sido almacenado anteriormente */
if (!existeProducto(codigoProducto, &producto)) {

producto.codigo = codigoProducto;

/* Se piden los demás datos del producto a insertar */
printf("\tNombre del producto: ");
leecad(producto.nombre, MAX);

printf("\tDescripción del producto: ");
leecad(producto.descripcion, MAX);

printf("\tLaboratorio: ");
leecad(producto.laboratorio, MAX);

printf("\tCosto de compra ($): ");
leecad(linea, MAX);
sscanf(linea, "%f", &producto.costo);

printf("\tCosto de venta ($): ");
leecad(linea, MAX);
sscanf(linea, "%f", &producto.precio);

printf("\tCantidad: ");
leecad(linea, MAX);
sscanf(linea, "%d", &producto.cantidad);

/* Se inserta el producto en el archivo */
if (insertarProducto(producto)) {
printf("\n\tEl producto fue insertado correctamente\n");

} else {
printf("\n\tOcurrió un error al intentar insertar el producto\n");
printf("\tInténtelo mas tarde\n");
}
} else {
/* El producto ya existe, no puede ser insertado. */
printf("\n\tEl producto de código %d ya existe.\n", codigoProducto);
printf("\tNo puede ingresar dos productos distintos con el mismo código.\n");
}

printf("\n\tDesea seguir ingresando productos? [S/N]: ");
leecad(respuesta, MAX);

if (!(strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0)) {
repite = 0;
}

} while (repite);
}

void menuBuscarClave()
{
Producto producto;
int codigoProducto;
char repite = 1;
char respuesta[MAX];

do {
system("cls");
tituloPrincipal();
printf("\n\t\t\t==> BUSCAR PRODUCTO POR CÓDIGO <==\n");

/* Se pide el código del producto a buscar */
printf("\n\tCódigo de producto: ");
leecad(linea, MAX);
sscanf(linea, "%d", &codigoProducto);

/* Se verifica que el producto a buscar, exista */
if (existeProducto(codigoProducto, &producto)) {

/* Se muestran los datos del producto */
printf("\n\tCódigo del producto: %d\n", producto.codigo);
printf("\tNombre del producto: %s\n", producto.nombre);
printf("\tCosto del producto: %.1f $\n", producto.costo);
printf("\tPrecio del producto: %.1f $\n", producto.precio);
printf("\tCantidad: %d\n", producto.cantidad);

} else {
/* El producto no existe */
printf("\n\tEl producto de código %d no existe.\n", codigoProducto);
}

printf("\n\tDesea seguir buscando algún producto? [S/N]: ");
leecad(respuesta, MAX);

if (!(strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0)) {
repite = 0;
}

} while (repite);
}

void menuBuscarDescripcion()
{
Producto producto;
char descripcionProducto;
char repite = 1;
char respuesta[MAX];

do {
system("cls");
tituloPrincipal();
printf("\n\t\t\t BUSCAR PRODUCTO POR DESCRIPCIÓN \n");

/* Se pide la descripción del producto a buscar */
printf("\tDescripción del producto: ");
leecad(producto.descripcion, MAX);

/* Se verifica que el producto a buscar, exista */
if (existeProducto2(descripcionProducto, &producto)) {

// Se muestran los datos del producto
printf("\n\tLaboratorio que elabora/distribuye el producto: %s\n", producto.laboratorio);


} else {
// El producto no existe
printf("\n\tEl producto de descripción %s no existe.\n", producto.descripcion);
}

printf("\n\tDesea seguir buscando algún producto? [S/N]: ");
leecad(respuesta, MAX);

if (!(strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0)) {
repite = 0;
}

} while (repite);
}

void menuUtilidad()
{
Producto *productos;
int numeroProductos;
int i;
float costoTotal;
float precioTotal;
float utilidadTotal;
int cantidadTotal;
char respuesta[MAX];

system("cls");
tituloPrincipal();
productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
printf("\n\tEl archivo está vacío!!\n");
system("pause>nul");

} else {
printf("\n\n\t\t        PRODUCTOS INGRESADOS EN INVENTARIO    \n");
printf(" -------------------------------------------------------------------------------------------------------------\n");
printf("%8s\t%-12s%15s%15s%15s%15s%10s\n", "CÓDIGO", "NOMBRE", "DESCRIPCIÓN", "LABORATORIO", "COSTO C. $", "COSTO V. $", "UNIDADES");
printf(" -------------------------------------------------------------------------------------------------------------\n");

/* Se recorre el vector dinámico de productos */
costoTotal = 0;
precioTotal = 0;
cantidadTotal = 0;
for (i = 0; i < numeroProductos; i++) {
if (productos[i].codigo != VALOR_CENTINELA) {
printf("%7d \t%-15s %-15s %-8s%15.1f%15.1f%8d\n", productos[i].codigo, productos[i].nombre, productos[i].descripcion, productos[i].laboratorio, productos[i].costo, productos[i].precio, productos[i].cantidad);
costoTotal += productos[i].costo;
precioTotal += productos[i].precio;
cantidadTotal += productos[i].cantidad;
}
}
printf(" -------------------------------------------------------------------------------------------------------------\n");
printf("\t\t\t                         TOTAL: %15.1f%15.1f%8d\n", costoTotal, precioTotal, cantidadTotal);

utilidadTotal = (precioTotal - costoTotal)*cantidadTotal;
printf("\n>>> Utilidad Total de Inventario: $ %.2f \n\n",utilidadTotal);

system("pause>nul");
}
}

void menuEliminar()
{
Producto producto;
int codigoProducto;
char repite = 1;
char respuesta[MAX];

do {
system("cls");
tituloPrincipal();
printf("\n\t\t\t    ELIMINAR UN PRODUCTO POR CÓDIGO    \n");

/* Se pide el código del producto a eliminar */
printf("\n\tCódigo de producto: ");
leecad(linea, MAX);
sscanf(linea, "%d", &codigoProducto);

/* Se verifica que el producto a buscar, exista */
if (existeProducto(codigoProducto, &producto)) {

/* Se muestran los datos del producto */
printf("\n\tCódigo del producto: %d\n", producto.codigo);
printf("\tNombre del producto: %s\n", producto.nombre);
printf("\tCosto del producto: %.1f $\n", producto.costo);
printf("\tPrecio del producto: %.1f $\n", producto.precio);
printf("\tCantidad: %d\n", producto.cantidad);

printf("\n\tSeguro que desea eliminar el producto? [S/N]: ");
leecad(respuesta, MAX);
if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
if (eliminarProducto(codigoProducto)) {
printf("\n\tProducto eliminado satisfactoriamente.\n");
} else {
printf("\n\tEl producto no pudo ser eliminado\n");
}
}

} else {
/* El producto no existe */
printf("\n\tEl producto de código %d no existe.\n", codigoProducto);
}

printf("\n\tDesea eliminar otro producto? [S/N]: ");
leecad(respuesta, MAX);

if (!(strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0)) {
repite = 0;
}

} while (repite);
}

void menuMostrar()
{
Producto *productos;
int numeroProductos;
int i;
float costoTotal;
float precioTotal;
int cantidadTotal;
char respuesta[MAX];

system("cls");
tituloPrincipal();
productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
printf("\n\tEl archivo está vacío!!\n");
system("pause>nul");

} else {
printf("\n\n\t\t        PRODUCTOS INGRESADOS EN INVENTARIO    \n");
printf(" -------------------------------------------------------------------------------------------------------------\n");
printf("%8s\t%-12s%15s%15s%15s%15s%10s\n", "CÓDIGO", "NOMBRE", "DESCRIPCIÓN", "LABORATORIO", "COSTO C. $", "COSTO V. $", "UNIDADES");
printf(" -------------------------------------------------------------------------------------------------------------\n");

/* Se recorre el vector dinámico de productos */
costoTotal = 0;
precioTotal = 0;
cantidadTotal = 0;
for (i = 0; i < numeroProductos; i++) {
if (productos[i].codigo != VALOR_CENTINELA) {
printf("%7d \t%-15s %-15s %-8s%15.1f%15.1f%8d\n", productos[i].codigo, productos[i].nombre, productos[i].descripcion, productos[i].laboratorio, productos[i].costo, productos[i].precio, productos[i].cantidad);
costoTotal += productos[i].costo;
precioTotal += productos[i].precio;
cantidadTotal += productos[i].cantidad;
}
}
printf(" -------------------------------------------------------------------------------------------------------------\n");
printf("\t\t\t                         TOTAL: %15.1f%15.1f%8d\n", costoTotal, precioTotal, cantidadTotal);

printf("\n\tDesea guardar el reporte en un archivo de texto? [S/N]: ");
leecad(respuesta, MAX);

if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
if (guardarReporte()) {
printf("\n\tEl reporte fue guardado con éxito\n");
} else {
printf("\n\tOcurrió un error al guardar el reporte\n");
}

system("pause>nul");
}
}
}

void menuModificar()
{
Producto producto;
int codigoProducto;
char repite = 1;
char respuesta[MAX];

do {
system("cls");
tituloPrincipal();
printf("\n\t\t\t\t\t    MODIFICAR UN PRODUCTO   \n");

/* Se pide el código del producto a modificar */
printf("\n\tCódigo de producto: ");
leecad(linea, MAX);
sscanf(linea, "%d", &codigoProducto);

/* Se verifica que el producto a buscar exista */
if (existeProducto(codigoProducto, &producto)) {

/* Se muestran los datos del producto */
printf("\n\tNombre del producto: %s\n", producto.nombre);
printf("\tDescripción: %s\n", producto.descripcion);
printf("\tLaboratorio: %s\n", producto.laboratorio);
printf("\tCosto de compra del producto ($): %.1f\n", producto.costo);
printf("\tCosto de venta del producto ($): %.1f\n", producto.precio);
printf("\tCantidad: %d\n", producto.cantidad);

printf("\n\tElija los datos a modificar\n");

/* Modificación del nombre del producto */
printf("\n\tNombre del producto actual: %s\n", producto.nombre);

/* Modificación del costo del producto */
printf("\n\tCosto de compra del producto actual: %.1f\n", producto.costo);
printf("\tDesea modificar el costo de compra del producto? [S/N]: ");
leecad(respuesta, MAX);
if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
printf("\tNuevo costo de compra del producto: ");
leecad(linea, MAX);
sscanf(linea, "%f", &producto.costo);
}

/* Modificación del precio del producto */
printf("\n\tCosto de venta del producto actual: %.1f\n", producto.precio);
printf("\tDesea modificar el costo de venta del producto? [S/N]: ");
leecad(respuesta, MAX);
if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
printf("\tNuevo costo de venta del producto: ");
leecad(linea, MAX);
sscanf(linea, "%f", &producto.precio);
}

/* Modificación de la cantidad del producto */
printf("\n\tCantidad del producto actual: %d\n", producto.cantidad);
printf("\tDesea modificar las existencias del producto? [S/N]: ");
leecad(respuesta, MAX);
if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
printf("\tNueva cantidad del producto: ");
leecad(linea, MAX);
sscanf(linea, "%d", &producto.cantidad);
}

printf("\n\tEstá seguro que desea modificar los datos del producto? [S/N]: ");
leecad(respuesta, MAX);

if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
/* Se modifica el producto en el archivo */
if (modificarProducto(producto)) {
printf("\n\tEl producto fue modificado correctamente\n");

} else {
printf("\n\tOcurrió un error al intentar modificar el producto\n");
printf("\tInténtelo mas tarde\n");
}
}
} else {
/* El producto no existe */
printf("\n\tEl producto de código %d no existe.\n", codigoProducto);
}

printf("\n\tDesea modificar algún otro producto? [S/N]: ");
leecad(respuesta, MAX);

if (!(strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0)) {
repite = 0;
}

} while (repite);
}

void menuEliminarFisica()
{
char respuesta[MAX];


system("cls");
tituloPrincipal();
printf("\n\t\t==> ELIMINAR FÍSICAMENTE REGISTROS DEL ARCHIVO <==\n");

/* Se pide el código del producto a eliminar */
printf("\n\tSeguro que desea proceder con la eliminación física? [S/N]: ");
leecad(respuesta, MAX);

if (strcmp(respuesta, "S") == 0 || strcmp(respuesta, "s") == 0) {
if (eliminacionFisica()) {
printf("\n\tLa eliminación física se realizó con éxito.\n");
} else {
printf("\n\tOcurrió algún error en la eliminación física.\n");
}

system("pause>nul");
}
}

void menuStockMinimo()
{
Producto *productos;
int numeroProductos;
int i;
int aux=0;
int minimo=3;
char respuesta[MAX];

system("cls");
tituloPrincipal();
productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
printf("\n\tEl archivo está vacío!!\n");
system("pause>nul");
   }
   
for (i = 0; i < numeroProductos; i++){
if (productos[i].cantidad <= minimo) {
   printf("\nEl producto:\n\n");
   printf("%8s\t%-12s%15s%15s%15s%15s\n", "CÓDIGO", "NOMBRE", "DESCRIPCIÓN", "LABORATORIO", "COSTO C. $", "COSTO V. $");
   printf("%7d \t%-15s %-15s %-8s%15.1f%15.1f\n", productos[i].codigo, productos[i].nombre, productos[i].descripcion, productos[i].laboratorio, productos[i].costo, productos[i].precio);
   printf("\nSe encuentra en niveles por debajo del mínimo permitido de existencias, deberías considerar adquirir más unidades\n");
}
aux++;

if(aux>4){
   printf("\n\tYa he revisado tus existencias y no hay nada por debajo del mínimo\n");
   }else{
   printf("\n\t \n");
   }
}


system("pause>nul");

}

Producto *obtenerProductos(int *n)
{
FILE *archivo;
Producto producto;
Producto *productos; /* Vector dinámico de productos */
int i;

/* Abre el archivo en modo lectura */
archivo = fopen("productos.dat", "rb");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
*n = 0; /* No se pudo abrir. Se considera n  */
productos = NULL;

} else {

fseek(archivo, 0, SEEK_END); /* Posiciona el cursor al final del archivo */
*n = ftell(archivo) / sizeof(Producto); /* # de productos almacenados en el archivo. (# de registros) */
productos = (Producto *)malloc((*n) * sizeof(Producto)); /* Se reserva memoria para todos los productos almacenados en el archivo */

/* Se recorre el archivo secuencialmente */
fseek(archivo, 0, SEEK_SET); /* Posiciona el cursor al principio del archivo */
fread(&producto, sizeof(producto), 1, archivo);
i = 0;
while (!feof(archivo)) {
productos[i++] = producto;
fread(&producto, sizeof(producto), 1, archivo);
}

/* Cierra el archivo */
fclose(archivo);
}

return productos;
}

char existeProducto(int codigoProducto, Producto *producto)
{
FILE *archivo;
char existe;

/* Abre el archivo en modo lectura */
archivo = fopen("productos.dat", "rb");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
existe = 0;

} else {
existe = 0;

/* Se busca el producto cuyo código coincida con codigoProducto */
fread(&(*producto), sizeof(*producto), 1, archivo);
while (!feof(archivo)) {
if ((*producto).codigo == codigoProducto) {
existe = 1;
break;
}
fread(&(*producto), sizeof(*producto), 1, archivo);
}

/* Cierra el archivo */
fclose(archivo);
}

return existe;
}

char existeProducto2(char descripcionProducto, Producto *producto)//
{
FILE *archivo;
char existe;

/* Abre el archivo en modo lectura */
archivo = fopen("productos.dat", "rb");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
existe = 0;

} else {
existe = 0;

/* Se busca el producto cuyo código coincida con codigoProducto */
fread(&(*producto), sizeof(*producto), 1, archivo);
while (!feof(archivo)) {
if ((*producto).descripcion == descripcionProducto) {
existe = 1;
break;
}
fread(&(*producto), sizeof(*producto), 1, archivo);
}

/* Cierra el archivo */
fclose(archivo);
}

return existe;
}

char insertarProducto(Producto producto)
{
FILE *archivo;
char insercion;

/* Abre el archivo para agregar datos al final */
archivo = fopen("productos.dat", "ab"); /* Añade datos al final. Si el archivo no existe, es creado */

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
insercion = 0;

} else {
fwrite(&producto, sizeof(producto), 1, archivo);
insercion = 1;

/* Cierra el archivo */
fclose(archivo);
}

return insercion;
}

/* ELiminación lógica de un registro */
char eliminarProducto(int codigoProducto)
{
FILE *archivo;
FILE *auxiliar;
Producto producto;
char elimina;

/* Abre el archivo para leer */
archivo = fopen("productos.dat", "r+b"); /* Modo lectura/escritura. Si el archivo no existe, es creado */

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
elimina = 0;

} else {
/* Se busca el registro que se quiere borrar. Cuando se encuentra, se sitúa en esa posición mediante la
función fseek y luego se modifica el campo clave de ese registro mediante algún valor centinela, eso se logra
con fwrite. Hasta allí se ha logrado una eliminación LÓGICA. Porque el registro sigue ocupando espacio en el archivo físico */

elimina = 0;
fread(&producto, sizeof(producto), 1, archivo);
while (!feof(archivo)) {
if (producto.codigo == codigoProducto) {
fseek(archivo, ftell(archivo) - sizeof(producto), SEEK_SET);
producto.codigo = VALOR_CENTINELA;
fwrite(&producto, sizeof(producto), 1, archivo);
elimina = 1;
break;
}
fread(&producto, sizeof(producto), 1, archivo);
}

/* Cierra el archivo */
fclose(archivo);
}

return elimina;
}

char eliminacionFisica()
{
FILE *archivo;
FILE *temporal;
Producto producto;
char elimina = 0;

archivo = fopen("productos.dat", "rb");
temporal = fopen("temporal.dat", "wb");

if (archivo == NULL || temporal == NULL) {
elimina = 0;
} else {
/* Se copia en el archivo temporal los registros válidos */
fread(&producto, sizeof(producto), 1, archivo);
while (!feof(archivo)) {
if (producto.codigo != VALOR_CENTINELA) {
fwrite(&producto, sizeof(producto), 1, temporal);
}
fread(&producto, sizeof(producto), 1, archivo);
}
/* Se cierran los archivos antes de borrar y renombrar */
fclose(archivo);
fclose(temporal);

remove("productos.dat");
rename("temporal.dat", "productos.dat");

elimina = 1;
}

return elimina;
}

char modificarProducto(Producto producto)
{
FILE *archivo;
char modifica;
Producto producto2;

/* Abre el archivo para lectura/escritura */
archivo = fopen("productos.dat", "rb+");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
modifica = 0;

} else {
modifica = 0;
fread(&producto2, sizeof(producto2), 1, archivo);
while (!feof(archivo)) {
if (producto2.codigo == producto.codigo) {
fseek(archivo, ftell(archivo) - sizeof(producto), SEEK_SET);
fwrite(&producto, sizeof(producto), 1, archivo);
modifica = 1;
break;
}
fread(&producto2, sizeof(producto2), 1, archivo);
}

fclose(archivo);
}

/* Cierra el archivo */
return modifica;
}

char guardarReporte()
{
FILE *archivo;
char guardado;
Producto *productos;
int numeroProductos;
int i;
float costoTotal;
float precioTotal;
int cantidadTotal;

productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
guardado = 0;

} else {
/* Abre el archivo en modo texto para escritura */
archivo = fopen("reporte.txt", "w");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
guardado = 0;

} else {
fprintf(archivo, "\n\t\t    ==> LISTADO DE PRODUCTOS REGISTRADOS <==\n");
fprintf(archivo, " ------------------------------------------------------------------------------\n");
fprintf(archivo, "%8s\t%-20s%15s%15s%10s\n", "CODIGO", "NOMBRE", "COSTO $", "PRECIO $", "CANTIDAD");
fprintf(archivo, " ------------------------------------------------------------------------------\n");

/* Se recorre el vector dinámico de productos */
costoTotal = 0;
precioTotal = 0;
cantidadTotal = 0;
for (i = 0; i < numeroProductos; i++) {
if (productos[i].codigo != VALOR_CENTINELA) {
fprintf(archivo, "%7d \t%-20.20s%15.1f%15.1f%8d\n", productos[i].codigo, productos[i].nombre, productos[i].costo, productos[i].precio, productos[i].cantidad);
costoTotal += productos[i].costo;
precioTotal += productos[i].precio;
cantidadTotal += productos[i].cantidad;
}
}
fprintf(archivo, " ------------------------------------------------------------------------------\n");
fprintf(archivo, "\t\t\t      TOTAL: %15.1f%15.1f%8d", costoTotal, precioTotal, cantidadTotal);

guardado = 1;

/* Cierra el archivo */
fclose(archivo);
}
}

return guardado;
}

int leecad(char *cad, int n)
{
int i, c;

/* Hay que verificar si el buffer está limpio o si hay un '\n'
 dejado por scanf y, en ese caso, limpiarlo:
*/

/* 1 COMPROBACIÓN DE DATOS INICIALES EN EL BUFFER */

/* Empezamos leyendo el primer caracter que haya en la entrada. Si es
 EOF, significa que no hay nada por leer, así que cerramos la cadena,
 dejándola "vacía" y salimos de la función retornando un valor de 0
 o falso, para indicar que hubo un error */
c = getchar();
if (c == EOF) {
cad[0] = '\0';
return 0;
}
 
/* Si el valor leído es '\n', significa que había un caracter de nueva línea
dejado por un scanf o función similar. Simplemente inicializamos i a 0,
para indicar que los siguientes caracteres que leamos iremos asignando a
partir del primer caracter de la cadena. */
if (c == '\n') {
i = 0;
} else {
/* Si no había un '\n', significa que el caracter que leímos es el primer
 caracter de la cadena introducida. En este caso, lo guardamos en la
 posición 0 de cad, e inicializamos i a 1, porque en este caso, como ya
 tenemos el primer caracter de la cadena, continuaremos agregando
 caracteres a partir del segundo.
 
*/
cad[0] = c;
i = 1;
}
 
/* 2. LECTURA DE LA CADENA */

/* El for empieza con un ; porque estamos omitiendo la inicialización del contador,
ya que fue inicializado en el punto anterior.
Este código lee un caracter a la vez,lo agrega a cad, y se repite hasta que
se encuentre un fin de línea, fin de archivo, o haya leído la cantidad máxima
de caracteres que se le indicó. Luego, cierra la cadena agregando un '\0'
al final. Todo esto es muy similar a la forma en que los compiladores suelen
implementar la función fgets, sólo que en lugar de getchar usan getc o fgetc
*/
for (; i < n - 1 && (c = getchar()) != EOF && c != '\n'; i++) {
cad[i] = c;
}
cad[i] = '\0';
 
/*3. LIMPIEZA DEL BUFFER */

/* Finalmente limpiamos el buffer si es necesario */
if (c != '\n' && c != EOF) /* es un caracter */
while ((c = getchar()) != '\n' && c != EOF);

/* La variable c contiene el último caracter leído. Recordemos que había 3 formas
de salir del for: que hayamos encontrando un '\n', un EOF, o que hayamos llegado
al máximo de caracteres que debemos leer. Si se da cualquiera de los dos
primeros casos, significa que leímos todo lo que había en el buffer, por lo que
no hay nada que limpiar. En el tercer caso, el usuario escribió más caracteres
de los debidos, que aún están en el buffer, por lo que hay que quitarlos, para
lo cual usamos el método que vimos poco más arriba
*/

return 1;
}

void tituloPrincipal()
{
int i;
printf("\n                                                                           \n");//
printf("\t\t\t                FARMACIAS DEL NORTE S.A de C.V\n");
printf("\t\t\t                 Tú salud nuestro premio!\n");

i = 0;
putchar('\n');
for (; i < 110; i++) {
putchar('*');
}
}

K-YreX

Cita de: Boris Morales en 19 Noviembre 2020, 04:13 AM
POR FAVOR, CUALQUIER AYUDA O COMENTARIO ES BIENVENIDO  :(  :-(
ESPERO NO ME IGNOREN...
Un consejo para que no te ignoren: no pongas un código de 990 líneas. Y más cuando es innecesario. El código en un vistazo general parece que está bien estructurado por lo que es más que suficiente con que pongas las funciones involucradas en la parte del error.

Cita de: Boris Morales en 19 Noviembre 2020, 04:13 AM
-Muestra el laboratorio de un producto buscándolo por su descripción, en este ya hice unos cambios que de hecho están en el menú "buscarDescripcion"; pero no me da el resultado que espero :(

El problema lo tienes en la función existeProducto2():
Cita de: Boris Morales en 19 Noviembre 2020, 04:13 AM

char existeProducto2(char descripcionProducto, Producto *producto)//
{
FILE *archivo;
char existe;

/* Abre el archivo en modo lectura */
archivo = fopen("productos.dat", "rb");

if (archivo == NULL) { /* Si no se pudo abrir el archivo, el valor de archivo es NULL */
existe = 0;

} else {
existe = 0;

/* Se busca el producto cuyo código coincida con codigoProducto */
fread(&(*producto), sizeof(*producto), 1, archivo);
while (!feof(archivo)) {
if ((*producto).descripcion == descripcionProducto) {
existe = 1;
break;
}
fread(&(*producto), sizeof(*producto), 1, archivo);
}

/* Cierra el archivo */
fclose(archivo);
}

return existe;
}

Estás comparando dos cadenas de caracteres char[] utilizando el operador ==. Para esto tienes que utilizar la función strcmp(). A juzgar por el comentario de la línea anterior (15), has cambiado código por descripción (siendo código un int y descripción un char[]) y se te ha olvidado cambiar la función de comparación.

Un par de consejos extra:
  • La función fread() la puedes meter en la condición del while()
  • La nomenglatura: (*puntero).valor se puede sustituir por: puntero->valor.
  • Los operadores & y * se anulan. Utilizar: &(*p) es lo mismo que utilizar: p.

    Cita de: Boris Morales en 19 Noviembre 2020, 04:13 AM
    -Ordenar alfabéticamente los productos por su descripción, utilizando método de selección
    -Ordenar alfabéticamente los productos por laboratorio, utilizando método de inserción
    Especifica qué problemas tienes con esas funciones. Lo único que tienes que hacer es cargar todos los productos en un Producto[], ordenarlos por cualquiera de los métodos y volver a guardarlos en el fichero.
    No es muy eficiente estar continuamente accediendo al fichero para cada operación. Por eso es mejor cargar los datos en memoria y trabajar con ellos desde un array.

Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

Boris Morales

Muchas Gracias por no ignorarme xandrewx

Claro entiendo, y agradezco bastante el consejo
Y si trataré de poner la parte dónde existe la confusión para que no sea tan tedioso  :laugh:

Boris Morales

Gracias estimado K-YreX. Ya intente poner el código para ordenar las descripciones y laboratorios alfabéticamente y respectivamente pero aún me marca error  :-\
Lo puse así utilizando strcmp:


void menuOrdenDescrp()
{
Producto *productos;
int numeroProductos;
int i,j,pos;
char min[MAX];
struct producto temp;

system("cls");
tituloPrincipal();
productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
printf("\n\tEl archivo está vacío!!\n");
system("pause>nul");

} else {
/* Se recorre el vector dinámico de productos */

for (int i = 0; i < numeroProductos-1; i++)
{
strcpy(min, productos[i].descripcion);
pos=i;
for (int j=i+1; j < numeroProductos; j++)
    if (strcmp(productos[j].descripcion , min) < 0)
    {
    strcpy(min, productos[j].descripcion);
    pos=j;
}
temp=productos[i];
productos[i]=productos[pos];
productos[pos]=temp;
}

printf("Datos ordenados:");
for(i=0; i<numeroProductos; i++)
{
printf("%s",productos[i].descripción);
}
}
system("pause>nul");
}

K-YreX

Cuando tengas un error, explícalo para poder saber de qué tipo de error se trata.

  • Las líneas 30 - 32 van fuera de ese for(). Así estás haciendo un intercambio en cada iteración de dentro y muchas veces será entre un mismo elemento, lo que equivale a no hacer nada.
  • Elimina las declaraciones de i y de j en la línea 5. Las estás declarando nuevamente en el for().
  • Utiliza otro nombre de variable en el for() de la línea 36. Puedes tener conflictos entre una i y la otra. Aparte supongo que ese último for lo tendrás para hacer las pruebas porque sino no tiene mucho sentido que muestres todos los productos en cada movimiento.

    Si el error no es por ninguna de esas cosas, adjunta el error.

    PD: No es recomendable utilizar system() para hacer una pausa. Esta función realiza una llamada al sistema lo que conlleva mayor gasto de recursos. La mejor alternativa para C es utilizar getchar() (que pertenece a <stdio.h>).
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

Boris Morales

Gracias K-YreX, ya hice cambios basado en tu valiosa ayuda

Quedando así:


void menuOrdenDescrp()
{
Producto *productos;
int numeroProductos;
int pos,i,j;
char min[MAX];
struct producto temp;

system("cls");
tituloPrincipal();
productos = obtenerProductos(&numeroProductos); /* Retorna un vector dinámico de productos */

if (numeroProductos == 0) {
printf("\n\tEl archivo está vacío!!\n");
system("pause>nul");

} else {
/* Se recorre el vector dinámico de productos */

for (i = 0; i<numeroProductos-1; i++)
{
strcpy(min, productos[i].descripcion);
pos=i;
for (j=i+1; j<numeroProductos-1; j++)
    if (strcmp(productos[j].descripcion , min) < 0)
    {
    strcpy(min, productos[j].descripcion);
    pos=j;
}

}
temp=productos[i];
productos[i]=productos[pos];
productos[pos]=temp;

printf("\n\tDatos ordenados:\n");
for(i=0; i<numeroProductos; i++)
{
printf("\n\t%s\n",productos[i].descripcion);
}
}
getchar();
}


El único detalle que tengo ahora es que al ingresar por ejemplo:
-Dosis
-Botella
-Caja
Me los ordena a la inversa por decirlo de alguna manera, quedando así:  :-\
-Dosis
-Caja
-Botella
Cuando debiera ser:
-botella
-caja
-dosis  :(

K-YreX

#6
No lo ordena al revés, eso ha sido casualidad por el orden en que los has introducido tú.
Lo que hace en realidad es intercambiar siempre el último con el penúltimo y fin. Esto ocurre principalmente por dos errores:
  • Llaves.
  • Error en la condición del bucle interno.

    Tu código (resumido) bien identado para que lo veas es:

    void menuOrdenDescrp(){
       // declaraciones y otros...
       // parte del if...
       } else {
           for (i = 0; i<numeroProductos-1; i++){
               strcpy(min, productos[i].descripcion);
               pos=i;
               for (j=i+1; j<numeroProductos-1; j++) // No utilizas llaves. Este bucle solo comprende el bloque del if()
                   if (strcmp(productos[j].descripcion , min) < 0){
                       strcpy(min, productos[j].descripcion);
                       pos=j;
                   }
           } // este no cierra el for interno porque no usas llaves. Cierra el bucle externo
           temp=productos[i];
           productos[i]=productos[pos];
           productos[pos]=temp;

           printf("\n\tDatos ordenados:\n");
           for(i=0; i<numeroProductos; i++){
               printf("\n\t%s\n",productos[i].descripcion);
           }
       } // Cierre del else{}
       getchar();
    }

    Por lo tanto la ejecución sería:

    i = 0 -> i < productos-1 (2)?? Si -> min = productos[0] (dosis) y pos = 0
     j = 1 -> j < productos-1 (2)?? Si -> productos[1] (botella) < min (dosis) ?? Si -> min = productos[1] y pos = 1
     j = 2 -> j < productos-1 (2)?? No
    i = 1 -> i < productos-1 (2)?? Si -> min = productos[1] (botella) y pos = 1
     j = 2 -> j < productos-1 (2)?? No
    i = 2 -> i < productos-1 (2)?? No
    //FINALIZAN LOS BUCLES Y SE HACE UN SOLO CAMBIO:
    temp = productos[2] (caja)
    productos[2] = productos[1] (botella)
    productos[1] = temp (caja)


    Como ves, ahí está el problema. Para encontrar estos errores la gente suele recurrir a un depurador que te muestra el estado de las variables en cada momento y qué instrucción se va a ejecutar. Y sino pues lápiz y papel y a mano como acabo de hacer.

    PD: Cuando arregles eso, ten cuidado con el último for() porque al usar la misma variable (i) que en el primero, como metas uno dentro del otro tendrás problemas.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;