Java - Gracias y Disculpas a Kabuto. Contador de domingos.

 
Vista:
Imágen de perfil de Javier

Gracias y Disculpas a Kabuto. Contador de domingos.

Publicado por Javier (18 intervenciones) el 01/12/2022 22:47:32
Buenas noches compañeros.
Hace unos días tenía una duda sobre un ejercicio de contar días concretos de un año y le pregunté por privado a Kabuto. El muy amablemente me ayudó pero me dijo que preferiría que fuera en público por si alguien mas tiene dudas. así que aquí vuelvo a poner su consulta, su ayuda ....y también mi nueva pregunta. Gracias a todos y a Kabuto en concreto.

Si dispones de tiempo y de ganas quería hacerte una consulta.
Tengo un ejercicio que a priori sé que es sencillo, pero como dicen aquí en Jerez de la Frontera me tiene empestillado. Te pongo el enunciado.

Ejercicio 3. Contador de domingos.
Calendario del año 2023

Escribe un programa en Java a partir de la plantilla que se os proporciona (Ejercicio03) para que solicite un año por teclado (número entero), que debe encontrarse entre 1900 y 2100 (ambos incluidos).

Si no se introduce un año correcto, bien porque no se introduzca un número entero válido (control de la excepción InputMismatchException), bien porque no esté dentro de los límites permitidos, se volverá a solicitar hasta que el año sea correcto. Se hará tantas veces como sea necesario.

Una vez introducido un año correcto, se procederá a recorrer cada mes de ese año (un bucle que vaya desde 1 hasta 12) para calcular y mostrar por pantalla cuántos domingos hay en cada mes. Finalmente, habrá que indicar cuántos domingos hay en total en el año.

Este ejercicio se puede resolver de muchas formas diferentes. Una manera sencilla de hacerlo es ir recorriendo los días o fechas (objetos de tipo LocalDate) que tiene cada mes (un segundo bucle, anidado, desde 1 hasta el número de días que tiene cada mes en concreto) y comprobar cuáles de ellos son domingo y cuáles no.

En ese segundo bucle (interno) podrás tener un contador que se iniciaría a cero antes de empezar el bucle para contabilizar cuántos domingos has encontrado en el mes y así poder mostrarlo por pantalla. Además, podrías tener otro contador global para saber cuántos domingos llevas acumulados en total.

Debes tener en cuenta que el método que proporciona la clase LocalDate para obtener el día de la semana es getDayOfWeek y que devuelve un enum de tipo DayOfWeek. Ese valor es el que tendrás que verificar si es domingo (DayOfWeek.SUNDAY) o no.

Recuerda que la clase LocalTime no dispone de constructores públicos, de manera que tendrás que usar los métodos "fábrica" o pseudoconstructores que proporcione para crear objetos instancia de esta clase.

Pues bien, he llegado a la parte en la que compruebo que el 1 de enero del año que tu me des es por ejemplo un Lunes.....Y ahora qué??????
Me podrías dar un empujoncillo?
Muchas gracias.
Te adjunto el proyecto que llevo hecho:
package tarea03;

// Aquí tendrás que incluir los "import" que necesites

import libtarea3.Utilidades;
import java.util.Scanner;
import java.util.InputMismatchException;
import java.time.*;

/**
* Ejercicio 3: Contador de domingos.
* @author Nombre alumno/a
*/
public class Ejercicio03 {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
//----------------------------------------------
// Declaración de variables
//----------------------------------------------
// Constantes


// Variables de entrada

int año=0;

// Variables de salida


// Variables auxiliares

boolean errorEntrada;

// Objeto Scanner para lectura desde teclado

Scanner teclado= new Scanner (System.in);

//----------------------------------------------
// Entrada de datos
//----------------------------------------------
System.out.println("CONTADOR DE DOMINGOS");
System.out.println("--------------------");

// 1.- Leer y comprobar el año (entre 1900 y 2100), ambos incluidos

do {
System.out.print("Introduzca año (1900-2100): ");
try {
año = teclado.nextInt();
errorEntrada = (año < 1900 || año > 2100);
} catch (InputMismatchException ex) {
System.err.println("Error de lectura: no es un número entero válido.");
errorEntrada = true;
teclado.nextLine(); // "Purgamos" lo que haya en el teclado, que es incorrecto
}
} while (errorEntrada);

//----------------------------------------------
// Procesamiento + Salida de resultados
//----------------------------------------------

System.out.println("\nCANTIDAD DE DOMINGOS DEL AÑO " + año);
System.out.println("---------------------------------");

// Iniciamos acumuladores

LocalDate fecha=LocalDate.parse(año + "-01-01");
// 2.- Recorremos todos los meses del año (bucle)

System.out.println(fecha.getDayOfWeek()) ;
// 2.1.- Para cada mes, recorremos cada una de las fechas que contiene y contamos cuántas hay que sean domingo




// 2.2.- Mostramos por pantalla la cantidad de domingos del mes (una línea por mes)


// 2.3.- Incrementamos el cómputo global de domingos para el año


// 3.- Mostramos por pantalla la cantidad de domingos totales


}

}




Muchísimas gracias de antemano. Un saludo




Su respuesta fue la siguiente:

Respecto al ejercicio.
Yo a la solución que he llegado es hacer un bucle de 1 a 12.
Dentro hacemos un bucle while donde comprobamos si es domingo y lo contamos. Y entonces incrementamos la fecha en 1 día para seguir comprobando cuantos domingos encontramos.
El bucle while se va a repetir mientras sigamos en el "mes actual", es decir, al incrementar la fecha llegará un momento que saltaremos al mes siguiente.
Pues entonces el bucle termina y mostramos los domingos del mes comprobado.
Esto se repite 12 veces, una por cada mes.

Te dejo el código, he añadido algún comentario explicando, aunque creo que se entiende bien la lógica.
Pregunta si algo no está claro.
Saludos.

public class Ejercicio03 {

public static void main(String[] args) {

int año=0;

boolean errorEntrada;

Scanner teclado= new Scanner (System.in);

//----------------------------------------------
// Entrada de datos
//----------------------------------------------
System.out.println("CONTADOR DE DOMINGOS");
System.out.println("--------------------");

// 1.- Leer y comprobar el año (entre 1900 y 2100), ambos incluidos

do {
System.out.print("Introduzca año (1900-2100): ");
try {
año = teclado.nextInt();
errorEntrada = (año < 1900 || año > 2100);
} catch (InputMismatchException ex) {
System.err.println("Error de lectura: no es un número entero válido.");
errorEntrada = true;
teclado.nextLine(); // "Purgamos" lo que haya en el teclado, que es incorrecto
}
} while (errorEntrada);
teclado.close();

//----------------------------------------------
// Procesamiento + Salida de resultados
//----------------------------------------------

System.out.println("\nCANTIDAD DE DOMINGOS DEL AÑO " + año);
System.out.println("---------------------------------");

// Iniciamos acumuladores

LocalDate fecha=LocalDate.parse(año + "-01-01");
// 2.- Recorremos todos los meses del año (bucle)
int domingosTotal = 0; //Contador de domingos totales
for (int mesActual = 1; mesActual <= 12; mesActual++) {
int domingosMes = 0; //Contador de domingos mensuales
/*
* En el siguiente bucle comprobamos si es domingo e incrementamos dia a dia.
* Tras incrementar, si terminamos el mes y pasamos al siguiente,
* el bucle terminará y mostraremos datos obtenidos
*/
// 2.1.- Para cada mes, recorremos cada una de las fechas que contiene y contamos cuántas hay que sean domingo
while (mesActual == fecha.getMonthValue()) {
//Comprobamos si es domingo
if (fecha.getDayOfWeek() == DayOfWeek.SUNDAY)
domingosMes++;
//Pasamos al siguiente dia
fecha = fecha.plusDays(1);
}
// 2.2.- Mostramos por pantalla la cantidad de domingos del mes (una línea por mes)
System.out.printf("Mes: %2d -- Domingos contados: %d\n", mesActual, domingosMes);
// 2.3.- Incrementamos el cómputo global de domingos para el año
domingosTotal += domingosMes;
}

// 3.- Mostramos por pantalla la cantidad de domingos totales
System.out.println("\nTotal domingos anual: " + domingosTotal);
}
}


Se la he mandado a la profesora pero me dice que el contador no sale del mes de Enero. Me dice lo siguiente:
La primera vez que entras en este bucle la fecha es el 1 de enero,¿no?; y vas recorriendo día a día para contabilizar los días que son domingo. Ahora bien, ¿cuándo sales del bucle?: cuando cambias de mes. Por tanto, sales del bucle cuando estamos en el mes de febrero. Y, a continuación, tienes el siguiente código:

String nombreMes= fecha.getMonth().getDisplayName(TextStyle.FULL, new Locale("es", "ES"));

