Avatar billede hauge1212 Nybegynder
11. november 2001 - 15:04 Der er 23 kommentarer og
2 løsninger

Cpr nummer checker

Jeg skal lave et program, der kan checke om et cpr nummer er ægte eller falck.
Programmet skal skrives i Pascal.
Først have jeg tænkt mig, at programmet skulle spørge efter cpr nummeret, også skal brugeren taste nummeret ind.
Hvis vi siger at cpr nummeret er: 1029012015

Så skal programmet gøre følgende:
1 * 4
0 * 3
2 * 2
9 * 7
0 * 6
1 * 5
2 * 4
0 * 3
1 * 2

Alle disse resultater skal derefter lægges sammen, og derefter:

[resultat] div 11
86 div 11 = 8

Hvis resten; 8, er lig med det 10. ciffer, så er cpr nummeret gyldigt. (i dette tilfælde, var det ikke)

Jeg har lavet fælgende, men kan ikke rigtigt få det til at virke, og kan ikke komme længere:

program Cpr;

uses
  Forms;
type
  raekke = array[0..9999] of integer;
var
  A,B:integer;
  Cprnr:raekke;
begin
  write(\'Indtast dit CPR-nummer:\');
  Readln(Cprnr);
  writeln(Cprnr[3]);
  Readln;
end.


Håber der er nogen der kan hjælpe mig videre, jeg ønsker ikke desideret at der er nogen der skriver et færdigt program til mig, da dette er en opgave jeg fik for i skolen. Og derfor skal lære af det :-)
Avatar billede dkn Nybegynder
11. november 2001 - 15:38 #1
1 * 4
0 * 3
2 * 2
9 * 7
0 * 6
1 * 5
2 * 4
0 * 3
1 * 2

Kan du ikke fortælle lidt mere om hvilken nummer de sjal ganges med?
ex. 1 i toppen bliver ganget med 4 - men 1 i bunden bliver ganget med 2 ??
Avatar billede hauge1212 Nybegynder
11. november 2001 - 15:58 #2
Ok, hvis cpr nummeret er:

1029012015

Så kommer det til at se sådan ud:

102901201
432765432

Hvor 5 er det sidste tal, og dermed kontrol nummeret.
Det første tal i cpr nummeret skal ganges med 4, det næste med 3, det næste med 2 også videre.

-----

En måde jeg havde tænkt opgaven løst på var og man gik ind og sagde:

