Błąd przy odczytywaniu z pliku do klasy

0

Witam!
Piszę program Quiz w C++, mój program posiada klasę nadrzędną quiz oraz klasę potomną Category
Zasada działania programu jest taka że, kategoria pobiera i przechowuje pytania pobrane z odpowiedniego dla niej pliku np. Kategoria wojskowość pobiera i przechowuje dane z pliku wojskowosc.txt. Pytania przechowywane są w strukturze.

struct pytanie
{
string pyt;
string odp[4];
string dobraOdp;
};

oto interfejs:

#include<iostream>
#include<cstring>
#include<conio.h>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<fstream>
using namespace std;

struct pytanie
{
string pyt;
string odp[4];
string dobraOdp;
};

class Quiz
{
private:
char* nazwa;
public:
Quiz(){nazwa= new char[strlen("BRAK")+1]; strcpy(nazwa,"BRAK");};
Quiz(char* nazwa){this->nazwa= new char[strlen(nazwa)+1]; strcpy(this->nazwa,nazwa);};
virtual ~Quiz(){delete[]nazwa;};
virtual void wypisz(){cout<<"Kategoria: "<<nazwa<<endl;};
};

class Category: public Quiz
{
private:

ifstream plik;
char *npliku;
pytanie *question;/** Wskaznik na strukture pytanie**/
vector<pytanie> t;

public:
void pobierz(ifstream & plik);
void wypStruct();
Category();

Category(char* n,char* npliku):Quiz(n)
{
    this->npliku=new char[strlen(npliku)+1];
    strcpy(this->npliku,npliku);

    plik.open(npliku,ios::in);
    if(plik.fail())
    {
    cout<<"NIe udalo sie nawiazac polaczenia z plikiem "<<npliku<<".\nProgram zostanie zamkniety.\n";
    exit(1);
    }

    pobierz(plik);

    plik.close();
}
~Category();

void wypisz();

};

A tutaj Definicje:

#include<iostream>
#include<cstring>
#include<conio.h>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<fstream>
#include"q.h"
using namespace std;

Category::Category(){};

Category::~Category()
{
delete [] npliku;
cout<<"Usunieto obiekta.\n";
}

void Category::pobierz(ifstream & plik)
{
while(!plik.eof())
{
getline(plik,question->pyt);
cout<<question->pyt<<endl;

  for(int i=0;i<4;i++)
  {
    getline(plik,question->odp[i]);
    cout<<question->odp[i]<<endl;
  }

   getline(plik,question->dobraOdp);
   cout<<question->dobraOdp;

   t.push_back(*question);
  }

}

void Category::wypStruct()
{
cout<<question->pyt<<endl<<endl;

for(int i=0;i<4;i++)
{
    cout<<question->odp[i]<<" ";
    if(i==1)cout<<endl;
}

}

void Category::wypisz()
{
Quiz::wypisz();

for(int i=0; i<t.size();i++)
{
    wypStruct();
}

}

Jak można zauważyć używam klasy Vector do przechowywania pytań, wiem że nie jest to najefektywniejsze rozwiązanie ale zwyczajnie jest ono najwygodniejsze bo nie muszę zliczać wierszy które pobieram... Ponad to moja struktura ma przechowywać wszystkie informacje i dane dotyczące pytania, z pytaniem i odpowiedziami włącznie.

Mam kilka wątpliwości:

  1. Co do tablicy (wektora) struktur, która docelowo ma przechowywać pytania.
    Tzn. skoro mam strukture o nazwie pytanie to deklaracja wektora to vector<pytanie>t ? czy vector<struct>t?
    Kompilator przepuszcza mi tylko tą pierwszą wersje i wydaje się ona dobra ze względu na to że przechowuje dane które mają wyglądać jak moja utworzona struktura.

  2. Nie mogę się odwołać do struktury w ten sposób np pushback(plik,pytanie.odp);
    Więc utworzyłem wskaźnik na strukturę i umieściłem go w klasie: pytanie *question; Dzięki temu już mogę się odwoływać do mojej struktury.
    Tylko nie wiem czy jest to dobre rozwiązanie.

