Autor Tema: Java Captura por teclado sin crear una variable validar la letra del nif o dni  (Leído 7102 veces)

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
El título del tema es ortopédico, perdón.

En la asignatura de Programación me piden, en un ejercicio, en primer lugar que cree una clase Alumno con sus atributos y sus setters y getters. En uno de los setters, que establece el NIF de un alumno, debo comprobar que la letra es correcta. Hasta ahí todo correcto. A continuación se me pide:

Citar
Crea otra clase que se llamará EntradaAlumnos, esta clase tendrá un método main donde se declararán 2 objetos de la clase Alumno, uno de ellos llamado alumno1 se inicializarán todos sus atributos a través de la entrada por teclado de esos datos, sin utilizar variables intermedias locales del método main, el otro objeto se instanciará y llenará a través de variables locales que se han declarado en el método main, usando para inicializar el objeto alumno2 el constructor en el que se pasan todos los parámetros.

Es aquí donde me surge el problema, ya que no consigo dilucidar cómo puedo pasar el método calcularLetra al NIF introducido sin almacenar en una variable la entrada por teclado. O, mejor dicho, ya que necesito hacer varias operaciones con el NIF (por un lado sacar el número para enviárselo al método y, por otro lado, calcular cuál es el caracter de la posición 8 ) , cómo podría realizarlas todas pidiendo el NIF una sola vez.

Este problema me surge, por cierto, por la siguiente frase del enunciado:

Citar
sin utilizar variables intermedias locales del método main

que si no me equivoco hace referencia a que en el código que pego a continuación, no se me permite crear la variable "nif".


Código: [Seleccionar]
import java.util.Scanner;

public class EntradaAlumnos
{
     public static void main(String[] args) {
         
         Alumno alumno1 = new Alumno();

         System.out.println("NIF del alumno: ");
         Scanner sc = new Scanner(System.in);
         String nif = sc.nextLine();
         
         System.out.println("NIF: " + nif);
         System.out.println("Letra calculada: " + alumno1.calcularLetra (nif.substring(0, 8)));
         System.out.println("Letra introducida: " + nif.charAt(8));
        }
    }

Agradecería cualquier pista sobre el tema, ya que hago Programación a distancia y la docencia brilla por su ausencia.
« Última modificación: 16 de Abril 2017, 19:59 por Alex Rodríguez »

pedro,,

  • Moderador Global
  • Experto
  • *******
  • APR2.COM
  • Mensajes: 1292
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #1 en: 07 de Febrero 2017, 19:41 »
Hola Primo.

Pedimos los datos del alumno y al mismo tiempo se los vamos asignado a cada atributo del alumno sin usar  variables intermedias locales del método main:

Código: [Seleccionar]
System.out.println("Introduce el nif del alumno1: ");
alumno1.setNif(sc.nexLine());

Y así con los demás atributos de tu clase alumno, de esta forma no haces uso de ninguna variable.

Saludos. ;D
« Última modificación: 07 de Febrero 2017, 19:43 por pedro,, »

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #2 en: 07 de Febrero 2017, 20:43 »
Gracias, Pedro.
Sin embargo, ese código sólo me serviría si asignara directamente la cadena del teclado a ese atributo. Pero necesito pasar la cadena, previamente, por los dos métodos: CalcularLetra y substring. Eso es lo que no consigo: pasar la cadena por esos dos métodos sin asignar el texto a una variable.
He probado pasando esta secuencia:

Código: [Seleccionar]
alumno1.setNif(sc.nexLine());
directamente por los métodos, pero me arroja diversos errores de incompatibilidad.

pedro,,

  • Moderador Global
  • Experto
  • *******
  • APR2.COM
  • Mensajes: 1292
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #3 en: 07 de Febrero 2017, 20:56 »
Según tu consulta...
Citar
En uno de los setters, que establece el NIF de un alumno, debo comprobar que la letra es correcta.

