P_61_E39+-+Ejercicio+de+Operaciones+de+calendario

=__**Ejercicio de operaciones con fechas del calendario**__=

//** Ejercicio 39 de la página 61 **//

Utilizando la sintaxis del lenguaje Pascal, se desea desarrollar un programa que presente un menú en pantalla con las siguientes opciones:

>> 1. Cálculo de años bisiestos >> 2. Días transcurridos de un año >> 3. Vacaciones anuales >> 0. Terminar

code format="pascal" PROGRAM P_58_E39 ; {NOTA: Se supondrá que se introducen siempre valores correctos} USES Crt ;

{******************************************************************************** Nombre: fncLeerOpcion Parámetros de entrada: NINGUNO Valor retornado: Una opción válida (tipo carácter) Descripción: Muestra el menú de opciones y retorna una opción válida. FUNCTION fncLeerOpcion : Char ; VAR cOpcion : Char ; BEGIN Clrscr ; Writeln ; Writeln ('********************** Menú **********************') ; Writeln ('1 Calcular número de años bisiestos en un rango') ; Writeln ('2 Indicar días transcurridos de un año') ; Writeln ('3 Indicar día final de las vacaciones') ; Writeln ; Writeln ('0 Terminar el programa') ; Writeln ; Write ('Pulsa el número de la opción: ') ; REPEAT cOpcion := Readkey UNTIL ('0' <= cOpcion) AND (cOpcion <= '3') ; Writeln (cOpcion) ; Writeln ;
 * }

fncLeerOpcion := cOpcion END ; { fncLeerOpcion }

{******************************************************************************* Nombre: fnboEsBisiesto Parámetros de entrada: iAnyo Representa un determinado año. Valor retornado: TRUE Si el año es bisisesto y FALSE En caso contrario Descripción: Si iAnyo es múltipo de 400, o de 4 pero no de 100, retorna TRUE, y FALSE en caso contrario. FUNCTION fnboEsBisiesto (iAnyo : Integer) : Boolean ; VAR boDivisiblePor_4, boDivisiblePor_100, boDivisiblePor_400 : Boolean ; BEGIN boDivisiblePor_4 := (iAnyo MOD 4) = 0 ; boDivisiblePor_100 := (iAnyo MOD 100) = 0 ; boDivisiblePor_400 := (iAnyo MOD 400) = 0 ;
 * }

IF boDivisiblePor_400 THEN fnboEsBisiesto := TRUE ELSE IF boDivisiblePor_4 AND NOT boDivisiblePor_100 THEN fnboEsBisiesto := TRUE ELSE fnboEsBisiesto := FALSE END ; { fnboEsBisiesto }

{******************************************************************************* Nombre: fnbyDiasDelMes Parámetros de entrada: byMes Representa un determinado mes iAnyo Representa un determinado año Valor retornado: El número de día que tiene el mes pasado como parámetro. Descripción: Indica el número de días que tiene un mes. Para el mes de Febrero tiene en cuenta si el año es bisiesto o no. FUNCTION fnbyDiasDelMes (byMes : Byte ; iAnyo : Integer) : Byte ; VAR byDiasMes : Byte ; BEGIN CASE byMes OF 1, 3, 5, 7, 8, 10, 12 : byDiasMes := 31 ; 4, 6, 9, 11 : byDiasMes := 30 ; 2 : IF fnboEsBisiesto (iAnyo) THEN byDiasMes := 29 ELSE byDiasMes := 28 END ; { CASE } fnbyDiasDelMes := byDiasMes ; END ; { fnbyDiasDelMes }
 * }

{********************************************************************************* Nombre: fniNumeroAnyosBisiestos Parámetros de entrada: iAnyo_1 Representa un determinado año (inicio de un rango) iAnyo_2 Representa un determinado año (final del rango ) Valor retornado: Número de años bisiestos dentro del rango (incluidos los límites del mismo) Descripción: Para cada año del rango averigua si es bisiesto o no, utilizando una variable local como contador. FUNCTION fniNumeroAnyosBisiestos (iAnyo_1, iAnyo_2 : Integer) : Integer; VAR iAnyo, iContador : Integer ; BEGIN iContador := 0 ;
 * }

