Tie koodariksi

C++-ohjelmointi

Luku 13: Standardikirjasto

Yleiskuva

C++:n standardikirjasto sisältää luokkia ja funktioita, joita voi käyttää ohjelmoinnin apuna. Standardikirjasto muodostuu osista, joista jokaisella on tietty otsikkotiedosto.

Otsikkotiedosto otetaan mukaan koodiin #include-direktiivin avulla. Olemme käyttäneet jo koodin alussa seuraavaa riviä, joka ottaa mukaan otsikkotiedoston <iostream>:

#include <iostream>
Tässä tiedostossa on määritelty esimerkiksi virrat cin ja cout, joilla avulla voi lukea ja tulostaa tietoa.

C++:n standardikirjastossa on sekä C-kielestä periytyviä otsikkotiedostoja, joiden alussa on kirjain c (kuten <cmath> ja <ctime>), että C++:n omia otsikkotiedostoja (kuten <random> ja <vector>). Tämä ja kaksi seuraavaa lukua käsittelevät joitakin standardikirjaston osia.

Hyvä tapa tutustua standardikirjaston sisältöön on hyödyntää netissä olevia referenssejä. Hyödyllisiä lähteitä ovat cplusplus.com ja cppreference.com.

Nimiavaruus std

Kaikki C++:n standardikirjaston osat kuuluvat nimiavaruuteen std, minkä vuoksi olemme käyttäneet koodin alussa seuraavaa komentoa, joka sallii niiden käyttämisen suoraan:
using namespace std;
Tämän jälkeen voimme esimerkiksi tulostaa tekstiä näin:
cout << "Moikka!\n";
Jos using-riviä ei ole, meidän täytyy kirjoittaa std:: jokaisen nimen alkuun:
std::cout << "Moikka!\n";
Tällöin standardikirjaston käyttäminen on hankalampaa, mutta toisaalta hyvänä puolena standardikirjaston nimet eivät sekaannu itse määrittelemiimme nimiin.

Matematiikka

#include <cmath>
Matemaattisia funktioita ovat esimerkiksi seuraavat: Näiden funktioiden parametrit ja palautusarvot ovat liukulukuja. Seuraava koodi esittelee funktioiden käyttöä:
cout << pow(3,4) << "\n"; // 81
cout << sqrt(5) << "\n"; // 2.23607
cout << sin(1) << "\n"; // 0.841471
cout << cos(1) << "\n"; // 0.540302
cout << tan(1) << "\n"; // 1.55741
cout << exp(3) << "\n"; // 20.0855
cout << log(7) << "\n"; // 1.94591
cout << floor(3.1) << "\n"; // 3
cout << ceil(3.1) << "\n"; // 4

Satunnaisluvut

#include <random>
Seuraava koodi luo satunnaislukugeneraattorin g sekä jakauman d, joka antaa satunnaisia kokonaislukuja väliltä 1...6. Generaattorina on Mersenne Twister (mt19937), joka on käytännössä hyvä ja tehokas tapa luoda satunnaislukuja. Tämän jälkeen koodi simuloi 10 kertaa nopan heittämistä.
mt19937 g(random_device{}());
uniform_int_distribution<int> d(1,6);
for (int i = 1; i <= 10; i++) {
    cout << d(g) << " ";
}
cout << "\n";
Koodin tulostus voi olla seuraava:
3 1 3 2 6 4 6 3 5 4

Generaattorin siemenluku (seed value) määrittää sen alkutilan. Yllä olevassa koodissa siemenlukuna on järjestelmän satunnaisuuslähteen (random_device) antama arvo, jolloin koodi tuottaa aina eri satunnaisluvut. Kuitenkin jos kokeen tulee olla toistettavissa, siemenluvuksi voi antaa jonkin vakion, kuten luvun 1337:

mt19937 g(1337);
Tällöin generaattori tuottaa aina saman lukujonon:
2 4 1 2 2 4 3 1 2 2

Ajan mittaus

#include <chrono>
Seuraava ohjelma laskee alkulukujen määrän välillä 2...106 ja ilmoittaa laskemiseen kuluneen ajan.
auto alku = chrono::system_clock::now();
int tulos = 0;
for (int i = 2; i <= 1000000; i++) {
    bool ok = true;
    for (int j = 2; j*j <= i; j++) {
        if (i%j == 0) {ok = false; break;}
    }
    if (ok) tulos++;
}
auto loppu = chrono::system_clock::now();
chrono::duration<double> aika = loppu-alku;
cout << "alkulukujen määrä: " << tulos << "\n";
cout << "laskenta-aika: " << aika.count() << " s\n";
Ohjelman tulostus voi olla seuraava:
alkulukujen määrä: 78498
laskenta-aika: 0.358783 s

Säännölliset lausekkeet

#include <regex>
Säännöllinen lauseke (regular expression) on merkkijono, joka kuvaa halutun merkkijonon formaatin. Esimerkiksi lauseke [a-z]{5,8} vastaa merkkijonoja, joissa on 5–8 merkkiä väliltä a–z.

Funktion regex_match avulla voi tarkastaa, täsmääkö säännöllinen lauseke merkkijonoon. Seuraava koodi esittelee funktion käyttämistä:

regex r("[a-z]{5,8}");
cout << regex_match("apina",r) << "\n"; // 1
cout << regex_match("banaani",r) << "\n"; // 1
cout << regex_match("cembalo",r) << "\n"; // 1
cout << regex_match("lol",r) << "\n"; // 0
cout << regex_match("12345",r) << "\n"; // 0