Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C-kielen perusteita

Sivun loppuun

JKWalas [31.12.2003 00:54:30]

#

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'.*/

JKWalas [31.12.2003 01:01:56]

#

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

Gwaur [31.12.2003 09:09:27]

#

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.

sooda [31.12.2003 11:36:54]

#

Kyllä on vähän liikaa kommentteja... rutkasti enemmän kommenttia kun ite koodia :P

Krisu [31.12.2003 12:13:00]

#

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.

odys [31.12.2003 15:30:56]

#

Tosta ei todellakaann kukaan enää ymmärrä mitään kun kommennteja on niin perkeleesti liikaa. Saa oikein etsiä missä on koodia ja missä kommentteja.

JKWalas [31.12.2003 16:28:23]

#

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 :)

JKWalas [31.12.2003 16:52:35]

#

*edit* muutin kommenttien ja koodiin järjestystä hieman niissä paikoissa joissa koodi hukkui kommenttien sekaan.. ehkäpä tuo selkiytti sitä edes vähän.

Antti Laaksonen [01.01.2004 01:10:05]

#

Värikoodaus toimii nyt, vähän bugisena tosin (parannusta luvassa...)

Anzuhan [01.01.2004 11:30:19]

#

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).

JKWalas [01.01.2004 20:30:31]

#

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. :)

JKWalas [01.01.2004 20:52:26]

#

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.

JKWalas [01.01.2004 22:14:25]

#

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 :)

JKWalas [02.01.2004 05:42:50]

#

*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..

nikke [19.01.2004 22:32:08]

#

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ää...

jeims [17.12.2004 21:39:26]

#

Thanke! Mäkin alan kohta älyyn tätä!

eraggo [22.03.2005 16:10:44]

#

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ä....

Aloittelija3 [05.04.2006 19:07:04]

#

eraggo googleen vaan hakusanaksi free compilers tjsp..

Codeprofile [10.12.2006 09:58:25]

#

Excellent! Matikan aika-tehtävissä tosta todellakin on hyötyä :D.

Pollapoju [08.04.2008 17:03:25]

#

opettavainen on tuo


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta