arrays - C 压缩器 - 数组下标的类型为 char

标签 arrays c char compression

我是一个真正的 C 初学者,所以我不知道为什么会出现这个错误。我将代码发送给我的 friend ,它对他有用,没有任何错误,也没有改变。我在 Oracle VM VirtualBox 上运行它。压缩程序还有更多文件。当我想使用 cmake 创建 Makefile 和正在运行的程序时,就会发生这种情况。

错误出在条件 if(isLeaf(root)) 的函数 buildDictionary 中。

enter image description here

我应该如何解决这个问题?有什么想法吗?

#include "huffman.h"

void buildDictionary(struct MinHeapNode *root, int arr[], int top, HuffmanDictionary *dictionary) {
    if (root->left) {
        arr[top] = 0;
        buildDictionary(root->left, arr, top + 1, dictionary);
    }

    if (root->right) {
        arr[top] = 1;
        buildDictionary(root->right, arr, top + 1, dictionary);
    }

    if (isLeaf(root)) {
        dictionary->symbol[root->data] = root->data;
        dictionary->code[root->data].code = encodeBits(arr, top);
        dictionary->code[root->data].size = top;
    }
}

void printDictionary(HuffmanDictionary *dictionary) {
    for (int i = 0; i < 256; i++) {
        int bs[MAX_TREE_HT];
        decodeBits(dictionary->code[i].code, dictionary->code[i].size, bs);
        printf("%c:", dictionary->symbol[i]);
        for (int a = 0; a < dictionary->code[i].size; a++) {
            printf("%d", bs[a]);
        }
        printf("\n");
    }
}

long huffman_compress(const uint8_t *src, long size, uint8_t *dst, HuffmanDictionary *dictionary) {
    FreqencyData *fd = malloc(sizeof(FreqencyData) * 256);
    buildFrequencyData(src, size, fd);
    uint8_t words[256];
    int frequencies[256];
    int count = 0;
    for (int a = 0; a < 256; a++) {
        if (fd[a].frequency > 0) {
            words[count] = (uint8_t) a;
            frequencies[count] = fd[a].frequency;
            count++;
        }
    }

    struct MinHeapNode *root
            = buildHuffmanTree(words, frequencies, count);
    int arr[MAX_TREE_HT], top = 0;

    buildDictionary(root, arr, top, dictionary);
    uint8_t *bits = malloc(size * MAX_TREE_HT);
    memset(bits, 0, size * MAX_TREE_HT);

    long numOfBits = 0;
    for (long i = 0; i < size; i++) {
        int n = dictionary->code[src[i]].size;
        uint32_t b = dictionary->code[src[i]].code;
        int bs[n];
        decodeBits(b, n, bs);
        for (int a = 0; a < n; a++) {
            bits[numOfBits + a] = bs[a];
        }
        numOfBits += n;
    }

    long cx = 0;
    for (long i = 0; i < numOfBits; i += 8) {
        int bs[8];
        for (int a = 0; a < 8; a++) {
            bs[a] = bits[i + a];
        }
        dst[cx] = encodeBitsArr(bs);
        cx++;
    }
    return cx;
}

uint32_t encodeBits(int arr[], int n) {
    uint32_t ret = 0;
    for (int i = 0; i < n; i++) {
        if (arr[i] == 1) {
            ret += pow(2, i);
        }
    }

    return ret;
}

uint8_t encodeBitsArr(const int arr[8]) {
    uint8_t ret = 0;
    for (int i = 0; i < 8; i++) {
        if (arr[i] == 1) {
            ret += pow(2, i);
        }
    }

    return ret;
}

void decodeBits(uint32_t b, int n, int bits[]) {
    for (int i = 0; i < n; i++) {
        bits[i] = (int) ((b >> i) & ONE_BIT_MASK_32BITS) != 0;
    }
}

void decodeBitsFromByte(uint8_t b, int bits[]) {
    for (int i = 0; i < 8; i++) {
        bits[i] = (int) ((b >> i) & 0x01) != 0;
    }
}

int findMatchingSymbol(const int bits[MAX_TREE_HT], HuffmanDictionary *dictionary,int* foundSize) {
    for (int i = 0; i < 256; i++) {
        int bs[MAX_TREE_HT];
        decodeBits(dictionary->code[i].code, dictionary->code[i].size, bs);
        bool found = false;
        for (int a = 0; a < dictionary->code[i].size; a++) {
            if (bs[a] == bits[a]) {
                found = true;
            } else {
                found = false;
                break;
            }
        }

        if (found) {
            *foundSize = dictionary->code[i].size - 1;
            return dictionary->symbol[i];
        }
    }

    return -1;
}

long huffman_extract(const uint8_t *src, long size, uint8_t *dst, HuffmanDictionary *dictionary) {
    uint8_t *bits = malloc(size * 8);
    memset(bits, 0, size * 8);

    for (long i = 0; i < size; i++) {
        int bs[8];
        decodeBitsFromByte(src[i], bs);
        for (int a = 0; a < 8; a++) {
            bits[(i * 8) + a] = bs[a];
        }
    }

    long foundBytes = 0;
    int bs[MAX_TREE_HT];
    for (long l = 0; l < size * 8; l++) {
        for (int a = 0; a < MAX_TREE_HT; a++) {
            bs[a] = bits[l + a];
        }
        int* foundSize = malloc(sizeof(int));

        uint8_t b = findMatchingSymbol(bs, dictionary, foundSize);
        if (b >= 0) {
            dst[foundBytes] = b;
            l+= *foundSize;
            foundBytes++;
        }
    }

    return foundBytes;
}

