HW01: Ascii85

Odevzdávání úkolu je ukončeno.
Autoři zadání Petr Pilař Tobiáš Kamenický
Úprava Patrick Ondika
Odevzdávané soubory ascii85.c
Začátek odevzdávání viz diskusní fórum
Další odevzdání navíc do 2024-03-07 12:00
Konec odevzdání 2024-03-13 24:00
Vzorová implementace /home/kontr/pb071/hw01/ascii85
Opravy v zadání 2024-03-06 13:34 3

Představení úkolu

Ascii85 (někdy též nazývané Base85) je kódování, které bylo vytvořeno primárně za účelem konverze binárních dat na data textová. Tato konverze umožňuje jejich přenos přes výhradně textové protokoly. Jelikož některé protokoly umožňují používání pouze vybraných tisknutelných znaků, je rozsah výstupních symbolů kódování Ascii85 omezen.

Zadání

Vaším úkolem bude vytvořit program schopný kódovat a dekódovat data ze standardního vstupu pomocí algoritmu Ascii85.

Ascii85 každým 4 bajtům přiřadí bajtů 5. Postup je následující: Vstupní 4 bajty převedeme na jedno číslo N (tak, že ony 4 bajty „poskládáme za sebe“). Z tohoto čísla N nejprve vezmeme zbytek po dělení 85, čímž získáme náš první mezivýpočet, poté se N celočíselně vydělí 85 (tento proces se celkem opakuje pětkrát, čímž získáme 5 čísel). Ke každému takto získanému číslu přičteme 33. Tím jsme získali ASCII kódy výsledných pěti znaků.

Zamyslete se nad tím, které numerické typy mají dostatečný rozsah — zaručují vám, že se do nich každé vstupní číslo N vejde.

Příklad

Vstup: "Lore"

Vstupní bajt Dekadické vyjádření Binární vyjádření

L

76

01001100

o

111

01101111

r

114

01110010

e

101

01100101

N je tedy v binární soustavě vyjádřeno jako 01001100011011110111001001100101, v dekadické je to 1282372197.

Zbytek po dělení 85 Výsledek dělení 85

62

15086731

81

177490

10

2088

48

24

24

0

Výsledkem tedy bude 5 bajtů vyjádřených znaky s ASCII označením 95, 114, 43, 81, 57 což jsou znaky '_', 'r', '+', 'Q', '9'.

Výstup: "_r+Q9"

Požadavky

Váš program musí jít přeložit a fungovat dle požadavků pro zkompilování na Aise.

Kódování

Funkce int encode(void) zakóduje data načtená ze standardního vstupu pomocí Ascii85 a vypíše je na standardní výstup.

  • Ze standardního vstupu přestaňte číst, jakmile funkce pro čtení signalizuje konec vstupu hodnotou EOF (End of File).

  • Pokud vstup skončí, aniž by z něj program načetl kompletní čtveřici bajtů, doplňte ji zprava znaky '\0'.

  • Dojde-li k chybě, funkce vrátí nenulové kladné číslo, jinak vrátí 0.

  • Funkce musí na konec výstupu zapsat znak nového řádku, '\n'.

Funkce encode() vrací hodnotu typu int především kvůli konzistenci s funkcí decode() (viz níže). Jestliže nebudete pracovat s žádnými zdroji, encode() by měla vždy vracet 0.

Dekódování

Funkce int decode(void) dekóduje data načtená ze standardního vstupu, která byla zakódována pomocí Ascii85, a vypíše je na standardní výstup.

  • Ze standardního vstupu přestaňte číst, jakmile funkce pro čtení signalizuje konec vstupu hodnotou EOF (End of File).

  • Při dekódování neodstraňujte z konce výstupu znaky '\0'. Nemůžete vědět, jestli původní vstup končil znaky '\0', jestli byly doplněny při zakódování, nebo jestli je vstupem např. obrázek ve formátu PNG, kde se nulové bajty běžně vyskytují.

  • Funkce musí při čtení ignorovat bílé znaky (např. '\n').

  • Pokud načtený vstup nemohl vzniknout použitím Ascii85, tedy:

    • jeho délka není dělitelná pěti,

    • obsahuje bajty, které Ascii85 nevyužívá a které nejsou bílé, nebo

    • celková hodnota po dekódování přesahuje 4 bajty;

      funkce vrátí nenulové kladné číslo, jinak vrátí 0.

Kostra řešení je navržena tak, že funkce encode() je volána z funkce main(), jestliže je program spuštěn bez přepínačů, nebo právě s přepínačem -e. Podobně, decode() je z main() volána, pokud je program spuštěn právě s přepínačem -d.

