Test z matematyki - zapis części struktury do pliku binarnego

0

Witam. Mam pewien problem. Mam do zrobienia projekt na laboratorium z programowania. Już jest prawie skończony jednak występuje kilka problemów. Podaję kod:

#include<iostream>
#include<cmath>
#include<conio.h>
#include<cstdlib>
#include<string>
#include<fstream>
#include<cstring>
#include<ctime>
#include<windows.h>


using namespace std;


string PL( const char * text )
{
    std::string result;
    for(; * text; text++ )
    switch( * text )
    {
    case 'ą': result += static_cast < char >( 0xa5 ); break;
    case 'ć': result += static_cast < char >( 0x86 ); break;
    case 'ę': result += static_cast < char >( 0xa9 ); break;
    case 'ł': result += static_cast < char >( 0x88 ); break;
    case 'ń': result += static_cast < char >( 0xe4 ); break;
    case 'ó': result += static_cast < char >( 0xa2 ); break;
    case 'ś': result += static_cast < char >( 0x98 ); break;
    case 'ż': result += static_cast < char >( 0xbe ); break;
    case 'ź': result += static_cast < char >( 0xab ); break;
    case 'Ą': result += static_cast < char >( 0xa4 ); break;
    case 'Ć': result += static_cast < char >( 0x8f ); break;
    case 'Ę': result += static_cast < char >( 0xa8 ); break;
    case 'Ł': result += static_cast < char >( 0x9d ); break;
    case 'Ń': result += static_cast < char >( 0xe3 ); break;
    case 'Ó': result += static_cast < char >( 0xe0 ); break;
    case 'Ś': result += static_cast < char >( 0x97 ); break;
    case 'Ż': result += static_cast < char >( 0xbd ); break;
    case 'Ź': result += static_cast < char >( 0x8d ); break;
        default: result += * text; break;
    }
    return result;
}


struct odpowiedz
{
	char tresc[30];
	bool prawda;
};

struct pytania
{
	int id_pytania;
	char tresc_pytania[150];
	odpowiedz odpowiedz1;
	odpowiedz odpowiedz2;
	odpowiedz odpowiedz3;
	odpowiedz odpowiedz4;
};

#pragma pack(push, 1)
struct testowani
{
	int id_testowanego;
	char imie[20];
	char nazwisko[20];
	char pesel[11];
	int wynik;
};
#pragma pack(pop)


void wyniki();
void wybor_testowanego();
void dodawanie_pytania();
void administrowanie();
void dodawanie_testowanego();
int menuGlowne();
int test(int);
void wpisywanieHasla();
char czyPoprawny(char pes[]);
void komunikat_o_malej_ilosci_pytan();
void zapisywanie_wyniku(int id_test,int wynik);

int main()

{
	cout << PL("Witaj w teście z matematyki") << endl;
	menuGlowne();

	return 0;
}

int menuGlowne()
	{	
	
	system("cls");
	cout << PL("MENU GŁÓWNE") << endl;
	cout << PL("1. Rozwiąż test") << endl << PL("2. Administruj danymi") << endl << PL("Inny klawisz -> Wyjdź z programu") << endl;
	char decyzja;
	decyzja=getch();
	if (decyzja=='1')
		wybor_testowanego();
		else if (decyzja=='2')
			wpisywanieHasla();
			else return 0;
	}

void wybor_testowanego()
	{
		testowani testowany;
		char s_pesel[11];
		cout << "Wybor testowanego" << endl;
		cout << PL("Podaj swój PESEL: "); cin >> s_pesel;
		ifstream plik("students.dat",ios::binary | ios::in);
		if (plik.good()==false)
		{
			dodawanie_testowanego();
			cout << "Nikogo nie ma w bazie" << endl;
		} else
		{
		
		for(int i=0;;i++)
				{
				plik.seekg(sizeof(struct testowani)*i);
				plik.read(reinterpret_cast<char*>(&testowany),sizeof(testowany));
				if (strcmp(s_pesel, testowany.pesel)==0)
                	{
					test(testowany.id_testowanego);
                    return;
                	}
				if (plik.eof())
				break;
				}
		}
		plik.close();

		cout << "Twojego peselu nie ma w bazie. Dodaj swoje dane do bazy." << endl;
		dodawanie_testowanego();
	}
	
