[c++] Får inte till inläsningen från fil

Permalänk
Medlem

[c++] Får inte till inläsningen från fil

Hej!

Jag har en funktion som sparar på fil och nu vill jag det jag läsa in den filen in till min array.

.txt filens output(raden med numren är tab-delimited)

3 Peter Hammar 03/21/11 Gräddtårta 200 3 27.7 19 Peter Hammar 03/21/11 Björnbärssylt 300 0.6 123.6 0.3 Peter Hammar 03/21/11 Hårt bröd fullkorn råg kli fibrer ca 15% Siljans kraftknäcke 195 6.175 41.535 1.625

Min tanke är att
1. 3an på rad ett hämtas och sätts till nrOfDiets.
2. hämta usrName på rad två som den är och sätta den in i en sträng.
3. hämta datumet på rad tre och sätta den in i en sträng.
4. hämta varan på rad fyra sen skippa tabben som kommer sen hämta 200 sätta som sträng skippa tabben osv osv.

när loopen har körts en gång så är all info inläst i strängar och då är det bara att omvandla vissa strängar till ints och andra till doubles och skicka det till arrayen.

så här ser min funktion ut hittills

void DH::read() { ifstream in("Kostdagböcker.txt"); int nrOfDiets=0; string strKcal=" "; string strCarb=" "; string strProtein=" "; string strLipid=" "; string name=" "; string usrName=" "; string date=" "; in>>nrOfDiets; getline(in,usrName); cout<<usrName; for(int i=0;i<this->nrOfDiets;i++) { getline(in,usrName); getline(in,date); getline(in,name,'\t'); getline(in,strKcal,'\t'); getline(in,strCarb,'\t'); getline(in,strProtein,'\t'); getline(in,strLipid,'\t'); cout<<usrName<<endl; cout<<date<<endl; cout<<name<<endl; cout<<strKcal<<endl; cout<<strCarb<<endl; cout<<strProtein<<endl; cout<<strLipid<<endl; } system("pause"); in.close(); }

gör bara couts så jag ser om den har hämtat nåt, vilket den inte har.

tacksam för all hjälp

Permalänk
Medlem

börja med att verifiera att in.fail () inte är true.

edit: kan vara bra att kolla in.is_open () också.

ett tips till
Permalänk
Hedersmedlem

Tänk på att getline() läser in en hel rad, så en textsträng kommer till exempel innehålla hela raden

Hårt bröd fullkorn råg kli fibrer ca 15% Siljans kraftknäcke 195 6.175 41.535 1.625

istället för bara "Hårt bröd fullkorn råg kli fibrer ca 15% Siljans kraftknäcke" (som man förmodligen menade). Dessutom är det jobbigt att, om man tillåter namn med varierande antal vita tecken, lägga sådana före annat då man måste lista ut om det till exempel är "Siljans", "kraftknäcke" eller "195" som är energiinnehållet. Alternativa lösningar är att lägga övrig information först och sedan anse att resten av raden är namnet, att byta ut vita tecken mot någon annan symbol (som inte används/tillåts) eller att låta bli att ha många sorters information på samma rad. I det senare fallet fungerar ju också getline() för inläsning.

Permalänk
Medlem
Skrivet av Elgot:

Tänk på att getline() läser in en hel rad

Jag tycker det ser ganska klart ut att han använder

istream& getline ( istream& is, string& str, char delim );

som sköter klippningen rätt fint.
Får du in nått vettigt i nrOfDiets? Har din ifstream några felflaggor satta?

Visa signatur

void@qnet
teeworlds, stålverk80, evil schemer, c, c++
Languages shape the way we think, or don't.

Permalänk
Hedersmedlem
Skrivet av jdv:

Jag tycker det ser ganska klart ut att han använder

istream& getline ( istream& is, string& str, char delim );

som sköter klippningen rätt fint.

Usch, jag läser dåligt.

