[C#] Validarea și procesarea CNP-urilor

CNP = cod numeric personal. (la acest Link e descris și formatul)

Cea mai ușoară metodă este să verific că:
1. șirul de caractere are lungimea exactă de 13;
2. fiecare caracter este o cifră;
3. cifra de control este corectă (secțiunea C);
4. secțiunea S este validă;
5. secțiunea AA;
6. secțiunea LL;
7. secțiunea ZZ;
8. secțiunea JJ;
9. secțiunea NNN (e mai puțin probabil să fie invalidă, deci este verificată la sfârșit).

Sumar

În designer realizez un simplu Form cu un TextBox numit tbCNP și un buton numit btnAnalizeaza. Codul din spate este modularizat: o clasă AnalizaCNP cu câmpurile publice
int S, AA, AAAA, LL, ZZ, JJ, NNN, CDat, CRecalculat (până aici au numele similare titlurilor de secțiune din articolul Wikipedia); string CNP, string Sex, Nascut, Luna, Judet; bool CEsteCorect, CNPValid. Clasa conține și metodele NumeLunaDinNumar, NumeJudetDinCodJudet și ToString (cea din urmă e supraîncărcată). Pentru validarea unui CNP sau afișarea informațiilor despre el, sunt necesare la final doar 2 rânduri de cod. Codul din spate mai conține rânduri care fac butonul acționabil cu tasta Enter/Return și focalizarea inițială a TextBox-ului la pornire (cursorul de introducere de text să fie inițial în TextBox).

Sub cod sunt capturi de ecran.

Codul

using System;
using System.Windows.Forms;

namespace cs_validare_cnp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Campurile CDat, CRecalculat si CEsteCorect se refera
        /// la cifra de control.
        /// </summary>
        public class AnalizaCNP
        {
            public string CNP;
            public int S, AA, AAAA, LL, ZZ, JJ, NNN, CDat, CRecalculat;
            public string Sex, Nascut, Luna, Judet;
            public bool CEsteCorect, CNPValid;

            public string NumeLunaDinNumar(int luna)
            {
                string s;
                switch (luna)
                {
                    case 1:
                        s = "ianuarie";
                        break;
                    case 2:
                        s = "februarie";
                        break;
                    case 3:
                        s = "martie";
                        break;
                    case 4:
                        s = "aprilie";
                        break;
                    case 5:
                        s = "mai";
                        break;
                    case 6:
                        s = "iunie";
                        break;
                    case 7:
                        s = "iulie";
                        break;
                    case 8:
                        s = "august";
                        break;
                    case 9:
                        s = "septembrie";
                        break;
                    case 10:
                        s = "octombrie";
                        break;
                    case 11:
                        s = "noiembrie";
                        break;
                    case 12:
                        s = "decembrie";
                        break;
                    default:
                        s = "luna necunoscuta";
                        break;
                }
                return s;
            }

            public string NumeJudetDinCodJudet(int codInt)
            {
                string cod = codInt >= 10 ?
                    codInt.ToString() :
                    $"0{codInt}";
                // Copy-Paste la tabelul din pagina Wikipedia CNP
                string coduri = @"01  Alba
02  Arad
03  Argeș
04  Bacău
05  Bihor
06  Bistrița - Năsăud
07  Botoșani
08  Brașov
09  Brăila
10  Buzău
11  Caraș - Severin
12  Cluj
13  Constanța
14  Covasna
15  Dâmbovița
16  Dolj
17  Galați
18  Gorj
19  Harghita
20  Hunedoara
21  Ialomița
22  Iași
23  Ilfov
24  Maramureș
25  Mehedinți
26  Mureș
27  Neamț
28  Olt
29  Prahova
30  Satu Mare
31  Sălaj
32  Sibiu
33  Suceava
34  Teleorman
35  Timiș
36  Tulcea
37  Vaslui
38  Vâlcea
39  Vrancea
40  București
41  București - Sector 1
42  București - Sector 2
43  București - Sector 3
44  București - Sector 4
45  București - Sector 5
46  București - Sector 6
51  Călărași
52  Giurgiu";
                try
                {
                    string judet = coduri.Split('\n')[codInt - 1]
                        .Split(new string[] { "  " },
                            StringSplitOptions.RemoveEmptyEntries)[1].Trim();
                    return judet;
                }
                catch (Exception)
                {
                    return "";
                }
            }

            public override string ToString()
            {
                AnalizaCNP a = this;

                return a.CNPValid ?
                    $@"CNP: {a.CNP}
S: {a.S} AA/AAAA: {a.AA}/{a.AAAA} LL: {a.LL} ZZ: {a.ZZ} JJ: {a.JJ} NNN: {a.NNN} C dat: {a.CDat}, C recalculat: {a.CRecalculat}
Sex: {a.Sex}
Nascut: {a.Nascut}
Luna: {a.Luna}
Judet: {a.Judet}
C este corect: {a.CEsteCorect}" :
"CNP invalid.";
            }

            /// <summary>
            /// CNP-ul dat poate fi inconjurat de spatii,
            /// acestea vor fi sterse.
            /// </summary>
            /// <param name="cnp"></param>
            public AnalizaCNP(string cnp)
            {
                CNP = cnp.Trim();

                // lungime corecta
                CNPValid = CNP.Length == 13;
                if (!CNPValid)
                {
                    return;
                }

                try
                {
                    CDat = Convert.ToInt32(cnp.Substring(12), 10);

                    string ctrl = "279146358279";
                    int suma = 0;
                    for (int i = 0; i < 12; ++i)
                    {
                        int cifra1 = cnp[i] - '0';
                        int cifra2 = ctrl[i] - '0';
                        int produs = cifra1 * cifra2;
                        suma += produs;
                    }
                    if (suma % 11 == 10)
                    {
                        CRecalculat = 1;
                    }
                    else
                    {
                        CRecalculat = suma % 11;
                    }

                    CEsteCorect = CRecalculat == CDat;
                    if (!CEsteCorect)
                    {
                        CNPValid = false;
                        return;
                    }

                    S = int.Parse(cnp.Substring(0, 1));

                    if (S == 1 || S == 3 ||
                        S == 5 || S == 7)
                    {
                        Sex = "masculin";
                    }
                    else
                    {
                        Sex = "feminin";
                    }

                    if (S == 1 || S == 2)
                    {
                        Nascut = "intre 1 ianuarie 1900 si 31 decembrie 1999";
                    }
                    else if (S == 3 || S == 4)
                    {
                        Nascut = "intre 1 ianuarie 1800 si 31 decembrie 1899";
                    }
                    else if (S == 5 || S == 6)
                    {
                        Nascut = "intre 1 ianuarie 2000 si 31 decembrie 2099";
                    }
                    else if (S == 7 || S == 8)
                    {
                        Nascut = "persoana straina rezidenta in Romania";
                    }
                    else
                    {
                        CNPValid = false;
                        return;
                    }

                    AA = int.Parse(cnp.Substring(1, 2));
                    AAAA = AA;

                    if (S == 1 || S == 2)
                        AAAA += 1900;
                    else if (S == 3 || S == 4)
                        AAAA += 1800;
                    else // 5 sau 6 sau rezidenti (7 sau 8)
                        AAAA += 2000;

                    LL = Convert.ToInt32(cnp.Substring(3, 2));
                    if (LL > 12 || LL < 1)
                    {
                        CNPValid = false;
                        return;
                    }
                    Luna = NumeLunaDinNumar(LL);

                    ZZ = Convert.ToInt32(cnp.Substring(5, 2), 10);
                    if (DateTime.DaysInMonth(AAAA, LL) < ZZ)
                    {
                        CNPValid = false;
                        return;
                    }

                    JJ = Convert.ToInt32(cnp.Substring(7, 2), 10);
                    Judet = NumeJudetDinCodJudet(JJ);

                    NNN = Convert.ToInt32(cnp.Substring(9, 3), 10);
                }
                catch (Exception)
                {
                    CNPValid = false;
                }
            }
        }

        private void btnAnalizeaza_Click(object sender, EventArgs e)
        {
            AnalizaCNP a = new AnalizaCNP(tbCNP.Text);
            MessageBox.Show(a.ToString());
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ActiveControl = tbCNP;
        }

        private void tbCNP_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                btnAnalizeaza.PerformClick();
            }
        }
    }
}

Capturi de ecran


 O parte din codul din spate:







 La rularea programului (CNP aleator: 6750821105927):





Documentație oficială

Dau link-uri la documentația oficială Microsoft pentru metodele folosite:

- clasa controlului TextBox;
- clasa controlului Form;
- metoda supraîncărcată Object.ToString;
- metoda String.Split și enumerarea StringSplitOptions;
- string-uri textuale (cu @, en. „verbatim”);
- string-uri interpolate (cu $);
- metoda int.Parse;
- metoda Convert.ToInt32;
- proprietatea ContainerControl.ActiveControl;
- metoda MessageBox.Show;
- metoda Button.PerformClick;
- metoda DateTime.DaysInMonth.

Niciun comentariu:

Trimiteți un comentariu