Úkoly z osmého semináře

  1. Napište program, který spočítá počet znaků, řádků a slov v textovém souboru. (Analogie textové utility wc).

  2. Napište funkci, která z proudu načte jeden řádek, když předem neznáme délky řádků. Zajistěte, aby šla funkce používat opakovaně. (Musíte vymyslet vhodné argumenty, jejich předání a vypořádat se s alokacemi).

  3. Nastudujte v referenční příručce a vyzkoušejte funkci fgets.

  4. Napište program, který načte textový soubor a do jiného souboru uloží kopii jeho obsahu tak, že jeden řádek bude mít maximálně 80 znaků. Přitom nerozdělí žádná slova kratší než 80 znaků a minimalizuje počet řádků.

  5. PBM je textový formát pro uložený černobílého obrázku (každý pixel je buď černý nebo bílý).

    Doplňte chybějící kód v následujícím. (Můžete si dopsat pomocné funkce atd.)

    //
    //  Pro jednoduchost případné chyby (nelze otevřít soubor atd.)
    //  řešte pouze ukončením programu pomocí assert
    //
    //  Volitelně lze dopsat funkci pro dealokaci vnitřních dat
    //  struktury Picture (ale není to nutné, jde o procvičení práce
    //  se streamy).
    //
    
    //
    // Struktura pro černobílý obrázek
    //
    typedef struct 
    {
        // TODO
    } Picture;
    
    //
    // nahraje ze souboru obrázek ve formátu pbm
    // 
    Picture load_from_pbm(char* filename)
    {
        // TODO 
    }
    
    //
    // zrcadlově obrátí obrázek podle svislé osy
    //
    void mirror_picture(Picture* p)
    {
        // TODO
    }
    
    //
    // uloží obrázek v pbm formátu
    //
    void save_to_pbm(char* filename, Picture src)
    {
        // TODO
    }
    
    //
    // příklad použití
    //
    int main()
    {
        Picture picture = load_from_pbm("test.pbm");
        mirror_picture(&picture);
        save_to_pbm("foo.pbm", picture);
    }
  6. Uvažme ukládání řetězců do souboru v binárním formátu.

    Naprogramujte funkci void append(char* string, char* filename), která na konec souboru přidá nový řetězec.

    Naprogramujte funkci long search(char* string, char* filename), která prohledá soubor a pokud obsahuje záznam o daném řetězci, vrátí jeho offset od začátku souboru. Jinak vrátí -1.

    V souboru odpovídá řetězci jeden záznam, záznamy jsou v souboru za sebou. Jeden záznam vypadá následovně.

    offset  velikost   vyznam
    --------------------------------------------------------------------------
         0       2          velikost retezce v bajtech
    
         2       ?          ulozeny retezec, chapan jako posloupnost unsigned char
                                bez 0 na konci
    --------------------------------------------------------------------------
  7. Run Length Encoding (RLE) je velmi jednoduchý bezeztrátový kompresní princip. Vysvětlíme jej na posloupnostech symbolů a později si řekneme, jak jej uplatníme v jednoduchém kompresním programu.

    Vstupem RLE je posloupnost symbolů (symbol je zde abstraktní pojem, který nijak nevztahujeme k jazyku C, znakům v textu atd.). Tu převedeme do komprimované podoby s pomocí následujícího principu:

    Například posloupnost aaabaabcccccbccccd zakódujeme na

    (a,3)(b,1)(a,2)(b,1)(c,5)(b,1)(c,3)(d,1)

    Naprogramujte základ jednoduchého kompresního programu.

    Soubor pro kompresi budeme otevírat v binárním módu. Pro RLE budeme za jeden symbol považovat jeden bajt souboru. Dvojici (x, n), kde x je symbol a n je počet jeho výskytů budeme do výsledného souboru ukládat pomocí dvou bajtů: do prvního uložíme x, do druhého uložíme n-1. Takto jsme schopni uložit pouze dvojice, kde je n <= 256. Dvojice, kde je n>256, si představíme jako posloupnost n/256 dvojic (x, 256) následovanou dvojicí (x, r), kde r = n % 256. Tyto dvojice poté uložíme stejným způsobem, jako dvojice s n<=256.

    Kompresní program implementujte jako funkce

    void RLE_encode(char* in_path, char *out_path);
    void RLE_decode(char* in_path, char *out_path);