Permalänk
Medlem

c++, kontroll av personnummer

Hej

Började och försökt med en vän få ihop programmeringen till en uppgift,
Det vi försöker göra är en metod som kontrollerar om kontrollsiffran i ett personnummer är korrekt. För att ni ska förstå ska vi förklara hur kontrollsiffran kontrolleras. Vi är nybörjare och har försökt få ihop en kod som fungerar men får den inte att funka, sen ska vi försöka få in någon knappar i programmet men det är nästa problem.

Exempel:
Personnummer: 720310-1212

7 * 2 = 14 -> 1 + 4
2 * 1 = 2 -> 2
0 * 2 = 0 -> 0
3 * 1 = 3 -> 3
1 * 2 = 2 -> 2
0 * 1 = 0 -> 0
1 * 2 = 2 -> 2
2 * 1 = 2 -> 2
1 * 2 = 2 -> 2
2 * 1 = 2 -> 2
1 + 4 + 2 + 0 + 3 + 2 + 0 + 2 + 2 + 2 + 2 = 20
20 / 10 = 2 Godkänt!

///här är något fel

public bool checkPnr() { int len, pnummer; String pnr = this.pnumber; try { pnummer = Convert.ToInt64(pnr); } catch (System.FormatException e) { return false; } char[] pnrchars = pnr.ToCharArray(); len = pnr.Length; if (len != 10) return false; int tot = 0; int temp = pnrchars[2]; MessageBox.Show("TEMP" + temp); for (int i = 0; i < len; ++i) { int temp = 0; temp = Convert.ToInt32(pnrchars[i]); if (i % 2 == 0) temp = Convert.ToInt32(pnrchars[i]); else temp = Convert.ToInt32(pnrchars[i]) * 2; MessageBox.Show("PNR" + pnrchars[i]); MessageBox.Show("TEMP" + temp); if (temp >= 10) tot += temp - 9; else tot += temp; } MessageBox.Show("Tot: " + tot); if (tot % 10 == 0) return true; else return false; }

Permalänk
Skrivet av johoha-8:

if (i % 2 == 0)
temp = Convert.ToInt32(pnrchars[i]);
else
temp = Convert.ToInt32(pnrchars[i]) * 2;

Borde inte de här fallen vara omkastade? Tänk på att när ni loopar över siffrorna så har den första siffran i personnumret index i == 0.

Permalänk
Medlem

det är början jag får fel?