void dodawanie_testowanego()
	{
		int dlugoscPliku;
 		fstream fs;
  		fs.open( "students.dat", ios::binary | ios::in );
  		if ( fs )
  			{
    			fs.seekg( 0, ios::end );
   				dlugoscPliku = fs.tellg();
    			fs.seekg( 0, ios::beg );
			}
		fs.close();
		char poprawnoscPeselu;
		testowani testowany;
		float iloscRekordow;
		fstream plik("students.dat",ios::binary | ios::out | ios::app | ios::in);
		iloscRekordow=dlugoscPliku/sizeof(testowany);
		cout << "Dodawanie testowanego" << endl;
		testowany.id_testowanego=iloscRekordow+1;
		cout << PL("Podaj imię: ");
		cin >> testowany.imie;
		cout << PL("Podaj nazwisko: ");
		cin >>testowany.nazwisko;
		cout << PL("Podaj PESEL: ");
		do
		{
			cin >> testowany.pesel;
			poprawnoscPeselu=czyPoprawny(testowany.pesel);
			cout << "\n";
			if (poprawnoscPeselu==0)
				cout << PL("Podaj poprawny 11-cyfrowy PESEL!") << endl;
		} while (poprawnoscPeselu==0);
		testowany.wynik=0;
		plik.write(reinterpret_cast<char*>(&testowany),sizeof(testowany));
		plik.close();
		cout << "\nNowy testowany dodany poprawnie!\n" << endl;
		cout << PL("Naciśnij dowolny klaiwsz, aby wrócić do menu głównego...");
		getch();
		menuGlowne();
	}


void dodawanie_pytania()
	{
		system("CLS");
		pytania pytanie;
		int dlugoscPliku;
 		ifstream fs;
  		fs.open( "qs.dat", ios::binary | ios::in );
  		if ( fs )
  			{
    			fs.seekg( 0, ios::end );
   				dlugoscPliku = fs.tellg();
    			fs.seekg( 0, ios::beg );
			}
		fs.close();
		int iloscRekordow;
		fstream plik("qs.dat",ios::binary | ios::out | ios::app | ios::in);
		iloscRekordow=dlugoscPliku/sizeof(pytanie);
		cout << "Dodawanie pytania" << endl;
		pytanie.id_pytania==iloscRekordow+1;
		cout << PL("Podaj treść pytania") << endl;
		cin.sync();
		cin.get( pytanie.tresc_pytania, 150 );
		cout << PL("Podaj pierwszą odpowiedź") << endl;
		cin.sync();
		cin.get( pytanie.odpowiedz1.tresc, 30 );
		cout << "Czy ta odpowiedz jest poprawna? 1 -TAK / 0 - NIE" << endl;
		cin >> pytanie.odpowiedz1.prawda;
		cout << PL("Podaj drugą odpowiedź") << endl;
		cin.sync();
		cin.get( pytanie.odpowiedz2.tresc, 30 );
		cout << "Czy ta odpowiedz jest poprawna? 1 -TAK / 0 - NIE" << endl;
		cin >> pytanie.odpowiedz2.prawda;
		cout << PL("Podaj trzecią odpowiedź") << endl;
		cin.sync();
		cin.get( pytanie.odpowiedz3.tresc, 30 );
		cout << "Czy ta odpowiedz jest poprawna? 1 -TAK / 0 - NIE" << endl;
		cin >>pytanie.odpowiedz3.prawda;
		cout << PL("Podaj czwartą odpowiedź") << endl;
		cin.sync();
		cin.get( pytanie.odpowiedz4.tresc, 30 );
		cout << "Czy ta odpowiedz jest poprawna? 1 -TAK / 0 - NIE" << endl;
		cin >> pytanie.odpowiedz4.prawda;
		plik.write(reinterpret_cast<char*>(&pytanie),sizeof(pytanie));
		plik.close();
		administrowanie();
	}



void administrowanie()
	{
		system("cls");
		cout << "MENU ADMINISTRATORA" << endl;
		cout << PL("Wybierz, co chcesz zrobić") << endl;
		cout << PL("1. Dodaj pytanie \n2. Wyświetl wyniki \n3. Powrót do menu głównego \nInny klawisz -> Wyjdź") << endl;
		char wybor;
		wybor=getch();
		if (wybor=='1')
			dodawanie_pytania();
			else if (wybor=='2')
					wyniki();
					else if (wybor=='3')
					menuGlowne();
					else exit(0);


	}

void wpisywanieHasla()
{
		string haslo;
		string wpisane;
		haslo="matematyka";
		cout << PL("Podaj hasło dostępu... ");
		do
		{
			cin >> wpisane;
			cout << "\n";
			if (wpisane!=haslo)
				cout << PL("Nieprawidłowe hasło, podaj ponownie") << endl;
		} while (wpisane!=haslo);
		administrowanie();

}

    
		
int test(int id)
	{
	int los;
	int iloscRekordow;
	char odp;	
	int wynik_testu = 0;
	pytania pytanie;
	int dlugoscPliku;
	int wylosowane_pytania[10];
	system("cls");
  	fstream plik("qs.dat",ios::binary | ios::out | ios::app | ios::in);
  		if ( plik )
  			{
    			plik.seekg( 0, ios::end );
   				dlugoscPliku = plik.tellg();
    			plik.seekg( 0, ios::beg );
			}
	
	plik.close();
	iloscRekordow=dlugoscPliku/sizeof(pytanie);
	cout << PL("Ilość pytań ") << iloscRekordow << endl;
	if (iloscRekordow<10)
		komunikat_o_malej_ilosci_pytan();
		else
	{
	

	cout << PL("Za chwilę zostanie wyświetlone 10 pytań.\nNa każde z nich odpowiedz wciskając odpowiadającą \nodpowiedzi literę na klawiaturze.\nNa pytanie możesz odpowiedzieć tylko raz,\nnie możesz wrócić do pytania, na które udzielono odpowiedzi!\n") << endl;
	cout << PL("Aby rozpocząć test, naciśnij Enter...") << endl;
	getch();
	srand(time(NULL));
			// LOSOWANIE 10 PYTAŃ
    int ile_pytan = iloscRekordow; 
    int ile_juz_wylosowano=0; 
    int *wylosowane = new int[11]; 
    bool losowanie_ok;

    for (int i=1; i<=10; i++)
    {
		do
		{
            int liczba=rand()%11;
            losowanie_ok=true;

			for (int j=1; j<=ile_juz_wylosowano; j++)
			{
				
				if (liczba==wylosowane[j]) losowanie_ok=false;
			}

			if (losowanie_ok==true)
			{
				
				ile_juz_wylosowano++;
				wylosowane[ile_juz_wylosowano]=liczba;
			}
		} while(losowanie_ok!=true);
    }
	for (int i=1;i<=10;i++) // PĘTLA WYPISUJĄCA 10 PYTAŃ
	{
	system("CLS");
	cout << "Pytanie " << i <<"/10\n\n" << endl;
	ifstream plik2("qs.dat",ios::binary | ios::in);
        
            plik2.seekg(sizeof(struct pytania)*wylosowane[i]);
			plik2.read(reinterpret_cast<char*>(&pytanie),sizeof(pytanie));
			cout << pytanie.tresc_pytania << endl;
			cout << "A. " << pytanie.odpowiedz1.tresc << endl;
			cout << "B. " << pytanie.odpowiedz2.tresc << endl;
			cout << "C. " << pytanie.odpowiedz3.tresc << endl;
			cout << "D. " << pytanie.odpowiedz4.tresc << endl;
			plik2.close();
			odp=getch();
	switch (odp)
	{
	
		case 'A':
		case 'a':
			{
				if (pytanie.odpowiedz1.prawda)
				wynik_testu++;
				break;
			}
		case 'B':
		case 'b':
			{
				if (pytanie.odpowiedz2.prawda)
				wynik_testu++;
				break;
			}
		case 'C':
		case 'c':
			{
				if (pytanie.odpowiedz3.prawda)
				wynik_testu++;
				break;
			}
		case 'D':
		case 'd':
			{
				if (pytanie.odpowiedz4.prawda)
				wynik_testu++;
				break;
			}
	}
	}
	cout << "Twoj wynik to: " << wynik_testu << endl;
	if (wynik_testu>5)
		{	
			cout << PL("TEST ZALICZONY!") << endl;
		}
		
	else 
		{
			cout << PL("TEST NIEZALICZONY!") << endl;
		}
	zapisywanie_wyniku(id,wynik_testu);
	
	cout << PL("\nAby powrócić do menu głównego, naciśnik dowolny klawisz...") << endl; getch();
	menuGlowne();
	
	}
	
	}
