📄 file_process.c
字号:
#include "huffman.h"
/*为了便于对多个同类型文件进行操作,把操作的文件名也作为函数形参来使用。*/
//2006-11-04
/*------------------------------------------------------------------------------------------*/
/*创建一个待编码的数据文件;此文本数据文件由26个字母,10个数字,空格,及常用标点符号(,;.:"!?)等
字符构成(初步假设文本文件的各种字符个数不操过60个)。定义一个数组来放这些字符*/
/*创建的数据文件名FILENAME为"DATAFILE"(实参)。*/
void create_data_file(const char* const FILENAME) //创建一个原始数据文件,文件名为FILENAME。
{
char ch;
FILE* fp;
printf("Create a data file.\n");
printf("%s\n%s\n%s\n%s\n%s",
"The characters of the file consists of 26 letters,10 numbers,space,",
"newline,and common interpunctions,etc.",
"Finish the input-contents with a character '#' as a ENDING FLAG !",
"Input the contents of your data file !",
"Contents:");
if((fp = fopen(FILENAME,"wb")) == NULL){
printf("\nOpen file \"%s\" to write ERROR !\n",FILENAME);
exit(1); //退出程序
}
while((ch = getchar()) != '#'){//直到输入字符'#'才结束文件的内容输入
/*函数getchar把键入的回车视为字符'\n'即换行功能字符;且getchar只有在键入回车后才把之前所有
输入字符送入到内存处理也即才开始执行后续程序。所以输入文件内容结束时键入"#再加回车键"即可。*/
if((fputc((int)ch,fp)) == EOF){
printf("Write file \"%s\" ERROR !\n",FILENAME);
exit(1);
}
}
fclose(fp);
printf("\nCreate file \"%s\" successfully !\n",FILENAME);
}
/*------------------------------------------------------------------------------------------*/
//分析原始数据文件的字符构成及各字符的频率(频度),作为先验概率。
/*由分析原始数据文件后得到字符集F的字符个数N。这个个数N很重要,表示了所要建立的Huffman二叉树的
叶子结点个数,在其后的Huffman编译码算法中都要用到。所以定义N为外部变量(即全局变量)。*/
// F为字符集的频率(频度)表,其字符个数为N。
void characters_analysis(StrSetFrequencyTable F,const char* const FILENAME)
{
int ch; //把一个字符当作一个整数(即字符的ASCII值)
int i;
int flag;
float total_sum;
FILE* fp;
//初始化字符集频度表数组
for(i = 0;i < N1;++i){
F[i].data = '#'; //假设字符'#'在数据文件中不出现
F[i].sum = 0;
F[i].weight = 0.0;
}
//统计各字符的个数
if((fp = fopen(FILENAME,"rb")) == NULL){
printf("\nOpen file \"%s\" to read ERROR !\n",FILENAME);
exit(1); //退出程序
}
flag = -1;//当前放入数组F的最后一个字符的位置标记;初始位置为-1。当前F中已有(flag+1)个字符。
while((ch = fgetc(fp)) != EOF){ //一直读到文件尾EOF
for(i = 0;i <= flag;++i){
if((char)ch == F[i].data){
++F[i].sum;
break;
}
}
if(i == flag + 1){ //在F的已有字符中不存在字符ch
++flag; //修正位置标记
F[flag].data = ch;
++F[flag].sum;
}
}
//求出哈夫曼树的叶子结点数N及树中结点总数M。 //M,N都是全局变量。
N = flag + 1;
M = 2 * N - 1;
//计算各字符的频度(百分比)即求出F[i].weight的值。
total_sum = 0.0;
for(i = 0;i <= flag;++i) //数组F中共有(flag+1)个有效字符(在原始数据文件中含有的字符个数)
total_sum += F[i].sum;
for(i = 0;i <= flag;++i)
F[i].weight = F[i].sum / total_sum;
}
/*---------------------------------------------------------------------------------*/
//文件指针fp1处于文件读操作的当前位置
char ReadACharFromFile(FILE* fp1) //从文件fp1中读取一个字符并返回
{
int ch; //注意:这里必须定义为int,因为要和EOF(-1)比较!
if((ch = fgetc(fp1)) == EOF) //从文件中读一个字符
return '\0';//返回空字符(不是空格字符SPACE!!),标记读字符读到了文件尾标记EOF)
else
return (char)ch; //强制转换为char型
}
/*--------------------------------------------------------------------------------*/
/*把编码字符串(0,1序列)code写入文件fp2保存,不保存字符串结束标志'\0',因为本算法在进行Huffman译码
时是借助Huffman树T及Huffman码表T一起进行的。另外一种算法是保存字符串结束标志'\0',把一个字符串
当作一帧('\0'作为帧的结尾标记),它对应一个字符的编码序列,只需借助Huffman码表T就可实现译码。 */
//若直接使用fputs(code,fp2);则会保存'\0',所以不能直接用它!
//文件指针fp2处于文件写操作的当前位置。
void WriteStringsToFile(FILE* fp2,const char* const code)
{
int i;
int j = 0;
i = strlen(code);
while(--i >= 0)
fputc((int)(code[j++]),fp2);
}
/*-----------------------------------------------------------------------------------*/
//文件指针fp2处于文件写操作的当前位置。
void WriteACharToFile(char ch1,FILE* fp2)//把字符ch1写入文件fp2保存
{
fputc((int)ch1,fp2);
}
/*-----------------------------------------------------------------------------------*/
void print(const char* const FILENAME) //打印文件FILENAME的内容
{
int ch;
FILE* fp;
if((fp = fopen(FILENAME,"rb")) == NULL){
printf("\nOpen file \"%s\" to print ERROR !\n",FILENAME);
exit(1); //退出程序
}
printf("The contents of FILE %s :\n",FILENAME);
while((ch = fgetc(fp)) != EOF) //一直读到文件尾EOF
putchar(ch);
}
/*----------------------------------------------------------------------------------*/
//输入两个文件名,并打开文件
void InputTwoFileName(char* const filename,char* const filename1,FILE* fp1,FILE* fp2)
{
char string[30];
printf("\nInput the filename(to read) to operate :");
gets(string);
strcpy(filename,string);
printf("\nInput the filename(to write) to save current operation results :");
gets(string);
strcpy(filename1,string);
if((fp1 = fopen(filename,"rb")) == NULL){
printf("File %s NOT exist !\n",filename);
printf("The program will exit later !\n");
exit(1);
}
if((fp2 = fopen(filename1,"wb")) == NULL){
printf("File %s NOT exist !\n",filename1);
printf("The program will exit later !\n");
exit(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -