Projekt bazy danych studentów przy użyciu listy dwukierunkowej wykonany w C++ przy użyciu funkcji i klas. Projekt dla I roku studiów Informatycznych. Projekt uruchamiany pod Visual Studio 2008.

Szczególne funkcje programu:
- automatyczne ładowanie bazy po uruchomieniu programu
- przy wyjściu z programu jesteśmy pytani o to czy zapisać zmiany w bazie
- przy zapisywaniu bazy danych możemy nadpisać rekordy w pliku txt rekordami z bazy znajdującej się w pamięci programu lub możemy dopisać rekordy do bazy txt.
Dopisanie rekordów oznacza przydzielenie im nowych numerów ID tak aby nie powtarzały się z tymi które już istnieją w pliku txt.
- Kasowanie bazy: albo tej w pamięci programu albo tej w pliku txt

- Dodawanie rekordów: możemy dodawać je na początek listy lub na koniec (tak jak to powinno funkcjonować według idei listy dwukierunkowej)
- Usuwanie rekordu: Przed usunięciem wyświetlana jest lista rekordów abyśmy mogli poznać ID rekordu który chcemy usunąć.
- Edycja rekordu: Podczas edycji możemy pominąć wpisywanie nowego pola poprzez podanie słowa: "ok"
- Podczas dodawania lub edycji rekordu sprawdzane jest czy podajemy poprawny ID lub rok studiów jako liczbę. Inne pola także są sprawdzane np.
jeśli podamy puste pole to zostaniemy poproszeni o podanie tekstu ponownie

- Sortowanie wyników przy użyciu QuickSort. Wyniki możemy sortować po poszczególnych polach. Mamy możliwość wybrania sposobu wyświetlenia
ich od najmniejszego do największego (ASC), od największego do najmniejszego (DESC)
- Po posortowaniu rekordów mamy możliwość zapamiętania tej kolejności wyników na stałe w pamięci programu.

- Wyszukiwanie w bazie następuje po wskazanym kryterium. Jeśli wyszukujemy po tekście np. imie, nazwisko itd to wyszukiwanie następuje poprzez
dopasowanie wzorca
. Np. jeśli wpiszemy aby wyszukiwać po kierunku studiów i podamy jako wzorzec "inf" to otrzymamy rekordy pasujące do niego
np. kierunek informatyka
- Wyniki wyszukiwania możemy zapisać do pliku txt. Zapamiętana jest data wyszukiwania, kryterium i wzorzec według którego szukaliśmy rekordów,
liczba rekordów.

Główny plik programu: Baza danych studentow.cpp



/*
The MIT License

Copyright (c) 2010 Webook.pl

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Baza danych studentow.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <conio.h> // zawiera funkcja getch()
#include <ctime> // time()
#include <Windows.h> //zawiera funkcje SetConsoleTextAttribute
#include "CBazaDanych.h"

using namespace std;

//=============================================================

//deklaracja funkcji globalnych
void color(int);
void clear_screen();
void menu_glowne();

//=============================================================

//tworzymy obiekt db naszej bazy danych
CBazaDanych db;

//=============================================================
//=============================================================

int _tmain(int argc, _TCHAR* argv[])
{
db.WczytajBazeZPliku(0, 0); //ladujemy baze danych przy uruchomieniu programu, 0- nie wyswietlamy komunikatu czy wczytac baze, 0-nie kasujemy baze, bo przy pierwszym ladowaniu baza jest juz pusta
menu_glowne();
db.SaveAutoIncrement(); //zapisanie wartosci ostatnio dodanego ID
return 0;
}

//=============================================================
//=============================================================

void color(int i) { // funkcja wlacza kolorowanie napisow drukowanych przez cout
if(i==1) { // czerwony
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
} else if(i==2) { // bialy
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else if(i==3) { // zielony
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
} else if(i==4) { // niebieski
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
} else if(i==5) { // czarno na bialym
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE);
} else { // domyslny kolor tekstu w konsoli
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
}

//=============================================================

void clear_screen()
{
system("cls");
cout<<"====== Baza danych studentow v1.0 25.05.2010 Webook.pl ======n";
db.ReturnAutoIncrementAndLiczbaRekordow();

color(1);
cout<<"1";
color(0);
cout<<" - wczytaj baze z pliku, ";

color(1);
cout<<"2";
color(0);
cout<<" - zapisz baze, ";

color(1);
cout<<"3";
color(0);
cout<<" - skasuj bazen";

color(3);
cout<<"4";
color(0);
cout<<" - dodaj nowy rekord, ";

color(3);
cout<<"5";
color(0);
cout<<" - usun rekord, ";

color(3);
cout<<"6";
color(0);
cout<<" - edytuj rekordn";

color(4);
cout<<"7";
color(0);
cout<<" - wyswietl rekordy, ";

color(4);
cout<<"8";
color(0);
cout<<" - posortuj rekordy, ";

color(4);
cout<<"9";
color(0);
cout<<" - wyszukaj rekordyn";

color(2);
cout<<"k";
color(0);
cout<<" - koniecnn";
}

//=============================================================

void menu_glowne()
{
clear_screen();

char nawigacja;
bool wybrano_poprawny_klawisz = 0;
bool exit = 0;

do {
nawigacja = _getch(); // pobiera znak tak dlugo az zostana wcisniete strzalki gora/dol lub enter
switch(nawigacja) {
case '1':
db.WczytajBazeZPliku(1, 1);//1-wyswietl komunikat z pytaniem czy zaladowac baze, 1-uruchom funkcje czyszczaca baze przed zaladowaniem rekordow z pliku
wybrano_poprawny_klawisz = 1;
break;
case '2':
db.ZapiszBazeDoPliku();
wybrano_poprawny_klawisz = 1;
break;
case '3':
cout<<"Czy aby na pewno chcesz skasowac baze danych? Wybierz dzialanie:n"
<<"1 - Skasuj baze danych zawarta w pamieci programun"
<<"2 - Skasuj tylko baze danych w pliku txtn"
<<"3 - Anulujnn";
char nawigacja_kasuj;
do {
nawigacja_kasuj = _getch();
} while(nawigacja_kasuj != '1' && nawigacja_kasuj != '2' && nawigacja_kasuj != '3');
if(nawigacja_kasuj == '1') {
db.SkasujBaze(1);//wyswietlamy komunikaty o udanym skasowaniu oraz zapytanie czy zapisac rowniez zmiany w bazie txt
} else if(nawigacja_kasuj == '2') {
db.WyczyscBazeDanychWPliku();
cout<<"Baza danych w pliku txt zostala wyczyszczona!";
} else {
cout<<"Anulowano kasowanie bazy...";
}
wybrano_poprawny_klawisz = 1;
break;
case '4':
cout<<"1 - Dodaj element na poczatek listyn"
<<"2 - Dodaj element na koniec listyn"
<<"3 - Anulujnn";
char nawigacja_dodaj;
do {
nawigacja_dodaj = _getch();
} while(nawigacja_dodaj != '1' && nawigacja_dodaj != '2' && nawigacja_dodaj != '3');
if(nawigacja_dodaj == '1') {
db.DodajNaPoczatek();
} else if(nawigacja_dodaj == '2') {
db.DodajNaKoniec();
} else cout<<"Anulowano...";
wybrano_poprawny_klawisz = 1;
break;
case '5':
db.UsunRekord();
wybrano_poprawny_klawisz = 1;
break;
case '6':
db.EdytujRekord();
wybrano_poprawny_klawisz = 1;
break;
case '7':
db.WyswietlRekordy();
wybrano_poprawny_klawisz = 1;
break;
case '8':
db.SortujRekordy();
wybrano_poprawny_klawisz = 1;
break;
case '9':
db.WyszukajRekordy();
wybrano_poprawny_klawisz = 1;
break;
case 'k':
cout<<"UWAGA!! Zanim wyjdziesz z programu:n ";
db.ZapiszBazeDoPliku(1,0);//0 oznaczacza ze nie pytamy sie czy zaladowac do pamieci programu zaktualizowana baze
wybrano_poprawny_klawisz = 1;
exit = 1;
break;
}
} while(wybrano_poprawny_klawisz==0);
if(exit!=1) {
cout<<"nn";
system("pause");
menu_glowne();
}
}

Plik nagłówkowy: CBazaDanych.h



/*
The MIT License

Copyright (c) 2010 Webook.pl

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "stdafx.h"
#include <string>
#include <fstream>
#include <conio.h>
#include <iostream>

using namespace std;

//=============================================================

// struktura listy dwukierunkowej
struct element {
element* next;
element* prev;
int id;
string imie;
string nazwisko;
int rok_studiow;
string kierunek;
};

// deklaracja i definicje metod klasy bazy danych
//=============================================================

class CBazaDanych
{
private:
//przechowuje id rekordu ostatnio dodanego, dzieki temu wiemy jaki nastepny ID przypisac dla kolejnego rekordu
int AutoIncrement;
int LiczbaRekordow; //zawiera liczbe rekordow akutalnie przechowywanych na liscie
element* lista_poczatek; //wskaznik na pierwszy element listy
element* lista_koniec; //wskaznik na ostatni element listy
const char* URL_Baza; //adres pliku z zapisana baza
const char* URL_AutoIncrement; //adres pliku przechowujacego informacje o ostatnio dodanym ID
const char* URL_LogWyszukiwanie;

// Metody prywatne
void DodajRekordBezposrednio(element* &, element* &, string, string, string, string, string);
void Dodaj(element* &, element* &, int);
void CountLiczbaRekordow();
void QuickSort(element [], int, int, string, int);
int StringFind(string, string, int, int); //funkcja wyszukujaca czy w tekscie wystepuje wzorzec, zwraca 1-tak
string IntToString(int);

public:
// konstruktor
CBazaDanych();
// destruktor
~CBazaDanych();

// Metody publiczne
void WczytajBazeZPliku(bool, bool);
void ZapiszBazeDoPliku(int WyswietlKomunikat=1, int WyswietlKomunikat2=1);
void SkasujBaze(int WyswietlKomunikat=0);
void WyczyscBazeDanychWPliku();
void SaveAutoIncrement();
void ReturnAutoIncrementAndLiczbaRekordow();
void DodajNaPoczatek();
void DodajNaKoniec();
void UsunRekord(int WlaczKomunikaty=1, int ID_delete=0);
void EdytujRekord();
void WyswietlRekordy();
void WyszukajRekordy();
void SortujRekordy();
};

Plik: CBazaDanych.cpp



/*
The MIT License

Copyright (c) 2010 Webook.pl

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>
#include <time.h>
#include <sstream>
#include "CBazaDanych.h"

using namespace std;

//=============================================================

// konstruktor
CBazaDanych::CBazaDanych()
{
//definicja zmienych prywatnych
this->URL_Baza = "baza_log/BazaStudentow.txt";
this->URL_AutoIncrement = "baza_log/AutoIncrement.txt";
this->URL_LogWyszukiwanie = "baza_log/log_wyszukiwanie.txt";

//inicjalizacja wskaznikow prywatych
this->lista_poczatek = NULL;
this->lista_koniec = NULL;
this->LiczbaRekordow = 0;

//ładujemy informacje o numerze ostatniego ID z pliku konfiguracyjnego
// przed odczytem otwieramy plik tak jakbysmy chcieli cos dopisac ale nic nie dopiszemy dzieki temu nieistniejacy plik zostanie utworzony
fstream plik;
plik.open(this->URL_AutoIncrement, ios::app);
plik.close();

// odczyt
ifstream ifile(this->URL_AutoIncrement);
string plik_au;
while(!ifile.eof()) {
getline(ifile,plik_au);
if(plik_au.length() == 0) {
this->AutoIncrement = 0;
} else {
this->AutoIncrement = atoi(plik_au.c_str()); //przypisanie do zmiennej prywatnej informacji o ostatnim ID
//funkcja atoi, HOWTO: http://4programmers.net/C/Konwersje_int_na_string_i_string_na_int#id-string-na-int
}
}
ifile.close();
}

//=============================================================

CBazaDanych::~CBazaDanych()
{
SaveAutoIncrement();
}

//=============================================================

void CBazaDanych::SaveAutoIncrement()
{
fstream plik;
plik.open(this->URL_AutoIncrement, ios::out);
plik<<this->AutoIncrement;
plik.close();
}

//=============================================================

void CBazaDanych::ReturnAutoIncrementAndLiczbaRekordow()
{
CountLiczbaRekordow();//zliczamy liczbe rekordow przed wyswietleniem ich
cout<<"====== ID ostatnio dodanego rekordu: "<<this->AutoIncrement<<", Rekordow w pamieci: "<<this->LiczbaRekordow<<"n";
}

//=============================================================

void CBazaDanych::CountLiczbaRekordow()
{
//zliczamy liczbe rekordow
this->LiczbaRekordow = 0;
if(this->lista_poczatek != NULL) {
element* temp = this->lista_poczatek;
while(temp != NULL)
{
this->LiczbaRekordow++;
temp = temp->next;
}
}
}

//=============================================================

// w_l - wskaznik pierwszego elementu na calej liscie!
// w_k - wskaznik konca listy
// gdzie_dodac==1 dodamy na koniec listy, a gdy==0 to na poczatek
void CBazaDanych::Dodaj(element* &w_l, element* &w_k, int gdzie_dodac)
{
element* wn = new element;

//zwiekszamy wartosci zmiennych prywatynch
this->AutoIncrement++;
this->LiczbaRekordow++;

wn->id = this->AutoIncrement;

cout<<"Podaj imie: ";
getline(cin,wn->imie);
while(wn->imie == "") {
cout<<"Podales pusty ciag znakow! Podaj imie: ";
getline(cin,wn->imie);
}

cout<<"Podaj nazwisko: ";
getline(cin,wn->nazwisko);
while(wn->nazwisko == "") {
cout<<"Podales pusty ciag znakow! Podaj nazwisko: ";
getline(cin,wn->nazwisko);
}

cout<<"Podaj rok studiow: ";
string rok;
int rok_int;
getline(cin,rok); //ładujemy do stringa rok
rok_int = atoi(rok.c_str()); //konwersja stringa na int
while(rok == "" || rok_int == 0) {//jesli nie podano roku lub podany rok to liczba 0, np. jesli ktos zamiast liczby poda slowo to ono jest konwertowane na 0 wiec w takim przypadku ponownie zapytamy o podanie wlasciwego roku
if(rok=="") {//podano pusty ciag znakow zamiast roku
cout<<"Podales pusty rok! Podaj nowy rok studiow: ";
} else { //podano ciag znakow o jakiejs dlugosci ktory zostal zamieniony na liczbe 0
cout<<"Podales ciag znakow zamiast roku liczbowego! Podaj nowy rok studiow: ";
}
getline(cin,rok);
rok_int = atoi(rok.c_str());
}
wn->rok_studiow = rok_int;

cout<<"Podaj kierunek: ";
getline(cin,wn->kierunek);
while(wn->kierunek == "") {
cout<<"Podales pusty ciag znakow! Podaj kierunek: ";
getline(cin,wn->kierunek);
}

if(gdzie_dodac == 1) { //gdzie_dodac==1 to dodajemy na koniec listy
wn->prev = w_k; //poprzedni element przed tym ktory teraz dodalismy to w_k czyli obecny koniec listy
wn->next = NULL; // nastepny element to NULL bo wlasnie dodajemy ostatni element i po nim nic juz nie ma

if(w_k != NULL) {
w_k->next = wn;
} else { //w_k==NULL co znaczy ze dodajemy pierwszy element!
w_l = wn;
}
w_k = wn; //teraz ustawiamy ze nowym elementem koncowym jest nasze wn (wskaznik nowy do elementu ktory wlasnie dodalismy)

cout<<"Dodano na koniec listy!";

} else { //gdzie_dodac==0 to dodajemy na poczatek listy
wn->prev = NULL; //pierwszy element listy nigdy nie ma poprzednika
wn->next = w_l; //nastepnym elementem listy staje sie wskaznik ktory dotychczas pokazywal na poczatek listy

//aktualizujemy wskaznik ktory teraz staje sie drugim elementem listy aby wiedzial ze ma przed soba nasze wn
if(w_l != NULL) {
w_l->prev = wn;
} else { //tylko gdy po raz pierwszy dodajemy rekord to ten dodany wlasnie element staje sie koncowym
w_k = wn;
}
w_l = wn; //naszym nowym poczatkiem listy staje sie wn
cout<<"Dodano na poczatek listy!";
}
}

//=============================================================

//funkcja przyjmujaca jako argumenty stringi, dodajemy nowy rekord na koniec listy
void CBazaDanych::DodajRekordBezposrednio(element* &w_l, element* &w_k, string id, string i, string n, string r, string k)
{
element* wn = new element;

int id_int = atoi(id.c_str()); //konwersja string na int
wn->id = id_int;
wn->imie = i;
wn->nazwisko = n;
int rok_studiow = atoi(r.c_str()); //konwersja string na int
wn->rok_studiow = rok_studiow;
wn->kierunek = k;

//dodajemy na koniec listy
wn->prev = w_k; //poprzedni element przed tym ktory teraz dodalismy to w_k czyli obecny koniec listy
wn->next = NULL; // nastepny element to NULL bo wlasnie dodajemy ostatni element i po nim nic juz nie ma

if(w_k != NULL) {
w_k->next = wn;
} else { //w_k==NULL co znaczy ze dodajemy pierwszy element!
w_l = wn;
}
w_k = wn; //teraz ustawiamy ze nowym elementem koncowym jest nasze wn (wskaznik nowy do elementu ktory wlasnie dodalismy)
cout<<"Dodano rekord: "<<id<<", "<<i<<", "<<n<<", "<<r<<", "<<k<<"n";
this->LiczbaRekordow++;
}

//=============================================================

void CBazaDanych::DodajNaPoczatek()
{
CBazaDanych::Dodaj(this->lista_poczatek, this->lista_koniec, 0);
}

//=============================================================

void CBazaDanych::DodajNaKoniec()
{
CBazaDanych::Dodaj(this->lista_poczatek, this->lista_koniec, 1);
}

//=============================================================

// w_l - wskaznik na pierwszy element listy
void CBazaDanych::WyswietlRekordy()
{
if(this->lista_poczatek == NULL) {
cout<<"Lista jest pusta!";

} else {
element* temp = this->lista_poczatek;
while(temp != NULL)
{
cout<<"ID: "<<temp->id<<"n"
<<"Imie: "<<temp->imie<<"n"
<<"Nazwisko: "<<temp->nazwisko<<"n"
<<"Rok studiow: "<<temp->rok_studiow<<"n"
<<"Kierunek: "<<temp->kierunek<<"n"
<<"==========================================n";

temp = temp->next;
}
}
}

//=============================================================

//domyslne parametry okreslone w CBazaDanych.h
//int WlaczKomunikaty=1, int ID_delete=0
void CBazaDanych::UsunRekord(int WlaczKomunikaty, int ID_delete)
{
if(WlaczKomunikaty) WyswietlRekordy();

if(this->lista_poczatek == NULL && this->lista_koniec == NULL)
{
if(WlaczKomunikaty) cout<<" Nie ma co usuwac!";
}
else
{
int id;
if(WlaczKomunikaty) {
cout<<"nPodaj ID rekordu ktory usunac: ";
string get;
getline(cin,get);
id = atoi(get.c_str()); //konwersja string na int
} else {
id = ID_delete; //usuwamy id ktory przeslalismy jako argument funkcji
}

element* temp = this->lista_poczatek;
int znaleziono = 0; //domyslana zmienna okreslajaca ze nie znaleziono elementu do usuniecia
element* temp_usun;
while(temp != NULL)
{
if(temp->id == id) {
element* temp_prev = temp->prev; //1
element* temp_next = temp->next; //3

//załóżmy że mamy element 1, 2, 3. Element 2 usuwamy.
// Poniżej elementowi 1 ustawiamy iz po nim jest 3
if(temp_prev != NULL) {
temp_prev->next = temp->next; //ustawiamy ze po elemencie 1 jest 3
if(temp->next == NULL) { //to oznacza ze ostatni element nie istnieje wiec element 2 ktory teraz usuwamy jest ostatnim a wiec element 1 bedzie teraz ostatnim wiec musimy mu ustawic ze dla naszej listy wskaznik ostatni to nasz element 1
this->lista_koniec = temp_prev;
}
}
// Poniżej elementowi 3 ustawiamy iz go poprzedza 1
if(temp_next != NULL) {
temp_next->prev = temp->prev;
if(temp->prev == NULL) { //jezeli nie istnieje element 1 to ustawiamy ze element 3 staje sie poczatkiem listy bo skasowalismy element 2
this->lista_poczatek = temp_next;
}
}

//kasujemy element 2
temp_usun = temp;
if(WlaczKomunikaty) cout<<"nUsunieto rekord o ID: "<<temp_usun->id;
delete temp_usun;
//cout<<"ntemp_usun: "<<temp_usun->imie;
//cout<<"ntemp: "<<temp->imie;

this->LiczbaRekordow--; //zmniejszamy liczbe rekordow

if(this->LiczbaRekordow == 0) {
//skasowalismy wszystkie rekordy wiec ustawiamy na NULL wartosci
this->lista_poczatek = NULL;
this->lista_koniec = NULL;
}

znaleziono = 1; //znaleziono rekord do usuniecia

break; //przerwanie pętli ponieważ znalezlismy juz element do usuniecia

} else {
temp = temp->next;
}
}

if(znaleziono == 0 && WlaczKomunikaty) {
cout<<"nNie znaleziono rekordu do usuniecia!";
}
}
}

//=============================================================

void CBazaDanych::EdytujRekord()
{
WyswietlRekordy();

if(this->lista_poczatek == NULL && this->lista_koniec == NULL)
{
cout<<" Nie ma co edytowac!";
}
else
{
cout<<"nPodaj ID rekordu ktory chcesz edytowac: ";
string get;//zmienna pomocnicza
getline(cin,get);
int id = atoi(get.c_str()); //konwersja string na int
int znaleziono = 0; //domyslana zmienna okreslajaca ze nie znaleziono elementu do edycji
element* temp = this->lista_poczatek;
while(temp != NULL)
{
if(temp->id == id) {

cout<<"n========= Rekord ktory edytujesz =========n"
<<"ID: "<<temp->id<<"n"
<<"Imie: "<<temp->imie<<"n"
<<"Nazwisko: "<<temp->nazwisko<<"n"
<<"Rok studiow: "<<temp->rok_studiow<<"n"
<<"Kierunek: "<<temp->kierunek<<"n"
<<"==========================================nn"
<<"UWAGA: Wpisz "ok" aby nie modyfikowac danego pola!nn";

cout<<"Podaj nowe imie: ";
getline(cin,get);
while(get == "") {
cout<<"Podales pusty ciag znakow! Podaj nowe imie: ";
getline(cin,get);
}
if(get != "ok") { //jesli podano cos innego niz ok to zapisujemy zmiane
temp->imie = get;
}

cout<<"Podaj nowe nazwisko: ";
getline(cin,get);
while(get == "") {
cout<<"Podales pusty ciag znakow! Podaj nowe nazwisko: ";
getline(cin,get);
}
if(get != "ok") {
temp->nazwisko = get;
}

cout<<"Podaj nowy rok studiow: ";
string rok;
int rok_int;
getline(cin,rok); //ładujemy do stringa rok
rok_int = atoi(rok.c_str()); //konwersja stringa na int
while((rok == "" || rok_int == 0) && rok !="ok") {//jesli nie podano roku lub podany rok to liczba 0, np. jesli ktos zamiast liczby poda slowo to ono jest konwertowane na 0 wiec w takim przypadku ponownie zapytamy o podanie wlasciwego roku. Jesli podano slowo ok to nie prosimy ponownie o rok
if(rok=="") {//podano pusty ciag znakow zamiast roku
cout<<"Podales pusty rok! Podaj nowy rok studiow: ";
} else { //podano ciag znakow o jakiejs dlugosci ktory zostal zamieniony na liczbe 0
cout<<"Podales ciag znakow zamiast roku liczbowego! Podaj nowy rok studiow: ";
}
getline(cin,rok);
rok_int = atoi(rok.c_str());
}
if(rok != "ok") {//jesli podano ok to nie zmieniamy roku
temp->rok_studiow = rok_int;
}

cout<<"Podaj nowy kierunek: ";
getline(cin,get);
while(get == "") {
cout<<"Podales pusty ciag znakow! Podaj nowy kierunek: ";
getline(cin,get);
}
if(get != "ok") {
temp->kierunek = get;
}

cout<<"nPomyslnie zapisano zmiany!";

znaleziono = 1; //znaleziono rekord do edycji
break; //przerwanie petli bo znalezlismy juz element do edycji
} else {
temp = temp->next;
}
}
if(znaleziono == 0) {
cout<<"nNie znaleziono rekordu do edycji!";
}
}
}

//=============================================================

//int WyswietlKomunikat=1 //domyslnie wyswietlamy ten komunikat
//WyswietlKomunikat2 = 1
void CBazaDanych::ZapiszBazeDoPliku(int WyswietlKomunikat, int WyswietlKomunikat2)
{
element* temp = this->lista_poczatek;
if(temp == NULL) {
if(WyswietlKomunikat) {//ten komunikat wyswietlamy podczas akcji zapisu do pliku, natomiast gdy uzytkownik uruchamia kasowanie bazy danych to pozniej wyswietlimy tylko same odpowiedzy czy chce rowniez skasowac baze txt. Nie wyswietlamy ponizszego komunikatu poniewaz juz w metodzie SkasujBaze jest wyswietlany komunikat z pytaniem
cout<<"nBrak rekordow w bazie ktore by mozna zapisac!n"
<<"A moze chcesz wyczyscic baze danych w pliku txt?n";
}

cout<<"1 - Tak, wyczysc baze danych w pliku txtn"
<<"2 - Nien";
char nawigacja;
do {
nawigacja = _getch();
} while(nawigacja != '1' && nawigacja != '2');
if(nawigacja == '1') {
WyczyscBazeDanychWPliku();
cout<<"Baza danych w pliku txt zostala wyczyszczona!";
} else {
cout<<"Baza danych w pliku txt pozostala nienaruszona.";
}

} else {

cout<<"nCzy chcesz zapisac liste rekordow do bazy w pliku txt?n"
<<"1 - Zapisz baze do pliku (obecne dane w pliku zostana nadpisane)n"
<<"2 - Zapisz baze do pliku poprzez dopisanie nowych rekordown"
<<"3 - Nie zapisuj bazyn";

char nawigacja;
do {
nawigacja = _getch();
} while(nawigacja != '1' && nawigacja != '2' && nawigacja != '3');

fstream plik;
if(nawigacja == '1') {
plik.open(this->URL_Baza, ios::out); //ustawiamy tryb nadpisania pliku
} else if(nawigacja == '2') {
plik.open(this->URL_Baza, ios::app); //ustawiamy tryb dopisywania do pliku
} else {
cout<<"nBaza nie zostanie zapisana!";
}

//zapisujemy dane w pliku
if(nawigacja == '1' || nawigacja == '2')
{

cout<<"nTrwa zapisywanie...n";
if(nawigacja == '2') {
cout<<"nWybrales opcje dopisania rekordow do bazy.n"
<<"Aby uniknac dublowania sie numerow ID, rekordy z pamieci programun"
<<"otrzymaja nowe ID, ktore bedzie wieksze niz rekordow w bazie txtnn";
}
int tempID;
while(temp != NULL)
{
/* jesli dopisujemy rekordy do bazy to zmieniamy tym rekordom ID nawieksze
niz posiadaja rekordy w pliku txt aby uniknac sytuacji ze dwa rekordy maja
w bazie txt ten sam ID.
*/
if(nawigacja == '2') {
//nadajemy rekordom nowe ID, wieksze od ostatnio dodanych ID w bazie aby uniknac sytuacji powtarzania sie ID rekordow w bazie
//jednoczesnie robimy to przez preinkrementacje aby zwiekszyc wartosc AutoIncrement
tempID = ++AutoIncrement;
cout<<"Zapisano rekord o ID="<<temp->id<<" w bazie txt i w pamieci programu pod nowym ID: "<<tempID<<"n";
temp->id = tempID; //ID z pamieci programu zmieniamy na nowe ID ktore bedzie w bazie aby zachowac synchornizacje numerow ID
} else {
tempID = temp->id;
cout<<"Zapisano rekord o ID="<<temp->id<<"n";
}
//wykonanie zapisu do pliku
plik<<temp->id<<endl;
plik<<temp->imie<<endl;
plik<<temp->nazwisko<<endl;
plik<<temp->rok_studiow<<endl;
plik<<temp->kierunek<<endl;