void zapisywanie_wyniku(int id_test,int wynik)
	{
	testowani testowany;
	ofstream plik1("students.dat",ios::binary | ios::out | ios::ate);
	plik1.seekp(sizeof(testowany)*(id_test-1));
	testowany.wynik=wynik;
	plik1.write(reinterpret_cast<char*>(&testowany),sizeof(testowany));
	plik1.close();
	}	

void wyniki()
{
	system("CLS");
	testowani testowany;
	ifstream plik("students.dat",ios::binary | ios::in);
	cout << "Wyniki:" << endl;
			for (int i=0;;i++)
				{
				if (plik.eof())
				break;
				plik.seekg(sizeof(struct testowani)*i);
				plik.read(reinterpret_cast<char*>(&testowany),sizeof(testowany));
				cout << testowany.imie << " " << testowany.nazwisko << " PESEL: " << testowany.pesel << " WYNIK: " << testowany.wynik << endl;
				
				} 
	plik.close();
	cout << PL("\n\nNaciśnij dowolny klawisz, aby powrócić...") << endl; getch(); administrowanie();
}

char czyPoprawny(char pes[11])
	{
    	int tab[11]={1,3,7,9,1,3,7,9,1,3};
    	int a,suma=0;
    	for(a=0;a<10;a++){
        suma=suma+(tab[a]* (pes[a]-48));
    	}
    	suma=suma%10;
    	suma=10-suma;
    	suma+=48;
    	if (suma!=pes[10]) return 0;
		else return 1;
	}
void komunikat_o_malej_ilosci_pytan()
	{
			cout << PL("Nie można wylosować pytań, gdyż ich liczba w \nbazie jest mniejsza niż wymagane 10!") << endl;
			cout << PL("Nastąpi powrót do Menu Głównego w celu dodania pytań") << endl;
			Sleep(1000);
			cout << "......." << endl;
			Sleep(1000);
			cout << "......" << endl;
			Sleep(1000);
			cout << "....." << endl;
			Sleep(1000);
			cout << "...." << endl;
			Sleep(1000);
			cout << "..." << endl;
			Sleep(1000);
			cout << ".." << endl;
			Sleep(1000);
			cout << "." << endl;
			Sleep(1000);
			menuGlowne();
			
		} 

Chodzi o to, że:

  1. Po wykonaniu testu nie zapisuje wyniku. Tzn. wynik zapisuje jednak takie dane jak imię nazwisko i pesel kasuje. W funkcji wybor_testowanego, funkcja write zapisuje do struktury odczytane dane i powinna je cały czas przechowywać. Jednak w funkcji zapisywanie_wyniku zmieniam tylko wynik i zapisuję strukturę do pliku w miejsce starej. Jednak nie chce to działać. Jakieś sugestie jak to rozwiązać?

  2. Wyświetlanie wyniku. Funkcja wyniki wyświetla wyniki. Jednak jeśli w bazie jest jeden testowany to wyświetla dwa razy ten rekord. Kiedy jest kilka to ostatni wyświetla dwa razy. Przeniosłem if z breakiem na początek pętli, żeby najpierw sprawdziło, czy koniec pliku, jednak nic to nie pomogło Tu również proszę o pomoc.

EDIT:

testowani testowany;

Dałem jako zmienną globalną i punkt pierwszy działa, dodaje tylko jeden znak do peselu nie wiem dlaczego. Jednak w projekcie nie można używać zmiennych globalnych więc muszę to osiągnąć inaczej.

0

co to za bzdury z tym case 'ą'. char przechowuje wartości -127 - 127 co odpowiada w jakiś sposób kodom ascii. Nie możesz tam przechować ą.
http://www.cplusplus.com/reference/cwchar/
http://www.cplusplus.com/reference/cwchar/wchar_t/

0

Tą funkcję string PL znalazłem w internecie jako sposób na wyświetlanie polskich znaków w konsoli.

0

No to bzdury znalazłeś. Masz jeszcze
http://www.cplusplus.com/reference/iostream/wcout/

1
lukaszek016 napisał(a):

Tą funkcję string PL znalazłem w internecie jako sposób na wyświetlanie polskich znaków w konsoli.
Dobrze radze nie grze w śmietnikach.
Naucz się używać tablic:

char trans(char ch)
  {
   static char PL[]="\xa5\x86\xa9\x88\xe4\xa2\x98\xbe\xab\xa4\x8f\xa8\x9d\xe3\xe0\x97\xbd\x8dąćęłńóśżźĄĆĘŁŃÓŚŻŹ";
   char *p=strchr(PL+18,ch);
   return p?*(p-18):ch;
  }