write(\'Indtast dit CPR-nummer:\');
  Readln(Cprnr);
  writeln((Cprnr[1]*4)+(Cprnr[2]*3)+..(osv.);
  Readln;

Dette virket bare ikke, kan det ikke være fordi at Cprnr ikke bliver opfattet af programmet som tal ?
Avatar billede pellelil Nybegynder
11. november 2001 - 16:02 #3
hauge1212> Umiddelbart ligner det \"den gode gamle Pascal\", inden GUI kom i højsæde.

Jeg vil foreslå at du indtaster CPR-nummeret som en streng. Hvert ciffer kan du så få fat i ved at indexere strengen (det 5. ciffer er CprStr[5]). Hvert ciffer kan laves om fra en char (et tegn fra strengen) til en Integer værdi ved at lave lidt \"ASCII-forskydning\": IntCiffer = Ord(CprStr[5])-48;

Med hensyn til de tal du skal gange med vil jeg foreslå at du opretter disse i et array som du kan anvende i \"den forløkke\" du bruger til at gennemse CPR-nummerets cifre: constGangeVaerdier : Array[1..9] of Integer = (4,3,2,7,6,5,4,3,2);

Resten burde du selv kunne klare :-)
Avatar billede dkn Nybegynder
11. november 2001 - 16:03 #4
nej fordi det der ikke virker, er pga [].
Ex:
Hvis en string er: TEST
så hvis man siger:
showmessage(TEST[1]);//Så vil den kun vise det første bogstav T
...showmessage(TEST[3]);// Vil være TES

Men jeg vil lige kigge på det når jeg får lidt tid
Avatar billede pellelil Nybegynder
11. november 2001 - 16:06 #5
dkn> TEST[3] vil kun være et bogstag \"S\". Hvis du i stedet vil have \"TES\", så skal du bruge Copy: Copy(TEST, 1, 3);
Avatar billede dkn Nybegynder
11. november 2001 - 16:46 #6
i dit exempel er det vel sådan her det skal forståes:
((1 * 4) + (0 * 3) + (2 * 2) + (9 * 7) + (0 * 6) + (1 * 5) + (2 * 4) + (0 * 3) + (1 * 2)) div 11 = noget

eller hva?
Avatar billede halifax Nybegynder
11. november 2001 - 16:57 #7
Er udregningen ikke sådan, at når cpr.nr. ganges med de aktuelle tal, er det kun det sidste ciffer af denne udregning som skal indgå i summen, der til sidst divideres med 11??
Hvorfan det så programmeres aner jeg intet om. Suk!
 
Avatar billede hauge1212 Nybegynder
11. november 2001 - 19:10 #8
Til dkn:

Du har fuldstændig ret.

Det der så skal være den variable værdi, er cprnr.
Avatar billede pellelil Nybegynder
11. november 2001 - 19:17 #9
halifax> Hvis jeg ikke husker helt forkert skal det sidste ciffer være: \"Summen Mod 11\" hvilket i så fald kan betyde at det sidst ciffer kan være 10, men mon ikke dette i såfald vil være 0 (eller er det noget med tværsummen ?) - beklager men jeg har ikke rodet med CPR validering siden jeg i sin tid gik på skole.
Avatar billede razersedge Nybegynder
11. november 2001 - 20:40 #10
hmmm nu har jeg selv siddet og leget lidt med det og kommet frem til dette:

procedure TForm1.Button1Click(Sender: TObject);
var
CPRnr : string;
res : array[0..10] of integer;
resultat : integer;

begin
CPRnr := edit1.Text;
res[1] := strToInt(Copy(Cprnr, 1, 1)) * 4;
res[2] := strToInt(Copy(Cprnr, 2, 1)) * 3;
res[3] := strToInt(Copy(Cprnr, 3, 1)) * 2;
res[4] := strToInt(Copy(Cprnr, 4, 1)) * 7;
res[5] := strToInt(Copy(Cprnr, 5, 1)) * 6;
res[6] := strToInt(Copy(Cprnr, 6, 1)) * 5;
res[7] := strToInt(Copy(Cprnr, 7, 1)) * 4;
res[8] := strToInt(Copy(Cprnr, 8, 1)) * 3;
res[9] := strToInt(Copy(Cprnr, 9, 1)) * 2;
res[10] := strToInt(Copy(Cprnr, 10, 1));  //sidste tal

resultat := (res[1] + res[2] + res[3] + res[4] + res[5] + res[6] + res[7] + res[8] + res[9]) div 11;
if resultat = res[10] then begin
label1.caption := \'Gyldigt cprnr\';
end else begin
label2.caption := \'Ugyldigt cprnr\';
end;


end;



men den kommer op med at mit eget cprnr er ugyldigt ??
Avatar billede dkn Nybegynder
11. november 2001 - 22:23 #11
Ja jeg har prøvet noget lignende, vil lige se igen havd fanden der er galt
Avatar billede dkn Nybegynder
11. november 2001 - 22:51 #12
Jeg ved sku ik, det her ser ud til at virke nogle gange?
Ved ikke helt hvorfor, men jeg har heller ikke brugt samme tal som dig, det var ved et uheld jeg lige prøvede og så virkede lortet på nogle Cpr numrer. Ved ik om du kan bruge det...


function TForm1.IsCprValid(Cpr: integer): boolean;
var
  I, TotalCount: integer;
  CurrentNum, StartCPR: string;
  Vaerdi : array[1..10] of integer;
begin
if length(inttostr(Cpr)) <> 10 then result := false else
  begin
  StartCPR := inttostr(Cpr);
  Delete(StartCPR, Length(StartCPR), Length(StartCPR));//fjerner sidste værdi
    for I := 1 to 10 do
    begin
      CurrentNum := inttostr(Cpr)[I];
      case I of
        1: Vaerdi[1] := (Round(strtoint(CurrentNum) * 6));
        2: Vaerdi[2] := (Round(strtoint(CurrentNum) * 5));
        3: Vaerdi[3] := (Round(strtoint(CurrentNum) * 4));
        4: Vaerdi[4] := (Round(strtoint(CurrentNum) * 3));
        5: Vaerdi[5] := (Round(strtoint(CurrentNum) * 2));
        6: Vaerdi[6] := (Round(strtoint(CurrentNum) * 6));
        7: Vaerdi[7] := (Round(strtoint(CurrentNum) * 5));
        8: Vaerdi[8] := (Round(strtoint(CurrentNum) * 4));
        9: Vaerdi[9] := (Round(strtoint(CurrentNum) * 3));
        10: Vaerdi[10] := (Round(strtoint(CurrentNum)*2));
      end;
    end;
    TotalCount := (Vaerdi[1]+Vaerdi[2]+Vaerdi[3]+Vaerdi[4]+Vaerdi[5]+Vaerdi[6]+Vaerdi[7]+Vaerdi[8]+Vaerdi[9]+Vaerdi[10]) div 11;
    if TotalCount = 10 then result := true else result := false;
  end;
end;


procedure TForm1.FormClick(Sender: TObject);
begin//Eksempel Cpr:
if IsCprValid(1008860159) then showmessage(\'Ok\') else  showmessage(\'Ikke valid\');
end;
Avatar billede hreiff Nybegynder
12. november 2001 - 14:12 #13
Man kan ikke bruge integer (eller longint) da de kun kan håndtere tal op til ca. 32000 hhv. 2100000000, dvs med longint går det kun til og med 21/4 for et vilkårligt år.

Man er godt bruge comp istedet, men da indlæsningen er en string, vil det være nemmest at bruge:
  if (StrToInt(s[1])*4 + StrToInt osv ) MOD 11 = StrToInt(s[10])
        then ok
eller
  if ((ord(s[1])-48)*4 + ... osv.    { da  ord(\'3\')-48 = 3  osv. }
Avatar billede dkn Nybegynder
12. november 2001 - 15:00 #14
det er ikke det som er problemmet tror jeg ikke :|
Avatar billede hreiff Nybegynder
12. november 2001 - 19:48 #15
Nej, det er rigtigt. Problemet kontrollen.
Det er ikke tallet Div eller mod 11 men:
11 - res MOD 11 = sidste ciffer (og 0 hvis det er 11)

dvs. vi kan f.eks bruge (Spring det over hvis du selv vil):


Function CprCheck(CprNr: String):Boolean;
Const
  Check: String[9] = \'432765432\';
Var
  i,Res: Integer;
begin
  Res := 0;
  Result := False;
  for i := 1 to 9 do
    Res := Res + (ord(CprNr[i])-48) * (Ord(Check[i])-48);
  Res := Res Mod 11;
  If Res <> 0  Then
    Res := 11 - Res;
  If Res = Ord(CprNr[10])-48 Then
    Result := True;
end;

Alle de andre svar er sikkert også ok, men forudsætninger var forkert.

//hreiff
Avatar billede dkn Nybegynder
12. november 2001 - 21:04 #16
>> forudsætninger var forkert.
Why?
Avatar billede hreiff Nybegynder
13. november 2001 - 09:30 #17
Fordi at oplægget var at man skulle lave en x DIV 11, men det skulle man ikke - Man skulle lave en 11 - x MOD 11 for at finde kontrolcifferet. Ellers virker testen ikke.
Avatar billede hreiff Nybegynder
13. november 2001 - 09:38 #18
Husk iøvrigt at checke for korrekte datoer
(Der er noget med skudår osv) og for fejlindtastninger
(O istedet for 0) og tåbelige lærere der starter med at indtaste:
123456-7890
Avatar billede dkn Nybegynder
13. november 2001 - 13:46 #19
Hvor har i fundet den formel til at regne det ud med?
Avatar billede hreiff Nybegynder
13. november 2001 - 13:59 #20
Eksperten / Databaser / Access (Søgning på \'Cpr Check\' på www)

Det er vist en meget brugt opgave inden for mange områder.
Avatar billede stoney Nybegynder
13. november 2001 - 15:09 #21
Avatar billede hauge1212 Nybegynder
13. november 2001 - 15:41 #22
Tak, skal i have, jeg har delt pointene op mellem jer, da jeg har kundet bruge lidt fra jer hver.

Angående x div 11, så er det min lære der har givet mig en forkert opgave formulering. Jeg fik samme fejl, med den metode. Men det rigtige med: 11 - x div 11


Jeg mangler kun en ting til at gøre mit program bedre, og det er noget der tester om der er tastet 10 tal ind eller ej. Og hvis der ikke er, så skal den komme med en form for fejl meddelelse.

Tak for hjælpen
Avatar billede hauge1212 Nybegynder
13. november 2001 - 15:42 #23
Nej, jeg brugte ikke 11 - x div 11

men 11 - x mod 11
Avatar billede dkn Nybegynder
13. november 2001 - 15:45 #24
nå, nu fik jeg ellers lige min til at virke, da jeg kunne se formlen til det. Tak stoney :)

function TForm1.IsCprValid(Cpr: string): boolean;
var
  I, TotalCount: integer;
  StartCPR: string;
  Vaerdi : array[1..10] of integer;
  DivCount:extended;
begin
if length(Cpr) <> 10 then result := false else
  begin
  StartCPR := Cpr;
    for I := 1 to 11 do
    begin
      case I of
        1: Vaerdi[1] := (Round(strtoint(Cpr[I]) * 4));
        2: Vaerdi[2] := (Round(strtoint(Cpr[I]) * 3));
        3: Vaerdi[3] := (Round(strtoint(Cpr[I]) * 2));
        4: Vaerdi[4] := (Round(strtoint(Cpr[I]) * 7));
        5: Vaerdi[5] := (Round(strtoint(Cpr[I]) * 6));
        6: Vaerdi[6] := (Round(strtoint(Cpr[I]) * 5));
        7: Vaerdi[7] := (Round(strtoint(Cpr[I]) * 4));
        8: Vaerdi[8] := (Round(strtoint(Cpr[I]) * 3));
        9: Vaerdi[9] := (Round(strtoint(Cpr[I]) * 2));
        10: Vaerdi[10] := (Round(strtoint(Cpr[I]) * 1));
      end;
      case I of
        2: Vaerdi[2] := Vaerdi[1]+Vaerdi[2];
        4: Vaerdi[4] := Vaerdi[3]+Vaerdi[4];
        6: Vaerdi[6] := Vaerdi[5]+Vaerdi[6];
        8: Vaerdi[8] := Vaerdi[7]+Vaerdi[8];
        10: Vaerdi[10] := Vaerdi[9]+Vaerdi[10];
      end;
    end;
    TotalCount := Vaerdi[2]+Vaerdi[4]+Vaerdi[6]+Vaerdi[8]+Vaerdi[10];
    DivCount := TotalCount div 11;
    if DivCount = 14 then result := true else result := false;
  end;
end;

/Call:
if IsCprValid(\'0707614285\') then showmessage(\'Ok\') else  showmessage(\'Ikke valid\');
Avatar billede hauge1212 Nybegynder
13. november 2001 - 15:58 #25
Tak for det dkn
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