ZTP 2019: Zadania przed lab.5

Zadanie 1:

Napisz funkcję, która wczytuje macierz z pliku tekstowego zapisaną tak, że w kolejnych wierszach pliku są wartości komórek kolejnych wierszy macierzy rozdzielone spacjami, a następnie dokonuje jej transpozycji. Przyjmij, że wymiary wczytywanej macierzy są nieznane, ale że dane w pliku są na pewno poprawne (tj. wiersze przechowują tylko liczby, liczby liczb w wierszach są takie same, itp.). Do wczytania macierzy użyj kontenera typu <deque<deque<double>>. Funkcja zwraca transponowaną macierz w postaci wskaźnika do dynamicznie alokowanego kontenera typu vector<vector<double>>. Wypisz w oknie konsoli zawartość wynikowego kontenera i sprawdź, czy transpozycja została przeprowadzona poprawnie.

Zadanie 2:

Wczytaj słowa z kolejnych wierszy z pliku tekstowego do listy list, tj. kontenera typu list<list<string>>, tak aby kontener zawierał listę wierszy, gdzie każdy wiersz jest reprezentowany przez listę słów z tego wiersza. Posortuj rosnąco słowa z każdego wiersza wg zasady sortowania takiej jak w słowniku języka polskiego, a następnie scal posortowane listy słów do jednej listy wynikowej reprezentowanej przez inny kontener typu lista<string>. Wypisz w oknie konsoli zawartość wynikowego kontenera w postaci kolumny i upewnij się, że sortowanie i scalanie się powiodło. Testy przeprowadź na pliku mistrz.txt.

ZTP 2019: Zadanie przed lab.4

Zamieszczony poniżej kod programu reprezentuje przykład programowania z wykorzystaniem cech charakterystycznych. W programie wykorzystywane są dwie klasy reprezentujące dwa pojęcia:

  1. temperatura_wody – liczba rzeczywista reprezentująca temperaturę wody
  2. kostka_do_gry – liczba całkowita reprezentująca wartość, jaka może wypaść w wyniku rzutu kostką do gry.

Dla tych klas zdefiniowano ich cechy charakterystyczne. Są nimi:

  1. _jest_liczba – cecha mówiąca, czy danych obiekt reprezentuje liczbę,
  2. _jest_liczba_calkowita – cecha mówiąca, czy liczba którą reprezentuje danych obiekt, jest liczbą całkowitą,
  3. _nalezy_do_przedzialu – cecha mówiąca, czy liczba którą reprezentuje danych obiekt, należy do przedziału,
  4. _dolna_granica_przedzialu – wartość dolnej granicy przedziału, do którego mogą należeć liczby reprezentowane przez danych obiekt,
  5. _gorna_granica_przedzialu – wartość górnej granicy przedziału, do którego mogą należeć liczby reprezentowane przez danych obiekt,

Cechy charakterystyczne zostały zaimplementowane w programie. W tym celu najpierw zostały zaimplementowane dwie klasy: Bazowe_Cechy oraz Cechy: public Bazowe_Cechy tworzące pojęcie zbioru cech.

Następnie dla każdej z dwóch klas: temperatura_wody i kostka_do_gry zostały skonkretyzowane w odpowiedni sposób przypisane im klasy cech:

  1. Cechy<temperatura_wody>: public Bazowe_Cechy
  2. Cechy<kostka_do_gry>: public Bazowe_Cechy

Działanie programu polega na gromadzeniu danych liczbowych różnych typów w kontenerach, przy czym kontenery do walidacji wprowadzanych danych używają cech charakterystycznych. W tym celu zdefiniowana została klasa reprezentująca kontener SzablonStosu przystosowany do przechowywania dowolnych wartości, w tym obiektów typu temperatura_wody i kostka_do_gry. Metoda push tego kontenera przed umieszczeniem danej dokonuje jej walidacji posługując się informacjami z klasy Bazowe_Cechy.

Wykorzystanie kontenera zostało zademonstrowane w funkcji main. W kodzie main tworzone są trzy kontenery K1, K2 i K3, a następnie są wypełniane wartościami. Uwaga: kontener K1 jest zapełniany wartościami tak długo, póki wystarczy zasobów komputera (w trakcie wykonania programu warto uruchomić menedżer zadań i w sekcji wydajności obserwować, jak ubywa wolnej pamięci w miarę pracy programu).

Zadania do zrobienia przed ćwiczeniami

  1. Przenieś kod do środowiska VS C++, skompiluj i uruchom.
  2. Przeanalizuj kod, upewnij się, że rozumiesz rolę wszystkich pól i metod w klasach i potrafisz to wyjaśnić na zajęciach.
  3. Upewnij się, że potrafisz wyjaśnić, dlaczego tyle właśnie elementów zostaje umieszczonych w każdym z trzech kontenerów (a nie więcej).
  4. dodaj do kodu jeszcze jedną klasę reprezentującą pojęcie liczbowe „numer kołnierzyka koszuli” i skonkretyzuj w odpowiedni sposób odpowiadającą jej klasę cech. Następnie, jeżeli to konieczne, rozszerz kod metody push tak aby poprawnie walidował obiekty nowego typu. W funkcji main dodaj kontener K4 w którym zgromadzisz kilka obiektów nowego typu.
  5. Przygotuj się do rozwijania tego kodu dla potrzeb nowych rodzajów wartości, jakie można przechowywać w tym kontenerze.

Pliki do pobrania

Plik programu: ZPO-lab4.cpp
Plik z danymi wejściowymi: qv-lab4 (po założeniu nowego projektu VC++ należy go umieścić w tym samym folderze, co plik z kodem programu).

 
/* ========================================
ZPO: laboratorium 4
WMP.SNS UKSW, Warszawa
========================================
*/
#include<iostream>
#include<fstream>
#include<string>
#include<limits>
#include<exception>

using namespace std;

class Bazowe_Cechy {
public:
	static const bool _jest_liczba = false;
	static const bool _nalezy_do_przedzialu = false;
	static const bool _jest_liczba_calkowita = false;
	static const int _dolna_granica_przedzialu = 0;
	static const int _gorna_granica_przedzialu = 0;
};

template<typename T>
class Cechy : public Bazowe_Cechy {
public:
	static const double dolna_granica_przedzialu() { return 0; };
	static const double gorna_granica_przedzialu() { return 0; };
};

class temperatura_wody {
	double t;
public:
	temperatura_wody(double temp = 50) : t(temp) {};
	double operator()() { return t; };
	temperatura_wody& operator=(double temp) { t = temp; return *this; };
};

template<>
class Cechy<temperatura_wody> : public Bazowe_Cechy{
public:
	static const bool _jest_liczba = true;
	static const bool _nalezy_do_przedzialu = true;
	static const double dolna_granica_przedzialu() { return 0; };
	static const double gorna_granica_przedzialu() { return 100; };
};

class kostka_do_gry {
	int n;
public:
	kostka_do_gry(int num = 1) : n(num) {};
	int operator()() { return n; };
	kostka_do_gry& operator=(int num) { n = num; return *this; };
};

template<>
class Cechy<kostka_do_gry> : public Bazowe_Cechy{
public:
	static const bool _jest_liczba = true;
	static const bool _nalezy_do_przedzialu = true;
	static const bool _jest_liczba_calkowita = true;
	static const int _dolna_granica_przedzialu = 1;
	static const int _gorna_granica_przedzialu = 6;
};

class Przepelnienie : public exception {
	char opis[100];
public:
	Przepelnienie(const char* o) { strcpy_s(opis, o); }
	const char* what() const throw() { return opis; };
};
class BrakDanych : public exception {
	char opis[100];
public:
	BrakDanych(const char* o) { strcpy_s(opis, o); }
	const char* what() const throw() { return opis; };
};


template<typename T, int rozmiar, class _Cechy = Cechy<T>>
class SzablonStosu{
	T stos[rozmiar];
	int top;
public:
	int zajetosc() { return top; };
	SzablonStosu() : top(0) {}
	void push(const T& i) {
		if (top == rozmiar)
			throw Przepelnienie(typeid(i).name());
		stos[top++] = i;
	}
	void push(int i) {
		if (top == rozmiar)
			throw Przepelnienie(typeid(i).name());

		// walidacja wartości przekazanej do zapisu
		if (Cechy<T>::_jest_liczba && Cechy<T>::_jest_liczba_calkowita) {
			if (Cechy<T>::_nalezy_do_przedzialu) {
				if ((Cechy<T>::_dolna_granica_przedzialu <= i) && (i <= Cechy<T>::_gorna_granica_przedzialu))
					stos[top++] = i;
			}
			else
				stos[top++] = i;
		}
	}
	void push(double i) {
		if (top == rozmiar)
			throw Przepelnienie(typeid(i).name());

		// walidacja wartości przekazanej do zapisu
		if (Cechy<T>::_jest_liczba && !Cechy<T>::_jest_liczba_calkowita) {
			if (Cechy<T>::_nalezy_do_przedzialu) {
				if ((Cechy<T>::dolna_granica_przedzialu() <= i) && (i <= Cechy<T>::gorna_granica_przedzialu()))
					stos[top++] = i;
			}
			else
				stos[top++] = i;
		}
	}
	T pop() {
		if (top == 0)
			throw BrakDanych(typeid(stos[0]).name());

		return stos[--top];
	}
};

int main() {
	SzablonStosu<string, 5> K1;
	SzablonStosu<temperatura_wody, 10> K2;
	SzablonStosu<kostka_do_gry, 10> K3;

	// zapełnianie stosu
	ifstream fi("qv-lab4.txt");
	string s;
	try{
		K1.push("Henryk");
		K1.push("Sienkiewicz");
		while (fi) {
			fi >> s;
			K1.push(s);
			fi.seekg(ios::beg);
			fi.clear();
			cout << '*';
		};
	}
	catch (Przepelnienie& e){
		cout << "K1 gotowy: " << e.what() << endl;
	};
	cout << "Danych na stosie K1: " << K1.zajetosc() << endl;

	K2.push(temperatura_wody());
	K2.push(temperatura_wody(36.6));
	K2.push(40);
	K2.push(71.2);
	cout << "Danych na stosie K2: " << K2.zajetosc() << endl;

	K3.push(kostka_do_gry(3));
	K3.push(kostka_do_gry());
	K3.push(4);
	K3.push(6);
	K3.push(10);
	cout << "Danych na stosie K3: " << K3.zajetosc() << endl;

	// opróżnianie stosu
	try{
		while (true)
			K1.pop();
	}
	catch (BrakDanych& e) {
		cout << "K1 pusty: " << e.what() << endl;
	}
	try{
		while (true)
			K2.pop();
	}
	catch (BrakDanych& e) {
		cout << "K2 pusty: " << e.what() << endl;
	}
	try{
		while (true)
			K3.pop();
	}
	catch (BrakDanych& e) {
		cout << "K3 pusty: " << e.what() << endl;
	}

	system("pause");
	return 0;
}

ZTP 2019: Zadanie przed lab.3

Zadanie, które dotyczy zakresu materiału, jaki będzie poruszany na lab. 3. Rozwiązanie nie jest wymagane. Zadanie stanowi wyłącznie pomoc w przygotowaniu się do zajęć.

Zadanie:

Korzystając z szablonu kontenera Konten utwórz w funkcji main obiekt reprezentujący kontener do przechowywania zmiennych typu double i umieść w nim za pomocą metody push dowolną liczbę (nie większą od 100) wartości losowych rzeczywistych z przedziału 〈0, 10).

Napisz szablony trzech funkcji, które jako argument wejściowy przyjmują parę iteratorów identyfikujących przedział danych z kontenera (tak jak na slajdzie 199, wykład 4), i które dla liczb w tym przedziale znajdują lub obliczają i zwracają:

  1. wartość minimalną/maksymalną,
  2. medianę,
  3. wartość średnią.

Przyjmij, że typ danych przechowywanych w kontenerze zawsze pozwala na wszystkie standardowe operacje arytmetyczne i logiczne (posiada odpowiednie operatory). Uwaga: funkcje nie otrzymują w argumentach wywołania referencji ani wskaźnika do obiektu kontenera, a jedynie iteratory wskazujące na poprawny przedział danych w nim zawartych.
Zademonstruj poprawne działanie tych szablonów funkcji wywołując je w funkcji main dla przykładowych danych zapisanych w kontenerze. Na początku na potrzeby testów poprawności spreparuj dane testowe w kontenerze tak, aby łatwo było w pamięci policzyć wynik i potwierdzić poprawność działania szablonów funkcji.


Hint: aby wygenerować wartość losową z przedziału 〈0, 1) można np. użyć funkcji:
//generates a psuedo-random double between 0.0 and 0.999...
double randdouble()
{
return rand()/(double(RAND_MAX)+1);
}