string PL(const char *text)
  {
   string result(text);
   for(size_t i=0;i<result.size();++i) result[i]=trans(result[i]);
   return result;
  }

Oczywiście lepiej jednak użyć gotowych funkcji jak podano w poście wyżej.

Reszta kodu też zrobiona metodą Kopiego Pejsta bez pojęcia o tym że istnieją pętle i tablice.

0

Resztę kodu pisałem zupełnie sam. Metodę zapisu do pliku i odczytu brałem z notatek z wykładów. Oczekuję pomocy, a nie bezsensownej krytyki. Jestem na pierwszym semestrze, nie wiem jeszcze wszystkiego.

Chodzi mi tylko o dwie rzeczy, ukończeniu testu, program zapisuje wynik, jednak do peselu dodaje znak serca.
Druga sprawa to, że wyświetla dwa razy ten sam rekord w wynikach. Jeśli jest więcej testowanych to dwa razy ten sam ostatni. Może zrobiłem gdzieś jakiś głupi błąd, nie wiem.

EDIT: Ok, sprawę powtarzania w wynikach rozwiązałem.
Jednak problem z dodatkowym znakiem występuje nadal. Dodatkowo, kiedy kolejna osoba rozwiąże test, to kasują się dane poprzedniej osoby. Czyli z zapisem wyników jest coś nie tak. Miałem w każdej funkcji, która korzysta ze struktury testowani zadeklarowaną zmienną typu testowani, jednak nie wiem, jak zapisać tylko wynik do pliku, a imię i nazwisko pozostawić bez zmian.

1
  1. Zapoznaj się z inkrementacją bo jej nie rozumiesz: http://4programmers.net/Forum/1101404
  2. Zapoznaj się z tablicami - odpowiedzi ma być tablicą
  3. Zamiast przy każdej odpowiedzi pytać czy poprawna, może lepiej na końcu spytać która z podanych jest poprawna?
  4. Pesel ma 11 znaków plus znak końca napisu.
  5. eof się ustawia przy nieudanej próbie odczytu - najpierw wyświetlasz wynik nieudanej próby.
2

Czemu go zwodzicie na manowce próbując naprawić tą bzdurę?
Tu się rozchodzi o kodowanie znaków. Jeśli byś utrzymywał jednolite kodowanie w swoim programie i w konsoli, nie musiałbyś robić takich dziwnych rzeczy.
Jeśli kodowanie to UTF-8 to wtedy jedna litera (taka jak ą) jest reprezentowana przez kilka następujących po sobie znaków.
Kodowanie "Windows-1250" jest jedno bajtowe i udostępnia polskie znaki (ale nie obsłuży np japońskiego, arabskiego, itp).
Nie potrafię ustalić jakie kodowanie wpisałeś w tym PL.
Doczytaj o kodowaniu napisów i wywal te twoje koślawe protezy.

Jak używasz C++ to już bądź konsekwentny i używaj C++ (wywal napisy jako tablice char).

1

Ogólnie zapis i odczyt pytań w postaci binarnej jest dla ciebie zbyt trudna.
Zapisuj tekstowo. Wtedy zbudowanie pliku z pytaniami będzie proste (edytor tekstowy).

struct odpowiedz
{
    string tresc;
    bool prawda;
};
 
struct pytanie
{
    string tresc_pytania;
    odpowiedz odpowiedzi[4];
};

istream& operator>>(istream& in, odpowiedz& odp)
{
      return getline(in, odp.tresc) >> odp.prawda >> std::ws;
}

istream& operator>>(istream& in, pytanie& pyt)
{
      return getline(in, odp.tresc_pytania) >> odpowiedzi[0] >> odpowiedzi[1] >> odpowiedzi[2] >> odpowiedzi[3];
}

istream& operator>>(istream& in, vector<pytanie>& zastawPytan)
{
     pytanie pyt;
     while(in >> pyt)
          zastawPytan.push_back(pyt);
     return in;
}

vector<pytanie> WczytajPytania()
{
      ifstream plik("qs.dat");

      vector<pytanie> zestaw;
      plik >> zestaw;

      return zestaw;
}

Plik "qs.dat" może wyglądać tak:

Pytanie Pierwsze
Odpowiedz 1
1
Odpowiedz 2
0
Odpowiedz 3
0
Odpowiedz 4
0

