Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

namio

Validação de CPF

Recommended Posts

Prezados colegas:

 

Segue abaixo código fonte de um novo tipo de dados que criei para a validação de cpfs.

 

Na verdade, trata-se de uma estrutura (struct), desenvolvida em C#, para tratar dados do tipo CPF. a melhor maneira de utilizá-la, é criar um novo projeto de classes e colocar o código abaixo dentro deste projeto; compilar, gerando assim uma dll e utilizar esta dll nos códigos de vocês; podendo este código ser VB, C# ou qualquer outro que possa interagir com a plataforma .NET. Em particular, testei em VB e C# e a estrutura se comportou perfeitamente.

 

using System;using System.Text.RegularExpressions;namespace Digitos{  /// <summary>  /// Representa um número de CPF  /// </summary>  [Serializable]  public struct Cpf : ICloneable  {    private static string _cpf;    /// <summary>    /// Retorna os dígitos verificadores do CPF    /// </summary>    /// <value>String</value>    public string Digitos    {      get      {        if (_cpf.Length == 0)          return string.Empty;        return _cpf.Substring(9, 2);      }    }    /// <summary>    /// Retorna os nove primeiros dígitos do CPF    /// </summary>    public string Raiz    {      get      {        if (_cpf.Length == 0)          return string.Empty;        return _cpf.Substring(0, 9);      }    }    /// <summary>    /// Inicializa uma nova instância da estrutura Cpf    /// </summary>    /// <param name="obj">Objeto do tipo string contendo o número do CPF.</param>    private Cpf(string obj)    {      _cpf = obj;    }    /// <summary>    /// Valida o CPF    /// </summary>    /// <returns>Retorna true se o CPF informado for um CPF válido. Caso contrário, retorna false</returns>    public bool IsValid()    {      if (_cpf.Trim().Length < 11)        return false;      int d1 = Cpf.CalculaDigitos(_cpf.Substring(0, 9));      int d2 = Cpf.CalculaDigitos(_cpf.Substring(1, 9));      d1 = ((d1 % 11) < 2) ? 0 : 11 - (d1 % 11);      d2 = ((d2 % 11) < 2) ? 0 : 11 - (d2 % 11);      string cpf = _cpf.Substring(0, 9) + d1.ToString() + d2.ToString();      return (_cpf.CompareTo(cpf) == 0);    }    /// <summary>    /// Retorna um CPF com os dígitos verificadores corrigidos, a partir de um CPF inválido, passado por cpf.    /// </summary>    /// <param name="cpf">CPF cujos dígitos deverão ser calculados</param>    /// <returns>Um CPF com os dígitos verificadores corrigidos</returns>    public static Cpf Fix(Cpf cpf)    {      if (cpf.ToString().Length == 0)        throw new ArgumentException("cpf");      if (! cpf.IsValid())      {        string raiz = cpf.Raiz;        int d1 = Cpf.CalculaDigitos(raiz);        d1 = ((d1 % 11) < 2) ? 0 : 11 - (d1 % 11);        string resultado = raiz + d1.ToString();        int d2 = Cpf.CalculaDigitos(resultado.Substring(1));        d2 = ((d2 % 11) < 2) ? 0 : 11 - (d2 % 11);        return resultado + d2.ToString();      }      return cpf;    }    /// <summary>    /// Método recursivo utilizado pelo método IsValid() para calculo dos dígitos verificadores    /// <see cref="IsValid"/>    /// </summary>    /// <param name="raiz">    /// String de nove posições, contendo os nove dígitos necessários para o cálculo de cada um    /// dos dois dígitos verificadores do CPF    /// </param>    /// <returns>Objeto do tipo Int32, contendo o valor calculado para raiz</returns>    private static int CalculaDigitos(string raiz)    {      if (raiz.Length == 1)        return (int.Parse(raiz) * 2);      return (int.Parse(raiz.Substring(0, 1)) * (raiz.Length + 1) + CalculaDigitos(raiz.Substring(1)));    }    /// <summary>    /// Converte um valor string em CPF    /// </summary>    /// <param name="valor">string contendo o valor a ser convertido em CPF</param>    /// <returns>Um objeto do tipo Cpf a partir de valor</returns>    public static Cpf Parse(string valor)    {      Cpf temp = valor;      return temp;    }    /// <summary>    /// Representa o valor desta instância convertido em uma string com o seguinte formato:    /// xxx.xxx.xxx-xx    /// </summary>    /// <returns>Uma string representando o valor desta instância formatado com pontos e hífen</returns>    public string Format()    {      return this.Format(Convert.ToChar("."), Convert.ToChar("-"));    }    /// <summary>    /// Representa o valor desta instância convertido em uma string, formatado com os separadores    /// especificados.    /// </summary>    /// <param name="sep1">    /// Caractere utilizado para separar os nove primeiros dígitos do CPF em grupos de três dígitos    /// </param>    /// <param name="sep2">    /// Caractere utilizado para separar os três grupos de três dígitos do CPF dos dígitos verificadores    /// </param>    /// <returns>    /// Uma string representando o valor desta instância formatado com os separadores indicados    /// </returns>    /// <example>    /// <code>    /// using System;    /// using System.Globalization;    /// public class MainClass    /// {    ///   public static void Main(string[] args)    ///   {    ///     Cpf valor = "34587647588";    ///         ///     Console.WriteLine(valor.Format());    ///     Console.WriteLine(valor.Format(Convert.ToChar(" "), Convert.ToChar("/"));    ///     /** Output.    ///      *    ///      * 345.876.475-88    ///      * 345 876 475/88    ///     */    ///   }    /// }    /// </code>    /// </example>    public string Format(char sep1, char sep2)    {      if (_cpf.Trim().Length == 0)        return _cpf;      string padrao = @"^(\d{3})(\d{3})(\d{3})(\d{2})";      string cpf = string.Empty;      Regex r = new Regex(padrao);      Match m = r.Match(_cpf);      return m.Groups[1].Value + sep1 + m.Groups[2].Value + sep1 + m.Groups[3].Value + sep2 +              m.Groups[4].Value;    }    /// <summary>    /// Retorna o valor desta instância convertido para string    /// </summary>    /// <returns>Uma string representando o valor desta instância</returns>    public override string ToString()    {      return _cpf;    }    /// <summary>    /// Inicializa uma nova instância da estrutura Cpf a partir de uma string    /// </summary>    /// <param name="valor">Uma string contendo um número válido para CPF</param>    /// <returns>Uma nova instância da estrutura Cpf</returns>    /// <remarks>    /// valor deve conter um número com no mínimo 11 dígitos. Se valor contiver mais que nove dígitos,    /// serão utilizados somente os nove primeiros dígitos.    /// <para>    /// Se valor contiver um número de CPF formatado (i.e. 234.567.456-99), os caracteres de formatação    /// serão descartados. Somente os caracteres numéricos serão mantidos.    /// </para>    /// </remarks>    /// <exception cref="System.InvalidCastException">    /// Se valor contiver menos que nove caracteres numéricos ou se algum dos caracteres, com exceção dos    /// caracteres separadores (existentes em suas devidas posições), não for um número válido    /// </exception>    /// <example>    /// <code>Cpf cpf = "385.456.432.67"; // Ok</code>    /// <code>Cpf cpf = "38545643267";    // Ok</code>    /// <code>Cpf cpf = "234$564.567*77;  // Ok</code>    /// <code>Cpf cpf = "324a456a234b55;  // erro</code>    /// <code>Cpf cpf = "123.a45.456-99   // erro</code>    /// </example>    public static implicit operator Cpf(string valor)    {      string padrao = @"^(\d{3})\W?(\d{3})\W?(\d{3})\W?(\d{2})";      Regex r = new Regex(padrao);      Match m = r.Match(valor);      if (!m.Success)        throw new InvalidCastException("valor não é um número de CPF válido");       return new Cpf(m.Groups[1].Value + m.Groups[2].Value + m.Groups[3].Value + m.Groups[4].Value);    }    /// <summary>    /// Retorna o valor de cpf convertido para string    /// </summary>    /// <param name="cpf">CPF a ser representado em string</param>    /// <returns></returns>    public static implicit operator string(Cpf cpf)    {      return _cpf;    }    /// <summary>    /// Cria uma nova instância de Cpf com o mesmo valor de cpf    /// </summary>    /// <param name="cpf">O CPF a ser copiado</param>    /// <returns>Um novo CPF com o mesmo valor de cpf</returns>    public static Cpf Copy(Cpf cpf)    {      int tamanho = cpf.ToString().Length;      if (tamanho == 0)        throw new ArgumentNullException("cpf");      return new Cpf(cpf.ToString());    }    #region ICloneable Members    /// <summary>    /// Retorna uma referência desta instância de Cpf    /// </summary>    /// <returns>Esta instância de Cpf</returns>    /// <remarks>    /// O valor retornado não é uma cópia independente desta instância. É simplesmente uma outra visão    /// do mesmo dado. Utilize o método Copy para criar um objeto Cpf separado, com o mesmo    /// valor desta instância.    /// </remarks>    public object Clone()    {      return this;    }    #endregion  }}
Um exemplo da utilização desta estrutura seria, em C#:

 

   private void Button1_Click(object sender, System.EventArgs e)    {      PLibrary.Cpf cpf = this.TextBox1.Text;      if (!cpf.IsValid())      {        this.Label2.Text = string.Format("CPF Inválido<br>Propriedades do CPF:<br>" +          "Raiz: {0}<br>Dígitos: {1}<br>" +          "CPF sem formatação: {2}<br>" +          "CPF com formatação padrão: {3}<br>" +          "CPF com formatação xxx-xxx-xxx/xx: {4}<br>",          cpf.Raiz, cpf.Digitos, cpf, cpf.Format(),          cpf.Format(Convert.ToChar("-"), Convert.ToChar("/")));        this.Button2.Visible = true;      }      else      {        this.Label2.Text = string.Format("CPF Válido<br>Propriedades do CPF:<br>" +          "Raiz: {0}<br>Dígitos: {1}<br>" +          "CPF sem formatação: {2}<br>" +          "CPF com formatação padrão: {3}<br>" +          "CPF com formatação xxx-xxx-xxx/xx: {4}<br>",          cpf.Raiz, cpf.Digitos, cpf, cpf.Format(),          cpf.Format(Convert.ToChar("-"), Convert.ToChar("/")));        this.Button2.Visible = false;      }    }
Como vocês podem ver, este é o código de resposta ao evento click do botão Button1 de um formulário. Ele pega o texto digitado dentro do textbox TextBox1, converte-o para a variável cpf, do tipo CPF e testa a sua validade através do método IsValid().

 

O resto do código serve simplesmente para ilustrar as demais propriedades e métodos da estrutura. Existe ainda o método Fix(), que corrige um cpf invélido.

 

Ainda falta, nesta estrutura a sobrescrição dos operadores de igualdade e diferença; permitindo, assim, comparar dois cpfs, da seguinte maneira:

 

if (cpf1 == cpf2){    ...}
ou

 

if (cpf1 == '345.567.765-99'){    ...}
Mas isso deixo de exercício para vocês http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Abaixo está um exemplo de utilização da estrutura em VB:

 

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click    Dim cpf As PLibrary.Cpf    cpf = PLibrary.Cpf.Parse(Me.TextBox1.Text)    If (Not cpf.IsValid()) Then      Me.Label2.Text = String.Format("CPF Inválido<br>Propriedades do CPF:<br>" & _          "Raiz: {0}<br>Dígitos: {1}<br>" & _          "CPF sem formatação: {2}<br>" & _          "CPF com formatação padrão: {3}<br>" & _          "CPF com formatação xxx-xxx-xxx/xx: {4}<br>", _          cpf.Raiz, cpf.Digitos, cpf, cpf.Format(), _          cpf.Format(Convert.ToChar("-"), Convert.ToChar("/")))      Me.Button2.Visible = True    Else      Me.Label2.Text = String.Format("CPF Válido<br>Propriedades do CPF:<br>" & _          "Raiz: {0}<br>Dígitos: {1}<br>" & _          "CPF sem formatação: {2}<br>" & _          "CPF com formatação padrão: {3}<br>" & _          "CPF com formatação xxx-xxx-xxx/xx: {4}<br>", _          cpf.Raiz, cpf.Digitos, cpf, cpf.Format(), _          cpf.Format(Convert.ToChar("-"), Convert.ToChar("/")))      Me.Button2.Visible = False    End If  End Sub
Um forte abraço a todos,

 

Nâmio Evangelista Cavalcante

Compartilhar este post


Link para o post
Compartilhar em outros sites

muito bacana Nâmio... Parabéns...depois irei estudar esse código... B) Att,Carlos

Compartilhar este post


Link para o post
Compartilhar em outros sites

Beleza, Carlos.Qualquer dúvida sinta-se a vontade para perguntar.estou implementando a dll, incluindo uma Interface para o desenvolvimento de estruturas para cálculo de dígitos e mais outras estruturas:Uma para cálculo do CNPJ e outra para cálculo da Inscrição Estadual.Se você tiver alguma sugestão para incluir na dll, me comunica.Depois posso passar os fontes para você ou, se desejar, a dll já compilada.Um forte abraço,Nâmio Evangelista Cavalcante.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.