Huffman-Zip

cpp
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <windows.h>
using namespace std;
const char SUFFIX[] = ".myz", TXT[] = ".txt";
const int N = 1e5 + 7, M = 5005;
FILE *fp, *fw;
char str[M], words[N];
struct Huff{
	char val;
	int cnt, left, right;
}huff[M];
struct cmp{
	bool operator()(int A, int B) {
		return huff[A].cnt > huff[B].cnt;
	}
};
priority_queue<int, vector<int>, cmp>q;
map<string, char>uzp;
map<char, string>zp;

void init()
{
	char ch = 0;
	int tot = 0;
	ch = getchar();
	while(ch == '\n')
		ch = getchar();
	while(ch != '\n') {
		str[tot++] = ch;
	ch = getchar();
	}
}

int judge()
{
	int len = strlen(str);
	char format[5] = {0};
	for(int i = len - 1; i >= len - 4; i--) {
		format[4 - len + i] = str[i];
	}
	if(strcmp(format, TXT) == 0) {
		return 0;
	} else if(strcmp(format, SUFFIX) == 0) {
		return 1;
	} else {
		return 2;
	}
}

bool huff_write(int root, string path)
{
	if(!huff[root].left && !huff[root].right) {
		fprintf(fw, "%c%s ", huff[root].val, path.c_str());
		
		zp[huff[root].val] = path;
		return 0;
	}
	if(huff[root].left) {
		huff_write(huff[root].left, path + '0');
	}
	if(huff[root].right) {
		huff_write(huff[root].right, path + '1');
	}
	return 0;
}

bool zip()
{
	strcat(str, SUFFIX);
	fw = fopen(str, "wb+");
	char ch;
	int tot = 0, cnt = 0, pd[M] = {0}, a, b;
	while((ch = fgetc(fp)) != EOF) {
		words[tot++] = ch;
		//printf("%c", ch);
		if((unsigned)ch > 127) {
			printf("Warning!含有非英文字符!\n");
			return 0;
		}
		pd[(unsigned)ch]++;
		if(tot > N) return 0;
	}
	//printf("%d", N * 5 - tot);
	fwrite(&tot, sizeof(int), 1, fw);
	for(int i = 0; i <= M; i++) {
		if(pd[i]) {
			huff[++cnt].cnt = pd[i];
			huff[cnt].val = (char)i;
			q.push(cnt);
		}
	}
	fwrite(&cnt, sizeof(int), 1, fw);
	//fprintf(fw, "%d ", cnt);
/*	while(!q.empty()) {
		a = q.top(), q.pop();
		printf("%2d:%c number:%d\n", a, huff[a].val, huff[a].cnt);
	}*/
	while(!q.empty()) {
		a = q.top(), q.pop();
		if(q.empty()) break;
		b = q.top(), q.pop();
		huff[++cnt].left = a;
		huff[cnt].right = b;
		huff[cnt].cnt = huff[a].cnt + huff[b].cnt;
		q.push(cnt);
//		if(!huff[a].val) huff[a].val = '0';
//		if(!huff[b].val) huff[b].val = '1';
	}
	char zerone[N * 5] = {0};
	if(huff_write(a, "")) return 0;
	for(int i = 0; i < tot; i++) {
		strcat(zerone, zp[words[i]].c_str());
	}
	//printf("%s", zerone);
	int len = strlen(zerone), j = 1, num = 0;
	for(unsigned int i = 0; i < len; i++) {
		if(j > 32) {
			//printf("%d\n", num);
			fwrite(&num, sizeof(int), 1, fw);
			j = 1;
		}
		if(j <= 32) {
			num = (num << 1) + zerone[i] - '0';
			//printf("%d\n", num);
			j++;
		} 
	}
	//printf("%d\n", num);
	/*while(num) {
		printf("%d", num % 2);
		num /= 2;
	}*/
	while(j <= 32) {
		num = (num << 1);
		j++;
	}
	//printf("%d", num);
	fwrite(&num, sizeof(int), 1, fw);
	fseek(fw, 0, SEEK_END);
	fseek(fp, 0, SEEK_END);
	double size1, size2;
	size1 = ftell(fp);
	size2 = ftell(fw);
	printf("压缩率为%.2lf%%\n", size2 / size1 * 100);
	fclose(fp);
	fclose(fw);
	return 1;
}

bool unzip()
{
	fclose(fp);
	fp = fopen(str, "rb");
	str[strlen(str) - 4] = 0;
	fw = fopen(str, "w+");
	int cnt = 0, tot = 0, a, wds = 0, atot = 0;
	char ch, path[25];
	string dic;
	fread(&wds, sizeof(int), 1, fp);
	fread(&cnt, sizeof(int), 1, fp);
	for(int i = 1; i <= cnt; i++) {
		//ch = fgetc(fp);
		//printf("111\n");
		fscanf(fp, "%c%s", &ch, path);
		fgetc(fp);
		dic = path;
		uzp[dic] = ch;
		//printf("%c %s\n", ch, dic.c_str());
		//printf("%c %s\n", uzp[dic], dic.c_str());
	}
	char zerone[N * 5] = {0};
	while(!feof(fp)) {
		//printf("111\n");
		fread(&a, sizeof(int), 1, fp);
		int bit = 31;
		while(bit >= 0) {
			zerone[tot++] = '0' + ((a >> bit) & 1);
		//	printf("%d:%c, %c\n", tot - 1, zerone[tot-1], '0' + ((a >> bit) & 1));
			bit--;
		}
	}
	//printf("%s", zerone);
	dic = "";
	for(int i = 0, j = 0; i < tot; i++) {
		dic += zerone[i];
		//printf("%s\n", dic.c_str());
		if(uzp[dic]) {
			fprintf(fw, "%c", uzp[dic]);
			dic = "";
			atot++;
			if(atot == wds) break;
		}
	}
	return 1;
}

int main()
{
MARK1:
	system("cls");
	printf("请将您要压缩/解压的文档(.txt/.myz)拖至窗口或输入文件目录(例如:c:\\files\\myzisverygood.txt)\n");
	memset(str, 0, sizeof str);
	init();
	fp = fopen(str, "r");
	while(fp == NULL) {
		printf("ERROR!请重新输入:\n");
		memset(str, 0, sizeof str);
		init();
		fp = fopen(str, "r");
	}
	system("cls");
	printf("请稍候...\n");
	Sleep(1000);
	if(judge() == 0) {
		if(zip() == 0) {
			printf("ERROR!压缩失败!\n");
		} else {
			printf("压缩成功!\n");
		}
	} else if(judge() == 1) {
		if(unzip() == 0) {
			printf("ERROR!解压缩失败!\n");
		} else {
			printf("解压成功!\n");
		}
	} else {
		printf("文件后缀名错误!请检查是否为txt文件或者%s文件!\n", SUFFIX);
		printf("按1重新输入,按2直接退出\n");
		int _a;
		scanf("%d", &_a);
		while(_a != 1 && _a != 2) {
			system("cls");
			printf("ERROR!\n");
			printf("按1重新输入,按2直接退出\n");
			scanf("%d\n", &_a);
		}
		if(_a == 1) {
			goto MARK1;
		} else {
			fclose(fp);
		}
	}
	system("pause");
	return 0;
}
本网站的建站故事
上机实验二解题报告