Kolejne pytanie
Zagadka 1
0
Zagadka 2
1
Zagadka 3
0
Zagadka 4
0

nastepne pytanie
Zagadka 1
0
Zagadka 2
0
Zagadka 3
0
Zagadka 4
1

Jeśli będziesz miał jednolite kodowanie UTF-8 w edytorze tekstowym (w którym wprowadzisz pytania), oraz w konsoli w której uruchomisz program, wszystko będzie działać bez jakichkolwiek udziwnień (nawet jeśli wpiszesz pytanie po chińsku).

0

Jeśli chodzi inkrementację to chodzi Wam o to, że piszę i++, a powinienem ++i? Nie pomyślałem o tym, w październiku pierwszy raz zetknąłem się z C++, poprzednio do czynienia miałem kilka lat temu w liceum z Pascalem.

Generalnie w poleceniu jest, że nie wolno wczytywać do tablicy i operować tablicą. Operacje tylko na plikach. Możemy używać tylko tego, co było na zajęciach, także wektory też odpadają. Najprościej mi było to zrobić na binarnych, przynajmniej tak mi się wydawało. W sobotę muszę projekt przedstawić, dlatego bardzo nie chcę tego już zmieniać tylko naprawić to, co jest źle.

Co do tej tablicy znaków, byłem na konsultacjach dwa tygodnie temu, prowadzący się zgodził na takie coś, jest mi też prościej na tym operować.

Co do problemu to z pytaniami nie ma żadnego, punkty zlicza dobrze. Problem jest tylko z zapisem wyników do pliku. Kiedy dodam testowanego, nawet 10 testowanych w menu głównym, a potem wyświetlę wyniki to jest dobrze, wszystko wyświetla, żadnych dodatkowych znaków. Problem zaczyna się, kiedy rozwiążę test, a następnie zapiszę wynik. Załóżmy są dwie osoby w bazie. Rozwiązuje test jako osoba druga na liście. Po rozwiązaniu i przejściu do wyświetlenia wyników na końcu peselu osoby testowanej dodawany jest znak, a dane poprzedniej osoby są kasowane lub zastępowane dziwnymi znakami.

Wychodzi na to, że problem jest z funkcją zapisującą wynik. Tylko tu proszę o pomoc. Jeśli to możliwe, to nie chcę pisać od nowa całego programu, gdyż muszę jeszcze zrobić do tego dokumentację, egzamin w sobotę, a do tego praca w tygodniu dochodzi. Proszę o pomoc.

0

Może jeszcze jedna rada, załóż że w pliku poprawna odpowiedź musi być pierwsza.
Wtedy lekko zmieniając to co podał @MarekR22:

#include <vector>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;

struct Pytanie
  {
   string pytanie,odpowiedzi[4];
   int order[4];
   Pytanie()
     {
      for(int i=0;i<4;++i) order[i]=i;
      random_shuffle(order,order+4);
     }
   friend istream &operator>>(istream &s,Pytanie &p)
     {
      getline(s>>ws,p.pytanie);
      for(int i=0;i<4;++i) getline(s,p.odpowiedzi[i]);
      return s;
     }
   friend ostream &operator<<(ostream &s,const Pytanie &p)
     {
      s<<p.pytanie<<endl;
      for(int i=0;i<4;++i) s<<((char)('A'+i))<<". "<<p.odpowiedzi[p.order[i]]<<endl;
     }
   bool czyPoprawnaOdpowiedz(char odp)
     {
      return !order[toupper(odp)-'A']; 
     }
  };
 
vector<Pytanie> WczytajPytania()
  {
   vector<Pytanie> zestaw;
   ifstream plik("qs.dat");
   copy(istream_iterator<Pytanie>(plik),istream_iterator<Pytanie>(),back_inserter(zestaw));
   random_shuffle(zestaw.begin(),zestaw.end());
   return zestaw;
  }

istream &eater(istream &s)
  {
   while(s.get()!='\n') {}
   return s;
  }

int main()
  {
   vector<Pytanie> zestaw(WczytajPytania());
   for(auto &x:zestaw)
     {
      for(char ch;;)
        {
         cout<<x<<"Odp: ";
         cin>>ch>>eater;
         ch=toupper(ch);
         if(('A'<=ch)&&(ch<='D'))
           {
            if(x.czyPoprawnaOdpowiedz(ch)) cout<<"Dobrze"<<endl; 
            else cout<<"Zle"<<endl; 
            break;
           }         
        }      
     }   
   return 0;
  }

