⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_process.c

📁 自己用C编写的Huffman编码通信系统应用
💻 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 + -