简体   繁体   中英

Java check String and match

I am trying to do a math operation and match a letter of a string:

I got this table:

static final char[] LETTERS = {'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X','B', 'N',  'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'};

桌子

And I am getting inputs from keyboard of ID's that are in 012345678X (8 digits + 1 char)

I am trying to make it check for 8digits+1char and got it done like this:

public void check() {
 if(input.matches("[0-9]{8}[TRWAGMYFPDXBNJZSQVHLCKE]{1}")){
status = true;}

My problem is that now I need to check the last entered letter matches the table by calculating the numbers of the input % 23. Example of valid inputs:

  • 00000102X since 102 % 23 = 10 and X is 10th letter in my char list;
  • 24659213Q since 24659213 % 23 = 16 and Q is 16th letter in char list.

Now what I did try is this:

int num = Integer.parseInt(input.replaceAll("[^0-9]", ""));
if(input.matches("[0-9]{8}[TRWAGMYFPDXBNJZSQVHLCKE]{1}"))
    {
      switch(num){
        case 0: if(num%23==0){
            if(input.charAt(8)==LETTERS[0]){
                status = true;
                break;
            }}
....
        case 10: if(num%23==10){
            if(input.indexOf(8)==LETTERS[10]){
                status = true;
            }}

        default: status = false;
    }

But with no results, any idea where am I going wrong? It's not that I get a compilation or code error, just that every 8digit+1letter input I get it gets accepted. Thank you in advance!

EDIT (PASTED CODE)

import java.util.Scanner;
public class Testing {

    static final char[] LETRAS = {'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X'
                                 ,'B', 'N',  'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C'
                                 , 'K', 'E'};
    String input;
    public boolean status = false;
    Scanner scanner = new Scanner(System.in);

 //Método problema general
public static void main (String[] args) {
Testing programa = new Testing();
programa.inicio();
}

public void inicio() {
    Intro();
    while (!status){
    datosUsuario();
    comprobacion();
    resultado();
}
}

//Explicar programa
public void Intro() {
    System.out.println("¡Hola!\nEste programa pide y comprueba DNI's."
            + "A continuación va a pedir un DNI de forma 8 dígitos y una letra,"
            + "y va a comprobar si es válido.\n"
            + "Ejemplo DNI válido: 24659213Q\n\n");
}

//Métodos primer nivel de decomposición
//Pedir DNI por teclado
public void datosUsuario() {
    System.out.print("Escribe DNI: ");
    input = scanner.nextLine();
}


//Comprobación DNI
public boolean comprobacion() {
    System.out.println("Comprobamos DNI...");
    char letra = input.charAt(8);
    if(input.matches("[0-9]{8}[TRWAGMYFPDXBNJZSQVHLCKEtrwagmyfpdxbnjzsqvhlcke]{1}"))
    {
        int numeros = Integer.parseInt(input.replaceAll("[^0-9]", ""));
        if(LETRAS[numeros%LETRAS.length] == input.charAt(8)) {
            return true;
        }
    }
    return false;
}

//Mostrar resultado
public void resultado() {
    if(status&&comprobacion()){
        System.out.println("DNI válido!");
    }
}
}

I see many problems in your code , first I am not sure why is the switch for? you can simply do it like this

    public static boolean isValid(String str) {

    if(str.matches("[0-9]{8}[TRWAGMYFPDXBNJZSQVHLCKE]{1}")) {
        int num = Integer.parseInt(str.replaceAll("[^0-9]", ""));
        if(LETTERS[num%LETTERS.length] == str.charAt(8) ) {
            return true;
        }
    }
    return false;
}
  1. You shouldn't parse the String before matching the regex. If the pattern does not match the String input.replaceAll("[^0-9]", "") could return the empty String ; Integer.parseInt throws an exception in this case.
  2. If the regex matches, you know which part of the String contains the number. Using substring is more efficient than using replaceAll in this case.
  3. Just compare the char you get from the from the input with the char in the array. Don't use a switch .
  4. If you compare the last letter with the element from the array, you do not need such a complicated character group. Just allow any character as the last one and leave the rest to the comparison with the array element.

static final char[] LETTERS = {'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X','B', 'N',  'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'};

public static boolean checkInput(String input) {
    return input.matches("[0-9]{8}.")
               && LETTERS[Integer.parseInt(input.substring(0, 8)) % LETTERS.length] == input.charAt(8);
}

Try this:

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegexTester2 {

    static final char[] LETTERS = {'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X','B', 'N',  'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'};

    public static boolean isMatch(String input) {

        Pattern p = Pattern.compile("^([0-9]{8})([TRWAGMYFPDXBNJZSQVHLCKE])$");

        Matcher m = p.matcher(input);

        if (m.matches()) {
            String strNum = m.group(1);
            String lastChar = m.group(2);
            int num = Integer.parseInt(strNum);
            int idx = num % 23;
            return LETTERS[idx] == lastChar.charAt(0);
        }
        return false;
    }

    public static void main(String[] args) {
        String[] inputs = {
                "00000102X",
                "24659213Q",
                "12345679Z"
        };

        for (String s : inputs) {
            System.out.println("match? " + s + " " + isMatch(s));
        }

    }
}

Your problem about in your value " num ". You check if ( num % 23 == 10 ) but what is your num ? You need value for " num " you need the get from user or you can give this value yourself. You need this i think good luck.

Do this:

final Pattern pat = Pattern.compile("[0-9]{8}[TRWAGMYFPDXBNJZSQVHLCKE]{1}");
final Matcher finder = pat.matcher(input);
final ArrayList<String> matchList = new ArrayList<String>();

while(finder.find()){
    char vchar;
    MatchResult mr = finder.toMatchResult();

    try {
        int vnum = Integer.parseInt(input.substring(mr.start(), mr.end() - 1));
        vchar = LETTERS[vnum % 23];
    } catch(Exception e){
        continue;
    }

    if(vchar == input.charAt(mr.end() - 1)){
        matchList.add(input.substring(mr.start(), mr.end()));
    }
}

The input is one string: "00000102X00000102X" would match twice. You could tweak the code to accept an array of input strings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM