» »

[c++]file read problem

[c++]file read problem

'FireSTORM' ::

mam en problem
in nevem kje sem zavozil
bom kar podal en delček kode ki me muči

fstream dat;
int neka_stevilja;
dat.clear();
dat.open("filename.ext",ios::in|ios::nocreate);
while(!dat.eof())
{
dat >> neka_stevilka;
// Tukaj pa pride prebiranje celotnih vrstic z dat.getline(char, "dolžina stringa");
// in še nadaljne funkcije ki jih aplikacija naj izvaja
}
dat.close();


v datoteki je pa zapisano tako
prvo pride zaporedna številka, kero uspešno preberem z dat >> neka_stevilka;
in potem nekaj 5 vrstic raznih besed in znakov
teh 5 vrstic tvori en podatek, ampak to je zdaj nepomembno
gre se za to ker po prebiranju iz datoteke, če je v datoteki samo en tak podatek
se pojavi naslednji problem
prebere se samo zaporedna številka
ostale vrstice so pa kar "izpuščene"...
oz. se char spremenljivkam nastavi prazna("") vrednost
če pa je več podatkov v dadoteki pa prebere vse normalno...razen zadnjega podatka

ok najprej sem ciljal na to zaporedno številko zato sem te številke iz datoteke pobrisal in tudi prebiranje te števike sem zakomentiral, kar ni rešilo ničesar

probal sem tudi prebiranje številke "posplošit" da bi jo prebral kot char
ampak t številko moram posredovat naslednji funkciji ki pa rabi int tip številke
ampak vseeno, prebrana je bila vseeno samo številka, nadaljne vrstice pa ne

no na drugi strani kode imam pa podobno funkcijo
ki pravtako prebira podatke iz datoteke, le da je datoteka drugačna in je obdelava podatkov drugačna, prebiranje je pa čisto enako in deluje popolnoma brezhibno

ostal sem čisto brez idej kaj bi še lahko blo...
če ma kdo kako idejo...i'm all ears
Those penguins.... They sure aint normal....

jan01 ::

Genetic ::

Dobro bi bilo ce bi videli se kodo, ki si jo ti zakomentiral (beres ostralih 5 vrstic z getline)

Glej, zapis v datoteki je taksen:

12
Vrstica1 bla bla
Vrstica2 bla bla
Vrstica3 bla bla
Vrstica4 bla bla
Vrstica5 bla bla

Z dat >> neka_stevilka preberes stevilko 12 in se postavis za to stevilko.
Potem beres z dat.getline do konca vrstice. Ampak ti si se vedno v vrstici, kjer je bila stevilka, v njej pa je ostal samo se newline znak. Kar dobis, ko zazenes dat.getline, je tisto, kar je med stevilko 12 in znakom za newline, to pa je empty string.

Gundolf ::

Problem je enostaven - nekaj narobe bereš v tisti zanki.
Potem - zakaj na datoteki na zeačetku kličeš clear, na koncu close in v zanki eof?
Še naprej - če želiš nekaj znakov ali vrstic ignorirati lahko uporabiš za to primerno funkcijo ignore.
In nazadnje, če želiš iz datoteke le brati uporabiš ifstream, pa mu ni treba nobenih parametrov (recimo in|nocreate) podajat.

Moja diagnoza je taka - ne veš kaj posamezne funkcije točno delajo in zato ne znaš pravilno uporabljat streamov. Najboljša rešitev je pa, da enkrat en dober tutorial na to temo daš skozi ali pa v kaki dobri knjigi predelaš poglavje, ki ima to čez.

Gundolf ::

Vcasih je bil zlo dober tutorial na cplus.about.com pa so se ga znebili. Ne vem zakaj. Samo opažam pa, da kar ti google najde na to temo je zelo pod nivojem. Sploh cplusplus.com je vir napačnih pristopov k programiranju v C++. Tako da morda je res najbolje reskirat neki cajta pa eno dobro knjigo mal pogledat.

Web archive od cplus.about.com tutoriala

Zgodovina sprememb…

  • spremenil: Gundolf ()

'FireSTORM' ::

am...
close je za while zanko...

ok ostali del kode po dat >> neka_stevilka;
dat.getline(ime,200);
dat.getline(opis,200);
// in tako vseh 5 vrstic, stem da ni vspovsod 200
// potem pa še kopiranje iz char v CString tip spremenljivke na tak način:
niz_ime.Format("%s", ime);
// in tako še za vse ostale
// pa je vseeno če potem gledam spremenljivko ime ali niz_ime
// obe sta prazni