temp = temp->next;
}
plik.close();

SaveAutoIncrement(); //zapisujemy ID ostatnio dodanego rekordu

if(nawigacja == '1') {
cout<<"Pomyslnie nadpisano baze danych nowymi rekordami!";
} else { //2
cout<<"Pomyslnie dopisano rekordy do bazy danych!nn";
/*trzeba teraz jeszcze zaktualizowac pamiec programu o rekordy ktore sa w bazie txt
Mianowicie dane rekordy z pamieci dopisalismy do pliku txt zmieniajac im ID tak aby nie dublowac numerow ID
z pliku txt. Teraz w pliku txt mamy jakies rekordy ktore juz tam byly plus rekordy ktore wlasnie dopisalismy.
Dlatego wykonujemy teraz zaladowanie do pamieci programu calej bazy txt aby w pamieci miec to samo co w pliku txt
*/
if(WyswietlKomunikat2) {
cout<<"UWAGA: Teraz powinienes zsynchronizowac zawartosc pamieci programu z baza txt.n"
<<"Jesli chcesz to zrobic to po prostu zgodz sie na zaladowanie bazy z pliku:n";
WczytajBazeZPliku(1, 1); //1-wyswietlamy komunikatu czy wczytac baze, 1-kasujemy baze w pamieci programu po czym ladujemy z pliku
}
}
}
}
}

//=============================================================

void CBazaDanych::WyczyscBazeDanychWPliku()
{
fstream plik;
plik.open(this->URL_Baza, ios::out); //ustawiamy tryb nadpisania pliku
plik<<"";
plik.close();
SaveAutoIncrement(); //zapisujemy ID ostatnio dodanego rekordu
}

//=============================================================

void CBazaDanych::WczytajBazeZPliku(bool komunikat, bool czy_kasowac)
{
bool zaladuj_baze;
if(komunikat == 1) //wyswietl komunikat z pytaniem czy zaladowac baze
{
cout<<"Czy chcesz wczytac baze danych z pliku do pamieci programu?n"
<<"(Baza zawarta w pamieci programu zostanie nadpisana baza z pliku)n"
<<"1 - Wczytaj baze z plikun"
<<"2 - Anulujnn";
char nawigacja_dodaj;
do {
nawigacja_dodaj = _getch();
} while(nawigacja_dodaj != '1' && nawigacja_dodaj != '2');

if(nawigacja_dodaj == '1') {
zaladuj_baze = 1;
cout<<"Wczytano!n";
} else {
zaladuj_baze = 0;
cout<<"Anulowano wczytywanie bazy z pliku...";
}
} else { // nie wyswietlamy komunikatu i odrazu ładujemy automatycznie baze
zaladuj_baze = 1;
}

if(zaladuj_baze) {
//skasowanie obecnej bazy w pamieci programu
//jesli ladujemy baze przy pierwszym uruhcomieniu programu to nie uruchamiamy funkcji kasujacej
if(czy_kasowac == 1) { //true = uruchom funkcje kasujaca baze
SkasujBaze();
}

// odczyt bazy
ifstream ifile(this->URL_Baza);

string tab[5]; //tablica zawierajaca 5 wierszy z kazdym polem informacji z bazy txt
string wiersz;
int l=1; //liczba linii
while(!ifile.eof()) {
getline(ifile,wiersz);

//cout<<l<<": "<<wiersz<<endl;

if(wiersz!="")
{
if(l%5==0) {
tab[4] = wiersz; //tab[4] bo indexy od 0 są
} else if(l%4==0) {
tab[3] = wiersz;
} else if(l%3==0) {
tab[2] = wiersz;
} else if(l%2==0) {
tab[1] = wiersz;
} else if(l%1==0) {
tab[0] = wiersz;
}
}
if(l%5==0) {
DodajRekordBezposrednio(this->lista_poczatek, this->lista_koniec, tab[0],tab[1],tab[2],tab[3],tab[4]);
l=0; //resetujemy po 5 rekordach na 0 licznik
}
l++;
}
ifile.close();
}
}

//=============================================================

//funkcja kasujaca baze w pamieci programu
//int WyswietlKomunikat=0 //domyslnie nie wyswietlamy komunikatu
void CBazaDanych::SkasujBaze(int WyswietlKomunikat)
{
if(this->lista_poczatek != NULL)//sprawdzamy czy lista nie jest pusta, bo jesli jest pusta to nie ma sensu tworzyc wskaznika
{
element* temp = this->lista_poczatek;
int ID_delete; //id do skasowania
while(temp != NULL)
{
ID_delete = temp->id; //przypisujemy do zmiennej pomocniczej ID poniewaz musimy przed usunieciem rekordu odczytac adres kolejnego elementu
temp = temp->next;
UsunRekord(0, ID_delete); //usuwamy rekord o danym ID
}
if(WyswietlKomunikat) {
cout<<"Usunieto wszystkie rekordy z pamieci programu!nn";
}
} else if(WyswietlKomunikat) {
cout<<"Baza danych w pamieci programu jest pusta! Nie ma co tam kasowac!n";
}

if(WyswietlKomunikat) {
cout<<"Czy chcesz rowniez aby wyczyscic plik txt bazy danych?n";
ZapiszBazeDoPliku(0);//uruchamiamy tę metodę bez wyswietlania komunikatu z pytaniem czy chcemy skasowac baze txt
}
}

