A következő problémába ütköztem: még C-ben írtam egy olyat, hogy egy fileból kiolvas egy random sort. Úgy oldottam meg hogy beolvastam az összes sort egy ciklusban, majd a egy generált véletlen szám modulusát vettem a ciklus számlálóval(n). Utána egy újabb ciklusban n-ig olvastam egy bufferbe a sorokat amíg el nem értem n-ig. Frankón müködött is. Most átírtam az egészet C++-ba:
void newWord()
{
int n=0,i;
char cbuf[80];
streamsize y=999;
A probléma az hogy a 2. Cbuf-nál cbuf-ban egyszerűen semmi nem lesz. A 2. ciklusban semmit nem olvas bele, mintha a getline() nem reagálna arra hogy vissza tettem a mutatót a file elejére Mi lehet a gond??? Egyébként, g++ fordító
1. Az y változónak a buffer méretét kéne tárolnia, tehát 80-at, nem pedig 999-et. Az std::string a jó megoldás, ott nem kell vacakolni a mérettel.
2. ne a wordfile.eof()-ot vizsgáld a ciklusban, hanem a wordfile -t csak úgy, mert ha valamilyen file hiba következik be olvasás alatt, akkor így bennragadsz a ciklusban.
3. A megoldás: text módban megnyitott állományoknál a seekg abszolút címzéssel nem mindig működik jól a standard szerint. Abba jóldefiniáltan csak egy tellg() által visszaadott pozíciót tehetsz. Az elejére (a while elé):
streampos start_pos = wordfile.tellg();
és a seeknél
wordfile.seekg(start_pos);
+1. ptiszai kollégának is igaza van, egyszerűen ne írj delimitert a getline-ba, nem kötelező, és valszeg a jót rakja bele default.
Igen linuxban dolgozom, a filet nem linux alatt hoztam létre.
1. teljesen igazad van, de azért használtam delimteret, mert biztosított hogy minden sor rövidebb mint 80.
2. Köszi a tippet, de akkor hogyan lép ki a ciklusból, ha a wordfile-t vizsgálom?
3. a seekg() pedig működik, seekg() után kiirattam a tellg()-t és 0-t adott vissza.
Hmm. Linux alatt olvasol egy windows/dos-ból létrejött állományt? Sajna abban nem vagyok nagyon otthon, de esetleg megpróbálhatod bináris módban megnyitni, bár linux alatt asszem nincs különbség.
A streamet viszgálni a köv. módon lehet, megszámolom a sorokat:
int count_lines(const char * filename) {
ifstream file(filename);
string line;
int n = 0;
while(file) {
getline(file, line);++n;
};
if (!file.eof())
throw "I/O error";
return n-1;
};
Az ifstream változó bool-ként false ha bármi zűr van, eof, olvasási hiba, nem létező file, etc. A végén megnézem, hogy ez a zűr az eof volt-e vagy valami durvább. Ha nem eof, akkor hiba.
Nem tudom, hogy az utolsó sor végén van-e sorvége jel a file-ban, mert ott el lehet csúszni aszámolással egy kicsit. Az eof akkor állítódik be, ha olvasni próbálsz az állomány végéről, nem pedig akkor, amikor elérted azt...
Úgy látszik akkor, hogy nem a seekg-nél van a gond. Esetleg bezárni a file-t és újra megnyitni a második olvasáshoz? Egyébként a sorok számot pontosan adja vissza az első ciklus? Hányszor fut le a második ciklus? Esetleg írd ki az összes sort a második ciklusban, hátha kiderül valami...
Sorok számát pontosan adja vissza, a második ciklus véletlenszerű számszor fut le. Ha kiiratom a buffert a második ciklusban, akkor azt látom, hogy semmi nincs benne, tehát mintha nem olvasna bele semmit. Bezárom, újra megnyitom akkor ugyanez
2. ha nem jo az elso, akkor
for(i=0;i<n;i++)
{
wordfile.getline(cbuf,y,'\\\\n');
cout << wordfile.gcount() << '\\\\n';
}
mit ir ki?
Az utolso muvelet altal olvasott karakterek szamat kellene kiirnia.
1. flush() ha jól tudom streameknél nem használatos. '\\\\n'-nel ua.
2. mindig 0-át ír ki
Egyetlen megoldást találtam. Definiálok még egy ifstream-et és azon keresztül olvasom be, de ez bántja a programozói lelkemet Szóval ha getline-al elérem a file végét, utána bármit csinálok azzal a streammel nem hajlandó belőle többet olvasni. Beiktattam egy hibaellenőrzést az első ciklus után, ellenőrzőm wordfile.bad()-et és wordfile.fail()-t: eredmény semmi, nincs hiba. Kiprobáltam mi történik ha a 2. ciklusban getline() helyett get()-et használok. Végig -1-et olvasott be . Gondoltam egyet, mondom ellenőrzőm a ciklus minden egyes lefutásánál hogy éppen melyik pos-nál van a fileba: cout << "Pos: " << wordfile.tellg() << " Adat: " << wordfile.get() << "\\\\n";. Na és mit gondoltok mi történt a ciklus minden egyes lefutásakor a tellg() -1-et adott vissza Érdekes, nagyon érdekes, a for ciklus előtt ha kiíratom a tellg()-t akkor 0-át ad. Alkalmaztam egy trükköt, a for ciklusban az i=0 után wordfile.seekg(0,ios::beg)-et írtam, de ugyanúgy -1. Mintha meghalna a stream vagy nem tudom