Autor Tema: Función de análisis lexico  (Leído 936 veces)

cris0710

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 17
    • Ver Perfil
Función de análisis lexico
« en: 05 de Marzo 2021, 18:12 »
Programa en el leguaje que sea( de preferencia Java) que lea una lista de cadenas de caracteres, y las valide. Los requerimientos son los siguientes:

Debe leer una lista de cadenas que se supone representan fechas y horarios.
El formato aceptado de cada cadena es: Dia de la semana, hora de inicio, hora final. (Separados por comas)
El programa debe leer cada una de esas cadenas y validarla.
Debe mostrar, después de la captura, la lista de cadenas capturadas indicando cuales son válidas. (o rechazadas, las que les resulte más facil, debe, sin embargo, mostrar el resultado de la validación.)
Para validarla debe tomar en cuenta lo siguiente:
Que los datos estén separados por comas.
Que contenga los tres datos.
Que el orden de los elementos sea precisamente ese: Dia de la semana, hora de inicio, hora final.
Que el día sea un día de la semana válido (Lunes, Martes, Miércoles, etc) Es decir, no debe contener palabras ajenas a la lista.
Tanto la hora de inicio como la final, deben ser válidas también. Es decir, no debe ser algo como las 54:76. Puede usarse un esquema de 24 horas para mayor facilidad.
El formato de la hora debe ser 00:00
Tomar en cuenta que la hora final debe ser mayor que la del principio.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 725
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #1 en: 06 de Marzo 2021, 00:31 »
Con el método split() de la clase String, puedes dividir la cadena en un array de String "cortando" allá donde encuentre una coma
Código: [Seleccionar]
String[] partes = cadena.split(",");
Ahí ya podrías preguntar cuánto mide ese array. Si el tamaño es 3, entonces es que al menos te han dado tres datos.
Si no mide 3, es que faltan o sobran datos.

Si tienes los tres datos, sigues adelante con las comprobaciones.
Puedes hacer un método de tipo boolean que reciba el primer dato y compruebe si es un día de la semana, por ejemplo con un switch, que devuelva true si es "lunes", o "martes", o "miercoles"... y false si no coincide con ningún día.

Los otros dos datos, las horas de inicio y fin, se los pasas por separado a otro método para comprobar que son horas.
Por ejemplo, de nuevo puedes usar split() para cortar entre los dos puntos split(":") y así obtienes otro array con las horas en el primer elemento y los minutos en el segundo elemento.
Luego los parseas a valores int y compruebas si están en los límites correctos: 0 y 23 para las horas, 0 y 59 para los minutos.

Si todos es correcto, lo último que falta comprobar es si la primera hora es anterior a la segunda.
Una forma de hacerlo es transformar esas horas al segundo del día que representan y comprobar si la primera es menor que la segunda

Es decir, por ejemplo las 00:30 representa el segundo 1800 del día:
hora 00 -> 0
minuto 30 --> 30x60 = 1800
0 + 1800 = 1800 segundos desde que ha comenzado el día


Y las 02:45 sería el segundo 9900 del día
hora 02 --> 02x60x60 = 7200
minuto 45 --> 45x60 = 2700
7200 + 2700 = 9900 segundos desde que ha comenzado el día


Como 1800 es menor que 9900, no hay duda de que las 00:30 es anterior a las 02:45

Todo esto son unas posibles formas de resolverlo. Inténtalo y consigas lo que consigas, compártelo por aquí y te ayudamos a corregir y/o completar lo que sea.


NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

cris0710

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 17
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #2 en: 06 de Marzo 2021, 23:45 »
Comence con el codigo pero me atore al inicio con el metodo split ya que no lo habia usado y estuve buscando algunos ejemplos se que no avance practicamente nada pero es lo que llevo al momento

Código: [Seleccionar]
import java.sql.*;//impota todas las librerias de mysql
import java.util.*;// importa todas las librerias de utilidad para leer en teclado

public class ProyectoP2 {
 