//=============================================================

void CBazaDanych::SortujRekordy()
{
CountLiczbaRekordow(); //przeliczamy liczbe rekordow

if(LiczbaRekordow) {

cout<<"Wybierz kryterium wedlug ktorego posortowac baze:n"
<<"1 - IDn"
<<"2 - Imien"
<<"3 - Nazwiskon"
<<"4 - Rok studiown"
<<"5 - Kieruneknn";
char nawigacja;
do {
nawigacja = _getch();
} while(nawigacja != '1' && nawigacja != '2' && nawigacja != '3' && nawigacja != '4' && nawigacja != '5');


element* tab = new element[LiczbaRekordow];
element* temp = this->lista_poczatek;

//tworzymy tablice elementow
int index=0;
while(temp != NULL)
{
tab[index].id = temp->id;
tab[index].imie = temp->imie;
tab[index].nazwisko = temp->nazwisko;
tab[index].rok_studiow = temp->rok_studiow;
tab[index].kierunek = temp->kierunek;
temp = temp->next;
index++;
}

if(nawigacja == '1') {
cout<<"Wybrales "ID" jako kryterium sortowania.nn";
QuickSort(tab, 0, LiczbaRekordow-1, "id", 1);//przy pierwszym wywolaniu quicksort pytamy sie o kolejnosc w jakiej maja byc posortowane rekordy (typ sortowania: ASC lub DESC)
} else if(nawigacja == '2') {
cout<<"Wybrales "imie" jako kryterium sortowania.nn";
QuickSort(tab, 0, LiczbaRekordow-1, "imie", 1);
} else if(nawigacja == '3') {
cout<<"Wybrales "nazwisko" jako kryterium sortowania.nn";
QuickSort(tab, 0, LiczbaRekordow-1, "nazwisko", 1);
} else if(nawigacja == '4') {
cout<<"Wybrales "rok studiow" jako kryterium sortowania.nn";
QuickSort(tab, 0, LiczbaRekordow-1, "rok_studiow", 1);
} else if(nawigacja == '5') {
cout<<"Wybrales "kierunek" jako kryterium sortowania.nn";
QuickSort(tab, 0, LiczbaRekordow-1, "kierunek", 1);
}

//wyswietlamy posortowane wyniki
for(int i=0; i<LiczbaRekordow; i++)
{
cout<<"ID: "<<tab[i].id<<"n"
<<"Imie: "<<tab[i].imie<<"n"
<<"Nazwisko: "<<tab[i].nazwisko<<"n"
<<"Rok studiow: "<<tab[i].rok_studiow<<"n"
<<"Kierunek: "<<tab[i].kierunek<<"n"
<<"==========================================n";
}

cout<<"nCzy chcesz aby ta kolejnosc rekordow zostala zapamietana w pamieci programu?n"
<<"1 - Tak (zapisz do pamieci programu ta kolejnosc rekordow)n"
<<"2 - Nienn";
do {
nawigacja = _getch();
} while(nawigacja != '1' && nawigacja != '2');
if(nawigacja == '1') {
temp = this->lista_poczatek;
index = 0;
while(temp != NULL)
{
temp->id = tab[index].id;
temp->imie = tab[index].imie;
temp->nazwisko = tab[index].nazwisko;
temp->rok_studiow = tab[index].rok_studiow;
temp->kierunek = tab[index].kierunek;
temp = temp->next;
index++;
}
cout<<"Wyniki sortowania zostaly zapamietane w pamieci programu!n"
<<"Jesli chcesz aby wyniki byly rowniez zapisane do bazy txt to skorzystaj z opcji nr 2";
} else {
cout<<"Wyniki sortowania NIE zostaly zapamietane w pamieci programu.";
}
delete [] tab;

} else {
cout<<"Baza jest pusta, nie ma co sortowac!";
}
}

//=============================================================

