Warning
This page is located in archive.

Úkol 1

1. úkol se skládá ze čtyř malých úloh:

  • Načtení matice ze vstupu
  • Výpis tabulky na výstup
  • Verifikace formátovaného vstupu
  • Práce s dlouhými čísly

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, který obsahuje jejich prázdná těla. Archiv se tedy dá po stažení zkompilovat a spustit, ale neprojdou testy.

Co odevzdat?

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

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í hlavičky, tests-main.cpp, zdrojový soubor s definicí makra CATCH_CONFIG_MAIN, a tests-small1.cpp, ve kterém jsou testy pro vaši implementaci.

Valgrind

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.

Rady

Užitečné hlavičky

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).

Dlouhá doba kompilace

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 -c
vá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 small1
a kompilace bude trvat výrazně kratší dobu.

Čtení kompilačních chyb

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 všem, 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: |
test.cpp:5:15: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'int')
    std::cout >> i;
    ~~~~~~~~~ ^  ~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/streambuf:168:9: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
        operator>>(basic_istream<_CharT2, _Traits2>&,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/istream:756:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<char, _Traits>& __in, unsigned char& __c)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/istream:761:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<char, _Traits>& __in, signed char& __c)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/istream:803:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<char, _Traits>& __in, unsigned char* __s)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/istream:808:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<char, _Traits>& __in, signed char* __s)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/bits/istream.tcc:923:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT& __c)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.1/../../../../include/c++/5.3.1/bits/istream.tcc:955:5: note: candidate template ignored: could not match 'basic_istream' against 'basic_ostream'
    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s)
    ^
1 error generated. 

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.

Undefined reference error

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.

  • Pokud vám chybí funkce main, nejspíše kompilujete pouze soubor s vaší implementací a nekompilujete soubory s testy.
  • Pokud vám chybí funkce, které máte implementovat, nejspíše kompilujete pouze soubory s testy a nekompilujete s nimi i vaši implementaci.
  • Pokud vám chybí funkce s Catch:: v názvu, nekompilujete tests-main.cpp.

Časově náročné testy

Ú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. stavět v Release módu nebo na příkazové řádce s parametrem -O3.

1)
Pokud má váš úkol 1 MB před zabalením, pravděpodobně toho odevzdáváte příliš. Pokud má váš úkol 1 MB po zabalení, *určitě* toho odevzdáváte příliš.
2)
Pokud ne, vyřeší za vás tyto věci vaše IDE.
courses/a7b36pjc/ukoly/ukol_1.txt · Last modified: 2016/10/13 10:59 by horenmar