| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
hetu.cTorak 10.09.05 15:23 Henkilötunnuksen tarkistaminen
/* Tämä ohjelma tarkistaa henkilötunnuksen oikeellisuuden. Sen on kirjoittanut Antti-Juhani Kaijanaho (gaia@iki.fi) 1999-02-21. Ohjelmaa saadaan käyttää, muuttaa ja levittää vapaasti, kunhan ohjeman tekijä ja mahdollisten muutosten tekijät mainitaan asianmukaisesti. Henkilötunnus luetaan komentoriviltä. Sen oikeellisuus tulostetaan standardisyötevirtaan, ja ohjelman paluuarvo kertoo onnistumisesta vain silloin, kun kaikki annnetut henkilötunnukset ovat OK. Henkilötunnuksen tarkistusmerkin oletetaan olevan joko suuraakkonen tai numero. Ohjelma on pyritty kirjoittamaan ISO-standardin mukaisella C:llä. Ohjelman teossa on pyritty välttämään oletuksia käytössä olevasta ympäristöstä (esim. merkistöasiat), joten ohjelman pitäisi olla maksimaalisen portattava. OHJELMAN TEKIJÄ EI OTA OHJELMAN TOIMINNAN OIKEELLISUUDESTA MINKÄÄNLAISTA VASTUUTA. Muutokset tiedoston lopussa. Tämä ohjelma on osa sfnet.atk.ohjelmointi.moderoitu-uutisryhmän FAQ:a. Sen uusin versio on saatavissa FAQ:n seittisivun <URL: http://www.iki.fi/gaia/faq/sao-faq.html > kautta. Ohjelma voi löytyä myös osoitteesta <URL: ftp://ftp.jyu.fi/private/antkaij/faq/hetu.c > */ #include <assert.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* Palauttaa toden, mikäli b jakaa a:n. */ int jakaa (int a, int b) { return a % b == 0; } /* Palauttaa toden, mikäli n on a:n ja b:n välissä. Oletus: a <= b.*/ int valissa (int n, int a, int b) { assert (a <= b); return a <= n && n <= b; } /* Toimii vain gregoriaanisella kalenterilla. Gregoriaaninen kalenteri syntyi 1582. */ int karkausvuosi (int vuosi) { assert (vuosi >= 1582); return (jakaa (vuosi, 4) && (!jakaa (vuosi, 100) || jakaa (vuosi, 400))); } /* Onko päiväys p.kk.v validi? */ int paivays_ok (int p, int kk, int v) { /* Tämä on päiviä kuukaudessa -taulukko; ensimmäinen dimensio valitsee karkausvuoden (1) ja tavallisen vuoden (0) välillä. */ static p_kk [2] [12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; return valissa (kk, 1, 12) && valissa (p, 1, p_kk [karkausvuosi (v) ? 1 : 0] [kk - 1]); } /* Muutetaan numeromerki c numeroksi. Mikäli c ei ole numeromerkki, palautetaan INT_MIN. */ int char2digit (char c) { switch (c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return INT_MIN; } } /* Muutetaan merkkijono s (josta huomioidaan enintään n merkkiä ja merkki ignore jätetään huomiotta) ei-negatiiviseksi luvuksi. Palautetaan LONG_MIN virhetapauksessa. */ long str2long (const char * s, size_t n, int ignore) { long rv = 0; int i; assert (s != 0); for (i = 0; s [i] != 0 && i < n; i++) { int c2d; if (i == ignore) continue; c2d = char2digit (s [i]); if (c2d == INT_MIN) return LONG_MIN; rv = rv * 10 + c2d; } return rv; } int hetu_ok (const char * hetu) { int vuosisata; const int VSM = 6; /* vuosisatamerkin indeksi */ const int TM = 10; /* tarkistemerkin indeksi */ static const char tarkmerk [] = "0123456789ABCDEFHJKLMNPRSTUVWXY"; if (strlen (hetu) != TM + 1) return 0; /* Tarkistetaan vuosisatamerkki. */ switch (hetu [VSM]) { case '-': vuosisata = 1900; break; case '+': vuosisata = 1800; break; case 'A': vuosisata = 2000; break; default: return 0; } /* Tarkistetaan päiväys. */ if (!paivays_ok (str2long (hetu, 2, -1), str2long (hetu + 2, 2, -1), str2long (hetu + 4, 2, -1) + vuosisata)) return 0; /* Tarkistetaan tarkiste. */ return hetu [TM] == tarkmerk [str2long (hetu, TM, VSM) % 31]; } int main (int argc, char * argv []) { int i; int rv = EXIT_SUCCESS; for (i = 1; i < argc; i++) { int ok; ok = hetu_ok (argv[i]); printf ("%s: %s\n", argv [i], ok ? "OK" : "Virhe"); rv = ok ? rv : EXIT_FAILURE; } return rv; } /* $Log: hetu.c,v $ Revision 1.2 1999/12/10 03:32:11 ajk Mainitaan oletus, että tarkistemerkki ei ole pienaakkonen. Mainitaan ohjelman suhde sao-faq:iin ja sen URL. 1999-02-21 gaia@iki.fi: paivays_ok Korjattu off by one -virhe taulukon indeksoinnissa. */ eis 15:33 10.9.05 "Tällä lomakkeella voit tallentaa omia ohjelmia/esimerkkejä Mureakuhan koodikirjastoon." Millä mielessä tuo on sinun omasi..? |
![]() Haku
|