La comprobación debes de hacerla en el setter que establece el NIF en la clase Alumno.
Así que no tendrías problema, otra cosa es que quisieses comprobarlo con anterioridad.

Saludos. ;D

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #4 en: 08 de Febrero 2017, 00:26 »
Perfecto. Muchas gracias.

Si me permites, una cuestión: ¿cómo tendría que hacer si quisiera, por ejemplo, pedir el NIF hasta que sea correcto (con un do-while)? La instrucción de pedir la entrada del teclado no está en el setter original y no veo cómo repetirla en la nueva clase.

Por otro lado, y perdón si estoy abusando, te agradecería si me arrojas luz sobre la última parte del enunciado. Aunque sospecho que en gran medida es un problema de mala redacción, seguro que con tus conocimientos me puedes dar alguna pista de qué me está pidiendo aquí:

Citar
Crea otra clase que se llamará EntradaAlumnos, esta clase tendrá un método main donde se declararán 2 objetos de la clase Alumno, uno de ellos llamado alumno1 se inicializarán todos sus atributos a través de la entrada por teclado de esos datos, sin utilizar variables intermedias locales del método main, el otro objeto se instanciará y llenará a través de variables locales que se han declarado en el método main, usando para inicializar el objeto alumno2 el constructor en el que se pasan todos los parámetros.


¿Se refiere por casualidad a esto?:

 
Código: [Seleccionar]
Alumno alumno2 = new Alumno("45011556A", "ELISA", "ALERA PLUVA", "16 DE MAYO", "CALVERO","12");
       
« Última modificación: 08 de Febrero 2017, 00:47 por Primo »

pedro,,

  • Moderador Global
  • Experto
  • *******
  • APR2.COM
  • Mensajes: 1292
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #5 en: 08 de Febrero 2017, 09:17 »
Buenas.

Usando do while se podría hacer, también dependerá de como sea el método que comprueba si la fecha es correcta, es decir, si ese método es un método que devuelve true o false dependiendo de si la fecha es correcta o no, podríamos usarlo en la condición del while, sino es así, mejor pon el código de tu clase Alumno y vemos que se puede hacer.

A la segunda pregunta, decirte que sí, pero usando variables locales.

Saludos.  ;D

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #6 en: 08 de Febrero 2017, 11:03 »
Vale, voy a pegar las dos clases tal como las tengo ahora.

En la clase Alumno he modificado el método que calcula la letra que corresponde al NIF para que retorne un booleano.

Código: [Seleccionar]
public class Alumno
{
    private String nif;
    private String nombre;
    private String apellidos;
    private String direccion;
    private String poblacion;
    private String matricula;
   
   
     public Alumno (String valorNif, String valorNombre, String valorApellidos, String valorDireccion, String valorPoblacion, String valorMatricula){
       nif=valorNif;
       nombre=valorNombre;
       apellidos=valorApellidos;
       direccion=valorDireccion;
       poblacion=valorPoblacion;
       matricula=valorMatricula;
    }   
   
    public void setNif(String nif){
        if (validarLetra(nif) == true){
            this.nif=nif;
        } else {
            System.out.println("El NIF introducido es INCORRECTO. Intentalo de nuevo.");
            this.nif="INVALIDO";
        }
    }
    public String getNif(){
        return this.nif;
    }
   
    public void setNombre(String nombre){
        this.nombre=nombre;
    }
    public String getNombre(){
        return this.nombre;
    }
   
    public void setApellidos(String apellidos){
        this.apellidos=apellidos;
    }
    public String getApellidos(){
        return this.apellidos;
    }
   
    public void setDireccion(String direccion){
        this.direccion=direccion;
    }
    public String getDireccion(){
        return this.direccion;
    }
   
    public void setPoblacion(String poblacion){
        this.poblacion=poblacion;
    }
    public String getPoblacion(){
        return this.poblacion;
    }
   
