Elikkä taas pitää vähän itteä viisaammilta pyytää apuja, olen tässä jo jonkin aikaa pähkäillyt tämän ohjelman kanssa.
C# kielenä, ohjelman pitäisi pyytää henkilötunnusta kokonaisena tai ilman tarkistusmerkkiä lopussa, jonka jälkeen ohjelma laskee tarkistusmerkin ja sanoo onko käyttäjä mies vai näinen.
jostai syystä koodi jumahtaa noihin substring lauseisiin, mielestäni ne on juuri niinkuin pitää, eli hakee määritellyt merkit tuosta syötetystä henkilötunnuksesta.
Enkä kyllä nyt tajua mikä tuossa olisi vikana, mielestäni pitäisi toimi, jos voisitta kattoa viisaampina mikä tuossa on. kiitos
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace henktunlasku { class Program { static void Main(string[] args) { var henkilötunnus = oikeaMuoto(); string sukupuoli; var kokotunnus = henkilötunnus; if (kokotunnus.Length == 11 || kokotunnus.Length == 10) { var lukuarvo = kokotunnus.Substring(0,6) + kokotunnus.Substring(7,10); var vikamerkki = kokotunnus.Substring(10,11); var tarkistusmerkki = laskeTarkistusMerkki(); int lukuarvoInt = int.Parse(lukuarvo); if (lukuarvoInt % 2 == 0) { sukupuoli = "nainen"; } else { sukupuoli = "mies"; } if (vikamerkki == "") { Console.WriteLine("Tunnukseen tuleva tarkistusmerkki on " +tarkistusmerkki); Console.WriteLine("ja tunnuksen haltija on " + sukupuoli); Console.ReadLine(); } else { if (vikamerkki == tarkistusmerkki) Console.WriteLine("Tunnus on oikein ja sen haltija on " + sukupuoli); else Console.WriteLine("Virheellinen tunnus!\nTämän tunnuksen haltija on " + sukupuoli); Console.ReadLine(); } } } static string oikeaMuoto() // aliohjelma jossa tarkistetaan henkilötunnuksen oikeallisuus { var henkilötunnus = ""; Console.WriteLine("Anna henkilötunnus kokonaisena tai ilman viimeistä merkkiä (PPKKVV-ZZZQ): "); henkilötunnus = Console.ReadLine(); if ((henkilötunnus.Length != 10) && (henkilötunnus.Length != 11) || (henkilötunnus.Substring(6, 7) != "-") && (henkilötunnus.Substring(6, 7) != "+") && (henkilötunnus.Substring(6, 7) != "A")) { Console.WriteLine("Tunnus ei ollut oikeassa muodossa!"); Console.ReadLine(); } else { Console.WriteLine("Syöte on oikeassa muodossa, siirrytään laskemaan se"); } return henkilötunnus.ToUpper(); //muuttaa viimisen kirjaimen isoksi ja palautta henkilötunnuksen pää metodiin } static string laskeTarkistusMerkki() //lasketaan tarkistusmerkki henkilötunnuksesta jos sitä ei ole annettu { string henkilötunnus = oikeaMuoto(); //haetaan henkilötunnus oikeaMuoto aliohjelmasta var luku = henkilötunnus.Substring(0,6) + henkilötunnus.Substring(7,10); //otetaan 9 ensimmäistä numeroa henkilötunnuksesta var tarkistusMerkki = "0123456789ABCDEFHJKLMNPRSTUVWXY"; //tarkistus merkit int lukuInt = int.Parse(luku); //muutetaan henkilötunnuksen string numerot intiksi jotta niiden jakojäännös voidaan laskea tarkistusMerkki = tarkistusMerkki.Substring(lukuInt % 31, lukuInt % 31+1); //lasketaan jäköjäännös return tarkistusMerkki; //palautetaan main metodiin tarkistusmerkki } } }
Mod. vaihtoi oikeat kooditagit!
No ainakin pistää silmään, että et ilmeisesti tiedä Substringin toisen parametrin olevan pituus, vaan oletat sen olevan alkumerkki+pituus.
Toinen juttu on, että et voi ottaa substringiä, joka menisi yli merkkijonon loppukohdan. Jos haluat ottaa tietystä merkistä eteenpäin kaiken, voit toki jättää length -parametrin pois.
Tyyliin
var vikamerkki = kokotunnus.Substring(10, 1);
ei toimi jos pituus on vain kymmenen, mutta
var vikamerkki = kokotunnus.Substring(10);
toimii.
Muokkasin koko koodin vielä toimivaksi... Samalla lyhensin koodia, eli käytin mm. validointiin ympäristön tarjoamia työkaluja. Ehkäpä keksit siitä jotain uusia juttuja omaankin käyttöön.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace henktunlasku { class Program { static void Main(string[] args) { while (true) { Console.WriteLine("Anna henkilötunnus kokonaisena tai ilman viimeistä merkkiä (PPKKVV-ZZZQ)"); Console.Write("tai tyhjä lopettaaksesi: "); string tunnusSyöte = Console.ReadLine().ToUpper(); //Poistutaan silmukasta jos tyhjä syöte if (string.IsNullOrWhiteSpace(tunnusSyöte)) break; if (new Regex("\\d{6}[-+A]\\d{3}[0-9A-Y]?").IsMatch(tunnusSyöte)) { Console.WriteLine("Syöte on oikeassa muodossa, siirrytään laskemaan se"); var tarkiste = laskeTarkiste(tunnusSyöte); string sukupuoli = (tunnusSyöte[9] % 2 == 0) ? "nainen" : "mies"; if (tunnusSyöte.Length == 10) { Console.WriteLine("Tunnukseen tuleva tarkistusmerkki on " + tarkiste); Console.WriteLine("ja tunnuksen haltija on " + sukupuoli); } else if (tunnusSyöte[10] == tarkiste) Console.WriteLine("Tunnus on oikein ja sen haltija on " + sukupuoli); else Console.WriteLine("Virheellinen tunnus!"); /* Jos tunnus on väärin, niin ei ole järkevää ilmoittaa sukupuolta, sillä voihan olla että juuri ko. merkki on väärin. */ } else { Console.WriteLine("Syöte ei ollut oikeassa muodossa!"); } Console.WriteLine(); } } static char laskeTarkiste(string tunnus) { int luku = int.Parse(tunnus.Substring(0, 6) + tunnus.Substring(7, 3)); //tarkistusmerkit return "0123456789ABCDEFHJKLMNPRSTUVWXY"[luku % 31]; } } }
Joo kiitos, olin tosiaan tajunnu väärin ton substringin, tajusin sen sillee et jokasella merkillä merkkijonossa olis oma numero ja jos haluasin esim. "yksikaksikolme" sanasta kaksi tulostaa niin pitäs pistää substring(5,9), mut eihän se näin menny, mut tajuun nyt ok, kiitos :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.