Jag har problem med att läsa från en fil. Problemet är att jag inte vet hur jag ska ta reda på när jag kommit till slutet av filen, för att avbryta läsningen. Filen jag ska läsa från innehåller flera olika datatyper, som måste hamna i sina egna variabler för att resten av programmet ska fungera. Så vad jag vet så funkar det inte att skriva: Två tänkbara problem (dock longshots, men den kanske samarbetar :-) ): Då klistar jag in hela klassen Medlem: Om du skall spara/läsa klasser till en fil bör du använda dig av "serialization". Det finns ingen sån funktion "inbyggd" i C++ men det finns ett bra alternativ i boost.serialization. (Har inte provat .Net serialization från c++ men det borde väl fungera även om syntaxen troligen är lite strulig) Det var inte meningen att klaga på ditt val av programmeringsspråk. Om du tycker att C++ är OK och passar för den sortens programmering som du gör, så kör hårt! C++ har både sina negativa och positiva sidor, och framförallt så finns det saker man kan göra i C++ som i stort sett bara går att göra med C++ (eller C, men det tycker jag är ännu värre). Okej, jag är nybörjare. Jag vet inte vad serialization ens betyder :D. Jag vet att du inte klagade. Jag menade att jag inte tänker stanna upp och klaga :).Filhanatering problem
char text[100];
ifstream inFil(filnamn);
while(inFil.getline(text, 100)){//Funkar inte för att den kommer läsa hela raden
//gör saker
}
Vad jag har försökt göra är följande:
ifstream inFil(filnamn);
while(true){
objekt.lasFranFil(inFil);
//stoppa in datan i en map
if(inFil.eof()){
break;
}
}
Problemet är att när jag väl hamnar i while-loopen så kommer jag inte ut. Efter 2 dagars testande fram och tillbaka så har jag kommit fram till att anledning till att jag inte kommer ur while-loopen är att jag precis efter objekt.lasFranFil(inFil), läser in datan i en map.
Detta vet jag för när jag kommenterar bort in läsningen till map:en så kommer jag ur loop:en. Men när jag inte kommenterar bort inläsningen till map:en så kommer jag aldrig ur loop:en.
Jag vet också att det inte är nåt fel på själva inläsningen till map:en eftersom att jag har provat att begränsa loopen så här:
while(i<2){
objekt.lasFranFil(inFil);
//läs till map
i++;
}
Och då funkade allt som det skulle. Men det förutsätter självklart att man har fullkoll på vad och hur mycket man har sparat i filen.
Så om jag ska sammanfatta problemet: När jag läser in data från en fil till en map så kommer jag inte ur while-loop:en. Men när jag för hand begränsar loop:en så kan jag läsa in data till map:en från samma fil. Dessutom, när jag kommenterar bort inläsningen till map:en så kan jag också komma ur loop:en.
Så jag undrar hur jag kan lösa detta? Får tillägga att jag är ganska newb på programmering. Har precis börjat läsa om map:ar. Koden jag har problem med tillhör en uppgift i en bok för gymnasiet, C++ Programmering C av Ingvar Gratte. Jag kodar på Linux Fedora, med GCC.
Vill verkligen lösa uppgiften så jag kan komma vidare i boken. Efter över ett års tråk-programmerande så börjar det precis bli intressant :).
Koden:
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
#include "medlem.cpp" //Metoder för att bland annat skriva till/från filer finns här
int main(){
Medlem medlem;
map <int, Medlem> m;
int nummer, antal;
char svar, filnamn[100];
bool betalt;
cout << "Läsa in från fil(j/n)? ";
cin >> svar; cin.ignore();
if(svar=='j'){
cout << "Filnamn: ";
cin.getline(filnamn, 100);
if(filnamn[0] != '\0'){
ifstream infil(filnamn);
if(!infil){
cerr << "Kunde inte öppna filen!" << endl;
exit(1);
}
while(true){
medlem.lasfranfil(infil);
nummer=medlem.getMedlnr();
m[nummer]=medlem;
if(infil.eof()){
break;
}
}
infil.close();
}
}
cout << "Dessa fanns i filen: " << endl;
map<int, Medlem>::iterator it=m.begin();
while(it!=m.end()){
int nummer=it->first;
Medlem mm=it->second;
mm.visa();
}
cout << endl;
return 0;
}
Vill ni ha klassen Medlem så säg till för den är ganska lång. Koden ovan är längre, jag har bara klippt ut det väsentliga.
UPPDATERING
Jag har trixat lite till och det verkar vara raden
m[nummer]=medlem; //på rad nummer 34
som programmet inte verka kunna komma förbi. Alltså själva inläsningen till map:en. För när jag kommenterar bort _bara_ den raden så kommer jag ur while-loopen. Men tar jag bort kommentaren så kommer jag inte ur while-loopen. Vad är det med den raden som gör att programmet inte kan komma vidare? Sv: Filhanatering problem
1. Hur ser Medlem::lasfranfil ut? Läser den in alla värden även om den redan är initierad (eftersom du använder samma instans för varje inläsning)? Påverkas inläsningen på något sätt av dess tillstånd?
2. Hur ser tilldelningsoperatorn för Medlem ut? Är den implementerad alls? Om inte, vad finns det för medlemsvariabler som inte är "enkla typer" (dvs int, float, std::string osv). Eftersom den anropas vid tilldening till mappen så kan den kanske påverka.
Det borde vara något med tilldelningsoperatorn, men det vet vi inte utan att ha sett koden :-).
Den här sortens problem är ett bra exempel på varför jag anser (OBS! min egen åsikt, take it or leave it) att C++ är ett uselt programmeringsspråk att använda för att lära sig programmering, använd Java eller C# till det istället.
/Andreas, som börjar bli litet rostig på C++Sv:Filhanatering problem
class Medlem{
int medlnr;
string namn;
bool betalt;
public:
Medlem(string nn="Okand", int m=0, bool b=false):namn(nn), medlnr(m), betalt(b){}
void visa(){
cout << "Medlemsnummer: " << medlnr << endl;
cout << "Namn: " << namn << endl;
if(betalt){
cout << "Betalt" << endl;
}
else{
cout << "Inte betalt" << endl;
}
}
void matain(){
char temp[200];
cout << "Namn: ";
cin.getline(temp, 200);
namn=temp;
cout << "Medlemsnummer: ";
cin >> medlnr;
char svar;
cout << "Betalt - mata in J eller N: ";
cin >> svar;
if(svar=='J' || svar=='j'){
betalt=true;
}
else{
betalt=false;
}
cin.ignore();
}
void lagraifil(ofstream& utfil){//Skriver till fil
int storlek=namn.size();
utfil.write((char *)&storlek, sizeof(int));
for(int plats=0; plats<storlek;++plats){
utfil.write(&namn[plats],1);
}
utfil.write((char *)&medlnr, sizeof(int));
utfil.write((char *)&betalt, sizeof(bool));
}
void lasfranfil(ifstream& infil){//Läser från fil
namn="";
int storlek;
infil.read((char *)&storlek, sizeof(int));
for(int plats=0; plats<storlek;++plats){
char tecken;
infil.read(&tecken,1);
namn=namn+tecken;
}
infil.read((char *)&medlnr, sizeof(int));
infil.read((char *)&betalt, sizeof(bool));
}
int getMedlnr(){
return medlnr;
}
};
Haha, jag höll på och skriva ett gigantiskt svar på programmeringspråk vs programmeringsspråk. Jag kan ge två korta svar på varför jag kör med c++ och inte tänker byta:
1. Anledningen till att jag valde C++ är att olika saker hände som gjorde att jag höll mest på med C++. Tex som att jag i gymnasiet "hamnade" i två C++ kurser. Medan jag bara läste 1 java kurs och 1 C# kurs. Och massa andra liknande saker hände.
Men nu inser jag ju att C++ faktiskt inte är så dumt :). Så det är helt lugnt för min del.
2. Som du märker är jag djupt inne i objektorienteringsdjungel med c++. Har därför som nybörjare kommit ganska långt i språket. Att släppa allt detta och börja om med ett nytt språk känns som över 1 års bort kastade tid.
Och det är inte precis som om jag inte har stött på problem förr. Man löser problemet och lär sig :). Ingen idé att stanna upp och klaga på att det är svårt. Allt på en avancerad nivå är svårt. Så det är bara att köra på med järnvilja :).Sv: Filhanatering problem
Ditt problem är troligen att du inte kollar om läsningen gick bra innan du använder värdet.
infil.read((char *)&storlek, sizeof(int));
if (!infil.good()) ...
Edit: såg att du la upp koden medan jag skrev.
Sv:Filhanatering problem
Jag utvecklade mestadels i C++ under 9 års tid, men har den senaste tiden arbetat mest med Java eller C#. Jag tycker att produktiviteten i Java/C# är betydligt bättre, men jag saknar ibland kraftfullheten (dvs enklare att rota med lågnivå, det finns i stort sett INGA begränsningar) och multipelt arv, men saknar inte syntaxen och minneshanteringen.
Som sagt passar det dig, så kör hårt. Steget att senare även lära sig Java eller C# är inte så stort.
Och som Martin Adrian sade: eftersom du inte kollar om läsningen av int storlek gick bra så går du rakt in i for-loopen med en oiniterad int som begränsning, vilket gör att du inte kommer ur den på ett tag. Debuggern är din vän.
/Andreas
/AndreasSv:Filhanatering problem
Har aldrig sett funktionen good(). Sökte lite på google, men hittade inte mycket om den. Vad är det den gör?
Min hårddisk kraschade och dog dagen efter att du skrev det inlägget. Jag förlorade all min kod. Hann inte testa good(). Ska beställa en ny hårddisk vilken dag som helst nu, så jag testar det då.Sv: Filhanatering problem
<b>>Jag tycker att produktiviteten i Java/C# är betydligt bättre, men jag saknar ibland kraftfullheten (dvs enklare att rota med lågnivå, det finns i stort sett INGA begränsningar) och multipelt arv, men saknar inte syntaxen och minneshanteringen.</b>
Jo, jag känner likadant. Det är enklare att jobba i java och c# och att c++ har horribel syntax. Men men... Om jag hade fått välja från början, utan att gymnasiet blandat sig i så hade jag valt att börja med java och sen ändå satsat på c++ för att man kan göra saker med c++ som man inte kan med java.
Men nu blev det c++ först. Men jag tänker utan tvivel lära mig något mer språk, troligen java. C# passar inte mig som Linux-användare.
Men som sagt så kraschade min hårddisk nyligen. Och min kod är borta. Ska fixa en ny hårddisk och får då prova det Martin Adrian sa. Får återkomma då.
Har inte lärt mig att använda en debugger än :). Får se när det blir av...