No i teraz najważniejsze, w sumie główny powód mojego postu tutaj jest fakt, że program wywala się przy pobieraniu zmiennych

domyślam się że chodzi tutaj o linijkę pushback(plik,*quiz);
Generalnie pobieranie danych z pliku realizuje za pomocą tej metody:

void Category::pobierz(ifstream & plik)
{
while(!plik.eof())
{
getline(plik,question->pyt);
cout<<question->pyt<<endl;

  for(int i=0;i<4;i++)
  {
    getline(plik,question->odp[i]);
    cout<<question->odp[i]<<endl;
  }

   getline(plik,question->dobraOdp);
   cout<<question->dobraOdp;

   t.push_back(*question);
  }

}

i wiem że to ona wywala mi cały program, niestety nie wiem dla czego. Czy mógłby mi ktoś z kolegów zobaczyć w czym leży problem i napisać jak go rozwiązać?

Pozdrawiam i z góry dziękuję za pomoc.

Dodam jeszcze załącznik rar z plikami klasy oraz plikiem wejściowym.

0

Udostępnione:D
jak cos to tutaj jest link:

http://4programmers.net/Pastebin/2912

1

Dlaczego nie używasz std::string? Obecnie Twój quiz nie jest bezpieczny w użyciu i nie respektuje zasady trzech (ew. 5 lub 0).

Nigdzie nie tworzysz struktury dla wskaźnika question ⟶ dokonujesz dereferencji niezainicjalizowanego wskaźnika ⟶ UB. W ogóle nie ma sensu aby była to zmienna klasy, lokalnie w funkcji wczytującej dodaj.

Dlaczego funkcja wypisz nie wypisuje elementów (elementu?) wektora?

0
kq napisał(a):

Dlaczego nie używasz std::string? Obecnie Twój quiz nie jest bezpieczny w użyciu i nie respektuje zasady trzech (ew. 5 lub 0).

Ponieważ używam biblioteki <cstring> ale zmieniłem na string.

Nigdzie nie tworzysz struktury dla wskaźnika question ⟶ dokonujesz dereferencji niezainicjalizowanego wskaźnika ⟶ UB. W ogóle nie ma sensu aby była to zmienna klasy, lokalnie w funkcji wczytującej dodaj.

Po zmianie którą zaproponowałeś, tzn strukturę wyrzuciłem z listy zmiennych klasy i utworzyłem nową w funkcji pobierającej


/**Funkcja pobierająca dane z pliku**/

void Category::pobierz(ifstream & plik)
{
    pytanie *question= new pytanie;/**Tworzenie nowego elementu na podstawie struktury**/

    while(!plik.eof())
    {
      getline(plik,question->pyt);
      cout<<question->pyt<<endl;

      for(int i=0;i<4;i++)
      {
        getline(plik,question->odp[i]);
        cout<<question->odp[i]<<endl;
      }

       getline(plik,question->dobraOdp);
       cout<<question->dobraOdp;

       t.push_back(question);
      }
}

Dlaczego funkcja wypisz nie wypisuje elementów (elementu?) wektora?

Okey, masz racje. Nie wiem co mi się uroiło że tak to zrobiłem:P Tutaj jest poprawiona wersja:)

void Category::wypisz()
{
    //pytanie question;

    Quiz::wypisz();

    cout<<t.size()<<endl;/**Sprawdzam dla samego siebie czy mój wektor wogóle posiada jakąś wielkość i elementy**/

    for(int i=0; i<t.size();i++)
    {
        cout<<t[i].pyt<<endl<<endl;

        for(int i=0;i<4;i++)
        {
        cout<<t[i].odp[i]<<" ";
        if(i==1)cout<<endl;
        }
    }
}

Teraz mi program wypisuje pytanie jednak niestety oto efekt działania programu. Screena przekazuje w załączniku.

1

Przy wypisywaniu zamień wewnętrznego fora z i np na j bo wypisujesz nie to co chcesz. Poza tym wartość size'a jest 2 a z pliku teoretycznie wczytujesz 1 pytanie.

0

Okey, wielkie dzięki:) Nie zauważyłem tego:)

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