Radnom sor beolvasása ifstream-ről
2004-11-30T00:29:18+01:00
2004-12-01T16:24:14+01:00
2022-07-20T02:01:38+02:00
Zipi
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;

ifstream wordfile(WORDFILE, ios::in);
if(!wordfile)
{
cout << "Hiba a szofile megnyitasa soran!";
}
else
{
while(!wordfile.eof())
{
wordfile.getline(cbuf,y,'\\\\n');
n++;
}
cout<< "1. Cbuf tartalma: "<< cbuf << "\\\\n";
wordfile.seekg(0,ios::beg);
srand((unsigned)time(NULL)*(unsigned)time(NULL));
n=rand()%n;
for(i=0;i<n;i++)
{
wordfile.getline(cbuf,y,'\\\\n');
}
}
wordfile.close();
cout << "2. Cbuf tartalma: " << cbuf;
}

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ó
Mutasd a teljes hozzászólást!
Az jutott eszembe, hogy az is lehet, hogy az eof bit beállítva marad a streamben. Lehet, hogy ezért sikertelen az összes olvasási kísérlet.
wordfile.clear();
VG
Mutasd a teljes hozzászólást!

  • Linuxban dolgozol?
    A beolvasandó fájlt linuxban készitetted?, akkor nincs a sorvégeken 0x0d, hanem 0x0a lehet.
    Mutasd a teljes hozzászólást!
  • Helló!

    Három fő probléma van a kóddal.

    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.

    VG
    Mutasd a teljes hozzászólást!
  • 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.
    Mutasd a teljes hozzászólást!
  • 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...

    VG
    Mutasd a teljes hozzászólást!
  • 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
    Mutasd a teljes hozzászólást!
  • 1.
    cout << "2. Cbuf tartalma: " << cbuf << flush(); vagy '\\\\n';

    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.
    Mutasd a teljes hozzászólást!
  • 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
    Mutasd a teljes hozzászólást!
  • Lehet, hogy hülyeséget írok, de úgy emlékszem, hogy van valami rewind utasítás.

    Ezt nem lehet használni ilyen esetekben?
    Pl.
    rewind(wordfile);

    Ennek vissza kéne állítani a file mutatót a file elejére.
    Persze ha rosszul emlékszem a nevére akkor nem.
    Vagy
    wordfile.rewind;
    De most tényleg csak találgattam.
    Mutasd a teljes hozzászólást!
  • Igen az még a jó öreg C féle FILE pointernél volt.
    Mutasd a teljes hozzászólást!
  • Vidd at a progit winre és vc++ vagy cbuilderrel vagy borland 5.2-el vagy mással nézd meg, nincs más ötletem.
    Talán a linuxos lib nem jó.
    Mutasd a teljes hozzászólást!
  • Az jutott eszembe, hogy az is lehet, hogy az eof bit beállítva marad a streamben. Lehet, hogy ezért sikertelen az összes olvasási kísérlet.
    wordfile.clear();
    VG
    Mutasd a teljes hozzászólást!
  • #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { FILE *f; char sor[255]; char darab = 0; char darab2 = 0; /* Megkiséreljük megnyitni a file-t */ if ((f = fopen("be.txt", "r")) == NULL) printf("Sikertelen file megnyitás"); /* Ha sikerült megszámoljuk hány sor van */ else { while (fgets(sor, 255, f)) darab++; /* Kiválasztunk egyet véletlenszerűen */ randomize(); darab = random(darab) + 1; /* Beolvassuk a kiválasztott sort */ rewind(f); do { fgets(sor, 255, f); darab2++; }while (darab > darab2); printf(sor); fclose(f); } }


    Ez így nálam müködik.
    Persze ez csak a jó öreg C.
    Mutasd a teljes hozzászólást!
  • Ezaz végre működik Tényleg ez volt a gond, már rengeteget szívtam vele. Köszi a segítséget, ott a pont
    Mutasd a teljes hozzászólást!
abcd