1. úkol se zaměřuje na práci s formátovaným vstupem a výstupem a skládá se ze čtyř malých úloh:
K dispozici máte archiv obsahující
Catch testy, které vám zkontrolují vaše
řešení, a dva další soubory. Hlavičkový soubor small1.hpp
obsahuje deklarace
funkcí, které máte implementovat; a zdrojový soubor small1.cpp
obsahuje jejich prázdná těla. Archiv se tedy dá po stažení zkompilovat a
spustit, ale neprojdou testy.
Odevzdávejte soubor .zip
, který obsahuje jeden nebo více souborů .cpp
,
ve kterých jsou implementované funkce z hlavičkových souborů z domácího úkolu.
Vámi odevzdané soubory by neměly být schované v podsložce a prosíme vás, abyste
neodevzdávali soubory vašeho IDE1).
Žádný ze souborů s testy není třeba odevzdávat.
Catch
je framework pro psaní testů pro C++ kód. Základní použití je
jednoduché, stačí v nějakém souboru deklarovat makro CATCH_CONFIG_MAIN
před
includováním hlavičky catch.hpp
a v ostatních souborech se již můžou psát
testy. Následně stačí zkompilovat zdrojové soubory a spustit výsledný program,
čímž se provedou a vypíšou výsledky testů.
V archivu, který máte od nás, najdete catch.hpp
, hlavičku s aktuální verzí
testovací testovacího frameworku, tests-main.cpp
, zdrojový soubor s definicí makra
CATCH_CONFIG_MAIN
, a tests-small1.cpp
, ve kterém jsou testy pro vaši
implementaci.
Všechny odevzdané úkoly jsou kontrolovány za použití Valgrindu. Valgrind je schopen najít spoustu chyb, které se normálně nemusí projevit, a v případě, že nějakou najde, bude vám sražena část bodů z domácího úkolu.
V různých úkolech si můžete ulehčit práci použitím standardních knihoven. V
tomto doporučujeme podívat se blíže na
hlavičku <iomanip> a samozřejmě na
věci, které se probíraly na cvičení (například std::stringstream
).
Pokud kompilujete z příkazové řádky2), pravděpodobně zjitíte, že vám kompilace běží velmi dlouho (5-10s).
Protože nejdelší dobu se kompiluje soubor tests-main.cpp
, který se nebude
měnit, vyplatí se ho zkompilovat do tzv. objektového souboru. Objektové soubory
jsou mezikrok mezi implementačními soubory a fungujícím programem.
Pokud spustíte kompilátor s argumentem -c
, místo binárky se vám vytvoří
objektové soubory. Volání
clang++ -std=c++14 tests-small.cpp tests-main.cpp -cvám vytvoří soubory
tests-small.o
a tests-main.o
, které pak můžete
použít při kompilaci místo tests-small.cpp
a tests-main.cpp
. Pozor,
soubor s vaší implementací takto nahradit nemůžete, protože .o
soubory se
automaticky neaktualizují při změnách původních .cpp
souborů.
Výsledné volání pro kompilaci tedy bude zhruba takovéto
clang++ -std=c++14 tests-small.o tests-main.o small1.cpp -o small1a kompilace bude trvat výrazně kratší dobu.
Pokud se něco pokazí při kompilaci, C++ je schopno generovat opravdu dlouhé chyby. Ve skutečnosti je z nich obvykle relevantní pouze krátká část, protože výpis má formu kompilačního stacktrace – při kompilaci jaké funkce vznikla chyba a proč byla daná funkce kompilována. To znamená, že při čtení kompilační chyby je potřeba najít první výpis, který je ve vašem kódu, protože právě ten způsobuje danou chybu. Kompilátory dále mají tendenci přidat na konec výpisu chyby informace, o co všechno se pokusili.
Co to znamená, ukážeme na příkladu:
#include <iostream> int main(){ int i; std::cout >> i; std::cout << i; }Tento kus kódu se snaží načíst a vypsat jedno číslo, ale místo
std::cin
je v
něm použit std::cout
. Když ho proženeme skrz Clang, získáme tento výpis:
Hned první řádek výpisu se odkazuje do našeho kódu a zhruba říká, kde je chyba
(nemůžeme použít operátor >>
na výstupní proud a int), ale výpis
obsahuje spoustu dalších řádků, které popisují, co všechno kompilátor zkusil,
než došel k tomu, že to je chyba. V tomto případě vyzkoušel různá přetížení
operátoru >>
, ale zjistil, že žádné z nich nepasuje pro daný výraz.
Pokud vám linkování programu selže s chybou během linkování, pravděpodobně to znamená, že nelinkujete vše, co máte.
main
, nejspíše kompilujete pouze soubor s vaší implementací a nekompilujete soubory s testy.
Catch::
v názvu, nekompilujete tests-main.cpp.
Úkol obsahuje časově náročné testy, které jsou při normálním spuštění vypnuté.
Pokud je chcete spustit, musíte zavolat výslednou binárku s argumentem
[.long]
:
small1 [.long]
Silně doporučujeme ho spouštět pouze v optimalizované binárce, tj. kompilovat v
Release módu nebo na příkazové řádce s parametrem -O3
.