Postar resposta

Observação: Este post não será mostrado enquanto não for aprovado por um moderador.

Nome:
Email:
Assunto:
Ícone de mensagem:

Verificação:
Escreva as letras mostradas na imagem
Escutar as letras / Pedir uma nova imagem

Escreva as letras mostradas na imagem:
Escreva "convidado" (sem as aspas) na caixa ao lado (ou abaixo).:

atalhos: pressione alt+s para enviar ou alt+p para pré-visualizar


Resumo do Tópico

Enviado por: Jefferson
« Online: Abril 17, 2019, 01:48:36 am »

Duas coisas que me deixaram confuso ao ler essa função, mas só por eu ser inexperiente:

return soma > 9 ? 0 : soma;

Essa é uma aplicação do operador ternário e equivale a:

if (soma>9) {
    return 0;
} else {
return soma;
}

A segunda foi o que danado "digito" está fazendo nesta linha:

for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {


Mas descobri que isso é uma simplificação de:

int digito;
for (int indice=str.length()-1; indice >= 0; indice-- ) {

Enviado por: Jefferson
« Online: Abril 16, 2019, 05:23:22 pm »

Se você procurar por isso na Internet uma das funções mais fáceis de entender que você encontra é esta aqui, que também valida o CNPJ:

Código: Java
1234567891011121314151617181920212223242526272829
public class ValidaCPFCNPJ {   private static final int[] pesoCPF = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2};   private static final int[] pesoCNPJ = {6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2};   private static int calcularDigito(String str, int[] peso) {      int soma = 0;      for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {         digito = Integer.parseInt(str.substring(indice,indice+1));         soma += digito*peso[peso.length-str.length()+indice];      }      soma = 11 - soma % 11;      return soma > 9 ? 0 : soma;   }   public static boolean isValidCPF(String cpf) {      if ((cpf==null) || (cpf.length()!=11)) return false;      Integer digito1 = calcularDigito(cpf.substring(0,9), pesoCPF);      Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1, pesoCPF);      return cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());   }   public static boolean isValidCNPJ(String cnpj) {      if ((cnpj==null)||(cnpj.length()!=14)) return false;      Integer digito1 = calcularDigito(cnpj.substring(0,12), pesoCNPJ);      Integer digito2 = calcularDigito(cnpj.substring(0,12) + digito1, pesoCNPJ);      return cnpj.equals(cnpj.substring(0,12) + digito1.toString() + digito2.toString());   }   public static void main(String[] args) {      System.out.printf("CPF Valido:%s \n", isValidCPF("01115375502"));      System.out.printf("CNPJ Valido:%s \n", isValidCNPJ("13642634756318"));   }}

Para melhorar a clareza, vamos retirar a parte relacionada com a validação do CNPJ. Aproveitei para acrescentar alguns casos de teste do CPF:

Código: Java
123456789101112131415161718192021222324
public class ValidaCPF {   private static final int[] pesoCPF = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2};   private static int calcularDigito(String str, int[] peso) {      int soma = 0;      for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {         digito = Integer.parseInt(str.substring(indice,indice+1));         soma += digito*peso[peso.length-str.length()+indice];      }      soma = 11 - soma % 11;      return soma > 9 ? 0 : soma;   }   public static boolean isValidCPF(String cpf) {      if ((cpf==null) || (cpf.length()!=11)) return false;      Integer digito1 = calcularDigito(cpf.substring(0,9), pesoCPF);      Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1, pesoCPF);      return cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());   }   public static void main(String[] args) {              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("622.673.390-05")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.960-08")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.100-08")); //inválido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("999.999.999-99")); //inválido   }}

O algoritmo usado para gerar o CPF tem uma "falha": CPFs com todos os dígitos iguais são considerados válidos, como se vê ao rodar o código anterior. Mas para a Receita são inválidos, logo você precisa desconsiderá-los "por fora". A função original não prevê isso, mas podemos acrescentar com isto:

 if ((cpf==null) || (cpf.length()!=11) ||
               cpf.equals("00000000000") || cpf.equals("11111111111") ||
               cpf.equals("22222222222") || cpf.equals("33333333333") ||
               cpf.equals("44444444444") || cpf.equals("55555555555") ||
               cpf.equals("66666666666") || cpf.equals("77777777777") ||
               cpf.equals("88888888888") || cpf.equals("99999999999")) return false;

Ou isto (fonte):

         java.util.regex.Pattern p = java.util.regex.Pattern.compile(cpf.charAt(0)+"{"+cpf.length()+"}");
         java.util.regex.Matcher m = p.matcher(cpf);
         if(m.find()) return false;

Eu vou manter a primeira opção por ser mais "clara". Não é fácil entender a segunda numa primeira olhada sem entender expressões regulares. O que esse trecho aparentemente faz é pegar o primeiro dígito do CPF, transformar em uma string do mesmo comprimento do CPF e verificar se essa string aparece no CPF. Por exemplo, se o primeiro dígito for '1', verifica se '11111111111' aparece na string.

E já que estamos aqui, por que não aproveitar para fazer a remoção de todos os caracteres não-numéricos, para que isso não precise ser feito antes de chamar a função? Em Java, basta uma linha:

cpf=cpf.replaceAll("\\D","");

Código: Java
123456789101112131415161718192021222324252627282930
public class ValidaCPF {   private static final int[] pesoCPF = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2};   private static int calcularDigito(String str, int[] peso) {      int soma = 0;      for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {         digito = Integer.parseInt(str.substring(indice,indice+1));         soma += digito*peso[peso.length-str.length()+indice];      }      soma = 11 - soma % 11;      return soma > 9 ? 0 : soma;   }   public static boolean isValidCPF(String cpf) {  cpf=cpf.replaceAll("\\D","");  if ((cpf==null) || (cpf.length()!=11) ||                                   cpf.equals("00000000000") || cpf.equals("11111111111") ||                                   cpf.equals("22222222222") || cpf.equals("33333333333") ||                                   cpf.equals("44444444444") || cpf.equals("55555555555") ||                                   cpf.equals("66666666666") || cpf.equals("77777777777") ||                                   cpf.equals("88888888888") || cpf.equals("99999999999")) return false;       Integer digito1 = calcularDigito(cpf.substring(0,9), pesoCPF);      Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1, pesoCPF);      return cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());   }   public static void main(String[] args) {              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("622.673.390-05")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.960-08")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.100-08")); //inválido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("999.999.999-99")); //inválido   }}

Como o peso adicionado a cada dígito varia linearmente (de 2 a 10 ao calcular o dígito 1 e de 2 a 11 ao calcular o dígito 2), o uso do array pode ser substituído por uma expressão matemática simples.:

 int valorPeso=str.length()+1-indice;

Eu admito que acho mais fácil entender o que está havendo quando é usado o array de pesos, mas se você preferir algo mais "enxuto":


Código: Java
1234567891011121314151617181920212223242526272829
public class ValidaCPF {   private static int calcularDigito(String str) {      int soma = 0;      for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {         digito = Integer.parseInt(str.substring(indice,indice+1));                 soma += digito*(str.length()+1-indice);      }      soma = 11 - soma % 11;      return soma > 9 ? 0 : soma;   }   public static boolean isValidCPF(String cpf) {  cpf=cpf.replaceAll("\\D","");  if ((cpf==null) || (cpf.length()!=11) ||                                   cpf.equals("00000000000") || cpf.equals("11111111111") ||                                   cpf.equals("22222222222") || cpf.equals("33333333333") ||                                   cpf.equals("44444444444") || cpf.equals("55555555555") ||                                   cpf.equals("66666666666") || cpf.equals("77777777777") ||                                   cpf.equals("88888888888") || cpf.equals("99999999999")) return false;       Integer digito1 = calcularDigito(cpf.substring(0,9));      Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1);      return cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());   }   public static void main(String[] args) {              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("622.673.390-05")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.960-08")); //válido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("871.790.100-08")); //inválido              System.out.printf("CPF Valido:%s \n", CNP.isValidCPF("999.999.999-99")); //inválido   }}

Eu não sou muito fã de usar .substring para obter apenas um caractere da string. Se você também não gosta, pode substituir a linha:

         digito = Integer.parseInt(str.substring(indice,indice+1));
por
         digito = Character.getNumericValue(str.charAt(indice));