Ocena użytkownikóww: ***** / 6
Nadesłany przez Tomasz Lubiński, 02 marca 2008 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
Dowod osobisty - Delphi/dowod.dpr:
// www.algorytm.org
// walidacja numeru dowodu osobistego
// Tomasz Lubinski (c) 2008
program dowod;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
letterValues: array[0..35] of Char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z');
function getLetterValue(letter: Char): Integer;
var
i: Integer;
begin
result := -1;
for i:=low(letterValues) to high(letterValues) do
if letter = letterValues[i] then
begin
result := i;
break;
end;
end;
var
id: String;
i, checkSum: Integer;
begin
//pobierz numer dowodu osobistego
writeln('Podaj numer dowodu osobistego (bez spacji, myslinkow, itp)');
readln(id);
//sprawdz dlugosc podanego numeru
if length(id) <> 9 then
begin
writeln('Nieprawidlowa dlugosc numeru');
exit;
end;
//sprawdz czy podano 3 litery a nastepnie 6 cyfr
for i:=1 to 3 do
if getLetterValue(id[i]) < 10 then
begin
writeln('Nieprawidlowa seria dowodu');
exit;
end;
for i:=4 to 9 do
if (getLetterValue(id[i]) < 0) or (getLetterValue(id[i]) > 9) then
begin
writeln('Nieprawidlowy numer dowodu');
exit;
end;
//sprawdz cyfre controlna
checkSum := 7 * getLetterValue(id[1]);
checkSum := checkSum + 3 * getLetterValue(id[2]);
checkSum := checkSum + 1 * getLetterValue(id[3]);
checkSum := checkSum + 7 * getLetterValue(id[5]);
checkSum := checkSum + 3 * getLetterValue(id[6]);
checkSum := checkSum + 1 * getLetterValue(id[7]);
checkSum := checkSum + 7 * getLetterValue(id[8]);
checkSum := checkSum + 3 * getLetterValue(id[9]);
checkSum := checkSum mod 10;
if checkSum <> getLetterValue(id[4]) then
writeln('Podany numer dowodu jest niepoprawny')
else
writeln('Podany numer dowodu jest poprawny');
end.
if letter in ['A'..'Z'] then [...]
i potem wystarczy odjąć 55 (czy coś koło tego) od kodu ascii
Suma kontrolna liczona również bez sensu, można to zrobić w pętli, a wagi trzymać w tablicy.
Waga znaku nr 4 powinna wynosić 9, a tutaj nie jest sprawdzana.
Generalnie bardzo słaby kod i źle zapisany algorytm.
letVal: array[1..36] of Char =
'0123456789ABCDEFGHI JKLMNOPQRSTUVWX YZ';
wagi: array[1..9] of integer = (7,3,1,9,7,3,1,7,3);
function getLetVal(znak: Char): Integer;
begin
getLetVal := pos(UpCase(znak ),letVal) - 1;
end;
var id: String;
i, suma: Integer;
begin
writeln('Podaj numer dowodu osobistego');
readln(id);
if length(id)<>9 then
begin
writeln('bledna dlugosc'); exit;
end;
for i:=1 to 3 do
if (getLetVal(id)<10)
OR (UpCase(id)='O') OR (UpCase(id)='Q') then
begin
writeln('bledna seria'); exit;
end;
for i:=4 to 9 do
if (getLetVal(id)<0) or (getLetVal(id)>9) then
begin
writeln('bledy w numerze'); exit;
end;
suma := 0;
for i:=1 to 9 do
suma := suma + wagi*getLetVal( id);
if (suma mod 10 <> 0)
then writeln('bledny')
else writeln('poprawny');
end.
Z punktu widzenia sprawdzania poprawności numeru nie ma znaczenia obliczanie cyfry kontrolnej - wystarczy, że suma iloczynów kończy się zerem.
Function czySumaOk(nrdow :string);
const Litery:string[36]='ABCDEFGHIJKLMNO PQRSTUVWXYZ0123456789';
wagiLit:Array[1..36] of byte=(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 ,29,30,31,32,33,34,35,
0,1,2,3,4,5,6,7,8,9);
waginrdow:array [1..9] of byte=(7,3,1,7,3,1,7,3,1);
var nrdokumOK:Boole an;
sumakontr:integ er;
begin
sumakontr:=0;
for i :=1 to 9 do
sumakontr:=sumakontr+byte( wagiLit[Pos(nrd okum,Litery)])* byte(waginrdow) ;
if StrToIntDef(cop y(linia1,10,1),-1)=(sumakontr mod 10) then
nrdokumOK:=True
else
nrdokumOK:=False;
end;