terminate called after throwing an instance of 'std::out_of_range'

0

Wywala mi taki błąd(http://zapodaj.net/923891b67f33f.png.html), a przecież nie wychodzę po za zakres, bo w pliku tekstowym mam:

Temat: Pytanie 1
A: OdpA
B: OdpB
C: OdbC
D: OdbD
Poprawna odpowiedz: A
Temat: Pytanie 2
A: OdpA
B: OdpB
C: OdbC
D: OdbD
Poprawna odpowiedz: B 
 void Klient::wczytaj_quiz(string odpA[], string odpB[], string odpC[], string odpD[], string odp_pop[])
{
    ifstream fl("quizy.txt");

    if(fl.is_open())
    {
        int nr_linii = 1;
        string linia;
        int licznik = 0, licznik2 = 0, licznik3 = 0, licznik4 = 0, licznik5 = 0;

        while(getline(fl, linia))
        {
            try{
                switch(nr_linii)
                {
                case 2:
                    {
                        odpA[licznik] = linia.substr(3);
                        licznik++;
                        break;
                    }
                case 3:
                    {
                        odpB[licznik2] = linia.substr(3);
                        licznik2++;
                        break;
                    }
                case 4:
                    {
                        odpC[licznik3] = linia.substr(3);
                        licznik3++;
                        break;
                    }
                case 5:
                    {
                        odpD[licznik4] = linia.substr(3);
                        licznik4++;
                        break;
                    }
                case 6:
                    {
                        odp_pop[licznik5] = linia.substr(20);
                        licznik5++;
                        break;
                    }
                }
            }
            catch(out_of_range& e)
            {
                cout << "Blad wczytywania!";
                Sleep(2000);

                break;
            }

            if(nr_linii == 6)
            {
                nr_linii = 0;
            }
            nr_linii++;
        }
    }

    fl.close();
    fl.clear();
}
1
  1. Zapoznaj się z inkrementacją nie rozumiesz jej: http://4programmers.net/Forum/1101404
  2. Po kiego robisz fl.clear(); to ma sens tylko jeżeli używasz tej samej zmiennej fl do ponownego otwarcia pliku
  3. Po kiego robisz fl.close(); skoro fl to zmienna lokalna to po zakończeniu funkcji samo się zamknie.
  4. Nie ma co zliczać wierszy o ile wiesz ile czego będzie, np:
size_t licznik=0;
string linia;
for(ifstream fl("quizy.txt");getline(fl,linia);++licznik) // w warunku omijamy temat
  {
   getline(fl,odpA[licznik]);
   getline(fl,odpB[licznik]);
   getline(fl,odpC[licznik]);
   getline(fl,odpD[licznik]);
   getline(fl,odp_pop[licznik]);
  }
  1. Robisz klasę a nie potrafisz zrobić prostej struktury?
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;

struct Question
  {
   string Q,Answers[4],ok;
   Question(istream &in)
     {
      while(getline(in,Q)) // dzięki pętli możesz w pliku pustymi wierszami pytania oddzielić.
        {
         if(Q.substr(0,7)=="Temat: ")
           {
            Q=Q.substr(7);
            for(int i=0;i<4;++i) getline(in,Answers[i]);
            getline(in,ok);
            ok=ok.substr(20);
            return;
           }
        }
     }
   friend ostream &operator<<(ostream &s,const Question &q)
     {
      s<<q.Q<<endl;
      for(int i=0;i<4;++i) s<<q.Answers[i]<<endl;
      return s<<q.ok<<endl;
     }
  };

void wczytaj_quiz(vector<Question> &tb)
  {
   for(ifstream fl("quizy.txt");fl;) tb.push_back(Question(fl));
  }  
  
int main()
  {
   vector<Question> tb;
   wczytaj_quiz(tb);
   for(size_t i=0;i<tb.size();++i) cout<<tb[i]<<endl;
   return 0;
  }
  1. Wyłazisz poza zakres prawdopodobnie np w odpA[licznik] pokaż jak przydzielona ta odpA
0

Dobra. Już działa. Wczoraj cały dzień programowałem, to komputer wieczorem zaczął zamulać. A teraz kompiluję, to już normalnie działa. Wygląda na to, że musiał się przespać.

Ale nie mogę jeszcze ogarnąć przesuwania wskaźnika. Odpowiedzi są już OK. Problem mam z wczytywanie tematów.
Kod:

void Klient::wczytaj_temat_quiz(string tematy[], int ilosc_quiz)
{
    ifstream fl("quizy.txt");

    if(fl.is_open())
    {
        int nr_linii = 1;
        string linia;
        int licznik = 0;

        //fl.seekg(7, ios_base::beg);

        while(getline(fl, linia))
        {
            switch(nr_linii)
            {
            case 1:
                {
                    tematy[licznik] = linia.substr(7);
                    licznik++;
                }
            }

            if(nr_linii == 6)
            {
                nr_linii = 0;
            }
            ++nr_linii;

            //fl.seekg(7, ios_base::cur);
        }
    }
} 

z tą funkcja 'substr' działa, ale gdy chciałem spróbować też innym sposobem, z tym przesuwaniem wskaźnika co jest zakomentowany, to źle go przesuwa. Plik tekstowy jest ten sam co z odpowiedziami.

Wyświetla mi pierwszy temat dobrze, ale w drugim temacie wyświetla mi 'wiedz: B;. Kolejny quiz jakbym dodał, to już tematu nie wyświetli.

Nie wiem czy dobrze rozumiem działanie, ale powinno to być tak, że ustawia najpierw wskaźnik na siódmy znak względem początku, wczytuje linię, i po przejściu do kolejnej linii względem obecnej pozycji przesuwa znowu o siedem.

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