/* Autor: Tomasz Krasnyk, ISI, sem 5, PW
 * Program ma za zadanie przedstawić działanie podstawowych funkcji standardowej
 * biblioteki języka C++ związanymi ze strumieniami wejściowymi
 */

#include <iostream>	//dla "cin" & "cout"
#include <fstream>	//dla wejscia/wyjscia z plikow

 /* "cin" i "cout" jest ze standardowej biblioteki zatem należy dodać poniższą linię aby uniknąć
  * pisania za każdym razem std::cin (std::cout) zamiast samego cin (cout)
  */
using namespace std;


int main () {

	//użycie ignore(), get()
	{
		//czytanie tekstu z pominięciem zawartości między nawiasami "(" i ")" włącznie
		char tmp;

		cout << "Napisz kilka rzeczownikow z ich synonimami w nawiasach, np: chatka(domek), lica(usta)" << endl;
		cin.get(tmp);					//pobranie pierwszego znaku wejscia i usunięcie go ze strumienia
		while(tmp != '\n'){				//pobieranie znaków do momentu zakończenia linii
			if(tmp == '('){				//czy pobrano nawias otwierający?
				cin.ignore(512, ')');	//pominięcie wszystkich znaków na wejściu aż do wystąpienia ")" włącznie
			} else {
				cout << tmp;
			}
			cin.get(tmp);				//czytanie kolejnego znaku z wejscia
		}
		cout << "\n\n";
	}
	/*użycie read(), tellg(), seekg() przy czytaniu z pliku, do wykonania ponizszego kodu potrzeby jest plik o
	 * o nazwie read.txt z zawartoscia dlugosci conajmniej 7 znakow
	 */
	{
		int dlugosc;
		char *buffor;
		char beginning[4+1];						//do przechowania poczatkowych 4 znakow pliku
		char ending[3+1];							//do przechowania koncowych 3 znakow pliku

		ifstream inStream;							//strumien wejściowy z pliku
		inStream.open("read.txt", ios::in);			//otwarcie pliku do czytania
		inStream.seekg(-3, ios::end);				//przesunięcie kursora czytania znaków na 3-cią
													//pozycje od konca pliku
		dlugosc = inStream.tellg();					//czytanie pozycji kursora czytania w pliku wejsciowym
		inStream.seekg(4, ios::beg);				//przesunięcie kursora czytania znaków na
													//4-ta pozycje wzgledem początku pliku
		dlugosc -= 4;								//nie czytamy pierwszych czterech znakow
		buffor = new char[dlugosc + 1];				//znamy już długość pliku, zatem alokujemy miejsce na jego zawartość
													//+ 1 znak na znak konca łancucha
		inStream.read (buffor,dlugosc);				//czytanie zawartości pliku

		inStream.seekg(0, ios::beg);				//przesuniecie pozycji kursora na poczatek pliku
		inStream.read(beginning, 4);				//czytanie 4 poczatkowych znakow

		inStream.seekg(-3, ios::end);
		inStream.read(ending, 3);					//czytanie koncowych znakow pliku

		inStream.close();							//zamknięcie pliku
		buffor[dlugosc] = '\0';						//"read" nie zapisuje znaku zerowego na końcu wczytanego bloku
		beginning[4] = '\0';
		ending[3] = '\0';

		cout << "Z pliku wczytano:\n\n"
				"Poczatek: " << beginning << "\n\nTekst: " << buffor << "\n\nKoniec: " << ending << "\n\n";
		delete[] buffor;
	}
	//użycie getline(), gcount(), peek()
	{
		/*wczytanie tylko linii zaczynającej się od znaku '+' i policzenie wczytanych znaków, znak '=' na poczatku
		 * linii oznacza koniec wczytywania linii. Zauważ, że getline() wczytuje także znaki końca linii co widać
		 * na podstawie liczenia wczytywanych znaków
		 */
		int tmp;
		bool CZYTAJ = true;
		char buf[150];

		cout << "Wpisz kilka linii konczac kazda enterem(wskazowka: upewnij sie, ze niektore wpisane przez Ciebie\n"
				" linie zaczynaja sie od znaku +, zakonczenie zabawy gwarantuje linia zaczynajaca sie od =" << '\n';
		while(CZYTAJ){
			tmp = cin.peek();							//podejrzenie nastepnego(tu pierwszego w linii) znaku w buforze wejsciowym
														//znak ten nie jest usuwany ze strumienia wejsciowego
			if(tmp == '='){								//czy wykryto linie konczaca zabawe?
				cin.ignore(150, '\n');					//pominięcie zawartości linii
				CZYTAJ = false;							//koniec czytania linii
			} else if(tmp == '+'){						//linie nalezy wczytac i wypisac uzytkownikowi na wyjscie
				cin.getline(buf, 150);					//przeczytaj całą linię do bufora
				cout << "Wczytano: " << buf << "\n"; 	//zapisanie zczytanej linii na wyjście

				//wyswietlenie liczby wczytanych znakow przez ostatnia operacje na strumieniu wejsciowym cin
				cout << "Znakow wczytanych: " << cin.gcount() << "\n\n";
			} else {
				cin.ignore(50, '\n');		//pomiń zawartość linii
				cout << "Linia nie wczytana, nie zaczyna sie od znaku +\n\n";
			}
		}
		cout << "\n\n";
	}
	//użycie operatora >>, get(), unget(), wczytywanie slowa badz liczby
	{
		char tmp;
		int liczba;
		char slowo[50];

		cout << "Wpisz słowo lub liczbę całkowitą i potwierdz enterem: ";
		cin.get(tmp);					//czytamy pierwszy znak wprowadzony przez uzytkownika
		if(tmp >= '0' && tmp <= '9'){	//czy kod wczytanego znaku jest kodem cyfry?
			cin.unget();				//cofnij ostatnią operację wczytania znaku
			cin >> liczba;				//wczytaj cala liczbe
			cout << "Wczytano liczbe: " << liczba << "\n\n";
		} else {
			cin.unget();				//cofnij ostatnią operację wczytania znaku
			cin >> slowo;				//wczytaj całe słowo
			cout << "Wczytano slowo: " << slowo << "\n\n";
		}
		/* wczytano slowo lub liczbę z wejscia, jednakze standardowe wejscie "cin" czyta wejscie od bialego do
		 * bialego znaku(tabulatora, entera, spacji), zatem w buforze został znak nowej linii(enter) - jest to
		 * zazwyczaj kłopotliwe kiedy mieszamy wejście sformatowane i niesformatowane
		 * Znak konca linii można usunąć np. tak:
		 */
		cin.get();
		//cin.ignore("50", '\n');    //lub tak
	}
	//sprawdzanie flag strumienia "cin", bledy czytania ze strumienia wejsciowego
	{
		int liczbaCopy, liczba;
		liczbaCopy = liczba = 666;
		cout << "program oczekuje wpisania liczby(jednakze wpisz mu jakas litere): ";
		cin >> liczba;				//proba wczytania liczby
		//sprawdzmy czy jakies flagi bledu wejscia zostaly ustawione:
		cout << "--------------------------------------\nUstawione flagi:\n";
		if(cin.fail()){ 		//czy wystapil blad podczas czytania, failbit lub badbit ustawiony?
			//nie dobrze, flaga ustawiona, aby wykonywać dalsze operacje wejścia trzeba je wyczyścić
			cout << "+ badbit or failbit ustawiony\n";
		} else {
			cout << "- badbit or failbit NIEustawiony\n";
		}
		if(cin.eof()){			//czy napotkano na koniec pliku?
			cout << "+ eofbit ustawiony\n";
		} else {
			cout << "- eofbit NIEustawiony\n";
		}
		if(cin.good()){			//czy strumień nadaje się do kolejnych operacji wejscia?
			cout << "wpisana liczba to: " << liczba << '\n';
			cout << "strumien wejscia OK, mozna czytac dalej\n";
		} else {
			cout << "wart. liczby przed czytaniem: " << liczbaCopy << " po czytaniu: " << liczba << " wniosek: wartosc liczba sie nie zmienila!\n";
			cout << "strumien wejscia NOT OK, nie mozna czytac dalej\n";
		}

		if(!cin.good()){			//jesli strumien wejsciowy nie nadaje sie do czytania
			char buffor[150];

			cin.clear();			//to wyczysc wszystkie flagi bledow aby mozna bylo dokonywac innych operacji wejscia
			//Sprawdzamy stan flag dla strumienia wejsciowego po cin.clear()
			cout << "--------------------------------------\nFlagi po wykonaniu cin.clear():\n";
			if(cin.fail()){
				cout << "+ badbit or failbit ustawiony\n";
			} else {
				cout << "- badbit or failbit NIEustawiony\n";
			}
			if(cin.eof()){
				cout << "+ eofbit ustawiony\n";
			} else {
				cout << "- eofbit NIEustawiony\n";
			}
			if(cin.good()){			//wczesniej wywolano clear(), takze cin.good() = true, zostawiono dla pokazania zmiany stanu
				cout << "strumien wejscia OK, mozna czytac dalej\n\n";
				//sprawdzmy czy w trakcie wystapienia bledu czytania, cokolwiek zostalo usunięte z wejscia:
				cin.getline(buffor, 150);	//zczytujemy to co zostalo w buforze wejsciowym
				cout << "Zawartosc bufora wejscia po bledzie odczytu: " << buffor << "\n"
						"Wniosek? Przy wystapieniu bledu odczytu, ustawiane sa flagi strumienia cin,"
						" nic nie zostaje wpisane do zmiennej, do ktorej wczytujemy dane oraz nic nie "
						"zostaje usuniete ze strumienia wejscia!\n\n";
			} else {
				cout << "strumien wejscia NOT OK, nie mozna czytac dalej\n";
			}
		}

		cout << "Program oczekuje liczby(podaj mu teraz liczbe): ";
		cin >> liczba;
		if(cin.good()){				//czy strumien wejsciowy nadaje sie do czytania?(wczesniej nie wystapil blad)
			cout << "Wpisana liczba to: " << liczba << "\n";
		} else {
			cout << "Miales wpisac liczbe!\n";
			cin.clear();
		}
		cin.get();			//usuniecie znaku konca linii z wejscia
	}

	return 0;
}