  public static void main(String[] args) {
  Scanner scn = new Scanner(System.in);
  String cadena;
  int datos=3;
 
  System.out.println("Ingresa la cadena de texto con el formato indicado");
  System.out.println("\n Dia de la semana,hora de inicio, hora final.");
  cadena = scn.nextLine();
  String[] partes = cadena.split(",");


  if (partes < datos){
   
  }else{
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato");
  }
                                                        }
                                 }

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 725
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #3 en: 07 de Marzo 2021, 00:11 »
Primero, no es necesario que importes las librerías sql. Estas se utilizan para hacer consultas a bases de datos, y no es el caso.

Segundo. El método split() te devuelve un array resultante de "cortar" la cadena allá donde le hayas dicho.
Supongamos que la cadena tecleada es esta cadena compuesta de tres partes separadas por dos comas.
lunes,00:45,02.30

Si le hacemos split(",") a esta cadena, obtendremos un array de 3 elementos como este:
[lunes]  [00:45]  [02:30]

Si la cadena tecleada, solo tuviera 2 partes, el array sería de dos elementos.
Si tuviera 4, pues cuatro elementos.. etc..

Por eso, tras hacer split(), lo primero que vamos a querer pregunta es si el tamaño del array obtenido, es igual a 3. Porque la cadena correcta ha de tener 3 partes, si tiene más o menos, no será valida.
Para saber lo que mide el array, hay que comprobar su atributo length


Código: [Seleccionar]
  if (partes.length == datos){
      //Por ahora tenemos 3 partes, hay que seguir haciendo más comprobaciones.
  }else{
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato");
  }



Tercero, la variable datos a la que das un valor de 3. Puedes usarla si quieres, pero no la necesitas. Para comprobar el tamaño del array, puedes comparar directamente con el valor 3

Código: [Seleccionar]
  if (partes.length == 3){
      //Por ahora tenemos 3 partes, hay que seguir haciendo más comprobaciones.
  }else{
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato");
  }

Bien, la siguiente comprobación sería ver si la primera parte de esa cadena, es un día de la semana: lunes, martes, etc...
Esa primera parte la tienes en el primer elemento del array partes, es decir, en partes[0].

Lo más cómodo es pasarle ese primer elemento a un método de tipo boolean que se encargue de comprobar si es el nombre de un día o no.
Ese es tu siguiente paso.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

cris0710

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 17
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #4 en: 07 de Marzo 2021, 01:11 »
Asi fue como lo modifique solo que me da errores con el inicio del metodo boolean no se si sea por donde esta

Código: [Seleccionar]
import java.util.*;// importa todas las librerias de utilidad para leer en teclado

public class ProyectoP2 {
 
  public static void main(String[] args) {
  Scanner scn = new Scanner(System.in);
  String cadena;
  int flag=3;
 
  do{
  System.out.println("\t Ingresa la cadena de texto con el formato indicado");
  System.out.println("\t Dia de la semana,hora de inicio, hora final.");
  cadena = scn.nextLine();
  String[] partes = cadena.split(",");


 if (partes.length == 3){
      public boolean ComprobarSemana()
      {
        boolean comprobacionSemana = false;
        if(partes[0]==("lunes" || "martes" || "miercoles" || "jueves" || "viernes" || "sabado" || "domingo"))
             {
             flag=1;
             ComprobarSemana= true;
        }else{
          ComprobarSemana= false;
        }
            return ComprobarSemana;
      }
  }else
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");
 
                                                     
  }while(flag == 3);
                             
  }
}

Lo de flag solo lo puse por si la comprobacion da error te devuelva a introducir los datos.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 725
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #5 en: 07 de Marzo 2021, 14:45 »
Asi fue como lo modifique solo que me da errores con el inicio del metodo boolean no se si sea por donde esta


Claro,no puedes declarar un método, dentro de otro método.

El código principal lo estás escribiendo dentro del método main, eso es correcto. Pero dentro de este método, no podemos declarar y escribir otro.
Hay que escribirlo fuera.
Dentro del main, simplemente lo invocaremos para que haga su tarea, pero su código ha de estar declarado fuera.

