文件压缩的C语言代码
这份代码是大二期间自己写的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);
}