Czytanie z pliku i tworzenie obiektów na podstawie danych z pliku

0

Witam, mam taki problem, chciałbym utworzyć obiekty jednej klasy przekazując do konstruktora strumień ifstream, co prawda udało mi się utworzyć jeden, ale tylko jeden objekt a chciałem utworzyć tyle obiektów ile jest danych w pliku czyli dopóki nie nastąpi koniec pliku.Napisałem to tak, konstruktor tworzący docelowy obiekt:

Potrawa::Potrawa(ifstream &i)
{
    CzyGotowa=0;
    getline(i, Nazwa);
    i>>Cena;
}
Menu::Menu(std::ifstream &i)
{
      while(! i.eof() )
          {
              Potrawa *potrawa=new Potrawa(i);
              Potrawy.push_back(potrawa);
          }
}
int main()
{
    ifstream plik("potrawy.txt");

    Menu menu(plik); ...

Pomijam tymczasowo sprawdzanie czy plik otworzono bo raczej to nie jest problem(?).
Program się zawiesza ale nie wyłącza, nie wyskakują też żadne poważne błędy, mam nadzieje że ktoś wie co odwaliłem.

0

A nie latwiej utworzyć sobie wektor i po wczytaniu danych tworzyć kolejny obiekt i wrzucać do wektora?

0

i.eof() zwraca true dopiero, gdy nastąpiła próba czytania poza plikiem, a nie gdy osiągnięto koniec pliku!
I tu jest twój problem.
Zrób to raczej tak:

Menu::Menu(std::ifstream &i)
{
     std::string linia;

     while(getline(i, linia)) {
              Potrawa *potrawa=new Potrawa(linia); // konstruktor przyjmujący za argument std::string!
              Potrawy.push_back(potrawa);
     }
}
0
MarekR22 napisał(a)

i.eof() zwraca true dopiero, gdy nastąpiła próba czytania poza plikiem, a nie gdy osiągnięto koniec pliku!
I tu jest twój problem.
Zrób to raczej tak:

Menu::Menu(std::ifstream &i)
{
     std::string linia;

     while(getline(i, linia)) {
              Potrawa *potrawa=new Potrawa(linia); // konstruktor przyjmujący za argument std::string!
              Potrawy.push_back(potrawa);
     }
}

rozumiem o co Ci chodzi tylko jest jeden problem, obiekt który tworze ma klika składowych (na razie dwie) i to byłoby niezbyt uniwersalne, owszem dobre ale za dużo by trzeba było rozbudowywać w razie zmian... A ja chciałbym przekazać strumień do konstruktora żeby konstruktor pobierał kolejne dane, wtedy zmienie tylko konstruktor potrawy a w menu nic bym nie musiał ruszać. Wiem że takie coś da się zrobić (może nie z funkcją eof() tylko jakimś innym sposobem) ponieważ o tym sposobie(przekazanie strumienia) mówił nam magister na zajęciach;/

i jeszcze jedno, tak sobie próbowałem żeby w ogóle wczytać kilka takich obiektów i zrobiłem to w forze:

Menu::Menu(std::ifstream &i)
{
    for (int j=0; j<3; j++){
    Potrawa *potrawa=new Potrawa(i);
    Potrawy.push_back(potrawa);}
} 

obiekty są tworzona co prawda ale tylko w pierwszym obiekcie dane zostały wczytane, w kolejnych danych nie ma... takie pytanie mam więc odnośnie zachowania się strumienia, jeśli podaje do pierwszego konstruktora strumień, on odczytuje z niego dwie linie i kończy się konstruowanie obiektu więc zaczynamy konstruowanie kolejnego który otrzymuje ten sam strumień, czy teraz konstruktor zaczyna czytać plik od początku czy od miejsca w którym skończył czytać poprzedni(konstruktor)?

0

Nie widzę problemu, Zakładając, że masz plik tekstowy w formacie:

jabłko: 12
szarlotka: 33
piwo: 10

to do tego co wcześniej podałem, tworzysz taki konstruktor:

Potrawa::Potrawa(const std::string s)
{
    std::stringstream linia(s);

    CzyGotowa=0;
    Cena = 0;
    getline(linia, Nazwa, ':'); // czytaj do znaku ':', który jest separatorem ceny i nazwy potrawy
    linia >> Cena;
}

Na dodatek wczytując linie możesz zauważyć, że masz np pustą linię, więc wtedy traktujesz to jako koniec twojego menu i nie tworzysz nowego obiektu potrawy!

1 użytkowników online, w tym zalogowanych: 0, gości: 1