FOR iAnyo := iAnyo_1 TO iAnyo_2 DO IF fnboEsBisiesto (iAnyo) THEN iContador := iContador + 1 ;

fniNumeroAnyosBisiestos := iContador END ; { fniNumeroAnyosBisiestos }

{******************************************************************************** Nombre: fniCalcularDiasPasadosAnyo Parámetros de entrada: byDia Representa un día de una determinada fecha byMes Representa un mes de una determinada fecha iAnyo Representa un año de una determinada fecha Valor retornado: El número de día transcurridos hata dicha fecha. Descripción: Calcula los días transcurridos desde el 1 de Enero del año indicado hasta la fecha (incluido el día de la fecha). FUNCTION fniCalcularDiasPasadosAnyo (byDia, byMes : Byte ; iAnyo : Integer) : Integer ; VAR byMesActual : Byte ; iDias : Integer ; BEGIN iDias := 0 ;
 * }

FOR byMesActual := 1 TO byMes - 1 DO iDias := iDias + fnbyDiasDelMes (byMesActual, iAnyo) ;

iDias := iDias + byDia ;

fniCalcularDiasPasadosAnyo := iDias END ; { fniCalcularDiasPasadosAnyo }

{********************************************************************** Nombre: PonerFechaCorrecta Parámetros de entrada: byDia Representa un día de una determinada fecha byMes Representa un mes de una determinada fecha iAnyo Representa un año de una determinada fecha

Parámetros de salida: UNA FECHA CORRECTA: byDia Representa un día de una determinada fecha byMes Representa un mes de una determinada fecha iAnyo Representa un año de una determinada fecha Descripción: Mientras que byDia represente un valor mayor que los días correspondientes al mes byMes del año iAnyo: Restar de byDia los días correspondiente a dicho mes e incrementa el valor de byMes Si el valor de byMes es mayor de 12 se pone a 1 y se incrementa el valor de iAnyo PROCEDURE PonerFechaCorrecta (VAR byDias, byMes : Byte ; VAR iAnyo : Integer) ; BEGIN WHILE byDias > fnbyDiasDelMes (byMes, iAnyo) DO BEGIN byDias := byDias - fnbyDiasDelMes (byMes, iAnyo) ; byMes := byMes + 1 ;
 * }

IF byMes > 12 THEN BEGIN byMes := 1 ; iAnyo := iAnyo + 1 ; END END END ; { PonerFechaCorrecta }

{******************************************************************************** Nombre: fnbyDiaDeLaSemana Parámetros de entrada: byPrimerDiaAnyo Representa el ordinal del día de la semana del 1 de Enero (comenzando por 0 = Lunes) iDiasPasadosAnyo Representa los días transcurridos desde ese 1 de Enero. Valor retornado: El ordinal del día de la semana, del día correspondiente a la cifra de días transcurridos. Descripción: Considerando iDiasPasadosAnyo, cifra de días transcurridos, como semanas se calcula el número de días de la última semana no completa y se le suma el ordinal del día de la semana del 1 de Enero. Con eso se obtiene el día de la semana de la fecha. Pero como se puede obtener un día mayor que 7, se debe tomar el módulo 7 de esa cifra FUNCTION fnbyDiaDeLaSemana ( byPrimerDiaAnyo : Byte ; iDiasPasadosAnyo : Integer) : Byte ; VAR byDiaSemana, byRestoSemana : Byte ; BEGIN ByRestoSemana := iDiasPasadosAnyo MOD 7 ; byDiaSemana := (byPrimerDiaAnyo + byRestoSemana) MOD 7 ;
 * }

fnbyDiaDeLaSemana := byDiaSemana ; END ; { fnbyDiaDeLaSemana }

