diff --git a/sk1/compressor.c b/sk1/compressor.c index 66851a2..11ce3a9 100644 --- a/sk1/compressor.c +++ b/sk1/compressor.c @@ -1,66 +1,71 @@ -#include "compressor.h" -#include -#include -#include +#include "compressor.h" // Hlavičkový súbor, ktorý obsahuje deklarácie funkcií a štruktúr používaných na kompresiu a dekompresiu. +#include // Knižnica pre prácu so vstupom a výstupom. +#include // Knižnica pre alokáciu pamäte a ďalšie základné funkcie. +#include // Knižnica pre prácu s reťazcami. +// Funkcia na čítanie obsahu súboru do pamäte. unsigned char* read_file(const char* file_name, size_t* size) { - FILE* file = fopen(file_name, "rb"); + FILE* file = fopen(file_name, "rb"); // Otvorenie súboru v režime čítania binárnych dát. if (!file) { - perror("Error opening file"); + perror("Error opening file"); // Chybové hlásenie, ak sa súbor nedá otvoriť. return NULL; } - fseek(file, 0, SEEK_END); - *size = ftell(file); - rewind(file); + fseek(file, 0, SEEK_END); // Posun ukazovateľa na koniec súboru. + *size = ftell(file); // Zistenie veľkosti súboru. + rewind(file); // Návrat ukazovateľa na začiatok súboru. - unsigned char* buffer = (unsigned char*)malloc(*size); + unsigned char* buffer = (unsigned char*)malloc(*size); // Alokácia pamäte pre obsah súboru. if (!buffer) { - perror("Memory allocation error"); + perror("Memory allocation error"); // Chybové hlásenie, ak sa nepodarí alokovať pamäť. fclose(file); return NULL; } - fread(buffer, 1, *size, file); + fread(buffer, 1, *size, file); // Načítanie obsahu súboru do bufferu. fclose(file); - return buffer; + return buffer; // Návrat ukazovateľa na buffer. } +// Funkcia na zápis obsahu z pamäte do súboru. int write_file(const char* file_name, const unsigned char* buffer, size_t size) { - FILE* file = fopen(file_name, "wb"); + FILE* file = fopen(file_name, "wb"); // Otvorenie súboru v režime zápisu binárnych dát. if (!file) { perror("Error opening file"); return -1; } - fwrite(buffer, 1, size, file); + fwrite(buffer, 1, size, file); // Zápis dát do súboru. fclose(file); return 0; } +// Funkcia na vytvorenie Huffmanovho stromu z daných dát. HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size) { - size_t frequencies[256] = {0}; + size_t frequencies[256] = {0}; // Pole na počítanie frekvencie každého znaku. for (size_t i = 0; i < size; i++) { - frequencies[data[i]]++; + frequencies[data[i]]++; // Zvýšenie frekvencie pre daný znak. } - HuffmanNode* nodes[256]; + HuffmanNode* nodes[256]; // Pole uzlov Huffmanovho stromu. int node_count = 0; + // Vytvorenie listových uzlov pre znaky s nenulovou frekvenciou. for (int i = 0; i < 256; i++) { if (frequencies[i] > 0) { HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); - node->symbol = (unsigned char)i; - node->frequency = frequencies[i]; + node->symbol = (unsigned char)i; // Znak reprezentovaný uzlom. + node->frequency = frequencies[i]; // Frekvencia znaku. node->left = NULL; node->right = NULL; - nodes[node_count++] = node; + nodes[node_count++] = node; // Pridanie uzla do zoznamu. } } + // Opakované zlúčenie dvoch uzlov s najnižšou frekvenciou. while (node_count > 1) { - + // Vyhľadanie dvoch uzlov s najnižšou frekvenciou. int min1 = 0, min2 = 1; if (nodes[min2]->frequency < nodes[min1]->frequency) { min1 = 1; @@ -76,104 +81,111 @@ HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size) { } } + // Vytvorenie nového rodičovského uzla. HuffmanNode* new_node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); - new_node->symbol = 0; + new_node->symbol = 0; // Symbol je irelevantný pre vnútorné uzly. new_node->frequency = nodes[min1]->frequency + nodes[min2]->frequency; new_node->left = nodes[min1]; new_node->right = nodes[min2]; + // Aktualizácia zoznamu uzlov. nodes[min1] = new_node; nodes[min2] = nodes[node_count - 1]; node_count--; } - return nodes[0]; + return nodes[0]; // Návrat koreňa Huffmanovho stromu. } + +// Rekurzívna funkcia na generovanie Huffmanových kódov pre každý znak. void generate_huffman_codes(HuffmanNode* root, char** codes, char* buffer, int depth) { - if (!root->left && !root->right) { - buffer[depth] = '\0'; - codes[root->symbol] = strdup(buffer); + if (!root->left && !root->right) { // Ak uzol nemá potomkov, je to listový uzol. + buffer[depth] = '\0'; // Ukončenie reťazca. + codes[root->symbol] = strdup(buffer); // Uloženie kódu pre znak. return; } if (root->left) { - buffer[depth] = '0'; + buffer[depth] = '0'; // Pridanie '0' pre cestu doľava. generate_huffman_codes(root->left, codes, buffer, depth + 1); } if (root->right) { - buffer[depth] = '1'; + buffer[depth] = '1'; // Pridanie '1' pre cestu doprava. generate_huffman_codes(root->right, codes, buffer, depth + 1); } } +// Funkcia na uvoľnenie pamäte alokovanej pre Huffmanov strom. void free_huffman_tree(HuffmanNode* root) { - if (!root) return; - free_huffman_tree(root->left); - free_huffman_tree(root->right); - free(root); + if (!root) return; // Ak je strom prázdny, nič nerobí. + free_huffman_tree(root->left); // Rekurzívne uvoľnenie ľavého podstromu. + free_huffman_tree(root->right); // Rekurzívne uvoľnenie pravého podstromu. + free(root); // Uvoľnenie aktuálneho uzla. } +// Funkcia na zápis bitov do súboru pomocou dočasného bufferu. void write_bits(FILE* file, const char* bits, unsigned char* buffer, int* bit_pos) { - for (int i = 0; bits[i] != '\0'; i++) { - if (bits[i] == '1') { + for (int i = 0; bits[i] != '\0'; i++) { // Prechádza všetky bity v reťazci. + if (bits[i] == '1') { // Ak je bit '1', nastaví príslušný bit v bufferi. buffer[*bit_pos / 8] |= (1 << (7 - (*bit_pos % 8))); } - (*bit_pos)++; - if (*bit_pos % 8 == 0) { + (*bit_pos)++; // Posunie sa na ďalšiu bitovú pozíciu. + + if (*bit_pos % 8 == 0) { // Ak je buffer plný (8 bitov), zapíše sa do súboru. fwrite(buffer, 1, 1, file); - buffer[*bit_pos / 8 - 1] = 0; + buffer[*bit_pos / 8 - 1] = 0; // Vyprázdni buffer. } } } +// Funkcia na čítanie jedného bitu zo súboru. int read_bit(FILE* file, unsigned char* buffer, int* bit_pos) { - if (*bit_pos % 8 == 0) { - if (fread(buffer, 1, 1, file) != 1) return -1; + if (*bit_pos % 8 == 0) { // Ak sa číta nový bajt, načíta ho do bufferu. + if (fread(buffer, 1, 1, file) != 1) return -1; // Ak sa nedá čítať, vráti chybu. } - int bit = (*buffer >> (7 - (*bit_pos % 8))) & 1; - (*bit_pos)++; + int bit = (*buffer >> (7 - (*bit_pos % 8))) & 1; // Získa hodnotu aktuálneho bitu. + (*bit_pos)++; // Posunie sa na ďalšiu bitovú pozíciu. return bit; } +// Funkcia na deserializáciu Huffmanovho stromu zo súboru. HuffmanNode* deserialize_tree(FILE* file) { - int marker = fgetc(file); - if (marker == EOF) return NULL; - - if (marker == '1') { + int marker = fgetc(file); // Prečíta znak z binárneho súboru. + if (marker == EOF) return NULL; // Ak je súbor na konci, vráti NULL. + if (marker == '1') { // Ak je marker '1', ide o listový uzol. HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); - node->symbol = fgetc(file); + node->symbol = fgetc(file); // Prečíta znak listového uzla. node->left = node->right = NULL; return node; } - + // Ak je marker '0', ide o vnútorný uzol. Rekurzívne načíta podstromy. HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); node->left = deserialize_tree(file); node->right = deserialize_tree(file); return node; } - +// Funkcia na kompresiu súboru pomocou Huffmanovho kódovania. int compress_1(const char* input_file_name, const char* output_file_name) { size_t size; - unsigned char* data = read_file(input_file_name, &size); + unsigned char* data = read_file(input_file_name, &size); // Načítanie vstupného súboru. if (!data) return -1; - HuffmanNode* root = build_huffman_tree(data, size); + HuffmanNode* root = build_huffman_tree(data, size); // Vytvorenie Huffmanovho stromu. if (!root) { free(data); return -1; } - char* codes[256] = {0}; + char* codes[256] = {0}; // Pole na uloženie kódov pre každý znak. char buffer[256]; - generate_huffman_codes(root, codes, buffer, 0); + generate_huffman_codes(root, codes, buffer, 0); // Generovanie Huffmanových kódov. - - FILE* output_file = fopen(output_file_name, "wb"); + FILE* output_file = fopen(output_file_name, "wb"); // Otvorenie výstupného súboru. if (!output_file) { perror("Error opening output file"); free(data); @@ -181,152 +193,151 @@ int compress_1(const char* input_file_name, const char* output_file_name) { return -1; } - - unsigned char bit_buffer[1] = {0}; + unsigned char bit_buffer[1] = {0}; // Dočasný buffer na bity. int bit_pos = 0; - for (size_t i = 0; i < size; i++) { - write_bits(output_file, codes[data[i]], bit_buffer, &bit_pos); + for (size_t i = 0; i < size; i++) { // Pre každý znak vo vstupnom súbore. + write_bits(output_file, codes[data[i]], bit_buffer, &bit_pos); // Zapíše kód do súboru. } - if (bit_pos % 8 != 0) { + if (bit_pos % 8 != 0) { // Ak buffer nie je prázdny, zapíše sa jeho zvyšok. fwrite(bit_buffer, 1, 1, output_file); } - fclose(output_file); + fclose(output_file); // Uzavretie výstupného súboru. printf("Compressing using Huffman coding...\n"); - for (int i = 0; i < 256; i++) { - if (codes[i]) free(codes[i]); + if (codes[i]) free(codes[i]); // Uvoľnenie pamäte pre kódy. } - free_huffman_tree(root); - free(data); + free_huffman_tree(root); // Uvoľnenie pamäte pre Huffmanov strom. + free(data); // Uvoľnenie dátového bufferu. return 0; } + +// Funkcia na dekompresiu súboru komprimovaného Huffmanovým kódovaním. int decompress_1(const char* input_file_name, const char* output_file_name) { - FILE* input_file = fopen(input_file_name, "rb"); + FILE* input_file = fopen(input_file_name, "rb"); // Otvorenie vstupného súboru v binárnom režime. if (!input_file) { - perror("Error opening input file"); + perror("Error opening input file"); // Chybové hlásenie, ak sa súbor nedá otvoriť. return -1; } - FILE* output_file = fopen(output_file_name, "wb"); + FILE* output_file = fopen(output_file_name, "wb"); // Otvorenie výstupného súboru v binárnom režime. if (!output_file) { perror("Error opening output file"); fclose(input_file); return -1; } - - HuffmanNode* root = deserialize_tree(input_file); + HuffmanNode* root = deserialize_tree(input_file); // Načítanie Huffmanovho stromu zo súboru. if (!root) { fclose(input_file); fclose(output_file); return -1; } - - unsigned char bit_buffer[1]; + unsigned char bit_buffer[1]; // Buffer na čítanie bitov. int bit_pos = 0; - HuffmanNode* current = root; + HuffmanNode* current = root; // Počiatočný uzol stromu. while (1) { - int bit = read_bit(input_file, bit_buffer, &bit_pos); - if (bit == -1) break; + int bit = read_bit(input_file, bit_buffer, &bit_pos); // Čítanie bitu zo súboru. + if (bit == -1) break; // Ak je koniec súboru, ukončí sa čítanie. - current = (bit == 0) ? current->left : current->right; + current = (bit == 0) ? current->left : current->right; // Posun v strome na základe bitu. - if (!current->left && !current->right) { - fputc(current->symbol, output_file); - current = root; + if (!current->left && !current->right) { // Ak je uzol listový, znamená to dekódovaný znak. + fputc(current->symbol, output_file); // Zapíše sa znak do výstupného súboru. + current = root; // Návrat na koreň stromu pre ďalší znak. } } - fclose(input_file); - fclose(output_file); - free_huffman_tree(root); + fclose(input_file); // Uzavretie vstupného súboru. + fclose(output_file); // Uzavretie výstupného súboru. + free_huffman_tree(root); // Uvoľnenie pamäte Huffmanovho stromu. printf("Decompressing using Huffman coding...\n"); return 0; } - - +// Funkcia na kompresiu súboru pomocou LZ77 algoritmu. int compress_2(const char* input_file_name, const char* output_file_name) { size_t size; - unsigned char* data = read_file(input_file_name, &size); + unsigned char* data = read_file(input_file_name, &size); // Načítanie obsahu vstupného súboru. if (!data) return -1; - FILE* output_file = fopen(output_file_name, "wb"); + FILE* output_file = fopen(output_file_name, "wb"); // Otvorenie výstupného súboru v binárnom režime. if (!output_file) { perror("Error opening output file"); free(data); return -1; } - size_t search_buffer_size = 1024; - size_t lookahead_buffer_size = 16; + size_t search_buffer_size = 1024; // Veľkosť vyhľadávacieho okna. + size_t lookahead_buffer_size = 16; // Veľkosť prehliadacieho okna. size_t pos = 0; while (pos < size) { - size_t best_match_offset = 0; - size_t best_match_length = 0; + size_t best_match_offset = 0; // Najlepší posun pre aktuálny segment. + size_t best_match_length = 0; // Dĺžka najlepšieho zhody. + // Vyhľadávanie najdlhšej zhody v rámci vyhľadávacieho okna. for (size_t i = (pos > search_buffer_size ? pos - search_buffer_size : 0); i < pos; i++) { size_t match_length = 0; while (match_length < lookahead_buffer_size && pos + match_length < size && data[i + match_length] == data[pos + match_length]) { - match_length++; + match_length++; // Počítanie dĺžky zhody. } - if (match_length > best_match_length) { + if (match_length > best_match_length) { // Aktualizácia najlepšieho zhody. best_match_length = match_length; best_match_offset = pos - i; } } - unsigned char offset_high = (best_match_offset >> 8) & 0xFF; - unsigned char offset_low = best_match_offset & 0xFF; - unsigned char length = best_match_length; - unsigned char next_symbol = (pos + best_match_length < size) ? data[pos + best_match_length] : 0; + // Zápis zhody a nasledujúceho symbolu do súboru. + unsigned char offset_high = (best_match_offset >> 8) & 0xFF; // Vyšších 8 bitov posunu. + unsigned char offset_low = best_match_offset & 0xFF; // Nižších 8 bitov posunu. + unsigned char length = best_match_length; // Dĺžka zhody. + unsigned char next_symbol = (pos + best_match_length < size) ? data[pos + best_match_length] : 0; // Nasledujúci symbol. fputc(offset_high, output_file); fputc(offset_low, output_file); fputc(length, output_file); fputc(next_symbol, output_file); - pos += best_match_length + 1; + pos += best_match_length + 1; // Posun v prehliadacom okne. } - fclose(output_file); - free(data); + fclose(output_file); // Uzavretie výstupného súboru. + free(data); // Uvoľnenie načítaných dát. printf("Compression using LZ77 completed successfully.\n"); return 0; } - +// Funkcia na dekompresiu súboru komprimovaného LZ77 algoritmom. int decompress_2(const char* input_file_name, const char* output_file_name) { - FILE* input_file = fopen(input_file_name, "rb"); + FILE* input_file = fopen(input_file_name, "rb"); // Otvorenie vstupného súboru v binárnom režime. if (!input_file) { perror("Error opening input file"); return -1; } - FILE* output_file = fopen(output_file_name, "wb"); + FILE* output_file = fopen(output_file_name, "wb"); // Otvorenie výstupného súboru v binárnom režime. if (!output_file) { perror("Error opening output file"); fclose(input_file); return -1; } - unsigned char* output_buffer = (unsigned char*)malloc(10 * 1024 * 1024); // Pre alokáciu 10 MB + unsigned char* output_buffer = (unsigned char*)malloc(10 * 1024 * 1024); // Alokácia bufferu na dekomprimované dáta (max. 10 MB). if (!output_buffer) { perror("Memory allocation error"); fclose(input_file); @@ -336,31 +347,32 @@ int decompress_2(const char* input_file_name, const char* output_file_name) { size_t pos = 0; while (1) { + // Čítanie posunu, dĺžky a nasledujúceho symbolu zo vstupného súboru. int offset_high = fgetc(input_file); int offset_low = fgetc(input_file); int length = fgetc(input_file); int next_symbol = fgetc(input_file); - if (offset_high == EOF || offset_low == EOF || length == EOF || next_symbol == EOF) break; - - size_t offset = (offset_high << 8) | offset_low; + if (offset_high == EOF || offset_low == EOF || length == EOF || next_symbol == EOF) break; // Koniec súboru. + size_t offset = (offset_high << 8) | offset_low; // Zloženie posunu z vyšších a nižších bitov. + // Obnovenie zhody z výstupného bufferu. for (size_t i = 0; i < length; i++) { output_buffer[pos] = output_buffer[pos - offset]; pos++; } - + // Zapísanie nasledujúceho symbolu do bufferu. output_buffer[pos++] = next_symbol; } - fwrite(output_buffer, 1, pos, output_file); + fwrite(output_buffer, 1, pos, output_file); // Zápis dekomprimovaných dát do súboru. - free(output_buffer); - fclose(input_file); - fclose(output_file); + free(output_buffer); // Uvoľnenie alokovaného bufferu. + fclose(input_file); // Uzavretie vstupného súboru. + fclose(output_file); // Uzavretie výstupného súboru. printf("Decompression using LZ77 completed successfully.\n"); return 0; -} +} \ No newline at end of file diff --git a/sk2/Makefile b/sk2/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/sk2/README.md b/sk2/README.md new file mode 100644 index 0000000..e69de29 diff --git a/sk2/calculator.c b/sk2/calculator.c new file mode 100644 index 0000000..e69de29 diff --git a/sk2/calculator.h b/sk2/calculator.h new file mode 100644 index 0000000..e69de29 diff --git a/sk2/main.c b/sk2/main.c new file mode 100644 index 0000000..e69de29