Hei!
Olen melko aloittelija c++ kanssa vielä, eli ihan perushommat vaan onnistuu.. Tarkoitus olisi saada luettua tiedostoa rivi kerrallaan, tai tiedosto taulukkoon tyyliin php, ja jokainen rivi löytyisi sit omasta taulustaan. Tiedosto on muotoa
1:5 2:3 3:4 ...
Eli onko tällaiseen olemassa valmista funktiota?
Tiedoston lukeminen rivi kerrallaan:
#include <fstream> std::ifstream filu("foo.dat"); // Avataan tiedosto while(!filu.eof()) { // Niin kauan kun ei olla lopussa std::string rivi; getline(filu, rivi); // Luetaan rivi // Nyt sitten tehdään tuolle riville mitä halutaan } filu.close(); // Suljetaan tiedosto
Kiitoksia nopeasta vastauksesta:)
Edit: Kun yritän tulostaa tuon rivin sisällön lauseella
cout << filu << endl;
tulee tulokseksi joka riville sama "0x22fea4", eli missä mättää?
Ei tiedostoa niin käytetä. Rivi pitää lukea tiedostosta muuttujaan. Et voi tulostaa tietovirtaoliota, koska se ei ole itse tietoa vaan vain olio, joka lukee tietoa tiedostosta, kun sen käskee lukea.
Vaihtoehtosi ovat C:n stdio.h-otsikon lukufunktiot, joista kerrotaan myös Putkan C-opassarjassa, ja C++:n tietovirrat, jotka tapaavat olla omalla tavallaan kömpelöitä ja usein myös hitaita suurten tietomäärien kanssa. Taulukon joudut joko varaamaan itse dynaamisesti, mikä ei aloittelijalle ole kovin helppo tapa. Helpompana vaihtoehtona on C++:n vector-luokka.
Jotenkin tähän malliin siis esimerkiksi:
// C++:n lukufunktiot ja vektoriluokka #include <fstream> #include <vector> #include <limits> // Ohjelma käyttää näitä luokkia using std::ifstream; using std::vector; using std::ws; using std::numeric_limits; // Tiedoston sisältö tallennetaan tällaisiin tietueisiin struct t_lukupari { int a, b; }; // Vektori (eräänlainen taulukko), joka sisältää tietueitamme vector<t_lukupari> lukuparit; // Lukufunktio void lue_tiedosto(char * tiedostonimi) { // Apumuuttuja t_lukupari pari; // Tietovirta ja sen avaus ifstream virta(tiedostonimi); // Luetaan loppuun asti while (!virta.eof()) { try { virta >> pari.a; // Ensimmäinen luku virta.ignore(1); // Välimerkki virta >> pari.b; // Toinen luku virta >> ws; // Tyhjät pois lukuparit.push_back(pari); // Lisätään vektoriin } catch (...) { // Virhe lukemisessa, skipataan rivin loppuun asti eli niin monta merkkiä kuin suinkin on ennen rivinvaihtoa (\n) virta.ignore(numeric_limits<int>::max(), '\n'); } } }
Tämä menetelmä on kuitenkin virhealtis, koska esimerkiksi rivi, jolla on vain yksi luku, sotkee kaiken. C:n funktioista on esimerkki Putkan C-oppaassa. Kuvaamasi tiedostomuodon lukemisessa auttaa fscanf-funktio muotoilulla "%i:%i".
Minen kyllä ihan allekirjoita väitettä C++-streamien kömpelyydestä ja hitaudesta. Streameja voi muokata ja laajentaa melkein miten vaan. Ovat ne lähtökohtaisesti vähän C:n värkkejä hitaampia, kun ne on pakko toteuttaa C-kirjastofunktioiden päälle, mutta pienellä tuumaamisella ja kääntäjän optimointivipujen käytöllä nopeusero on usein varsin siedettävä. Ja muutoin streamit ovat kyllä sitten turvallisempia käyttää.
IO-hommat ovat ihan aikuisten oikeesti vaikeita. Yksi ongelma on siinä, kun yrittää miettiä, millaisista virhetilanteista vielä yritetään toipua ja miten. Jos esimerkiksi tässä tapauksessa jokin rivi on virheellinen, voidaanko mihinkään muuhunkaan luettuun tai vielä lukemattomaan dataan enää luottaa? Jos ei älyä, että virhe on yleensä virhe, tulee usein rakennelleeksi aivan liian hienoa ja itsessään virheellistä muka-toipumislogiikkaa.
Kun vielä ottaa huomioon, ettei streameissa ole virheraportointi exceptioneilla oletusarvoisesti päällä, olisin mukiloimassa edellisen esimerkin tähän malliin:
#include <fstream> #include <vector> struct lukupari { int a, b; lukupari(int a_, int b_) : a(a_), b(b_) {} }; std::vector<lukupari> lue_parit(char const *tiedostonimi) { std::ifstream tiedosto(tiedostonimi); std::noskipws(tiedosto); int a, b; char sep, lf; std::vector<lukupari> taulukko; while ((tiedosto >> a >> sep >> b >> lf) && sep == ':' && lf == '\n') taulukko.push_back(lukupari(a, b)); if (!tiedosto.eof()) throw "tiedostonluvussa meni jotakin vikaan\n"; return taulukko; }
Toivottavasti tuosta saisi tarpeeksi vinkkejä lukea manuaaleja ja kirjoja oikeasta kohdasta, vaikkei C++:n kanssa niin pitkällä vielä olisikaan.
Näitä kysellään verraten säännöllisesti... Voisi olla paikka vinkille/oppaalle. Jos jollakin osaavalla olisi aikaa.
(Itse osaan kyllä käyttää mutta ei ole kykyjä neuvoa, ja aikakin on usein kortilla)
Aihe on jo aika vanha, joten et voi enää vastata siihen.