用C压缩文件

时间:2015-12-01 00:32:59

标签: c arrays function compression

我真的不知道如何缩短代码所以我把整个事情放在下面,但当我运行代码并尝试压缩它时,它会继续运行,当我使用ctrl + z停止它时生成的输出文件大于我试图压缩的文件。我认为错误来自我的压缩文件功能,但下面是整个代码。它编译并运行,但它不是我所期望的。它也没有打印出我在compressFile函数中的语句。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define len(x) ((int)log10(x)+1)

struct node{
        int value;
        char letter;
        struct node *left, *right;
    };

    typedef struct node Node;

    int engLetterFreq[27] = {81, 15, 28, 43, 128, 23, 20, 61, 71, 2, 1, 40, 24, 69, 76, 20, 1, 61, 64, 91, 28, 10, 24, 1, 20, 1, 130};

int findSmaller (Node *array[], int differentFrom){    //start findSmaller

    int smaller;
    int i = 0;

    while(array[i]->value== -1)
        i++;
    smaller = i;
    if(i == differentFrom){
        i++;
        while(array[i]->value== -1)
            i++;
        smaller = i;
    }

    for(i=1; i<27; i++){
        if(array[i]->value== -1)
            continue;
        if(i==differentFrom)
            continue;
        if(array[i]->value<array[smaller]->value)
            smaller = i;
    }

    return smaller;

}//end findSmaller

void buildHuffmanTree(Node **tree){     //start buildHuffmanTree

    Node *temp;
    Node *array[27];
    int i;
    int subTrees = 27;
    int smallOne, smallTwo;

    for(i=0; i<27; i++){
        array[i] = malloc(sizeof(Node));
        array[i]->value = engLetterFreq[i];
        array[i]->letter = i;
        array[i]->left = NULL;
        array[i]->right = NULL;
 }

    while(subTrees>1){
        smallOne = findSmaller(array, -1);
        smallTwo = findSmaller(array, smallOne);
        temp = array[smallOne];
        array[smallOne] = malloc(sizeof(Node));
        array[smallOne]->value=temp->value+array[smallTwo]->value;
        array[smallOne]->letter=127;
        array[smallOne]->left=array[smallTwo];
        array[smallOne]->right=temp;
        array[smallTwo]->value = -1;
        subTrees--;
    }

    *tree = array[smallOne];

    return;
}

void fillTable(int codeTable[], Node *tree, int Code){

    if(tree->letter<27){
        codeTable[(int)tree->letter] = Code;
    }else{
        fillTable(codeTable, tree->left, Code*10+1);
        fillTable(codeTable, tree->right, Code*10+2);
    }

    return;
}

void compressFile(FILE *input, FILE *output, int codeTable[]){

    char bit, c, x = 0;
    int n, length, bitsLeft = 8;
    int originalBits = 0; 
    int compressedBits = 0;

    while((c=fgetc(input))!=10){
        originalBits++;
        if(c==32){
            length = len(codeTable[26]);
            n = codeTable[26];
        }else{
            length = len(codeTable[c-97]);
            n = codeTable[c-97];
        }

        while(length>0){
            compressedBits++;
            bit = n % 10 - 1;
            n /= 10;
            x = x | bit;
            bitsLeft--;
            length--;
            if(bitsLeft == 0){
                fputc(x, output);
                x = 0;
                bitsLeft = 8;
            }
            x = x << 1;
        }
    }

    if(bitsLeft != 8){
        x = x << (bitsLeft-1);
        fputc(x, output);
    }

    printf("Original bits = %d\n", originalBits*8);
    printf("Compressed bits = %d\n", compressedBits);
    printf("Saved %.2f of memory\n", ((float)compressedBits/(originalBits*8))*100);

    return;
}

void decompressFile(FILE *input, FILE *output, Node *tree){

    Node *current = tree;
    char c, bit;
    char mask = 1 << 7;
    int i;

    while ((c=fgetc(input))!=EOF){

        for(i=0; i<8; i++){

            bit = c & mask;
            c = c << 1;

            if(bit==0){
                current = current->left;
                if(current->letter != 127){
                    if(current->letter == 26){
                        fputc(32, output);
                    }else{
                        fputc(current->letter+97, output);
                    }

                    current = tree;
                }
            }else{
                current = current->right;
                if(current->letter != 127){
                    if(current->letter == 26){
                        fputc(32, output);
                    }else{
                        fputc(current->letter+97, output);
                    }

                    current = tree;
                }
            }
        }
    }

    return;
}

void invertCodes(int codeTable[], int codeTable2[]){

    int i, n, copy;

    for (i=0; i<27; i++){

        n = codeTable[i];
        copy = 0;

        while(n>0){
            copy = copy * 10 + n%10;
            n /= 10;
        }

        codeTable2[i] = copy;
    }

    return;
}

int main(){

    Node *tree;
    int codeTable[27], codeTable2[27];
    int compress;
    char filename[20];
    FILE *input, *output;

    buildHuffmanTree(&tree);

    fillTable(codeTable, tree, 0);

    invertCodes(codeTable, codeTable2);

    printf("Type the name of the file\n");
    scanf("%s", filename);
    printf("1 to compress, 2 to decompress\n");
    scanf("%d", &compress);

    input = fopen(filename, "r");
    output = fopen("output.txt", "w");

    if(compress == 1){
        compressFile(input, output, codeTable2);
    }else{
        decompressFile(input, output, tree);
    }

    return 0;

}

0 个答案:

没有答案