Search
V této jednohubce budete mít za úkol naimplementovat jednoduchou funkci, write_stats, která bere dva argumenty, sadu dat a výstupní proud, a do výstupního proudu zapíše 3 statistické údaje o datech: minimum, maximum a průměr.
write_stats
Údaje musí být zapsány ve specifickém formátu, například pro vstupní data “1.23, 5.44, -23” by výstup vypadal takto:
min: -23.00 max: 5.44 mean: -5.44
Všimněte si, že čísla jsou vždy vypsaná se dvěma desetinnými čísly.
Projekt s testy najdete zde.
Do Brute odevzdávejte pouze Váš soubor tiny-00.cpp s vaší implementací funkce write_stats.
tiny-00.cpp
Formátovací manipulátory, které budete potřebovat, najdete v jedné ze dvou hlaviček:
Zároveň vás může zajímat šablona numeric_limits, přes kterou můžete získat informace o největší možné hodnotě typu a další podobné informace.
V této jednohubce dostanete rozpracovaný kód implementující dvě přetížení funkce pluralize, specificky
pluralize
std::string pluralize(std::string const& str);
std::vector<std::string> pluralize(std::vector<std::string> const& str);
Jak název napovídá, úkol této funkce je převést předané slovo, případně vektor slov, na jejich množné číslo. V kódu který máte je ovšem chyba, takže část testů neprochází, a vaším úkolem je změnit kód který dostanete tak, aby všechny testy procházely.
Do Brute odevzdávejte pouze zazipovaný soubor tiny-01.cpp s vašimi změnami.
tiny-01.cpp
Tento úkol si můžete udělat velmi těžký, nebo velmi jednoduchý. Proto vám doporučujeme si před hledáním chyby v kódu pustit testy a rozmyslet si, co vidíte na výstupu.
V této jednohubce znovu dostanete již hotový kód, ale na rozdíl od minulé jednohubky všechny testy procházejí. To ovšem neznamená, že je s ním vše v pořádku – jak název napovídá, obsahuje chybu práce s dynamicky alokovanou pamětí.
Projekt s implementací a testy najdete zde.
Poznámka k implementaci: funkcionalita funkce summarize_data je popsána uvnitř hlavičky tiny-02.hpp anglicky. Pro jistotu ji zde uvádíme i česky:
summarize_data
tiny-02.hpp
Pokud jste na Linuxu, již mnohokrát zmiňovaný Valgrind vám řekne k jaké chybě dochází a kde. Pokud jste na Windows, doporučujeme Dr. Memory, který funguje zhruba stejně jako Valgrind. Pokud používáte aktuální verzi OS X, Valgrind vám bohužel nebude fungovat, budete tedy muset použít o něco komplikovanější nástroj jménem AddressSanitizer.
Poučen problémy v minulé jednohubce se programátor rozhodl opravit kód summarize_data tak, aby ke stejné chybě již nemohlo dojít. Vytvořil si tedy třídu fixed_array, která za alokované pole zodpovídá a vždy ho správně uvolní. Bohužel se to zcela nepovedlo a na vás je, abyste to opravili.
fixed_array
Též trochu změnil formát výstupu, protože si uvědomil, že když se špatné řádky prostě vypustí, tak není možné zpětně zjistit, které řádky nebyly platné. Nyní se tedy pro neplatné řádky vrací statistika, která říká, že na řádku bylo std::numeric_limits<size_t>::max() prvků.
std::numeric_limits<size_t>::max()
Pokud se vám kompilátor snaží poradit, je dobrý nápad mu naslouchat.
V této jednohubce bude vaším úkolem doplnit funkční kopírovací a přesunující operace pro jednoduchý binární vyhledávací strom.
Připomeňte si obsah odpovídající cvičení.
V této jednohubce si vyzkoušíte přetěžování operátorů pro třídu. Specificky se jedná o třídu pjc::complex a matematické operátory +, - a * (pouze v binární variantě). Specificky chceme, aby šly sčítat (respektive odčítat nebo násobit) dvě instance třídy pjc::complex nebo instance třídy pjc::complex s double.
pjc::complex
+
-
*
double
Do Brute tentokrát odevzdejte i vámi změněnou hlavičku tiny-05.hpp.
tiny-05.hpp
Pokud si nepamatujete jak fungují dané operace nad komplexními čísly, wikipedie poradí.
V této jednohubce vás čeká modifikace již existující virtuální hierarchie tříd. Specificky se jedná o hierarchii různých generátorů náhodných čísel a vaším úkolem bude do ní doplnit sběr různých statistik:
int
bool
Do Brute tentokrát odevzdejte i vámi změněnou hlavičku tiny-06.hpp.
tiny-06.hpp
Existují dva způsoby, jak tuto jednohubku vyřešit. Jeden je pracnější, zabere vám delší dobu, ale nemusíte u něj vůbec přemýšlet. Alternativně můžete použít idiom, kterému se říká Nevirtuální rozhraní (NVI – NonVirtual Interface), který umožňuje předkovi (rozhraní) vynutit, aby byly dodrženy invarianty během volání poděděných metod.
NVI je implementace návrhového vzoru “Template Method” (šablona, šablonová metoda), specifická pro C++. Bohužel se nám nepovedlo najít dobrý text vysvětlující specificky NVI v češtině, ale WikiBooks obsahuje dobré vysvětlení v angličtině.
Jak jsme si ukazovali na cvičení, v C++ nelze kombinovat kovariantní návratové typy s chytrými ukazately, jako je například std::unique_ptr. Nicméně, chytrou kombinací nevirtuálního rozhraní, schovávání, virtuálního rozhraní a boilerplate, se dá kovariance simulovat.
std::unique_ptr
V této jednohubce budete znovu pracovat s hierarchií tříd které generují náhodná čísla a vaším úkolem bude doplnit metodu clone, která vrací příslušně konkretizovaný std::unique_ptr a zároveň se chová polymorfně.
clone
Do Brute odevzdejte i vámi změněnou hlavičku tiny-07.hpp.
tiny-07.hpp
Je jasné, že metoda clone nemůže být virtuální, ale pro její správné chování potřebujete virtuální polymorfismus. Jinak řečeno, budete muset těch metod implementovat více.
V této jednohubce si napíšete jednoduchou šablonovou funkci clamp. Tato funkce se v C++17 stala součástí standardní knihovny, ale protože v tomto předmětu používáme tento semestr stále ještě C++14, budeme ji implementovat my.
clamp
Funkce clamp má dvě přetížení
T const& clamp(T const& value, T const& low, T const& high)
T const& clamp(T const& value, T const& low, T const& high, Compare cmp)
které vrací low pokud value je menší než low, high pokud value je větší než high a jinak value. Jinak řečeno, value je omezeno do rozsahu [low, high]. První overload předpokládá, že T je porovnatelné pomocí operátoru <, druhý overload pak bere vhodný komparátor jako 4. argument.
low
value
high
[low, high]
T
<
Do Brute odevzdejte vaši hlavičku tiny-08.hpp.
tiny-08.hpp
Není potřeba implementovat obě funkce stejně, můžete implementovat jednu voláním druhé. K tomu se vám bude hodit obsah hlavičky functional.
K této jednohubce vám navíc nabízíme dvě otázky k zamyšlení:
const int& clamped = clamp(value, 0, 255);
V této jednohubce se naposled vrátíme k naší implementaci vector ze cvičení. Poslední, co jsme s ním dělali, byla optimalizace metody push_back(Iterator, Iterator) dle typu iterátoru, kterou dostala. V této jednohubce budeme podobně optimalizovat zvětšování (a kopírování) vektoru v závislosti na typu, pro který je náš vector instanciovaný. Specificky to znamená, že budeme rozlišovat 3 druhy typů,
vector
push_back(Iterator, Iterator)
noexcept
a budeme se k nim chtít chovat jinak, když budeme rozšiřovat pole uvnitř vektoru. Specificky, triviálně kopírovatelné typy chceme kopírovat pomocí memcpy, typy, které nejsou triviálně kopírovatelné, ale nemohou vyhodit výjimku při přesunujícím přiřazení, chceme opravdu přesunout a typy, které výjimku vyhodit mohou, chceme prostě zkopírovat.
Do Brute odevzdejte hlavičky array.hpp, vector.hpp a případné jiné hlavičky které jste vytvořili.
array.hpp
vector.hpp
K zjištění, jestli je typ triviálně kopírovatelný používejte pjc::is_trivially_constructible z pjc-traits.hpp, a ne std::is_trivially_constructible.
pjc::is_trivially_constructible
pjc-traits.hpp
std::is_trivially_constructible
Pro implementaci tohoto úkolu doporučujeme použít SFINAE (viz přednáška), a ne tag dispatch, který byl použit na cvičení.
Jestli přesunující přiřazení daného typu je noexcept se dá zjistit pomocí traitu is_nothrow_move_assignable ze standardní knihovny.
Triviálně kopírovatelné typy jsou typy s triviálním kopírovacím konstruktorem a přiřazením. Méně kruhově definováno, jsou to typy u kterých je volání kopírovacích operací ekvivalentní se zkopírováním jejich bitové reprezentace2).
Důvod, proč nechceme přesouvat typy, které mohou vyhodit výjimku je poskytnutí tzv. silné záruky. Detaily jsou v přednášce “Exception Safety”, hrubý nástin pak je, že pokud dojde k chybě během zvětšování vektoru, tak se silnou zárukou zůstanou původní prvky zachovány a nepřijdeme o data.
trivially_copyable_tracker