Código: [Seleccionar]
//Declaracion metodo main
  public static void main(String[] args) {
  Scanner scn = new Scanner(System.in);
  String cadena;
  int flag=3;
 
  do{
  System.out.println("\t Ingresa la cadena de texto con el formato indicado");
  System.out.println("\t Dia de la semana,hora de inicio, hora final.");
  cadena = scn.nextLine();
  String[] partes = cadena.split(",");


 if (partes.length == 3){
     if (comprobarSemana(partes[0])) {
         //Dia de la semana comprobado, ahora hay que comprobar las dos horas de inicio y fin
     }
     else
        System.out.println(partes[0] + " no es un dia de la semana.");
  }else
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");
 
                                                     
  }while(flag == 3);
                             
  }
  //Fin del metodo main

  //Declaracion metodo comprobarSemana
   public boolean comprobarSemana() {
        boolean comprobacionSemana = false;
        if(partes[0]==("lunes" || "martes" || "miercoles" || "jueves" || "viernes" || "sabado" || "domingo"))
             {
             flag=1;
             ComprobarSemana= true;
        }else{
          ComprobarSemana= false;
        }
            return ComprobarSemana;
    }

Bien, ya está declarado fuera. Pero el código de ese método no funcionará
Este método, ha de recibir entre paréntesis, la cadena String que ha de comprobar ya que no va a saber qué es partes[0]

El array partes está declarado dentro del método main, y solo va a existir dentro de este método.
El resto de métodos no pueden saber que es partes, porque están en ámbitos distintos.

Por eso, lo que se hace es definir este método de manera que reciba el String que ha de comprobar entre los paréntesis.
Además el método ha de ser declarado como static, porque lo vamos a llamar desde el main, que también es estático.
No te preocupes ahora en saber que diferencia hay entre métodos static y "no estáticos", ya llegarás a eso en otra ocasión.

Otra cosa que no funcionará es esta comparación:
Código: [Seleccionar]
if(partes[0]==("lunes" || "martes" || "miercoles" || "jueves" || "viernes" || "sabado" || "domingo"))
Ojalá funcionase, porque resultaría muy cómodo poder escribirlo así, pero la sintaxis de Java no funciona de ese modo. No va a servir separar los String con el operador OR ( || )
Además cuando se comparan objetos (un String es un objeto) no es recomendable usar el ==
No va a funcionar como esperamos, ese operador es para tipos primitivos: int, double, boolean, byte,...

Para objetos de clase, hay que usar el método equals().
Así que, un posible método con estas correcciones podría quedar así:
Código: [Seleccionar]
  //Declaracion metodo comprobarSemana
   public static boolean comprobarSemana(String dia) {
        if(dia.equals("lunes") || dia.equals("martes") || dia.equals("miercoles") || dia.equals("jueves") || dia.equals("viernes")
        || dia.equals("sabado") || dia.equals("domingo"))
             return true;
        else
          return false;
    }
Otra alternativa, quizás un poco menos engorrosa de escribir, es utilizar un switch.
El resultado a la hora de computar es el mismo, pero es algo más cómodo de escribir:
Código: [Seleccionar]
  //Declaracion metodo comprobarSemana
   public static boolean comprobarSemana(String dia) {
        switch(dia) {
            case "lunes":
            case "martes":
            case "miercoles":
            case "jueves":
            case "viernes":
            case "sabado":
            case "domingo":
                return true;
            default:
                return false;
        }
    }

Ambas formas son buenas.
Luego ya en el main, llamamos a este método, le pasamos lo que tenemos en partes[0] y  a ver que dice.
Si resulta true, pues habrá que seguir con las siguientes comprobaciones.
Si no, (false) pues informamos que no nos ha dado un día de la semana correcto.

Código: [Seleccionar]
if (partes.length == 3){
     if (comprobarSemana(partes[0])) {
         //Dia de la semana comprobado, ahora hay que comprobar las dos horas de inicio y fin
     }
     else
        System.out.println(partes[0] + " no es un dia de la semana.");
  }else
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");

La siguiente comprobación es revisar el formato de la hora de inicio y la hora de fin.

Para esto puedes declarar otro método, recuerda, ha de ser static y estar fuera del main.
Entre paréntesis indicas que va a recibir un String.
Este String ha de tener el formato --> 00:00

Es decir dos números de dos cifras, separados por dos puntos.
No sería aceptable por ejemplo: 001:45, ni tampoco 1:45, ni 01,45,...

Así que de nuevo podríamos cortar ese String con split(":").
Código: [Seleccionar]
String[] partes = hora.split(":");Esto nos ha de retornar un array de dos elementos.
Si este array no tiene dos elementos, formato mal...
Código: [Seleccionar]
if (partes.length != 2) //Formato malY si estos elemenos, no son Strings de dos caracteres , formato mal...
Código: [Seleccionar]
if (partes[0].length() != 2 || partes[1].length() != 2) //Formato mal
Y una vez comprobado todo esto, además, tenemos que averiguar si nos han dado unas horas acordes con el sistema horario real.
Es decir, la hora 34:78, pues es incorrecta....
Para esto, hay que parsear a números enteros las dos partes que hemos obtenido y ver si están en el rango adecuado.

Código: [Seleccionar]
int hh = Integer.parseInt(partes[0]);
int mm = Integer.parseInt(partes[1]);

Código: [Seleccionar]
if (hh >= 0 && hh <= 23) //Las horas son correctas
Código: [Seleccionar]
if (mm >= 0 && mm <= 59) //Los minutos son correctos
Como ves este método va a tener que hacer muchas comprobaciones y solo podrá retornar true si se cumplen todas ellas.
Intenta escribirlo tú. Insisto, no desesperes ni te frustres si no te sale a la primera, pues que no te salga a la primera es lo normal.

Pero esos errores, confusiones, atascarte al querer trasladar la lógica de tu cerebro a la lógica del programa,...eso es lo que hace que aprendas.

Un saludo.




« Última modificación: 07 de Marzo 2021, 14:49 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

cris0710

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 17
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #6 en: 08 de Marzo 2021, 01:47 »
Hola, muchas gracias por las explicaciones ya logre avanzar una gran parte solo que al ultimo me marco error con los returns no se si porque no declare el metodo como me mencionabas o por que alguna linea mal esto es lo que llevo hasta el momento:

Código: [Seleccionar]
import java.util.*;// importa todas las librerias de utilidad para leer en teclado

public class ProyectoP2 {
 
  public static void main(String[] args) {
  Scanner scn = new Scanner(System.in);
  String cadena;
  int flag=3;
 
  do{
  System.out.println("\t Ingresa la cadena de texto con el formato indicado");
  System.out.println("\t Dia de la semana,hora de inicio, hora final.");
  cadena = scn.nextLine();
  String[] partes = cadena.split(",");


 if (partes.length == 3){
     if (comprobarSemana(partes[0])) {//if 1 comprobar el dia de la semana
       if (partes.length != 2){ //Formato mal if 2 comprobar el formato de la hora 00:00
                 System.out.println("\n \t"+partes[0] + " no esta escrito en el formato establecido 00:00.");
       }else{// cierre if 2
         if (partes[0].length() != 2 || partes[1].length() != 2){ //Formato mal if 3 comprobar hora inicio y hora final en formato 00:00, 00:00
                          System.out.println("\n \t"+partes[0] +","+partes[1]+ " no esta escrito en el formato establecido 00:00,00:00.");
         }else{
           if(comprobarHoras(partes[0])){
             System.out.println("\t Validacion realizada correctamente la cadena introducida: "+cadena+" se apega al formato correctamente");
             }else{
                 System.out.println("\t Formato de hora incorrecto favor de revisar introducir cadena valida (23:59)");
           }
           
         }
       }//cierre else 2
     }// cierre if 1
     else
        System.out.println("\n \t"+partes[0] + " no es un dia de la semana.");
  }else
      System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");
 
                                                     
  }while(flag == 3);
                             
  }
 
  //Declaracion metodo comprobarSemana
        public static boolean comprobarSemana(String dia) {
        boolean comprobacionSemana = false;
        if(dia.equals("lunes") || dia.equals("martes") || dia.equals("miercoles") || dia.equals("jueves") || dia.equals("viernes")
        || dia.equals("sabado") || dia.equals("domingo"))
             return true;
        else
          return false;
    }
          //Declaracion metodo comprobarHoras
         public static boolean comprobarHoras(String hora) {
                   boolean comprobacionHoras = false;
         String[] partes = hora.split(":");
         int hh = Integer.parseInt(partes[0]);
         int mm = Integer.parseInt(partes[1]);
         if (hh >= 0 && hh <= 23){ //Las horas son correctas
           if (mm >= 0 && mm <= 59) //Los minutos son correctos
             return true;
         }else
           return false ;       
}
}


Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 725
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #7 en: 08 de Marzo 2021, 03:48 »
Esta línea que señalo en rojo debería ir en el método de comprobarHoras

Citar
if (partes.length == 3){
     if (comprobarSemana(partes[0])) {//if 1 comprobar el dia de la semana
       if (partes.length != 2){ //Formato mal if 2 comprobar el formato de la hora 00:00
                 System.out.println("\n \t"+partes[0] + " no esta escrito en el formato establecido 00:00.");

Porque ahí, ese "partes" es el array que tiene las tres partes del horario: dia,inicio,fin

Lo de validar longitud igual 2, es para el array "partes" que está en el método comprobar horas.
Aunque los arrays se llamen igual, no tienen ninguna relación entre ellos, porque están en métodos/ámbitos distintos.
Quizás habría sido mejor idea no llamarlos igual para evitar estas confusiones, pero bueno.


Otra cosa que va a fallar en el método, son los if que mostraré a continuación, seguramente el compilador se quejará de que falta un return.
Cuando hacemos return mediante if, tenemos que garantizar dos return, para cuando se cumple la condición que evaluamos y para cuando no se cumple.

El primer if, el que señalo en verde, tiene ambos return garantizados. Pero el segundo if, el que marco en rojo, solo tiene return para cuando SÍ se cumple la condición, pero NO para cuando no la tiene, y esto el compilador no lo puede aceptar.

Citar
if (hh >= 0 && hh <= 23){ //Las horas son correctas
            if (mm >= 0 && mm <= 59) //Los minutos son correctos
                return true;

        } else
           return false ;

En este método hay muchas comprobaciones y es fácil que nos equivoquemos y no proporcionemos un return para cada posibilidad.
Para facilitarlo, podemos cambiar la estrategia.

En los if solo preguntaremos si "está mal", en cuyo caso haremos un return false;
Luego al final del método, la última línea, será un return true; sin ninguna condición.

De esta manera, si se encuentra "algo mal", algún return false habrá puesto fin al método.
Si no ha ocurrido ningún return false, es porque TODO está bien, por lo tanto podemos hacer tranquilamente un retun true.

Así no nos liamos y el compilador quedará contento, pues como hay un return al final que no depende de ninguna condición, queda garantizado que el método podrá finalizar en cualquier caso.

Podría quedar del siguiente modo.
Fíjate que añado algo que no comenté antes, un try  catch para capturar posibles excepciones al parsear horas y minutos.
Esto es importante, porque imagina que el usuario introduce esto: h5:9m
Son dos elementos, correcto.
Cada elemento tiene dos caracteres, correcto.
Pero al intentar parsear eso a números, no va a ser posible porque hay letras. Y se producirá una excepción y el programa se interrumpirá lanzando mensaje de error, a no ser que controlemos esa posible excepción con try catch

Código: [Seleccionar]
     public static boolean comprobarHoras(String hora) {
   
        String[] partes = hora.split(":");
        if (partes.length != 2)
            return false; //No hemos obtenido un array de dos elementos
        else {
            //Sí tenemos dos elementos, pero ambos elementos han de tener longitud de 2 caracteres
            if (partes[0].length() != 2 || partes[1].length() != 2)
                return false;//Uno, o ambos elementos, no tienen dos caracteres
            else {
                //Ambos elementos tienen dos caracteres.
                //Los parseamos a enteros para comprobar si son horas y minutos válidos
                //Usamos try catch por si los caracteres no son números parseables
                try {
                    int hh = Integer.parseInt(partes[0]);
                    int mm = Integer.parseInt(partes[1]);
                    //Comprobamos horas
                    if (hh < 0 || hh >= 24)
                        return false; //Horas incorrectas
                    if (mm < 0 || mm >= 60)
                        return false; //Minutos incorrectos
                }
                catch(NumberFormatException ex) {
                    return false;//Usuario no ha tecleado números
                }
            }
        }
       
        return true; //Todas las comprobaciones han sido correctas
    }


Con este método ya podríamos comprobar ambas horas.
Por cierto, lo de repetir "mientras flag == 3", no lo veo claro, porque solo repetiría si damos tres elementos.
Si damos más o menos, ha de indicar el error, pero estaría bien que siguiera pidiendo cadenas.

Quizás podríamos hacer que se repita hasta que el usuario introduzca la cadena "salir"

Código: [Seleccionar]
public class Main
{
    public static void main(String[] args) {
        Scanner scn = new Scanner(System.in);
        String cadena ="";
 
        while (!cadena.equals("salir")){
            if (!cadena.equals("salir")) {
                System.out.println("\n\t Ingresa la cadena de texto con el formato indicado");
                System.out.println("\t Dia de la semana,hora de inicio, hora final.");
                System.out.println("\t Escriba \"salir\" para terminar programa");
                System.out.print("\n\t Cadena: ");
                cadena = scn.nextLine();
                String[] partes = cadena.split(",");
           
                if (partes.length == 3){
                    if (comprobarSemana(partes[0])) {//if 1 comprobar el dia de la semana
                        if (comprobarHoras(partes[1]) && comprobarHoras(partes[2])) {
                            //Ahora hay que comprobar que la hora de partes[1] es anterior a la de partes[2]
                        }
                        else
                            System.out.println("Formato de horas incorrecto. El fomato ha de ser hh:mm");
             
                    }// cierre if 1
                    else
                        System.out.println("\n \t"+partes[0] + " no es un dia de la semana.");
                }
            }
            else //No hemos obtenido 3 partes
                System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");
        }
       
        System.out.println("Fin de programa");
    }
   
      //Declaracion metodo comprobarSemana
        public static boolean comprobarSemana(String dia) {
            boolean comprobacionSemana = false;
            if(dia.equals("lunes") || dia.equals("martes") || dia.equals("miercoles") || dia.equals("jueves") || dia.equals("viernes")
                || dia.equals("sabado") || dia.equals("domingo"))
                return true;
            else
            return false;
    }
   
     public static boolean comprobarHoras(String hora) {
   
        String[] partes = hora.split(":");
        if (partes.length != 2)
            return false; //No hemos obtenido un array de dos elementos
        else {
            //Sí tenemos dos elementos, pero ambos elementos han de tener longitud de 2 caracteres
            if (partes[0].length() != 2 || partes[1].length() != 2)
                return false;//Uno, o ambos elementos, no tienen dos caracteres
            else {
                //Ambos elementos tienen dos caracteres.
                //Los parseamos a enteros para comprobar si son horas y minutos válidos
                //Usamos try catch por si los caracteres no son números parseables
                try {
                    int hh = Integer.parseInt(partes[0]);
                    int mm = Integer.parseInt(partes[1]);
                    //Comprobamos horas
                    if (hh < 0 || hh >= 24)
                        return false; //Horas incorrectas
                    if (mm < 0 || mm >= 60)
                        return false; //Minutos incorrectos
                }
                catch(NumberFormatException ex) {
                    return false;//Usuario no ha tecleado números
                }
            }
        }
       
        return true; //Todas las comprobaciones han sido correctas
    }
}


Este código se puede probar online en este enlace.

Pero no está completo, falta una última comprobación.
La hora de inicio que tenemos en partes[1] ha de ser anterior a la hora de fin que tenemos en partes[2]

Es decir, esta cadena es correcta: martes,15:30,17:00

Pero esta, no lo es: martes,17:00,15:30

Para comprobar esto, necesitamos nuevo método y podemos hacer que reciba los dos String donde tenemos las horas:

Código: [Seleccionar]
public static boolean comprobarTiempos(String inicio, String fin) {


}

Inicio y fin son horas con formato hh:mm
Y como ya dije anteriormente, una forma fácil de comprobar si una es anterior a la otra es transformar esos tiempos en segundos.
Así que de nuevo habría que hacer split(":") para separar las hh de las mm, tanto de inicio, como de fin
De nuevo hay que parsear a enteros, esta vez podemos ahorrarnos el try catch porque llegados a este punto de programa, ya hemos comprobado que las horas son caracteres numéricos.

Primero convertimos las hh de inicio a segundos, multiplicando por 3600.
Luego los mm, multiplicando por 60 y se los sumamos a los segundos que nos han dado las hh.

Ya tenemos los segundos de inicio. Ahora habría que hacer lo mismo para conseguir los segundos de fin.

Cuando tengamos ambas cantidades de segundos, las comparamos. Si los segundos de inicio son menores que los de fin, todo es correcto, devolvemos TRUE y ya por fin podemos decirle al usuario que la cadena introducida es VÁLIDA.

Si los segundos son iguales, o los de inicio son mayores que los de fin, entones retornamos FALSE y la cadena no es correcta, porque el tiempo de inicio no puede ser posterior al de fin.

Venga, último esfuerzo, ya casi lo tenemos  ;)
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

cris0710

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 17
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #8 en: 08 de Marzo 2021, 10:25 »
El metodo entonces quedaria asi pero tengo duda si como al inicio del metodo separo partes de inicio como de fin entonces al momento de parear hh y mm tiene que ser igual de inicio y fin o con una sola vez se parearian las dos horas

Código: [Seleccionar]
  public static boolean comprobarTiempos(String inicio, String fin) {
        String[] partes = inicio.split(":");
        String[] partes = fin.split(":");
           int hh = Integer.parseInt(partes[0]);
           int mm = Integer.parseInt(partes[1]);
           
}

como llamaria al tiempo de inicio y al tiempo de fin para mutliplicarlos y convertirlos.

Gracias por los consejos me parece una solucion mucho mas facil el salir del programa al introducir salir.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 725
    • Ver Perfil
Re: Función de análisis lexico
« Respuesta #9 en: 08 de Marzo 2021, 12:10 »
Necesitas dos arrays con nombres distintos.
Lo mismo con las variables hh y mm, cambiar nombres para tener las horas y minutos de inicio separadas de las de fin
El método, ya calculando y comparando los tiempos, podría quedar así:
Código: [Seleccionar]
      public static boolean comprobarTiempos(String inicio, String fin) {
        //Inicio
        String[] partesInicio = inicio.split(":");
        int hhIni = Integer.parseInt(partesInicio[0]);
        int mmIni = Integer.parseInt(partesInicio[1]);
        int segundosInicio = hhIni * 3600; //Horas a segundos
        segundosInicio = segundosInicio + (mmIni * 60); //Sumamos los minutos convertidos en segundos
        //Fin
        String[] partesFin = fin.split(":");
        int hhFin = Integer.parseInt(partesFin[0]);
        int mmFin = Integer.parseInt(partesFin[1]);
        int segundosFin = hhFin * 3600;
        segundosFin = segundosFin + (mmFin * 60);
        //Comparamos
        if (segundosInicio < segundosFin)
            return true;
        else
            return false;
    }

Y el programa ya completo, quedaría así:
Código: [Seleccionar]
import java.util.Scanner;

public class Main
{
    public static void main(String[] args) {
        Scanner scn = new Scanner(System.in);
        String cadena ="";
 
        while (!cadena.equals("salir")){
            if (!cadena.equals("salir")) {
                System.out.println("\n\t Ingresa la cadena de texto con el formato indicado");
                System.out.println("\t Dia de la semana,hora de inicio, hora final.");
                System.out.println("\t Escriba \"salir\" para terminar programa");
                System.out.print("\n\t Cadena: ");
                cadena = scn.nextLine();
                String[] partes = cadena.split(",");
           
                if (partes.length == 3){
                    if (comprobarSemana(partes[0])) {//if 1 comprobar el dia de la semana
                        if (comprobarHoras(partes[1]) && comprobarHoras(partes[2])) {
                            //Ahora hay que comprobar que la hora de partes[1] es anterior a la de partes[2]
                            if (comprobarTiempos(partes[1], partes[2]))
                                System.out.println("La cadena es valida");
                            else
                                System.out.println("La hora de inicio ha de ser anterior a la de fin");
                        }
                        else
                            System.out.println("Formato de horas incorrecto. El fomato ha de ser hh:mm");
             
                    }// cierre if 1
                    else
                        System.out.println("\n \t"+partes[0] + " no es un dia de la semana.");
                }
            }
            else //No hemos obtenido 3 partes
                System.out.println("La cadena ingresada es incorrecta favor de verificar el formato \n");
        }
       
        System.out.println("Fin de programa");
    }
   
      //Declaracion metodo comprobarSemana
        public static boolean comprobarSemana(String dia) {
            boolean comprobacionSemana = false;
            if(dia.equals("lunes") || dia.equals("martes") || dia.equals("miercoles") || dia.equals("jueves") || dia.equals("viernes")
                || dia.equals("sabado") || dia.equals("domingo"))
                return true;
            else
            return false;
    }
   
     public static boolean comprobarHoras(String hora) {
   
        String[] partes = hora.split(":");
        if (partes.length != 2)
            return false; //No hemos obtenido un array de dos elementos
        else {
            //Sí tenemos dos elementos, pero ambos elementos han de tener longitud de 2 caracteres
            if (partes[0].length() != 2 || partes[1].length() != 2)
                return false;//Uno, o ambos elementos, no tienen dos caracteres
            else {
                //Ambos elementos tienen dos caracteres.
                //Los parseamos a enteros para comprobar si son horas y minutos válidos
                //Usamos try catch por si los caracteres no son números parseables
                try {
                    int hh = Integer.parseInt(partes[0]);
                    int mm = Integer.parseInt(partes[1]);
                    //Comprobamos horas
                    if (hh < 0 || hh >= 24)
                        return false; //Horas incorrectas
                    if (mm < 0 || mm >= 60)
                        return false; //Minutos incorrectos
                }
                catch(NumberFormatException ex) {
                    return false;//Usuario no ha tecleado números
                }
            }
        }
       
        return true; //Todas las comprobaciones han sido correctas
    }
   
      public static boolean comprobarTiempos(String inicio, String fin) {
        //Inicio
        String[] partesInicio = inicio.split(":");
        int hhIni = Integer.parseInt(partesInicio[0]);
        int mmIni = Integer.parseInt(partesInicio[1]);
        int segundosInicio = hhIni * 3600; //Horas a segundos
        segundosInicio = segundosInicio + (mmIni * 60); //Sumamos los minutos convertidos en segundos
        //Fin
        String[] partesFin = fin.split(":");
        int hhFin = Integer.parseInt(partesFin[0]);
        int mmFin = Integer.parseInt(partesFin[1]);
        int segundosFin = hhFin * 3600;
        segundosFin = segundosFin + (mmFin * 60);
        //Comparamos
        if (segundosInicio < segundosFin)
            return true;
        else
            return false;
    }
}


Y creo que con esto se termina.  :)
Si sigues teniendo dudas o preguntas, no te las guardes y publícalas.

Y espero que cuando otros visitantes lean este tema, vean la importancia de intentar uno mismo hacer el código y fallar, y atascarse, y equivocarse con la sintaxis, etc...

Yo podría haberte dado el programa terminado. De hecho, lo escribí (con una solución algo distinta a la que hemos hecho aquí) antes de tu primera respuesta.
Podría habértelo dado y explicado que hago aquí, y que hago allá.

Y tu habrías entendido las explicaciones, sí...pero habrías aprendido menos.
No es lo mismo que si lo intentas tú y te vas encontrando con todas las dudas que has ido teniendo:
- no se puede declarar un método dentro de otro.
- dos elementos (variable, array, objeto, lo que sea...) aunque se llamen igual dentro del programa, son cosas distintas si están declarados en métodos distintos. El array partes del método main principal es distinto del array partes del método comprobarHoras()
- en los métodos que retornan un valor, ya sea boolean, int, String... lo que sea..., hay que tener cuidado con las instrucciones condicionales (if, switch..) porque el código que escribamos ha de garantizar que se va a retornar dicho valor.

Y más cosas...

Insisto mucho en esto porque en muchos foros veo gente pidiendo ayuda con los ejercicios pero solo buscan que les den la solución terminada.
Y hacerles el trabajo, pues no estamos para eso la verdad..., pero sobre todo porque entonces no se les ayuda realmente.

A mi me resultaría más rápido y cómodo escribir el código y "regalarlo", además tengo un tiempo algo limitado para dedicarlo a esto.

El código de este ejercicio ya lo escribí hace un par de días, podría habértelo dado y olvidarme para dedicarme a otra cosa.
Pero prefiero ayudar a que lo intentes, aunque nos llevase varios días, e ir resolviendo dudas conforme van surgiendo.

Espero que haya sido útil. Un saludo.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".