Permalänk
Medlem
Skrivet av Z3R0:

void DH::read() { ifstream in("Kostdagböcker.txt"); int nrOfDiets=0; string strKcal=" "; string strCarb=" "; string strProtein=" "; string strLipid=" "; string name=" "; string usrName=" "; string date=" "; in>>nrOfDiets; getline(in,usrName); cout<<usrName; for(int i=0;i<this->nrOfDiets;i++) { getline(in,usrName); getline(in,date); getline(in,name,'\t'); getline(in,strKcal,'\t'); getline(in,strCarb,'\t'); getline(in,strProtein,'\t'); getline(in,strLipid,'\t'); cout<<usrName<<endl; cout<<date<<endl; cout<<name<<endl; cout<<strKcal<<endl; cout<<strCarb<<endl; cout<<strProtein<<endl; cout<<strLipid<<endl; } system("pause"); in.close(); }

Vet inte om det är exakt det problemet ?
Men du läser in username 2 ggr först
Så innan du hopar in i for loopen har du redan hopat ner 2 lines i filen

kod filen in>>nrOfDiets; 3 getline(in,usrName); Peter Hammar cout<<usrName; for(int i=0;i<this->nrOfDiets;i++) { getline(in,usrName); Gräddtårta 200 3 27.7 19 getline(in,date); Peter Hammar

Etz

Hopas det hjälper

[edit] Det är enklare att hitta vad som är fel om du säger vad som blir fel också typ felutskrift eller kompilerings fel.

Visa signatur

orka

Permalänk
Medlem
Skrivet av helmet:

börja med att verifiera att in.fail () inte är true.

edit: kan vara bra att kolla in.is_open () också.

tror du detta skulle kunna funka?

if(in.fail()!=true) { for(int i=0;i<this->nrOfDiets&& in.good();i++) { blabla } } sen kanske en else här.

Skrivet av jdv:

Jag tycker det ser ganska klart ut att han använder

istream& getline ( istream& is, string& str, char delim );

som sköter klippningen rätt fint.
Får du in nått vettigt i nrOfDiets? Har din ifstream några felflaggor satta?

jag gjorde en utskrift av den första inläsningen förut och fick ut en trea, så det e nog som det ska.
När det gäller felflaggor har jag ingen aning :-/

Permalänk
Medlem

btw så när jag prövar

cout<<nrOfDiets<<endl; getline(in,usrName); cout<<usrName<<endl; system ("pause");

inne i if-satsen så skrivs bara trean ut och inget mer

prövar med att sätta en breakpoint vid getlinen och får reda på att usrName sätts till " ", dvs space :S

Permalänk
Medlem

när jag kör detta

if(in.fail()!=true) { /*cout<<nrOfDiets<<endl; getline(in,usrName,'\n'); cout<<usrName<<endl; system ("pause");*/ for(int i=0;i<this->nrOfDiets && in.good();i++) { getline(in,usrName); getline(in,date); getline(in,name,'\t'); getline(in,strKcal,'\t'); getline(in,strCarb,'\t'); getline(in,strProtein,'\t'); getline(in,strLipid,'\t'); cout<<usrName<<endl; cout<<date<<endl; cout<<name<<endl; cout<<strKcal<<endl; cout<<strCarb<<endl; cout<<strProtein<<endl; cout<<strLipid<<endl; } } else cout<<"Gick inte att öppna filen!"<<endl; system("pause"); in.close();

får jag denna utskrift(utklippt från konsolen)

Peter Hammar 03/21/11 Gräddtårta 200 3 27.7 19 Peter Hammar 03/21/11 Björnbärssylt 300 0.6 123.6 0.3 Peter Hammar 03/21/11 Hårt bröd fullkorn råg kli fibrer ca 15% Siljans kraftknäcke 195 6.175 41.535 1.625

Permalänk
Medlem

Jag löste det, men har ett litet problem.
Det är nämligen så att jag har en funktion som låter användaren mata in namn och datum och då presenteras allt i arrayen som innehåller den informationen.
och när jag mattar in

Peter Hammar 03/21/11

så visas bara innehållet på plats 1 och 2 men inte det på plats 0.
sök funktionen

void DH::findOld(string date,string usrName)const { for(int i=0;i<this->nrOfDiets;i++) { if(date==this->dh[i]->getDate() && usrName==this->dh[i]->getUsrName()) { this->dh[i]->show(i); } } }

när jag tar bort if-satsen så visas allt som det ska, så då börjar jag tro att det är nåt fel vid inläsningen från fil, att det första itemet inte skickas som det ska.

Permalänk
Medlem

har fixat läsning så här, allt funkar som det ska.

void DH::read() { ifstream in("Kostdagböcker.txt"); string strKcal=" "; int kcal=0; string strCarb=" "; double carb=0.0; string strProtein=" "; double protein=0.0; string strLipid=" "; double lipid=0.0; string name; string usrName; string usrName1; string usrName2; string date; string nrs; getline(in,nrs); this->nrOfDiets=atoi(nrs.c_str()); if(!in.fail()) { for(int i=0;i<this->nrOfDiets && in.good();i++) { getline(in,usrName1,' '); getline(in,usrName2); usrName=usrName1+ " " + usrName2; getline(in,date); getline(in,name,'\t'); getline(in,strKcal,'\t'); getline(in,strCarb,'\t'); getline(in,strProtein,'\t'); getline(in,strLipid); kcal=atoi(strKcal.c_str()); carb=atoi(strCarb.c_str()); protein=atoi(strProtein.c_str()); lipid=atoi(strLipid.c_str()); this->dh[i]=new Diet(name,kcal,protein,carb,lipid,usrName,date); } } else cout<<"Gick inte att öppna filen!"<<endl; in.close(); }

men när jag försöker stänga ner konsolen med menyvalet "avsluta" så kraschar hela alltet och jag får detta felmeddelande

HEAP CORRUPTION DETECTED etc etc CRT detected that the application wrote to memory after end of heap buffer.

när jag tar bort inläsningen från fil så funkar allt som det ska igen :-/

vad tror ni kraschen beror på? och hur löser jag felet?

Permalänk
Medlem

Sådana meddelanden ges väll om man skriver till utrymme som ej är allokerat, sedan ska man ju frigöra minnet också.
Vart och hur stor allokerar du this->dh[]?

Permalänk
Medlem

DH::DH() { this->capacity=3; this->nrOfDiets=0; this->dh=new Diet*[this->capacity]; for(int i=0;i<this->capacity;i++) { this->dh[i]=NULL; } }

sen har jag en virtuell destruktor

Permalänk
Medlem
Skrivet av Z3R0:

DH::DH() { this->capacity=3; this->nrOfDiets=0; this->dh=new Diet*[this->capacity]; for(int i=0;i<this->capacity;i++) { this->dh[i]=NULL; } }

sen har jag en virtuell destruktor

Så du har capacity satt till 3 i din kod också? Då har du endast 3 platser allokerade och du hade tänkt läsa in hur många? Dvs. Du måste ha lika många platser allokerade som

this->dh[i]=new Diet(name,kcal,protein,carb,lipid,usrName,date);

du använder.
Kanske kan du använda nån sorts lista eller vector som som används på detta sätt: minlista.add(...), eller var det push_back(...) i c++ :). Dvs ingen förallokering behövs.

Permalänk
Medlem

Jag har en add funktion som utför expansion av arrayen om capacity == nrOfElements men av nån anledning så funkar det inte här.
kan jag på nåt sätt göra så att arrayen expanderar vid behov?

Permalänk
Hedersmedlem
Skrivet av Z3R0:

kan jag på nåt sätt göra så att arrayen expanderar vid behov?

Den bekväme hade nog använt en std::vector.