C++-ohjelmoinnin aloittaminen
Tiedostojen käsittely
Vertaillaan tiedostojen käsittelyä Pythonilla ja C++:lla. Seuraavissa esimerkeissä lasketaan tiedostossa olevien kokonaislukujen summa. Jokaisen luvun tulee olla omalla rivillään, eikä tyhjiä rivejä saa olla.
Python
def main(): tiedoston_nimi = input("Syötä tiedoston nimi: ") try: tiedosto_olio = open(tiedoston_nimi, "r") summa = 0 for rivi in tiedosto_olio: summa += int(rivi) tiedosto_olio.close() print("Lukujen summa: ", summa) except IOError: print("Virhe tiedoston avaamisessa.") except ValueError: print("Virhe tiedoston rivillä") main()
C++
#include <iostream> #include <fstream> // Tiedostojen käsittely #include <string> using namespace std; int main() { string tiedoston_nimi = ""; cout << "Syota tiedoston nimi: "; getline(cin, tiedoston_nimi); // Yritetään avata tiedosto ifstream tiedosto_olio(tiedoston_nimi); if (!tiedosto_olio) { cout << "Virhe tiedoston avaamisessa." << endl; return 0; } // Tiedoston avaaminen onnistui int summa = 0; string rivi; while (getline(tiedosto_olio, rivi)) { summa += stoi(rivi); } tiedosto_olio.close(); cout << "Lukujen summa: " << summa << endl; }
Ohjelmat eivät aivan täysin toimi samalla tavalla. C++-esimerkissä tiedostosta luettu rivi muunnetaan kokonaisluvuksi stoi-funktiolla. Se hyväksyy kelvollisen lukualun, vaikka rivin lopussa olisi ylimääräisiä merkkejä. Jos rivin alussa ei ole kokonaisluvuksi kelpaavaa tekstiä tai luku on liian suuri, stoi aiheuttaa poikkeuksen. Poikkeusten käsittelyyn palataan myöhemmillä ohjelmointikursseilla.
Tiedoston lukeminen ja kirjoittaminen
C++:ssa tiedostojen käsittely etenee yleensä näin:
- Ota käyttöön
<fstream>-kirjasto, joka sisältää tiedostojen käsittelyyn tarvittavat tietotyypit. - Määrittele lukemista varten
ifstream-olio tai kirjoittamista vartenofstream-olio. Anna käsiteltävän tiedoston nimi konstruktorille. - Tarkista tiedoston avaamisen onnistuminen käyttämällä tiedosto-oliota
if-rakenteen ehtona. Onnistunut virta evaluoituu todeksi. - Tiedostoa on usein helppo lukea silmukassa rivi kerrallaan merkkijonomuuttujaan ja käsitellä luettua riviä sen jälkeen.
- Sulje tiedosto
close-metodilla, kun olet valmis. Sulkeminen vapauttaa tiedoston ja varmistaa kirjoitettaessa, että tiedot viimeistellään.
ifstream-oliosta voidaan lukea myös >>-operaattorilla samaan tapaan kuin cin-tietovirrasta. Tiedostoon kirjoitetaan ofstream-oliolla ja <<-operaattorilla samaan tapaan kuin näytölle tulostetaan cout-virralla.
Tietovirrat
Tietovirta (stream) on yleisnimitys muuttujalle, jonka avulla käsitellään oheislaitteita, kuten näppäimistöä, näyttöä tai tiedostoa. C++:ssa oheislaitteiden käsittely on toteutettu tietovirtojen avulla. Syötevirtoja käsitellään samalla tavalla keskenään, samoin tulostusvirtoja. Esimerkiksi cin ja ifstream-oliot ovat syötevirtoja, kun taas cout ja ofstream-oliot ovat tulostusvirtoja.
Tämä helpottaa ohjelmointia: samaa käsittelytapaa voidaan soveltaa useaan käyttötarkoitukseen.
Hyödyllisiä tietovirtaoperaatioita
Tulostaminen operaattorilla <<
Tulostusvirtaan voidaan kirjoittaa tietoa tulostusoperaattorilla:
cout << "Tulostettava teksti";
tulostusvirta << tulostettava;
Lukeminen operaattorilla >>
Syötevirrasta voidaan lukea tunnetun tyyppinen tieto suoraan kyseistä tyyppiä olevaan muuttujaan:
int luku = 0; cin >> luku; syotevirta >> tallennusmuuttuja;
Rivin lukeminen getline-funktiolla
getline(syotevirta, rivi) lukee syötevirrasta tekstirivin ja tallentaa sen merkkijonomuuttujaan. Kolmannella parametrilla voi antaa char-tyyppisen erotinmerkin. Tällöin lukeminen jatkuu seuraavaan erotinmerkkiin asti.
string tekstirivi = ""; getline(cin, tekstirivi); // Lukee yhden rivin getline(tiedosto_olio, tekstirivi, ':'); // Lukee kaksoispisteeseen asti
Yhden merkin lukeminen
syotevirta.get(merkki) lukee virrasta yhden merkin char-muuttujaan:
// Tiedoston voi lukea läpi merkki kerrallaan char luettu_merkki; while (tiedosto_olio.get(luettu_merkki)) { cout << "Merkki: " << luettu_merkki << endl; }
Tietovirran tilan tarkistaminen
Tietovirtaa voi käyttää ehtona if- tai while-rakenteessa. Tällöin se tulkitaan totuusarvoksi: virta on tosi, kun se on kunnossa, ja epätosi, jos operaatio epäonnistui tai tiedosto on luettu loppuun.
ifstream tiedosto_olio("tiedosto.txt"); if (!tiedosto_olio) { // Avaaminen epäonnistui cout << "Virhe!" << endl; return 0; } // Avaaminen onnistui, käsitellään tiedostoa tiedosto_olio.close();
Myös tietovirtaoperaation voi kirjoittaa suoraan ehdoksi. Esimerkiksi silmukka lukee rivejä niin kauan kuin getline onnistuu:
while (getline(tiedosto_olio, rivi)) { // Silmukkaan tullaan, jos rivin lukeminen onnistui } // Silmukka päättyy, kun uutta riviä ei saada luettua
Kun tietovirtaan kohdistuva operaatio suoritetaan, sen paluuarvona on kyseinen tietovirta. Jos paluuarvo on if- tai while-rakenteen ehto, kääntäjä muuntaa sen totuusarvoksi operaation onnistumisen perusteella.
Tämän opintojakson tehtävät ratkaiset yksinkertaisimmin testaamalla tietovirtaoperaation onnistumisen suoraan if- tai while-ehdossa.