    public void setMatricula(String matricula){
        this.matricula=matricula;
    }
    public String getMatricula(){
        return this.matricula;
    }
   
    public Alumno () {}
   
    public boolean validarLetra(String nif){
        String caracteres = "TRWAGMYFPDXBNJZSQVHLCKE";
        int numeroDNI = Integer.parseInt(nif.substring(0, 8));
        int modulo= numeroDNI % 23;
        char letraNifCalculada = caracteres.charAt(modulo);
        boolean EsValido = false;
       
        if (letraNifCalculada == nif.charAt(8)){
            EsValido = true;
        }
        return EsValido;
    }
   
   
}

Y esto es lo mejor que he podido conseguir para que repita la petición en caso de que el NIF introducido sea incorrecto. Preferiría que la comprobación se hiciera directamente sobre el resultado booleano de validarLetra, pero desconozco cómo hacerlo.

Código: [Seleccionar]

import java.util.Scanner;

public class EntradaAlumnos
{
     public static void main(String[] args) {
         

         Alumno alumno1 = new Alumno();

         
         Scanner sc = new Scanner(System.in);
         
         do {
             System.out.println("NIF del alumno: ");
             alumno1.setNif(sc.nextLine());
            } while (alumno1.getNif()=="INVALIDO");
       
           
         System.out.println("NOMBRE: ");
         alumno1.setNombre(sc.nextLine());
         
         System.out.println("APELLIDOS: ");
         alumno1.setApellidos(sc.nextLine());
         
         System.out.println("DIRECCION: ");
         alumno1.setDireccion(sc.nextLine());
         
         System.out.println("POBLACION: ");
         alumno1.setPoblacion(sc.nextLine());
         
         System.out.println("MATRICULA: ");
         alumno1.setMatricula(sc.nextLine());
         
         
         System.out.println("---DATOS DEL ALUMNO 1---");
         System.out.println("NIF: " + alumno1.getNif());
         System.out.println("NOMBRE: " + alumno1.getNombre());
         System.out.println("APELLIDOS: " + alumno1.getApellidos());
         System.out.println("DIRECCION: " + alumno1.getDireccion());
         System.out.println("POBLACION: " + alumno1.getPoblacion());
         System.out.println("MATRICULA: " + alumno1.getMatricula());
       
         Alumno alumno2 = new Alumno("33020556G", "PEPA", "PONS ALEA", "15 DE MAYO", "MARA","12");
     
         System.out.println("---DATOS DEL ALUMNO 2---");
         System.out.println("NIF: " + alumno2.getNif());
         System.out.println("NOMBRE: " + alumno2.getNombre());
         System.out.println("APELLIDOS: " + alumno2.getApellidos());
         System.out.println("DIRECCION: " + alumno2.getDireccion());
         System.out.println("POBLACION: " + alumno2.getPoblacion());
         System.out.println("MATRICULA: " + alumno2.getMatricula());
       
    }
   
}

Respecto a esto:

Citar
A la segunda pregunta, decirte que sí, pero usando variables locales.

He intentado hacerlo siguiendo estas instrucciones:

https://www.aprenderaprogramar.es/index.php?option=com_content&view=article&id=494:variables-locales-a-un-metodo-o-constructor-en-java-conflictos-y-sobrecarga-de-nombres-cu00638b&catid=68:curso-aprender-programacion-java-desde-cero&Itemid=188

Es decir con:

Código: [Seleccionar]
public Alumno() {
        nif= "45355676D";
    }

Pero me arroja "illegal start of expression".

pedro,,

  • Moderador Global
  • Experto
  • *******
  • APR2.COM
  • Mensajes: 1292
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #7 en: 08 de Febrero 2017, 17:53 »
Ahora, para declarar dar los valores de los atributos al alumno2, sí tienes que crear variables locales, guardar lo que recojas del teclado en ellas y luego crear el alumno2 pasándole como parámetros estas variables, todo esto en la clase EntradaAlumnos.

