/*
Taller #7
Autores: Juan David Roman - Sebastian Rivas Rubio
Fecha: 19/11/2023
*/
// Inclusion de librerias
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include <conio.h>
#include <windows.h>
// Macros
#define SONIDO "\7"
#define BEEP printf(SONIDO)
#define LIMPIAPANTALLA system("cls")
#define FONDOPANTALLA system("color F3")
#define PAUSA system("pause")
#define ANIOACTUAL 2023
#define BISIESTO(Anio) (Anio % 4 == 0 && Anio % 100 != 0 || Anio % 400 == 0)
#define FINCADENA '\0'
#define SALTOLINEA(N) { for (int i = 0; i < N; i++) printf("\n"); }
#define ENTER 13
#define SPACE ''
#define MENSAJEAGREGAR {printf("*** AVISO: No se pueden agregar mas datos***");
PAUSA; break;}
// Definicion de tipos propios
typedef unsigned short int usi;
typedef enum Meses {Enero = 1, Febrero, Marzo, Abril, Mayo, Junio, Julio, Agosto,
Septiembre, Octubre, Noviembre, Diciembre};
typedef enum Colores {Blanco=1, Negro, Plateado, Militar, Desconocido};
typedef enum TiposPropulsion {Convencional=1, Semielectrico, Propulsionnuclear,
SubDesconocido};
typedef enum OpcionesMenu{Agregar = 1, Imprimir, Estadisticas, Salir};
typedef enum TipoEntrada {Letras, Digitos, Todo};
// Definicion de estructuras
typedef struct Fecha {
usi Dia;
Meses Mes;
usi Anio;
};
typedef struct MotoNave {
float Sumergibilidad;
float Peso;
int Dormitorios;
int CapacidadTripulacion;
Colores Color;
TiposPropulsion Tipo;
Fecha Creacion;
char *Modelo;
char *Marca;
};
// Definicion de vectores auxiliares de trabajo
const char *NomMes [] = {"No permitido", "Enero", "Febrero", "Marzo", "Abril", "Mayo",
"Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"};
const char *NomColor [] = {"No permitido", "Blanco", "Negro", "Plateado", "Militar",
"Desconocido"};
const char *NomTipo [] = {"No permitido", "Convencional", "Semielectrico",
"Propulsionnuclear", "SubDesconocido"};
/* -- Funciones de validacion auxiliares -- */
// Funcion para validar las cadenas de texto
usi LeerTexto(char *Cadena, TipoEntrada Tipo, usi LongCadena) {
char Car;
usi NroCarLeidos = 0;
while (((Car = toupper(getche())) != ENTER) && NroCarLeidos < LongCadena) {
switch (Tipo) {
case Letras:
if (isalpha(Car) || (isspace(Car) == SPACE))
Cadena[NroCarLeidos++] = toupper(Car);
break;
case Digitos:
if (isdigit(Car))
Cadena[NroCarLeidos++] = toupper(Car);
else BEEP;
break;
case Todo:
Cadena[NroCarLeidos++] = toupper(Car);
break;
}
}
if (Car == ENTER) Cadena[NroCarLeidos++] = '\n';
Cadena[NroCarLeidos] = FINCADENA;
printf ("\n");
return NroCarLeidos;
}
// Funcion para asignar el dia maximo del mes
int DiaMaxMes(int Aniolanzamiento, Meses Mes) {
int DiaMax;
switch (Mes) {
case Enero :
case Marzo :
case Mayo :
case Julio :
case Agosto :
case Octubre :
case Diciembre : DiaMax = 31;
break;
case Febrero : DiaMax = 28;
if (BISIESTO(Aniolanzamiento)) {
DiaMax = 29;
break;
}
case Abril :
case Junio :
case Septiembre :
case Noviembre : DiaMax = 30;
break;
}
return DiaMax;
}
// Funcion para validar la sumergibilidad
float LeeSumergibilidadValida() {
float SumergibilidadValida;
while (1) {
scanf("%f", &SumergibilidadValida);(fflush(stdin));
if (SumergibilidadValida > 0) return SumergibilidadValida;
BEEP;
printf(" *** AVISO: sumergibilidad no valida, debe de ser un valor mayor a 0
***");
printf("\n Sumergibilidad: ");
}
}
// Funcion para validar el numero de dormitorios
int LeeDormitoriosValido() {
int DormitoriosValido;
while (1) {
scanf("%d", &DormitoriosValido);(fflush(stdin));
if (DormitoriosValido > 0) return DormitoriosValido;
BEEP;
printf(" *** AVISO: dormitorios no valido, debe de ser un valor mayor a 0 ***");
printf("\n Dormitorios: ");
}
}
// Funcion para validar la capacidad de la tripulacion
int LeeCapacidadValida() {
int CapacidadValida;
while (1) {
scanf("%d", &CapacidadValida);(fflush(stdin));
if (CapacidadValida > 0) return CapacidadValida;
BEEP;
printf("*** AVISO: capacidad de la tripulacion no valida, debe de ser un valor mayor a
0 ***");
printf("\nCapacidad de tripulacion: ");
}
}
// Funcion para validar el tipo de submarino
TiposPropulsion LeeTipoValido() {
int TipoValido;
while (1) {
scanf("%d", &TipoValido);(fflush(stdin));
if (TipoValido >= Blanco && TipoValido <= Desconocido) return
(TiposPropulsion)TipoValido;
BEEP;
printf(" *** AVISO: tipo de submarino no valido ***");
printf("\n Tipos de Propulsion:\n 1 - Convencional\n 2 - Semielectrico\n 3 -
Propulsion nuclear");
printf("\n Seleccione una opcion: ");
}
}
// Funcion para validar el anio
int LeeAnioValido() {
int AnioValido;
while(1) {
scanf("%u", &AnioValido);(fflush(stdin));
if (AnioValido <= ANIOACTUAL) return AnioValido;
BEEP;
printf(" *** AVISO: Anio no valido ***");
printf("\n Anio de creacion: ");
}
}
// Funcion para validar el mes
Meses LeeMesValido() {
Meses MesValido;
while(1) {
scanf("%u", &MesValido);(fflush(stdin));
if (MesValido >= Enero && MesValido <= Diciembre) return MesValido;
BEEP;
printf(" *** AVISO: Mes no valido ***");
printf("\n Mes de creacion: ");
}
}
// Funcion para validar el anio
int LeeDiaValido(int Anio, Meses Mes) {
int DiaValido;
while(1) {
scanf("%u", &DiaValido);(fflush(stdin));
if (DiaValido >= 1 && DiaValido <= DiaMaxMes(Anio, Mes)) return DiaValido;
BEEP;
printf(" *** Error: Dia invalido para el mes de %s ***", NomMes[Mes]);
printf("\n Dia de creacion: ");
}
}
// Funcion para validar la sumergibilidad
float LeePesoValido() {
float PesoValido;
while (1) {
scanf("%f", &PesoValido);(fflush(stdin));
if (PesoValido > 0) return PesoValido;
BEEP;
printf(" *** AVISO: peso no valido, debe de ser un valor mayor a 0
***");
printf("\n Peso: ");
}
}
// Funcion para validar el color
Colores LeeColorValido() {
int ColorValido;
while (1) {
scanf("%d", &ColorValido);(fflush(stdin));
if (ColorValido >= Blanco && ColorValido <= Desconocido) return
(Colores)ColorValido;
BEEP;
printf(" *** AVISO: Color no valido ***");
printf("\n Colores:\n 1 - Blanco\n 2 - Negro\n 3 - Plateado\n 4 -
Militar\n 5 - Desconocido");
printf("\n Seleccione un color: ");
}
}
/* ---------------------------------------- */
/* -- Funciones principales auxiliares -- */
// Funcion para el menu principal
OpcionesMenu ImprimirMenu() {
int opcion;
LIMPIAPANTALLA;
printf("\n|------------ Menu ------------|\n");
printf("\n Seleccione una Opcion:\n 1-Insertar Submarino\n 2-Imprimir
Submarinos\n 3-Imprimir Estadisticas\n 4-Salir\n");
printf("\n Seleccione: ");
scanf("%d", (int*)&opcion);(fflush(stdin));
return (OpcionesMenu)opcion;
}
// Funcion para Ingresar un Submarino
usi IngresarDatos(MotoNave Sub[], int *ContadorTiposSubAgregar, int
*ContadorColoresAgregar, usi N, usi NDTO) {
LIMPIAPANTALLA;
usi NN = N;
char Decision;
char Aux [50];
do {
printf("\n-------- Ingrese los Datos de la MotoNave --------\n");
printf("\n Marca: "); strcpy(Sub[NN].Marca =
(char*)malloc(LeerTexto(Aux, Letras, 20)*sizeof(char)), Aux); //LeerTexto(Sub[NN].Marca,
Letras, 20);
printf("\n Modelo: "); strcpy(Sub[NN].Modelo =
(char*)malloc(LeerTexto(Aux, Letras, 30)*sizeof(char)), Aux); //LeerTexto(Sub[NN].Modelo,
Todo, 30);
printf("\n Sumergibilidad: "); Sub[NN].Sumergibilidad =
LeeSumergibilidadValida();
printf("\n Dormitorios: "); Sub[NN].Dormitorios = LeeDormitoriosValido();
printf("\nCapacidad de tripulacion: "); Sub[NN].CapacidadTripulacion =
LeeCapacidadValida();
printf("\n Tipos de Propulsion:\n 1 - Convencional\n 2 - Semielectrico\n 3 -
Propulsion nuclear\n");
printf("\n Seleccione una opcion: "); Sub[NN].Tipo = LeeTipoValido();
printf("\n Anio de creacion: "); Sub[NN].Creacion.Anio = LeeAnioValido();
printf("\n Mes de creacion: "); Sub[NN].Creacion.Mes = LeeMesValido();
printf("\n Dia de creacion: "); Sub[NN].Creacion.Dia =
LeeDiaValido(Sub[NN].Creacion.Anio, Sub[NN].Creacion.Mes);
printf("\n Peso: "); Sub[NN].Peso = LeePesoValido();
printf("\n Colores:\n 1 - Blanco\n 2 - Negro\n 3 - Plateado\n 4 -
Militar\n 5 - Desconocido\n");
printf("\n Seleccione un color: "); Sub[NN].Color =
LeeColorValido();
ContadorTiposSubAgregar[Sub[NN].Tipo]++;
ContadorColoresAgregar [Sub[NN].Color]++;
NN ++;
printf("\n\n ¿Desea ingresar otro Submarino?: S/N \n\n"); scanf("%c", &Decision);
(fflush(stdin));
} while (toupper(Decision) == 'S' && NN < NDTO);
return NN;
}
// Funcion para enlistar los Submarinos
void ImprimirDatos(MotoNave Sub[] , usi N) {
FONDOPANTALLA;
LIMPIAPANTALLA;
if (N == 0) {
BEEP;
printf("AVISO: No hay datos para imprimir \n\n");
PAUSA;
return;
}
for (int i = 0; i < N; i++) {
printf("\n\n-------- Impresion de Datos del Submarino: %d --------\n\n", i + 1);
printf(" Sumergibilidad: %f\n", Sub[i].Sumergibilidad);
printf("\n Dormitorios: %d\n", Sub[i].Dormitorios);
printf("\nCapacidad de tripulacion: %d\n", Sub[i].CapacidadTripulacion);
printf("\n Modelo del submarino: %s ", Sub[i].Modelo);
printf("\n Tipo de Submarino: %s\n", NomTipo[Sub[i].Tipo]);
printf("\n Fecha de creacion: %hu/%d/%hu\n", Sub[i].Creacion.Dia,
Sub[i].Creacion.Mes, Sub[i].Creacion.Anio);
printf("\n Peso: %f\n", Sub[i].Peso);
printf("\n Marca: %s" , Sub[i].Marca);
printf("\n Color: %s\n", NomColor[Sub[i].Color]);
printf("\n\n----- oprima la tecla <ENTER> para el siguiente dato -----\n");
PAUSA;
}
}
// Funcion para enlistar las Estadisticas
void ImprimirEstadisticas(int *ContadorTiposSub, int *ContadorColores, usi N) {
FONDOPANTALLA;
LIMPIAPANTALLA;
if (N == 0) {
BEEP;
printf("AVISO: \t\n No hay datos para imprimir estadisticas \n\n");
PAUSA;
return;
}
printf("\n|------------------ Estadisticas de los submarinos ------------------|\n");
// Tipos de Submarino
for (int i = 1; i < 4; i++) {
printf(" %s: %u\n", NomTipo[i], ContadorTiposSub[i]);
}
printf("\n\n");
// Colores
for (int i = 1; i < 5; i++) {
printf(" %s: %u\n", NomColor[i], ContadorColores[i]);
}
printf("\n|--------------------------------------------------------------------|\n");
PAUSA;
}
/* ------------------------------------- */
// Funcion principal
int main() {
// Declaracion de variables
OpcionesMenu Opcion;
MotoNave *Submarinos = NULL;
// Declaracion de contadores
int ContadorTiposSub [4] = {0, 0, 0, 0};
int ContadorColores [5] = {0, 0, 0, 0, 0};
// Control de Datos
usi NumSub = 0;
usi NdtaSub;
do {
Opcion = ImprimirMenu();
switch (Opcion) {
case Agregar:
if (NumSub == 0) {
LIMPIAPANTALLA;
printf("Cuantos Submarinos desea ingresar?: "); scanf("%u", &NdtaSub);
Submarinos = (MotoNave*)malloc(NdtaSub*sizeof(MotoNave));
}
if (NumSub >= NdtaSub) MENSAJEAGREGAR;
// Insercion de Datos
NumSub = IngresarDatos(Submarinos, ContadorTiposSub, ContadorColores,
NumSub, NdtaSub);
break;
case Imprimir:
// Impresion de Datos
ImprimirDatos(Submarinos, NumSub);
break;
case Estadisticas:
// Estadisticas de cada Enumerado
ImprimirEstadisticas(ContadorTiposSub, ContadorColores, NumSub);
break;
case Salir:
FONDOPANTALLA;
printf("Saliendo del programa.\n");
PAUSA;
break;
default:
printf("Opcion no valida. Intente de nuevo.\n");
PAUSA;
}
} while (Opcion != Salir);
return(0);
}