sk1
This commit is contained in:
parent
d163fcaae8
commit
db623c28ad
@ -9,5 +9,5 @@ train: main.o a_train.o
|
|||||||
gcc main.o a_train.o -o train
|
gcc main.o a_train.o -o train
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o train
|
rm *.o train.exe
|
||||||
|
|
||||||
|
|||||||
@ -9,5 +9,5 @@ station: main.o a_station.o
|
|||||||
gcc $(CFLAGS) main.o a_station.o -o station
|
gcc $(CFLAGS) main.o a_station.o -o station
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o station
|
rm *.o station.exe
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
struct station* create_station(){
|
struct station* create_station(){
|
||||||
struct station* station = (struct station*)calloc(1,sizeof(struct station));
|
struct station* station = (struct station*)calloc(1,sizeof(struct station));
|
||||||
station->tracks = (struct car**)calloc(STATION_SIZE, sizeof(struct car*));
|
station->tracks = (struct car**)calloc(STATION_SIZE, sizeof(struct car*));
|
||||||
@ -11,7 +10,7 @@ struct station* create_station(){
|
|||||||
return station;
|
return station;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_station(struct station* station){
|
|
||||||
void destroy_station(struct station* station) {
|
void destroy_station(struct station* station) {
|
||||||
if (station == NULL) return;
|
if (station == NULL) return;
|
||||||
for (int i = 0; i < station->track_count; i++) {
|
for (int i = 0; i < station->track_count; i++) {
|
||||||
@ -26,7 +25,7 @@ void destroy_station(struct station* station){
|
|||||||
free(station->tracks);
|
free(station->tracks);
|
||||||
free(station);
|
free(station);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int select_track(struct station* station, const char* target) {
|
int select_track(struct station* station, const char* target) {
|
||||||
unsigned long hash = 5381;
|
unsigned long hash = 5381;
|
||||||
|
|||||||
@ -1,78 +1,13 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#define SIZE 100
|
#include <unistd.h>
|
||||||
|
void printchar(char c) { write(1, &c, 1);
|
||||||
struct tree {
|
|
||||||
char* value;
|
|
||||||
struct tree* left;
|
|
||||||
struct tree* right;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tree* read_tree(int* counter) {
|
|
||||||
char buffer[SIZE];
|
|
||||||
memset(buffer, 0, SIZE);
|
|
||||||
char* r = fgets(buffer, SIZE, stdin);
|
|
||||||
if(r == NULL){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (buffer[0] == '\n') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
struct tree* tree = calloc(1, sizeof(struct tree));
|
|
||||||
tree->value = malloc(strlen(buffer) + 1);
|
|
||||||
strcpy(tree->value, buffer);
|
|
||||||
if (buffer[0] == '*') {
|
|
||||||
(*counter)++;
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
tree->left = read_tree(counter);
|
|
||||||
tree->right = read_tree(counter);
|
|
||||||
return tree;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_tree(struct tree* tree) {
|
|
||||||
if (tree == NULL) return;
|
|
||||||
destroy_tree(tree->left);
|
|
||||||
destroy_tree(tree->right);
|
|
||||||
free(tree->value);
|
|
||||||
free(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_tree(struct tree* tree) {
|
|
||||||
if (tree == NULL) return;
|
|
||||||
printf("%s", tree->value);
|
|
||||||
if (tree->value[0] == '*') {
|
|
||||||
printf("Koniec\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getchar();
|
|
||||||
char r = getchar();
|
|
||||||
if (r == 'a') {
|
|
||||||
print_tree(tree->left);
|
|
||||||
} else if (r == 'n') {
|
|
||||||
print_tree(tree->right);
|
|
||||||
} else if (r == EOF) {
|
|
||||||
printf("Koniec vstupu\n");
|
|
||||||
}else {
|
|
||||||
printf("Nerozumiem\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int counter = 0;
|
// Пишет символ 'c' в стандартный вывод
|
||||||
struct tree* root = read_tree(&counter);
|
printchar('A'); // Bыbodum сuмbол do fork()
|
||||||
if(root != 0){
|
fork(); // Создается новый процесс
|
||||||
printf("Expert z bufetu to vie.\n");
|
printchar('B');
|
||||||
printf("Pozna %d druhov ovocia a zeleniny.\n", counter);
|
return 0;
|
||||||
printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.\n");
|
|
||||||
print_tree(root);
|
|
||||||
} else{
|
|
||||||
printf("Expert z bufetu to vie.\n");
|
|
||||||
printf("Chybna databaza\n");
|
|
||||||
}
|
|
||||||
destroy_tree(root);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
17
sk1/Makefile
Normal file
17
sk1/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -std=c99
|
||||||
|
|
||||||
|
all: compressor
|
||||||
|
|
||||||
|
compressor: main.o compressor.o
|
||||||
|
$(CC) $(CFLAGS) -o compressor main.o compressor.o
|
||||||
|
|
||||||
|
main.o: main.c compressor.h
|
||||||
|
$(CC) $(CFLAGS) -c main.c
|
||||||
|
|
||||||
|
compressor.o: compressor.c compressor.h
|
||||||
|
$(CC) $(CFLAGS) -c compressor.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o compressor
|
||||||
|
|
||||||
34
sk1/README.md
Normal file
34
sk1/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Dokumentácia
|
||||||
|
|
||||||
|
## Zadanie
|
||||||
|
Vytvorte program na kompresiu a dekompresiu súborov pomocou dvoch rôznych algoritmov: RLE (Run Length Encoding) a LZ78. Program musí podporovať nasledujúce operácie:
|
||||||
|
- Kompresia pomocou RLE
|
||||||
|
- Dekompresia pomocou RLE
|
||||||
|
- Kompresia pomocou LZ78
|
||||||
|
- Dekompresia pomocou LZ78
|
||||||
|
|
||||||
|
## Stručný opis funkčnosti
|
||||||
|
Program `compressor` umožňuje kompresiu a dekompresiu súborov pomocou algoritmov RLE a LZ78. Program sa spúšťa z príkazového riadku s nasledujúcimi argumentmi:
|
||||||
|
- `-c infile outfile`: Kompresia pomocou algoritmu RLE
|
||||||
|
- `-d infile outfile`: Dekompresia pomocou algoritmu RLE
|
||||||
|
- `-c2 infile outfile`: Kompresia pomocou algoritmu LZ78
|
||||||
|
- `-d2 infile outfile`: Dekompresia pomocou algoritmu LZ78
|
||||||
|
- `-h`: Zobrazenie pomoci
|
||||||
|
|
||||||
|
## Stručný opis riešenia
|
||||||
|
Program je implementovaný v jazyku C a obsahuje nasledujúce súbory:
|
||||||
|
- `main.c`: Obsahuje hlavný program, ktorý spracováva argumenty príkazového riadku a volá príslušné funkcie na kompresiu a dekompresiu.
|
||||||
|
- `compressor.c`: Obsahuje implementáciu kompresných a dekompresných algoritmov RLE a LZ78.
|
||||||
|
- `compressor.h`: Hlavičkový súbor s deklaráciami funkcií.
|
||||||
|
- `Makefile`: Súbor na kompiláciu programu pomocou nástroja `make`.
|
||||||
|
|
||||||
|
Algoritmus RLE komprimuje súbor tak, že nahradí opakujúce sa znaky dvojicou (znak, počet opakovaní). Algoritmus LZ78 komprimuje súbor tak, že nahradí opakujúce sa sekvencie znakov dvojicou (index, znak), kde index odkazuje na predchádzajúcu sekvenciu v slovníku.
|
||||||
|
|
||||||
|
## Podmienky za ktorých funguje
|
||||||
|
Program bol testovaný na systéme Windows s kompilátorom GCC. Na kompiláciu programu použite príkaz `make` v príkazovom riadku. Program vyžaduje, aby vstupné súbory existovali a boli čitateľné. Výstupné súbory budú vytvorené alebo prepísané.
|
||||||
|
|
||||||
|
## Zoznam použitých zdrojov
|
||||||
|
- Dokumentácia k jazyku C
|
||||||
|
- Wikipedia: [Run Length Encoding](https://en.wikipedia.org/wiki/Run-length_encoding)
|
||||||
|
- Wikipedia: [LZ78](https://en.wikipedia.org/wiki/LZ78)
|
||||||
|
- [Stránka predmetu](https://student.kemt.fei.tuke.sk/usaa/home)
|
||||||
223
sk1/compressor.c
Normal file
223
sk1/compressor.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
#include "compressor.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_DICT_SIZE 4096
|
||||||
|
|
||||||
|
int read_file(const char* filename, unsigned char** data, size_t* size) {
|
||||||
|
FILE* file = fopen(filename, "rb");
|
||||||
|
if (!file) return -1;
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
*size = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
*data = malloc(*size);
|
||||||
|
if (!*data) {
|
||||||
|
fclose(file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(*data, 1, *size, file);
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int write_file(const char* filename, const unsigned char* data, size_t size) {
|
||||||
|
FILE* file = fopen(filename, "wb");
|
||||||
|
if (!file) return -1;
|
||||||
|
|
||||||
|
fwrite(data, 1, size, file);
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//RLE
|
||||||
|
int compress_1(const char* input_file_name, const char* output_file_name) {
|
||||||
|
size_t size;
|
||||||
|
unsigned char* data;
|
||||||
|
if (read_file(input_file_name, &data, &size) != 0) return -1;
|
||||||
|
FILE* output = fopen(output_file_name, "w");
|
||||||
|
if (!output) {
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size;) {
|
||||||
|
unsigned char byte = data[i];
|
||||||
|
size_t count = 1;
|
||||||
|
while (i + count < size && data[i + count] == byte && count < 255) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
fprintf(output, "%c%d", byte, (int)count);
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(output);
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
unsigned char* decompress_1_buffer(const unsigned char* data, size_t size, size_t* out_size) {
|
||||||
|
unsigned char* decompressed = malloc(size * 255);
|
||||||
|
if (!decompressed) return NULL;
|
||||||
|
size_t write_idx = 0;
|
||||||
|
for (size_t i = 0; i < size;) {
|
||||||
|
unsigned char byte = data[i++];
|
||||||
|
size_t count = 0;
|
||||||
|
while (i < size && isdigit(data[i])) {
|
||||||
|
count = count * 10 + (data[i++] - '0');
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < count; j++) {
|
||||||
|
if (write_idx >= size * 255) {
|
||||||
|
size_t new_size = write_idx * 2;
|
||||||
|
unsigned char* new_buffer = realloc(decompressed, new_size);
|
||||||
|
if (!new_buffer) {
|
||||||
|
free(decompressed);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
decompressed = new_buffer;
|
||||||
|
}
|
||||||
|
decompressed[write_idx++] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out_size = write_idx;
|
||||||
|
return decompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decompress_1(const char* input_file_name, const char* output_file_name) {
|
||||||
|
size_t size;
|
||||||
|
unsigned char* data;
|
||||||
|
if (read_file(input_file_name, &data, &size) != 0) return -1;
|
||||||
|
|
||||||
|
size_t out_size;
|
||||||
|
unsigned char* decompressed = decompress_1_buffer(data, size, &out_size);
|
||||||
|
if (!decompressed) {
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = write_file(output_file_name, decompressed, out_size);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
free(decompressed);
|
||||||
|
return result == 0 ? (int)out_size : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LZ78
|
||||||
|
int compress_2(const char* input_file_name, const char* output_file_name) {
|
||||||
|
unsigned char* data;
|
||||||
|
size_t size;
|
||||||
|
if (read_file(input_file_name, &data, &size) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FILE* output = fopen(output_file_name, "w");
|
||||||
|
if (!output) {
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char* dictionary[MAX_DICT_SIZE] = { NULL };
|
||||||
|
size_t dict_size = 0;
|
||||||
|
size_t current_index = 0;
|
||||||
|
while (current_index < size) {
|
||||||
|
size_t match_index = 0;
|
||||||
|
size_t match_length = 0;
|
||||||
|
for (size_t i = 0; i < dict_size; i++) {
|
||||||
|
size_t len = 0;
|
||||||
|
while (data[current_index + len] != '\0' &&
|
||||||
|
dictionary[i][len] != '\0' &&
|
||||||
|
data[current_index + len] == dictionary[i][len]) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if (len > match_length) {
|
||||||
|
match_length = len;
|
||||||
|
match_index = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current_index + match_length < size) {
|
||||||
|
fprintf(output, "%zu%c", match_index, data[current_index + match_length]);
|
||||||
|
}
|
||||||
|
if (dict_size < MAX_DICT_SIZE) {
|
||||||
|
dictionary[dict_size] = malloc(match_length + 2);
|
||||||
|
if (!dictionary[dict_size]) {
|
||||||
|
fclose(output);
|
||||||
|
free(data);
|
||||||
|
for (size_t i = 0; i < dict_size; i++) {
|
||||||
|
free(dictionary[i]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (match_length > 0) {
|
||||||
|
memcpy(dictionary[dict_size], &data[current_index], match_length);
|
||||||
|
}
|
||||||
|
dictionary[dict_size][match_length] = data[current_index + match_length];
|
||||||
|
dictionary[dict_size][match_length + 1] = '\0';
|
||||||
|
dict_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_index += match_length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(output);
|
||||||
|
free(data);
|
||||||
|
for (size_t i = 0; i < dict_size; i++) {
|
||||||
|
free(dictionary[i]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int decompress_2(const char* input_file_name, const char* output_file_name) {
|
||||||
|
unsigned char* data;
|
||||||
|
size_t size;
|
||||||
|
if (read_file(input_file_name, &data, &size) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FILE* output = fopen(output_file_name, "w");
|
||||||
|
if (!output) {
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char* dictionary[MAX_DICT_SIZE] = { NULL };
|
||||||
|
size_t dict_size = 0;
|
||||||
|
size_t current_index = 0;
|
||||||
|
while (current_index < size) {
|
||||||
|
unsigned short index = 0;
|
||||||
|
unsigned char ch = '\0';
|
||||||
|
while (current_index < size && isdigit(data[current_index])) {
|
||||||
|
index = index * 10 + (data[current_index] - '0');
|
||||||
|
current_index++;
|
||||||
|
}
|
||||||
|
if (current_index < size) {
|
||||||
|
ch = data[current_index++];
|
||||||
|
}
|
||||||
|
if (index == 0) {
|
||||||
|
fputc(ch, output);
|
||||||
|
} else {
|
||||||
|
fwrite(dictionary[index - 1], 1, strlen((char*)dictionary[index - 1]), output);
|
||||||
|
fputc(ch, output);
|
||||||
|
}
|
||||||
|
if (dict_size < MAX_DICT_SIZE) {
|
||||||
|
size_t length = (index > 0) ? strlen((char*)dictionary[index - 1]) : 0;
|
||||||
|
dictionary[dict_size] = malloc(length + 2);
|
||||||
|
if (!dictionary[dict_size]) {
|
||||||
|
fclose(output);
|
||||||
|
free(data);
|
||||||
|
for (size_t i = 0; i < dict_size; i++) {
|
||||||
|
free(dictionary[i]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (index > 0) {
|
||||||
|
memcpy(dictionary[dict_size], dictionary[index - 1], length);
|
||||||
|
}
|
||||||
|
dictionary[dict_size][length] = ch;
|
||||||
|
dictionary[dict_size][length + 1] = '\0';
|
||||||
|
dict_size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(output);
|
||||||
|
free(data);
|
||||||
|
for (size_t i = 0; i < dict_size; i++) {
|
||||||
|
free(dictionary[i]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
sk1/compressor.h
Normal file
9
sk1/compressor.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef COMPRESSOR_H
|
||||||
|
#define COMPRESSOR_H
|
||||||
|
|
||||||
|
int compress_1(const char* input_file_name, const char* output_file_name);
|
||||||
|
int decompress_1(const char* input_file_name, const char* output_file_name);
|
||||||
|
int compress_2(const char* input_file_name, const char* output_file_name);
|
||||||
|
int decompress_2(const char* input_file_name, const char* output_file_name);
|
||||||
|
|
||||||
|
#endif
|
||||||
66
sk1/main.c
Normal file
66
sk1/main.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "compressor.h"
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
printf("Použitie:\n");
|
||||||
|
printf(" ./compressor -c infile outfile # Kompresia pomocou algoritmu RLE\n");
|
||||||
|
printf(" ./compressor -d infile outfile # Dekompresia pomocou algoritmu RLE\n");
|
||||||
|
printf(" ./compressor -c2 infile outfile # Kompresia pomocou algoritmu LZ78\n");
|
||||||
|
printf(" ./compressor -d2 infile outfile # Dekompresia pomocou algoritmu LZ78\n");
|
||||||
|
printf(" ./compressor -h # Zobrazit pomoc\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Chyba: Chybaju argumenty. Pouzite -h pre zobrazenie pomoci.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "-h") == 0) {
|
||||||
|
print_help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "-d") == 0 ||
|
||||||
|
strcmp(argv[1], "-c2") == 0 || strcmp(argv[1], "-d2") == 0) && argc != 4) {
|
||||||
|
fprintf(stderr, "Chyba: Nespravny pocet argumentov. Pouzite -h pre zobrazenie pomoci.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* input_file = argv[2];
|
||||||
|
const char* output_file = argv[3];
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "-c") == 0) {
|
||||||
|
result = compress_1(input_file, output_file);
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr, "Chyba: Kompresia zlyhala.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "-d") == 0) {
|
||||||
|
result = decompress_1(input_file, output_file);
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr, "Chyba: Dekompresia zlyhala.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "-c2") == 0) {
|
||||||
|
result = compress_2(input_file, output_file);
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr, "Chyba: Kompresia zlyhala.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "-d2") == 0) {
|
||||||
|
result = decompress_2(input_file, output_file);
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr, "Chyba: Dekompresia zlyhala.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Chyba: Neznamy argument. Použite -h pre zobrazenie pomoci.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user