DarkByte
Moderator
 Inregistrat: acum 19 ani
Postari: 10
|
|
Datorita feedback-ului super multumitor primit la primul meu tutorial (la ora cand scriu asta doar Geo postase raspuns ), ma apuc de al doilea tutorial.
Asa ca, hai sa vedem cum putem verifica un CNP (cod numeric personal) in Delphi. Orice CNP (tineti cont ca doar in Romania exista CNP, din cate stiu ) e format din 13 cifre (yeah... i'm feeling lucky ).
SAALLZZOONNNC unde: S= sex (1=barbat, 2=femeie, 3=barbat nascut inainte de 1900, 4=femeie before 1900, 5=barbat dupa 2000, 6=femeie dupa 2000) AA= anul (2 cifre) LL= luna ZZ= ziua OO= orasul NNN= numar din registrul Starii Civile (posibil, nu e sigur) C= cifra de control (MD5-ul )
Ok, acum ca stim astea, sa vedem care sunt conditiile ca un CNP sa fie valid. 1. Trebuie sa aiba exact 13 cifre 2. Luna nu poate avea o valoare mai mare de 12 3. Ziua nu poate avea o valoare mai mare de 31 (depinzand si de luna) 4. Valoarea orasului nu poate fi 0 si nici mai mare de 41 5. Cifra de control Formula de calcul al cifrei de control se bazeaza pe un numar 279146358279, iar cifra se calculeaza astfel: Primele 12 cifre din CNP se inmultesc fiecare cu cifra corespondenta din numarul de mai sus, iar aceste produse sunt adunate. Suma rezultata se imparte (intreg) la 11, din care impartire ne intereseaza doar restul. Sunt doua cazuri: a) Restul este intre 0 si 9, caz in care e cifra de control b) Restul este 10, caz in care cifra de control e 1
Aici e lista judetelor, in ordinea necesara pentru validarea unui CNP  Lista judetelor (albabetic)
01 Alba 02 Arad 03 Arges 04 Bacau 05 Bihor 06 Bistrita-Nasaud 07 Botosani 08 Braila 09 Brasov 10 Buzau 11 Caras Severin 12 Calarasi 13 Cluj 14 Constanta 15 Covasna 16 Dambovita 17 Dolj 18 Galati 19 Giurgiu 20 Gorj 21 Harghita 22 Hunedoara 23 Ialomita 24 Iasi 25 Ilfov 26 Maramures 27 Mehedinti 28 Mures 29 Neamt 30 Olt 31 Prahova 32 Satu Mare 33 Salaj 34 Sibiu 35 Suceava 36 Teleorman 37 Timis 38 Tulcea 39 Vaslui 40 Vâlcea 41 Vrancea
Bun, de ajuns cu teoria, un pic de practica...
Porniti Delphi, bla bla... Acum va zic de la inceput: faceti un director nou pe undeva (INTERZIS in Recycle Bin ), si salvati programul (care momentan face un NIMIC mare ).
Puneti pe forma un Edit, un Label si un Button (vezi tutorialul precedent, daca e ceva in neregula cu astea ) Selectati labelul, setati proprietatea Caption (in Object Inspector) sa fie "Introduceti CNP pentru verificare:" (sau orice altceva, dar sa fie inteligibil ). Selectati butonul, Caption sa fie egal cu "Verificare CNP" (orice, vezi regula de mai sus). Cautati si proprietatea Default a butonului si setati-o pe True. Asta va face ca programul, atunci cand este apasat Enter, sa considere ca s-a vrut apasarea butonului (este default). Selectati casuta text, din proprietatea Text stergeti tot. Pe langa astea, care deja (teoretic) va sunt cunoscute, vom adauga un ComboBox (o casuta derulanta , in care vom afisa erorile sau daca este valid CNP-ul. In acest moment programul ar trebui sa semene (macar de departe) cu asta
Bun, sa incepem cu inceputul. Prima oara trebuie sa verificam daca are lungimea de 13 cifre si sa fie cifre. Verificarea daca un sir de caractere are lungimea 13 (tineti minte ca Edit tine doar siruri de caractere, nu cifre) e foarte simpla:
Code:
If Length(sir) = 13 Then ... |
Functia Length de mai sus este o functie care accepta un singur parametru de tip string (sir de caracter) si returneaza lungimea lui in caractere. Tipul de date string are o lungime maxima de 255 de caractere si este stocat in 256 de octeti. Pe prima pozitie a sirului este lungimea sirului, apoi urmeaza caracterele componente ale acestuia. Deci, de fapt, Length ne returneaza codul ASCII al primului caracter (care nu este folosit la nimic altceva).
Pentru a verifica daca sirul contine (sau nu) doar cifre, trebuie sa-l parcurgem, caracter cu caracter, si sa testam fiecare caracter. Pentru asta avem nevoie de o bucla (structura repetitiva) care sa ia, pe rand, fiecare caracter din sir. Sintaxa FOR For contor := valoare_initiala To valoare_finala Do comanda; sau For contor := valoare_finala DownTo valoare_initiala Do comanda; Structura repetitiva FOR are 2 modalitati de folosire, prezentate mai sus. Prima are un contor crescator, cealalta are un contor descrescator. De retinut ca NU este permisa (desi uneori compilatorul nu genereaza eroare) modificarea valorii contorului buclei.
Stiind acestea, sa vedem codul unei functii care verifica daca un sir contine numai cifre sau nu:
Code:
function OnlyDigits(s:string):boolean;
var i:byte;
d:boolean;
begin
d:=true;
for i:=1 to length(s) do
if not (s[i] in ['0'..'9']) then d:=false;
result:=d;
end; |
Tipul de date Boolean este tipul logic. Variabilele de acest tip pot lua doar valori True sau False. Denumit astfel dupa George Boole, inventatorul notiunii. Practic, aceasta functie foloseste doua variabile, una intreaga si una logica, pentru a parcurge sirul, iar la primul caracter care se dovedeste a NU fi cifra, se muta variabila logica pe False, adica sirul NU contine DOAR cifre. Rezultatul functiei este tocmai aceasta variabila logica (sirul S contine doar cifre ? True / False). Acum, avand aceste lucruri terminate, sa vedem prima varianta a verificarii, de fapt ce face butonul Verifica cand e apasat. Tineti cont ca momentan verifica doar lungimea sirului si faptul ca aceste contine doar cifre.
Code:
function OnlyDigits(s:string):boolean;
var i:byte;
d:boolean;
begin
d:=true;
for i:=1 to length(s) do
if not (s[i] in ['0'..'9']) then d:=false;
result:=d;
end;
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
begin
ComboBox1.Items.Clear;
s:=Edit1.Text;
if (Length(s)=13) and OnlyDigits(s)
Then Begin
ComboBox1.Items.Add('CNP Valid');
Edit1.Color:=clWhite;
End
Else Begin
If not OnlyDigits(s) then ComboBox1.Items.Add('CNP trebuie sa contina doar cifre');
if not (Length(s)=13) then ComboBox1.Items.Add('CNP trebuie sa contina 13 cifre');
Edit1.Color:=clRed;
End;
ComboBox1.ItemIndex:=0;
end; |
Atentie: functia OnlyDigits va trebui scrisa complet (sau direct copiata) in codul sursa al programului. procedure TForm1.Button1Click va aparea in momentul in care dati dublu-click pe buton si veti adauga doar variabilele si codul. Dupa cum vedeti in codul sursa al butonului, in caz de CNP eronat, vom colora casuta text Edit1 in rosu, pe care il refacem in alb cand se va introduce un CNP corect.
Acum sa verificam ca valoarea lunii sa fie corecta. Pentru asta, vom lua cifrele 4 si 5 impreuna si vom verifica sa fie mai mare decat 0 si mai mica sau egala cu 12. Simplu, nu ? -->
Code:
function IsMonthOk(s:String):Boolean;
var luna:byte;
begin
luna := StrToInt (Copy(s, 4, 2));
IsMonthOk := (luna <= 12) and (luna <> 0);
end; |
Intalnim din nou tipul logic, dar de data asta intalnim si tipul Byte. Este tot un tip intreg (ca si integer si longint din tutorialul trecut), dar este strict pozitiv. Plaja lui de valori este intre 0 si 255 ($00 si $FF). Ce se intampla in functie ? Copiem (cu functia Copy) din sirul S, de la pozitia 4, doua caractere, adica al 4-lea si al 5-lea caracter (sper ca ma urmariti pe functie). Rezultatul functiei Copy este direct parametru al functiei StrToInt, care trannsforma cele 2 caractere intr-un numar. Alta diferenta (intentionata) este modalitatea de returnare a rezultatului functiei. Avand in vedere ca rezultatul functiei poate fi doar True sau False, e clar ca e posibil ca rezultatul functiei sa fie o conditie (luna mai mica sau egala cu 12 SI luna sa fie mai mare ca 0).
Bun, am terminat si cu luna, verificarea zilei este asemanatoare:
Code:
function IsDayOk(s:String):Boolean;
var ziua:byte;
begin
ziua := StrToInt (Copy(s, 6, 2));
IsDayOk := (ziua <= 31) and (ziua <> 0);
end; |
Singurele diferente sunt: - am luat caracterele 6 si 7 - am verificat sa aiba valoarea maxim 31
Verificarea orasului este (din nou) identica, acum stiti ce trebuie modificat, deci asta o faceti singuri si-i veti da numele IsTownOk. Caracterele sunt (ca sa nu va chinuiti cu numaratul ) 8 si 9.
Acum, verificarea cifrei de control. Poata ca pare greu, dar sincer... nu e. Imi spuneti voi parerea voastra, dar acum sa continuam. Nu cred ca are rost sa trec din nou prin explicatia care am dat-o la inceput, asa ca va voi prezenta direct codul sursa:
Code:
function IsControlDigitOk(s:string):Boolean;
const c : string = '279146358279';
var suma, rest : integer;
i : byte;
begin
suma := 0;
For i:=1 to 12 do suma := suma + StrToInt(s[i])*StrToInt(c[i]);
rest := suma mod 11;
if rest = 10 then rest := 1;
IsControlDigitOk := (IntToStr(rest) = s[13]);
end; |
Aici am definit un sir de caracter (cel pentru verificare) in constanta (care se poate modifica, btw ) C, apoi am facut suma produselor, am calculat restul, care, daca a fost 10, i-am pus valoarea 1. Daca restul acesta este egal cu ultima cifra din CNP (a 13-a) atunci CNP-ul este corect. In mod normal, doar aceasta functie ar fi de ajuns... dar am sa va las pe voi sa va ganditi de ce nu e de ajuns 
Acum, ajunsi la sfarsitul tutorialului, daca ati adaugat toate functiile si conditiile in codul sursa al butonului, ar trebui sa aveti un verificator de CNP functional.
Pentru ca sa fiu sigur ca m-ati urmarit , aveti aici sursa cu executabil cu tot 
Observatii: v-am dat lista oraselor, ati putea modifica programul in asa fel incat, dupa ce a fost introdus un CNP corect, sa afiseze data nasterii (inclusiv anul cu 4 cifre !) si numele orasului. Nu e prea greu, stiti voi e banal 
In continuare, Practice makes perfect 
_______________________________________ Portal SkullBox SkullBox Forum IP Finder and web browser details revealer
|
|