2.4.2 Funktiokirjastot

C++-kieli tarjoaa runsaasti valmiita funktioita, joiden koodi on toimitettu kääntäjän mukana. Funktiot on koottu aihepiirien mukaisiin ohjelmaryhmiin ns. kirjastoiksi. Valmiita ohjelmia voi ja kannattaa käyttää; ensinnäkin ne säästävät aikaa (miksi suotta keksiä ruutia uudelleen) ja toiseksi ne luultavasti toimivat kohtuullisen virheettömästi, sillä niitä on kielen eri kehitysvaiheissa testattu runsaasti.

Käyttäjä voi sisällyttää kirjastojen sisältämiä funktioita omiin ohjelmiinsa, kunhan huolehtii siitä, että kirjastojen sisältämät funktiot on asianmukaisesti esitelty ohjelmatekstissä (header-tiedostot), ja että ohjelmalla on linkittämisvaiheessa tieto siitä, mistä hakemistosta kirjastofunktioiden koodit löytyvät.

Ohjelmankehityksestä voidaan erottaa kolme toisistaan eriävää vaihetta:
1. Ohjelmatekstin kirjoitus (editing). Tässä vaiheessa käyttäjä kirjoittaa C++-kielistä ohjelmakoodia ASCII-pohjaisella tekstieditorilla. Syntyvän tiedoston (tarkenne yleensä CPP) sisältö on vielä luettavissa (tekstimuodossa).
2. Ohjelmatekstin esikääntäminen (preprocessing) ja kääntäminen (compiling). Esikääntämisessä tekstimuotoiseen tiedostoon mm. lisätään ilmoitetuissa tiedostoissa sijaitseva C++-kielinen koodi (#include) ja korvataan vakiot niille määrätyillä arvoilla (#define). Kääntämisessä kukin C++-kielen lause muunnetaan sarjaksi konekielisiä käskyjä. Saatu konekielinen objektitiedosto, binääritiedosto (tarkenne OBJ), ei enää ole (ainakaan helposti) ihmisen tulkittavissa.
3. Linkkausvaiheessa (linking) yhdistetään mahdollisesti useampi objektitiedosto sekä aliohjelmakirjastoissa määriteltyjen olioiden (funktiot, muuttujat, vakiot) konekieliset koodit toisiinsa siten, että tuloksena on suorituskelpoinen ohjelma (tarkenne EXE).

Funktiokirjastojen sisältämät funktiot tulee esitellä ohjelmassa ennen niiden käyttöönottoa, jotta kääntäjä tietää, minkälaista syöttötietoa ko. funktiot tarvitsevat ja minkälaista tietoa ne kenties palauttavat.

Funktiot on esitelty aihepiireittäin ns. header-tiedostoissa (tarkenne H), jotka sisällytetään ohjelmatekstiin direktiivillä #include. Funktioiden esittelyjen lisäksi header-tiedostot sisältävät myös yleisiä aihepiiriin sisältyviä määrittelyjä, mm. tietotyyppien ja vakioiden määrittelyjä. Esimerkiksi tiedostossa iostream.h esitellään mm. syötössä ja tulostuksessa käytettävät cin ja cout, ja tiedostossa stdio.h mm. funktio printf.

2.4.2.1 Matemaattisia funktioita

Tiedosto math.h sisältää yleisimpien matemaattisten funktioiden esittelyt. Kirjastosta löytyvät mm. seuraavat funktiot:

double sin(double x);   // trigonometriset funktiot
double cos(double x);   //  (x radiaaneina)
double tan(double x);

double asin(double x);  // trigonometriset käänteisfunktiot
double acos(double x);  //  (tulos radiaaneina)
double atan(double x);
double atan2(double x, double y); // luvun x/y arkustangentti

double sinh(double x);  // hyperboliset funktiot
double cosh(double x);
double tanh(double x);

double exp(double x);   // eksponenttifunktio
double log(double x);   // luonnollinen logaritmi
double log10(double x); // 10-kantainen logaritmi

double fabs(double x);           // liukuluvun itseisarvo
double sqrt(double x);           // neliöjuuri
double pow(double x, double y);  // yleinen potenssifunktio
double fmod(double x, double y); // jakojäännös liukulukuna

double ceil(double x);  // kattofunktio (pyöristys ylöspäin)
double floor(double x); // lattiafunktio (pyöristys alaspäin)

Tästä nähdään, että esimerkiksi neliöjuuren laskevan funktion sqrt palauttama arvo on tyyppiä double, ja sen argumentin x tyyppi on myös double. Näin ollen omassa ohjelmassa voidaan kutsua funktiota sqrt huolehtimalla siitä, että se on asianmukaisesti esitelty liittämällä tiedosto math.h ohjelmatekstiin direktiivillä

#include <math.h>

Tämän jälkeen funktiota sqrt voidaan käyttää lausekkeissa, esim. laskettaessa suorakaiteen lävistäjän pituutta:

lavistaja = sqrt(sivu1*sivu1 + sivu2*sivu2);

Matemaattisten funktioiden tyypiksi on valittu double, jotta niiden laskentatarkkuus olisi siedettävä (noin 15 merkitsevää numeroa; tyypillä float vain noin 7 numeroa).

Huomaa, että itseisarvofunktiota fabs käytetään vain kaksoistarkkuuden liukuluvuille. Kokonaisluvuille vastaava funktio on abs ja pitkille kokonaisluvuille labs, jotka on esitelty tiedostossa stdlib.h. (Tosin useimmissa kääntäjissä abs ja labs ovat sekä math- että stdlib-kirjastoissa.)

2.4.2.2 Merkkien luokitusta ja muunnoksia

Tiedostossa ctype.h on esitelty funktioita, joilla voidaan testata, onko argumenttina annetulla merkillä jokin tietty ominaisuus. Paluuarvona on nolla, jos ominaisuutta ei ole, muuten jokin nollasta poikkeava arvo. Tällaisia ovat mm.

int isalnum(char c); // onko c alfanumeerinen (A-Z, a-z, 0-9)
int isalpha(char c); // onko c kirjain (A-Z, a-z)
int isdigit(char c); // onko c numero (0-9)
int isupper(char c); // onko c iso kirjain (A-Z)
int islower(char c); // onko c pieni kirjain (a-z)

int iscntrl(char c); // onko c kontrollimerkki (ASCII 0-31,127)
int isprint(char c); // onko c kirjoittuva merkki (ASCII 32-126)
int isgraph(char c); // onko c graafinen merkki (muu kirjoittuva
                     //                     merkki kuin välilyönti)
int ispunct(char c); // onko c välimerkki (kirjoittuva merkki, joka
                     //      ei ole alfanumeerinen eikä välilyönti)
int isspace(char c); // onko c tyhjän välin merkki (välilyönti, \f,
                     //                          \n, \r, \t tai \v)

Huomaa, että eo. funktiot eivät välttämättä toimi ASCII-taulukon jälkimmäisessä puoliskossa oleville merkeille (koodit 128-255).

Kirjastossa ctype on lisäksi kaksi muunnosfunktiota, joilla voidaan muuntaa pienet kirjaimet isoiksi kirjaimiksi, tai päinvastoin:

char toupper(char c); // muunnos isoiksi kirjaimiksi
char tolower(char c); // muunnos pieniksi kirjaimiksi

Jos merkki c ei ole kirjain, paluuarvona tulee sama merkki sellaisenaan.