vem da se ne postavim v naslednjo vrstico po dat >> neka_stevilka;
to mi je jasno...
ampak tudi če to zakomentiram ta dat >> neka_stevilka;
bi se morala ta začetna številka v datoteki skopirat v spremenljivko ime
in to tudi stori
in ker prebiram z getline se na koncu postavi v naslednjo vrstico
potem pride getline opis, in v spremenljivko opis bi moralo biti tisto kar bi jaz dejansko rad v spremenljivki ime
ampak ni, je prazna vrednost

Problem je enostaven - nekaj narobe bereš v tisti zanki.

ne res?

Potem - zakaj na datoteki na zeačetku kličeš clear, na koncu close in v zanki eof?

en del sem že odgovoril zgoraj
clear pa kličem zato ker sem tako naučen...če je napačno mi prosim povej pravilen način in bom to upošteval ;)

Še naprej - če želiš nekaj znakov ali vrstic ignorirati lahko uporabiš za to primerno funkcijo ignore.

bom upošteval, hvala

In nazadnje, če želiš iz datoteke le brati uporabiš ifstream, pa mu ni treba nobenih parametrov (recimo in|nocreate) podajat.

to sem že tudi slišal in ofstream za output v file...

in hvala za prekrasen vodič, si bom vzel čas in ga prebral...
morda pa zdaj lahko nehaš pljuvat po mojem (ne)znanju in mi dejansko poveš kaj bi lahko bilo narobe?

saj bi razumel če bi delal to prvič
ampak ker že mam podobno kodo na drugi strani te aplikacije in sem jo samo prekopiral in popravil nekaj spremenljivk princip je pa enak in tam deluje kot mora, tukaj pa nikakor ne...
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Vesoljc ::

newline-e si preveril tak kot je rekel genetic?
uporabi kak notepad++, nalozi ta tekstni fajl ter daj view/show all characters...

a struktura fajla je fiksna oziroma stalno enaka? so kje dodatne prazne vrstice ipd. ??
Abnormal behavior of abnormal brain makes me normal...

'FireSTORM' ::

struktura je vedno enaka...

številka
line
line
line
line
line
številka
line
line
itd
itd


newline-i so bili prvo kar sem sam preveril v sami datoteki, in so ok...
Those penguins.... They sure aint normal....

Vesoljc ::

in dobis prave podatke ce preberes 6 vrstic zapored v 6 stringov?
Abnormal behavior of abnormal brain makes me normal...

'FireSTORM' ::

recimo da je v file-u tole:
0
lala
lala
lala
lala
lala
1
haha
haha
haha
haha
haha
mi prebere najprej 0
in potem naslednjih 5 lala-jev vsak lala v svojo spremenljivko
in ta podatek potem vtakne v seznam na mesto 0
in potem gre prebirat naslednji podatek
ki mora biti na mestu 1 in 5 hahajev
ampak na mesto 1 vtakne prazen podatek
oz so vrednosti spremenljivk:
številka: 1
prva: newline
druga: newline
tretja: newline
četrta: newline
peta: newline

če je v datoteki 500 podatkov
torej od 0-499 so številke
in potem 500x tisith 5 vrstic
bo od 0 do 498 vse vredu, zadenj bo pa samo začetna številka in 5 newine characterjev
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Gundolf ::

Lej, glede mojga pluvanja po tvojem (ne)znanju - si ga malo preveč osebno vzel. C++ je malo specifičen. Obstajo vzorci uporabe okoli katerih je bil zgrajena standardna knjižnica in obstaja naiven način uporabe knižnice, pri katerem se vsak zaplete v krog nedelovanja oz. nepravilnega delovanja. Ti si globoko na tem drugem koncu in zato bi bilo najbolje, da si v eni knjigi pogledaš pravilen način uporabe. To je vse. Nisem te hotel zajebavat, niti to ne pomeni, da ti ne bom pomagal.

>> Problem je enostaven - nekaj narobe bereš v tisti zanki.
> ne res?
Če je tako očitno problem v zanki, zakaj si jo v prvem postu potem skrčil na en sam stavek?

clear na začetku ni narobe, nima pa nobene uporabne vrednosti. Ko jo ustvariš, je tvoj stream v stanju brez napak in opozoril in ga ni treba clearat. Isto velja za close na koncu. Brez veze je, ni pa narobe. Destruktor ti sam zapre stream.

eof v zanki je pa narobe. Zato ker eof ti vrne true šele, ko želiš prebrati prvi znak po koncu datoteke. In tu (sem 99% sigurem) leži tvoja napaka. Ti že prebereš tudi zadnji podatek pravilno ampak s tem le do konca prebereš datoteko. Zato se zanka še enkrat ponovi. In takrat začne brati preko konca datoteke, kar seveda pomeni, da vsa branja failajo in se postavi eof flag na streamu. Tako da se v tej iteraciji prebere en velik 0, naslednja se pa ne izvrši več, ker eof vrne true.

'FireSTORM' ::

saj nisem mislil z tem nič slabega
in vem da me nisi hotel "užalit" in me tudi nisi

glede close
a ni zmeraj pametno po koncu uporabe neke datoteke ta stream tudi zapreti?
in tudi glede clear
naredil sem samo to kar mi je bilo povedano...
tak način mi je bil naučen in razložen na primerih
in res nikoli se nisem poglabljal v to če je to sploh potrebno ali ni potrebno
ampak enostavno sem ga napisal...

glede eof
morda je res tu napaka
ampak...zakaj potem na drugi strani v drugi funkciji taka zanka deluje brez problema?
morda res na koncu vse ponovi in prebere prazen nič še na koncu enkrat ki je res nepotreben
ampak nebi potem zgledalo tako:

prebere podatek
ga vstavi v seznam na konec oz. na določeno mesto z tisto številko(kateri int se potem pretvori v POSITION spremenljivko)
zanka se ponovi ker še ni eof
dokler tako ne pride do zadnjega podatka
zdaj je pred zadnjim podatkom, kar še vedno ni eof
prebere ta zaden podatek
ga vstavi v seznam na konec oz. na določeno mesto z tisto številko(kateri int se potem pretvori v POSITION spremenljivko)
in kot ti praviš in sodeč po tvojih postih ti lahko kar verjamem še vedno ni eof
in še enkrat prebere nekaj kar dejansko ne obstaja v datoteki
in ta prazen nič poskuša vstavit v seznam na mesto NULL ker ne dobi nobene pozicije kam mora vstavit, in ker pozicija NULL ne obstaja vrne error oz. se aplikacija zruši, kar se pa ne zgodi...

si mi pa dal idejo
to while zanko zakomentiram ali zbrišem
v datoteko vstavim samo en podatek in vidim kar se zgodi
poročam čez nekaj sekund

edit:
maš prav
problem je v eof zanki
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Gundolf ::

Glede clear ne vem kdo te je tako naučil in mi je tudi čisto vseeno ampak, kot sem rekel, je tam čisto brezveze. Pravzaprav ga prvič vidim na takem kraju. V bistvu kadar takole odpiraš fajl to ponavadi narediš kar direkt v konstruktorju, ne pa trojica konstruktor, clear, open.

Praviš, da je pametno stream zapreti - ja in ne. Kot sem rekel, destruktor ti sam ga zapre, zato ga tebi ni treba. Je tudi nekako v duhu C++, da to prepustiš destruktorju. Sploh kadar si tako len, da se ti ne da niti preverit, a si fajl prej uspešno odprl :) Tako da close uporabiš le, ko hočeš z istim streamom odpreti drug fajl.

Če kodo pišeš na način, za kakršnega je bila std knjižnica napisana, ti bo najbolj sigurno delala, bo najbolj pregledna in najkrajša.

'FireSTORM' ::

v primeru sem napisal
fstream dat če se ne motim
napisal sem kot da je to spremenljivka samo v eni funkciji
je pa dejansko globalna spremenljivka
in jo uporabljam v vseh funkcijah
in da, preverjam če je file odprt
samo se mi je zdelo to tukaj nepotrebno pisati

edit: za clear sem pa bil naučen na feriju :P
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Gundolf ::

Globalna spremenljivka - še en slab programerski stil :P Ampak dejstvo, da je globalna, pa postavi vse mešetarjenje z njo v perspektivo. V tem primeru pa kar prav upravljaš z njo.

Pa se ti ne zdi da bi blo mal lažje, če bi namesto globalne spremenljivke, ki jo clear-aš, close-aš in odpiraš s kopico parametrov, imel vsakič svojo lokalno spremenljivko, ki bi jo le odprl in pozabil nanjo? Hitreje za pisat, lažje za vzdrževat. No, samo ideja za naslednji projekt :)

'FireSTORM' ::

zakaj pa za naslednji?
saj tega pa ja ni bog ve kaj spremenit :P
samo v vsaki funkcijki kjer uporabljam file dodam deklaracijo spremenljivke
pobrišem close in clear
in takrat bi namesto fstream uporabljal i in ofstream
tako da bi še tiste parametre pobrisal

vsekakor bi bilo bolje narediti tako...se kar strinjam ;)
Those penguins.... They sure aint normal....


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[Pascal] Kako program prepričati, da preskoči vrstico

Oddelek: Programiranje
81107 (830) joze67
»

Vislice

Oddelek: Programiranje
71702 (1477) VASkO
»

[c++]iskalnik po bazi podatkov

Oddelek: Programiranje
12995 (895) Gundolf
»

[C++] Problem z datotekami in sortiranjem

Oddelek: Programiranje
271227 (856) BigWhale
»

c++ datoteke

Oddelek: Programiranje
463837 (3326) Vesoljc

Več podobnih tem