Comentarte también sobre el método que creaste para validar el nif, que deberías profundizar más en los posibles errores que pueda dar, por ejemplo si no se introducen 8 números y una letra dará error, yo personalmente tengo un nif de 6 cifras numéricas y una letra, así que tu método me daría error. :o

Saludos. ;D

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #8 en: 09 de Febrero 2017, 10:19 »
Justo había utilizado una regex pero, claro, con el formato de 8 números. Según

https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal

hay NIFs con 7 números, pero no con 6.

Así pues, he pensado en utilizar, como primer paso, una regex que me diga (IF...) si el formato del NIF se corresponde con el "estándar" (8 números +letra). En caso de que no (ELSE...), pasaría a comprobar si el formato introducido es de letra+7 números+letra y, en tal caso, comprobaría (IF...) que la primera letra sea una de las tres del NIE (X, Y, Z). En tal caso, lanzaría el cálculo de la letra para cada caso particular. Si no tiene tampoco ese formato (ELSE...) imprimiría un mensaje de error y volvería a preguntar por el NIF.

¿Es correcto?

Vuelvo a poner las dos clases. La primera, para la regex que valida el NIF; la segunda, para la instanciación de alumno2 con variables locales.

Código: [Seleccionar]
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Alumno
{
    private String nif;
    private String nombre;
    private String apellidos;
    private String direccion;
    private String poblacion;
    private String matricula;
   
   
     public Alumno (String valorNif, String valorNombre, String valorApellidos, String valorDireccion, String valorPoblacion, String valorMatricula){
       nif=valorNif;
       nombre=valorNombre;
       apellidos=valorApellidos;
       direccion=valorDireccion;
       poblacion=valorPoblacion;
       matricula=valorMatricula;
    }   
   
    public void setNif(String nif){
        if (validarNif(nif) == true){
            this.nif=nif;
        } else {
            this.nif="INVALIDO";
        }
    }
    public String getNif(){
        return this.nif;
    }
   
    public void setNombre(String nombre){
        this.nombre=nombre;
    }
    public String getNombre(){
        return this.nombre;
    }
   
    public void setApellidos(String apellidos){
        this.apellidos=apellidos;
    }
    public String getApellidos(){
        return this.apellidos;
    }
   
    public void setDireccion(String direccion){
        this.direccion=direccion;
    }
    public String getDireccion(){
        return this.direccion;
    }
   
    public void setPoblacion(String poblacion){
        this.poblacion=poblacion;
    }
    public String getPoblacion(){
        return this.poblacion;
    }
   
    public void setMatricula(String matricula){
        this.matricula=matricula;
    }
    public String getMatricula(){
        return this.matricula;
    }
   
    public Alumno () {}
   
    public boolean validarNif (String nif){
       
        Pattern pat = Pattern.compile("\\d{8}[A-Z]");
        Matcher mat = pat.matcher(nif);
        boolean esValido = false;
       
        if (mat.matches()){
           
            String caracteres = "TRWAGMYFPDXBNJZSQVHLCKE";
            int numeroDNI = Integer.parseInt(nif.substring(0, 8));
            int modulo= numeroDNI % 23;
            char letraNifCalculada = caracteres.charAt(modulo);
            esValido = false;
           
            if (letraNifCalculada == nif.charAt(8)){
                esValido = true;
            } else {
                System.out.println("La letra del NIF no es correcta. Intentalo otra vez.");
            }
           
        } else {
            System.out.println("El NIF introducido no tiene el formato correcto. \nDebe contener 8 numeros seguidos de una letra mayuscula.");
        }
       
        return esValido;
    }
   
}
Código: [Seleccionar]
import java.util.Scanner;

public class EntradaAlumnos
{
     public static void main(String[] args) {
         

         Alumno alumno1 = new Alumno();

         
         Scanner sc = new Scanner(System.in);
         System.out.println("Introduce los datos del alumno 1: ");
         do {
             System.out.println("NIF del alumno: ");
             alumno1.setNif(sc.nextLine());
            } while (alumno1.getNif()=="INVALIDO");
       
         
         System.out.println("NOMBRE: ");
         alumno1.setNombre(sc.nextLine());
         
         System.out.println("APELLIDOS: ");
         alumno1.setApellidos(sc.nextLine());
         
         System.out.println("DIRECCION: ");
         alumno1.setDireccion(sc.nextLine());
         
         System.out.println("POBLACION: ");
         alumno1.setPoblacion(sc.nextLine());
         
         System.out.println("MATRICULA: ");
         alumno1.setMatricula(sc.nextLine());
         
         
         System.out.println("Introduce los datos del alumno 2: ");
         System.out.println("NIF: ");
         String nif2 = sc.nextLine();
         System.out.println("NOMBRE: ");
         String nombre2 = sc.nextLine();
         System.out.println("APELLIDOS: ");
         String apellidos2 = sc.nextLine();
         System.out.println("DIRECCION: ");
         String direccion2 = sc.nextLine();
         System.out.println("POBLACION: ");
         String poblacion2 = sc.nextLine();
         System.out.println("MATRICULA: ");
         String matricula2 = sc.nextLine();
         
         Alumno alumno2 = new Alumno(nif2, nombre2, apellidos2, direccion2, poblacion2, matricula2);
         
         System.out.println("---DATOS DEL ALUMNO 1---");
         System.out.println("NIF: " + alumno1.getNif());
         System.out.println("NOMBRE: " + alumno1.getNombre());
         System.out.println("APELLIDOS: " + alumno1.getApellidos());
         System.out.println("DIRECCION: " + alumno1.getDireccion());
         System.out.println("POBLACION: " + alumno1.getPoblacion());
         System.out.println("MATRICULA: " + alumno1.getMatricula());
       
 
     
         System.out.println("---DATOS DEL ALUMNO 2---");
         System.out.println("NIF: " + alumno2.getNif());
         System.out.println("NOMBRE: " + alumno2.getNombre());
         System.out.println("APELLIDOS: " + alumno2.getApellidos());
         System.out.println("DIRECCION: " + alumno2.getDireccion());
         System.out.println("POBLACION: " + alumno2.getPoblacion());
         System.out.println("MATRICULA: " + alumno2.getMatricula());
       
    }
       
         
}
« Última modificación: 09 de Febrero 2017, 14:46 por Primo »

Primo

  • Sin experiencia
  • *
  • Mensajes: 6
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #9 en: 09 de Febrero 2017, 21:18 »
Bueno, así he dejado finalmente la clase Alumno comprobando todas los formatos de NIF/NIE:

Código: [Seleccionar]
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Alumno
{
    private String nif;
    private String nombre;
    private String apellidos;
    private String direccion;
    private String poblacion;
    private String matricula;

    public Alumno (String valorNif, String valorNombre, String valorApellidos, String valorDireccion, String valorPoblacion, String valorMatricula){
        nif=valorNif;
        nombre=valorNombre;
        apellidos=valorApellidos;
        direccion=valorDireccion;
        poblacion=valorPoblacion;
        matricula=valorMatricula;
    }   

    public void setNif(String nif){
        if (validarNif(nif) == true){
            this.nif=nif;
        } else {
            this.nif="INVALIDO";
        }
    }

    public String getNif(){
        return this.nif;
    }

    public void setNombre(String nombre){
        this.nombre=nombre;
    }

    public String getNombre(){
        return this.nombre;
    }

    public void setApellidos(String apellidos){
        this.apellidos=apellidos;
    }

    public String getApellidos(){
        return this.apellidos;
    }

    public void setDireccion(String direccion){
        this.direccion=direccion;
    }

    public String getDireccion(){
        return this.direccion;
    }

    public void setPoblacion(String poblacion){
        this.poblacion=poblacion;
    }

    public String getPoblacion(){
        return this.poblacion;
    }

    public void setMatricula(String matricula){
        this.matricula=matricula;
    }

    public String getMatricula(){
        return this.matricula;
    }

    public Alumno () {}

    public boolean validarNif (String nif){

        Pattern patEstandar = Pattern.compile("\\d{8}[A-Z]"); // Expresión regular para el formato estándar.
        Matcher nifEstandar = patEstandar.matcher(nif);
       
        Pattern patNie = Pattern.compile("[XYZ]\\d{7}[A-Z]"); // Expresión regular para el NIE.
        Matcher nifNie = patNie.matcher(nif);
       
        // Mediante expresiones regulares acotamos los dos formatos de entrada admitidos.
       
        String caracteres = "TRWAGMYFPDXBNJZSQVHLCKE";
        boolean esValido = false;

        if (nifEstandar.matches()){ // Si el NIF tiene un formato estandar...
            if (caracteres.charAt(Integer.parseInt(nif.substring(0, 8)) % 23) == nif.charAt(8)) 
            /*
             * 1. Se convierte a entero la parte del NIF correspondiente al número.
             * 2. Se divide ésta entre 23. Se toma el resto de la division.
             * 3. Se comprueba qué letra de la cadena "caracteres" se encuentra en la posición correspondiente al resto.
             * 4. Se compara ésta con la que ha introducido el usuario.
             */
            {esValido = true;} else {System.out.println("La letra del NIF no es correcta. Intentalo otra vez.");}
            // En caso de que ambas sean iguales, se valida el booleano; en caso contrario, se informa del error.

        } else if (nifNie.matches()){ // Si resulta tener el formato de un NIE...
            switch(nif.charAt(0)){ // En función de la letra inicial (X, Y o Z) se continúa por un itinerario u otro.
                case 'X':
                if (caracteres.charAt(Integer.parseInt(nif.substring(1, 8)) % 23) == nif.charAt(8)){
                    esValido = true;} else {System.out.println("La letra del NIF no es correcta. Intentalo otra vez.");}
                // En este caso, el proceso a seguir es el mismo que para el NIF, excepto que se desecha la X inicial.
                break;
               
                case 'Y': // Si comienza por Y...
                nif = nif.replace('Y', '1'); // Se sustituye la Y por un 1 y se sigue el proceso ya indicado.
                if (caracteres.charAt(Integer.parseInt(nif.substring(0, 8)) % 23) == nif.charAt(8)){
                    esValido = true;} else {System.out.println("La letra del NIF no es correcta. Intentalo otra vez.");} 
                   
                break;
                case 'Z': // Si comienza por Z...
                nif = nif.replace('Z', '2'); // Se sustituye la Z por un 2 y continúa el proceso ya indicado.
                if(caracteres.charAt(Integer.parseInt(nif.substring(0, 8)) % 23) == nif.charAt(8)){
                    esValido = true;} else {System.out.println("La letra del NIF no es correcta. Intentalo otra vez.");}     
                break;
            }
        } else { // Si no coincide con ninguno de los dos formatos...
            System.out.println("El formato de este NIF/NIE no es valido.");} // Se imprime un aviso de error
        return esValido; // Se retorna el valor de la variable booleana
    }
}

pedro,,

  • Moderador Global
  • Experto
  • *******
  • APR2.COM
  • Mensajes: 1292
    • Ver Perfil
Re:Captura por teclado sin crear una variable
« Respuesta #10 en: 09 de Febrero 2017, 21:37 »
Buenas.

Ahora el código queda completo.

Mi nif por mucho que diga wikipedia tiene 6 cifras y una letra, 7*3**4*?, me imagino que oficialmente habría que añadirle dos ceros delante.

Saludos. ;D

 

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".