void CBazaDanych::QuickSort(element t[], int p, int k, string co_sortowac, int kolejnosc)
{
static char typ_kolejnosci;
if(kolejnosc) {//przy pierwszym uruchomieniu funkcji zapytamy o sposob prezentacji wynikow
cout<<"Wybierz sposob wyswietlenia posortowanych danych:n"
<<"1 - ASC (rekordy od najmniejszego do najwiekszego)n"
<<"2 - DESC (rekordy od najwiekszego do najmniejszego)nn";
do {
typ_kolejnosci = _getch();
} while(typ_kolejnosci != '1' && typ_kolejnosci != '2');

}

int i, j, pivot;
string pivot_s; //pivot dla stringow
element wtemp;//pomocnicza zmienna
i = p;
j = k;
if(co_sortowac == "id") {
pivot = t[p].id; //definicja punkut podzialu
} else if(co_sortowac == "rok_studiow") {
pivot = t[p].rok_studiow;
} else if(co_sortowac == "imie") {
pivot_s = t[p].imie;
} else if(co_sortowac == "nazwisko") {
pivot_s = t[p].nazwisko;
} else if(co_sortowac == "kierunek") {
pivot_s = t[p].kierunek;
}
//cout<<"pivot = "<<pivot<<"n";
while(i < j) // moga sie minąć ale mogą też być równe (zamiana skrajnych)
{
if(co_sortowac == "id") {
if(typ_kolejnosci=='1') {
while(t[i].id<pivot) i++;
while(t[j].id>pivot) j--;
} else {
while(t[i].id>pivot) i++;
while(t[j].id<pivot) j--;
}
} else if(co_sortowac == "rok_studiow") {
if(typ_kolejnosci=='1') {
while(t[i].rok_studiow<pivot) i++;
while(t[j].rok_studiow>pivot) j--;
} else {
while(t[i].rok_studiow>pivot) i++;
while(t[j].rok_studiow<pivot) j--;
}
} else if(co_sortowac == "imie") {
if(typ_kolejnosci=='1') {
while(t[i].imie<pivot_s) i++;
while(t[j].imie>pivot_s) j--;
} else {
while(t[i].imie>pivot_s) i++;
while(t[j].imie<pivot_s) j--;
}
} else if(co_sortowac == "nazwisko") {
if(typ_kolejnosci=='1') {
while(t[i].nazwisko<pivot_s) i++;
while(t[j].nazwisko>pivot_s) j--;
} else {
while(t[i].nazwisko>pivot_s) i++;
while(t[j].nazwisko<pivot_s) j--;
}
} else if(co_sortowac == "kierunek") {
if(typ_kolejnosci=='1') {
while(t[i].kierunek<pivot_s) i++;
while(t[j].kierunek>pivot_s) j--;
} else {
while(t[i].kierunek>pivot_s) i++;
while(t[j].kierunek<pivot_s) j--;
}
}

if(i <= j)
{
//cout<<"zamiana: "<<t[i].id<<" z "<<t[j].id<<endl;
wtemp = t[i];
//zamieniamy tylko wartosci, a informacje o adresach do kolejnych elementow pozostaja bez zmian
t[i].id = t[j].id;
t[i].imie = t[j].imie;
t[i].nazwisko = t[j].nazwisko;
t[i].rok_studiow = t[j].rok_studiow;
t[i].kierunek = t[j].kierunek;

t[j].id = wtemp.id;
t[j].imie = wtemp.imie;
t[j].nazwisko = wtemp.nazwisko;
t[j].rok_studiow = wtemp.rok_studiow;
t[j].kierunek = wtemp.kierunek;

i++;
j--;
}
}
if(i < k) {
QuickSort(t, i, k, co_sortowac, 0); //ostatnie 0 oznacza ze nie pytamy sie juz o tym sortowania: ASC lub DESC
// od i tam gdzie sie zatrzymalo na i, az do k koniec tablicy
}
if(p < j) {
QuickSort(t, p, j, co_sortowac, 0);
}
}

//=============================================================

/* t - tekst
** w - wzorzec
** i - od ktorego znaku zaczynamy wyszukiwanie
** reset - jesli 1 to resetujemy zmienna statyczna przechowujaca informacje o tym czy w wyniku rekurencji udalo sie znalesc wzorzec
** jesli w tym samym programie bedziemy w roznych tekstach szukac roznych wzorcow to nalezy przed kazdym wywolaniem funkcji ustawic na 1 aby nastapila resetacja zmiennej statycznej, ktora jest pamietana z poprzedniego wyszukiwania wzorca!
*/
int CBazaDanych::StringFind(string t, string w, int i=0, int reset=1)
{
int x=0;//początkowy index dla wzorca
int trash; //zmienna pomocnisza, poszczegolne wywolania funkcji zwracajace czy udalo sie dopasowac wzorzec beda do tej zmiennej przypisywane
static int find = 0;
if(reset) {
find = 0; //jesli 1 to resetujemy zmienna statyczna
}

if(i<t.length() && x<w.length()) {
if(t[i] == w[x]) {
int ok=1;
for(int f=1; f<w.length(); f++) {
if(t[i+f] == w[x+f]) {//sprawdzamy czy kolejne znaki sa rowne sobie po pierwszym wystapieniu literki a ze slowa ala
ok++;
} else {
break; //jesli jakas literka sie nie zgadza to przerywamy petle bo wiemy juz ze wzorzec nie pasuje w calosci
}
}
if(ok == w.length()) {//jesli liczba znalezionych literek jest rowna dlugosci wzorca to znaczy ze znalezlismy miejsce wystapienia wzorca
find = 1;//ustawiamy ze dopasowalismy wzorzec
int od_pozycji = i+1;
int do_pozycji = i+w.length();
/*cout<<"Dopasowano wzorzec od pozycji nr: "<<od_pozycji<<" do pozycji: "<<do_pozycji<<"n";
cout<<t<<endl;
for(int a=1; a<od_pozycji; a++) {
cout<<" ";
}
cout<<w<<"nn";
*/
//po udanym dopasowaniu wzorca uruchamiamy funkcje by szukala kolejnego dopasowania w tekscie
trash = StringFind(t, w, do_pozycji, 0);

} else { //jesli nie uda sie dopasowac calego wzorca to szukamy od nastepnego znaku probujac znowu dopasowac caly wzorzec
trash = StringFind(t, w, i+1, 0);
}

} else {
trash = StringFind(t, w, i+1, 0); //sprawdzamy kolejny znak czy jest rowny pierwszemu znakowi wzorca
}
}

return find;
}

//=============================================================