System.out.printf("%2s:%d\n", nombreMes, domingosMes);

Lógicamente, cuando haces fecha.getMonth() te devuelve que estás en el mes de febrero PERO te muestra los domingos que ha encontrado en el mes de enero. Y así sucesivamente....¿Ves lo que te quiero decir? No se corresponden los meses con el número de domingos que has contabilizado.


A alguien se le ocurre algo???

Gracias a todos.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
1
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Gracias y Disculpas a Kabuto. Contador de domingos.

Publicado por Kabuto (1381 intervenciones) el 03/12/2022 01:34:23
Hola Javi, gracias por compartir el problema con la comunidad.

Es cierto que cuando el bucle while termina, el objeto "fecha" ya ha pasado al siguiente mes.
Pero los datos recopilados y que van a mostrarse en pantalla, corresponden al mes anterior, o sea, al que realmente se ha comprobado.

Yo en mi código solo puse el número de mes en pantalla, pero si quieres poner el nombre, y que sea el nombre correcto, lo que puedes hacer es capturar el nombre del mes en la variable String ANTES de que comience el bucle que cuenta domingos.
Y luego al terminar, aunque "fecha" ya haya pasado al mes siguiente, no importa porque en el String conservas el nombre correcto del mes

Hay que modificar el printf para que ahora muestre un String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
		// 2.- Recorremos todos los meses del año (bucle)
		int domingosTotal = 0; //Contador de domingos totales
		for (int mesActual = 1; mesActual <= 12; mesActual++) {
			int domingosMes = 0; //Contador de domingos mensuales
			/*
			 * En el siguiente bucle comprobamos si es domingo e incrementamos dia a dia.
			 * Tras incrementar, si terminamos el mes y pasamos al siguiente,
			 * el bucle terminará y mostraremos datos obtenidos
			 */
			// 2.1.- Para cada mes, recorremos cada una de las fechas que contiene y contamos cuántas hay que sean domingo
			String nombreMes= fecha.getMonth().getDisplayName(TextStyle.FULL, new Locale("es", "ES"));
			while (mesActual == fecha.getMonthValue()) {
				//Comprobamos si es domingo
				if (fecha.getDayOfWeek() == DayOfWeek.SUNDAY)
					domingosMes++;
				//Pasamos al siguiente dia
				fecha = fecha.plusDays(1);
			}
			// 2.2.- Mostramos por pantalla la cantidad de domingos del mes (una línea por mes)
			System.out.printf("Mes: %-10s -- Domingos contados: %d\n", nombreMes, domingosMes);
			// 2.3.- Incrementamos el cómputo global de domingos para el año
			domingosTotal += domingosMes;
		}

En pantalla ahora saldrán los nombres de los meses y sus domingos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CONTADOR DE DOMINGOS
--------------------
Introduzca año (1900-2100): 2022
 
CANTIDAD DE DOMINGOS DEL AÑO 2022
---------------------------------
Mes: enero      -- Domingos contados: 5
Mes: febrero    -- Domingos contados: 4
Mes: marzo      -- Domingos contados: 4
Mes: abril      -- Domingos contados: 4
Mes: mayo       -- Domingos contados: 5
Mes: junio      -- Domingos contados: 4
Mes: julio      -- Domingos contados: 5
Mes: agosto     -- Domingos contados: 4
Mes: septiembre -- Domingos contados: 4
Mes: octubre    -- Domingos contados: 5
Mes: noviembre  -- Domingos contados: 4
Mes: diciembre  -- Domingos contados: 4
 
Total domingos anual: 52


Por cierto, estos constructores de la clase Locale han sido muy recientemente (septiembre de este año 2022) marcados como obsoletos (deprecated) en Java 19
1
String nombreMes= fecha.getMonth().getDisplayName(TextStyle.FULL, new Locale("es", "ES"));

No tiene demasiada importancia, se pueden seguir usando.
Pero ahora sería más correcto hacerlo así:
1
String nombreMes= fecha.getMonth().getDisplayName(TextStyle.FULL, Locale.of("ES"));

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Javier

Gracias y Disculpas a Kabuto. Contador de domingos.

Publicado por Javier (18 intervenciones) el 03/12/2022 10:18:46
Como siempre digo, Kabuto, eres un grande.
Muchas gracias. Así da gusto y a los "torpes" que estamos empezando no se nos hace tan dificil.
Lo dicho, Gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar