Avatar billede skindbeni Nybegynder
17. december 2006 - 15:13 Der er 22 kommentarer og
1 løsning

CPR-validering og angivelse af alder

Hej.

Kender i til, om der ligger noget gratis kodeværk på nettet, der validerer et dansk CPR-nr og samtidig kan angive alderen.
Avatar billede kroning Nybegynder
17. december 2006 - 15:17 #1
Jeg bruger denne til at checke om cpr nr. er ok:

function testcprnummerok(cprnummer : string) : byte;
var
    cpr            : string;
    nr            : array(.1..10.) of byte;
    x                : byte;
    verdi        : word;
    tal            : byte;
    code        : integer;
begin
    testcprnummerok:=1;
    cpr:=cleancprnummer(cprnummer);

    if length(cpr)<>10 then
        exit;

    for x:=1 to 10 do
    begin
        val(cpr(.x.),tal,code);
        nr(.x.):=tal;
    end;
    verdi:=4*nr(.1.)+3*nr(.2.)+2*nr(.3.)+7*nr(.4.)+6*nr(.5.)+5*nr(.6.)+
          4*nr(.7.)+3*nr(.8.)+2*nr(.9.)+nr(.10.);

    if verdi mod 11<>0 then
      testcprnummerok:=2
    else
        testcprnummerok:=3;
end;
Avatar billede martinlind Nybegynder
17. december 2006 - 15:20 #2
Kontrolcifferberegning ved brug af modulus 11
CPR-kontoret  Dato: 14/06/2006
Beregning af kontrolciffer

Ni første tal 0
7
0
7
6
1
4
2
8

gange med x
x
x
x
x
x
x
x
x

hver deres værdi 4
3
2
7
6
5
4
3
2

giver 00+ 21+ 00+ 49+ 36+ 05+ 16+ 06+ 16


sammenlagt giver disse tal 149

149 delt med 11 giver 13 med en rest på 6

Kontrolcifret beregnes ved at trække resten 6 fra 11.

Kontrolcifret bliver i dette tilfælde 5 og det 10-cifrede nummer bliver 07 07 61-4285.

Hvis resten bliver 1 skulle kontrolcifret efter metoden være 10. Da 2-cifrede kontroltal ikke accepteres, kan kontrolcifrene i sådanne tilfælde ikke benyttes.

Kontrolberegning af et nummer med kontrolciffer

De 10 tal 0 7 0 7 6 1 4 2 8 5
ganget med x x x x x x x x x x
hver deres værdi 4 3 2 7 6 5 4 3 2 1
giver 00+ 21+ 00+ 49+ 36+ 05+ 16+ 06+ 16+ 05


sammenlagt giver disse tal 154

154 delt med 11 giver 14 og ingen rest.

Når 11 går op i 154 og der derved ingen rest findes, er kontrolberegningen i orden.
Ellers er kombinationen af de 10 cifre i nummeret forkert.
Avatar billede martinlind Nybegynder
17. december 2006 - 15:20 #3
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:24 #4
Jeg vil gerne give jer begge points.

@ Kroning.

Kan jeg få dig til at give en kommentar til din kode.

1. Hvorfor anvender du tal til at angive resultatet af valideringen i stedet for true/false (boolean)

2. Er det to forskellige måder, der gør det samme, om man skkriver
a) result:=
b) testcprnummerok:=
i dit eksempel?
Avatar billede kroning Nybegynder
17. december 2006 - 15:26 #5
ok, jeg var lidt for hurtig så her er en der returnere en boolean:

function CprNummerOK(CprNr : string) : boolean;
var
    nr            : array(.1..10.) of byte;
    x                : byte;
    verdi        : word;
    tal            : byte;
    code        : integer;
begin
    Result:=false;

    for x:=Length(CprNr) downto 1 do
      if not (upcase(CprNr(.x.)) in (.'0'..'9','A'..'Z'.)) then
        delete(CprNr,x,1);

    if Length(CprNr)<>10 then
        exit;

    for x:=1 to 10 do
    begin
        val(CprNr(.x.),tal,code);
        nr(.x.):=tal;
    end;
    verdi:=4*nr(.1.)+3*nr(.2.)+2*nr(.3.)+7*nr(.4.)+6*nr(.5.)+5*nr(.6.)+
          4*nr(.7.)+3*nr(.8.)+2*nr(.9.)+nr(.10.);

    if verdi mod 11<>0 then
      exit;

    Result:=true;
end;

----------------------------

  if not CprNummerOK('120570-1235') then
      showmessage('nej, ikke gyldig');
end;
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:28 #6
@ Kroning

Jeg får fejlmeddelelser i din kode:

"cleancprnummer" kan koden selvfølgelig ikke finde ud af hos mig. Hvad gør den?

ved
nr: array(.1..10.) of byte
og
val(cpr(.x.),tal,code);