void buildFrequencyData(const uint8_t *src, long size, FreqencyData *fd) {
    for (long i = 0; i < size; i++) {
        fd[src[i]].frequency++;
    }
}

struct MinHeapNode *newNode(uint8_t data, unsigned freq) {
    struct MinHeapNode *temp = (struct MinHeapNode *)malloc(
            sizeof(struct MinHeapNode));

    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;

    return temp;
}

struct MinHeap *createMinHeap(unsigned capacity) {
    struct MinHeap *minHeap
            = (struct MinHeap *) malloc(sizeof(struct MinHeap));

    minHeap->size = 0;
    minHeap->capacity = capacity;
    minHeap->array = (struct MinHeapNode **)malloc(
            minHeap->capacity * sizeof(struct MinHeapNode *));
    return minHeap;
}

void swapMinHeapNode(struct MinHeapNode **a,
                     struct MinHeapNode **b) {
    struct MinHeapNode *t = *a;
    *a = *b;
    *b = t;
}

void minHeapify(struct MinHeap *minHeap, int idx) {
    int smallest = idx;
    int left = 2 * idx + 1;
    int right = 2 * idx + 2;

    if (left < minHeap->size
        && minHeap->array[left]->freq
           < minHeap->array[smallest]->freq)
        smallest = left;

    if (right < minHeap->size
        && minHeap->array[right]->freq
           < minHeap->array[smallest]->freq)
        smallest = right;

    if (smallest != idx) {
        swapMinHeapNode(&minHeap->array[smallest],
                        &minHeap->array[idx]);
        minHeapify(minHeap, smallest);
    }
}

int isSizeOne(struct MinHeap *minHeap) {
    return (minHeap->size == 1);
}

struct MinHeapNode *extractMin(struct MinHeap *minHeap) {
    struct MinHeapNode *temp = minHeap->array[0];
    minHeap->array[0] = minHeap->array[minHeap->size - 1];

    --minHeap->size;
    minHeapify(minHeap, 0);

    return temp;
}

void insertMinHeap(struct MinHeap *minHeap,
                   struct MinHeapNode *minHeapNode) {
    ++minHeap->size;
    int i = minHeap->size - 1;

    while (i
           && minHeapNode->freq
              < minHeap->array[(i - 1) / 2]->freq) {

        minHeap->array[i] = minHeap->array[(i - 1) / 2];
        i = (i - 1) / 2;
    }

    minHeap->array[i] = minHeapNode;
}

void buildMinHeap(struct MinHeap *minHeap) {
    int n = minHeap->size - 1;
    int i;

    for (i = (n - 1) / 2; i >= 0; --i)
        minHeapify(minHeap, i);
}

int isLeaf(struct MinHeapNode *root) {
    return !(root->left) && !(root->right);
}

struct MinHeap *createAndBuildMinHeap(uint8_t data[],
                                      int freq[], int size) {
    struct MinHeap *minHeap = createMinHeap(size);

    for (int i = 0; i < size; ++i)
        minHeap->array[i] = newNode(data[i], freq[i]);

    minHeap->size = size;
    buildMinHeap(minHeap);

    return minHeap;
}

struct MinHeapNode *buildHuffmanTree(uint8_t data[],
                                     int freq[], int size) {
    struct MinHeapNode *left, *right, *top;

    struct MinHeap *minHeap
            = createAndBuildMinHeap(data, freq, size);

    while (!isSizeOne(minHeap)) {
        left = extractMin(minHeap);
        right = extractMin(minHeap);

        top = newNode('$', left->freq + right->freq);

        top->left = left;
        top->right = right;

        insertMinHeap(minHeap, top);
    }

    return extractMin(minHeap);
}

我没有尝试任何操作,因为代码在其他计算机上正常运行,但在我的计算机上却运行不正常。

最佳答案

在头文件 huffman.h 中,结构体 MinHeapNode 有一个类型为 char 的成员 data,在默认情况下对 char 类型进行签名的某些体系结构上,可以具有负值。这会在索引 dictionary->symbol[root->data]dictionary->code[root->data] 时导致未定义的行为,因为您将取消引用外部元素数组边界。只需将类型更改为 unsigned charuint8_t 即可避免此问题并修复警告,即 -Werror 变成了错误。

关于arrays - C 压缩器 - 数组下标的类型为 char,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75302611/

相关文章:

c - 无法使用Makefile链接数学库

c - 使用 openGL 截图并保存为 png

mysql - 关于 char varchar 和tinyint 的问题

c - 变量 在 C 中使用 Fgets 和 char 数组

java - 对于最多 10 个元素的数组 : for loop copy or System. arrayCopy?

php - 将 php 数组传递给 jquery 函数

c - 在将输入作为 shell 命令传递给 exe 时,可以将文件替换为缓冲区吗?

关于选择排序的澄清?

c++ - 如何从 vector<char> 转换为数字整数

c++ - 拆分学生列表,其格式如下:0001 William Bill Junior 8.5