1. C-kieli

1. C-kieli
yleiskäyttöinen ohjelmointikieli, standardoitu 1990.
• siirrettävä
• laiteläheinen
• pieni ydin, monimutkaiset kokonaisuudet rakennetaan aliohjelmakirjastojen avulla.
• direktiivit ja esikääntäjien käyttö
• vaikeahko, helppo tehdä pahoja virheitä
• heikosti tyypitetty eikä ajonaikaisia tarkistuksia ( vrt. Java )
1
C-kieli mahdollistaa hyvin tiiviin ja samalla sekavan tavan esittää asioita,
kuitenkin hyvän ohjelman tulisi olla mahdollisimman helppolukuinen ja
ymmärrettävä.
2
C-kielen yleispiirteet
Ohjelman ulkoasu
esikääntäjän direktiivit
main-funktion otsikko {
muuttujien määrittelyt
suoritettavat lauseet
}
3
Esikääntäjän direktiivit
Jokaiseen C-ohjelmaan liitetään yksi tai useampia otsikkotiedostoja, joiden
tarve riippuu ohjelmassa käytetyistä funktioista.
Esikääntäjän direktiivit ovat C-esiprosessorin ymmärtämiä käskyjä, jotka
suoritetaan ennen ohjelman varsinaista kääntämistä.
• direktiivi alkaa "#"-merkillä
• #include kertoo käytetyt kirjastot
• #define määrittelee vakiomakrot
4
C-kieli sisältää aika pienen määrän toimintoja
• ohjelmakirjastojen käyttö
• C-kielen standardi edellyttää tiettyjen kirjastojen toimittamisen jokaisen
C-kielen toteutuksen mukana.
• kirjastotiedostot päättyvät -.h tunnukseen (header)
5
Esimerkiksi:
#include<stdio.h> -direktiivi käskee esiprosessoria lisäämään tiedoston
stdio.h sisältämät määrittelyt ohjelmatiedostoon ennen ohjelman varsinaista
kääntämistä.
Määrittelyt kertovat esiprosessorille mm. sen, että ohjelmassa käytetyt nimet
(kuten scanf ja printf ) löytyvät em. tiedostosta.
#define MK_EUROINA 5.94573 /* muunnosvakio */
liittää vakiomakroon MK_EUROINA merkityksen 5.94573.
Esiprosessori korvaa ohjelmakoodissa esiintyvän tunnuksen MK_EUROINA
arvolla 5.94753 ennen kääntämistä.
6
• vakiomakroiksi kannattaa määritellä vain sellaisia arvoja, jotka pysyvät
vakioina
• tunnuksen käyttö ohjelmakoodissa lisää ohjelman luettavuutta ja ylläpidettävyyttä.
7
main-funktio
main-funktion otsikko kertoo, mistä ohjelman suoritus alkaa
main-funktion otsikko on muotoa:
int main (void)
tai
int main(int argc, char * argv[])
Kaikissa C-ohjelmissa on main-funktio.
8
• Loput koodirivit muodostavat ohjelman rungon.
• Ohjelman runko sijoitetaan { , } -merkkien sisälle
• Sulkeissa olevaa ohjelman osaa kutsutaan lohkoksi (block).
• Ohjelma päättyy "}"- merkkiin.
9
Ohjelman runko koostuu kahdesta osasta
• Määrittelyistä
• Suoritettavista lauseista
Esimerkki C-ohjelmasta:
#include <stdio.h>
int main(void){
printf("Hello, World! ");
return(0);
}
10
Ohjelma sisältää kaksi suoritettavaa lausetta ( statement ):
printf("Hello, World! ");
Se tulostaa kuvaruudulle tekstin "Hello, World!", (lainausmerkkejä ei
tulosteta).
Käskyllä
return(0);
lähetetään kontrolli takaisin käyttöjärjestelmälle, eli main-funktion suoritus
päättyy.
Luku 0 ilmoittaa käyttöjärjestelmälle että ohjelman suoritus päättyi normaalisti.
11
Varatut sanat
• varattuja sanoja (32 kpl), joita ei saa käyttää mihinkään muuhun, kuin
niille varattuun tarkoitukseen.
auto
break
case
char
const
continue
default
do
12
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
Standarditunnukset
• esimerkiksi scanf ja printf, ovat standardi syöttö/tulostus -kirjastossa
(stdio.h) määriteltyjen operaatioiden nimiä
• voidaan määritellä uudelleen (ei suositella)
Käyttäjän määrittelemät tunnukset
• ohjelman käyttämien muistipaikkojen ja funktioiden nimeäminen
Tunnus voi koostua
• kirjaimista ( a - z ,A - Z)
• numeroista ( 0 - 9 ), mutta ei saa alkaa numerolla
• alaviivasta
13
Tunnuksen pituudelle ei ole määritelty maksimipituutta, mutta jotkut ANSI Ckääntäjät saattavat pitää kahta tunnusta samana elleivät ne eroa mitenkään
31ensimmäisen merkin osalta.
• Tunnukset kannattaa nimetä kuvaavasti, jolloin sen merkitys on helpompi
tajuta.
• Jos tunnus koostuu kahdesta tai useammasta sanasta voidaan lukemista
helpotta kirjoittamalla esim.
hintaEuroina tai
hinta_euroina
• Liikaa toisiaan muistuttavia tunnusten nimiä kannatta välttää, ei kannata
määritellä tunnuksia suuri ja SUURI
• C-kääntäjä tekee eron isojen ja pienten kirjainten välillä!
14
Muuttujien määrittelyt
Muuttuja on muistielementti, joka tallettaa ohjelman käsittelemää syöttö- ja
tulostustietoa sekä välituloksia. Muuttujan määrittely kertoo:
• talletetun tiedon tyypin
• talletukseen käytetyn muistielementin nimen
int vuosi;/*kokonaislukumuuttuja nimeltä vuosi */
char kirjain_1, kirjain_2, kirjain_3; /*kolme kirjainta*/
doub¬le kilometrit;
Muuttujien, vakioiden, funktioiden ja tyyppien niminä käytetään ohjelmoijan
määrittelemiä tunnuksia.
Kaikki C-ohjelmassa käytettävät muuttujat on määriteltävä!
15
Tietotyypit
C-kielen etukäteen määritellyt standarditietotyypit ovat
• kokonaisluvut:
• long
• int
• short
• byte
• reaaliluvut
• double
• float
• merkkitieto
• char
• totuusarvot (c99->) tarvitaan stdbool.h tiedostoa
• bool
16
Kaikki C-kielen numeeriset vakiot ovat positiivisia kokonaislukuja.
Negatiivisten lukujen "-" -merkki tulkitaan operaattoriksi (ei luvun osaksi),
joka muuttaa positiivisen luvun negatiiviseksi.
tietotyyppi int
int -tyyppiseen muistipaikkaan voidaan tallettaa kokonaislukuja.
ANSI C määrittelee tyypin int koon siten, että sen täytyy kyetä tallettamaan
vähintään arvoja väliltä -32767 ... 32767.
mahdolliset aritmeettiset operaatiot
• +, -, *, / ja % -operaatiot
• == lukujen vertailu
17
tietotyyppi double
Tietotyyppi double kykenee tallettamaan reaalilukuja
kokonais- ja desimaaliosa erotetaan toisistaan pisteellä ( 32.99 )
mahdolliset aritmeettiset operaatiot
• +, -, *, / -operaatiot
• == lukujen vertailu
double -tyypin luvut voidaan esittää myös käyttäen tieteellistä notaatiota
(yleensä hyvin pienten ja hyvin suurten arvojen esittämisessä).
1.23e5 tai 1.23 E5, jossa e tai E tulkitaan luvuksi 10, jota korotetaan potenssiin
5.
18
Tyyppi double kykenee tallettamaan vain pienen osan kaikista reaaliluvuista,
koska muistipaikoilla on rajallinen koko. Esimerkiksi lausekkeen 2.1 - 1.1 arvo
ei välttämättä ole 1.0.
Tietotyyppi char
Tyyppi char esittää yksittäisen merkin arvon.
Yksittäinen merkki esitetään ohjelmakoodissa heittomerkkien sisällä ('A', '1' ,
'&', '.' , ...)
Kullekin merkille on sovittu numeerinen arvo, tavallisimmin on käytössä ns.
ASCII-koodi (American Standard Code for Information Interchange).
char-tyypin tietoja voidaan verrata ja tiedoille voidaan suorittaa myös
aritmeettisia operaatioita.
19
Suoritettavat lauseet
Suoritettavat lauseet sijaitsevat ohjelmakoodissa määrittelyiden jälkeen.
• Suoritettava lause päättyy puolipisteeseen (;).
Ohjelmalle suoritettavat operaatiot
1. käännetään konekielelle
2. ladataan muistiin
3. suoritetaan
20
Sijoituslauseet
Sijoituslause tallettaa käsittelyn tuloksen muuttujaan.
• C:n sijoitusoperaattorina käytetään = -merkkiä.
• Sijoituslause on muotoa:
muuttuja = lauseke;
Esimerkiksi:
euro = MK_EUROINA * mk;
Muuttujan euro entinen arvo tuhoutuu ja tilalle talletetaan lausekkeen
MK_EUROINA * mk tulos.
21
• C:ssä voidaan samaa muuttujaa käyttää lausekkeen molemmissa puoliskoissa yhtä aikaa.
pankkitili = pankkitili - otto;
22
Syöttö- ja tulostusoperaatiot ( I/O)
Ohjelmalle välitetään tietoa syöttö-operaatioiden avulla ja ohjelmasta
välitetään tietoja tulostusoperaatioiden avulla.
C-kielessä ei ole itsessään valmiita syöttö- tai tulostusoperaatioita, vaan
käytetään kirjastofunktioita.
Useimmat C-kielen syöttö- ja tulostusfunktiot käyttävät puskurointia.
Tiedot kerätään väliaikaiseen muistialueeseen (puskuri). Tieto välitetään
lukufunktiolle, kun käyttäjä on painanut returnia.
C-kieli käyttää ns. virtoja (stream, vuo) esittämään tietoa, joka siirtyy
ohjelmaan tai ohjelmasta ulos.
23
Ennalta määriteltyjä standardeja tietovirtoja ovat:
Virran nimi
stdin
stdout
stdprn
stdaux
stderr
kuvaus
syöttövirta
tulostusvirta
tulostinvirta
oheislaitetulostus
virhevirta
laite
näppäimistö
näyttö
rinnakkaisportti
sarjaportti
näyttö
Standardivirrat avataan automaattisesti ohjelmaa suoritettaessa (vrt. Java).
Tietoja voidaan lukea myös puskuroimattomasti, jolloin käyttäjän antamat
yksittäiset merkit ovat ohjelman käytettävissä heti merkkien syöttämisen
jälkeen.
24
Tavallisimmin käytetyt I/O-funktiot toimitetaan C:n standardikirjastojen
mukana ja saadaan käyttöön esikääntäjän direktiivillä
#include <stdio.h>
25
Tietojen tulostaminen
Yksittäisen merkin tulostaminen tapahtuu funktiolla:
char merkki = 'A';
putchar ( merkki );
26
Muotoileva tulostus; printf
printf-funktio kykenee muotoilemaan tulostusta käyttäjän haluamalla tavalla.
funktion
nimi
funktion argumentit (parametrit )
printf ("Pankkitilin saldo on %f markkaa.\n" , pankkitili);
formaattimerkkijono
27
tulostuslista
Funktion printf kutsu koostuu
• funktion nimestä
• suluissa kirjoitetuista funktion argumenteista.
28
Funktion printf argumentit ovat
• formaatti-merkkijono lainausmerkeissä
• tulostuslista; muuttuja pankkitili
Jos muuttujalla pankkitili on arvo 55999.99 niin kuvaruudulle tulostuisi
Pankkitilin saldo on 55999.99 markkaa.
ennen tulostusta muotoilumääre %f tai %lf korvataan tulostuslistan
muuttujan pankkitili sisällöllä.
Muotoilumääre ilmaisee missä muodossa muuttujien arvot tulostetaan.
Muotoilumääre alkaa aina %-merkillä.
29
Jokaiselle tietotyypille on oma muotoilumääreensä esim.
muotoilumääre
%d
%f
%lf
%c
%s
tyyppi
käyttö funktiossa
int
double
double
char
merkkijono
printf / scanf
printf
printf / scanf
printf / scanf
printf / scanf
Huomatkaa että %d ei ole reaalilukujen tulostamiseen tarkoitettu muotoilumääre!
30
Tulostettavan muuttujan arvo tulostuu muotoilumääreen paikalle siten, että
varataan tilaa juuri sen verran kuin tarvitaan.
Haluttaessa voidaan tulostuskentän leveyteen vaikuttaa kirjoittamalla %merkin ja kirjainkoodin väliin kokonaisluku, joka ilmaisee vähimmäistilan,
joka varataan tulostettavalle tiedolle.
Esimerkiksi %8d varaa kahdeksan merkkiä tilaa kokonaisluvun tulostusta
varten. Tulostettava tieto kirjoitetaan tulostuskentän oikeaan laitaan.
Jos halutaan sijoittaa tulostettava tieto kentän vasempaan reunaan käytetään ""- merkkiä %-merkin ja kentän koon välissä, esim. %-8d.
Reaalilukujen desimaalit tulostetaan oletusarvoisesti järjestelmän määräämällä
tarkkuudella.
31
Haluttaessa voidaan tarkkuutta rajoittaa kirjoittamalla tulostuskentän
leveysmääreen jälkeen piste ja kokonaisluku, jolla ilmaistaan tulostettavien
desimaalien määrä.
Esimerkiksi
printf ("Pankkitilin saldo on %7.1f markkaa.\n" , pankkitili);
tulostaisi
Pankkitilin saldo on 55999.9 markkaa.
32
Desimaalit pyöristetään tulostuksessa, jos tulostuksen muotoilussa käytetään
desimaalien määrää kuvaavaa kenttää. Tämä ei kuitenkaan muuta pysyvästi
käsiteltävää tulostettavaa tietoa.
Tulostuskentän leveysosa voidaan jättää pois ja kuitenkin tulostettavien
desimaalien määrää voidaan rajata esim.
printf("Pankkitilin saldo on %.2lf euroa.\n", pankkitili);
Formaattirivi sisältää myös tulostuksenohjausmerkin “\n” (rivinvaihto). Kaikki
C-kielen ohjauskomennot alkavat aina "\"-merkillä.
Samalla printf-lauseella voidaan tulostaa useamman muuttujan arvo.
Muotoilumääreiden paikalle sijoitetaan perässä tulevien muuttujien sisällöt
siinä järjestyksessä kuin ne on tulostuslistaan kirjoitettu.
33
printf("%d + %d = %d\n", luku1, luku2, summa);
jos luku1, luku2 ja summa ovat int-tyypin muuttujia ja niillä on arvot.
luku1 = 10;
luku2 = 19;
summa = 29;
Ohjelma tulostaisi:
10 + 19 = 29
34
printf-lauseesta voi myös puuttua tulostuslista:
println("Tässäpä on kaksi\nriviä tekstiä.\n");
Tulostaisi
Tässäpä on kaksi
riviä tekstiä.
35
Muita ohjausmerkkejä ovat:
Koodi
\a
\b
\r
\f
\n
\t
\v
\\
\0
\"
\'
\?
36
Määrittely
äänimerkki (alarm)
askelpalautin
palautus saman rivin alkuun
sivunvaihto
rivinvaihto
vaakatabulaattori
pystytabulaattori
kenoviiva
null-arvo
lainausmerkki
heittomerkki
kysymysmerkki
Tiedon lukeminen
C-kielestä löytyy useita funktioita, joiden avulla voidaan lukea tietoja
ohjelman käyttöön.
Tavallisimmin tietoja luetaan näppäimistöltä.
• luetaan merkki kerralla
• luetaan rivi kerralla
Kaikki lukeminen tapahtuu merkkitietona, muunnos muuttujan käyttämäksi
tietotyypiksi tapahtuu lukuvaiheessa.
37
Puskuroitu lukeminen
Yksittäisten merkkien lukeminen funktiolla getchar()
char mki;
mki = getchar();
• Palauttaa näppäimistöltä syötetyn yksittäisen merkin.
• Käyttää puskurointia.
• Ei tarvitse argumentteja.
38
Muotoiltu lukeminen, scanf
Funktiolla scanf luetaan formatoidusti standardi-inputvirrasta, joka on
tyypillisesti näppäimistö.
scanf("%lf", &palkka);
funktio scanf -kopioi näppäimistöltä syötetyn tiedon palkka -muuttujaan.
• %lf kertoo minkä tyyppistä tietoa luetaan (tässä tapauksessa reaaliluku).
• &-merkki on ns. osoiteoperaattori. scanf -funktiolle kerrotaan muuttujan
palkka osoite, jonne luettava tieto talletetaan reaalilukuna.
• scanf odottaa luettavaa tietoa ja <return>-näppäimen painallusta.
39
• tietoa voidaan korjata syöttövaiheessa, jos ei ole ehditty painaa <return>näppäintä.
• scanf palauttaa tiedon siitä kuinka monta merkkiä se pystyi lukemaan
näppäimistöltä virheettömästi.
• lukuvirheen sattuessa puskuriin jää lukematon tieto talteen, puskuri
voidaan tyhjentää funktiolla fflush(stdin);
40
Useamman tiedon lukeminen yhdellä scanf-funktiolla tapahtuu seuraavasti:
int maara;
char merkki;
double palkka;
printf("Anna yksi kokonaisluku, merkki ja reaaliluku");
scanf ("%d%c%lf", &maara, &merkki, & palkka);
Käyttäjä voi syöttää pyydetyt tiedot samalla rivillä välilyönneillä erotettuna tai
jokaisen tiedon omalla rivillä. Esimerkiksi
1 A 1200.50<return>
tai
1<return>
A<return>
1200.50<return>
41
Jos edellinen lukufunktio kirjoitetaan esimerkiksi näin:
scanf("%d,%c,%lf", &maara, &merkki, &palkka);
Odottaa ohjelma, että syötetävät tiedot erotetaan toisistaan pilkuilla:
1, A, 1200.50<return>
Pilkun paikalla voi käyttää vaikka kirjainta a, jolloin lukeminen tulkitsee a:n
erottimeksi eikä lue sitä muuttujien sisällöksi.
scanf("%da%ca%lf", &maara, &merkki, &palkka);
1aAa1200.50<return>
42
Aritmeettiset operaatiot
operaattorit:
• +, -, *, / ; sekä int- että double-tyypeille
• % -operaattori (jakojäännös ) vain int-tyypille
43
Lausekkeen tyypin määräytyminen
Lausekkeen tyyppi määräytyy sen operandien perusteella seuraavasti:
int operaattori int
--> lausekkeen tyyppi int
double operaattori int
--> lausekkeen tyyppi double
int operaattori double
--> lausekkeen tyyppi double
double operaattori double --> lausekkeen tyyppi double
44
Aritmeettisten lausekkeiden laskentajärjestys
1. Ensin sulut, sisältä ulos
2. Operaattoreiden sidontajärjestyksen mukaan
a) unaari +. b) *, /, %
c) binaarit vasemmalta oikealle eli 3 + 4 - 1 on (3 + 4) - 1
45