如何在 C 中从霍夫曼压缩中解压缩

How to decompress from Huffman's compression in C

提问人:Virgil G. 提问时间:2/12/2023 最后编辑:Virgil G. 更新时间:2/12/2023 访问量:82

问:

我正在开发一个程序来解压缩作为参数传递的文件,并且之前通过霍夫曼算法进行压缩,但我的解压缩功能不起作用,你能帮我吗?

以下是加密格式:

110;;1100;o1101000; 1101001;f1101010;r1101011;
1101100;�1101101;�1101110;{1101111;�1110000;�1110001;�1110010;�1110011;@1110100;61110101;m11101100;h11101101;l11101110;e11101111;01111;
���;o�;�����E}�j�U����͛wo�Ǘ>�@6

我有一个函数来读取文件,另一个函数用于解析霍夫曼代码(在文件顶部)

我的减压功能:

unsigned char *read_bits_from_compressed(unsigned char *str, list_t *code) {
    int str_len = strlen(str);
    unsigned char padding = str[str_len - 1];
    int padding_bits = padding >> 4;
    int bits_read = 0;
    int curr_byte = 0;
    int curr_bit = 7;
    int bit = 0;
    int i = 0;
    int j = 0;
    node_t *node = code->head;
    cipher_t *cipher = NULL;
    unsigned char *result = malloc(str_len);
    memset(result, 0, str_len);
    for (i = str_len - 2; i >= 0; i--) {
        curr_byte = str[i];
        for (j = 7; j >= 0; j--) {
            bit = (curr_byte >> j) & 1;
            while (node != NULL && bits_read < padding_bits) {
                node = node->next;
                bits_read++;
            }
            while (node != NULL) {
                cipher = (cipher_t *) node->data;
                if (cipher->code[curr_bit] == bit) {
                    curr_bit--;
                    if (cipher->code[curr_bit + 1] == -1) {
                        result[str_len - padding - 1 - i] = cipher->c;
                        node = code->head;
                        curr_bit = 7;
                        break;
                    }
                } else {
                    node = node->next;
                    curr_bit = 7;
                }
            }
        }
    }
    return result;
}

该函数必须执行以下操作:

  1. 反转并从末尾读取字符串。
  2. 字符串的第一个字符是我们取回的填充
  3. 一点一点地开始阅读,忽略填充。
  4. 将整个位表示形式插入到数组中
  5. 读取数组并检索相应的字符
  6. 将相应的字符写入输出文件
  7. 重复直到压缩字符结束(检测并跳过霍夫曼的代码)

以下是链式列表的结构:

列表:

typedef struct list {
    node_t *head;
    node_t *tail;
    size_t size;
} list_t;

节点:

typedef struct node {
    struct node *prev;
    struct node *next;
    void *data;
} node_t;

节点中包含的数据:

typedef struct cipher {
    unsigned char c;
    int *code;
} cipher_t;

c对应于 char 和 Huffman 码(由 1 和 0 组成,以 -1 结尾)。code

我的函数当前返回一个空字符串。

C 压缩 霍夫曼代码

评论


答:

0赞 chqrlie 2/12/2023 #1

不能使用 计算压缩数组的长度。 指向可能包含有意义的嵌入 null 字节的二进制数据。您应该将长度作为额外参数传递给 。int str_len = strlen(str);strread_bits_from_compressed

事实上,编译器应该抱怨你传递给 which 需要 a (或 .不要忽略编译器警告。unsigned char *strlen()char *const char *

此外,还可以使用 .不能保证解压缩字符串的长度与压缩缓冲区的长度相同。它可能或多或少,具体取决于霍夫曼树和未压缩的值。另请注意,如果您打算生成 C 字符串,则必须为 null 终止符分配 ne 个额外的字节。unsigned char *result = malloc(str_len);

评论

0赞 فِرجِيل 2/12/2023
我忘了提到,在我的压缩算法实现中,没有代码可以值“0”。
2赞 chqrlie 2/12/2023
@VirgilG。即使没有代码可以具有所有位为零,位流中也可能存在与字节边界重合的八个连续零的序列。传递压缩缓冲区长度是必要的。此外,解压缩字符串的长度可能与压缩流的长度(以字节为单位)不同。