skuska
This commit is contained in:
parent
1def797a53
commit
a33cf7a158
0
sk1/Makefile
Normal file
0
sk1/Makefile
Normal file
0
sk1/README.md
Normal file
0
sk1/README.md
Normal file
178
sk1/compressor.c
Normal file
178
sk1/compressor.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include "compressor.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
unsigned char* read_file(const char* file_name, size_t* size) {
|
||||||
|
FILE* file = fopen(file_name, "rb");
|
||||||
|
if (!file) {
|
||||||
|
perror("Error opening file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
*size = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
unsigned char* buffer = (unsigned char*)malloc(*size);
|
||||||
|
if (!buffer) {
|
||||||
|
perror("Memory allocation error");
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(buffer, 1, *size, file);
|
||||||
|
fclose(file);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_file(const char* file_name, const unsigned char* buffer, size_t size) {
|
||||||
|
FILE* file = fopen(file_name, "wb");
|
||||||
|
if (!file) {
|
||||||
|
perror("Error opening file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(buffer, 1, size, file);
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size) {
|
||||||
|
size_t frequencies[256] = {0};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
frequencies[data[i]]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
HuffmanNode* nodes[256];
|
||||||
|
int node_count = 0;
|
||||||
|
|
||||||
|
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->left = NULL;
|
||||||
|
node->right = NULL;
|
||||||
|
nodes[node_count++] = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node_count > 1) {
|
||||||
|
|
||||||
|
int min1 = 0, min2 = 1;
|
||||||
|
if (nodes[min2]->frequency < nodes[min1]->frequency) {
|
||||||
|
min1 = 1;
|
||||||
|
min2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 2; i < node_count; i++) {
|
||||||
|
if (nodes[i]->frequency < nodes[min1]->frequency) {
|
||||||
|
min2 = min1;
|
||||||
|
min1 = i;
|
||||||
|
} else if (nodes[i]->frequency < nodes[min2]->frequency) {
|
||||||
|
min2 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HuffmanNode* new_node = (HuffmanNode*)malloc(sizeof(HuffmanNode));
|
||||||
|
new_node->symbol = 0;
|
||||||
|
new_node->frequency = nodes[min1]->frequency + nodes[min2]->frequency;
|
||||||
|
new_node->left = nodes[min1];
|
||||||
|
new_node->right = nodes[min2];
|
||||||
|
|
||||||
|
nodes[min1] = new_node;
|
||||||
|
nodes[min2] = nodes[node_count - 1];
|
||||||
|
node_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root->left) {
|
||||||
|
buffer[depth] = '0';
|
||||||
|
generate_huffman_codes(root->left, codes, buffer, depth + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root->right) {
|
||||||
|
buffer[depth] = '1';
|
||||||
|
generate_huffman_codes(root->right, codes, buffer, depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_huffman_tree(HuffmanNode* root) {
|
||||||
|
if (!root) return;
|
||||||
|
free_huffman_tree(root->left);
|
||||||
|
free_huffman_tree(root->right);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!data) return -1;
|
||||||
|
|
||||||
|
HuffmanNode* root = build_huffman_tree(data, size);
|
||||||
|
if (!root) {
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* codes[256] = {0};
|
||||||
|
char buffer[256];
|
||||||
|
generate_huffman_codes(root, codes, buffer, 0);
|
||||||
|
|
||||||
|
printf("Compressing using Huffman coding...\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
if (codes[i]) free(codes[i]);
|
||||||
|
}
|
||||||
|
free_huffman_tree(root);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decompress_1(const char* input_file_name, const char* output_file_name) {
|
||||||
|
size_t size;
|
||||||
|
unsigned char* data = read_file(input_file_name, &size);
|
||||||
|
if (!data) return -1;
|
||||||
|
|
||||||
|
printf("Decompressing using Huffman coding...\n");
|
||||||
|
|
||||||
|
int result = write_file(output_file_name, data, size);
|
||||||
|
free(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!data) return -1;
|
||||||
|
|
||||||
|
printf("Compressing using Algorithm 2 (LZ77)...\n");
|
||||||
|
|
||||||
|
int result = write_file(output_file_name, data, size);
|
||||||
|
free(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decompress_2(const char* input_file_name, const char* output_file_name) {
|
||||||
|
size_t size;
|
||||||
|
unsigned char* data = read_file(input_file_name, &size);
|
||||||
|
if (!data) return -1;
|
||||||
|
|
||||||
|
printf("Decompressing using Algorithm 2 (LZ77)...\n");
|
||||||
|
|
||||||
|
int result = write_file(output_file_name, data, size);
|
||||||
|
free(data);
|
||||||
|
return result;
|
||||||
|
}
|
36
sk1/compressor.h
Normal file
36
sk1/compressor.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
unsigned char* read_file(const char* file_name, size_t* size);
|
||||||
|
|
||||||
|
int write_file(const char* file_name, const unsigned char* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct HuffmanNode {
|
||||||
|
unsigned char symbol;
|
||||||
|
size_t frequency;
|
||||||
|
struct HuffmanNode* left;
|
||||||
|
struct HuffmanNode* right;
|
||||||
|
} HuffmanNode;
|
||||||
|
|
||||||
|
HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size);
|
||||||
|
|
||||||
|
void generate_huffman_codes(HuffmanNode* root, char** codes, char* buffer, int depth);
|
||||||
|
|
||||||
|
void free_huffman_tree(HuffmanNode* root);
|
||||||
|
|
||||||
|
#endif
|
50
sk1/main.c
Normal file
50
sk1/main.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "compressor.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf(" ./compressor -c infile outfile Compress using default algorithm (Huffman)\n");
|
||||||
|
printf(" ./compressor -d infile outfile Decompress using default algorithm (Huffman)\n");
|
||||||
|
printf(" ./compressor -h Print help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc < 2) {
|
||||||
|
print_help();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "-h") == 0) {
|
||||||
|
print_help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
fprintf(stderr, "Error: Invalid number of arguments.\n");
|
||||||
|
print_help();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* input_file = argv[2];
|
||||||
|
const char* output_file = argv[3];
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "-c") == 0) {
|
||||||
|
result = compress_1(input_file, output_file);
|
||||||
|
} else if (strcmp(argv[1], "-d") == 0) {
|
||||||
|
result = decompress_1(input_file, output_file);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error: Unknown option '%s'.\n", argv[1]);
|
||||||
|
print_help();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr, "Error: Operation failed.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Operation completed successfully.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user