void CBazaDanych::WyszukajRekordy()
{
cout<<"Wybierz kryterium wedlug ktorego chcesz przeszukac baze:n"
<<"1 - IDn"
<<"2 - Imien"
<<"3 - Naziwskon"
<<"4 - Rok studiown"
<<"5 - Kieruneknn";

char nawigacja;
do {
nawigacja = _getch();
} while(nawigacja != '1' && nawigacja != '2' && nawigacja != '3' && nawigacja != '4' && nawigacja != '5');

string wzorzec, kryterium;
int wzorzec_int;//uzywany w przypadku gdy wyszukujemy po ID
if(nawigacja == '1') {
kryterium = "ID";
cout<<"Podaj ID ktore chcesz znalesc: ";
getline(cin,wzorzec);
wzorzec_int = atoi(wzorzec.c_str()); //konwersja stringa na int
while(wzorzec == "" || wzorzec_int == 0) {
if(wzorzec=="") {//podano pusty ciag znakow
cout<<"Podales puste ID! Podaj poprawne ID: ";
} else { //podano ciag znakow o jakiejs dlugosci ktory zostal zamieniony na liczbe 0
cout<<"Podales ciag znakow zamiast numeru! Podaj poprawne ID: ";
}
getline(cin,wzorzec);
wzorzec_int = atoi(wzorzec.c_str());
}

} else if(nawigacja == '2') {
kryterium = "Imie";
cout<<"Podaj imie ktore chcesz znalesc: ";
getline(cin,wzorzec);
while(wzorzec == "") {
cout<<"Podales pusty ciag znakow! Podaj imie: ";
getline(cin,wzorzec);
}

} else if(nawigacja == '3') {
kryterium = "Nazwisko";
cout<<"Podaj nazwisko ktore chcesz znalesc: ";
getline(cin,wzorzec);
while(wzorzec == "") {
cout<<"Podales pusty ciag znakow! Podaj nazwisko: ";
getline(cin,wzorzec);
}

} else if(nawigacja == '4') {
kryterium = "Rok studiow";
cout<<"Podaj rok studiow ktory chcesz znalesc: ";
getline(cin,wzorzec);
wzorzec_int = atoi(wzorzec.c_str()); //konwersja stringa na int
while(wzorzec == "" || wzorzec_int == 0) {
if(wzorzec=="") {//podano pusty ciag znakow
cout<<"Podales pusty rok studiow! Podaj poprawny: ";
} else { //podano ciag znakow o jakiejs dlugosci ktory zostal zamieniony na liczbe 0
cout<<"Podales ciag znakow zamiast roku studiow! Podaj poprawny: ";
}
getline(cin,wzorzec);
wzorzec_int = atoi(wzorzec.c_str());
}

} else if(nawigacja == '5') {
kryterium = "Kierunek studiow";
cout<<"Podaj kierunek ktory chcesz znalesc: ";
getline(cin,wzorzec);
while(wzorzec == "") {
cout<<"Podales pusty ciag znakow! Podaj kierunek: ";
getline(cin,wzorzec);
}

}

cout<<"n";
//wyswietlamy rekordy pasujace do zapytania
if(this->lista_poczatek == NULL) {
cout<<"Lista rekordow jest pusta! Nie ma w czym wyszukiwac!";

} else {

//wyznaczanie obecnej daty
//http://www.cplusplus.com/reference/clibrary/ctime/localtime/
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
string czas_teraz = asctime (timeinfo);

string wyniki;
wyniki+="=========================================================n";
wyniki+="====== Kryterium: ""+kryterium+""n";
wyniki+="===== Wzorzec: ""+wzorzec+""n";
wyniki+="==== Data: "+czas_teraz;
wyniki+="===n";
wyniki+="== Znalezione rekordy ponizej: n";
wyniki+="=nn";


int rekordow=0;
int pasuje; //informacja czy rekord pasuje do wzorca
string temps;
element* temp = this->lista_poczatek;
while(temp != NULL)
{
pasuje = 0;//zakladamy ze rekord nie pasuje do wzorca
switch(nawigacja)
{
case '1'://czy ID rowne wzorzec_int
if(temp->id == wzorzec_int) pasuje=1;
break;
case '2':
pasuje = StringFind(temp->imie, wzorzec); //zwraca 1 jesli wzorzec pasuje do tekstu
break;
case '3':
pasuje = StringFind(temp->nazwisko, wzorzec);
break;
case '4':
if(temp->rok_studiow == wzorzec_int) pasuje=1;
break;
case '5':
pasuje = StringFind(temp->kierunek, wzorzec);
break;
}

if(pasuje) //jesli rekord pasuje to zapisujemy go do wynikow
{
temps = IntToString(temp->id);
wyniki+="ID: "+temps+"n";
wyniki+="Imie: "+temp->imie+"n";
wyniki+="Nazwisko: "+temp->nazwisko+"n";
temps = IntToString(temp->rok_studiow);
wyniki+="Rok studiow: "+temps+"n";
wyniki+="Kierunek: "+temp->kierunek+"n";
wyniki+="==========================================n";
rekordow++;
}

temp = temp->next;

}

temps = IntToString(rekordow);
wyniki+="n=n";
wyniki+="==n";
wyniki+="=== Rekordow pasujacych do wzorca: "+temps+"n";
wyniki+="=========================================================nnn";

if(rekordow) {//jesli znaleziono jakies rekordy to je wyswietl + zapytanie czy dopisac do loga

cout<<wyniki;

cout<<"Czy chcesz zapisac wyniki wyszukiwania w pliku?n"
<<"1 - Tak, dopisz wyniki do pliku log_wyszukiwanie.txtn"
<<"2 - Nie zapisujnn";
char nawigacja2;
do {
nawigacja2 = _getch();
} while(nawigacja2 != '1' && nawigacja2 != '2');
if(nawigacja2 == '1') {
cout<<"Wyniki zostaly dopisane do pliku log_wyszukiwanie.txt!";
fstream plik;
plik.open(this->URL_LogWyszukiwanie, ios::app); //ustawiamy tryb dopisywania do pliku
plik<<wyniki;
plik.close();
} else {
cout<<"Wyniki NIE zostaly zapisane!";
}

} else {
cout<<"Nie znaleziono rekordow ktore pasowalyby do podanego wzorca: ""<<wzorzec<<""n"
<<"dla zadanego kryterium: ""<<kryterium<<""!";
}

}


}

//=============================================================

//konwersja int na string
string CBazaDanych::IntToString(int number)
{
stringstream ss;
ss << number;
return ss.str();
}

//=============================================================

W katalogu projektu należy umieścić folder: "baza_log", a w nim 3 pliki:
a) AutoIncrement.txt
Do tego pliku zapisywany jest ostatnio przydzielony ID rekordu.
b) log_wyszukiwanie.txt
W tym pliku zapisywane są wyniki wyszukiwania przeprowadzone na bazie danych.
c) BazaStudentow.txt
Plik bazy danych. Poniżej podaje kilka przykładowych rekordów. Uwaga! Ostatnia liniia pliku musi być pusta. Plik zawiera zmyślone nazwiska.



1
artur
nowak
1
informatyka
2
adrian
kowalski
2
filozofia
3
michal
wielki
2
matematyka
4
franciszek
bokser
6
geodezja
5
kamil
kowalski
3
psychologia
6
wojciech
krol
6
elektrotechnika
7
marcin
wrobel
1
psychologia
8
tomasz
tomaszewski
7
matematyka
9
anna
kowalska
1
elektrotechnika
10
bartlomiej
nowak
6
informatyka