Pelejä ohjelmoitaessa tallennetaan pelitiedot usein tiedostoon, josta ne ladataan käyttöön. PHP:ä ohjelmoijat tietävätkin file funktion, joka tekee tiedoston riveistä taulukon. Samaten funktio explode on useimmille tuttu. Se "räjäyttää" annetun merkkijonon annettujen katkaisumerkkien kohdalta osiin. Tähän koodivinkkiin olen tehnyt vastaavat toteutukset C++ kielellä.
#include "funktiot.hpp"
/**
* Lataa muistiin tiedoston rivit
* palauttaa vektorin, jossa jokainen tiedoston rivi on oma solunsa
* heittää virheen, jos tiedostoa ei löydy tai se ei aukea
*/
std::vector <std::string> file(std::string nimi){
std::vector <std::string> tmp_rivit;
std::string tmp;
std::ifstream sisaan(nimi.c_str());
if(!sisaan){
throw std::logic_error("Tiedostoa " + nimi + "ei ole, tai se ei aukea");
}
while(sisaan){
getline(sisaan, tmp);
tmp_rivit.push_back(tmp);
}
sisaan.close();
return tmp_rivit;
}
/**
* Purkaa annetun rivin osiin, jossa käyttäjä voi itse päättää erottimen
* Heittää virheen, jos annettua erotinta ei löydy
*/
std::vector<std::string> explode(std::string erotin, std::string rivi){
std::vector <std::string> tmp_solut;
std::string temppi = "";
while(rivi.length()){
std::string::size_type pos = rivi.find(erotin, 0);
if (pos == std::string::npos){
throw std::logic_error("Rivi ei tue " + erotin + " erotinta");
}
temppi = rivi.substr(0, pos);
rivi.erase(0, pos+1);
tmp_solut.push_back(temppi);
}
return tmp_solut;
}main.cpp
#include <iostream>
#include <vector>
#include <stdexcept>
#include "funktiot.hpp"
std::vector <std::string> Rivit;
std::vector <std::string> Solut;
int main(){
try{
Rivit = file("tiedot.txt");
}catch(std::exception &virhe){
std::cout << virhe.what() << std::endl;
}
for(unsigned int a = 0; a < Rivit.size(); a++){
try{
Solut = explode("|", Rivit[a]);
for(unsigned int b = 0; b < Solut.size(); b++){
std::cout << Solut[b] << " ";
}
std::cout << std::endl;
}catch(std::exception &virhe){
std::cout << virhe.what() << std::endl;
}
}
return EXIT_SUCCESS;
}tiedot.txt
Juha|Helsinki|30.5|13 Pekka|Vantaa|15.32|4 Janne|Sipoo|28.57|8 Riikka|Tuusula|26.37|13
File-funktio laittaa loppuun ylimääräisen tyhjän rivin. While-silmukan ehdossa pitäisi yrittää ensin lukea merkki ja sitten vasta tarkistaa, onko tiedosto loppu:
while (sisaan.peek(), (sisaan.good() && !sisaan.eof()))
Explode-funktiossa on ilmiselvä virhe: jos rivi ei pääty erotinmerkkiin, koodi heittää poikkeuksen. Muutenkin on outoa käytöstä, että erotinmerkitön rivi aiheuttaisi virheen. Järkevämmin funktion silmukka menisi näin:
while (true) {
std::string::size_type pos = rivi.find(erotin, 0);
if (pos == std::string::npos) {
tmp_solut.push_back(rivi);
return tmp_solut;
}
tmp_solut.push_back(rivi.substr(0, pos));
rivi.erase(0, pos + 1);
}Turhasta apumuuttujastakin päästiin samalla eroon.
Kaiken kukkuraksi vinkistä puuttuu funktiot.hpp ja ainakin GCC:n Linux-version mukaan useita include-rivejä (string, fstream, cstdlib).
Aihe on jo aika vanha, joten et voi enää vastata siihen.