vil min maskine selvfølgelig have de firkantede paranteser [], hvor du har valgt de runde. ???
Avatar billede kroning Nybegynder
17. december 2006 - 15:29 #7
Mht. om man benytter Result= eller CprNummerOK= så er der ingen forskel, den første function jeg postede var en gammel en fra dengang (for mange år siden i Borland pascal) hvor der ikke var noget der hed Result.
Avatar billede kroning Nybegynder
17. december 2006 - 15:31 #8
Glem den første funktion og brug den anden. Virker det ikke på din computer hvis du benytter (. i stedet for [ ? I min Delphi 7 kan jeg benytte begge dele.
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:32 #9
Jeg har fået det til at virke og siger mange tak for hjælpen.

Jeg er som nævnt klar til at give points.
Avatar billede kroning Nybegynder
17. december 2006 - 15:34 #10
ok, et svar
Avatar billede kroning Nybegynder
17. december 2006 - 15:38 #11
Hov, du skrev "og samtidig kan angive alderen", har du fundet ud af det?
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:40 #12
Nej endnu ikke.
Avatar billede martinlind Nybegynder
17. december 2006 - 15:42 #13
Takker :)
Avatar billede kroning Nybegynder
17. december 2006 - 15:46 #14
Jeg kan rette funktionen til så den samtidig kan give alderen f.eks.?
function CprNummerOK(CprNr : string; var Alder : integer) : boolean;

Eller man kan lave en separat funktion til det?

Hvilken Delphi version benytter du? Jeg spørger fordi der i de ældre versioner ikke findes så mange dato/tids funktioner.
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:46 #15
Nu breder tråden sig efterhånden, men jeg er ikke så stiv i det herinde og er først ved at rydde op i gamle pointregnskab nu osv.

Men jeg ville gerne have givet points til både Martinlind (linket til CPR og baggrunden for udregningen) og Kroning (koden).

Men det ser ud til, at jeg ikke kan give Martinlind points efter jeg har givet Kroning. Kan man ikke give points til 2 personer herinde?
Avatar billede skindbeni Nybegynder
17. december 2006 - 15:48 #16
Jeg sidder med en 7'er.
Avatar billede martinlind Nybegynder
17. december 2006 - 15:56 #17
Det går nok
Avatar billede kroning Nybegynder
17. december 2006 - 17:05 #18
Når du benytter D7 så burde det også virke uanset om du bruger (. eller [, eller hvad?
Avatar billede skindbeni Nybegynder
17. december 2006 - 17:07 #19
Hej igen.

Ja, det virker som det skal.

Hvis du evt. får tid engang er jeg meget interesseret i den del, der beregner alderen også.
Avatar billede kroning Nybegynder
17. december 2006 - 17:09 #20
ok, det kikker jeg lige på.
Avatar billede kroning Nybegynder
17. december 2006 - 18:22 #21
Jeg fandt functionen CalculateAge på Torry. Husk at tilføje DateUtils til din uses.

------------------------

function CalculateAge(Birthday, CurrentDate: TDate): Integer;
var
  Month, Day, Year, CurrentYear, CurrentMonth, CurrentDay: Word;
begin
  DecodeDate(Birthday, Year, Month, Day);
  DecodeDate(CurrentDate, CurrentYear, CurrentMonth, CurrentDay);

  if (Year = CurrentYear) and (Month = CurrentMonth) and (Day = CurrentDay) then
  begin
    Result := 0;
  end
  else
  begin
    Result := CurrentYear - Year;
    if (Month > CurrentMonth) then
      Dec(Result)
    else
    begin
      if Month = CurrentMonth then
        if (Day > CurrentDay) then
          Dec(Result);
    end;
  end;
end;

function CprNummerOK(CprNr : string; var Alder : integer) : boolean;
var
    nr    : array[1..10] of byte;
    x    : byte;
    verdi    : word;
  Dato : TDate;
begin
    Result:=false;

    for x:=Length(CprNr) downto 1 do
        if not (upcase(CprNr[x]) in ['0'..'9','A'..'Z']) then
        delete(CprNr,x,1);

    if Length(CprNr)<>10 then
        exit;

    for x:=1 to 10 do
      Nr[x]:=StrToIntDef(CprNr[x],-1);

    verdi:=4*nr[1]+3*nr[2]+2*nr[3]+7*nr[4]+6*nr[5]+5*nr[6]+4*nr[7]+3*nr[8]+2*nr[9]+nr[10];

    if verdi mod 11<>0 then
        exit;

    Result:=true;

//  TwoDigitYearCenturyWindow:=50;
  Dato:=StrToDate(Copy(CprNr,1,2)+DateSeparator+Copy(CprNr,3,2)+DateSeparator+Copy(CprNr,5,2));
  if Dato>Date then
      Dato:=IncYear(Dato,-100);
    Alder:=CalculateAge(Dato,Date);
end;
Avatar billede kroning Nybegynder
17. december 2006 - 18:22 #22
var
    Alder : integer;
begin
    if not CprNummerOK(Edit1.Text,Alder) then
      Showmessage('Nej, ugyldig cpr nummer')
  else
      Showmessage('OK. Alder er: '+IntToStr(Alder));
end;
Avatar billede borrisholt Novice
09. januar 2007 - 10:49 #23
Nu er spørgsmålet godt nok lukket, men jeg er også lige glad med points.

Jeg har en gang skrevet en CPR Parser, som kan hentes inde på torry.net :
http://www.torry.net/vcl/misc/other/CPR.zip

Jens B
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester