歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 文件壓縮的C語言代碼

文件壓縮的C語言代碼

日期:2017/3/1 10:02:52   编辑:Linux編程

這份代碼是大二期間自己寫的c語言代碼,因為某種原因,改變自己的人生軌跡,開始對數據庫產生了興趣,現在把這份代碼粘貼出來,表達自己大學期間對編程的愛好和曾經那些不眠之夜的奮斗的懷念吧,同時表示對編程人的崇高敬佩,你們是很棒的。

#include<stdio.h>

#include<stdlib.h>
#define MAXS 1000000000
/*定義節點*/
struct node
{
unsigned int weight;/*權值*/
int left; /*左節點*/
int right; /*右節點*/
int flag; /*標志(試節點有沒有用過)*/
};
struct node hfm[511]={{0,-1,-1,-1}};


/*定義一個編碼*/
struct type
{
int bit[256];/*編碼*/
int start; /*編碼長度*/
};
struct type code[256]={{-1,0}};


/*自定義函數聲明*/
int findm(struct node *p,int t);
void preorder(int x);
void output_count();
void hu_fm();
void hf_code();
void turn(int *p,int f);
void output_wc();
void y_s();
void j_ys(int head);


/*找出最小的數*/
int findm(struct node *p,int t)
{
int s1=-1,j;
int min=MAXS;
for(j=0;j<(256+t);j++)
{
if((p[j].flag!=1)&&(p[j].weight>0)&&(p[j].weight<=min)) /*已經用過的節點不參與比較*/
{
min=p[j].weight;
s1=j;
}
}
return s1;
}
/*遍歷二叉樹(遞歸)*/
void preorder(int x)
{
if(x==-1) return;
printf("%d,%d,%d\n",hfm[x].weight,hfm[x].left,hfm[x].right);
preorder(hfm[x].left);
preorder(hfm[x].right);
}


/*輸出統計情況*/
void output_count()
{
int i;
for(i=0;i<511;i++)
{
if (hfm[i].weight !=0)
printf("%d\t%d\n",hfm[i].weight,i);
}
printf("\n");
}


/*生成二叉樹和計算權值*/
void hu_fm()
{
int t=0;
int m1,m2;
while(t<=255)
{
m1=findm(hfm,t);
hfm[256+t].left=m1;
hfm[m1].flag=1;
m2=findm(hfm,t);
if(m2==-1) break;
hfm[256+t].right=m2;
hfm[m2].flag=1;
hfm[256+t].weight=hfm[m1].weight+hfm[m2].weight;
t++;
}
}
/*生成編碼*/
void hf_code()
{
int x,i,j;
for(i=0;i<256;i++) /*葉節點*/
{
if(hfm[i].weight>0) /*出現了的字符*/
{
x=i;
for(j=256;hfm[j].weight!=0;j++) /*父節點*/
{
if(x==hfm[j].left) /*判斷是否是父節點的左節點(編碼為0)*/
{
code[i].bit[code[i].start]=0;
code[i].start++;
x=j;
}
else if(x==hfm[j].right) /*判斷是否是父節點的右節點(編碼為1)*/
{
code[i].bit[code[i].start]=1;
code[i].start++;
x=j;
}
}
turn(code[i].bit,--code[i].start);
}
}
}
/*翻轉編碼*/
void turn(int *p,int f)
{
int s;
for(s=0;s<f;s++,f--)
{
p[s]=p[s]^p[f];
p[f]=p[f]^p[s];
p[s]=p[s]^p[f];
}
}


/*輸出字符的編碼情況*/
void output_wc()
{
int i,j;
for(i=0;i<256;i++)
{
if(hfm[i].weight>0)
{
printf("%c\t",i);
for(j=0;j<=code[i].start;j++)
printf("%d",code[i].bit[j]);
printf("\n");
}
}
}


/*壓縮文件*/
void y_s(FILE *fp,FILE *fp2)
{
int i;
for(i=0;i<256;i++) /*將各字符的權值壓入文件頭*/
{
fwrite(&hfm[i].weight,sizeof(unsigned int),1,fp2);
}

int cn=0; /*統計當前位數*/
unsigned char b=0;/*存入轉成的二進制*/
while(!feof(fp))
{
int nt=0;
unsigned char p;
if(fread(&p,1,1,fp)!= 1) /*每取一個字節*/
break;
while(nt<=code[p].start)
{

if(code[p].bit[nt])
{
b |= 1<<(7-cn); /*將當前字節第幾位置零*/
}
nt++;
if((cn+1)==8)
{
fwrite(&b,sizeof(b),1,fp2); /*滿8位壓入文件*/
b=0; /*清零*/
}
cn = (cn+1)%8; /*滿8位清零*/
}
}

if(cn) /*寫入尾巴(最後一個沒有滿8位的)*/
{
fwrite(&b,sizeof(b),1,fp2);
cn=0;
b=0;
}
fclose(fp);
fclose(fp2);
}


int main(int a ,char *str[])
{
FILE *fp=fopen(str[1],"r");/*打開需壓縮的文件*/
if(fp == NULL)
{
perror("open file.txt\n");
exit(1);
}


FILE *fp2=fopen(str[2],"w"); /*打開需壓縮形成的文件*/
if(fp2 == NULL)
{
perror("open file2.txt\n");
exit(1);
}
unsigned char p;
int i,j;
/*給節點數組賦初值*/
for(i=1;i<511;i++)
{
hfm[i]=hfm[0];
}

/*統計*/
while(!feof(fp))
{
if (fread(&p,1,1,fp) != 1)
break;
hfm[p].weight++;
}
rewind(fp);
hu_fm();
output_count();/*輸出統計情況*/
/*查找根節點*/
for(i=510;i>=256;i--)
{
if (hfm[i].weight !=0)
break;
}
unsigned int head=i;
preorder(head);
/*給編碼數組賦初值*/
for(i=1;i<256;i++)
{
code[i]=code[0];
}


hf_code();
output_wc();
y_s(fp,fp2);
}

Copyright © Linux教程網 All Rights Reserved