Juu eli tässä ajattelin tehdä simppelin esimerkin ihan vaan joistakin C:n perusteista kun niitä ei täällä ole näkynyt niin jospa ihan aloittelijatkin saavat täältä jatkossa jotain irti. Koodissa käytetään merkkipuskuria, gets, sscanf ja printf -funktioita sekä silmukoita ja löytyypä siitä yksinkertaisia virheenkäsittelyitäkin. Toivottavasti tästä on jotain hyötyä jollekin... joskus...
Taisi mennä vähän överiksi tuon kommentoinnin kanssa :)
Ohjelmassa on yksinkertaisia virheenkäsittelyjä, joten koodi on aika turval-
linen ja ei pitäisi sekoilla.
/****Include(t)*/ #include <stdio.h> /****Ohjelma alkaa*/ int main(void) { /****Muuttujat*/ double mins=0, sekun=0, sek=0, tunnit=0; char ehto; char puskuri[128]; /****Selitykset "long int.." Muuttujat joilla hoidetaan laskut. Muuttujat myös alustetaan "=0". "char ehto;" Merkkimuuttuja ehdolle, jotta voidaan kysyä suoritetaanko ohjelma uudestaan vai ei. "char puskuri.." Varataan 128 merkin puskuri "roskia" varten esim. ENTERIN pai- nallus sekunneille annetun arvon jälkeen. Se voidaan hypätä yli kun puskuria käydään läpi "sscanf"-funktiolla.*/ /****Aloitetaan looppi*/ do { /****Kysytään sekuntien määrä*/ printf ("\nProggy from a furious monster!! RoArRRrRR!\n"); printf ("Gimme a bunch of seconds: "); fgets (puskuri, sizeof(puskuri), stdin); sscanf (puskuri,"%d", &sek); /****Tarkistetaan käyttäjän antama luku*/ if (sek < 0) { /****Virheenkäsittely alkaa*/ do { printf ("Gimme a bunch of seconds: "); fgets (puskuri, sizeof(puskuri), stdin); sscanf (puskuri,"%d", &sek); }while (sek < 0); } /****Selitykset "printf ("\n..." Tulostetaan teksti, joka on lainausmerkkien sisällä. "\n" on koodi tyhjälle riville. Tässä siis ennen ja jälkeen tekstin. "fgets (pusku..." Luetaan käyttäjän antamia merkkejä puskuriin. "sscanf (puskuri,"%d..." Aloitetaan puskurin läpikäynti. sscanf lukee puskuria kunnes se löytää sieltä numeron "%d" ja sijoittaa sen sek-muuttujaan. "if (sek < 0)" Tarkistetaan onko käyttäjän antama luku pienempi kuin nolla. "do .. while" Virheenkäsittely alkaa. Tässä silmukassa kysytään käyttäjältä uutta lukua kunnes syötetään nolla tai suurempi luku.*/ /****Tehdään laskutoimitukset*/ tunnit=sek/60/60; mins=sek/60-tunnit*60; sekun=sek-(mins*60)-(tunnit*60*60); /****Tulostetaan tulos ruudulle*/ printf ("The seconds are %d",tunnit); printf (" hour(s) and %d",mins); printf (" minute(s) and %d",sekun); printf (" second(s)\n"); /****Selitykset "printf ("The secon.." Tulostetaan teksti ja sen perään tunnit-muuttujan arvo "%d".*/ /****Kysytään halutaanko laskea uusi sekuntiläjä*/ printf ("\nVery simple eh? Thats all it does :P\n\n"); printf ("Wanna do it again (y/n) ??: "); fgets (puskuri, sizeof(puskuri), stdin); sscanf (puskuri,"%c", &ehto); /****Vastauksen tarkistus mahdollista virheenkäsittelyä varten*/ if (ehto != 'n' && ehto != 'y') { /****Vastauksen virheenkäsittely*/ while (ehto != 'n' || ehto != 'y') { printf ("Wanna do it again (y/n) ??: "); fgets (puskuri, sizeof(puskuri), stdin); sscanf (puskuri,"%c", &ehto); if (ehto == 'n' || ehto == 'y') { break; } } } /****Katsotaan täyttyykö loopin lopettava ehto*/ }while (ehto != 'n'); /****Ohjelma loppuu*/ printf ("\n\nOK, as you wish :P Exiting..... "); return 0; } /****Selitykset "sscanf (pusku..." sscanf lukee puskuria kunnes löytää sieltä kirjaimen "%c". "if (ehto != 'n.." Katsotaan onko ehto-muuttujan arvo 'n' tai 'y'. "while (ehto ..." Kysytään käyttäjältä uutta vastausta kunnes käyttäjä vastaa joko 'n' tai 'y'. "if (ehto == ...." Tässä katsotaan onko käyttäjän syöttämä uusi arvo 'n' tai 'y'. Jos on, niin while-silmukasta poistutaan break-käskyllä. "do... while" Lauseke "(ehto != 'n')" tarkoittaa, että silmukasta ei poistuta, jos ehto-muuttujassa on jokin muu arvo kuin kirjain 'n'.*/
mainittakoon vielä että itse painin aikanaan virheenkäsittelyn kanssa oikein kunnolla näinkin yksinkertaisen ohjelman kanssa, että olisi tämän tyylinen koodi ollut itselleni silloin oikeen hyvään tarpeeseen.. olisi ehkä pitänyt jättää ohjelman toiminnan kuvaus vähän vähemmälle :P
Kommentteja on liikaa. Esim. jokainenhan tajuaa että "do {" kohta alottaa loopin ilman mitään lisäkommentteja. :P Sain itse samanlaisia kommentteja kun pistin ylikommentoidun rinkulamatokoodin tänne.
Kyllä on vähän liikaa kommentteja... rutkasti enemmän kommenttia kun ite koodia :P
Lukekaapa millä otsikolla tämä vinkki tänne on tullut...
Siinähän näkyy suoraan, kenelle tämä on suunattu. Ei aloittelija todellakaan tiedä, mitä "do" tarkoittaa... tai välttämättä mitään muutakaan c:stä ;)
Tuo kommentointihan on hyvä... sillähän varmistetaan että joku muukin/itse ymmärtää koodin vaikka 10 vuoden kuluttua.
Tosta ei todellakaann kukaan enää ymmärrä mitään kun kommennteja on niin perkeleesti liikaa. Saa oikein etsiä missä on koodia ja missä kommentteja.
tuosta karsin jo paljon alkuperäistä kommentointia pois ja värikoodauksen puuttuessa koodi tosiaan vähän häviää sinne sekaan, mutta täysin alottelijoillehan tuon suuntasin ja siksi siinä on paljon kommentointia :)
*edit* muutin kommenttien ja koodiin järjestystä hieman niissä paikoissa joissa koodi hukkui kommenttien sekaan.. ehkäpä tuo selkiytti sitä edes vähän.
Värikoodaus toimii nyt, vähän bugisena tosin (parannusta luvassa...)
Kaksi sanaa: buffer overflow. standardikirjaston gets on sananmukaisesti turvaton ja sen käyttämisen sijasta suositellaan fgetsin käyttöä. Siispä, jos käyttäjä antaa yli 128 merkkiä pitkän olevan syötteen -> pum. Eli, fgets(fileno(stdin), 128, puskuri).
Tässä tapauksessa puskurin ylivuotoa ei ilmeisesti pääse tapahtumaan getsin käytöstä huolimatta. Testasin sen kun syötin 140 merkkiä ja enemmänkin ohjelmalle, jollon se kysyi vain uutta syötettä eikä siis kaatunut. DOS itsessään ei kuulemma hyväksy yli 128 merkin syötteitä. Kiitokset kuitenkin vinkistä Anzuhan. :)
Testasinpa uudelleen ja ohjelma tosiaan saattaa toimia ylipitkissä syötteissä hieman arvaamattomasti, mutta kaatumaan en sitä silti saanut. Tunneiksi, minuuteiksi ja sekunneiksi vain saatiin arvoiksi satunnaisia lukuja. Näin siis ainakin win2k:n dossissa.
Ja vielä kommentoinnista..
<rant>
Perinteisesti ohjelmointiputkan koodivinkkejä on kommentoitu hyvin laiskasti ja siksi ne eivät toimi tukena ohjelmointia opetteleville (niinkuin esimerkiksi minulle) kovinkaan hyvin, koska pelkkä koodi ei välttämättä selitä aloittelijalle mitään miksi jotain on tehty niin kuin on tehty ja miten se toimii. Tästä syystä poikkesin vallitsevasta suuntauksesta.
</rant>
Sen kuitenkin myönnän, että kommentointia voi toki olla liikaakin, mutta kultaisen keskitien löytäminen tässä asiassa on vaikeaa :)
*edit* Lisää tilaa muuttujille ja gets:in tilalle fgets. Riittävän kauan kun ohjelmaa käytti niin kyllä se ylivuoto iski, vaikkakin vasta ohjelmasta poistuttaessa :P Maksimi arvo joka lasketaan on nyt noin 9*10^32 tai jotain sen suuntaista..
Raskaan oloista.. Tuo että ensin if tarkistaa syötteen ja sit kaikki on kirjoitettu toiseen kertaan do-while -silmukan sisälle... Mulla on tapana laittaa nuo kysymykset suoraan silmukkaan. Pidemmän päälle turhauttaa copy-pastettaa kaikki moneen kertaan... Mutta koodi vastaa hyvin otsikkoa! Ja kommentointi on todellakin hyvin tyhjentävää...
Thanke! Mäkin alan kohta älyyn tätä!
jos yleensä yämä olisi HYVÄ ohje aloittelijalle (mulle) niin miksi tässä ei ole selostettu esim. sitä mistä saa hyvän ohjelman jos haluu ohjelmoida C:tä....
eraggo googleen vaan hakusanaksi free compilers tjsp..
Excellent! Matikan aika-tehtävissä tosta todellakin on hyötyä :D.
opettavainen on tuo
Aihe on jo aika vanha, joten et voi enää vastata siihen.