Příklady

Kódování

Vstup Výstup

Man

>oqj9

Donec nec euismod orci

SsQu6#Z#j@*?#j@0-elB2f>0ACobq@

Lorem ipsum dolor sit amet, consectetur adipiscing elit

_r+Q93P3'DB=2*F&:c8A;FfZE/"G<FGITTA+7Hr@ngfRAHUMEFk(X:@ucdlB')(JDkt[hC

Dekódování

Vstup Výstup

T1C#6

Amet

Uu]i:26K(F*tbD+6rTfD-",!F)FV5B6Jo(F%jN+E$UuSA6>c)F

Praesent lobortis dignissim pellentesque

Bonusová rozšíření

Korektní typy [10 bodů]

Až 10 bonusových bodů obdrží ti, kteří správně použijí numerické typy s pevnou velikostí. Tyto typy se nachází v hlavičce stdint.h. Mezi typy s pevnou velikostí patří například uint8_t (8-bitové číslo bez znaménka) nebo int32_t (32-bitové číslo se znaménkem).

Poznámky

  • Pro čtení doporučujeme použít bezparametrickou funkci getchar(3). Tato funkce vrací buď jeden znak ze standardního vstupu, nebo EOF, pokud už žádné další znaky není možné přečíst. Návratovým typem této funkce je int, aby bylo možné rozlišit EOF od vstupních bajtů.

  • Zda je znak bílý, lze ověřit pomocí funkce isspace(3).

  • Při zadávání vstupu z příkazové řádky můžete poslat znak EOF stisknutím ^D (Ctrl+D), čímž značíme konec vstupu.

  • Pro testování vaší implementace můžete na Linuxu použít např. příkaz

    echo -en 'Donec nec euismod orci' | ./ascii85

    Na Windows doporučujeme použít Windows Subsystem for Linux nebo Git Bash.

  • Pro dekódování může být užitečné umět přečíst netisknutelné znaky. To můžete v Linuxovém terminálu udělat např. pomocí hexdump.

    • Příklad: Chceme-li se podívat, zda nám sekvence encode a decode vrátí původní sekvenci bajtů, uděláme to následovně:

      echo -en "\x00\x01\x02\x03" | ./ascii85 -e | ./ascii85 -d | hexdump -c

      Výstupem bude sekvence bajtů oddělených mezerami, kde první sloupec značí počáteční pozici.

      0000000  \0 001 002 003
      0000004
  • Kontrola bude probíhat porovnáváním výstupů. Dejte si tedy pozor, ať nevypisujete nic navíc.

    • V případě chybných vstupů není kontrolován standardní výstup programu, ale pouze, zda funkce encode (resp. decode) vrací nenulové kladné číslo.

    • Na standardní chybový výstup nic nevypisujte. O to se postará funkce main z kostry. Tuto funkci neupravujte.

  • Své vypracování můžete porovnat se vzorovým, které naleznete na aise. Umístění vzoru je následující:

    /home/kontr/pb071/hw01/ascii85
  • Pro testování doporučujeme použít buď CUT nebo CLI testy. CUT je vhodný na testování malých komponent, zatímco CLI je vhodnější na testování celkového fungování programu, a bude se spouštět při commitu na git. První úloha je dostatečně malá na to, aby dávaly smysl obě možnosti.

Opravy v zadání

Extend early deadline

c4e60e9 2024-03-06 13:34 Roman Lacko
 -7,3 +7,3  publish: now
 publish-solution: ~
-deadline-early: 2024-03-06 24:00
+deadline-early: 2024-03-07 12:00
 deadline-final: 2024-03-13 24:00

Fix shell command

e9db2e3 2024-03-03 09:35 Filip Krása
 -148,3 +148,3  nebo link:https://www.fi.muni.cz/pb071/man/#git-for-windows-verzovac%C3%AD-syst%
 ----
-echo -en "\x00\x01\x02\x03" | | ./ascii85 -e | ./ascii85 -d | hexdump -c
+echo -en "\x00\x01\x02\x03" | ./ascii85 -e | ./ascii85 -d | hexdump -c
 ----

Fix example output

78bd79a 2024-02-29 10:56 xondika
 -101,3 +101,3  Podobně, `decode()` je z `main()` volána, pokud je program spuštěn právě s
 | Vstup | Výstup
-| `Man` | `9jqo>`
+| `Man` | `>oqj9`
 | `Donec nec euismod orci` | `SsQu6#Z#j@*?#j@0-elB2f>0ACobq@`