qs.dat (zawsze pierwsza poprawna):

Pytanie Pierwsze
Odpowiedz 3* 
Odpowiedz 1
Odpowiedz 2
Odpowiedz 4

Kolejne pytanie
Zagadka 2*
Zagadka 1
Zagadka 3
Zagadka 4
 
nastepne pytanie
Zagadka A*
Zagadka B
Zagadka C
Zagadka D
0
lukaszek016 napisał(a):

Generalnie w poleceniu jest, że nie wolno wczytywać do tablicy i operować tablicą.

No to nie ma problemu. Zamiast vector robisz odpowiednią pętle i czytasz wszystko aż do napotkania właściwego pytania (rozwiązanie łatwe).
Rozwiązanie zaawansowane, to stworzyć plik z indeksem pozycji pytań w pliku tekstowym (i napisać program, który będzie generował taki indeks).

0

Hmm, a nie może zostać tak jak jest? Z pytaniami wszystko jest w porządku(w takim porządku, że działa). Rozumiem, że kod mój może być mało wydajny, jednak, to moje początki, także wystarczy to co jest. Pliku z pytaniami nie mogę tworzyć w notatniku, musi być tworzony w programie. Generalnie to, co teraz mam jest dla mnie zrozumiałe i w razie pytań o zasadę działania jestem w stanie to prowadzącemu wytłumaczyć. Chodzi mi tylko o zmianę jednej zmiennej w strukturze 'testowani'. Zdefiniowałem zmienną globalną o typie testowani, w funkcji 'wybor_testowanego' do tej zmiennej podstawiane są dane odczytane w pętli for, która sprawdza pesel. Potem tych danych nie zmieniam, dopiero w funkcji zapisywanie_wyniku zmieniam jedynie 'testowany.wynik' i kasuje się poprzedni rekord w pliku.

Możecie mi wyjaśnić dokładniej o co chodzi z tym ostatnim znakiem w peselu w pkt 4? Jak to rozwiązać?

1

C-string musi być zakończony znakiem '\0'

0

Ale w deklaracji muszę coś zmieniać? Np. mam zmienić na char pesel[12]? Czy 13? I gdzie to zapisać \0? I dlaczego dzieje się takie coś tylko na peselu, a nie np. na imieniu czy nazwisku nie?

I to rozwiąże problem z zapisywaniem wyniku?

0

Mam cię wkleić fragment kursu na temat C-string czy sam sięgniesz?

0

No widziałem ten kurs. Czyli chodzi o to, że pesel ma 11 znaków, to muszę zadeklarować tablicę 12 elementową, gdyż 1 bajt to znak null. I to wszystko?

1
lukaszek016 napisał(a):

mam zmienić na char pesel[12]? Czy 13?

12

lukaszek016 napisał(a):

I gdzie to zapisać \0? I dlaczego dzieje się takie coś tylko na peselu, a nie np. na imieniu czy nazwisku nie?

I to rozwiąże problem z zapisywaniem wyniku?

no na końcu

lukaszek016 napisał(a):

I dlaczego dzieje się takie coś tylko na peselu, a nie np. na imieniu czy nazwisku nie?

Otóż w imieniu i nazwisku też się tak dzieje. Jeżeli wpiszesz jakieś 20-znakowe imię/nazwisko to przy wczytywaniu program będzie chciał \0 zapisać już poza tablicą, pod indeksem 20. Z tego właśnie powodu takie coś jest niebezbieczne

cin >>testowany.nazwisko;
0

Ok. Pesel działa, nie pokazuje innych znaków. Jednak przy rozwiązaniu testu przez kolejnego testowanego, program "kasuje" dane z pliku poprzednich testowanych. Problem jest prawdopodobnie w funkcji zapisywanie_wyniku.

0

Witam. Problem rozwiązany. W zapisie wyniku linia z otwarciem pliku powinna wyglądać tak:

ofstream plik1("students.dat",ios::binary | ios::in | ios::ate);
	plik1.seekp(sizeof(struct testowani)*(id_test-1));
	plik1.write(reinterpret_cast<char*>(&testowany_save),sizeof(testowany_save));
	plik1.close(); 

Dodanie ios::in rozwiązało problem.
Dziękuję wszystkim za pomoc. Pozdrawiam.

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