#include <stdio.h>
#include <string.h> /*for strcpy()*/
#include <math.h> /*for log(),pow()*/
#include <malloc.h> /*for malloc(),free()*/
#include <stdlib.h> /*for abs()*/
#define CACHE_SIZE 128
typedef char element_type;
typedef double element_chance;
typedef struct element_set /*用来描述一个概率模型*/
{
int num;
element_type *name;
element_chance *chance;
}element_set;
int init_elements(element_set *);
int set_elements(element_set *); /*设置一个概率模型的值*/
int set_series(char **); /*设置一个待压缩序列*/
int coder(element_set *,char *,char **); /*对待压缩序列用给定概率模型进行算术编码*/
int set_element_name(char *);
int set_element_chance(double *);
int check_elements(element_set *);
int print_elements_info(element_set *);
int main(void)
{
element_set set;
element_type *series=0;
char *code=0;
if(init_elements(&set))
{
printf("init_elements error!/n");
return 1;
}
if(set_elements(&set))
{
printf("set_elements error!/n");
return 1;
}
if(set_series(&series))
{
printf("set_series error!/n");
return 1;
}
if(coder(&set,series,&code))
{
printf("coder error!/n");
return 1;
}
printf("the code is:%s/n",code);
system("pause");
return 0;
}
int init_elements(element_set *set)
{
if(!set)
{
printf("pointer is NULL!/n");
return 1;
}
set->num=0;
set->name=0;
set->chance=0;
return 0;
}
int set_elements(element_set *set)
{
int i,j,flag=0;
do
{
printf("how many elements in the set?/n");
do
{
scanf("%d",&(set->num));
while(getchar()!='/n')
{
;
}
if(set->num<1)
{
flag=1;
printf("the num should greater than 0!/n");
}
else
{
flag=0;
}
}while(set->num<1);
set->name=malloc(set->num*sizeof(element_type));
set->chance=malloc(set->num*sizeof(element_chance));
if(!(set->name&&set->chance))
{
printf("malloc error!/n");
return 1;
}
printf("please input the elements name and their chances./n");
for(i=0;i<set->num;i++)
{
do
{
printf("%d:/n",i+1);
printf("/tname:/n/t/t");
if(set_element_name(&(set->name[i])))
{
printf("set_element_name error!/n");
return 1;
}
flag=0;
for(j=0;j<i;j++)
{
if(set->name[i]==set->name[j])
{
flag=1;
printf("the name is same with /"%d/"!/n",j+1);
printf("please reinput./n");
break;
}
}
}while(flag);
do
{
printf("/tchance:/n/t/t");
if(set_element_chance(&(set->chance[i])))
{
printf("set_element_chance error!/n");
return 1;
}
if(set->chance[i]<0||set->chance[i]>1)
{
flag=1;
printf("chance error!/n");
printf("please reinput./n");
}
else
{
flag=0;
}
}while(flag);
}
do
{
if(check_elements(set))
{
flag=1;
printf("total chance is not 1!/n");
printf("the elements information is:/n");
if(print_elements_info(set))
{
printf("print_elements_info error!/n");
return 1;
}
printf("which element's chance do you want to modify?(0 to reinput all and negatives to quit.)/n");
scanf("%d",&i);
while(getchar()!='/n')
{
;
}
if(i)
{
if(i>0)
{
printf("%d:/n",i+1);
printf("/tchance:/n/t/t");
if(set_element_chance(&(set->chance[i])))
{
printf("set_element_chance error!/n");
return 1;
}
}
else
{
return 1;
}
}
else
{
break;
}
}
else
{
flag=0;
}
}while(flag);
}while(flag);
return 0;
}
int set_series(char **series)
{
char *buf,tmp;
int i,j=0;
if(*series)
{
printf("pointer may be using by other procedure!/n");
return 1;
}
printf("please input the series./n");
while(++j>0)
{
buf=malloc((j*CACHE_SIZE+1)*sizeof(char));
if(!buf)
{
printf("malloc error!(may the series is too long.)/n");
return 1;
}
if(*series)
{
strcpy(buf,*series);
free(*series);
}
*series=buf;
for(i=0;i<CACHE_SIZE;i++)
{
tmp=getchar();
if(tmp=='/n')
{
break;
}
buf[(j-1)*CACHE_SIZE+i]=tmp;
}
buf[(j-1)*CACHE_SIZE+i]='/0';
if(tmp=='/n')
{
break;
}
}
return 0;
}
int coder(element_set *set,char *series,char **code)
{
int i,j,k;
double low,width,chance;
double fractional;
if(!(set&&series)||*code)
{
printf("wrong pointer!/n");
return 1;
}
for(i=low=0,width=1;series[i]!='/0';i++)
{
for(j=0;j<set->num;j++)
{
if(series[i]==set->name[j])
{
break;
}
}
if(series[i]!=set->name[j]) /*set->num<0 and other errors*/
{
printf("error!(either series not in element_set or an ill element_set.)/n");
return 1;
}
for(k=0,chance=0;k<j;k++)
{
chance+=set->chance[k];
}
low+=width*chance;
width*=set->chance[j];
}
k=(int)(log(width)/log(2))*(-1);
*code=malloc((k+1)*sizeof(char));
if(!(*code))
{
printf("malloc erroc!/n");
return 1;
}
fractional=modf(width*pow(2,k),&chance);
if(abs(fractional)>=1e-16)
{
width+=pow(2,-k);
}
for(i=0;i<k;i++)
{
low*=2;
(*code)[i]=((int)low)%2+'0';
}
(*code)[k]='/0';
return 0;
}
int set_element_name(char *name)
{
if(!name)
{
printf("pointer is NULL!/n");
return 1;
}
*name=getchar();
while(getchar()!='/n')
{
;
}
return 0;
}
int set_element_chance(double *chance)
{
if(!chance)
{
printf("pointer is NULL!/n");
return 1;
}
scanf("%lf",chance);
while(getchar()!='/n')
{
;
}
return 0;
}
int check_elements(element_set *set)
{
int i;
double total=0;
if(!set)
{
printf("pointer is NULL!/n");
return 1;
}
for(i=0;i<set->num;i++)
{
total+=set->chance[i];
}
if(total!=1)
{
return 1;
}
else
{
return 0;
}
}
int print_elements_info(element_set *set)
{
int i;
if(!set)
{
printf("pointer is NULL!/n");
return 1;
}
for(i=0;i<set->num;i++)
{
printf("%d:name %c chance %g/n",i+1,set->name[i],set->chance[i]);
}
return 0;
}
算数编码
最新推荐文章于 2023-12-03 16:18:24 发布
本文介绍了一种基于算术编码的压缩算法实现过程。该算法通过定义概率模型,为不同元素分配相应的概率,并据此对输入序列进行编码,最终生成压缩后的编码字符串。文章详细描述了初始化概率模型、设置系列数据及进行算术编码的具体步骤。
摘要由CSDN通过智能技术生成