public bool checkPnr() { int len, pnummer; String pnr = this.pnumber;

vad har jag missat i programmet

Permalänk
Medlem

måste det inte vara en klass eller struktur för att man ska kunna använda this?

Visa signatur

¯\_(ツ)_/¯

Permalänk
Hedersmedlem
Skrivet av Jhuyt:

måste det inte vara en klass eller struktur för att man ska kunna använda this?

checkPnr skulle kunna vara en medlemsfunktion någonstans, men this är ändå en pekare och fungerar därför dåligt med punktoperatorn.

Skrivet av johoha-8:

det är början jag får fel?

public bool checkPnr() { int len, pnummer; String pnr = this.pnumber;

vad har jag missat i programmet

Var finns pnumber, och är checkPnr en medlemsfunktion i en klass?

Titta också på felmeddelandena; känner kompilatorn till String, eller borde du skriva

System::String^ pnr

this är också en pekare, så det borde nog vara

System::String^ pnr = this->pnumber;

(Jag antar alltså att du kör c++/cli)

Permalänk
Medlem

jag kan inte c++ men jag gjorde en liknande grej i javascript. kolla källkoden för lite tips om du vill. det här kan säkerligen göras väldigt mycket bättre och jag vet inte om min metod är 100%-ig heller men ändå. här e den:
http://chal.nu/personnummer/

Permalänk
Skrivet av kismo:

jag kan inte c++ men jag gjorde en liknande grej i javascript. kolla källkoden för lite tips om du vill. det här kan säkerligen göras väldigt mycket bättre och jag vet inte om min metod är 100%-ig heller men ändå. här e den:
http://chal.nu/personnummer/

För att testa hur kort det kunde bli så skrev jag algoritmen för att kontrollera att det är ett giltigt personnummer i C# med LINQ:

string pn = "7205181212"; bool valid = pn.Length == 10 && pn.Select((c, i) => { int n = Int32.Parse(c.ToString()) * (2 - (i & 1)); return n < 10 ? n : n - 9; }).Sum() % 10 == 0;

Funktionell programmering FTW

Permalänk
Medlem
Skrivet av VirtualIntent:

För att testa hur kort det kunde bli så skrev jag algoritmen för att kontrollera att det är ett giltigt personnummer i C# med LINQ:

string pn = "7205181212"; bool valid = pn.Length == 10 && pn.Select((c, i) => { int n = Int32.Parse(c.ToString()) * (2 - (i & 1)); return n < 10 ? n : n - 9; }).Sum() % 10 == 0;

Funktionell programmering FTW

snyggt!
hur skulle det där se ut i JS?

Permalänk
Hedersmedlem
Skrivet av kismo:

snyggt!
hur skulle det där se ut i JS?

Obskyrare är roligare. Naiv scheme-tolkning:

((λ (f n) (and (> n 1000000000) (< n 9999999999) (=(remainder (f f n 0) 10) 0))) (λ (f n x)(let ((k (remainder n 10)) (x1 (+ x 1))) (if(= n 0) 0 (+(remainder (* x1 k) 10) (quotient (* x1 k) 10) (f f (quotient n 10) (remainder x1 2)))))) 7205181212)

Permalänk
Skrivet av Elgot:

Obskyrare är roligare. Naiv scheme-tolkning:

Nice! Jag hade inte sett ditt inlägg förrän nu.

Här kommer en konvertering av din kod till F#:

let valid n = let rec f n x = match n with | 0UL -> 0UL | n -> let k = n % 10UL let x1 = x + 1UL (x1 * k) % 10UL + (x1 * k) / 10UL + f (n / 10UL) (x1 % 2UL) n >= 1000000000UL && n <= 9999999999UL && (f n 0UL) % 10UL = 0UL let pn = 7205181212UL System.Console.WriteLine (pn.ToString () + " is " + if (valid pn) then "valid" else "invalid")

Fast det blev namngivna funktioner istället för anonyma.

Sparade in några tecken, och ändrade till pattern matching
Permalänk
Medlem

Bara för att lägga till ännu ett exempel, skrivet i PHP för nått år eller två sen:

$personnummer = 'yymmddxxxx'; $summa = 0; for($i = 1; $i < 10; $i++) { $del = $personnummer[$i - 1] * ($i % 2 + 1); if($del > 9) $summa += 1 + $del % 10; else $summa += $del; } if(($summa + $personnummer[9]) % 10) echo 'Ej giltligt.'; else echo 'Giltligt.';

Ser genast sätt att göra det mindre, som vanligt när man kollar på lite äldre kod

Permalänk
Skrivet av nemrod:

Ser genast sätt att göra det mindre, som vanligt när man kollar på lite äldre kod

Schyst! Uppdatera gärna med förbättringarna du tänker på, om du har lust. Det kan vara illustrativt att se hur man skriver en sån här (förvisso enkel) grej i olika språk på smidigaste sätt.

Permalänk
Medlem
Skrivet av VirtualIntent:

Schyst! Uppdatera gärna med förbättringarna du tänker på, om du har lust. Det kan vara illustrativt att se hur man skriver en sån här (förvisso enkel) grej i olika språk på smidigaste sätt.

function validateSSN($personnummer = '0000000000') { // yymmddxxxx $summa = 0; for($i = 1; $i < 10; $i++) { $del = $personnummer[$i - 1] * ($i % 2 + 1); $summa += ($del > 9 ? 1 + $del % 10 : $del); } return !(($summa + $personnummer[9]) % 10); }

Omskriven till funktion och lite mindre, om än inte så mycket. Orkar inte riktigt göra någon stor overhaul och tänka om