{"id":20665183,"url":"https://github.com/martan03/ijc-project2","last_synced_at":"2025-08-12T09:03:13.961Z","repository":{"id":160439287,"uuid":"618140080","full_name":"Martan03/IJC-Project2","owner":"Martan03","description":"Second project to IJC subject","archived":false,"fork":false,"pushed_at":"2023-04-24T07:12:28.000Z","size":1765,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-17T11:26:43.567Z","etag":null,"topics":["c","hash-table","tail","wordcount"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Martan03.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-23T20:47:32.000Z","updated_at":"2023-10-05T21:15:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"e26bae53-b13c-41a0-b457-df1e465f2759","html_url":"https://github.com/Martan03/IJC-Project2","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Martan03/IJC-Project2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Martan03%2FIJC-Project2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Martan03%2FIJC-Project2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Martan03%2FIJC-Project2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Martan03%2FIJC-Project2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Martan03","download_url":"https://codeload.github.com/Martan03/IJC-Project2/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Martan03%2FIJC-Project2/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270032623,"owners_count":24515322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","hash-table","tail","wordcount"],"created_at":"2024-11-16T19:28:56.690Z","updated_at":"2025-08-12T09:03:13.935Z","avatar_url":"https://github.com/Martan03.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"Jazyk C                       DU2                      21.3.2023\n----------------------------------------------------------------\n\n                         Domácí úkol č.2\n\n\nTermín odevzdání: 18.4.2023                       (Max. 15 bodů)\n\n1) (max 5b)\n   a) V jazyku C napište program \"tail.c\", který  ze zadaného\n   vstupního souboru vytiskne posledních  10 řádků. Není-li\n   zadán vstupní soubor, čte ze stdin. Je-li programu zadán\n   parametr -n číslo, bude se tisknout tolik posledních řádků,\n   kolik je zadáno parametrem 'číslo' (bez znaménka).\n   Případná chybová hlášení tiskněte do stderr. Příklady:\n\n     tail soubor\n     tail -n 20 \u003csoubor\n\n   [Poznámka: výsledky by měly být +-stejné jako u POSIX tail]\n\n   Implementujte funkce cb_create(n), cb_put(cb,line), cb_get(cb), cb_free(cb)\n   tvořící API pro specializovaný kruhový buffer dynamicky alokovaných řádků\n   (https://en.wikipedia.org/wiki/Circular_buffer). Pozor na test\n   prázdnosti/plnosti (shoda indexů znamená prázdný buffer).\n\n   Program tail není modulární.\n   Použijte implementační limit na délku řádku (např. 4095 znaků),\n   v případě prvního překročení mezí hlaste chybu na stderr (řádně otestujte)\n   a pokračujte se zkrácenými řádky (zbytek řádku přeskočit/ignorovat).\n\n\n2) (max 10b)\n   Přepište následující C++ program do jazyka ISO C\n\n    // wordcount-.cc\n    // Použijte: g++ -O2\n    // Příklad použití STL kontejneru unordered_map\u003c\u003e\n    // Program počítá četnost slov ve vstupním textu,\n    // slovo je cokoli oddělené \"bílým znakem\"\n\n    #include \u003cstring\u003e\n    #include \u003ciostream\u003e\n    #include \u003cunordered_map\u003e\n\n    int main() {\n        using namespace std;\n        unordered_map\u003cstring,int\u003e m;  // asociativní pole\n                     // mapuje klíč/string na hodnotu/int\n        string word;\n        while (cin \u003e\u003e word) // čtení slova (jako scanf \"%s\", ale bezpečné)\n            m[word]++;      // počítání výskytů slova (zvýší hodnotu pro\n                            // zadaný klíč/slovo pokud záznam existuje,\n                            // jinak vytvoří nový záznam s hodnotou 0 a\n                            // tu operace ++ zvýší na 1)\n\n        for (auto \u0026mi: m)   // pro všechny prvky kontejneru m\n            cout \u003c\u003c mi.first \u003c\u003c \"\\t\" \u003c\u003c mi.second \u003c\u003c \"\\n\";\n            //      klíč/slovo          hodnota/počet\n            // prvky kontejneru typu \"map\" jsou dvojice (klíč,hodnota)\n    }\n\n   Výstupy programů musí být pro stejný vstup stejné (kromě pořadí a příliš\n   dlouhých slov).\n\n   Výsledný program se musí jmenovat \"wordcount.c\".\n\n   Implementujte tabulku s rozptýlenými položkami (hash table) - viz dále.\n   Veškeré operace s tabulkou budou v samostatné knihovně (vytvořte statickou\n   i dynamickou/sdílenou verzi).  V knihovně musí být prakticky každá funkce ve\n   zvláštním modulu -- to například umožní případnou výměnu htab_hash_function() ve vašem\n   staticky sestaveném programu. (V dynamicky sestaveném programu je to možné vždy.)\n   Vyzkoušejte si to: definujte svoji verzi htab_hash_function() v programu\n   s podmíněným překladem -- použijte #ifdef HASHTEST.\n\n   Knihovna s tabulkou se musí jmenovat\n   \"libhtab.a\" (na Windows je možné i \"htab.lib\") pro statickou variantu,\n   \"libhtab.so\" (na Windows je možné i \"htab.dll\") pro sdílenou variantu\n   a rozhraní \"htab.h\".\n\n   Podmínky:\n    - Implementace musí být dynamická (malloc/free) a musíte zvládnout\n      správu paměti v C (použijte valgrind nebo jiný podobný nástroj).\n\n    - Vhodná rozptylovací funkce pro řetězce je podle literatury\n      (http://www.cse.yorku.ca/~oz/hash.html - varianta sdbm):\n\n        size_t htab_hash_function(const char *str) {\n          uint32_t h=0;     // musí mít 32 bitů\n          const unsigned char *p;\n          for(p=(const unsigned char*)str; *p!='\\0'; p++)\n              h = 65599*h + *p;\n          return h;\n        }\n\n      její výsledek modulo arr_size určuje index do tabulky:\n        index = (htab_hash_function(\"mystring\") % arr_size);\n      Zkuste použít i jiné podobné funkce a porovnejte efektivitu.\n\n    - Tabulka je (pro knihovnu privátní) struktura obsahující pole seznamů,\n      jeho velikost a počet položek tabulky v následujícím pořadí:\n\n      +----------+\n      | size     | // aktuální počet záznamů [(key,data),next]\n      +----------+\n      | arr_size | // velikost pole ukazatelů (počet položek)\n      +----------+\n      | arr_ptr  | // ukazatel na dynamicky alokované pole ukazatelů\n      +----------+\n        |\n        V\n      +---+\n      |ptr|--\u003e[(key,data),next]--\u003e[(key,data),next]--\u003e[(key,data),next]--|\n      +---+\n      |ptr|--|\n      +---+\n      |ptr|--\u003e[(key,data),next]--\u003e[(key,data),next]--|\n      +---+\n      |ptr|--|\n      +---+\n\n      (V obrázku platí velikost .arr_size==4 a počet položek .size==5.)\n      Položka .arr_size je velikost dynamicky alokovaného pole ukazatelů.\n      Paměť pro strukturu se dynamicky alokuje a ukazatel na ni se používá\n      pro identifikaci tabulky.  V programu zvolte vhodnou velikost pole\n      a v komentáři zdůvodněte vaše rozhodnutí.\n      Rozhraní knihovny obsahuje jen _neúplnou_deklaraci_ struktury, definice\n      je uživateli knihovny skryta (jde o formu zapouzdření - \"encapsulation\").\n\n    - Napište funkce podle následujícího hlavičkového souboru (API):\n\n==================================================================\n// htab.h -- rozhraní knihovny htab (řešení IJC-DU2)\n// Licence: žádná (Public domain)\n\n// následující řádky zabrání násobnému vložení:\n#ifndef HTAB_H__\n#define HTAB_H__\n\n#include \u003cstring.h\u003e     // size_t\n#include \u003cstdbool.h\u003e    // bool\n\n// Tabulka:\nstruct htab;    // neúplná deklarace struktury - uživatel nevidí obsah\ntypedef struct htab htab_t;     // typedef podle zadání\n\n// Typy:\ntypedef const char * htab_key_t;        // typ klíče\ntypedef int htab_value_t;               // typ hodnoty\n\n// Dvojice dat v tabulce:\ntypedef struct htab_pair {\n    htab_key_t    key;          // klíč\n    htab_value_t  value;        // asociovaná hodnota\n} htab_pair_t;                  // typedef podle zadání\n\n// Rozptylovací (hash) funkce (stejná pro všechny tabulky v programu)\n// Pokud si v programu definujete stejnou funkci, použije se ta vaše.\nsize_t htab_hash_function(htab_key_t str);\n\n// Funkce pro práci s tabulkou:\nhtab_t *htab_init(const size_t n);              // konstruktor tabulky\nsize_t htab_size(const htab_t * t);             // počet záznamů v tabulce\nsize_t htab_bucket_count(const htab_t * t);     // velikost pole\n\nhtab_pair_t * htab_find(const htab_t * t, htab_key_t key);  // hledání\nhtab_pair_t * htab_lookup_add(htab_t * t, htab_key_t key);\n\nbool htab_erase(htab_t * t, htab_key_t key);    // ruší zadaný záznam\n\n// for_each: projde všechny záznamy a zavolá na ně funkci f\n// Pozor: f nesmí měnit klíč .key ani přidávat/rušit položky\nvoid htab_for_each(const htab_t * t, void (*f)(htab_pair_t *data));\n\nvoid htab_clear(htab_t * t);    // ruší všechny záznamy\nvoid htab_free(htab_t * t);     // destruktor tabulky\n\n// výpočet a tisk statistik délky seznamů (min,max,avg) do stderr:\nvoid htab_statistics(const htab_t * t);\n\n#endif // HTAB_H__\n==================================================================\n\n      Hlavičkový soubor můžete celý převzít (je \"Public domain\").\n\n    - Stručný popis základních funkcí:\n\n        t=htab_init(num)          konstruktor: vytvoření a inicializace tabulky\n                                  num = počet prvků pole (.arr_size)\n\n        size_t s=htab_size(t)           vrátí počet prvků tabulky (.size)\n\n        size_t n=htab_bucket_count(t)   vrátí počet prvků pole (.arr_size)\n\n        ptr=htab_find(t,key)         vyhledávání - viz dále\n        ptr=htab_lookup_add(t,key)   vyhledávání+přidání - viz dále\n\n        b=htab_erase(t,key)       zrušení záznamu se zadaným klíčem (úspěch:true)\n\n        htab_for_each(t,funkce)   projde všechny záznamy, na každý zavolá funkci\n                                  (pozor na možné změny tabulky!)\n\n        htab_clear(t)             zrušení všech položek, tabulka zůstane prázdná\n\n        htab_free(t)              destruktor: zrušení tabulky (volá htab_clear())\n\n        htab_statistics(t)        tiskne statistiky délky seznamů do stderr\n                                  (ilustruje kvalitu hash_function)\n                                  (použijte v programu #ifdef STATISTICS)\n\n      kde t       je ukazatel na tabulku (typu htab_t *),\n          b       je typu bool,\n          ptr     je ukazatel na záznam (položku tabulky {klíč,hodnota}),\n\n    - Vhodně zvolte typy parametrů funkcí (včetně použití const).\n\n    - Záznam [(key,value),next] je typu\n          struct htab_item\n      a obsahuje položky:\n          next ... ukazatel na další záznam\n          struct htab_pair ... veřejná struktura s položkami:\n            key ..... ukazatel na dynamicky alokovaný řetězec,\n            value ... asociovaná data = počet výskytů\n      Tento záznam je definován v privátním hlavičkovém souboru pro všechny\n      moduly tabulky a není dostupný při použití knihovny (\"Opaque data type\").\n      Uživatel používá ukazatel na vnořenou strukturu htab_pair_t.\n\n    - Funkce\n        htab_pair_t *htab_find(htab_t *t, htab_key_t key);\n      V tabulce  t  vyhledá záznam odpovídající řetězci  key  a\n        - pokud jej nalezne, vrátí ukazatel na záznam\n        - pokud nenalezne, vrátí NULL\n\n    - Funkce\n        htab_pair_t htab_lookup_add(htab_t *t, htab_key_t key);\n      V tabulce  t  vyhledá záznam odpovídající řetězci  key  a\n        - pokud jej nalezne, vrátí ukazatel na záznam\n        - pokud nenalezne, automaticky přidá záznam a vrátí ukazatel\n      Poznámka1: Dobře promyslete chování této funkce k parametru key.\n      Poznámka2: podobně se chová C++ operator[] pro std::unordered_map\n\n    - Když htab_init nebo htab_lookup_add nemohou alokovat paměť,\n      vrací NULL (a uživatel musí testovat výsledek těchto operací)\n      Poznámka: C++ na to používá výjimky (\"exceptions\").\n\n\n    Napište funkci\n\n        int read_word(char *s, int max, FILE *f);\n\n      která čte jedno slovo ze souboru f do zadaného pole znaků\n      a vrátí délku slova (z delších slov načte prvních max-1 znaků,\n      a zbytek přeskočí). Funkce vrací EOF, pokud je konec souboru.\n      Umístěte ji do zvláštního modulu \"io.c\" (nepatří do knihovny).\n      Poznámka: Slovo je souvislá posloupnost znaků oddělená isspace znaky.\n\n    Omezení: řešení v C bude tisknout jinak uspořádaný výstup\n      a je povoleno použít implementační limit na maximální\n      délku slova (např. 255 znaků), delší slova se ZKRÁTÍ a program\n      při prvním delším slovu vytiskne varování na stderr (max 1 varování).\n\n    Poznámka: Vhodný soubor pro testování je například seznam slov\n              v souboru /usr/share/dict/words\n              nebo texty z http://www.gutenberg.org/\n              případně výsledek příkazu:  \"seq 1000000 2000000|shuf\"\n\n(10b)\n\nPoužijte implicitní lokalizaci (= nevolat setlocale()). Zamyslete se nad tím,\nco by pro váš kód znamenalo použití UTF-8 při zapnuté lokalizaci s tímto\ndnes běžně používaným kódováním.\n\nNapište soubor Makefile tak, aby příkaz make vytvořil programy\n\"tail\", \"wordcount\", \"wordcount-dynamic\" a knihovny \"libhtab.a\",\n\"libhtab.so\" (nebo \"htab.dll\" atd.).\n\nProgram \"wordcount\" musí být staticky sestaven s knihovnou \"libhtab.a\".\n\nProgram \"wordcount-dynamic\" musí být sestaven s knihovnou \"libhtab.so\".\nTento program otestujte se stejnými vstupy jako u staticky sestavené verze.\n\nPorovnejte efektivitu obou (C i C++) implementací (viz např. příkaz time)\na zamyslete se nad výsledky (pozor na vliv vyrovnávacích paměťí, velikosti\nvstupního souboru atd.)\nTaké si zkuste překlad s optimalizací i bez ní (-O2, -O0) a porovnejte\nefektivitu pro vhodný vstup.\n\nPoznámky:\n - pro testy wordcount-dynamic na linuxu budete potřebovat nastavit\n      LD_LIBRARY_PATH=\".\"   (viz \"man ld.so\" a odpovídající přednáška)\n - Čtěte pokyny pro vypracování domácích úkolů (viz dále)\n\n----------------------------------------------------------------\n\nObecné pokyny pro vypracování domácích úkolů (rev 21.3.2023)\n\n*  Pro úkoly v jazyce C používejte ISO C11 (soubory *.c)\n   Pro úkoly v jazyce C++ používejte ISO C++17 (soubory *.cc)\n   Použití nepřenositelných konstrukcí není dovoleno.\n\n*  Úkoly zkontrolujte překladačem například takto:\n      gcc -g -std=c11 -pedantic -Wall -Wextra priklad1.c\n      g++ -std=c++17 -pedantic -Wall priklad.cc\n   Místo gcc můžete použít i jiný překladač.\n   V  souvislosti s tím napište do poznámky na začátku\n   souboru jméno překladače, kterým byl program testován\n   (implicitní je verze GNU C instalovaná na serveru merlin).\n\n   Pro ověření správnosti paměťových operací zkuste extra parametry pro gcc\n   (Makefile: CFLAGS += -fsanitize=address, LDFLAGS += -fsanitize=address).\n\n*  Programy  pište, pokud je to možné, do jednoho zdrojového\n   souboru. Dodržujte předepsaná jména souborů.\n\n*  Na začátek každého souboru napište poznámku, která bude\n   obsahovat jméno, fakultu, označení příkladu a datum.\n\n* Úkoly je nutné zabalit programem zip takto:\n       zip xunkno99.zip *.c *.cc *.h Makefile\n\n  Jméno xunkno99 nahradíte vlastním. ZIP neobsahuje adresáře.\n  Každý si zkontroluje obsah ZIP archivu jeho rozbalením v prázdném adresáři\n  a napsáním \"make run\".\n\n* Řešení se odevzdává elektronicky v ISVUT (velikost souboru je omezena)\n\n* Posílejte pouze nezbytně nutné soubory -- ne *.EXE !\n\n* Úkoly neodevzdané v termínu budou za 0 bodů.\n\n* Opsané úkoly budou hodnoceny 0 bodů pro všechny zůčastněné\n  a to bez výjimky (+bonus v podobě návštěvy u disciplinární komise).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartan03%2Fijc-project2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartan03%2Fijc-project2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartan03%2Fijc-project2/lists"}