Lawful Evil #2 – Pilne Kolos z struktur

Treść prośby1 o pomoc wyglądała następująco:

Zadanie 1
Zdefiniuj strukturę opisującą książkę zawierającą pola (ilość stron, numer
biblioteczny, termin wypożyczenia) , oraz zdefiniuj strukturę opisującą datę. W
programie dynamicznie utwórz zmienną typu strukturalnego z polem typu
strukturalnego , następnie wczytaj z klawiatury wartości pól, po czym wczytane
informacje wydrukuj na ekranie. Przed zakończeniem programu zwolnij pamięć po
dynamicznie utworzonej zmiennej. (3 pkt)
Zadanie 2
Napisz funkcję, która zwraca jako wartość wskaźnik do zmiennej strukturalnej
opisującej książkę. Zadaniem funkcji jest zaalokowanie zmiennej oraz ustalenie
wartości jej pól (wartości pól zmiennej wczytujemy z klawiatury).
Napisz program testujący działanie funkcji.

Visual Studio

Wyglądała więc na idealnego kandydata do tej kategorii.

Pomimo ograniczenia czasowego – 90 minut – myślę, że udało mi się osiągnąć zamierzony efekt.

Zadanie 1

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
 
#include <algorithm>
#include <array>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <thread>
#include <typeinfo>
 
using namespace std;
 
template<typename T>
struct Value
{
    T value;
};
 
struct Data
{
    int rok;
    int miesiac;
    int dzien;
};
 
struct IloscStron : Value<int>{};
struct NumerBilioteczny : Value<string>{};
struct TerminWypozyczenia : Value<Data>{};
 
typedef tuple<IloscStron, NumerBilioteczny, TerminWypozyczenia> Struktura;
 
auto main() -> int
{
    auto * dyn = new Struktura;
    cout << "Podaj ilosc stron:" << endl;
    cin >> get<IloscStron>(*dyn).value;
    cout << "Podaj numer biblioteczny:" << endl;
    cin >> get<NumerBilioteczny>(*dyn).value;
    cout << "Podaj termin wypozyczenia - rok:" << endl;
    cin >> get<TerminWypozyczenia>(*dyn).value.rok;
    cout << "Podaj termin wypozyczenia - miesiac:" << endl;
    cin >> get<TerminWypozyczenia>(*dyn).value.miesiac;
    cout << "Podaj termin wypozyczenia - dzien:" << endl;
    cin >> get<TerminWypozyczenia>(*dyn).value.dzien;
 
    cout << "Wczytano: " << endl <<
            "Numer biblioteczny: " << get<NumerBilioteczny>(*dyn).value << endl <<
            "Ilosc stron: " << get<IloscStron>(*dyn).value << endl <<
            "Termin wypozyczena: " << get<TerminWypozyczenia>(*dyn).value.rok << "-" <<
            get<TerminWypozyczenia>(*dyn).value.miesiac << "-" <<
            get<TerminWypozyczenia>(*dyn).value.dzien << endl;
 
    delete dyn;
}

Nie ma tutaj specjalnych cudów, ale dla uczących się podstaw C++ ten kod to powinna być czarna magia. Nie przeszedłby też żadnego sensownego code review, ale technicznie rzecz biorąc, jest poprawny.

Na uwagę zasługuje szablon klasy Value, po którym dziedziczą klasy IloscStron , NumerBilioteczny i TerminWypozyczenia. Dzięki zastosowaniu tych klas jako typów zmiennych, mogłem użyć jako struktury z zadania tuple<IloscStron, NumerBilioteczny, TerminWypozyczenia> oraz wybierać jej elementy za pomocą std::get po typie. Niestety, okazało się, że konieczna jest kompatybilność z VS 2010, który wymaga std::get z indeksem.

Utworzyłem też, zgodnie z wymaganiami, strukturę Data. Ale nigdzie jej nie użyłem.

Zadanie 2

Ponieważ dostałem feedback, że zadanie 1 nie zostało dostatecznie przekombinowane, w zadaniu drugim podniosłem poprzeczkę:

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
 
#define WIN32_LEAN_AND_MEAN
 
#include <algorithm>
#include <array>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
 
#include <hash_map>
#include <array>
#include <windows.h>
#include <random>
#include <ostream>
 
#include <map>
#include <memory>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <thread>
#include <typeinfo>
#include <tuple>
 
using namespace std;
 
#define DBG(x) { cout << left << setw(100) << #x << boolalpha << (x) << endl; }
#define DBG_CONT(x) { cout << left << setw(40) << #x; for(auto const& _name : (x)) \
    cout << boolalpha << _name << " "; cout << endl; }
 
template<typename T>
struct Value
{
    T value;
};
 
struct Data
{
    int rok;
    int miesiac;
    int dzien;
};
 
struct IloscStron : Value<int>{};
struct NumerBilioteczny : Value<string>{};
struct TerminWypozyczenia : Value<Data>{};
 
typedef tuple<IloscStron, NumerBilioteczny, TerminWypozyczenia> Struktura;
 
template<int Magic = 42>
Struktura* utworzIWczytajStrukture(){
    return utworzIWczytajStrukture<Magic-1>();
}
 
template<>
Struktura* utworzIWczytajStrukture<0>()
{
    auto * Magic = new Struktura;
    cout << "Podaj ilosc stron:" << endl;
    cin >> get<0>(*Magic).value;
    cout << "Podaj numer biblioteczny:" << endl;
    cin >> get<1>(*Magic).value;
    cout << "Podaj termin wypozyczenia - rok:" << endl;
    cin >> get<2>(*Magic).value.rok;
    cout << "Podaj termin wypozyczenia - miesiac:" << endl;
    cin >> get<2>(*Magic).value.miesiac;
    cout << "Podaj termin wypozyczenia - dzien:" << endl;
    cin >> get<2>(*Magic).value.dzien;
 
    return Magic;
}
 
int main()
{
    auto * dyn = utworzIWczytajStrukture();
 
    cout << "Wczytano: " << endl <<
            "Numer biblioteczny: " << get<1>(*dyn).value << endl <<
            "Ilosc stron: " << get<0>(*dyn).value << endl <<
            "Termin wypozyczena: " << get<2>(*dyn).value.rok << "-" <<
            get<2>(*dyn).value.miesiac << "-" <<
            get<2>(*dyn).value.dzien << endl;
 
    delete dyn;
    int zlap_konosole;
    cin >> zlap_konosole;
}

Nie tylko pierwsze litery części include’ów układały się w nazwisko prowadzącego:

#include <hash_map>
#include <array>
#include <windows.h>
#include <random>
#include <ostream>

Ale też zadaną funkcję utworzyłem jako szablon pseudo-rekursywnie się wywołujący, co dało mi ładne 42 zbędne poziomy wywołań na callstacku:

template<int Magic = 42>
Struktura* utworzIWczytajStrukture(){
	return utworzIWczytajStrukture<Magic-1>();
}
 
template<>
Struktura* utworzIWczytajStrukture<0>()
{
	auto * Magic = new Struktura;
	cout << "Podaj ilosc stron:" << endl;
	cin >> get<0>(*Magic).value;
	cout << "Podaj numer biblioteczny:" << endl;
	cin >> get<1>(*Magic).value;
	cout << "Podaj termin wypozyczenia - rok:" << endl;
	cin >> get<2>(*Magic).value.rok;
	cout << "Podaj termin wypozyczenia - miesiac:" << endl;
	cin >> get<2>(*Magic).value.miesiac;
	cout << "Podaj termin wypozyczenia - dzien:" << endl;
	cin >> get<2>(*Magic).value.dzien;
 
	return Magic;
}

W wykonaniu wygląda to tak:

ScreenshotScreenshot

Niestety tym razem nie wygrało dobro (kq):

Pytał ale jakoś jana popaliłem i zaliczył :d a z drugiej strony skąd znasz nazwisko mojego wykładowcy ?

1W sumie ciężko było powiedzieć czy to prośba, bo słowo “proszę” ani żadne podobne nie znajduje się w treści.

3 thoughts on “Lawful Evil #2 – Pilne Kolos z struktur

    1. Pytanie zostało zadane z sali zajęć. Jeden z moderatorów postanowił sprawdzić czy to nie jakaś uczelnia, oraz, jeśli tak, czy odbywają się na niej akurat jakieś zajęcia, które pasują do pytań. Udało się 🙂

  1. Very good article! We are linking to this particularly great content on our site. Keep up the great writing.

Leave a Reply

Your email address will not be published.