{******************************************************************************** Nombre: MostrarNombreDiaSemana Parámetros de entrada: bydiaSemana Representa el ordinal del día de la semana (considerando el 0como el Lunes) Parámetros de salida: NINGUNO Descripción: Escribe en pantalla la cadena de caracteres correspondiente al nombre del día de la semana. PROCEDURE MostrarNombreDiaSemana (byDiaSemana : Byte) ; BEGIN CASE byDiaSemana OF 0 : Write ('Lunes') ; 1 : Write ('Martes') ; 2 : Write ('Miércoles') ; 3 : Write ('Jueves') ; 4 : Write ('Viernes') ; 5 : Write ('Sábado') ; 6 : Write ('Domingo') ; END ; END ; { MostrarDiaSemana }
 * }

{**************** Variables del Programa principal ********************} VAR cOpcion, cEspera : Char ; byDia, byMes, byDiasVacaciones, byDiaSemana, byDiaSemanaBuscado : Byte ; iAnyo_1, iAnyo_2, iDiasPasados : Integer ;

BEGIN {*********************** Programa principal *********************} REPEAT cOpcion := fncLeerOpcion ;

CASE cOpcion OF '1' : BEGIN Write ('Año inicial: ') ; Readln (iAnyo_1) ; Write (' Año final: ') ; Readln (iAnyo_2) ; Writeln ; Write ('Número de años bisiestos desde ', iAnyo_1, ' hasta ', iAnyo_2, ' : ', fniNumeroAnyosBisiestos (iAnyo_1, iAnyo_2)) ; Writeln END ;

'2' : BEGIN Writeln ('Fecha.- ') ; Write ('Día: ') ; Readln (byDia) ; Write ('Mes: ') ; Readln (byMes) ; Write ('Año: ') ; Readln (iAnyo_1) ; REPEAT Write ('Día de la semana del 1 de Enero de ', iAnyo_1, ' (0 = Lunes ... 6 = Domingo) ') ; Readln (byDiaSemana) ; UNTIL (0 <= byDiaSemana) AND (byDiaSemana <= 6) ; Writeln ;

iDiasPasados := fniCalcularDiasPasadosAnyo (byDia, byMes, iAnyo_1) ;

byDiaSemanaBuscado := fnbyDiaDeLaSemana (byDiaSemana, iDiasPasados - 1);

Writeln ('Días transcurridos: ', iDiasPasados) ; Write (' Día de la semana: ') ; MostrarNombreDiaSemana (byDiaSemanaBuscado) ; Writeln END ;

'3' : BEGIN Writeln ('Fecha del primer día de vacaciones') ; Write ('Día: ') ; Readln (byDia) ;

Write ('Mes: ') ; Readln (byMes) ;

Write ('Año: ') ; Readln (iAnyo_1) ;

Write ('Número de días de vacaciones: ') ; Readln (byDiasVacaciones) ; Writeln ;

byDia := byDia + byDiasVacaciones - 1 ;

PonerFechaCorrecta (byDia, byMes, iAnyo_1) ; Writeln ('Las vacaciones terminan el día: ', byDia, '/', byMes, '/', iAnyo_1) ;

Writeln END ; END ; { CASE }

IF cOpcion <> '0' THEN cEspera := Readkey UNTIL cOpcion = '0' END. code


 * Algunas variaciones:**

code format="pascal" FUNCTION fncLeerOpcion : Char ; VAR cOpcion : Char ; BEGIN Clrscr ; Writeln ; Writeln (' **Menú** ') ; Writeln ('1 Calcular número de años bisiestos en un rango') ; Writeln ('2 Indicar días transcurridos de un año') ; Writeln ('3 Indicar día final de las vacaciones') ; Writeln ; Writeln ('0 Terminar el programa') ; Writeln ; Write ('Pulsa el número de la opción: ') ; REPEAT cOpcion := Readkey UNTIL ('0' <= cOpcion) AND (cOpcion <= '3') ; Writeln (cOpcion) ; Writeln ;

fncLeerOpcion := cOpcion END ; { fncLeerOpcion }